239 votes

Remplacer le contrôleur d'enregistrement des appareils

J'ai ajouté un champ au formulaire d'inscription qui est basé sur un modèle différent, cf. Comment utiliser des attributs imbriqués avec le modèle devise ? pour les détails sanglants. Cette partie fonctionne bien.

Le problème est que lorsque j'enregistre, cela échoue dans l'action de création du contrôleur d'enregistrements qui est fourni par devise avec un Activerecord::UnknownAttributeError sur ce champ (entreprise).

Je suppose que je dois remplacer le contrôleur des enregistrements, ou y a-t-il une meilleure façon de procéder ?

1 votes

En fait, j'ai écrit un article entier sur ce sujet jacopretorius.net/2014/03/

361voto

theTRON Points 6421

Dans votre formulaire, transmettez-vous d'autres attributs, via l'affectation de masse, qui n'appartiennent pas à votre modèle utilisateur ou à l'un des modèles imbriqués ?

Si c'est le cas, je pense que l'erreur ActiveRecord::UnknownAttributeError est déclenchée dans ce cas.

Sinon, je pense que vous pouvez simplement créer votre propre contrôleur, en générant quelque chose comme ceci :

# app/controllers/registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
  def new
    super
  end

  def create
    # add custom create logic here
  end

  def update
    super
  end
end 

Puis dites à devise d'utiliser ce contrôleur au lieu du contrôleur par défaut :

# app/config/routes.rb
devise_for :users, :controllers => {:registrations => "registrations"}

3 votes

Mais comment s'assurer que devise recherche les vues dans le répertoire devise ? J'essaie de le faire mais les méthodes devise comme "sign_in_and_redirect(resource_name, resource)" cherchent le modèle dans les vues.

7 votes

Si vous souhaitez personnaliser vos vues devise, il vous suffit de les générer d'abord et devise vérifiera votre dossier de vues avant de charger les vues de la gemme. Dans Rails 3, c'est : rails generate devise:views et dans Rails 2 (je pense) c'est : script/generate devise:views

2 votes

Le hack ci-dessus ne fonctionne pas avec devise 1.0.8 qui est la version qui fonctionne pour rails 2.

67voto

Vincent Points 5364

Un moyen plus efficace et plus organisé de remplacer les contrôleurs et les vues Devise en utilisant les espaces de noms :

Créez les dossiers suivants :

app/controllers/my_devise
app/views/my_devise

Placez tous les contrôleurs que vous voulez remplacer dans app/controllers/my_devise et ajoutez-y les éléments suivants MyDevise aux noms des classes du contrôleur. Registrations exemple :

# app/controllers/my_devise/registrations_controller.rb
class MyDevise::RegistrationsController < Devise::RegistrationsController

  ...

  def create
    # add custom create logic here
  end

  ...    

end 

Modifiez vos itinéraires en conséquence :

devise_for :users,
           :controllers  => {
             :registrations => 'my_devise/registrations',
             # ...
           }

Copiez toutes les vues requises dans app/views/my_devise à partir du dossier Devise gem ou utiliser rails generate devise:views supprimez les vues que vous ne remplacez pas et renommez-les en devise vers le dossier my_devise .

De cette façon, vous aurez tout bien organisé dans deux dossiers.

1 votes

C'est une approche similaire à celle que j'adopte, mais je ne sais pas quelle logique personnalisée mettre en place dans le fichier create méthode de Devise que j'ai réécrite. Le contrôleur créé par l'échafaudage que j'ai modifié fonctionne très bien, mais comment le faire fonctionner avec la méthode de Devise resource des affaires ?

0 votes

@Vincent merci - si je veux remplacer une seule méthode, dois-je écrire seulement la méthode que je veux remplacer - et tout le reste fonctionnera-t-il normalement ? Votre aide est très appréciée

0 votes

MyDevise::RegistrationsController < Devise::RegistrationsController crée une erreur de dépendance circulaire. Est-ce que je fais quelque chose de mal ?

35voto

thb Points 241

