2016-04-14 2 views
1

Я следую вместе с руководством по рельсам Майкла Хартла и делаю небольшие корректировки. Пользователи могут создавать микросообщения (обновления статуса) в своих профилях, после чего страница будет перезагружаться и будет отображаться новый статус. Я могу подтвердить вручную, что это работает точно так, как предполагалось. Проблема в том, что тесты для него не проходят по какой-то причине, хотя конечный результат вне тестов выглядит идеально.«Нельзя перенаправить на ноль!»

Скриншоты microposts_controller.rb, microposts_interface_test.rb (тест отсутствии), соответствующие сообщения об ошибках, и users_controller.rb, в таком порядке: http://imgur.com/a/IS1HI

microposts_controller.rb

class MicropostsController < ApplicationController 
    before_action :logged_in_user, only: [:create, :destroy] 
    before_action :correct_user, only: :destroy 

    def create 
    @micropost = current_user.microposts.build(micropost_params) 
    if @micropost.save 
     flash[:success] = "Status updated!" 
     redirect_to @user 
    else 
     @feed_items = [] 
     flash[:warning] = "Status was blank!" 
     redirect_to @user 
    end 
    end 

    def destroy 
    @micropost.destroy 
    flash[:success] = "Status deleted." 
    redirect_to @user 
    end 

microposts_interface_test.rb:

require 'test_helper' 

class MicropostsInterfaceTest < ActionDispatch::IntegrationTest 

    def setup 
    @user = users(:mrtestit) 
    end 

    test "micropost interface" do 
    log_in_as(@user) 
    assert is_logged_in? 
    # Invalid submission 
    assert_no_difference 'Micropost.count' do 
     post microposts_path, micropost: { content: "" } 
    end 
    # Valid submission 
    content = "This status really ties the room together" 
    assert_difference 'Micropost.count', 1 do 
     post microposts_path, micropost: { content: content } 
    end 
    follow_redirect! 
    assert_match content, response.body 
    # Delete a post. 
    assert_select 'a', text: 'delete' 
    first_micropost = @user.microposts.paginate(page: 1).first 
    assert_difference 'Micropost.count', -1 do 
     delete micropost_path(first_micropost) 
    end 
    # Visit a different user. 
    get user_path(users(:archer)) 
    assert_select 'a', text: 'delete', count: 0 
    end 

end 

users_controller.rb

class UsersController < ApplicationController 
    before_action :logged_in_user, only: [:index, :edit, :update, :destroy] 
    before_action :correct_user, only: [:edit, :update] 
    before_action :admin_user, only: :destroy 

    def index 
    @users = User.where(activated: true).paginate(page: params[:page]) 
    end 

    def show 
    @user = User.find(params[:id]) 
    if logged_in? 
     @micropost = current_user.microposts.build 
     @feed_items = current_user.feed.paginate(page: params[:page]) 
    end 
    @microposts = @user.microposts.paginate(page: params[:page]) 
    redirect_to root_url and return unless @user.activated? 
    end 

Я понимаю, что по какой-то причине это говорит о том, что @user является nil. Тем не менее, я неоднократно подтверждал, что redirect_to @user работает везде.

Тот факт, что все остальные испытания проходят, является доказательством этого, но для того, чтобы пройти лишнюю милю, я подтвердил, что строка кода ошибки redirect_to @user работает в других файлах, например, когда пользователь обновляет свою информацию о профиле под их страницей настроек и затем перенаправляется на страницу своего профиля. Я потратил более 10 часов на это (в основном вчера), и я нахожусь на грани простого удаления этого теста и продолжения своей жизни. Stackoverflow - мое последнее средство.

+0

Введите код в вопрос, а не ссылки на скриншоты –

+0

Я теперь сделал то, что вы просили. – Display

ответ

4

Я думаю, что вы должны изменить

redirect_to @user 

в

redirect_to current_user 

@user является класс переменным экземпляра и должны быть созданы вручную, например:

@user = User.find_by_id post.owner_id 

Хотя current_user является глобальная переменная и может использоваться в любом месте. Но не забудьте проверить его на ноль, потому что пользователь не может войти в систему!

