concevoir et plusieurs modèles «utilisateur»

J’utilise les rails 3.2 et 2.0 et je suis assez nouveau sur Rails.

Exigences

J’aimerais réaliser ce qui suit:

  • avoir 2 modèles “utilisateurs” ou plus, par ex. Membre, Client, Admin
  • tous les modèles partagent certains champs obligatoires (par exemple, email et mot de passe)
  • chaque modèle peut avoir des champs uniques (ex. entreprise pour client uniquement)
  • certains champs peuvent être partagés mais ne pas avoir la même validation (par exemple, le nom est requirejs pour le client mais facultatif pour le membre)
  • tous les champs doivent être remplis pendant le processus d’inscription, les formulaires sont donc différents
  • le formulaire de connexion doit être unique

Solutions possibles

J’ai cherché Google et cherché StackOverflow pendant un long moment, mais rien ne me semblait juste (je suis un gars de Java, désolé 🙂 et maintenant je suis plutôt confus. Deux solutions sont apparues:

Utilisateur unique

C’est la réponse la plus fréquente. Créez simplement l’utilisateur par défaut et créez des relations entre Membre -> Utilisateur et Client -> Utilisateur. Ma préoccupation ici est de savoir comment réaliser un processus d’enregistrement personnalisé pour chaque modèle. J’ai essayé différentes choses mais tout s’est terminé en désordre!

Utilisateurs multiples

Cela résout le processus d’enregistrement personnalisé et me semble correct, mais le formulaire de connexion unique est un bloqueur. J’ai trouvé une réponse sur SO ( Devise – login from two model ) qui suggère de remplacer Devise :: Models :: Authenticatable.find_for_authentication (conditions). Cela semble compliqué (?) Et comme je suis nouveau sur les rails, j’aimerais savoir si cela pourrait fonctionner?

Merci pour vos conseils!

Bienvenue à bord de Java guy =), j’espère que vous apprécierez le monde Rails. Simplement, pour résoudre votre problème, vous avez 2 solutions:

  1. Pour chaque utilisateur, créez une table dans la firebase database et le modèle correspondant.
  2. Créez une seule table dans la firebase database et créez un modèle pour chaque type d’utilisateur. Cela s’appelle l’inheritance de table unique (STI).

Lequel choisir? Cela dépend des atsortingbuts communs des rôles. Si elles sont presque communes (par exemple, toutes ont un nom, un email, un mobile,…) et que quelques atsortingbuts sont différents, je recommande fortement la solution STI.

Comment faire l’IST? 1. Créez simplement le modèle d’utilisateur et le tableau du dispositif en utilisant les rails generate devise User commande rails generate devise User 2. Ajoutez une colonne nommée avec le type de données de chaîne à la table d’utilisateurs de la firebase database en utilisant une migration. 3. Pour chaque type d’utilisateur, créez un modèle (par exemple, rails g model admin ). 4. Faites en sorte que la classe Admin hérite du modèle utilisateur.

 class Admin < User end 

Ca y est c'est fini =) ... Yupeee

Pour créer un admin, exécutez la commande Admin.create(...) où les points sont les atsortingbuts admin, par exemple le courrier électronique, le nom, ...

Je pense que cette question pourrait vous aider aussi

Je suis dans la même situation que vous, après avoir essayé toutes sortes d’approches avec un seul modèle d’utilisateur, qui appartiendrait à des rôles polymorphes. Cela semble être le moyen le plus simple de réaliser une connexion unique.

Le modèle d’utilisateur contiendrait les informations spécifiques à la connexion uniquement.

Le modèle de rôle stockerait des champs spécifiques à chaque rôle, ainsi que d’autres associations spécifiques au rôle.

Les nouveaux enregistrements seraient personnalisés pour chaque type d’utilisateur (rôles) via des contrôleurs individuels, puis en créant des atsortingbuts nesteds pour l’utilisateur.

 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_atsortingbutes_for :user end 

Routes – juste des trucs réguliers pour le modèle Member.

 resources :members #maybe make a new path for New signups, but for now its new_member_path 

Controller – vous devez build_user pour les atsortingbuts nesteds

 #controllers/members_controller.rb def new @member = Member.new @member.build_user end def create #... standard controller stuff end 

views / members / new.html.erb

 

Sign up for new members!

<%= 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 %>

Je tiens à souligner qu’il n’y a pas besoin d’atteindre pour gemme nested_form; comme l’exigence est que l’utilisateur ne peut appartenir qu’à un type de rôle.

J’ai trouvé le chemin à parcourir et j’en suis assez content. Je vais le décrire ici pour les autres.

Je suis allé avec la seule classe “utilisateur”. Mon problème était de réaliser un processus d’enregistrement personnalisé pour chaque pseudo-modèle.

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 

Ensuite, j'ai adapté http://railscasts.com/episodes/217-multistep-forms et http://pastie.org/1084054 pour avoir deux chemins d'enregistrement avec un contrôleur surchargé:

config / 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' 

les contrôleurs / utilisateurs / registrations_controller.rb:

J'ai créé une classe d'assistant qui connaît les champs à valider à chaque étape

 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 

et mes vues sont:

  • new.rb
  • new_client.rb incluant un partiel en fonction de l'étape de l'assistant:
    • _new_client_1.rb
    • _new_client_2.rb
  • new_member.rb incluant un partiel en fonction de l'étape de l'assistant:
    • _new_member_1.rb
    • _new_member_2.rb

Alors, qu’est-ce qui ne va pas? rails g devise:views [model_name] simplement rails g devise:views [model_name] , personnalisez chaque formulaire d’inscription et dans config/initializer/devise.rb mettez simplement config.scoped_views = true .