Ruby on Rails Tutorial Lesson 9 - ruby-on-rails

Update Saturday April 23, 2011
Lesson is green after implementing the following in user.rb
def authenticate_with_salt(id, cookie_salt)
user = find_by_id(id)
(user && user.salt == cookie_salt) ? user : nil
end
I get:
Failures:
1) SessionsController POST 'create' success should sign the user in
Failure/Error: controller.current_user.should == #user
ArgumentError:
wrong number of arguments (1 for 2)
# ./app/models/user.rb:45:in `authenticate_with_salt'
# ./app/helpers/sessions_helper.rb:36:in `user_from_remember_token'
# ./app/helpers/sessions_helper.rb:14:in `current_user'
# ./spec/controllers/sessions_controller_spec.rb:58:in `block (4 levels) in <top (required)>'
Finished in 0.54296 seconds
7 examples, 1 failure
I am continuing to investigate... oh the joy! :D
EDIT: Working on finishing lesson 9 then will post back here -- seems that im back onto the path finding the problem myself again thanks to GrahamJRoy!
Update Friday April 22, 2011 :
I've spent the last day trying to find the similar problem but have been sorely unsuccessful, if you need any more information please let me know, both failures are highly likely related to each other so if i fix one i think it will fix the other
Failures:
1) SessionsController POST 'create' success should sign the user in
Failure/Error: post :create, :session => #attr
NameError:
undefined local variable or method `clear_return_to' for #<SessionsController:0x00000101648ac8>
# ./app/helpers/sessions_helper.rb:28:in `redirect_back_or'
# ./app/controllers/sessions_controller.rb:16:in `create'
# ./spec/controllers/sessions_controller_spec.rb:51:in `block (4 levels) in <top (required)>'
2) SessionsController POST 'create' success should redirect to the user show page
Failure/Error: post :create, :session => #attr
NameError:
undefined local variable or method `clear_return_to' for #<SessionsController:0x00000100ea0690>
# ./app/helpers/sessions_helper.rb:28:in `redirect_back_or'
# ./app/controllers/sessions_controller.rb:16:in `create'
# ./spec/controllers/sessions_controller_spec.rb:57:in `block (4 levels) in <top (required)>'
Finished in 0.42858 seconds
7 examples, 2 failures
In sessions helper.rb file:
def redirect_back_or(default)
redirect_to(session[:return_to] || default)
clear_return_to
end
In sessions_controller_spec.rb file:
it "should sign the user in" do
post :create, :session => #attr
controller.current_user.should == #user
controller.should be_signed_in
end
it "should redirect to the user show page" do
post :create, :session => #attr
response.should redirect_to(user_path(#user))
end
In sessions_controller.rb file:
def create
user = User.authenticate(params[:session][:email],
params[:session][:password])
if user.nil?
flash.now[:error] = "Invalid email/password combination."
#title = "Sign in"
render 'new'
else
sign_in user
redirect_back_or user
end
end
Original Problem below:
I'm currently working in Lesson 9 on the Ruby on Rails Tutorial and am getting the following error when running autotest:
Failures:
1) SessionsController POST 'create' success should sign the user in
Failure/Error: post :create, :session => #attr
NoMethodError:
undefined method `sign_in' for #<SessionsController:0x000001017082d8>
# ./app/controllers/sessions_controller.rb:15:in `create'
# ./spec/controllers/sessions_controller_spec.rb:51:in `block (4 levels) in <top (required)>'
2) SessionsController POST 'create' success should redirect to the user show page
Failure/Error: post :create, :session => #attr
NoMethodError:
undefined method `sign_in' for #<SessionsController:0x00000100ecbca0>
# ./app/controllers/sessions_controller.rb:15:in `create'
# ./spec/controllers/sessions_controller_spec.rb:57:in `block (4 levels) in <top (required)>'
sessions_controller_spec.rb:
it "should sign the user in" do
post :create, :session => #attr
controller.current_user.should == #user
controller.should be_signed_in
end
it "should redirect to the user show page" do
post :create, :session => #attr
response.should redirect_to(user_path(#user))
end
IF i comment out the above sessions_controller_spec.rb I will be GREEN! Possibly that will help someone guide me in the right direction as I am clueless!
sessions_controller.rb:
def create
user = User.authenticate(params[:session][:email],
params[:session][:password])
if user.nil?
flash.now[:error] = "Invalid email/password combination."
#title = "Sign in"
render 'new'
else
sign_in user
redirect_back_or user
end
end
sessions_helper.rb:
def sign_in(user)
cookies.permanent.signed[:remember_token] = [user.id, user.salt]
self.current_user = user
end
ADDED per GrahamJRoy 'include SessionsHelper' in application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery
include SessionsHelper
end
2 new errors that I think are leading to my problem:
Failures:
1) SessionsController POST 'create' success should sign the user in
Failure/Error: post :create, :session => #attr
NoMethodError:
undefined method `redirect_back_or' for #<SessionsController:0x0000010405adc0>
# ./app/controllers/sessions_controller.rb:16:in `create'
# ./spec/controllers/sessions_controller_spec.rb:51:in `block (4 levels) in <top (required)>'
2) SessionsController POST 'create' success should redirect to the user show page
Failure/Error: post :create, :session => #attr
NoMethodError:
undefined method `redirect_back_or' for #<SessionsController:0x000001030a3c60>
# ./app/controllers/sessions_controller.rb:16:in `create'
# ./spec/controllers/sessions_controller_spec.rb:57:in `block (4 levels) in <top (required)>'