Вы можете проверить его вручную unless current_user.nil? в каждом методе или лучше добавить вспомогательный метод и использовать его в своих контроллерах, учебник уже описывает этот путь:

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

class MicropostsController < ApplicationController 
    before_action :signed_in_user 
# ... 

Обновление: За советом Aleks: если вам хотите перенаправить владельца сообщения, который может быть не текущим пользователем, использовать

user = micropost.owner 
redirect_to user 
+0

Вы были правы! Больно, что я встал до этого момента несколько часов назад, но я не был уверен, правильно ли это, поэтому я удалил это и продолжал пробовать другие вещи. Я сделал это, потому что появилось новое сообщение об ошибке, которое я теперь вижу снова: http://i.imgur.com/6YoYQ7J.png Я не уверен, почему эта последняя часть теста также терпит неудачу. Вероятно, это связано с тем, что автор пишет эту строку как «assert_select» a, text: text: «delete», count: 0} », но это не сработает, поэтому я удалил второй« текст: »и закрытая скобка. Сообщение об ошибке синтаксиса исчезает, когда вы это делаете, но код не работает. – Display

+0

Похоже, у тестового пользователя есть доступ к другим пользователям. Он админ? Попробуйте ограничить доступ к пользователям, не являющимся администраторами. Просмотр будет выглядеть примерно так: '<% if! Current_user.nil? и current_user.admin? User.all.each do | user | %><% = link_to user.email, user%> ' –

+0

Проверяя несколько разных комбинаций пользователей, я понял, что строка 30 является ошибкой, а не линией 31. Вместо того, чтобы посещать другого пользователя, тест делает пользователь останется на своей собственной странице, поэтому они всегда будут видеть количество микросообщений, которые у них есть в файле microposts.yml, и будет соответствующее количество ссылок на удаление, так как они являются пользователями, которые сделали эти микропоты. Я попытался исправить это, добавив follow_redirect! к строке под ней, но это не сработало, так как «получить» путь пользователя не считается перенаправлением. У вас есть идея, как это исправить? – Display

1

Для этого есть два возможных решения.

Первый из них это:

Изменить это:

def create 
    @micropost = current_user.microposts.build(micropost_params) 
    if @micropost.save 
     flash[:success] = "Status updated!" 
     redirect_to @user 
    else 
     @feed_items = [] 
     flash[:warning] = "Status was blank!" 
     redirect_to @user 
    end 
    end 

к этому:

def create 
    @micropost = current_user.microposts.build(micropost_params) 
    if @micropost.save 
     flash[:success] = "Status updated!" 
     redirect_to current_user 
    else 
     @feed_items = [] 
     flash[:warning] = "Status was blank!" 
     redirect_to current_user 
    end 
    end 

ИЛИ (если первый не работает) второй подход:

Обновление этой линии:

before_action :correct_user, only: :destroy 

к:

before_action :correct_user, only: [:create, :destroy] 
+0

Вы были правы! Больно, что я встал до этого момента несколько часов назад, но я не был уверен, правильно ли это, поэтому я удалил это и продолжал пробовать другие вещи. Я сделал это, потому что появилось новое сообщение об ошибке, которое я теперь вижу снова: http://i.imgur.com/6YoYQ7J.png Я не уверен, почему эта последняя часть теста терпит неудачу. Для справки, первый пользователь - администратор, второй пользователь - нет, и оба они являются объектами внутри users.yml. – Display

+0

Причина, вероятно, в том, что при переходе на «user_path» ссылка удаления отсутствует. Сначала администратор, и он, вероятно, может видеть ссылку удаления, а вторая ссылка - обычный пользователь и не должна видеть ссылку на удаление вообще. – Aleks

+0

Проверяя несколько разных комбинаций пользователей, я понял, что строка 30 является ошибкой, а не линией 31. Вместо того, чтобы посещать другого пользователя, тест заставляет пользователя оставаться на своей странице, поэтому они всегда будут видеть количество микросообщений, которые у них есть под microposts.yml, и будет соответствующее количество ссылок на удаление, так как они являются пользователями, которые сделали эти микросообщения. Я попытался исправить это, добавив follow_redirect!к строке под ней, но это не сработало, так как «получить» путь пользователя не считается перенаправлением. У вас есть идея, как это исправить? – Display

Смежные вопросы