2010-09-27 3 views
2

J'ai la situation suivante avec ActiveRecord (dans Rails 2.3.8):ActiveRecord a été modifié? drapeau ne signale pas de changements chez les enfants associés

class Order < ActiveRecord::Base 
    has_many :documents 
    accepts_nested_attributes_for :documents 
end 

class Document <ActiveRecord::Base 
    belongs_to :order 
end 

Maintenant, dans un contrôleur que je veux diriger l'utilisateur différemment selon ou non ils ont apporté des modifications aux enregistrements existants, par exemple

@order.attributes = params[:order] 
if @order.changed? 
    # save order 
    # redirect one place 
else 
    # redirect another place 
end 

Pour cela, je veux utiliser le changé? drapeau. Il s'avère que @ order.changed? ne questionne pas les enfants.

J'ai essayé de mettre en œuvre que par une méthode proxy d'association sur la has_many: documents association, comme ceci:

has_many :documents do 
    def changed? 
     any? {|doc| doc.changed?} 
    end 
    end 

Mais ce qui a pour effet secondaire involontaire qu'il charge les documents associés à partir du disque, qui, apparemment, efface toutes les modifications qui ont été faites dans l'attribution des attributs imbriqués dans @ order.attributes = params [: order] Cela semble soit une décision de conception intentionnelle dans Rails, mais alors comment le résoudre? Ou est-ce un écart de fonctionnalité?

Pensées?

Loup

+0

exigent la classe 'dm-core' REQUIRE migrations dm-' require 'dm-accepts_nested_attributes' Commander comprennent DataMapper :: ressources propriété: id, série a n,: documents accepts_nested_attributes_for: documents fin classe document comprennent DataMapper :: ressources propriété: id, série propriété: foo, String belongs_to: pour fin données Mapper.setup (: par défaut, 'sqlite :: memory:') DataMapper.auto_migrate! @o = Order.create @ o.attributes = {'documents' => [{'foo' => 'bar'}]} @ o.documents.any? {| doc | doc.dirty?} – Reactormonk

Répondre

4

vous pourriez jeter un oeil à la source de nested_records_changed_for_autosave.

Ce n'est pas exactement ce que vous voulez, mais il a des indices sur la façon de le faire. Spécialement association_instance_get qui "obtient l'instance d'association spécifiée si elle répond à: chargé ?, nul sinon."

+0

Merci pour ce petit conseil. Cela nous mène sur la bonne voie de l'enquête. Il s'est avéré que notre problème était lié au fait que tous les objets en mémoire créés à partir d'attributs imbriqués étaient écrasés dans diverses règles de validation et before_save hooks chargeant par inadvertance les associations du disque, en particulier: validates_presence_of: documents dans le modèle Order permettra d'utiliser les attributs imbriqués pour les mises à jour. –

+0

pas de problème, heureux d'avoir aidé. – hellvinz

+0

Merci! Je voulais détecter si un objet avait son association passée d'un objet persistant à un objet non persistant. La méthode 'changes' renvoie la nouvelle valeur sous la forme d'une chaîne vide, car elle attend un ID. 'object.association (attribute.gsub '_id', '') .target' a fait l'affaire pour moi! – zykadelic

Questions connexes