Per the documentation, have you referenced the SessionsHelper in the ApplicationController?
class ApplicationController < ActionController::Base
protect_from_forgery
include SessionsHelper
end

So I basically backtracked and started the lesson over again and carefully commented out the code on each page that shouldnt be there.
My Saturday update above made me start inspecting what the failure was showing, so I went to each line it mentioned and checked RailsTutorial git repo to see any obvious differences.
This led to the * next to the remember_token
User.authenticate_with_salt(*remember_token)
When adding that * the error changed from
Failures:
1) SessionsController POST 'create' success should sign the user in
Failure/Error: controller.current_user.should == #user
ArgumentError:
wrong number of arguments (1 for 2)
# ./app/models/user.rb:45:in `authenticate_with_salt'
# ./app/helpers/sessions_helper.rb:36:in `user_from_remember_token'
# ./app/helpers/sessions_helper.rb:14:in `current_user'
# ./spec/controllers/sessions_controller_spec.rb:58:in `block (4 levels) in <top (required)>'
Finished in 0.54296 seconds
7 examples, 1 failure
to:
Failures:
1) SessionsController POST 'create' success should sign the user in
Failure/Error: controller.should be_signed_in
NoMethodError:
undefined method `signed_in?' for #<SessionsController:0x00000104086088>
# ./spec/controllers/sessions_controller_spec.rb:59:in `block (4 levels) in <top (required)>'
Finished in 1.73 seconds
63 examples, 1 failure
At which point i checked my code:
def signed_in
!current_user.nil?
end
to the git repoos:
def signed_in?
!current_user.nil?
end
And conveniently saw a '?' missing which I figured I would add and see what happens..
And apparently I'm green now... lets finish this lesson now!
Many thanks to GrahamJRoy for your input!

Related

Devise Rspec expected the response to have a success status code (2xx) but it was 302

