Sostituisci ideare il controller delle registrazioni


236

Ho aggiunto un campo al modulo di iscrizione basato su un modello diverso, vedi Come utilizzare gli attributi nidificati con il modello di idea per i dettagli gory. Questa parte funziona bene.

Il problema ora è quando salvo, non riesce nell'azione di creazione del controller delle registrazioni che viene fornita da escogitare un Activerecord::UnknownAttributeErrorsu questo campo (azienda).

Suppongo di dover scavalcare il controller delle registrazioni o esiste un modo migliore / più semplice per avvicinarmi a questo?


1
In realtà ho scritto un intero post sul blog su questo jacopretorius.net/2014/03/…
Jaco Pretorius

Risposte:


354

Nel tuo modulo stai passando altri attributi, tramite assegnazione di massa che non appartiene al tuo modello utente o uno dei modelli nidificati?

In tal caso, credo che ActiveRecord :: UnknownAttributeError sia attivato in questa istanza.

Altrimenti, penso che puoi semplicemente creare il tuo controller, generando qualcosa del genere:

# 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 

E quindi dire a escogitare di utilizzare quel controller invece del valore predefinito con:

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

3
Ma come ti assicuri che escogiti i look nella directory escogita per le viste? Sto provando questo, ma escogitare metodi come "sign_in_and_redirect (nome_ risorsa, risorsa)" stanno cercando nelle viste per il modello.
AnApprentice,

7
Se vuoi personalizzare le tue viste idea, devi solo generarle prima e escogitare controllerà la cartella delle viste prima di caricare le viste dalla gemma. In Rails 3 è: rails generate devise:viewse in Rails 2 (penso) è:script/generate devise:views
theTRON

2
l'hack sopra non funziona con devise 1.0.8 che è la versione funziona per rotaie 2.
William Yeung,

18
Se esegui l'override di un controller Devise in questo modo, assicurati di copiare tutte le visualizzazioni da app / visualizzazioni / idea / registrazioni in app / visualizzazioni / registrazioni / (modifica per qualsiasi controller che stai ignorando).
Jamie Cobbett,

31
In alternativa è possibile lasciare le vostre opinioni testamentaria dove sono e aggiungere paths.app.views << "app/views/devise"nella vostra config/application.rb.
theTRON

66

Un modo migliore e più organizzato di ignorare i controller e le viste Devise usando gli spazi dei nomi:

Creare le seguenti cartelle:

app/controllers/my_devise
app/views/my_devise

Inserisci tutti i controller che desideri sovrascrivere in app / controller / my_devise e aggiungi lo MyDevisespazio dei nomi ai nomi delle classi dei controller. Registrationsesempio:

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

  ...

  def create
    # add custom create logic here
  end

  ...    

end 

Modifica i tuoi percorsi di conseguenza:

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

Copia tutte le viste richieste app/views/my_devisedalla cartella gemma di Devise o usa rails generate devise:views, elimina le viste che non stai sostituendo e rinomina la devisecartella my_devise.

In questo modo avrai tutto organizzato in modo ordinato in due cartelle.


1
Questo è simile all'approccio che sto adottando, ma non so quale logica personalizzata mettere nel createmetodo di Devise abbia sovrascritto. Il mio controller creato da scaffold che ho modificato funziona alla grande, ma come si fa a farlo funzionare con Devise resource?
Kyle Carlson,

@Vincent grazie - se voglio scavalcare solo un metodo, scrivo solo il metodo che voglio scavalcare - e tutto il resto funzionerà normalmente? La tua assistenza è stata molto apprezzata
BKSpurgeon,

MyDevise::RegistrationsController < Devise::RegistrationsControllercrea un errore di dipendenza circolare. Sto facendo qualcosa di sbagliato?
ianrandmckenzie,

34

Credo che ci sia una soluzione migliore che riscrivere il RegistrationsController. Ho fatto esattamente la stessa cosa (ho solo Organizzazione anziché Azienda).

Se imposti correttamente la tua forma nidificata, a livello di modello e di vista, tutto funziona come un fascino.

Il mio modello utente:

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

Il mio modello di organizzazione:

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

Il mio punto di vista: "escogitare / registrazioni / 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
Spostare la logica di compilazione dalla vista al modello sarebbe più pulito, vedi stackoverflow.com/questions/3544265#3764837
meleyal

Ho generato i controller ideati e ora ho attivato l'azione del controller quando l'utente fa clic su Iscriviti. C'è un modo (come l'override / qualche codice di esempio) che posso usare Devise per crittografare la password e fare controlli backend della password e di altri campi? e salvarlo nel database del modello?
HP,

Come puoi accedere alla variabile locale resourcenella vista anziché a una variabile di istanza di classe @resource?
Chloe,

12

È possibile generare viste e controller per ideare la personalizzazione.

Uso

rails g devise:controllers users -c=registrations

e

rails g devise:views 

Copierà particolari controller e viste dalla gemma alla tua applicazione.

Quindi, dire al router di utilizzare questo controller:

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

11

Metodi molto semplici Basta andare al terminale e digitare il seguente

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

Avanti per utilizzare le visualizzazioni personalizzate

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

ora nel tuo file route.rb

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

Puoi aggiungere anche altri controller. Questo farà escogitare l'uso dei controller nella cartella degli utenti e le visualizzazioni nella cartella degli utenti.

Ora puoi personalizzare le tue visualizzazioni come desideri e aggiungere la tua logica ai controller nella cartella controller / utenti. Godere !

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.