Alain Goldman
Alain Goldman

Reputation: 2908

Rails by Example (by Michael Hartl), Lesson 9.23 redirect will not work

I am following Lesson 9 covering redirects, yet the redirect just won't work! I followed the code to the letter to no avail.

This is my location in the online tutorial

Here is the current Github of the app

The idea is -- If a user is logged out and clicks a protected page(such as a user edit page) he will be sent to a login page.(Because you should not be allowed to edit anything when your logged out.) After he logs in he is then returned to the protected page he clicked earlier(as oppose to going to profile page.)

This is supposed to work at this current section in the tutorial but it does not. I have included the rspec and failures in case that helps.

Failure:

1) Authentication authorization for non-signed-in users when attempting to visit a protected page after signing in should render the desired protected page

 Failure/Error: page.should have_selector('title', text: 'Edit user')
   expected css "title" with text "Edit user" to return something

 # ./spec/requests/authentication_pages_spec.rb:65:in `block (6 levels) in <top (required)>'

authentication_pages_spec.rb

require 'spec_helper'

describe "Authentication" do
  subject { page }

  describe "signin page" do
    before { visit signin_path }

    it { should have_selector('h1',    text: 'Sign in') }
    it { should have_selector('title', text: 'Sign in') }
  end

  describe "signin" do
    before { visit signin_path }

    describe "with invalid information" do
      before { click_button "Sign in" }

      it { should have_selector('title', text: 'Sign in') }
      it { should have_selector('div.alert.alert-error', text: 'Invalid') }

        describe "after visiting another page" do
        before { click_link "Home" }
        it { should_not have_selector('div.alert.alert-error') }
        end  
    end

    describe "with valid information" do
      let(:user) { FactoryGirl.create(:user) }
      before do
        fill_in "Email",    with: user.email.upcase
        fill_in "Password", with: user.password
        click_button "Sign in"
    end

      it { should have_selector('title', text: user.name) }
      it { should have_link('Profile', href: user_path(user)) }
      it { should have_link('Settings', href: edit_user_path(user)) }
      it { should have_link('Sign out', href: signout_path) }
      it { should_not have_link('Sign in', href: signin_path) }

      describe "followed by signout" do
        before { click_link "Sign out" }
        it { should have_link('Sign in') }
      end
  end
end

  describe "authorization" do

    describe "for non-signed-in users" do
      let(:user) { FactoryGirl.create(:user) }

      describe "when attempting to visit a protected page" do
        before do
          visit edit_user_path(user)
          fill_in "Email",    with: user.email
          fill_in "Password", with: user.password
          click_button "Sign in"
        end

        describe "after signing in" do

          it "should render the desired protected page" do
            page.should have_selector('title', text: 'Edit user')
          end

          describe "when signing in again" do
            before do
              delete signout_path
              visit signin_path
              fill_in "Email",    with: user.email
              fill_in "Password", with: user.password
              click_button "Sign in"
            end

            it "should render the default (profile) page" do
              page.should have_selector('title', text: user.name) 
            end
          end
        end
      end
      describe "in the Users controller" do

        describe "visiting the edit page" do
          before { visit edit_user_path(user) }
          it { should have_selector('title', text: 'Sign in') }
        end

        describe "submitting to the update action" do
          before { put user_path(user) }
          specify { response.should redirect_to(signin_path) }
        end
      end
    end

    describe "as wrong user" do
      let(:user) { FactoryGirl.create(:user) }
      let(:wrong_user) { FactoryGirl.create(:user, email: "[email protected]") }
      before { sign_in user }

      describe "visiting Users#edit page" do
        before { visit edit_user_path(wrong_user) }
        it { should_not have_selector('title', text: full_title('Edit user')) }
      end

      describe "submitting a PUT request to the Users#update action" do
        before { put user_path(wrong_user) }
        specify { response.should redirect_to(root_path) }
      end
    end

  end
end

sessions_Controller.rb

class SessionsController < ApplicationController

  def new
  end

  def create
    user = User.find_by_email(params[:session][:email].downcase)
    if user && user.authenticate(params[:session][:password])
      sign_in user
      redirect_to user
    else
      flash.now[:error] = 'Invalid email/password combination'
      render 'new'
    end
  end

  def destroy
    sign_out
    redirect_to root_url
  end
