gpt4 book ai didi

ruby-on-rails - 使用 Ruby On Rails 的多个用户模型,并设计有单独的注册路线,但只有一个共同的登录路线

转载 作者:行者123 更新时间:2023-12-03 08:29:09 25 4
gpt4 key购买 nike

首先,我用谷歌和雅虎进行了激烈的搜索,我发现了几个像我这样的主题的回复,但它们都没有真正涵盖我需要知道的内容。
我的应用程序中有几个用户模型,现在是客户、设计师、零售商,而且似乎还有更多。他们都有不同的数据存储在他们的表和网站上他们被允许或不允许的几个区域中。所以我想去 devise+CanCan 的方式,并用多态关联来试试我的运气,所以我得到了以下模型设置:

class User < AR
belongs_to :loginable, :polymorphic => true
end

class Customer < AR
has_one :user, :as => :loginable
end

class Designer < AR
has_one :user, :as => :loginable
end

class Retailer < AR
has_one :user, :as => :loginable
end
对于注册,我为每种不同的用户类型提供了自定义 View ,并且我的路线设置如下:
devise_for :customers, :class_name => 'User'
devise_for :designers, :class_name => 'User'
devise_for :retailers, :class_name => 'User'
现在注册 Controller 保留为标准(即“设计/注册”),但我想,因为我有不同的数据要存储在不同的模型中,我也必须自定义此行为!?
但是有了这个设置,我得到了像 customer_signed_in? 这样的帮助者。和 designer_signed_in? ,但我真正需要的是像 user_signed_in? 这样的通用助手对于网站上所有用户都可以访问的区域,无论是哪种用户类型。
我还想要一个像 new_user_session_path 这样的路线助手而不是几个 new_*type*_session_path等等。事实上,我需要与众不同的是注册过程......
所以我想知道这是否是解决这个问题的方法?或者是否有更好/更容易/更少必须定制的解决方案?

最佳答案

好的,所以我完成了它并得出了以下解决方案。
我需要对设计进行一些服装化,但这并不复杂。

用户模型

# user.rb
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable

attr_accessible :email, :password, :password_confirmation, :remember_me

belongs_to :rolable, :polymorphic => true
end

客户模型
# customer.rb
class Customer < ActiveRecord::Base
has_one :user, :as => :rolable
end

设计师模型
# designer.rb
class Designer < ActiveRecord::Base
has_one :user, :as => :rolable
end

所以用户模型有一个简单的多态关联,定义它是客户还是设计师。
接下来我要做的是使用 rails g devise:views 生成设计 View 。成为我申请的一部分。由于我只需要自定义注册,因此我保留了 app/views/devise/registrations仅文件夹并删除其余部分。

然后我为新注册定制了注册 View ,可以在 app/views/devise/registrations/new.html.erb 中找到。在你生成它们之后。
<h2>Sign up</h2>

<%
# customized code begin

params[:user][:user_type] ||= 'customer'

if ["customer", "designer"].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 = "Customer"
user_type = "customer"
end

resource.rolable = child_class_name.constantize.new if resource.rolable.nil?

# customized code end
%>

<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
<%= my_devise_error_messages! # customized code %>

<div><%= f.label :email %><br />
<%= f.email_field :email %></div>

<div><%= f.label :password %><br />
<%= f.password_field :password %></div>

<div><%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation %></div>

<% # customized code begin %>
<%= fields_for resource.rolable 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><%= f.submit "Sign up" %></div>
<% end %>

<%= render :partial => "devise/shared/links" %>

对于每个用户类型,我创建了一个单独的部分,其中包含该特定用户类型的自定义字段,即 Designer --> _designer_fields.html
<div><%= f.label :label_name %><br />
<%= f.text_field :label_name %></div>

然后我设置路由以在注册时使用自定义 Controller
devise_for :users, :controllers => { :registrations => 'UserRegistrations' }

然后我生成了一个 Controller 来处理定制的注册过程,从 create 复制原始源代码 Devise::RegistrationsController 中的方法并修改它以按我的方式工作(不要忘记将您的 View 文件移动到适当的文件夹,在我的情况下为 app/views/user_registrations
class UserRegistrationsController < 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.rolable = 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.rolable.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_with_scope :new }
end
end
end

这一切基本上是 Controller 根据 user_type确定必须创建的用户类型。传送到 Controller 的 create 的参数 View 中隐藏字段的方法,该方法通过 URL 中的简单 GET-param 使用参数。

例如:
如果你去 /users/sign_up?user[user_type]=designer你可以创建一个设计师。
如果你去 /users/sign_up?user[user_type]=customer您可以创建一个客户。
my_devise_error_messages!方法是一个辅助方法,它也处理关联模型中的验证错误,基于原始 devise_error_messages!方法
module ApplicationHelper
def my_devise_error_messages!
return "" if resource.errors.empty? && resource.rolable.errors.empty?

messages = rolable_messages = ""

if !resource.errors.empty?
messages = resource.errors.full_messages.map { |msg| content_tag(:li, msg) }.join
end

if !resource.rolable.errors.empty?
rolable_messages = resource.rolable.errors.full_messages.map { |msg| content_tag(:li, msg) }.join
end

messages = messages + rolable_messages
sentence = I18n.t("errors.messages.not_saved",
:count => resource.errors.count + resource.rolable.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

更新:

为了能够支持 /designer/sign_up 这样的路由和 /customer/sign_up您可以在路由文件中执行以下操作:
# routes.rb
match 'designer/sign_up' => 'user_registrations#new', :user => { :user_type => 'designer' }
match 'customer/sign_up' => 'user_registrations#new', :user => { :user_type => 'customer' }

内部路由语法中未使用的任何参数都将传递给 params 哈希。所以 :user被传递给 params 哈希。

就是这样了。在这里和那里稍微调整一下,我就让它以一种非常通用的方式工作,这很容易与许多其他用户模型共享一个公共(public)用户表进行扩展。

希望有人觉得它有用。

关于ruby-on-rails - 使用 Ruby On Rails 的多个用户模型,并设计有单独的注册路线,但只有一个共同的登录路线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7299618/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com