How to query a polymorphic relationship in Rails 3/4?

Asked

Viewed 445 times

0

I have a table jobs and a table activities. A Job can have several Activities. The relationship is polymorphic.

Tables:

job         activities
----------- -------------
id          id
...         target_id
            target_type
            ...

Classes of models:

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 a given Job is equal to the state of the last Activity created for Job.

Job +-> Activity 1 - state: new        |
    +-> Activity 2 - state: submitted  +--> Estado desse Job é approved
    `-> Activity 3 - state: approved   |

What is the best way to do a query that brings all Jobs that are in a given state, considering Rails Activerecord 3/4?

It also occurred to me now an idea to, instead of doing this query, use something like "counter caches" do and denormalize this relationship. I would create a redundancy field called state on the model Job and would keep the two in sync using a after_create on the model Activity. Something like that:

after_create :update_state

def update_state
  target.update_attribute(state: self.state) if target.respond_to?(:state)
end

That would be a viable alternative?

2 answers

1

Whereas you are looking for alternatives to the query, you could use the Gem https://github.com/pluginaweek/state_machine

With state control and the ability to execute methods in changing from one state to another you would sum it all up to something like

  after_transition :to => :submitted do |transition|
    # Sincroniza ou executa o que você quiser após o job ir para o estado submitted
  end

  # Atividade muda o estado de acordo com a máquina que você definiu, sem
  # você se preocupar em dizer o estado que a atividade deve ir
  activity.next


Although it seems more difficult to use a state machine, in its case it would decrease the complexity of the system as a whole.

0

You want to bring all Jobs Approved from an object?

Job.first.activities.where(state:'approved')

Want to bring all activities that are related to Job?

Job.joins(:activities).where(activities:{state:'approved')
  • but I recommend creating an Scope for this

own active record will prepare the sql with the query targetable_id = x e targetable_type = 'Job'


also recommend using state_machine

Browser other questions tagged

You are not signed in. Login or sign up in order to post.