I have few models: User and Article. User has_many articles and Article belongs to user.
I try to write test to check Post
method (NOTE: i use locales in my application):
require 'spec_helper'
describe ArticlesController do
render_views
before(:each) do
@admin = FactoryGirl.create( :admin )
@user = FactoryGirl.create( :user )
end
describe "POST 'create'" do
before(:each){ @article = FactoryGirl.create(:article) }
describe "for signed-in admin" do
before(:each){ test_sign_in( @admin ) }
it "should create article" do
expect do
post :create, :locale => :en, :article => @article.attributes.merge( :content => "some" )
end.should change( Article, :count ).by(1)
end
end
end
end
But i get such error:
1) ArticlesController POST 'create' for signed-in admin should create article
ActiveModel::MassAssignmentSecurity::Error:
Can't mass-assign protected attributes: id, user_id, created_at, updated_at
Failure/Error: post :create, :locale => :en, :article => @article.attributes.merge( :content => "some" )
# ./app/controllers/articles_controller.rb:15:in `create'
# ./spec/controllers/articles_controller_spec.rb:106:in `block (5 levels) in <top (required)>'
# ./spec/controllers/articles_controller_spec.rb:105:in `block (4 levels) in <top (required)>'
How can i fix that?
My Factories:
FactoryGirl.define do
factory :user do
sequence(:email) { |n| "email#{n}@factory.com" }
password 'qwerty'
factory :admin do
admin true
end
end
factory :article do
content 'text is here'
user
end
end
My controller:
class ArticlesController < ApplicationController
before_filter do
redirect_to :root unless current_user && current_user.admin?
end
def create
@article = Article.new( params[:article] )
if @article.save
redirect_to articles_path
flash[:success] = "It has been created!"
else
render 'new'
end
end
end
Article model:
# == Schema Information
#
# Table name: articles
#
# id :integer not null, primary key
# user_id :integer
# content :text
# created_at :datetime not null
# updated_at :datetime not null
#
class Article < ActiveRecord::Base
belongs_to :user
attr_accessible :content
validates :content,
:presence => { :message => :presense_message },
:length => {
:maximum => 50000,
:message => :max_lenght_message
}
end
UPD: Application is here: https://github.com/Loremaster/Chirch_app
Without testing your code directly I can't say for sure, but try changing
before(:each){ @article = FactoryGirl.create(:article) }
to
before(:each){ @article = FactoryGirl.build(:article, :user => @admin) }
so that you are giving the article an author as well as not saving the article before you make the call to POST. Also, this line should probably also go within your describe "for signed-in admin"
block.
Your MassAssignmentSecurity::Error
s will go away if you change your test code so that you build
your :article
upfront with all the necessary parameters as defined in your factories:
spec/controllers/articles_controllers.spec
describe "POST 'create'" do
before(:each) do
@article = FactoryGirl.build(:article, :user => @admin, :content => "some")
end
describe "for non-signed users" do
it "should deny access" do
post :create, :locale => :en, :article => @article
response.should redirect_to( root_path )
end
it "should not create article" do
expect do
post :create, :locale => :en, :article => @article
end.should_not change( Article, :count )
end
end
describe "for signed-in users" do
before(:each){ test_sign_in( @user ) }
it "should deny access" do
post :create, :locale => :en, :article => @article
response.should redirect_to( root_path )
end
it "should not create article" do
expect do
post :create, :locale => :en, :article => @article
end.should_not change( Article, :count )
end
end