устаревшие данные ассоциации на экземпляре модели ActiveRecord?


Я использую Rails 2, и у меня есть однозначная связь между моделью Project и моделью Schedule в этом приложении.

У меня есть наблюдатель, проверяющий, когда атрибуты различных вещей меняются, и в ответ он перебирает массив хэшей, чтобы заполнить новые экземпляры Schedule.

Каждый экземпляр Schedule должен иметь атрибут disp_order, который в конечном итоге сообщает интерфейсу, где его отображать при отображении в списке. disp_order заполняется при добавлении запланируйте проект таким образом, чтобы он был на единицу больше текущего максимума disp_order.

Проблема заключается в итерации в наблюдателе. Когда я перебираю массив хэшей, заполненных данными Schedule, каждый раз через итерацию следует вычислить disp_order как один выше предыдущего, чтобы учесть Schedule, который он только что добавил. Однако на практике это не так-если я не обновляю Объект Project в середине итерации с помощью project = Project.find(project.id), или же он всегда вычисляется то же самое максимальное значение disp_orders, и не имеет точного списка этих Schedule экземпляров, чтобы продолжить.

Есть ли лучший способ сделать это? (Примечание: Я просто имею в виду, есть ли лучший способ, чтобы мне не пришлось говорить проекту, чтобы он снова нашел себя. Есть несколько мест, где я активно очищаю остальную часть кода, которая следует, но для этого вопроса меня действительно интересует только эта строка и вещи, которые влияют оно.)

Проект.rb

class Project < ActiveRecord::Base
  # ...
  has_many :schedules, :dependent => :destroy
  # ...
  belongs_to :data, :polymorphic => true, :dependent => :destroy
    accepts_nested_attributes_for :data
  # ...

Расписание.rb

class Schedule < ActiveRecord::Base
  belongs_to :project, :include => [:data]
  # ...

Project_event_observer.rb

class ProjectEventObserver < ActiveRecord::Observer
  # ...          
  def perform_actions(project, actions)
    # ...
    actions.each { |action|
      action.each { |a_type, action_list|
        action_list.each { |action_data|
          self.send(action_type.to_s.singularize, action_data, project)
          project = Project.find(project.id) #My question is about this line.
        }
      }
    }
  # ...

Пример действий для итерации выше

[    
  {:add_tasks => [
    {:name => "Do a thing", :section => "General"},
    {:name => "Do another thing", :section => "General"},
   ]
  },
  # More like this one.
]

Метод наблюдателя, который получает остальные данные действия

def add_task(hash, project)
  # ...
  sched = Schedule.new
  hash.each { |key, val|
    # ...
    sched.write_attribute(key, val)
    # ...
  }
  sched.add_to(project)
end

Расписание.rb

def add_to(proj)
  schedules = proj.schedules
  return if schedules.map(&:name).include?(self.name)
  section_tasks = schedules.select{|sched| sched.section == self.section}
  if section_tasks.empty?
    self.disp_order = 1
  else
    self.disp_order = section_tasks.map(&:disp_order).max + 1 #always display after previously existing schedules
  end
  self.project = proj
  self.save
end
1 4

1 ответ:

Вы столкнулись с этой проблемой, потому что вы работаете с кэшированным в памяти объектом.

Взгляните на документацию ассоциации .

Вы можете передать аргумент true в функцию add_to модели расписания для перезагрузки запроса.

Другие варианты включают inverse_of, но это недоступно для вас, потому что вы используете полиморфные ассоциации, согласно документам.