如何在 Ruby on Rails 5.2.3 中正确地将 html 表单发布到控制器

Nan*_*ore 3 ruby-on-rails

我是 ruby​​ on Rails 的新手。这里我尝试将 html 表单发布到 ruby​​ on Rails (5.2.3 版本) 为此,我参考了此处找到的解决方案链接

<form accept-charset="UTF-8" method='post' action='http://localhost:3000/user1s'>

      
        <label for='name'>Name</label>
            <input type="text" name='name' placeholder='Enter your name'> <br>
        <label for='password'>password</label>
            <input type="text" name='password' placeholder='Enter your password'> <br>
        <label for='email'>confirm pass</label>
            <input type="text" name='password_confirmation' placeholder='Enter your password_confirmation'> <br>
     
            <input type="submit" value='Save'>
    </form>
Run Code Online (Sandbox Code Playgroud)

用户1控制器

class User1sController < ApplicationController
    

  # POST /user1s
  # POST /user1s.json
  def create
    @name = params[:name]
    @password = params[:password]
    @password_confirmation = params[:password_confirmation]
    @user1 = User1.new(name=>@name, password=>@password , password_confirmation=>@password_confirmation)

    respond_to do |format|
      if @user1.save
        format.html { redirect_to @user1, notice: 'User1 was successfully created.' }
        format.json { render :show, status: :created, location: @user1 }
        #format.json {status: :created }
      else
        format.html { render :new }
        format.json { render json: @user1.errors, status: :unprocessable_entity }
      end
    end
  end

  
end
Run Code Online (Sandbox Code Playgroud)

这是config/routes.rb

Rails.application.routes.draw do
  #resources :user1s
  post '/user1s', to: 'user1s#create', as: 'user1s'  
end
Run Code Online (Sandbox Code Playgroud)

当我运行代码时出现以下错误

浏览器为打开了基于源的伪造保护的请求返回了“空”源。这通常意味着您启用了“no-referrer”Referrer-Policy 标头,或者请求来自拒绝提供其来源的站点。这使得 Rails 无法验证请求的来源。最好的解决方案可能是将您的引荐来源网址政策更改为不太严格的政策,例如同源或严格同源。如果无法更改引荐来源网址策略,可以使用 Rails.application.config.action_controller.forgery_protection_origin_check 设置禁用来源检查。

为了减轻上述错误,我在此处引用了链接,该链接建议了下面的解决方案,但无法使其正常工作。 链接2

在 config/application.rb 我有

Bundler.require(*Rails.groups)

module Saverecord
  class Application < Rails::Application
    Rails.application.config.action_controller.forgery_protection_origin_check = false
    config.action_controller.allow_forgery_protection = false

    # Initialize configuration defaults for originally generated Rails version.
    config.load_defaults 5.2

  end
end
Run Code Online (Sandbox Code Playgroud)

在应用程序控制器我有

class ApplicationController < ActionController::Base   
  # Prevent CSRF attacks by raising an exception.   
  # For APIs, you may want to use :null_session instead.   
  #protect_from_forgery with: :exception   
  protect_from_forgery with: :null_session

  
end  
Run Code Online (Sandbox Code Playgroud)

max*_*max 5

如果您只遵循 Rails 约定,这会容易得多。

首先使用强参数,而不是从 params 哈希中复制变量两次。

class User1sController < ApplicationController
  # POST /user1s
  # POST /user1s.json
  def create
    # Use strong parameters instead  
    @user1 = User1.new(user1_parameters)

    respond_to do |format|
      if @user1.save
        format.html { redirect_to @user1, notice: 'User1 was successfully created.' }
        format.json { render :show, status: :created, location: @user1 }
        #format.json {status: :created }
      else
        format.html { render :new }
        format.json { render json: @user1.errors, status: :unprocessable_entity }
      end
    end
  end

  # ...
  private 
  def user1_parameters
    params.require(:user1).permit(:name, :email, :password, :password_confirmation)
  end
end
Run Code Online (Sandbox Code Playgroud)

Ruby(和 Rails)具有用于操作哈希的出色功能。如果您曾经手动将密钥从一个散列复制到另一个散列,那么您就错了。

然后使用表单助手而不是手动创建表单:

<%= form_with(model: @user1) do |form| %>
  <div class="field">
    <%= form.label :name %>
    <%= form.text_field :name %>
  </div>
  <div class="field">
    <%= form.label :email %>
    <%= form.email_field :email %>
  </div>
  <div class="field">
    <%= form.label :password %>
    <%= form.password_field :password %>
  </div>
  <div class="field">
    <%= form.label :password_confirmation %>
    <%= form.password_field :password_confirmation %>
  </div>
  <div class="actions">
    <% form.submit %>
  </div>
<% end %>
Run Code Online (Sandbox Code Playgroud)

Rails 内置了跨站点引用伪造 (CSRF) 对策,这意味着 Rails 将拒绝不包含有效 CSRF 令牌的表单提交。form_with当您使用(或更旧的form_tag)创建表单时,form_forRails 会包含一个 CSRF 令牌作为表单中的隐藏输入。

这意味着您手工制作的表单是不行的,除非您禁用 CSRF 保护或提供比仅使用表单助手复杂得多的令牌。

您的表单也没有name为嵌套哈希使用正确的属性。Rails 按照惯例使用嵌套哈希:

{
  users1: {
    name: 'foo',
    email: 'foo@example.com'
    ...
  }
}
Run Code Online (Sandbox Code Playgroud)

表单助手通过在输入上设置正确的名称属性来实现此目的:

<input type="email" name='user1[email]' ...>
Run Code Online (Sandbox Code Playgroud)

params.require(:user1).permit(...). 您的表格将出现ActionController::ParameterMissing错误。您可以解决这个问题,使用平面哈希,但您也可以学习Rails Way来避免潜在的名称冲突。