I have a user which I'm creating with FactoryGirl which needs to have a company in order to login successfully to my root_url.
I'm not having any luck at all stubbing the user method to login. I've followed this tutorial for the Devise portion of the user and needed to amend it a little since my user also requires a company to be associated to it.
I've now created a new model/controller called Scans that is behind Devise's authenticate filter and my first pass at testing it failing with:
5) ScansController GET #show returns http success
Failure/Error: expect(response).to have_http_status(:success)
expected the response to have a success status code (2xx) but it was 302
# ./spec/controllers/scans_controller_spec.rb:32:in `block (3 levels) in <top (required)>'
# ./spec/spec_helper.rb:127:in `block (3 levels) in <top (required)>'
# ./spec/spec_helper.rb:126:in `block (2 levels) in <top (required)>'
The spec is currently:
require 'rails_helper'
RSpec.describe ScansController, type: :controller do
before(:all) do
#user = build(:user)
#company = build(:company)
#device = build(:device)
#scan = build(:scan)
end
describe "GET #show" do
it "returns http success" do
login_with #user
get :show, :device_id => #device.id, :id => #scan.id
expect(response).to render_template(:show)
end
end
I'm doing a puts on the response, because I want to see what's being returned:
ScansController
GET #show
302
{"X-Frame-Options"=>"SAMEORIGIN", "X-XSS-Protection"=>"1; mode=block", "X-Content-Type-Options"=>"nosniff", "Location"=>"http://test.host/login", "Content-Type"=>"text/html; charset=utf-8"}
#<Rack::BodyProxy:0x007fb52a7407c0>
So, I'm being redirected back to my login page, which tells me that my login_with method in ControllerHelpers is not working correctly:
module ControllerHelpers
def login_with(user = double('user'), scope = :user)
current_user = "current_#{scope}".to_sym
if user.nil?
allow(request.env['warden']).to receive(:authenticate!).and_throw(:warden, {:scope => scope})
allow(controller).to receive(current_user).and_return(nil)
else
allow(request.env['warden']).to receive(:authenticate!).and_return(user)
allow(controller).to receive(current_user).and_return(user)
end
end
end
Now, my login functionality does currently work (testing manually). The first controller that fires after ApplicationController is PagesController#home:
def home
if current_user && current_user.company
verify_subscription
....
else
redirect_to new_company_path
end
end
If verify_subscription fails the user is also sent to new_company_path, so that doesn't seem to be related to this issue.
Based off my rudimentary rspec capabilities, am I right to assume that I'm not even getting close to mimicking a login? If not, what am I doing wrong?
After alot of tinkering I finally got my tests to pass. I ended up creating a company within my user Factory:
after(:build) do |user|
user.company = create(:company)
end

NoMethodError: in Rspec

