【问题标题】:Rails No route matches {:action=>"destroy", :controller=>"session"}, missing required keys: [:id]Rails 没有路由匹配 {:action=>"destroy", :controller=>"session"},缺少必需的键:[:id]
【发布时间】:2018-06-19 01:48:06
【问题描述】:

我正在开发一个具有身份验证的 Rails 应用程序,并且收到一条错误消息:

没有路由匹配 {:action=>"destroy", :controller=>"session"},缺少必需的键:[:id]

我在尝试从会话控制器呈现“新”视图时遇到此错误,并且无法弄清楚为什么它应该只查看 New/Create 方法时引用 destroy 方法。以下是我如何设置路线、控制器、模型和视图,如果有人可以就我需要检查的内容给我一些指导,将不胜感激。

路线:

Rails.application.routes.draw do root to: "root#index" resources :users, only: [:new, :create, :index, :show] resources :session, only: [:new, :create, :destroy] resources :pets end

型号:

class User < ApplicationRecord

  PASSWORD_LENGTH = (6..25)
  USERNAME_LENGTH = (5..25)

  validates_presence_of :username
  validates :username, length: USERNAME_LENGTH, uniqueness: true
  validates :password, length: PASSWORD_LENGTH, allow_nil: true

  has_many :pets

  attr_reader :password

  def self.find_from_credentials(username, password)
    user = find_by(username: username)
    return nil unless user
    user if user.is_password?(password)
  end

  def is_password?(password_attempt)
    BCrypt::Password.new(password_digest).is_password?(password_attempt)
  end

  def password=(password)
    @password = password
    self.password_digest = BCrypt::Password.create(password)
  end
end

控制器:

class SessionController < ApplicationController

    before_action :ensure_signed_out, only: [:new, :create]

    def new
        @user = User.new
    end

    def create
        username = user_params[:username]
        password = user_params[:password]

        user = User.find_from_credentials(username, password)

        if user
            sign_in(user)
            flash[:notice] = "#{username} has successfully signed in."
            redirect_to "/"
        else
            flash[:error] = "User not found."
            @user = User.new(username: username)
            render :new
        end
    end

    def destroy
        sign_out
        flash[:notice] = "User signed out."
        redirect_to new_session_path
    end

    private

    def user_params
        params.require(:user).permit(:username, :password)
    end
end

查看:

<h2>Enter your credentials below: </h2>

<%= form_for :user, url: session_path do |f| %>
    <%= f.text_field :username, placeholder: 'Username', required: true %>
    <%= f.password_field :password, placeholder: 'Password', required: true %>
    <%= submit_tag 'Log in' %>
<% end %>


<p> Don't have an account?  <%= link_to 'Sign up here!', new_user_path %></p>

【问题讨论】:

    标签: ruby-on-rails session authentication


    【解决方案1】:

    问题在于表单中使用的 URL,因为它应该根据我的路由指向 session_index_path。感谢所有回复!

    【讨论】:

      【解决方案2】:

      先说明一下:如果您使用的是 Rails 5.x,那么您需要在视图中使用 form_withCheck it out here

      我认为问题在于您用于表单的网址。您正在告诉表单向将导致 session#show 操作 (session_path) 的 url 提交 post 请求,但这不存在并且您没有发送会话实例这就是为什么它说它缺少 id。

      您的表单应该如下所示(您可能只是缺少了一个“s”:

      <h2>Enter your credentials below: </h2>
      # you will need to run 'rails routes' in your terminal to find out the exact prefix, but you want the prefix that routes to 'sessions#create'
      <%= form_with url: sessions_path do |f| %>
          <%= f.text_field :username, placeholder: 'Username', required: true %>
          <%= f.password_field :password, placeholder: 'Password', required: true %>
          <%= submit_tag 'Log in' %>
      <% end %>
      
      
      <p> Don't have an account?  <%= link_to 'Sign up here!', new_user_path %></p>
      

      【讨论】:

      • 我又看了一遍我的路由,重点是会话路由: session_index POST /session(.:format) session#create
        new_session GET /session/new(.:format) session #new
        session DELETE /session/:id(.:format) session#destroy
        我认为我的第一个问题是将 DELETE URI Pattern 更改为 /session,我的第二个问题是缺少 POST该会话路线也是如此。我会继续修补,看看是否可以修复这些更改。感谢您的回复!
      • 那么看起来您应该使用的 url 助手是 session_index_path,因为这将用于会话控制器中的创建操作,对吧?
      【解决方案3】:

      欢迎来到 StackOverflow — 第一个问题很好!

      从顶部开始:当您在 routes.rb 文件中调用 resources 时,您是在告诉 Rails 为标准 CRUD 创建路由。

      现在,根据比你和我更聪明的人——也就是那些将他们的鲜血/汗水/泪水倾注到 Rails 中的人——根据 RESTful 标准,删除资源——在你的情况下,Session——需要服务器响应 DELETE 类型的请求(GET/POST/PATCH/PUT/DELETE...还有更多),

      DELETE /sessions/1

      Rails 像这样映射:

      match '/sessions/:id' =&gt; 'sessions#destroy', :via =&gt; :delete

      via 很重要。请注意,match 也可以只是 delete,我们可以省略 via

      现在因为我没有您的完整视图文件,所以很难确定发生这种情况的位置。但是要知道,如果您打算删除 Session 资源,则需要知道它的 ID,这就是此错误试图告诉您的内容:为该路径生成 URL 帮助程序(一些 Rails 魔术)需要一个持久化的 Session。

      【讨论】:

      • 我把我的回复搞砸了,如果这给你的收件箱发了垃圾邮件,我很抱歉。我发布的视图文件是整个视图文件,如果您需要其他文件,请告诉我,我很乐意发布。我明白你所说的错误在说什么,这更清楚。我正在努力解决的是为什么 New 视图会在加载后立即引用 Destroy 方法。我的理解是视图只引用了它们在控制器中的特定方法。
      • 那么你会想要使用看起来像的sessions_index_path。这会路由到会话控制器中的创建操作,对吧?
      • 哦,这样更容易解决!另一条评论让我认为这是我的路线中的问题,但是在视图中进行更改完美地解决了问题,感谢您的提示!
      猜你喜欢
      • 2014-11-26
      • 1970-01-01
      • 1970-01-01
      • 2016-12-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多