验证失败时,关联的记录数仍会发生变化
When validation fails, associated record count still changes
有个问题。我有我的模型:
class Collection < ActiveRecord::Base
has_many :collection_ownerships
has_many :items
has_many :users, :through => :collection_ownerships
validates :title, presence: true, length: { maximum: 25 }
validates :description, length: { maximum: 100 }
end
class Item < ActiveRecord::Base
belongs_to :collection
has_many :item_ownerships, :dependent => :destroy
accepts_nested_attributes_for :item_ownerships
validates :name, :presence => true, length: { maximum: 50 }
validates :collection, :presence => true
end
class ItemOwnership < ActiveRecord::Base
belongs_to :item
belongs_to :user
validates :user, :presence => true
validates :item, :presence => true
end
这是我的控制器代码:
before_filter(:except => :toggle_item_owned_state) do
@collection = current_user.collections.find(params[:collection_id])
end
def new
@item = @collection.items.new
@item_ownership = @item.item_ownerships.build(:owned => true, :user => current_user, :item => @item)
end
def create
@item = @collection.items.new(item_params)
@item_ownership = @item.item_ownerships.build(:owned => false, :user => current_user, :item => @item)
if @item.save
redirect_to collection_items_path(@collection)
else
flash.now[:alert] = "There was a problem saving this item."
render "new"
end
end
我有几个控制器测试:
describe 'POST#create' do
context "with bad data" do
it "should not create a new record for 'items'" do
expect { post :create, :collection_id => batman_collection.id,
:item => { :name => '',
:item_ownership_attributes => { :owned => '1'} }
}.to change(Item,:count).by(0)
end
it "should not create new record 'item_ownerships'" do
expect { post :create, :collection_id => batman_collection.id,
:item => { :name => 'item_name',
:item_ownership_attributes => { :owned => '1'} }
}.to change(ItemOwnership,:count).by(0)
end
end
end
当我 运行 我的测试时,第二个失败:
1) ItemsController authenticated user POST#create with bad data should not create new record 'item_ownerships'
Failure/Error: expect { post :create, :collection_id => batman_collection.id,
expected #count to have changed by 0, but was changed by 1
# ./spec/controllers/items_controller_spec.rb:62:in `block (5 levels) in <top (required)>'
最终这也反映在视图中。现在,当我查看数据库时,看不到创建的记录。我假设这是他发生的,因为 Count 以某种方式反映了内存中对象的数量,而不是数据库中的对象数量。
我该如何处理这种情况。问题表现在,当提交表单以填充 Item 的验证失败时,ItemOwnership 的多个实例最终会出现在表单上。
谢谢
我发现了问题。我的第二个测试是错误的,因为它实际上向服务器提交了一个有效请求,因为 'name' 不是空白。
我删除了它,现在测试通过了。
即使父记录验证失败,Rails 也会默认保存从嵌套属性创建的记录。这就是 Item.count
增加的原因。 .count
不像 collection#size
总是查询数据库。
您需要做的是在 Item 上创建一个验证,告诉 Rails 除非父集合有效,否则 Item 无效。
class Item < ActiveRecord::Base
belongs_to :collection
has_many :item_ownerships, :dependent => :destroy
accepts_nested_attributes_for :item_ownerships
validates :name, :presence => true, length: { maximum: 50 }
validates :collection, :presence => true
validates_associated :collection #!
end
http://guides.rubyonrails.org/active_record_validations.html#validates-associated
有个问题。我有我的模型:
class Collection < ActiveRecord::Base
has_many :collection_ownerships
has_many :items
has_many :users, :through => :collection_ownerships
validates :title, presence: true, length: { maximum: 25 }
validates :description, length: { maximum: 100 }
end
class Item < ActiveRecord::Base
belongs_to :collection
has_many :item_ownerships, :dependent => :destroy
accepts_nested_attributes_for :item_ownerships
validates :name, :presence => true, length: { maximum: 50 }
validates :collection, :presence => true
end
class ItemOwnership < ActiveRecord::Base
belongs_to :item
belongs_to :user
validates :user, :presence => true
validates :item, :presence => true
end
这是我的控制器代码:
before_filter(:except => :toggle_item_owned_state) do
@collection = current_user.collections.find(params[:collection_id])
end
def new
@item = @collection.items.new
@item_ownership = @item.item_ownerships.build(:owned => true, :user => current_user, :item => @item)
end
def create
@item = @collection.items.new(item_params)
@item_ownership = @item.item_ownerships.build(:owned => false, :user => current_user, :item => @item)
if @item.save
redirect_to collection_items_path(@collection)
else
flash.now[:alert] = "There was a problem saving this item."
render "new"
end
end
我有几个控制器测试:
describe 'POST#create' do
context "with bad data" do
it "should not create a new record for 'items'" do
expect { post :create, :collection_id => batman_collection.id,
:item => { :name => '',
:item_ownership_attributes => { :owned => '1'} }
}.to change(Item,:count).by(0)
end
it "should not create new record 'item_ownerships'" do
expect { post :create, :collection_id => batman_collection.id,
:item => { :name => 'item_name',
:item_ownership_attributes => { :owned => '1'} }
}.to change(ItemOwnership,:count).by(0)
end
end
end
当我 运行 我的测试时,第二个失败:
1) ItemsController authenticated user POST#create with bad data should not create new record 'item_ownerships'
Failure/Error: expect { post :create, :collection_id => batman_collection.id,
expected #count to have changed by 0, but was changed by 1
# ./spec/controllers/items_controller_spec.rb:62:in `block (5 levels) in <top (required)>'
最终这也反映在视图中。现在,当我查看数据库时,看不到创建的记录。我假设这是他发生的,因为 Count 以某种方式反映了内存中对象的数量,而不是数据库中的对象数量。
我该如何处理这种情况。问题表现在,当提交表单以填充 Item 的验证失败时,ItemOwnership 的多个实例最终会出现在表单上。
谢谢
我发现了问题。我的第二个测试是错误的,因为它实际上向服务器提交了一个有效请求,因为 'name' 不是空白。
我删除了它,现在测试通过了。
Rails 也会默认保存从嵌套属性创建的记录。这就是 Item.count
增加的原因。 .count
不像 collection#size
总是查询数据库。
您需要做的是在 Item 上创建一个验证,告诉 Rails 除非父集合有效,否则 Item 无效。
class Item < ActiveRecord::Base
belongs_to :collection
has_many :item_ownerships, :dependent => :destroy
accepts_nested_attributes_for :item_ownerships
validates :name, :presence => true, length: { maximum: 50 }
validates :collection, :presence => true
validates_associated :collection #!
end
http://guides.rubyonrails.org/active_record_validations.html#validates-associated