5

I have nested attributes for a Rails model and the associations validations are failing for some reason. I am not useing accepts_nested_attributes_for, but I am doing something very similar.

class Project < ActiveRecord::Base
  has_many :project_attributes

  def name
    project_attributes.find_by_name("name")
  end

  def name=(val)
    attribute = project_attributes.find_by_name("name")

    if attribute
      attribute.value = val
    else
      project_attributes.build(:name=>"name", :value=>val)
    end
  end
end

class ProjectAttribute < ActiveRecord::Base
  belongs_to :project

  validates_presence_of :name
  validates_uniqueness_of :name, :scope => :project_id

  validates_presence_of :project_id, :unless => lambda {|attribute| attribute.project.try(:valid?)}
  validates_associated :project

end

This is a contrived example, but similar to what I am trying to do. I've taken a look at what accepts_nested_attributes_for does and it uses the build method, which I thought would associate the built attribute with the project.

I also looked at accepts_nested_attributes_for child association validation failing which gave me the validates_presence_of :unless=>valid?

Any ideas on how to get this to work?

Community
  • 1
  • 1
John Duff
  • 38,090
  • 5
  • 35
  • 45
  • I tried changing this to use accepts_nested_attributes_for and am running into the same problem. In the validates_presence_of :project_id calling 'project' is returning nil. – John Duff Jan 20 '10 at 18:09

2 Answers2

5

validates_associated looks to be more trouble than it's worth. Your example works if you drop validates_presence_of :project_id. Here is a hacky example that restores that validations (found description here).

class ProjectAttribute < ActiveRecord::Base
  belongs_to :project

  validates_presence_of :name
  validates_uniqueness_of :name, :scope => :project_id

  validates_presence_of :project_id, :unless => Proc.new { |project_attribute|
    project = project_attribute.project
    ObjectSpace.each_object(Project) {|o| project = o if o.project_attributes.include?(project_attribute)} unless project
    project
  }
end
ffoeg
  • 2,336
  • 1
  • 14
  • 13
-2

just add non null constraint on project_id and let it explode if funky things happen. oh, and ensure your test coverage is good too.

user255283
  • 13
  • 1