我正在使用RSpec测试我的Rails应用程序,但后来我遇到了一个问题。我想要一个一致的数据库,因此我强制要求某些列不能为空。
我有一个评论模型,评论可能是另一条评论的答案。 Morevoer评论的IP地址不应为空。这是迁移:
create_table :comments do |t|
t.string :name, :limit => 20, :null => false
t.string :comment, :limit => 8192, :null => false
t.string :ip, :null => false
t.integer :answer_to_comment_id
end
然后我创建了Comment
模型,只有name
和comment
可访问
class Comment < ActiveRecord::Base
attr_accessible :name, :comment
belongs_to :answer_to, :class_name => "Comment",
:foreign_key => "answer_to_comment_id"
has_many :answers, :class_name => "Comment",
:foreign_key => "answer_to_comment_id",
:dependent => :destroy
end
我的factories.rb
看起来像这样:
Factory.define :comment do |comment|
comment.name "test"
comment.comment "test"
comment.ip "0.0.0.0"
end
现在我在RSpec测试comment_spec.rb
describe "some test" do
before(:each) do
@answer = @comment.answers.create(Factory.attributes_for(:comment))
end
end
这将失败,因为:ip
不在attr_accessible
列表中,因此ActiveRecord无法在数据库中创建记录。我可以将:ip
添加到列表中,但由于批量分配,这可能会导致一些安全问题。或者我可以手动添加:ip
,但如果有更多属性,例如ip
所以我寻找绕过attr_accessible
列表的可能性。或者如果你有更好的设计模式,请告诉我
谢谢
答案 0 :(得分:3)
我在搜索同一问题的解决方案时遇到了这个问题。我知道它已经很老了,但是为了什么值得我挖掘代码并决定以这种方式解决问题:
before :each do
ActiveModel::MassAssignmentSecurity::WhiteList.any_instance.stub(:deny?).and_return(false)
end
也许这会对在这里结束的其他人派上用场。
答案 1 :(得分:1)
只需使用:
describe "some test" do
before(:each) do
@answer = @comment.answers << Factory(:comment)
end
end
或者如果您需要多条评论,请说n
describe "some test" do
before(:each) do
@answer = @comment.answers = FactoryGirl.create_list(:comment, n)
end
end
答案 2 :(得分:0)
我在测试过程中基本上使用this的变体(以及其他一些调整)。
(但Fabio的答案更清晰 - 这是工厂的事情之一,制造东西 - 不仅仅是属性的持有者:)