わかりましたが、私はそれを通じ働いて、次のソリューションに来ました。
私はちょっと気を遣う必要がありましたが、それほど複雑ではありません。
Userモデル
# 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
ので、Userモデルは、単純なポリモーフィックな関連を持っている、それが顧客の場合は定義したり、デザイナー。
私がしなければならなかったことは、rails g devise:views
と私のアプリケーションの一部であるdeviseビューを生成することでした。私は登録をカスタマイズする必要があったので、私はapp/views/devise/registrations
フォルダのみを残して残りを削除しました。
次に、新しい登録の登録ビューをカスタマイズしました。これは、登録後に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_fields.html
<div><%= f.label :label_name %><br />
<%= f.text_field :label_name %></div>
はその後、私のセットアップの登録
devise_for :users, :controllers => { :registrations => 'UserRegistrations' }
上のカスタムコントローラを使用するための工夫のためのルートは、それから私は、元のソースコードをコピーし、カスタマイズされた登録プロセスを処理するためのコントローラを生成しましたDevise::RegistrationsController
のcreate
メソッドから、私の場合には適切なフォルダにビューファイルを移動することを忘れないでください。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
これは基本的にコントローラが、コントローラのcreate
メソッドに渡されたuser_type
パラメータに従って作成する必要のあるユーザタイプを、単純なGETパラメータでパラメータを使用するビューの非表示フィールドで決定することですURL。
例:
/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
UPDATEに基づいて、また連想モデルで検証エラーを処理するヘルパーメソッドである:
/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ハッシュに渡されます。
だから...それです。ちょっとピンキーで、私はこれをかなり一般的な方法で動作させました。これは、共通のUserテーブルを共有する他の多くのUserモデルでは容易に拡張できます。
誰かが役に立つと願っています。
提案がありますか? – Vapire