Оформление дополнительных strong_parameters в RoR4

Я использую драгоценный камень оформления, который является в основном аутентификацией по электронной почте.

Теперь я хочу сохранить вход по электронной почте, но хочу добавить поле "имя" в регистрационную форму для пользователя.

User.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 Текстовое поле из моей формы все работает, но я хочу дополнительные поля для моей формы.

4 ответа

Решение

Вы должны поместить свой users_controller в такие папки:

приложение / контроллеры / оформление /users_controller.rb

Затем в users_controller.rb вместо:

class UsersController < Clearance::UsersController

вам нужно поставить:

class Clearance::UsersController < ApplicationController

Это не отменяет пользовательский контроллер Clearance. Вместо этого, теперь вы пишете это. Это контроллер, на который будет отправлена ​​ваша регистрационная форма. Таким образом, вам все равно нужно включить базовый код из гема Clearance и отредактировать 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

и обновить оформление:: UsersController # allow_params

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

ОБНОВЛЕНИЕ: я изменил свой предыдущий ответ, так как он упускал суть.

Код, который вы предоставили, в порядке. Причина, по которой вы получаете ActiveModel::ForbiddenAttributesError потому что вы не переопределяете контроллер пользователей Clearance.

Вы должны указать своему приложению использовать переопределяющий контроллер вместо контроллера в движке Clearance, добавив следующее в ваш config/rout.rb.

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

ИМО это лучше, чем писать новый Clearance::UsersController в коде вашего приложения выше.

Вам на самом деле не нужно переопределять create метод, на всякий случай, если вы создаете API (как выглядит).

Шаги:

  • конфиг /routes.rb

    Rails.application.routes.draw do
      resources :users, controller: 'users', only: Clearance.configuration.user_actions
    end
    
  • приложение / контроллеры /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 вещи:

  • Добавить столбец имени в миграции
  • Создайте 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 файла:

приложение / контроллеры / 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

а также

приложение / просмотров / пользователей / 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'
Другие вопросы по тегам