Rails ActiveRecord:: Proper way for validating presence on associations?

邮差的信 提交于 2020-01-06 02:36:07

问题


I have a Rails association between models Project and Queue. A project has_many queues. A queue must have a project, and consequently has a presence validation on project_id

Suppose I want to create a new project WITH queues. For example, something like this:

project = Project.new(valid: param, options: here)
project.queues << Queue.new(other_valid: param, options: here)
project.save!

The save is going to fail because the queues fail the project_id presence validation.

My usual ugly way of getting around this is to create a project, then add queues, and wrap the whole lot in a transaction so that if any part of the process fails, it rolls back. ...Somehow that seems uglier than it should be.

So, is there a more graceful way of creating queues on a new project without hitting the presence validation, but still assert that those queues must have a project?

Cheers


回答1:


Try to use the build method on your queues association, like this:

project = Project.new(valid: param, options: here)
project.queues.build(other_valid: param, options: here) //this will build the queue and set its project_id to your current project.
project.save!

Just to be sure that your project_id has the correct value, before calling project.save! insert this line:

project.queues.each do |queue|
  puts queue.project_id 
end

So what's wrong with your code?

project = Project.new(valid: param, options: here) //build a new project - this is not yet persisted, so your id column is nil
project.queues << Queue.new(other_valid: param, options: here) // this line tries to save the queue to the database, does not wait for you to call project.save!
project.save!

When you call:

project.queues << Queue.new(other_valid: param, options: here)`

Rails tries to save your new queue to the database, but since your project is not saved, queue.project_id is nil so your queue validation fails.

If you try something similar with a project fetched from the database (a persisted project), your code will work without errors.

If you still want to use something similar, save the project before adding a new queue on it, like this:

project = Project.new(valid: param, options: here)

if project.save
  project.queues << Queue.new(other_valid: param, options: here) //this guarantees that project_id exists
end


来源:https://stackoverflow.com/questions/24226116/rails-activerecord-proper-way-for-validating-presence-on-associations

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!