Rails:validationhas_many关联中parent_id的存在
我有一个项目资源,有很多任务。 我想通过将validates_presence_of :project_id
添加到任务模型来确保每个任务都有一个project_id
。
但是,在使用任务创建新项目时,在记录保存之前project_id将不可用,因此我无法使用validates_presence_of :project_id
。
所以我的问题是,如何在任务模型中validationproject_id的存在? 我想确保每个任务都有父母。
…
class Project :destroy accepts_nested_attributes_for :tasks, :allow_destroy => true
…
class Task < ActiveRecord::Base belongs_to :project validates_presence_of :project_id
你的代码有效:
- 如果您validation了_presence_of:project,那么只要项目在那里,它就会validation。 但是如果你的项目未保存,你仍然可以保存任务。
- 如果您使用validates_presence_of:project_id,那么整数必须在那里,表示已保存的值。
这是certificate重点的rSpec。 如果validation:project_id,则无法保存任务而不保存项目。
class Task < ActiveRecord::Base belongs_to :project end
/specs/model_specs/task_spec.rb
require File.dirname(__FILE__) + '/../spec_helper' describe Task do before(:each) do @project = Project.new end it "should require a project_id, not just a project object" do task = Task.new task.project = @project Task.instance_eval("validates_presence_of :project_id") task.valid?.should == false end it "should not be valid without a project" do task = Task.new task.project = @project Task.instance_eval("validates_presence_of :project") task.valid?.should == false task.save.should == false end end
请看这里的最终答案:
class Project < ActiveRecord::Base has_many :tasks, :dependent => :destroy, :inverse_of => :project accepts_nested_attributes_for :tasks, :allow_destroy => true class Task < ActiveRecord::Base belongs_to :project validates_presence_of :project
如果你问我就不那么优雅......它应该透明地validation。
也许我不明白,但看起来你正在试图欺骗铁轨。 你为什么不这样做:
class Task < ActiveRecord::Base belongs_to :project validate_presence_of :project end
看看这个:
我过去做的一件事是添加: validates_presence_of :parent_id, :on => :update
。 不是很好,但它有助于收紧网络。
我认为你遇到了同样的问题。 我有两个模型,帐户和用户,创建帐户时,第一个用户是通过@account.users.build
创建的。 User模型具有validates_presence_of :account
validation。
为了使第一个用户通过validation,我将以下代码添加到我的帐户模型中:
before_validation_on_create :initialize_users def initialize_users users.each { |u| u.account = self } end
实际上你需要两个:
validates_presence_of project validates_presence_of project_id
这样,假设您在数据库中只有2个有效项目,即项目ID 99无效,则不会在以下任何一种情况下保存任务:
task.project_id = 99 task.save task.project = Project.new task.save
我希望这对某人有所帮助。
您的Project
类必须定义
accepts_nested_attributes_for :tasks
有关如何制作表单的更多详细信息,请参阅Railscast上的嵌套模型表单 。
编辑:
在你的表格中你应该有这样的东西:
_form.html.erb
<% form_for @project do |f| %> # project fields... <% f.fields_for :tasks do |builder| %> <%= render 'task_fields', :f => builder %> <% end %> <%= link_to_add_fields "Add task", f, :tasks %>
<%= f.submit %> <% end %>
_task_fields.html.erb
<%= f.label :name, "Task name:" %> <%= f.text_field :name %> # task fields... <%= link_to_remove_fields "Delete task", f, :tasks %>
link_to_add_fields
和link_to_remove_fields
是application_helper中定义的方法,用于动态添加/删除字段。