Accepts_nested_attributes_ for unsuccessful child association validation

I am using accepts_nested_attributes_for in one of my Rails models, and I want to save the children after creating the parent.

The form works fine, but the validation fails. For simplicity, imagine the following:

class Project < ActiveRecord::Base has_many :tasks accepts_nested_attributes_for :tasks end class Task < ActiveRecord::Base belongs_to :project validates_presence_of :project_id validates_associated :project end 

And I run:

 Project.create!( :name => 'Something', :task_attributes => [ { :name => '123' }, { :name => '456' } ] ) 

When saving the project model, verification is not performed in tasks because they do not have project_id (since the project was not saved).

Rails seems to execute the following pattern:

  • Check project
  • Confirm Tasks
  • Save project
  • Save Tasks

The sample should be:

  • Check project
  • On Pass: Save the project and continue ...
  • Confirm Tasks
    • On Pass: Save Tasks
    • In case of failure: delete the project (possibly rollback)

So my question boils down to the following: How can I get Rails to run the project_id = (or project =) method and check for the child elements (tasks) AFTER the parent (project) was saved, but NOT saving the parent (project), if any child (task) is invalid?

Any ideas?

+69
validation ruby-on-rails activerecord nested
Jun 01 '09 at 16:43
source share
6 answers

Use this answer for Rails 2, otherwise see below answer :inverse_of

You can get around this by not checking for project_id if the corresponding project is valid.

 class Task < ActiveRecord::Base belongs_to :project validates_presence_of :project_id, :unless => lambda {|task| task.project.try(:valid?)} validates_associated :project end 
+12
Sep 16 '09 at 1:15
source share

Use :inverse_of and validates_presence_of :parent . This should fix your validation problem.

  class Dungeon < ActiveRecord::Base has_many :traps, :inverse_of => :dungeon end class Trap < ActiveRecord::Base belongs_to :dungeon, :inverse_of => :traps validates_presence_of :dungeon end 

http://apidock.com/rails/ActiveModel/Validations/HelperMethods/validates_presence_of

https://github.com/rails/rails/blob/73f2d37505025a446bb5314a090f412d0fceb8ca/activerecord/test/cases/nested_attributes_test.rb

+159
Jan 24 2018-11-11T00:
source share

Check only relationships, not identifier:

 class Task < ActiveRecord::Base belongs_to :project validates_presence_of :project end 

Once the association is complete, ActiveRecord will assume that the verification was successful, regardless of whether the model was saved. You can also study autosave to ensure that the task design is always saved:

 class Task < ActiveRecord::Base belongs_to :project, :autosave => true validates_presence_of :project end 
+8
Mar 10
source share

Unfortunately, none of the above suggestions work for me with Rails 2.3.5.

In my case, the project in the task is always zero if both of them are created using nested attributes. Only if I remove validates_presence_of will the creation succeed. unit test and log show that everything is created correctly.

So, now I would like to add restrictions to the database instead of Rails, because in the first place it seems more reliable.

+2
Mar 09 '10 at 11:22
source share

You can simply create a project and add only projects if it passes the test:

 tasks = params.delete(:task_attributes) if Project.create(params) Project.update_attributes(:task_attributes => tasks) end 

Ciao

+1
Jun 08 '09 at 14:50
source share

Unlike what bigo offers, it is not always acceptable to save the parent object first and then the children. Usually you want to make sure that all objects are scanned before they are saved. This gives the user the ability to re-edit the input form and correct any errors.

The problem you described will be fixed in Rails 3.0. I would post a link to the Lighthouse ticket, but stackoverflow.com does not allow this because I am a new user (#fail). But for now, you can use the " parental_control " plugin, which will fix your "error".

0
Aug 03 '09 at 16:53
source share



All Articles