Program Tip

accepts_nested_attributes_for 하위 연결 유효성 검사 실패

programtip 2020. 10. 28. 20:32
반응형

accepts_nested_attributes_for 하위 연결 유효성 검사 실패


Rails 모델 중 하나에서 accepts_nested_attributes_for를 사용하고 있으며 부모를 만든 후 자식을 저장하고 싶습니다.

양식은 완벽하게 작동하지만 유효성 검사가 실패합니다. 간단하게하기 위해 다음을 상상해보십시오.

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

그리고 나는 달리고 있습니다.

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

프로젝트 모델을 저장할 때 작업에 project_id가 없기 때문에 유효성 검사가 실패합니다 (프로젝트가 저장되지 않았기 때문에).

Rails가 아래 패턴을 따르는 것 같습니다.

  • 프로젝트 검증
  • 작업 검증
  • 프로젝트를 저장하다
  • 작업 저장

패턴은 다음과 같아야합니다.

  • 프로젝트 검증
  • On Pass : 프로젝트를 저장하고 계속 ...
  • 작업 검증
    • On Pass : 작업 저장
    • 실패시 : 프로젝트 삭제 (아마도 롤백 하시겠습니까?)

그래서 내 질문은 다음과 같이 요약됩니다. 부모 (프로젝트)가 저장되었지만 부모 (프로젝트) 모델을 저장하지 않은 후 Rails가 project_id = (또는 project =) 메서드와 자식 (작업)에 대한 유효성 검사를 실행하도록 할 수 있습니까? 자식 (작업)이 유효하지 않은 경우?

어떤 아이디어?


이 답변을 Rails 2에 사용하고 그렇지 않으면 아래 :inverse_of답변을 참조하십시오.

연관된 프로젝트가 유효한 경우 project_id를 확인 하지 않음 으로써이 문제를 해결할 수 있습니다 .


class Task < ActiveRecord::Base
  belongs_to :project

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

사용 :inverse_of하고 validates_presence_of :parent. 이렇게하면 유효성 검사 문제가 해결됩니다.

   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


ID가 아닌 관계 만 확인합니다.

class Task < ActiveRecord::Base
  belongs_to :project

  validates_presence_of :project
end

As soon as the association is populated, ActiveRecord will consider the validation to have succeeded, whether or not the model is saved. You might want to investigate autosaving as well, to ensure the task's project is always saved:

class Task < ActiveRecord::Base
  belongs_to :project, :autosave => true

  validates_presence_of :project
end

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

In my case, the project in a task is always nil if both are created using nested attributes. Only if I remove the validates_presence_of, the create goes through successfully. The unit test and the log show that all is created correctly.

So I'd now tend to add constraints to the DB instead of Rails as that seems to be more reliable in the first place.


You could just create the project and only add the projects if it passes validation:

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

Ciao


Contrary to what bigo suggests, it's not always acceptable to save the parent object first and then the children. Usually you want to make sure all objects validate before you start saving them. That gives the user the chance to re-edit the input form and correct any errors.

The problem you describe will be fixed in Rails 3.0. I would have posted a link to the Lighthouse ticket, but stackoverflow.com does not allow this because I'm a new user (#fail). But for the time being, you can use the plugin "parental_control", which will fix your "bug".

참고URL : https://stackoverflow.com/questions/935650/accepts-nested-attributes-for-child-association-validation-failing

반응형