ruby Rails 7 -创建新记录时发生路由错误

crcmnpdw  于 12个月前  发布在  Ruby
关注(0)|答案(3)|浏览(82)

创建新记录时出现路由错误。我无法理解为什么Rails将POST请求视为GET。详情如下:
我有一个表格,如下所述:

<%= form_with model: @user, url: home_new_user_path, method: :post do |f|%>

<%= hidden_field_tag :authenticity_token, form_authenticity_token %>

<%= f.text_field :name, placeholder: "Enter name", class: 'form-content form-content w-100 p-1', autocomplete: "off" %>

<%= f.text_field :email, placeholder: "Enter email", class: 'form-content form-content w-100 p-1', autocomplete: "off" %> 

<%= f.text_field :password, placeholder: "Enter password", class: 'form-content form-content w-100 p-1', autocomplete: "off" %>

<%= f.text_field :password_confirmation, placeholder: "Enter password to confirm", class: 'form-content form-content w-100 p-1', autocomplete: "off" %>

<%= f.submit %>

<%end%>

下面是路线.rb

post 'home/new_user', to: 'home#new_user'

下面是控制器方法:

def new_user
   user_to_be_created = User.create!(name: params[:name], email: params[:email], password: params[:password], password_confirmation: params[:password_confirmation])
  end

查看访问此控制器方法的代码:

<%= link_to "New user", home_new_user_path, method: :post %>

然而,我得到了如下的路由错误:

No route matches [GET] "/home/new_user"
db2dz4w8

db2dz4w81#

你可能正在使用Rails,但你正在编写的代码不是Rails代码。
在Rails中,创建一个记录是通过两个单独的操作来处理的,分别是newcreate

HTTP Method   Path         Description
----------------------------------------------------------------
GET           /users/new   Renders a form which is used to create a user.
POST          /users       Responds to form submissions and creates the user

显示表单的new操作使用GET,因为它是一个幂等操作。它不会创建或修改任何东西,对所有访问者来说都是一样的。
实际上,记录的创建是通过将表单发送到集合路径(/users)来完成的。如果记录无效,新视图将作为响应呈现,但这一次它应该包含来自验证的错误消息。
您可以使用资源宏生成这些路由:

# routes.rb
resources :users, only: [:new, :create]

链接到新操作是通过以下方式完成的:

<%= link_to "New user", new_user_path %>

按照惯例,您将在UsersController中响应这些请求。
将应用程序中的所有内容打包到一个god类HomeController中并不是一个好的做法。

class UsersController < ApplicationController
  before_action :authenticate_user!
  # @todo authorize that the current user should be allowed to create users

  # GET /users/new
  def new
    @user = User.new
  end

  # POST /users/new
  def create
    @user = User.new(user_params)
    if @user.save
      redirect_to '/somewhere' # @todo replace with actual path
    else
      render :new
    end
  end

  private

  def user_params
    params.require(:user)
          .permit(
            :name, :email, :password, :password_confirmation
          )
  end
end

您的表单还应该使用以下约定:

# app/views/users/_form.html.erb
<%= form_with model: @user do |f|%>
  <% if @user.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@user.errors.count, "error") %> prohibited this user from being saved:</h2>
 
      <ul>
      <% @user.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%# do not use placeholders as labels. It's a huge accessibilty anti-pattern %>
    <%= f.label :name %> 
    <%= f.text_field :name, class: 'form-content form-content w-100 p-1', autocomplete: "off" %>
  </div>
  <div class="field">
    <%= f.label :email %>
    <%= f.text_field :email, class: 'form-content form-content w-100 p-1', autocomplete: "off" %> 
  </div>
  <div class="field">
    <%= f.label :password %>
    <%= f.text_field :password, class: 'form-content form-content w-100 p-1', autocomplete: "off" %>
  </div>
  <div class="field">
    <%= f.label :password_confirmation %>
    <%= f.text_field :password_confirmation, class: 'form-content form-content w-100 p-1', autocomplete: "off" %>
  </div>
  <div class="action"> 
    <%= f.submit %>
  </div>
<% end %>
# app/views/users/new.html.erb
<%= render partial: "form" %>

当你传递一个User Rails的示例时,它会检查模型是否被持久化,并自动将请求方法设置为POST,并从类名中派生出正确的路由users_path。通过不显式设置任何一个,您可以重复使用相同的表单进行编辑。
但是
如果你打算在生产应用程序中实际使用它,我真的建议你使用Devise::Invitable。它消除了要求管理员设置用户密码然后与用户交流密码的麻烦和潜在的安全隐患。
不要重新发明轮子。

brtdzjyr

brtdzjyr2#

在rails 7中,你应该使用data-turbo-method="post"属性来使JavaScript魔法与链接

<%= link_to "New user", home_new_user_path, data: { turbo_method: :post } %>

如果你使用表单而不是链接,那么魔法就不会发生了。为此,您可以使用button_to助手

<%= button_to "New user", home_new_user_path, method: :post %>

顺便说一句,

post 'home/new_user', to: 'home#new_user'

不是RESTful路由,可能更好地使用

resources :users, only: :create
ar5n3qh5

ar5n3qh53#

通过link_to提交非GET请求需要JS或Turbo,如文档所述:
支持的动词有:post:delete:patch:put。请注意,如果用户禁用了JavaScript,则请求将回退到使用GET。
你应该使用button_to而不是link_to。重新连接link_to以发送POST请求将是一个麻烦,需要JS。
This tutorial演示如何使用button_to发出post/put请求

相关问题