Je pense qu'il existe une meilleure solution que de réécrire le RegistrationsController. J'ai fait exactement la même chose (j'ai juste l'Organisation au lieu de la Société).

Si vous configurez correctement votre formulaire imbriqué, au niveau du modèle et de la vue, tout fonctionne comme sur des roulettes.

Mon modèle d'utilisateur :

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :token_authenticatable, :confirmable, :lockable and :timeoutable
  devise :database_authenticatable, :registerable,
     :recoverable, :rememberable, :trackable, :validatable

  has_many :owned_organizations, :class_name => 'Organization', :foreign_key => :owner_id

  has_many :organization_memberships
  has_many :organizations, :through => :organization_memberships

  # Setup accessible (or protected) attributes for your model
  attr_accessible :email, :password, :password_confirmation, :remember_me, :name, :username, :owned_organizations_attributes

  accepts_nested_attributes_for :owned_organizations
  ...
end

Mon modèle d'organisation :

class Organization < ActiveRecord::Base
  belongs_to :owner, :class_name => 'User'
  has_many :organization_memberships
  has_many :users, :through => :organization_memberships
  has_many :contracts

  attr_accessor :plan_name

  after_create :set_owner_membership, :set_contract
  ...
end

Ma vue : 'devise/registrations/new.html.erb'.

<h2>Sign up</h2>

<% resource.owned_organizations.build if resource.owned_organizations.empty? %>
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
  <%= devise_error_messages! %>

  <p><%= f.label :name %><br />
    <%= f.text_field :name %></p>

  <p><%= f.label :email %><br />
    <%= f.text_field :email %></p>

  <p><%= f.label :username %><br />
    <%= f.text_field :username %></p>

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

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

  <%= f.fields_for :owned_organizations do |organization_form| %>

    <p><%= organization_form.label :name %><br />
      <%= organization_form.text_field :name %></p>

    <p><%= organization_form.label :subdomain %><br />
      <%= organization_form.text_field :subdomain %></p>

    <%= organization_form.hidden_field :plan_name, :value => params[:plan] %>

  <% end %>

  <p><%= f.submit "Sign up" %></p>
<% end %>

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

3 votes

Déplacer la logique de construction de la vue vers le modèle serait plus propre, cf. stackoverflow.com/questions/3544265#3764837

0 votes

J'ai généré les contrôleurs devise et j'ai maintenant un contrôleur qui crée une action déclenchée lorsque l'utilisateur clique sur S'inscrire. Existe-t-il un moyen (comme une surcharge / un exemple de code) d'utiliser Devise pour crypter le mot de passe et effectuer des vérifications en arrière-plan du mot de passe et d'autres champs ? et les enregistrer dans la base de données du modèle ?

0 votes

Comment pouvez-vous accéder à la variable locale resource dans la vue au lieu d'une variable d'instance de classe @resource ?

14voto

user1201917 Points 771

Vous pouvez générer des vues et des contrôleurs pour la personnalisation de la devise.

Utilisez

rails g devise:controllers users -c=registrations

et

rails g devise:views 

Il copiera des contrôleurs et des vues particuliers de gem à votre application.

Ensuite, indiquez au routeur d'utiliser ce contrôleur :

devise_for :users, :controllers => {:registrations => "users/registrations"}

14voto

pradeep sapkota Points 20

Des méthodes très simples Il suffit d'aller dans le terminal et de taper ce qui suit

rails g devise:controllers users //This will create devise controllers in controllers/users folder

Ensuite, utiliser des vues personnalisées

rails g devise:views users //This will create devise views in views/users folder

maintenant dans votre fichier route.rb

devise_for :users, controllers: {
           :sessions => "users/sessions",
           :registrations => "users/registrations" }

Vous pouvez également ajouter d'autres contrôleurs. Cela permettra à Devise d'utiliser les contrôleurs dans le dossier des utilisateurs et les vues dans le dossier des utilisateurs.

Maintenant vous pouvez personnaliser vos vues comme vous le souhaitez et ajouter votre logique aux contrôleurs dans le dossier controllers/users. Bonne lecture !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X