2014-01-31 9 views
3

У меня есть таблица jobs и таблица activities. У одного задания может быть много действий. Отношение является полиморфным.Как запросить полиморфные отношения

Таблицы:

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

модели псевдо-код:

class Job < ActiveRecord::Base 
    # ... 
    has_many :activities, :as => :target, :dependent => :delete_all 
    # ... 
end 

class Activity < ActiveRecord::Base 
    # ... 
    belongs_to :target, :polymorphic => true 
    # ... 
end 

состояние данного задания определяется состоянием последней деятельности это относится к, как показано ниже (последняя в этот случай является последним, поэтому мы можем безопасно заказать по id).

Job +-> Activity 1 - state: new  | 
    +-> Activity 2 - state: submitted +--> Job state is approved 
    `-> Activity 3 - state: approved | 

Как бы вы запрашиваете только те задания, которые на данном состоянии, с помощью ActiveRecord и Rails 3/4?

Он также (просто) придумал мне идею вместо того, чтобы делать этот запрос в целом, использовать что-то вроде «counter caches», используя и денормализовать отношения. Я бы сохранил состояние в таблице рабочих мест и поддерживал его синхронизацию с помощью after_create крюка на модели Activity? Что-то в этом отношении:

after_create :update_state 

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

Будет ли это жизнеспособной альтернативой для решения проблемы более простым способом?

+1

Я думаю, что у вас уже есть самые простые решения.Я бы пошел со вторым методом, потому что проверка работы с определенными состояниями займет много времени. –

+1

вы можете попробовать использовать http://api.rubyonrails.org/classes/ActiveRecord/SpawnMethods.html#method-i-merge –

ответ

0

Я не думаю, полиморфизм будет проблемой здесь (это просто способ, чтобы выбрать нужные данные)


State Machine

Что об использовании state machine

Из-за внешнего вида вы переделываете свои модели. У вашего Job есть состояние, а не activity, так зачем усложнять, используя другую модель?

Если вы используете государственную машину, состояние объекта обрабатывается изначально, как это:

#app/models/job.rb 
Class Job < ActiveRecord::Base 

state_machine :initial => :new do 

     #States 
     state :new 
     state :submitted 
     state :approved 

     ### Events ### 

     #Submit 
     event :submit do 
     transition :new => :submitted 
     end 

     #Approve 
     event :approve do 
     transition :submitted => :approved 
     end 
    end 

end 

Это будет обрабатывать Job состояния с использованием атрибута state в вашей работе модели непосредственно

The наиболее важным аспектом является использование 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" 

Прицелы

Если вы не хотите, чтобы удалить activity модель, вы можете использовать вместо scopes

Хотя я знаю, что вы можете использовать это, я не уверен, если синтаксис правильно с полиморфной ассоциацией:

#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 
Смежные вопросы