Ich benutze Rails 3.2 und entwickle 2.0 und bin ziemlich neu in Rails.
Bedarf
Ich möchte Folgendes erreichen:
- 2 oder mehr "Benutzer" -Modelle haben, z. Mitglied, Kunde, Admin
- Alle Modelle haben einige erforderliche Felder gemeinsam (z. B. E-Mail und Passwort).
- Jedes Modell kann einige eindeutige Felder haben (z. B. Firma nur für Kunden).
- Einige Felder können gemeinsam genutzt werden, haben jedoch nicht dieselbe Validierung (z. B. Name ist für den Kunden erforderlich, für Mitglied jedoch optional).
- Alle Felder müssen während des Registrierungsprozesses ausgefüllt werden, daher sind die Formulare unterschiedlich
- Das Anmeldeformular sollte eindeutig sein
Mögliche Lösungen
Ich habe ziemlich lange gegoogelt und StackOverflow durchsucht, aber mir scheint nichts richtig zu sein (ich bin ein Java-Typ, sorry :) und jetzt bin ich ziemlich verwirrt. Es wurden zwei Lösungen gefunden:
Einzelner Benutzer
Das ist die häufigste Antwort. Erstellen Sie einfach den Standardbenutzer und erstellen Sie Beziehungen zwischen Mitglied -> Benutzer und Kunde -> Benutzer. Mein Anliegen ist hier, wie ich einen individuellen Registrierungsprozess für jedes Modell erreichen kann. Ich habe verschiedene Dinge ausprobiert, aber alles endete als Chaos!
Benutzer mit mehreren Geräten
Dies löst den benutzerdefinierten Registrierungsprozess und scheint mir richtig zu sein, aber das eindeutige Anmeldeformular ist ein Blocker. Ich habe auf SO eine Antwort gefunden ( Devise - Login von zwei Modellen ), die vorschlägt, Devise :: Models :: Authenticatable.find_for_authentication (Bedingungen) zu überschreiben. Das scheint kompliziert (?) Und da ich neu in Schienen bin, würde ich gerne wissen, ob das funktionieren könnte?
Danke für deinen Rat!
quelle
config.scoped_views = true
?Ich bin in ähnlichen Schuhen wie Sie, nachdem ich alle möglichen Ansätze ausprobiert hatte, entschied ich mich für ein einzelnes Benutzermodell, das zu polymorphen Rollen gehören würde. Dies scheint der einfachste Weg zu sein, um eine einmalige Anmeldung zu erreichen.
Das Benutzermodell würde nur die Informationen enthalten, die für die Anmeldung spezifisch sind.
Das Rollenmodell würde für jede Rolle spezifische Felder sowie andere für die Rolle spezifische Zuordnungen speichern.
Neue Registrierungen würden für jeden Benutzertyp (Rollen) über einzelne Controller angepasst und dann verschachtelte Attribute für den Benutzer erstellt.
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
Routen - nur normales Zeug für das Mitgliedsmodell.
resources :members #maybe make a new path for New signups, but for now its new_member_path
Controller - Sie müssen build_user für verschachtelte Attribute erstellen
#controllers/members_controller.rb def new @member = Member.new @member.build_user end def create #... standard controller stuff end
Ansichten / Mitglieder / 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 %>
Ich möchte darauf hinweisen, dass es KEINE NOTWENDIGKEIT gibt, nach nested_form gem zu greifen. da die Anforderung ist, dass der Benutzer nur zu einem Rollentyp gehören kann.
quelle
has_one
im Benutzermodell undbelongs_to
im Mitgliedsmodell zu haben, damit Sie die polymorphe Beziehung vermeiden können . Gibt es einen Grund, warum Sie das Gegenteil getan haben?polymorphic
nur fürbelongs_to
. Es gibt andere Lösungen in Bezug auf "revers polymorph", die jedoch nicht in den Geltungsbereich fallen.Ich habe einen Weg gefunden und bin bisher ziemlich zufrieden damit. Ich werde es hier für andere beschreiben.
Ich ging mit der einzelnen "Benutzer" -Klasse. Mein Problem war es, für jedes Pseudomodell einen individuellen Registrierungsprozess zu erreichen.
model / 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
Dann habe ich http://railscasts.com/episodes/217-multistep-forms und http://pastie.org/1084054 so angepasst , dass zwei Registrierungspfade mit einem überschriebenen Controller vorhanden sind:
config / route.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'
controller / users / registrations_controller.rb:
Ich habe eine Assistentenklasse erstellt, die die Felder kennt, die bei jedem Schritt überprüft werden müssen
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
und meine Ansichten sind:
new.rb
new_client.rb
einschließlich eines Teils gemäß dem Assistentenschritt:_new_client_1.rb
_new_client_2.rb
new_member.rb
einschließlich eines Teils gemäß dem Assistentenschritt:_new_member_1.rb
_new_member_2.rb
quelle
Also, was ist falsch? Einfach ausführen
rails g devise:views [model_name]
, jedes Registrierungsformular anpassen undconfig/initializer/devise.rb
einfach eingebenconfig.scoped_views = true
.quelle
scoped_views
Option aktiviertconfig/initializers/devise.rb
? Es ist standardmäßig deaktiviert, um die Leistung zu verbessern.