开发者

Ruby On Rails 3 Tutorial Chap 8: Unit tests not passing

I'm working through Hartl's book and I'm up to chapter 8. I've written some tests that I believe should be passing. I've quadruple checked my code against what's in the book, and double checked it against what's in the book's github repo, but I'm stumped. I'm getting the following errors from RSpec:

Failures:

  1) UsersController POST 'create' should redirect to the user "show" page
     Failure/Error: response.should redirect_to(user_path(assigns(:user)))
     ActionController::RoutingError:
       No route matches {:action=>"show", :controller=>"users", :id=>#<User id: nil, name: nil, email: nil, created_at: nil, updated_at: nil, encrypted_password: nil, salt: nil>}
     # ./spec/controllers/users_controller_spec.rb:93:in `block (3 levels) in <top (required)>'

  2) UsersController POST 'create' should have a welcome message
     Failure/Error: flash[:success].should =~ /welcome to the sample app/i
       expected: /welcome to the sample app/i
            got: nil (using =~)
     # ./spec/controllers/users_controller_spec.rb:98:in `block (3 levels) in <top (required)>'

Finished in 0.83875 seconds
46 examples, 2 failures

Like I said, I've checked the code again and again. Restarted spork, restarted rails server, ran without spork. I've checked it against the code in the book and in the github repo. I've even copy/pasted the spec and controller code in the github repo, but all to no avail.

I'm stumped. It's late and I need to crash. :)

Hopefully one of you guys can see something I'm not. Here's what I've got so far...

users_controller_spec.rb

require 'spec_helper'

describe UsersController do
  render_views

  # ...

  describe "POST 'create'" do

    # ...

    describe 'success' do
      before(:each) do
        @attr = { :name => 'New User', :email => 'some-email@gmail.com', :password => 'foobar', :password_confirmation => 'foobar' }
      end

      it 'should create a new user' do
        lambda do
          post :create, :user => @attr
        end.should change(User, :count).by(1)
      end
    end

    it 'should redirect to the user "show" page' do
      post :create, :user => @attr
      response.should redirect_to(user_path(assigns(:user)))
    end

    it 'should have a welcome message' do
      post :create, :user => @attr
      flash[:success].should =~ /welcome to the sample app/i
    end

  end
end

users_controller.rb

class UsersController < ApplicationController
  def new
    @user = User.new
    @title = 'Sign up'
  end

  def show
    @user =开发者_如何学编程 User.find params[:id]
    @title = @user.name
  end

  def create
    @user = User.new(params[:user])
    if @user.save
      flash[:success] = 'Welcome to the Sample App!'
      redirect_to @user
    else
      @title = 'Sign up'
      render 'new'
    end
  end
end

user.rb

class User < ActiveRecord::Base
  # Virtual properties (don't exist in db)
  attr_accessor :password

  # Accessible properties
  attr_accessible :name, :email, :password, :password_confirmation
  email_regex = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i

  validates :name,  :presence => true,
                    :length => { :maximum => 50 }

  validates :email, :presence => true,
                    :format => { :with => email_regex },
                    :uniqueness => { :case_sensitive => false }

  validates :password,  :presence => true,
                        :confirmation => true,
                        :length => { :within => 6..40 }

  before_save :encrypt_password

  # Return true if the user's password matches the submitted password
  def has_password?(submitted_password)
    # Compare encrypted_password with the encrypted version of submitted_password
    encrypted_password == encrypt(submitted_password)
  end

  # Static/Class methods
  def self.authenticate(email, submitted_password)
    user = find_by_email email
    return nil if user.nil?
    return user if user.has_password? submitted_password
  end

  # Private functionality.
  # Anything after the 'private' pragma will be inaccessable from outside the class
  private

    def encrypt_password
      self.salt = make_salt if new_record? # Using ActiveRecord goodness to make sure this only gets created once.
      self.encrypted_password = encrypt(password)
    end

    def encrypt(string)
      secure_hash("#{salt}--#{string}")
    end

    def make_salt
      secure_hash("#{Time.now.utc}--#{password}")
    end

    def secure_hash(string)
      Digest::SHA2.hexdigest(string)
    end
end

routes.rb

SampleApp::Application.routes.draw do
  #get '/users/new'
  resources :users

  match '/signup' => 'users#new'

  match '/about' => 'pages#about'
  match '/contact' => 'pages#contact'
  match '/help' => 'pages#help'

  root :to => 'pages#home'
end

Thanks in advance. If you guys really want to dig through or if I've missed something in my post, here's my code.

I'm very new to rails, and absolutely love it so far. Any help will be greatly appreciated.


Look closely at your users_controller_spec "success" spec: when will it create @attr? Before each test, or just before the "should create a new user" test? You use it in all the "POST 'create'" tests...

Once you make that non-spec-specific your tests will pass.

(By the way, having the code up in git is handy, but only if the code you're posting is actually checked in, otherwise... not as much ;)


your it "should redirect to the user show page" and it "should have a welcome message"

is outside of the describe "success" do loop

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