Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Railsでモデルのステータスを扱うベタープラクティス/Better practice to handle state on Rails

ngmt
February 07, 2019

Railsでモデルのステータスを扱うベタープラクティス/Better practice to handle state on Rails

ngmt

February 07, 2019
Tweet

More Decks by ngmt

Other Decks in Technology

Transcript

  1. ྫ • SNSͷΞΧ΢ϯτ ༑ୡ, ༑ୡਃ੥த, ༑ୡղআࡁ, ϛϡʔτ, ϒϩοΫ • ఆ੍ֹαʔϏεͷϓϥϯ

    Free, Basic, Pro, ٳࢭத, ΞΧ΢ϯτ࡟আ, ͓ࢼ͠༻ϓϥϯ • ܾࡁ ϦΫΤετத, ঝೝࡁ, ࢧ෷͍଴ͪ, ܾࡁࣦഊ, Ωϟϯηϧࡁ, ෦෼ฦۚ
  2. ݪҼ • εςʔλεʹؔ͢Δઃܭڞ༗ෆ଍ or ߋ৽࿙Ε • εςʔλεछྨͷ૿Խɺεςʔλεؔ࿈৚݅ͷෳࡶԽ - ૝ఆ֎ͷεςʔλε -

    ͦͷ৔͠ͷ͗తʹ҆қʹ૿΍ͨ͠εςʔλε - εςʔλεA->B͸ભҠՄೳ͕ͩɺA->C͸ભҠͰ͖ͳ͍ - Ϟσϧx͕ଘࡏ͠ɺϞσϧy͕ଘࡏ͠ͳ͍৔߹͸εςʔλεD • ࠷ॳظʹա౓ʹॊೈੑΛ࣋ͬͨઃܭΛ͢Δ
  3. PlantUMLͩͱϨϏϡ͠΍͍͢ @startuml{super-simple-state- machine.png} title Userঢ়ଶભҠਤ0 [*] --> registered : ొ࿥͢Δ

    registered --> active : ਖ਼ࣜʹొ ࿥͢Δ active --> banned : BAN͞ΕΔ active --> Inactive : ୀձ͢Δ @enduml .puml
  4. User.rb class User < ApplicationRecord has_one :activation, class_name: 'UserActivation' has_one

    :deactivation, class_name: 'UserDeactivation' has_one :ban, class_name: 'UserBan' def status return 'active' if active? return 'banned' if banned? return 'inactive' if inactive? return 'registered' end def registered? return false if banned? || inactive? || active? true end def active? return false if banned? || inactive? return false unless activation.present? true end def banned? ban.present? end def inactive? deactivation.present? end def activate! raise StandardError unless registered? create_activation! end def ban! raise StandardError unless active? create_ban! end def deactivate! raise StandardError unless active? create_deactivation! end end user.rb user.rbଓ͖
  5. ঢ়ଶભҠਤΛߋ৽ @startuml{state.png} title Userঢ়ଶભҠਤ [*] --> registered registered --> active

    : ਖ਼ࣜʹొ࿥͢Δ active --> suspended : ౚ݁͞ΕΔ suspended --> active : ౚ݁ղআ͞ΕΔ suspended --> banned : BAN͞ΕΔ suspended --> Inactive : ୀձ͢Δ active --> banned : BAN͞ΕΔ active --> Inactive : ୀձ͢Δ @enduml puml
  6. AASMʹΑΔঢ়ଶભҠ aasm do state :registered, :initial => true state :active,

    :suspended, :banned, :inactive event :activate do transitions from: :registered, to: :active end event :suspend do transitions from: :active, to: :suspended end event :unsuspend do transitions from: :suspended, to: :active end event :ban do transitions from: [:active, :suspended], to: :banned end event :deactivate do transitions from: [:active, :suspended], to: :inactive end end user.rb಺ͷaasm࣮૷෦෼(؆қίʔυ)
  7. AASMʹෳࡶͳঢ়ଶભҠ has_many :suspensions, class_name: 'UserSuspension' has_one :active_suspension, lambda { where(removed_at:

    nil) }, class_name: ‘UserSuspension' aasm do … event :suspend do transitions from: :active, to: :suspended, guard: :without_active_suspension? after do suspensions.create! end end … end def without_active_suspension? return false if active_suspension true end user.rbͷౚ࣮݁૷෦෼
  8. ·ͱΊ • εςʔλε؅ཧ͸ΠϯΫϦϝϯλϧʹվળ͠Α͏ - ʮεςʔλεʹؔ͢Δઃܭڞ༗ෆ଍ or ߋ৽࿙Εʯରࡦ →PlantUMLͱϨϏϡͰઃܭڞ༗ɾߋ৽Λ࿙Β͞ͳ͍ - ʮεςʔλεछྨͷ૿Խɺεςʔλεؔ࿈৚݅ͷෳࡶԽʯରࡦ

    →AASM gemͰεςʔλε؅ཧɾ࣮૷Λ؆୯ʹ - ʮ࠷ॳظʹա౓ͳॊೈੑΛ࣋ͬͨઃܭΛ͢Δʯରࡦ →࠷ॳ͸খ࢝͘͞ΊΔɻDBઃܭ͕ਖ਼نԽ͞Ε͍ͯΕ͹͍͍ͩͨޙͰͲ ͏ʹ͔Ͱ͖Δ