我正在使用rails 3.2并设计2.0,而且我对Rails很新。
我想实现以下目标:
我用Google搜索并搜索了StackOverflow很长一段时间,但对我来说似乎没什么问题(我是一个Java人,对不起:)现在我很困惑。出现了两个解决方案:
这是最常见的答案。只需创建默认设备用户并在会员 - >用户和客户 - >用户之间创建关系。 我关注的是如何为每个模型实现自定义注册流程?我尝试了不同的东西,但一切都结束了!
这解决了自定义注册过程,对我来说似乎是对的,但唯一的登录表单是一个阻止程序。我在SO(Devise - login from two model)上找到了一个答案,建议重写Devise :: Models :: Authenticatable.find_for_authentication(conditions)。 这似乎很复杂(?),因为我刚开始使用rails,我想知道这是否可行?
感谢您的建议!
答案 0 :(得分:66)
欢迎加入Java家伙=),我希望你会喜欢Rails世界。 简单地说,要解决您的问题,您有两个解决方案:
选择哪一个? 它取决于角色的共同属性。如果它们几乎是常见的(例如,所有都有名称,电子邮件,移动设备......)并且一些属性不同,我强烈推荐STI解决方案。
如何做STI?
1.使用命令rails generate devise User
创建设计用户模型和表
2.使用迁移将名为type
的字符串数据类型的列添加到数据库中的用户表。
3.为每个用户类型创建一个模型(例如rails g model admin
)
4.使Admin类继承自用户模型
class Admin < User
end
就是你做完了=)...... Yupeee
要创建管理员,请运行命令Admin.create(...)
,其中点是管理员属性,例如电子邮件,名称,...
我认为这question也可以帮到你
答案 1 :(得分:26)
我和你一样穿着类似的鞋子,在尝试了各种方法后,我选择了一个属于多态角色的用户模型。这似乎是实现单一登录的最简单方法。
用户模型将包含特定于登录的信息。
角色模型将存储特定于每个角色的字段,以及特定于该角色的其他关联。
将通过各个控制器为每个用户类型(角色)自定义新注册,然后为用户构建嵌套属性。
class User < ActiveRecord::Base
#... devise code ...
belongs_to :role, :polymorphic => true
end
class Member < ActiveRecord::Base
attr_accessible :name, :tel, :city #etc etc....
attr_accessible :user_attributes #this is needed for nested attributes assignment
#model specific associations like
has_many :resumes
has_one :user, :as => :role, dependent: :destroy
accepts_nested_attributes_for :user
end
路线 - 只是会员模型的常规内容。
resources :members
#maybe make a new path for New signups, but for now its new_member_path
控制器 - 您必须为嵌套属性构建build_user
#controllers/members_controller.rb
def new
@member = Member.new
@member.build_user
end
def create
#... standard controller stuff
end
视图/构件/ new.html.erb
<h2>Sign up for new members!</h2>
<%= simple_form_for @member do |f| %>
# user fields
<%= f.fields_for :user do |u| %>
<%= u.input :email, :required => true, :autofocus => true %>
<%= u.input :password, :required => true %>
<%= u.input :password_confirmation, :required => true %>
<% end %>
# member fields
<%= f.input :name %>
<%= f.input :tel %>
<%= f.input :city %>
<%= f.button :submit, "Sign up" %>
<% end %>
我想指出,没有必要达到nested_form gem;因为要求是用户只能属于一种类型的角色。
答案 2 :(得分:18)
我找到了一条路可走,到目前为止我对此非常满意。我会在这里为其他人描述。
我选择了单个“用户”类。我的问题是为每个伪模型实现自定义注册过程。
<强>模型/ user.rb:强>
class User < ActiveRecord::Base
devise :confirmable,
:database_authenticatable,
:lockable,
:recoverable,
:registerable,
:rememberable,
:timeoutable,
:trackable,
:validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me, :role
as_enum :role, [:administrator, :client, :member]
validates_as_enum :role
## Rails 4+ for the above two lines
# enum role: [:administrator, :client, :member]
end
然后我调整http://railscasts.com/episodes/217-multistep-forms和http://pastie.org/1084054以使两个注册路径具有被覆盖的控制器:
<强>配置/ routes.rb中:强>
get 'users/sign_up' => 'users/registrations#new', :as => 'new_user_registration'
get 'clients/sign_up' => 'users/registrations#new_client', :as => 'new_client_registration'
post 'clients/sign_up' => 'users/registrations#create', :as => 'client_registration'
get 'members/sign_up' => 'users/registrations#new_member', :as => 'new_member_registration'
post 'members/sign_up' => 'users/registrations#create', :as => 'member_registration'
<强>控制器/用户/ registrations_controller.rb:强>
我创建了一个向导类,它知道要在每个步骤验证的字段
class Users::RegistrationsController < Devise::RegistrationsController
# GET /resource/sign_up
def new
session[:user] ||= { }
@user = build_resource(session[:user])
@wizard = ClientRegistrationWizard.new(current_step)
respond_with @user
end
# GET /clients/sign_up
def new_client
session[:user] ||= { }
session[:user]['role'] = :client
@user = build_resource(session[:user])
@wizard = ClientRegistrationWizard.new(current_step)
render 'new_client'
end
# GET /members/sign_up
def new_member
# same
end
# POST /clients/sign_up
# POST /members/sign_up
def create
session[:user].deep_merge!(params[:user]) if params[:user]
@user = build_resource(session[:user])
@wizard = ClientRegistrationWizard.new(current_step)
if params[:previous_button]
@wizard.previous
elsif @user.valid?(@wizard)
if @wizard.last_step?
@user.save if @user.valid?
else
@wizard.next
end
end
session[:registration_current_step] = @wizard.current_step
if @user.new_record?
clean_up_passwords @user
render 'new_client'
else
#session[:registration_current_step] = nil
session[:user_params] = nil
if @user.active_for_authentication?
set_flash_message :notice, :signed_up if is_navigational_format?
sign_in(:user, @user)
respond_with @user, :location => after_sign_up_path_for(@user)
else
set_flash_message :notice, :"signed_up_but_#{@user.inactive_message}" if is_navigational_format?
expire_session_data_after_sign_in!
respond_with @user, :location => after_inactive_sign_up_path_for(@user)
end
end
end
private
def current_step
if params[:wizard] && params[:wizard][:current_step]
return params[:wizard][:current_step]
end
return session[:registration_current_step]
end
end
我的观点是:
new.rb
new_client.rb
根据向导步骤包含部分:
_new_client_1.rb
_new_client_2.rb
new_member.rb
根据向导步骤包含部分:
_new_member_1.rb
_new_member_2.rb
答案 3 :(得分:6)
那有什么不对?只需运行rails g devise:views [model_name]
,自定义每个注册表单,然后在config/initializer/devise.rb
中添加config.scoped_views = true
。