[英]Multiple user models with Ruby On Rails and devise to have separate registration but one common login
i have same problem just like this link:我有同样的问题,就像这个链接:
Multiple user models with Ruby On Rails and devise to have separate registration routes but one common login route 使用 Ruby On Rails 的多个用户模型,并设计为具有单独的注册路径但有一个通用的登录路径
in my app there are two model在我的应用程序中有两个模型
Company公司
Employee员工
my User model我的用户模型
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
belongs_to :usr, :polymorphic => true
end
my Company model我的公司模式
class Company < ActiveRecord::Base
has_many :users, :as => :usr
end
my Employee model我的员工模型
class Employee < ActiveRecord::Base
has_many :users, :as => :usr
end
app/views/devise/registrations/new.html.erb应用程序/视图/设计/注册/new.html.erb
<h2>Sign up</h2>
<%
# customized code begin
params[:user][:user_type] ||= 'company'
if ["company", "employee"].include? params[:user][:user_type].downcase
child_class_name = params[:user][:user_type].downcase.camelize
user_type = params[:user][:user_type].downcase
else
child_class_name = "Company"
user_type = "company"
end
resource.usr = child_class_name.constantize.new if resource.usr.nil?
# customized code end
%>
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true %>
</div>
<div class="field">
<%= f.label :password %>
<% if @validatable %>
<em>(<%= @minimum_password_length %> characters minimum)</em>
<% end %><br />
<%= f.password_field :password, autocomplete: "off" %>
</div>
<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation, autocomplete: "off" %>
</div>
<% # customized code begin %>
<%= fields_for resource.usr do |rf| %>
<% render :partial => "#{child_class_name.underscore}_fields", :locals => { :f => rf } %>
<% end %>
<%= hidden_field :user, :user_type, :value => user_type %>
<% # customized code end %>
<div class="actions">
<%= f.submit "Sign up" %>
</div>
<% end %>
<%= render "devise/shared/links" %>
my registration create method :我的注册创建方法:
controllers/users/registrations_controller.rb控制器/用户/registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
def create
build_resource
# customized code begin
# crate a new child instance depending on the given user type
child_class = params[:user][:user_type].camelize.constantize
resource.usr = child_class.new(params[child_class.to_s.underscore.to_sym])
# first check if child instance is valid
# cause if so and the parent instance is valid as well
# it's all being saved at once
valid = resource.valid?
valid = resource.usr.valid? && valid
# customized code end
if valid && resource.save # customized code
if resource.active_for_authentication?
set_flash_message :notice, :signed_up if is_navigational_format?
sign_in(resource_name, resource)
respond_with resource, :location => redirect_location(resource_name, resource)
else
set_flash_message :notice, :inactive_signed_up, :reason => inactive_reason(resource) if is_navigational_format?
expire_session_data_after_sign_in!
respond_with resource, :location => after_inactive_sign_up_path_for(resource)
end
else
clean_up_passwords(resource)
respond_with_navigational(resource) { render :new }
end
end
end
my application helper file :我的应用程序帮助文件:
module ApplicationHelper
def my_devise_error_messages!
return "" if resource.errors.empty? && resource.usr.errors.empty?
messages = usr_messages = ""
if !resource.errors.empty?
messages = resource.errors.full_messages.map { |msg| content_tag(:li, msg) }.join
end
if !resource.usr.errors.empty?
usr_messages = resource.usr.errors.full_messages.map { |msg| content_tag(:li, msg) }.join
end
messages = messages + usr_messages
sentence = I18n.t("errors.messages.not_saved",
:count => resource.errors.count + resource.usr.errors.count,
:resource => resource.class.model_name.human.downcase)
html = <<-HTML
<div id="error_explanation">
<h2>#{sentence}</h2>
<ul>#{messages}</ul>
</div>
HTML
html.html_safe
end
end
but i got error something like this when i open any user sign_up page:但是当我打开任何用户注册页面时,我遇到了这样的错误:
localhost:3000/emloyees/sign_up **OR**
localhost:3000/companies/sign_up
error in registration view注册视图中的错误
ERROR :-错误 :-
So what am I doing wrong?那么我做错了什么?
Your question is really broad but to solve the error you posted, it is erroring undefined method because of the nested hash that doesn't exist.您的问题非常广泛,但为了解决您发布的错误,由于不存在的嵌套散列,它正在错误未定义的方法。 Here's the example:这是示例:
[1] pry(main)> params = {}
=> {}
[2] pry(main)> params[:user]
=> nil
[3] pry(main)> params[:user][:user_type]
NoMethodError: undefined method `[]' for nil:NilClass
If your code is to expect that params[:user] won't ever exist without a user_type
and you want to default that to company, then that would simply be:如果您的代码期望 params[:user] 在没有user_type
情况下永远不会存在,并且您希望将其默认为 company,那么这将是:
[7] pry(main)> params[:user] ||= { user_type: "company" }
=> {:user_type=>"company"}
[8] pry(main)> params
=> {:user=>{:user_type=>"company"}}
Alternativley if you want to just return a string if params[:user] doesn't exist, you can use ||= or Hash#fetch with a default value.或者,如果您只想在 params[:user] 不存在的情况下返回一个字符串,您可以使用 ||= 或Hash#fetch与默认值。 Hash#fetch is a safer way to error handle imo. Hash#fetch 是一种更安全的错误处理方式。
[5] pry(main)> params.fetch(:user, "company")
=> "company"
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.