【问题标题】:"missing required keys" - Ruby on Rails“缺少必需的键” - Ruby on Rails
【发布时间】:2017-06-06 22:31:51
【问题描述】:

我有以下名为 Login 的控制器:

class LoginController < ApplicationController
  skip_before_action :verify_authenticity_token
  protect_from_forgery
  before_action :require_user
  helper_method :current_user

  def current_user
    @current_user ||= User.find(session[:user_id]) if session[:user_id]
    rescue ActiveRecord::RecordNotFound
  end

  def require_user
    redirect_to login_path unless current_user
  end

  def show

  end

  def new
    if session[:user]
      @user = User.find(session[:user])
    end
  end

  def destroy
    reset_session
    redirect_to "/login/acesso", notice: "Você foi deslogado"
  end

  def create
    user = User.validate(login_params[:email], login_params[:senha])
    if user
      session[:user] = user.id
      redirect_to "/home/inicio", notice: "login feito com sucesso"
    else
      redirect_to "/login/acesso", notice: "Dados incorretos"
    end
  end

  private

  def login_params
    params.require(:login).permit(:email, :senha)
  end
end

这是我的路线:

Rails.application.routes.draw do

  root 'login#new'
  get '/home/inicio', to: 'home#index'

  scope '/login' do
    get '/acesso', to:'login#new'
    post '/acessorecebendo', to:'login#create'
    get '/sair', to:'login#destroy'
  end

  resources :login
  resources :home
  resources :produtos
  resources :fornecedors
end

和错误:

没有路由匹配 {:action=>"show", :controller=>"login"},丢失 所需键:[:id]

在行:

def require_user
  redirect_to login_path unless current_user   
end

重点是:如果我删除登录控制器中的“before_action :...”行,我会收到此错误:

找不到 'id'=2 的用户

new.html.erb(登录视图):

<% if flash[:notice] %>
  <div class="notice"><%= flash[:notice] %></div> 
<% end %>

<div class="login-page">   
  <div class="form">
    <form class="register-form" action="/login/acessorecebendo" method="post">
      <input type="text" name="login[email]" placeholder="Email"/>
      <input type="password" name="login[senha]" placeholder="Senha"/>
      <button>Cadastrar</button>
      <p class="message">Já é registrado? <a href="#">Login</a></p>
    </form>
    <form class="login-form" action="/login/acessorecebendo" method="post">
      <input type="text" name="login[email]" placeholder="email"/>
      <input type="password" name="login[senha]" placeholder="password"/>
      <button>login</button>
      <p class="message">Não está registrado <a href="#">Criar uma conta</a></p>
    </form>
    <% if session[:user] %>
      <a href="/login/sair">Sair sessão <%= @user.nome %> </a>
    <% end %>
  </div>
</div>

所以,为了尝试解决这个问题,我需要检查是否有人登录并重定向到正确的视图。我正在尝试在行动之前用这个做类似的事情......

谁能给我解释一下,好吗? :\

我尝试遵循以下解决方案:Couldn't find User with id=1

但它没有工作..

【问题讨论】:

  • 您能添加将您重定向到 show 方法的视图吗?
  • 什么观点?问题出在 before_action 方法上:\
  • @SebastiánPalma 我放了登录控制器的视图

标签: ruby-on-rails ruby ruby-on-rails-3 ruby-on-rails-4


【解决方案1】:

这个问题:

redirect_to login_path unless current_user

