ruby on rails - How to query a polymorphic relationship -
i have jobs
table , activities
table. 1 job can have many activities. relation polymorphic.
tables:
job activities ----------- ------------- id id ... target_id target_type ...
models pseudo-code:
class job < activerecord::base # ... has_many :activities, :as => :target, :dependent => :delete_all # ... end class activity < activerecord::base # ... belongs_to :target, :polymorphic => true # ... end
the state of given job determined state of last activity relates to, below (the last in case last created, can safely order id).
job +-> activity 1 - state: new | +-> activity 2 - state: submitted +--> job state approved `-> activity 3 - state: approved |
how query jobs on given state, using activerecord , rails 3/4?
it (just) occurred me idea to, instead of doing query altogether, use "counter caches" uses , denormalize relationship. store state on jobs table , keeping sync'ed using after_create
hook on activity
model? along lines:
after_create :update_state def update_state target.update_attribute(state: self.state) if target.respond_to?(:state) end
would viable alternative solve problem in simpler way?
i don't imagine polymorphism issue here (it's way select right data)
state machine
what using state machine
from looks of it, you're over-engineering models. job
has state, not activity
, why complicate using model?
if use state machine, state of object handled natively, this:
#app/models/job.rb class job < activerecord::base state_machine :initial => :new #states state :new state :submitted state :approved ### events ### #submit event :submit transition :new => :submitted end #approve event :approve transition :submitted => :approved end end end
this handle job
state using state
attribute in jobs model directly
the important aspect of use of state-machine
events:
#state machine functions @job = job.find(id) @job.state #-> "new" @job.new? #-> false @job.submitted? #-> false @job.approved? #-> true @job.submit! #-> state: "new" -> "submitted" @job.approve! #-> state: "submitted" -> "approved"
scopes
if didn't want remove activity
model, may wish use scopes
instead
although know can use this, i'm not sure if syntax correct polymorphic association:
#app/models/job.rb class job < activerecord::base scope :submitted, -> { joins(:activity).where(state: "submitted") } scope :activity, ->(activity = new) { joins(:activity).where(state: activity) } end
Comments
Post a Comment