我有一个包含许多任务的项目资源。我想通过向任务模型添加project_id
来确保每个任务都有validates_presence_of :project_id
。
但是,在创建包含任务的新项目时,在记录保存之前,project_id将不可用,因此我无法使用validates_presence_of :project_id
。
所以我的问题是,如何在任务模型中验证project_id的存在?我想确保每个任务都有父母。
...
class Project < ActiveRecord::Base
has_many :tasks, :dependent => :destroy
accepts_nested_attributes_for :tasks, :allow_destroy => true
...
class Task < ActiveRecord::Base
belongs_to :project
validates_presence_of :project_id
答案 0 :(得分:17)
您的代码有效:
这是证明重点的rSpec。如果验证: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
答案 1 :(得分:15)
有关确定答案,请参阅here:
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
如果你问我不那么优雅......它应该透明地验证。
答案 2 :(得分:3)
也许我不理解某些东西,但看起来你正试图欺骗铁轨。你为什么不这样做:
class Task < ActiveRecord::Base
belongs_to :project
validate_presence_of :project
end
答案 3 :(得分:2)
看看这个:
我过去做过的一件事就是添加:validates_presence_of :parent_id, :on => :update
。不是很好,但它有助于收紧网络。
答案 4 :(得分:2)
我认为你遇到了同样的问题。我有两个模型,帐户和用户,创建帐户时,第一个用户是通过@account.users.build
创建的。用户模型具有validates_presence_of :account
验证。
要使第一个用户通过验证,我将以下代码添加到我的帐户模型中:
before_validation_on_create :initialize_users
def initialize_users
users.each { |u| u.account = self }
end
答案 5 :(得分:1)
实际上你需要两者:
validates_presence_of project
validates_presence_of project_id
这样,假设您在数据库中只有2个有效项目,即项目ID 99无效,则不会在以下任何一种情况下保存任务:
task.project_id = 99
task.save
task.project = Project.new
task.save
我希望这对某人有帮助。
答案 6 :(得分:0)
您的Project
课程必须定义
accepts_nested_attributes_for :tasks
有关如何制作表单的详细信息,请参阅Nested Model Form on Railscasts。
编辑:
在你的表格中你应该有这样的东西:
_form.html.erb
<% form_for @project do |f| %>
# project fields...
<% f.fields_for :tasks do |builder| %>
<%= render 'task_fields', :f => builder %>
<% end %>
<p><%= link_to_add_fields "Add task", f, :tasks %></p>
<%= 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中定义的方法,用于动态添加/删除字段。