How do I query a polymorphic relationship in Rails 3/4?

0

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

Tables:

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

Model classes:

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 will bring all Jobs that are in a certain state, considering Rails 3/4 ActiveRecord?

I also came up with an idea, instead of doing this query, to use something like the "counter caches" make and denormalize that relationship. I would create a redundant field called state in the Job model and keep the two in sync using a after_create in the Activity model. Something like this:

after_create :update_state

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

Would this be a viable alternative?

    
asked by anonymous 31.01.2014 / 18:54

2 answers

1

Considering that you are looking for alternatives to the query, you could use the gem link Home With state control and the ability to execute methods on changes from one state to another you would summarize everything 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 your case it would reduce the complexity of the system as a whole.

    
01.02.2014 / 07:30
0

Do you want to bring all jobs approved of an object?

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

Do you want to bring all the activities that are related to jobs?

Job.joins(:activities).where(activities:{state:'approved')
  • However I recommend creating a scope for this

The actual record itself will prepare sql with query targetable_id = x e targetable_type = 'Job'

I also recommend using state_machine

    
02.08.2016 / 03:17