21

我正在尝试向registrations#new 添加一些额外的字段。由于我只想要额外的数据并且不需要不同的功能,我不明白为什么我需要覆盖控制器等。所以我所做的是修改registrations#new,如下所示:

%h2
  Sign up
= form_for(resource, as: resource_name, url: registration_path(resource_name)) do ||f
  = devise_error_messages!
  %div
    = f.label :email
    %br
    = f.email_field :email, autofocus: true
  %div
    = f.label :title_id
    %br
    = f.text_field :title_id
  %div
    = f.label :province_id
    %br
    = f.text_field :province_id
  %div
    = f.label :first_name
    %br
    = f.text_field :first_name
  %div
    = f.label :last_name
    %br
    = f.text_field :last_name
  %div
    = f.label :password
    %br
    = f.password_field :password
  %div
    = f.label :password_confirmation
    %br
    = f.password_field :password_confirmation
  %div= f.submit 'Sign up'
= render 'devise/shared/links'

为了通过 sanitizer 启用这些额外的字段,我更新了 ApplicationController 如下:

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
  before_filter :store_requested_url!
  # before_filter :authenticate_user!

  def configure_permitted_parameters
    devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(:email) }
    devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:email, :password, :password_confirmation, :title_id, :province_id, :first_name, :last_name) }
    devise_parameter_sanitizer.for(:account_update) { |u| u.permit(:email, :password, :password_confirmation, :current_password) }
  end

  def after_sign_in_path_for(resource)
    session[:requested_url] || root_path
  end

  private

  def store_requested_url
    # store last url as long as it isn't a /users path
    session[:previous_url] = request.fullpath unless request.fullpath == /\/users/
  end
end

由于某种原因,它不起作用,额外的字段作为空值进入数据库。

我正在使用带有 Devise 3.0.0.rc 的 Ruby 2 和 Rails 4 rc1。

4

8 回答 8

31

您的问题中的代码示例似乎不起作用,因为您没有设置 before_filter 来调用消毒剂。

before_filter :configure_permitted_parameters, if: :devise_controller?

话虽如此,最好覆盖控制器,如接受的答案所示,这样应用程序控制器就不会一直进行此检查。可以使用下面的代码缩短接受的答案。我已经用我的应用程序测试了这段代码,它运行良好。所有这些都记录在3.0.0.rc 标记中自述文件的强参数部分。

覆盖控制器:

class RegistrationsController < Devise::RegistrationsController
  before_filter :configure_permitted_parameters, :only => [:create]

  protected

    def configure_permitted_parameters
      devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:username, :email, :password) }
    end
end

然后更新路由以使用它:

devise_for :members, :controllers => { :registrations => "registrations" }
于 2013-06-06T23:35:52.973 回答
16

从 2017 年 5 月 15 日的 Devise 版本 4.3.0 开始,文档中的解决方案如下。在这种情况下,将添加用户名字段。

如果您想允许附加参数(惰性方式™),您可以在 ApplicationController 中使用简单的前置过滤器来实现:

class ApplicationController < ActionController::Base
  before_action :configure_permitted_parameters, if: :devise_controller?

  protected

  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:username])
  end
end

当然,只需将该字段添加到您的数据库中

> rails g migration AddUsernameToUsers

class AddUsernameToUsers < ActiveRecord::Migration[5.0]
  def change
    add_column :users, :username, :string, null: false, index: true, unique: true
  end
end

然后将必要的字段添加到注册视图中#new

<%= f.text_field :username, placeholder: "Username"  %>
于 2017-05-17T21:45:43.433 回答
12

在设计 4.0 之后,关于此主题的旧答案无效。而不是for您必须使用的方法:

devise_parameter_sanitizer.permit(:sign_up, keys: [:username])

所以,对于一个完整的解决方案ApplicationController

class ApplicationController < ActionController::Base
  before_action :configure_permitted_parameters, if: :devise_controller?

  protected
    def configure_permitted_parameters
       devise_parameter_sanitizer.permit(:sign_up, keys: [:username])
    end
