I have a admin namespaced controller for a simple blog I am writing, as soon as I add in some user support to my test I get back an error, this error only happens when I add the let(:user) { ... } and before { ... } bit
Failure/Error: post :create, :post => blog_post
NoMethodError:
undefined method `merge!' for "a-sample-blog-post":String
# ./app/controllers/admin/posts_controller.rb:13:in `create'
# ./spec/controllers/admin/post_controller_spec.rb:13:in `block (4 levels) in <top (required)>'
# ./spec/controllers/admin/post_controller_spec.rb:12:in `block (3 levels) in <top (required)>'
This is on line 13 of PostsController:
@post = Post.new(params[:post].merge!(:user => current_user))
My simple test code is as follows
require 'spec_helper'
describe Admin::PostsController do
describe "new blog post with valid attributes" do
let(:blog_post) { Factory(:post) }
let(:user) { Factory(:user, :admin => true) }
before { sign_in user }
it "should be valid" do
lambda do
post :create, :post => blog_post
end.should change(Post, :count).by(1)
end
end
end
And in case this helps, here is my factories.rb file
Factory.define :post do |post|
post.title "A sample blog post"
post.content "Duis mollis, est non commodo eget lacinia odio sem nec elit."
end
Factory.define :user do |user|
user.email "[email protected]"
user.password "foobar"
user.admin true
end
Can someone help me understand?
It's telling you what the error is:
undefined method `merge!' for "a-sample-blog-post":String
And that's only happening during the post :create, :post => blog_post
section of your test which means it's directly related to creating a new Post object (and has nothing to do with the let(:user)
section).
Ruby's merge method only works on hashes, but the params you are trying to merge the :user
entry into is a string which is incompatible.
What I'm not seeing is how you're associating users with posts. For example, you should probably have a user_id
field in the Post
model which ties a user to a specific post (to tell you who created that post).
So rewriting this a bit:
class Post < ActiveRecord::Base
# tell Rails what we should let the user update via a form
attr_accessible :title, :content
# == Schema Information
#
# Table name: posts
#
# id :integer not null, primary key
# user_id :integer
# title :string(255)
# content :text
# created_at :datetime
# updated_at :datetime
end
In your PostsController
def create
@post = Post.new(params[:post])
@post.user_id = current_user.id
if @post.save
# great success
else
# Y U NO SAVE?!
end
end
And your params should include :title
and :content
.
If you want to automatically associate your Factory(:post)
with a user, you can do:
Factory.define :post do |post|
post.association :user
post.title "A sample blog post"
post.content "Duis mollis, est non commodo eget lacinia odio sem nec elit."
end