I'm testing my Rails application with RSpec, but then I ran into a problem. I want a consistent database, therefore I imposed a constraint that some columns can not be null.
I have a Comment model and a comment may be an answer to another comment. Morevoer a comment has an IP address which should not b开发者_开发百科e null. This is the migration:
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
Then I created a Comment
model with only name
and comment
accessible
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
My factories.rb
looks like this:
Factory.define :comment do |comment|
comment.name "test"
comment.comment "test"
comment.ip "0.0.0.0"
end
Now I have the following problem in the RSpec test comment_spec.rb
describe "some test" do
before(:each) do
@answer = @comment.answers.create(Factory.attributes_for(:comment))
end
end
This will fail, because :ip
is not in the attr_accessible
list and therefore ActiveRecord can't create the record in the database. I could add :ip
to the list, but this may cause some security issues because of mass assignment. Or I could add the :ip
manually, but this could become a lot of work if there were more attributes like ip
So I look for a possibility to bypass the attr_accessible
list. Or if you have a better design pattern, please let me know
Thank you
I ran across this question while searching for a solution to the same problem. I know it's very old, but for what it's worth I dug through the code and decided to solve the problem this way:
before :each do
ActiveModel::MassAssignmentSecurity::WhiteList.any_instance.stub(:deny?).and_return(false)
end
Perhaps this will come in handy to someone else who winds up here.
Just use:
describe "some test" do
before(:each) do
@answer = @comment.answers << Factory(:comment)
end
end
or if you need more than one comment, say n
describe "some test" do
before(:each) do
@answer = @comment.answers = FactoryGirl.create_list(:comment, n)
end
end
I basically use a variation of this (along with a few other tweak) during testing.
(But Fabio's answer is cleaner--that's one of the things factories are for, making things--not just a holder for attributes :)
精彩评论