устаревшие данные ассоциации на экземпляре модели ActiveRecord?
Я использую Rails 2, и у меня есть однозначная связь между моделью Project
и моделью Schedule
в этом приложении.
У меня есть наблюдатель, проверяющий, когда атрибуты различных вещей меняются, и в ответ он перебирает массив хэшей, чтобы заполнить новые экземпляры Schedule
.
Каждый экземпляр Schedule
должен иметь атрибут disp_order
, который в конечном итоге сообщает интерфейсу, где его отображать при отображении в списке. disp_order
заполняется при добавлении запланируйте проект таким образом, чтобы он был на единицу больше текущего максимума disp_order
.
Проблема заключается в итерации в наблюдателе. Когда я перебираю массив хэшей, заполненных данными Schedule
, каждый раз через итерацию следует вычислить disp_order
как один выше предыдущего, чтобы учесть Schedule
, который он только что добавил. Однако на практике это не так-если я не обновляю Объект Project
в середине итерации с помощью project = Project.find(project.id)
, или же он всегда вычисляется то же самое максимальное значение disp_order
s, и не имеет точного списка этих 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 ответ:
Вы столкнулись с этой проблемой, потому что вы работаете с кэшированным в памяти объектом.
Взгляните на документацию ассоциации .
Вы можете передать аргумент true в функцию add_to модели расписания для перезагрузки запроса.
Другие варианты включают inverse_of, но это недоступно для вас, потому что вы используете полиморфные ассоциации, согласно документам.