I'm currently doing rspec testing on two files and I got these failures regarding undefined methods. I need more calcification on how to exactly fixes these errors,Thanks!
Failures:
1) FavoritesController#create creates a favorite for the current user and specified post
Failure/Error: #post = create(:post)
NoMethodError:
undefined method `create' for #<RSpec::ExampleGroups::FavoritesController::Create:0x007fdabc84f7f8>
# /Users/bryanporras/.rvm/gems/ruby-2.2.1/gems/actionpack-4.2.1/lib/action_dispatch/testing/assertions/routing.rb:171:in `method_missing'
# ./spec/controllers/favorites_controller_spec.rb:8:in `block (2 levels) in <top (required)>'
2) FavoritesController#destroy destroys the favorite for the current user and post
Failure/Error: #post = create(:post)
NoMethodError:
undefined method `create' for #<RSpec::ExampleGroups::FavoritesController::Destroy:0x007fdabfe0f3e8>
# /Users/bryanporras/.rvm/gems/ruby-2.2.1/gems/actionpack-4.2.1/lib/action_dispatch/testing/assertions/routing.rb:171:in `method_missing'
# ./spec/controllers/favorites_controller_spec.rb:8:in `block (2 levels) in <top (required)>'
3) VotesController#up_vote adds an up-vote to the post
Failure/Error: sign_in #user
NoMethodError:
undefined method `sign_in' for #<RSpec::ExampleGroups::VotesController::UpVote:0x007fdabfe26fe8>
# /Users/bryanporras/.rvm/gems/ruby-2.2.1/gems/actionpack-4.2.1/lib/action_dispatch/testing/assertions/routing.rb:171:in `method_missing'
# ./spec/controllers/votes_controller_spec.rb:12:in `block (3 levels) in <top (required)>'
4) Vote after_save calls `Post#update_rank` after save
Failure/Error: vote = Vote.new(value: 1, post: post)
NameError:
undefined local variable or method `post' for #<RSpec::ExampleGroups::Vote::AfterSave:0x007fdabdb8b0b0>
# ./spec/models/vote_spec.rb:25:in `block (3 levels) in <top (required)>'
Finished in 0.78639 seconds (files took 2.82 seconds to load)
15 examples, 4 failures, 2 pending
Failed examples:
rspec ./spec/controllers/favorites_controller_spec.rb:14 # FavoritesController#create creates a favorite for the current user and specified post
rspec ./spec/controllers/favorites_controller_spec.rb:24 # FavoritesController#destroy destroys the favorite for the current user and post
rspec ./spec/controllers/votes_controller_spec.rb:8 # VotesController#up_vote adds an up-vote to the post
rspec ./spec/models/vote_spec.rb:24 # Vote after_save calls `Post#update_rank` after save
This is the favorites_controller_spec.rb file:
require 'rails_helper'
describe FavoritesController do
include Devise::TestHelpers
before do
#post = create(:post)
#user = create(:user)
sign_in #user
end
describe '#create' do
it "creates a favorite for the current user and specified post" do
expect( #user.favorites.find_by(post_id: #post.id) ).to be_nil
post :create, { post_id: #post.id }
expect( #user.favorites.find_by(post_id: #post.id) ).not_to be_nil
end
end
describe '#destroy' do
it "destroys the favorite for the current user and post" do
favorite = #user.favorites.where(post: #post).create
expect( #user.favorites.find_by(post_id: #post.id) ).not_to be_nil
delete :destroy, { post_id: #post.id, id: favorite.id }
expect( #user.favorites.find_by(post_id: #post.id) ).to be_nil
end
end
end
and this is the votes_controller_spec.rb file:
require 'rails_helper'
describe VotesController do
include TestFactories
describe '#up_vote' do
it "adds an up-vote to the post" do
request.env["HTTP_REFERER"] = '/'
#user = authenticated_user
#post = associated_post
sign_in #user
expect {
post( :up_vote, post_id: #post.id )
}.to change{ #post.up_votes }.by 1
end
end
end
Check if you have config.include FactoryGirl::Syntax::Methods inside rails_helper.rb
If you have above line in rails_helper.rb file you can always use FactoryGirl.create :user
You didn't probably include include Devise::TestHelpers in specs for VotesController that's why it does not see sign_in method

Hartl Chapter 11 Ajax undefined local variable or method `cookies'

I am doing the Hartl Tutorial, and am currently in Chapter 11.2.5 A working follow button with AJAX.
My tests are failing for the Relationship Controller and I can't figure out why. The expected behavior happens in the browser. If I remove the cookies method it causes many other tests to fail. What am I missing that is causing this issue?
Here are my tests for the RelationshipController
require 'spec_helper'
describe RelationshipsController do
let(:user) { FactoryGirl.create(:user) }
let(:other_user) { FactoryGirl.create(:user) }
before { sign_in user, no_capybara: true }
describe "creating a relationship with Ajax" do
it "should increment the Relationship count" do
expect do
xhr :post, :create, relationship: { followed_id: other_user.id }
end.to change(Relationship, :count).by(1)
end
it "should respond with success" do
xhr :post, :create, relationship: { followed_id: other_user.id }
expect(response).to be_success
end
end
describe "destroying a relationship with Ajax" do
before { user.follow!(other_user) }
let(:relationship) { user.relationships.find_by(followed_id: other_user) }
it "should decrement the Relationship count" do
expect do
xhr :delete, :destroy, id: relationship.id
end.to change(Relationship, :count).by(-1)
end
it "should respond with success" do
xhr :delete, :destroy, id: relationship.id
expect(response).to be_success
end
end
end
Here is my Utilities.rb
include ApplicationHelper
RSpec::Matchers.define :have_error_message do |message|
match do |page|
expect(page).to have_selector('div.alert.alert-error', text: message)
end
end
def sign_in(user, options={})
if options[:no_capybara]
# Sign in when not using Capybara.
remember_token = User.new_remember_token
cookies[:remember_token] = remember_token
user.update_attribute(:remember_token, User.encrypt(remember_token))
else
visit signin_path
fill_in "Email", with: user.email
fill_in "Password", with: user.password
click_button "Sign in"
end
end
Here is my relationships_controller.rb
class RelationshipsController < ApplicationController
before_action :signed_in_user
def create
#user = User.find(params[:relationship][:followed_id])
current_user.follow!(#user)
respond_to do |format|
format.html { redirect_to #user }
format.js
end
end
def destroy
#user = Relationship.find(params[:id]).followed
current_user.unfollow!(#user)
respond_to do |format|
format.html { redirect_to #user }
format.js
end
end
end
Here is my tests output:
Failures:
1) RelationshipsController creating a relationship with Ajax should increment the Relationship count
Failure/Error: before { sign_in user, no_capybara: true }
NameError:
undefined local variable or method `cookies' for # <RSpec::Core::ExampleGroup::Nested_1::Nested_1:0x007fc7f827f930>
# ./spec/support/utilities.rb:13:in `sign_in'
# ./spec/models/relationship_spec.rb:8:in `block (2 levels) in <top (required)>'
2) RelationshipsController creating a relationship with Ajax should respond with success
Failure/Error: before { sign_in user, no_capybara: true }
NameError:
undefined local variable or method `cookies' for # <RSpec::Core::ExampleGroup::Nested_1::Nested_1:0x007fc7f8516a90>
# ./spec/support/utilities.rb:13:in `sign_in'
# ./spec/models/relationship_spec.rb:8:in `block (2 levels) in <top (required)>'
3) RelationshipsController destroying a relationship with Ajax should decrement the Relationship count
Failure/Error: before { sign_in user, no_capybara: true }
NameError:
undefined local variable or method `cookies' for #<RSpec::Core::ExampleGroup::Nested_1::Nested_2:0x007fc7f85367f0>
# ./spec/support/utilities.rb:13:in `sign_in'
# ./spec/models/relationship_spec.rb:8:in `block (2 levels) in <top (required)>'
4) RelationshipsController destroying a relationship with Ajax should respond with success
Failure/Error: before { sign_in user, no_capybara: true }
NameError:
undefined local variable or method `cookies' for #<RSpec::Core::ExampleGroup::Nested_1::Nested_2:0x007fc7f8556938>
# ./spec/support/utilities.rb:13:in `sign_in'
# ./spec/models/relationship_spec.rb:8:in `block (2 levels) in <top (required)>'
Finished in 0.06635 seconds
4 examples, 4 failures
Failed examples:
rspec ./spec/models/relationship_spec.rb:12 # RelationshipsController creating a relationship with Ajax should increment the Relationship count
rspec ./spec/models/relationship_spec.rb:18 # RelationshipsController creating a relationship with Ajax should respond with success
rspec ./spec/models/relationship_spec.rb:29 # RelationshipsController destroying a relationship with Ajax should decrement the Relationship count
rspec ./spec/models/relationship_spec.rb:35 # RelationshipsController destroying a relationship with Ajax should respond with success
I noticed you put your test of RelationshipsController in spec/models. Is that really what the tutorial says to do? Try putting it under spec/controllers so it is treated as a controller spec.
I have just been struggling with this issue, as well as a lot of other people by the looks of things.
My solution (which I suspect is not the right one) was to change the line :
before { sign_in user, no_capybara: false }
to
before { sign_in user }
Not sure why, but it looks like my rspec test can not see the code in utilities.rb

Pre-processing within a Rails Controller create method does not work

I am following Michael Hartl's tutorial, and trying to implement the reply twitter-like functionality, ie. "#122-john-smith: hello there" should be a reply to user 122.
I first tried filtering the "#XXX-AAA-AAA" part using a before_filter, but I decided to try it first in the very same Micropost#create action. So far I've got this MicropostController:
class MicropostsController < ApplicationController
before_filter :signed_in_user, only: [:create, :destroy]
before_filter :correct_user, only: [:destroy]
#before_filter :reply_to_user, only: [:create]
def index
end
def create
#micropost=current_user.microposts.build(params[:micropost])
#Rails.logger.info "hoooola"
regex=/\A#(\d)+(\w|\-|\.)+/i
message=#micropost.content.dup
isResponse=message.match(regex)[0].match(/\d+/)[0]
#micropost.response=isResponse
if #micropost.save
flash[:success]="Micropost created!"
redirect_to root_path
else
#feed_items=[]
render 'static_pages/home'
end
end
def destroy
#micropost.destroy
redirect_to root_path
end
private
def correct_user
#micropost = current_user.microposts.find_by_id(params[:id])
redirect_to root_path if #micropost.nil?
end
def reply_to_user
regex=/\A#(\d)+(\w|\-|\.)+/i
#I use [0] cause the output of match is a MatchData class with lots of bs
mtch=params[:micropost][:content].match(regex)[0]
#puts mtch
##micropost=current_user.microposts.build(params[:micropost])
if mtch != nil
user_id=mtch.match(/\d+/)[0]
#replied_user=User.find(user_id)
#micropost.response=user_id unless #replied_user.nil?
end
end
end
And this is the snippet test I'm trying to pass:
require 'spec_helper'
describe "MicropostPages" do
subject { page }
let(:user) { FactoryGirl.create(:user) }
before { valid_signin user }
describe "micropost creation" do
before { visit root_path }
describe "with invalid information" do
it "should not create a micropost" do
expect { click_button "Post" }.should_not change(Micropost,
:count)
end
describe "error messages" do
before { click_button "Post" }
it { should have_content('error') }
end
end
describe "with valid information" do
before { fill_in 'micropost_content', with: "Lorem ipsum" }
it "should create a micropost" do
expect { click_button "Post" }.should change(Micropost,
:count).by(1)
end
end
end
...
end
If I run these tests I get the follwing error:
Failures:
1) MicropostPages micropost creation with invalid information should not create a micropost
Failure/Error: expect { click_button "Post" }.should_not change(Micropost, :count)
NoMethodError:
undefined method `[]' for nil:NilClass
# ./app/controllers/microposts_controller.rb:14:in `create'
# (eval):2:in `click_button'
# ./spec/requests/micropost_pages_spec.rb:11:in `block (5 levels) in <top (required)>'
# ./spec/requests/micropost_pages_spec.rb:11:in `block (4 levels) in <top (required)>'
2) MicropostPages micropost creation with invalid information error messages
Failure/Error: before { click_button "Post" }
NoMethodError:
undefined method `[]' for nil:NilClass
# ./app/controllers/microposts_controller.rb:14:in `create'
# (eval):2:in `click_button'
# ./spec/requests/micropost_pages_spec.rb:14:in `block (5 levels) in <top (required)>'
However if I modify the tests and comment out all the #XXX filtering in the Micropost#create action:
def create
#micropost=current_user.microposts.build(params[:micropost])
#Rails.logger.info "hoooola"
#regex=/\A#(\d)+(\w|\-|\.)+/i
#message=#micropost.content.dup
#isResponse=message.match(regex)[0].match(/\d+/)[0]
##micropost.response=isResponse
if #micropost.save
flash[:success]="Micropost created!"
redirect_to root_path
else
#feed_items=[]
render 'static_pages/home'
end
end
The tests pass just fine and the new Micropost is not a Nil object.
It can't seem to find an explanation here.
The error comes from this line:
isResponse=message.match(regex)[0].match(/\d+/)[0]
Check if your two match calls actually match correctly. If the pattern is not found in your string, nil is returned and the [0] call is made on nil. There's two instances in this line alone where this could happen.
Try to spread it out over several lines and check the return values of your matches or extend your Regex to properly check the pattern in one go.

run callback on factorygirl

I have a callback in my user.rb model something like:
class User
include Mongoid::Document
include Mongoid::Timestamps::Created
.
.
.
.
#add a first board for user
after_create :first_board
def first_board
board = self.boards.new(:title => self.username, :category_id => Category.find_or_create_by(slug: "other"))
board.save!
end
end
When a user is created, the app create a new board with above callback.
In my spec/factories/users.rb I have:
FactoryGirl.define do
factory :user do
name 'Test User'
username 'test username'
password 'please'
password_confirmation 'please'
# required if the Devise Confirmable module is used
confirmed_at Time.now
end
end
In my spec/controllers/users_controller_spec.rb I have:
require 'spec_helper'
describe UsersController do
before :each do
request.env['devise.mapping'] = Devise.mappings[:user]
end
include Devise::TestHelpers
before (:each) do
#user = FactoryGirl.create(:user)
sign_in #user
end
describe "GET 'show'" do
it "should be successful" do
get :show, :id => #user.id
response.should be_success
end
it "should find the right user" do
get :show, :id => #user.slug
assigns(:user).should == #user
end
end
end
How can I run my callback with factorygirl?
I get 2 errors:
Failures:
1) UsersController GET 'show' should be successful
Failure/Error: #user = FactoryGirl.create(:user)
Errno::ECONNREFUSED:
Connection refused - connect(2)
# (eval):2:in `post'
# ./app/models/user.rb:190:in `first_board'
# ./spec/controllers/users_controller_spec.rb:10:in `block (2 levels) in <top (required)>'
2) UsersController GET 'show' should find the right user
Failure/Error: #user = FactoryGirl.create(:user)
Errno::ECONNREFUSED:
Connection refused - connect(2)
# (eval):2:in `post'
# ./app/models/user.rb:190:in `first_board'
# ./spec/controllers/users_controller_spec.rb:10:in `block (2 levels) in <top (required)>'
The find_or_create_by method can't be called like that, afaik. It uses method_missing and expects an activerecord attribute tacked on the end. Try:
Category.find_or_create_by_slug("other")

Resources