login_path 需要和id,你可以通过在控制台中运行rake routes 看到:

           acesso GET    /login/acesso(.:format)          login#new
  acessorecebendo POST   /login/acessorecebendo(.:format) login#create
             sair GET    /login/sair(.:format)            login#destroy
      login_index GET    /login(.:format)                 login#index
                  POST   /login(.:format)                 login#create
        new_login GET    /login/new(.:format)             login#new
       edit_login GET    /login/:id/edit(.:format)        login#edit
            login GET    /login/:id(.:format)             login#show
                  PATCH  /login/:id(.:format)             login#update
                  PUT    /login/:id(.:format)             login#update
                  DELETE /login/:id(.:format)             login#destroy
       home_index GET    /home(.:format)                  home#index
                  POST   /home(.:format)                  home#create
         new_home GET    /home/new(.:format)              home#new
        edit_home GET    /home/:id/edit(.:format)         home#edit
                  GET    /home/:id(.:format)              home#show
                  PATCH  /home/:id(.:format)              home#update
                  PUT    /home/:id(.:format)              home#update
                  DELETE /home/:id(.:format)              home#destroy

(为简洁起见,我删除了一些。)

我猜你可能想这样做:

redirect_to accesso_path unless current_user

或者,可能:

redirect_to new_login_path unless current_user

顺便说一句,它们都指向同一个地方,因此您可能可以去掉 accesso_path 并将其替换为 login_new

所以,另一个问题听起来像是您可能(来自您的 cmets),是您在 session[:user_id] 中有一个无效的 id。当您删除 before_action :require_user 时,您将:

def new
  if session[:user]
    @user = User.find(session[:user])
  end
end

然后引发异常:

找不到 'id'=2 的用户

所以,这可能是你应该做的:

class LoginController < ApplicationController
  skip_before_action :verify_authenticity_token
  protect_from_forgery
  before_action :go_home_if_signed_in
  helper_method :current_user
  # ^^^
  # I don't know what this is


  def go_home_if_signed_in
    if session[:user_id]
      # there was a session[:user_id]
      # use find_by instead of find because it won't raise an exception
      if User.find_by(id: session[:user_id])
        # the session[:user_id] resulted in a valid user, so
        # send the user to their home page.
        redirect_to home_index_path
      else
        # if the User wasn't found, then you'll be in here, without
        # raising an exception.
        # So now you want to set the session[:user_id] to nil
        # because it's invalid.
        session[:user_id] = nil
      end
    end
  end

  # you should be able to get rid of this.
  # def require_user
  #   redirect_to new_login_path unless current_user # or wherever, but not login_path
  # end

  def show

  end

  def new
    # This seems wrong. What is session[:user] and how do you 
    # expect User to find it?
    # if session[:user]
    #   @user = User.find(session[:user])
    # end
  end

  def destroy
    # Make sure you set session[:user] = nil somewhere!!!
    reset_session
    # ^^^
    # I don't know what this is.
    # redirect_to "/login/acesso", notice: "Você foi deslogado"
    redirect_to :acesso_path, notice: "Você foi deslogado"
    # ^^^
    # Why not use the path you generated in routes? You went through
    # the trouble of defining it.
  end

  def create
    user = User.validate(login_params[:email], login_params[:senha])
    if user
      session[:user] = user.id
      redirect_to "/home/inicio", notice: "login feito com sucesso"
    else
      redirect_to "/login/acesso", notice: "Dados incorretos"
    end
  end

  private

  def login_params
    params.require(:login).permit(:email, :senha)
  end
end                      

【讨论】:

  • 我没有任何名为 accesso_path 或 login_new 的方法。这在这里不存在)=
  • 没有。这些是路径名。查看我在上面粘贴的rake routes 的输出(第 1 行和第 6 行)。就像我说的那样,您正在尝试 redirect_to login_path 并且该路径需要 id(第 8 行)。顺便说一句,我把new_login_path 的路径名弄错了,我刚刚更正了它。
  • 我明白这一点,但我怎样才能“清除”缓存呢?我的意思是,如果我也删除了 before_ation 和 helper_method 这两种方法,我会收到此错误:在该行找不到具有 'id'=2 的用户:def new if session[:user] @user = User.find( session[:user]) end end
  • 这对我来说没有意义,因为 id=2 是我在从 DB 的表中删除之前测试过的最后一个 id。
  • @jvillian 可以接受他的回答。你必须阅读更多关于rails路由guides.rubyonrails.org/routing.html
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多