end

user_controllers.rb

class UsersController < ApplicationController
  before_filter :signed_in_user, only: [:edit, :update]
  before_filter :correct_user,   only: [:edit, :update]


  def show
    @user = User.find(params[:id])
  end

  def new
    @user = User.new
  end

  def edit
    # @user = User.find(params[:id])
  end

  def update
      if @user.update_attributes(params[:user])
      flash[:success] = "Profile updated"
      sign_in @user
      redirect_to @user
    else
      render 'edit'
    end
  end


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

  private

    def signed_in_user
      unless signed_in?
        store_location
        redirect_to signin_url, notice: "Please sign in."
      end
    end

    def correct_user
      @user = User.find(params[:id])
      redirect_to(root_path) unless current_user?(@user)
    end
end

session_helper.rb

module SessionsHelper

  def sign_in(user)
    cookies.permanent[:remember_token] = user.remember_token
    self.current_user = user
  end

  def signed_in?
    !current_user.nil?
  end

  def current_user=(user)
    @current_user = user
  end

  def current_user
    @current_user ||= User.find_by_remember_token(cookies[:remember_token])
  end

  def current_user?(user)
    user == current_user
  end

  def sign_out
    self.current_user = nil
    cookies.delete(:remember_token)
  end

  def redirect_back_or(default)
    redirect_to(session[:return_to] || default)
    session.delete(:return_to)
  end

  def store_location
    session[:return_to] = request.url
  end
end

edit.htmnl.erb

<% provide(:title, "Edit user") %> 
<h1>Update your profile</h1>

<div class="row">
  <div class="span6 offset3">
    <%= form_for(@user) do |f| %>
      <%= render 'shared/error_messages' %>

      <%= f.label :name %>
      <%= f.text_field :name %>

      <%= f.label :email %>
      <%= f.text_field :email %>

      <%= f.label :password %>
      <%= f.password_field :password %>

      <%= f.label :password_confirmation, "Confirm Password" %>
      <%= f.password_field :password_confirmation %>

      <%= f.submit "Save changes", class: "btn btn-large btn-primary" %>
    <% end %>

    <%= gravatar_for @user %>
    <a href="http://gravatar.com/emails">change</a>
  </div>
</div>

EDIT *development log*

    Started POST "/sessions" for 127.0.0.1 at 2013-    04-17 22:20:22 -0400    
Processing by SessionsController#create as HTML    
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"aEDz4BcEpiAI+CQXcb6Fz8SHTP30NSqHZlzn4w1GvuQ=", "session"=>{"email"=>"[email protected]", "password"=>    "[FILTERED]"}, "commit"=>"Sign in"}
  User Load (0.2ms)  SELECT "users".* FROM "users" WHERE "users"."email" = '[email protected]' LIMIT 1
Redirected to http://localhost:3000/users/1
Completed 302 Found in 451ms (ActiveRecord: 0.2ms)


Started GET "/users/1" for 127.0.0.1 at 2013-04-17 22:20:22 -0400
Processing by UsersController#show as HTML
  Parameters: {"id"=>"1"}
  User Load (0.3ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1  [["id", "1"]]
  Rendered users/show.html.erb within layouts/application (1.1ms)
  Rendered layouts/_shim.html.erb (0.1ms)
  User Load (0.2ms)  SELECT "users".* FROM "users" WHERE "users"."remember_token" = 'sIGAbFoWQKYG0cjXhK5nWg' LIMIT 1
  Rendered layouts/_header.html.erb (3.9ms)
  Rendered layouts/_footer.html.erb (0.6ms)
Completed 200 OK in 195ms (Views: 192.9ms | ActiveRecord: 0.5ms)

Upvotes: 1

Views: 308

Answers (1)

JoshEmory
JoshEmory

Reputation: 644

Oh glaring thing I see is your sessions controller (in the create method), needs to be changed to use redirect_back_or. That might fix it.

Upvotes: 3

Related Questions