Rails accepts_nested_attributes_for child doesn't have parent set when validating

前端 未结 4 1677
情书的邮戳
情书的邮戳 2021-02-04 12:50

I\'m trying to access my parent model in my child model when validating. I found something about an inverse property on the has_one, but my Rails 2.3.5 doesn\'t recognize it, s

相关标签:
4条回答
  • 2021-02-04 12:59

    check these sites, maybe they'll help you...

    Rails Nested Attributes Association Validation Failing

    accepts_nested_attributes_for child association validation failing

    http://ryandaigle.com/articles/2009/2/1/what-s-new-in-edge-rails-nested-attributes

    it seems, rails will assign parent_id after child validation succeeds. (as parent has an id after it's saved)

    maybe worth trying this:

    child.parent.some_condition
    

    instead of self.parent.some_condition ... who knows...

    0 讨论(0)
  • 2021-02-04 13:01

    I had a similar problem: Ruby on Rails - nested attributes: How do I access the parent model from child model

    This is how I solved it eventually; by setting parent on callback

    class Parent < AR
      has_one :child, :before_add => :set_nest
      accepts_nested_attributes_for :child
    
    private
      def set_nest(child)
        child.parent ||= self
      end
    end
    
    0 讨论(0)
  • 2021-02-04 13:08

    You cannot do this because in-memory child doesn't know the parent its assigned to. It only knows after save. For example.

    child = parent.build_child
    parent.child # => child
    child.parent # => nil
    
    # BUT
    child.parent = parent
    child.parent # => parent
    parent.child # => child
    

    So you can kind of force this behavior by doing reverse association manually. For example

    def child_with_inverse_assignment=(child)
      child.parent = self
      self.child_without_inverse_assignment = child
    end
    
    def build_child_with_inverse_assignment(*args)
      build_child_without_inverse_assignment(*args)
      child.parent = self
      child
    end
    
    def create_child_with_inverse_assignment(*args)
      create_child_without_inverse_assignment(*args)
      child.parent = self
      child
    end
    
    alias_method_chain :"child=", :inverse_assignment
    alias_method_chain :build_child, :inverse_assignment
    alias_method_chain :create_child, :inverse_assignment
    

    If you really find it necessary.

    P.S. The reason it's not doing it now is because it's not too easy. It needs to be explicitly told how to access parent/child in each particular case. A comprehensive approach with identity map would've solved it, but for newer version there's :inverse_of workaround. Some discussions like this one took place on newsgroups.

    0 讨论(0)
  • 2021-02-04 13:13

    I had basically the same problem with Rails 3.2. As suggested in the question, adding the inverse_of option to the parent's association fixed it for me.

    Applied to your example:

    class Parent < AR
      has_one :child, inverse_of: :parent
      accepts_nested_attributes_for :child
    end
    
    class Child < AR
      belongs_to :parent, inverse_of: :child
      validates_presence_of :name, :if => :some_method
    
      def some_method
        return self.parent.some_condition   # => undefined method `some_condition' for nil:NilClass
      end
    end
    
    0 讨论(0)
提交回复
热议问题