NoMethodError: in Rspec - ruby-on-rails

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

Related

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

rspec can't find #user when application can

The following rspec test file
require 'spec_helper'
describe EvaluationsController do
render_views
before(:each) do
association_attr
end
describe "'eval_selektor'" do
before(:each) do
#eval_selektor = get :eval_selektor, student_group_id: #student_group
end
it "should be successful" do
#eval_selektor
response.should be_success
end
...
end
...
end
is throwing the following error:
1) EvaluationsController 'eval_selektor' should be successful
Failure/Error: #eval_selektor = get :eval_selektor, student_group_id: #student_group
NoMethodError:
undefined method `student_groups' for nil:NilClass
# ./app/controllers/application_controller.rb:7:in `get_student_group'
# ./spec/controllers/evaluations_controller_spec.rb:14:in `block (3 levels) in <top (required)>'
from this method in the application_controller:
def get_student_group
#user = current_user
#student_group = #user.student_groups.find(params[:student_group_id])
end
At first I thought maybe rspec just wasn't getting passed the method from application_controller, but that's not the case as it can see it in the error. The code works in the browser, and if I put <%= #user %> in the view, it shows the correct user instance. Any ideas why rspec can't read #user?
apneadiving got me started in the right direction, and between this post and this one I got to the correct code:
ApplicationController.any_instance.stub(:current_user).and_return(#user)

RSpec undefined method 'should'

I am getting an undefined method for 'should' in my controller tests and cannot figure out why. I spent some time on google and stack overflow, but am stuck. Any help?
Spec Helper:
require 'simplecov'
SimpleCov.start 'rails'
# This file is copied to spec/ when you run 'rails generate rspec:install'
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'rspec/autorun'
# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories.
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
RSpec.configure do |config|
config.expect_with :rspec do |c|
c.syntax = :expect
end
# ## Mock Framework
#
# If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
#
#config.mock_with :mocha
# config.mock_with :flexmock
# config.mock_with :rr
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
config.fixture_path = "#{::Rails.root}/spec/fixtures"
# If you're not using ActiveRecord, or you'd prefer not to run each of your
# examples within a transaction, remove the following line or assign false
# instead of true.
config.use_transactional_fixtures = false
# If true, the base class of anonymous controllers will be inferred
# automatically. This will be the default behavior in future versions of
# rspec-rails.
config.infer_base_class_for_anonymous_controllers = false
# Run specs in random order to surface order dependencies. If you find an
# order dependency and want to debug it, you can fix the order by providing
# the seed, which is printed after each run.
# --seed 1234
config.order = "random"
end
Capybara.javascript_driver = :webkit
Controller Test:
require 'spec_helper'
include Devise::TestHelpers
describe PagesController do
# This should return the minimal set of attributes required to create a valid
# Page. As you add validations to Page, be sure to
# update the return value of this method accordingly.
def valid_attributes
{ }
end
# This should return the minimal set of values that should be in the session
# in order to pass any filters (e.g. authentication) defined in
# PagesController. Be sure to keep this updated too.
def valid_session
{}
end
describe "GET index" do
it "assigns all pages as #pages" do
page = Page.create! valid_attributes
get :index, {}, valid_session
assigns(:pages).should eq([page])
end
end
describe "GET show" do
it "assigns the requested page as #page" do
page = Page.create! valid_attributes
get :show, {:id => page.to_param}, valid_session
assigns(:page).should eq(page)
end
end
describe "GET new" do
it "assigns a new page as #page" do
get :new, {}, valid_session
assigns(:page).should be_a_new(Page)
end
end
describe "GET edit" do
it "assigns the requested page as #page" do
page = Page.create! valid_attributes
get :edit, {:id => page.to_param}, valid_session
assigns(:page).should eq(page)
end
end
describe "POST create" do
describe "with valid params" do
it "creates a new Page" do
expect {
post :create, {:page => valid_attributes}, valid_session
}.to change(Page, :count).by(1)
end
it "assigns a newly created page as #page" do
post :create, {:page => valid_attributes}, valid_session
assigns(:page).should be_a(Page)
assigns(:page).should be_persisted
end
it "redirects to the created page" do
post :create, {:page => valid_attributes}, valid_session
response.should redirect_to(Page.last)
end
end
describe "with invalid params" do
it "assigns a newly created but unsaved page as #page" do
# Trigger the behavior that occurs when invalid params are submitted
Page.any_instance.stub(:save).and_return(false)
post :create, {:page => { }}, valid_session
assigns(:page).should be_a_new(Page)
end
it "re-renders the 'new' template" do
# Trigger the behavior that occurs when invalid params are submitted
Page.any_instance.stub(:save).and_return(false)
post :create, {:page => { }}, valid_session
response.should render_template("new")
end
end
end
describe "PUT update" do
describe "with valid params" do
it "updates the requested page" do
page = Page.create! valid_attributes
# Assuming there are no other pages in the database, this
# specifies that the Page created on the previous line
# receives the :update_attributes message with whatever params are
# submitted in the request.
Page.any_instance.should_receive(:update_attributes).with({ "these" => "params" })
put :update, {:id => page.to_param, :page => { "these" => "params" }}, valid_session
end
it "assigns the requested page as #page" do
page = Page.create! valid_attributes
put :update, {:id => page.to_param, :page => valid_attributes}, valid_session
assigns(:page).should eq(page)
end
it "redirects to the page" do
page = Page.create! valid_attributes
put :update, {:id => page.to_param, :page => valid_attributes}, valid_session
response.should redirect_to(page)
end
end
describe "with invalid params" do
it "assigns the page as #page" do
page = Page.create! valid_attributes
# Trigger the behavior that occurs when invalid params are submitted
Page.any_instance.stub(:save).and_return(false)
put :update, {:id => page.to_param, :page => { }}, valid_session
assigns(:page).should eq(page)
end
it "re-renders the 'edit' template" do
page = Page.create! valid_attributes
# Trigger the behavior that occurs when invalid params are submitted
Page.any_instance.stub(:save).and_return(false)
put :update, {:id => page.to_param, :page => { }}, valid_session
response.should render_template("edit")
end
end
end
describe "DELETE destroy" do
it "destroys the requested page" do
page = Page.create! valid_attributes
expect {
delete :destroy, {:id => page.to_param}, valid_session
}.to change(Page, :count).by(-1)
end
it "redirects to the pages list" do
page = Page.create! valid_attributes
delete :destroy, {:id => page.to_param}, valid_session
response.should redirect_to(pages_url)
end
end
end
Errors:
Failures:
1) PagesController GET index assigns all pages as #pages
Failure/Error: assigns(:pages).should eq([page])
NoMethodError:
undefined method `should' for #<Array:0x007fb986c42948>
# ./spec/controllers/pages_controller_spec.rb:23:in `block (3 levels) in <top (required)>'
2) PagesController POST create with valid params creates a new Page
Failure/Error: expect {
count should have been changed by 1, but was changed by 0
# ./spec/controllers/pages_controller_spec.rb:53:in `block (4 levels) in <top (required)>'
3) PagesController POST create with valid params assigns a newly created page as #page
Failure/Error: assigns(:page).should be_a(Page)
NoMethodError:
undefined method `should' for nil:NilClass
# ./spec/controllers/pages_controller_spec.rb:60:in `block (4 levels) in <top (required)>'
4) PagesController POST create with valid params redirects to the created page
Failure/Error: response.should redirect_to(Page.last)
NoMethodError:
undefined method `should' for #<ActionController::TestResponse:0x007fb987232c68>
# ./spec/controllers/pages_controller_spec.rb:66:in `block (4 levels) in <top (required)>'
5) PagesController POST create with invalid params assigns a newly created but unsaved page as #page
Failure/Error: assigns(:page).should be_a_new(Page)
NoMethodError:
undefined method `should' for nil:NilClass
# ./spec/controllers/pages_controller_spec.rb:75:in `block (4 levels) in <top (required)>'
6) PagesController POST create with invalid params re-renders the 'new' template
Failure/Error: response.should render_template("new")
NoMethodError:
undefined method `should' for #<ActionController::TestResponse:0x007fb986e1d1f0>
# ./spec/controllers/pages_controller_spec.rb:82:in `block (4 levels) in <top (required)>'
7) PagesController GET new assigns a new page as #page
Failure/Error: assigns(:page).should be_a_new(Page)
NoMethodError:
undefined method `should' for #<Page:0x007fb982404708>
# ./spec/controllers/pages_controller_spec.rb:38:in `block (3 levels) in <top (required)>'
8) PagesController PUT update with valid params updates the requested page
Failure/Error: put :update, {:id => page.to_param, :page => { "these" => "params" }}, valid_session
#<Page:0x007fb9872517f8> received :update_attributes with unexpected arguments
expected: ({"these"=>"params"})
got: ({})
# ./app/controllers/pages_controller.rb:61:in `block in update'
# ./app/controllers/pages_controller.rb:60:in `update'
# ./spec/controllers/pages_controller_spec.rb:96:in `block (4 levels) in <top (required)>'
9) PagesController PUT update with valid params assigns the requested page as #page
Failure/Error: assigns(:page).should eq(page)
NoMethodError:
undefined method `should' for #<Page:0x007fb981579a30>
# ./spec/controllers/pages_controller_spec.rb:102:in `block (4 levels) in <top (required)>'
10) PagesController PUT update with valid params redirects to the page
Failure/Error: response.should redirect_to(page)
NoMethodError:
undefined method `should' for #<ActionController::TestResponse:0x007fb9827b7350>
# ./spec/controllers/pages_controller_spec.rb:108:in `block (4 levels) in <top (required)>'
11) PagesController PUT update with invalid params assigns the page as #page
Failure/Error: assigns(:page).should eq(page)
NoMethodError:
undefined method `should' for #<Page:0x007fb987444a88>
# ./spec/controllers/pages_controller_spec.rb:118:in `block (4 levels) in <top (required)>'
12) PagesController PUT update with invalid params re-renders the 'edit' template
Failure/Error: response.should render_template("edit")
NoMethodError:
undefined method `should' for #<ActionController::TestResponse:0x007fb982e75750>
# ./spec/controllers/pages_controller_spec.rb:126:in `block (4 levels) in <top (required)>'
13) PagesController GET show assigns the requested page as #page
Failure/Error: assigns(:page).should eq(page)
NoMethodError:
undefined method `should' for #<Page:0x007fb9830f3a68>
# ./spec/controllers/pages_controller_spec.rb:31:in `block (3 levels) in <top (required)>'
14) PagesController DELETE destroy redirects to the pages list
Failure/Error: response.should redirect_to(pages_url)
NoMethodError:
undefined method `should' for #<ActionController::TestResponse:0x007fb988100e98>
# ./spec/controllers/pages_controller_spec.rb:142:in `block (3 levels) in <top (required)>'
15) PagesController GET edit assigns the requested page as #page
Failure/Error: assigns(:page).should eq(page)
NoMethodError:
undefined method `should' for #<Page:0x007fb9872585f8>
# ./spec/controllers/pages_controller_spec.rb:46:in `block (3 levels) in <top (required)>'
RSpec offers two ways of writing expectations:
should style 1.should == 1
expect style expect(1).to eq(1)
Your spec_helper is configured to use the latter. Change the syntax config to: c.syntax = :should
Reference: https://www.relishapp.com/rspec/rspec-expectations/docs/syntax-configuration

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")

Ruby on Rails Tutorial Lesson 9

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!

Resources