开发者

Ruby on Rails allow mass assignment for an RSpec test

开发者 https://www.devze.com 2023-04-05 18:36 出处:网络
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'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 :)

0

精彩评论

暂无评论...
验证码 换一张
取 消