【问题标题】:Clearance additional strong_parameters in RoR4清除 RoR4 中的其他 strong_parameters
【发布时间】:2013-09-15 18:06:22
【问题描述】:

我使用的是clearance gem,基本上是通过电子邮件进行身份验证。

现在我想通过电子邮件保持登录,但想在用户的注册表单中添加一个“姓名”字段。

用户.rb

class User < ActiveRecord::Base
  include Clearance::User

  validates_presence_of :name
  validates_uniqueness_of :name
end

users_controller.rb

class UsersController < Clearance::UsersController
  def create
    @user = user_from_params

    if @user.save(permit_params)
      sign_in @user
      render :json => {:success => true}
    else
      render :json => {:success => false}
    end
  end

  private

  def user_from_params
    user_params = params[:user] || Hash.new
    email = user_params.delete(:email)
    password = user_params.delete(:password)

    Clearance.configuration.user_model.new(user_params).tap do |user|
      user.email = email
      user.password = password
    end
  end

  def permit_params
    params.require(:user).permit(:name, :email, :encrypted_password, :password, :confirmation_token, :remember_token)
  end
end

如您所见,我向.save 添加了权限,但该应用仍应请求向我抛出以下错误:

ActiveModel::ForbiddenAttributesError in Clearance::UsersController#create

如果我从表单中删除 :name 文本字段,一切正常,但我想要表单的其他字段。

【问题讨论】:

  • 我没有看到您所显示的内容有什么问题。你能显示 db/schema.rb 吗?您是否已将 :name 列迁移到数据库中?
  • 如果permit_params 不在.new(...) 语句中,例如Clearance.configuration.user_model.new(permit_params).tap....

标签: ruby-on-rails ruby-on-rails-4 strong-parameters clearance


【解决方案1】:

您需要将您的 users_controller 放入如下文件夹:

app/controllers/clearance/users_controller.rb

然后在 users_controller.rb 中,而不是:

class UsersController < Clearance::UsersController

你需要输入:

class Clearance::UsersController < ApplicationController

这不会覆盖清除用户控制器。相反,现在您正在编写它。这是您的注册表单将转到的控制器。因此,您仍然需要包含 Clearance 的 gem 中的基本代码并进行编辑 Clearance::UsersController#user_from_params

def user_from_params
  user_params = params[:user] || Hash.new
  email = user_params.delete(:email)
  password = user_params.delete(:password)
  name = user_params.delete(:name)

  Clearance.configuration.user_model.new(user_params).tap do |user|
    user.email = email
    user.password = password
    user.name = name
  end
end

并更新Clearance::UsersController#permit_params

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

【讨论】:

    【解决方案2】:

    更新:我已经更改了我之前的答案,因为它没有抓住重点。

    您提供的代码很好。您收到 ActiveModel::ForbiddenAttributesError 的原因是您没有覆盖 Clearance Users Controller。

    您需要通过将以下内容添加到您的 config/routes.rb 来告诉您的应用使用您的覆盖控制器而不是 Clearance 引擎中的控制器。

    resources :users,
      controller: 'users',
      only: 'create'
    

    IMO 这比在上面的应用程序代码中编写新的Clearance::UsersController 更好。

    【讨论】:

      【解决方案3】:

      您实际上不需要重新实现 create 方法,以防万一您正在创建 API(看起来像什么)。

      步骤如下:

      • config/routes.rb

        Rails.application.routes.draw do
          resources :users, controller: 'users', only: Clearance.configuration.user_actions
        end
        
      • app/controllers/users_controller.rb

        class UsersController < Clearance::UsersController
        
          private
        
          def user_from_params
            email = user_params.delete(:email)
            password = user_params.delete(:password)
            name = user_params.delete(:name)
        
            Clearance.configuration.user_model.new(user_params).tap do |user|
              user.email = email
              user.password = password
              user.name = name
            end
          end
        
        end
        

      之后,将名称字段添加到表单中即可。

      【讨论】:

        【解决方案4】:

        我尝试了两种方法,并意识到您不需要许可参数。你只需要做 4 件事:

        • 在迁移中添加名称列
        • 创建 app/controllers/users_contoller.rb 以覆盖 gem 控制器
        • 创建新表单以接受名称 app/views/users/new.html.erb
        • 修改您的路线

        从生成的迁移rails generate clearance:install开始(在运行rake db:migrate之前)

        1. 添加一个带有索引的 name:string 列,以便您的迁移看起来像: 通过添加此列,它包含在用户参数的创建中。

          def change
            change_table :users do |t|
              t.timestamps null: false
              t.string :email, null: false
              t.string :name, null: false, limit: 50
              t.string :encrypted_password, limit: 128, null: false
              t.string :confirmation_token, limit: 128
              t.string :remember_token, limit: 128, null: false
            end
          
            add_index :users, :name
            add_index :users, :email
            add_index :users, :remember_token
          end
          

        那么你只需要创建2个文件:

        app/controllers/users_controller.rb

        class UsersController < Clearance::UsersController
        
          def create
            @user = user_from_params
        
            if @user.save
              sign_in @user
              redirect_to '/'
            else
              render template: 'users/new'
            end 
          end 
        
          private
        
          def user_from_params
            user_params = params[:user] || Hash.new
            name = user_params.delete(:name)
            email = user_params.delete(:email)
            password = user_params.delete(:password)
        
            Clearance.configuration.user_model.new(user_params).tap do |user|
              user.name = name
              user.email = email
              user.password = password
            end
          end
        end
        

        app/views/users/new.html.erb

        <div id='clearance' class='sign-up'>
          <h2><%= t('.title') %></h2>
        
          <%= form_for @user do |form| %>
          <div class='text-field'>
            <%= form.label :name %>
            <%= form.text_field :name, :type => 'name' %>
          </div>
        
          <div class='text-field'>
            <%= form.label :email %>
            <%= form.text_field :email, :type => 'email' %>
          </div>
        
          <div class='password-field'>
            <%= form.label :password %>
            <%= form.password_field :password %>
          </div>
        
          <div class='submit-field'>
            <%= form.submit %>
          </div>
        
          <div class='other-links'>
            <%= link_to t('.sign_in'), sign_in_path %>
          </div>
          <% end %>
        </div>
        

        那么你的路线应该包括这个

        resources :users,
            controller: 'users',
            only: 'create'
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-10-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-30
          • 1970-01-01
          相关资源
          最近更新 更多