2009-06-04 3 views
0

У меня есть несколько классов со многими ассоциациями, связывающими их вместе, и я хотел бы иметь возможность взять объект верхнего уровня, закрыть его и закрыть все дочерние объекты. Мне нужно, чтобы каждый объект закрывался, потому что я хочу иметь возможность выбрать любого родителя и закрыть всех его детей.Rails Association - Cascading Update

Например (я понимаю, что это, вероятно, не существует):

class Requisition 
    has_many :shipments, :dependent_method => :close 
end 

class Shipment 
    belongs_to :requisition 

    has_many :reroutes, :dependent_method => :close 
end 

class Reroute 
    belongs_to :shipment 

    has_many :deliveries, :dependent_method => :close 
end 

class Delivery 
    belongs_to :reroute 
end 

Кто-нибудь знает хорошего решения для достижения этой цели? Жемчуг/плагин был бы вполне приемлем :-)

Спасибо большое!

+0

Следует «закрыть» предмет, чтобы уничтожить его, или сделать что-то вроде closed = true? – Matchu

+0

Когда я «закрываю» объект, я поставлю его атрибут dateClosed на текущую дату, и я хочу, чтобы дочерние объекты делали то же самое. –

ответ

0

Я сел и написал небольшой плагин, чтобы сделать это. Я называю это acts_as_closable, и он просто добавляет следующий метод к фильтру before_save. Вы должны использовать :autosave => true для каждой ассоциации, с которой вы хотите работать, но это имело смысл для меня, а не для того, чтобы acts_as_closable автоматически сохранил вашу ассоциацию. Я могу сделать это позже и выпустить код. Вот мясо:

def update_closed_status_of_children 
    [self.class.reflect_on_all_associations(:has_many), self.class.reflect_on_all_associations(:has_one)].flatten.each do |assoc| 

    # Don't consider :through associations since those should be handled in 
    # the associated class 
    if not (assoc.options.include? :through) 
     attribute = self.class.acts_as_closable_config.closed_attribute 
     children = self.send(assoc.name) 
     children = Array(children).flatten.compact 

     children.each do |child| 
     # Check to make sure we're only doing this on something declaring acts_as_closable 
     if child.class.included_modules.include? ActsAsClosable 
      child.send(:closed_value=, self.closed_value) 
     end 
     end 
    end 

    end 
end 

Я определяю некоторые другие методы (например, :closed_value= и :closed?), но это основной код, который я должен был выяснить. Надеюсь, это поможет кому-то еще!

+1

Было бы намного лучше сделать его более абстрактным, а не «закрытым», что, вероятно, будет бессмысленным для большинства пользователей, но неким каскадным обновлением. – RocketR

+0

@RocketR - Действительно! Извините, я опубликовал это более двух лет назад. Поскольку никто не сказал ничего, я не думал об этом. Подумайте об этом, я не верю, что у меня даже есть доступ к коду. Если я когда-нибудь сделаю что-то подобное в будущем, я продолжу и создаю полный камень и отпустите его, а затем обновить этот вопрос :-) –

0

Трудно понять вашу цель. Это поможет, если вы сможете прояснить, что вы подразумеваете под «закрытием».

Следующая информация может ответить на ваш вопрос.

ActiveRecord имеет концепцию сохранения базы данных через «сохранить» и «сохранить!». методы. По умолчанию объекты ассоциации сохраняются при сохранении родительского объекта.

+0

Итак, если ассоциации автоматически сохраняются, я мог бы переопределить метод 'before_save' и проверить, имеет ли мой родитель (если он существует) свой атрибут dateClosed для чего-то другого, кроме nil? Если это так, поставьте мне на него. Звучит ли это разумно? –

+0

P.S. Пожалуйста, см. Комментарий к вышеприведенному вопросу для лучшего описания «закрытия» объекта. Благодаря! –

+0

Лучшим подходом было бы использовать обратные вызовы ассоциаций. Обратный вызов ассоциации установил дочерний атрибут на связь с родительским объектом. Перейдите по ссылке http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html и выполните поиск в разделе «Несвязанные объекты и ассоциации». Вам нужно будет просмотреть раздел «Обратные вызовы ассоциации», но также актуальны и предыдущие два раздела. –

0

, если вы никогда не удалить строку из вашей БД с помощью уничтожить методы, которые вы могли бы просто перезаписать Destory методы, чтобы сделать в dateClosed, а затем я верю: зависимый =>: уничтожить просто вызывает соответствующие объекты уничтожения методу

def destroy 
    dateClosed = Date.today 
end 

class Requisition has_many :shipments, :dependent => :destroy 
+0

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