end
于 2016-08-18T21:44:08.097 回答
10

好的,所以我所做的只是覆盖设计注册控制器,根据设计文档更新 routes.rb 以反映这一点,按原样复制并粘贴用于注册的设计代码#create,并将获取参数部分更改为使用我自己的强参数方法,就是这样。

class RegistrationsController < Devise::RegistrationsController

  def create
    build_resource(registration_params)

    if resource.save
      if resource.active_for_authentication?
        set_flash_message :notice, :signed_up if is_navigational_format?
        sign_up(resource_name, resource)
        respond_with resource, :location => after_sign_up_path_for(resource)
      else
        set_flash_message :notice, :"signed_up_but_#{resource.inactive_message}" if is_navigational_format?
        respond_with resource, :location => after_sign_up_path_for(resource)
      end
    else
      clean_up_passwords
      respond_with resource
    end
  end  

  private

  def registration_params
    params.require(:user).permit(:email, :title_id, :first_name, :last_name, 
      :province_id, :password, :password_confirmation)
  end

end
于 2013-05-12T00:11:45.210 回答
9

首先公开视图

rails generate devise:views users

然后编辑 config/initializers/devise.rb 并更改

# config.scoped_views = false

config.scoped_views = true

这将允许您修改 app/views/users/registration 中的视图。

您将在此处添加所需的字段

app/views/users/registration/edit.html.erb

app/views/users/registration/new.html.erb

现在我们必须处理 rails mass assignment 问题,去 application_controller.rb 并添加一个 before_filter

before_filter :configure_permitted_parameters, if: :devise_controller?

然后添加您的字段 + 原始字段以进行清理

protected

    def configure_permitted_parameters
        # Fields for sign up
        devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:username, :email, :password) }
        # Fields for editing an existing account
        devise_parameter_sanitizer.for(:account_update) { |u| u.permit(:username, :email, :password, :current_password, :gender) }
    end

重新启动您的网络服务器并交叉手指。

于 2015-09-07T08:52:51.653 回答
6

我有类似的情况(只是领域不同)。

这是官方文档可以提供的方式:只需将其添加到您的 ApplicationController。并将“用户名”更改为您需要的任何内容,并在需要时添加更多内容。

before_action :configure_permitted_parameters, if: :devise_controller?

  protected

  def configure_permitted_parameters
    devise_parameter_sanitizer.for(:sign_up) << :username
  end

我的应用程序控制器如下所示:

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

  before_action :configure_permitted_parameters, if: :devise_controller?

  protected

    def configure_permitted_parameters
      devise_parameter_sanitizer.for(:sign_up) << :public_name
    end
end

更多细节在这里:https ://github.com/plataformatec/devise (“强参数”)

于 2015-01-26T14:35:21.380 回答
3

首先:rails 4 是否存在新的“强参数”问题,您可能也想研究一下。

如果您将新参数迁移到您的用户模型中。然后您所要做的就是覆盖(创建)文件:

app/views/devise/registrations/edit.html.erb
app/views/devise/registrations/new.html.erb

您可以在此处查看默认文件: https ://github.com/plataformatec/devise/tree/master/app/views/devise/registrations

如果您可能想要实现自己的registrations_controller.rb(带有新建和编辑操作)和您自己的@variables,那么将其添加到您的routes.rb中很重要

devise_for :users, :controllers => { :registrations => 'registrations' }
resources :users

这样可以确保该设计从现在开始使用您的新“注册”控制器(如果您决定拥有一个)。

我不知道“消毒剂”或这有什么好处。但是我的应用程序可以很好地配合我刚刚向您推荐的那些小改动。您不需要覆盖控制器!覆盖视图就足够了。

于 2013-05-09T21:49:31.933 回答
1

可以像这个例子一样添加新字段。对于设计 4,Parameter Sanitaizer API 已更改:

class ApplicationController < ActionController::Base
  before_action :configure_permitted_parameters, if: :devise_controller?

  protected

  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:username, :name])
  end
end
于 2020-07-20T14:55:09.043 回答