我正在使用Devise和Rails 4开发一个网络应用程序。我有一个用户模型,我已经扩展了2个额外的表单字段,这样当用户注册时他也可以提交他的名/姓。 (基于http://blog.12spokes.com/web-design-development/adding-custom-fields-to-your-devise-user-model-in-rails-4/)。我现在想要添加机构模型。此模型 has_many :用户和用户 belongs_to :机构。我希望能够在我注册用户的同一表格上注册机构名称。我知道我需要在 Institution 模型中使用nested_attribute,因为这是父类,我将稍微展示一下。当我尝试注册用户时,我进入控制台:未加工参数:机构。
我的提示是我无法根据我的子类(User)更新我的父类(Institution)。可能有解决方案吗?或者有没有人经历过类似的事情?
class Institutions < ActiveRecord::Base
has_many :users,
accepts_nested_attributes_for :users
end
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
belongs_to :institution
end
registrations / new.html.erb 这里我有嵌套表格
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
.
.
<%= f.fields_for :institutions do |i| %>
<p><%= i.label :name %><br />
<%= i.text_field :institutions_attr %></p>
<% end %>
根据我之前链接的教程,我创建了一个新的 User :: ParameterSanitizer ,它继承自 Devise :: ParameterSanitizer 并覆盖 { {1}} 方法如下:
LIB / user_sanitizer.rb
sign_up
最后,我的 application_controller.rb
private
def sign_up
default_params.permit(:first_name, :last_name ,:email, :password, :password_confirmation, :current_password, institutions_attributes: [:id, :name])
end
感谢您阅读!
控制台参数输出:
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
protected
def devise_parameter_sanitizer
if resource_class == User
User::ParameterSanitizer.new(User, :user, params)
else
super
end
end
end
修改
根据建议,我添加了
{"utf8"=>"✓",
"authenticity_token"=>"JKuN6K5l0iwFsj/25B7GKDj7WEHR4DO3oaVyGxGJKvU=",
"user"=>{"email"=>"abc@foo.com",
"first_name"=>"abc",
"last_name"=>"xyz",
"institutions"=>{"name"=>"Government"},
"password"=>"[FILTERED]",
"password_confirmation"=>"[FILTERED]"},
"commit"=>"Sign up"}
但是,如果我重新编辑
params.require(resource_name).permit( :email, :first_name, :last_name, institution: [:name], :password, :password_confirmation ) and I get an *error syntax error, unexpected ',', expecting => ...nstitution: [:name], :password, :password_confirmation )*
我没有语法错误,但我得到了Unpermited参数:请求中的机构。
我认为这是因为用户是机构的孩子。但是,我无法找到解决方法。
答案 0 :(得分:37)
<强>配置/ routes.rb中强>
像这样创建你自己的注册控制器...(see Devise documentation for the details of overriding controllers here ...)...这是更优雅的方式,而不是通过ApplicationController
devise_for :users, controllers: {registrations: 'users/registrations'}
应用/控制器/用户/ registrations_controller.rb 强>
重写新方法以创建与Profile
模型关联的User
,如下所示...运行configure_permitted_parameters
方法之前清理参数(注意如何添加嵌套参数)
class Users::RegistrationsController < Devise::RegistrationsController
before_filter :configure_permitted_parameters
# GET /users/sign_up
def new
# Override Devise default behaviour and create a profile as well
build_resource({})
resource.build_profile
respond_with self.resource
end
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) { |u|
u.permit(:email, :password, :password_confirmation, :profile_attributes => :fullname)
}
end
end
<强>分贝/迁移/ xxxxxxxxxxxxxx_create_profiles.rb 强>
这是生成Profile
模型的迁移(注意对User
的引用)...此示例配置文件仅将fullname
作为扩展名User
的{{1}}但可随意添加!
class CreateProfiles < ActiveRecord::Migration
def change
create_table :profiles do |t|
t.references :user
t.string :fullname
t.timestamps
end
end
end
应用/模型/ user.rb 强>
class User < ActiveRecord::Base
# Associations
has_one :profile, dependent: :destroy, autosave: true
# Allow saving of attributes on associated records through the parent,
# :autosave option is automatically enabled on every association
accepts_nested_attributes_for :profile
# Devise
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
应用/模型/ profile.rb 强>
class Profile < ActiveRecord::Base
# Associations
belongs_to :user
# Validations
validates :fullname, presence: true
end
应用/视图/设计/注册/ new.html 强>
<% resource.build_profile if resource.profile.nil? %>
<%= form_for(resource, :as => resource_name,
:url => registration_path(resource_name)) do |f| %>
<ul>
<%= devise_error_messages! %>
<li class="fullname">
<%= f.fields_for :profile do |profile_fields| %>
<%= profile_fields.label :fullname %>
<%= profile_fields.text_field :fullname %>
<% end %>
</li>
<li class="email">
<%= f.label :email %>
<%= f.email_field :email, :autofocus => true %>
</li>
<li class="password">
<%= f.label :password %>
<%= f.password_field :password %>
</li>
<li class="password">
<%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation %>
</li>
<li>
<%= f.submit %>
</li>
<li>
<p><%= render "devise/shared/links" %></p>
</li>
</ul>
<% end %>
答案 1 :(得分:12)
您必须创建自己的注册控制器,方法如下:
<强> 的routes.rb 强>
devise_for :users, controllers: {registrations: 'registrations'}
<强> 控制器 强>
您必须将:your_fields
替换为您想要允许的字段(抱歉,如果我将其留给您,但这会使我的答案更加通用,因此对于任何可以通过的人都可以使用)
class RegistrationsController < Devise::RegistrationsController
private
def sign_up_params
allow = [:email, :your_fields, :password, :password_confirmation]
params.require(resource_name).permit(allow)
end
end
其他信息(嵌套属性+某些测试)
另请注意,如果您使用关联和accepts_nested_attributes_for
,则params
的结构将如此
model: {field, field, field, associated_model: {field, field}}
当然,您必须在sign_up_params
方法中使用相同的结构。如果您需要了解这一点,可以更改sign_up_params
方法的内容,如下所示:
def sign_up_params
params.require(resource_name).permit!
end
这将允许任何参数,然后发布您的表单(它应该通过这一次)并查看您的rails控制台以查看params
的结构,最后您可以正确设置sign_up_params
方法
选中此处以获取更多信息http://www.railsexperiments.com/using-strong-parameters-with-nested-forms/
在您的情况下,您应该使用:
params.require(resource_name).permit( :email, :first_name, :last_name, institutions: [:name], :password, :password_confirmation )
答案 2 :(得分:6)
使用rails 5.1和devise 4.4.1是最短的并且效果很好:
应用/模型/ user.rb 强>
after_initialize do
build_profile if new_record? && profile.blank?
end
应用/控制器/ application_controller.rb 强>
before_action :configure_permitted_parameters, if: :devise_controller?
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [{ profile_attributes: :name }])
end
这里的关键是你可以在不制作单独的控制器的情况下进行以下操作: