Anular diseñar controlador de registros

236

He agregado un campo al formulario de registro que se basa en un modelo diferente, vea ¿Cómo uso los atributos anidados con el modelo de diseño para los detalles sangrientos? Esta parte está funcionando bien.

El problema ahora es que cuando guardo, está fallando en la acción de creación del controlador de registros que es provisto por un dispositivo Activerecord::UnknownAttributeErroren este campo (empresa).

Supongo que necesito anular el controlador de registros, ¿o hay una manera mejor / más fácil de abordar esto?

Craig McGuff
fuente
1
De hecho, escribí una publicación de blog completa en este jacopretorius.net/2014/03/…
Jaco Pretorius

Respuestas:

354

En su formulario, ¿está pasando otros atributos, a través de una asignación masiva que no pertenece a su modelo de usuario, o cualquiera de los modelos anidados?

Si es así, creo que ActiveRecord :: UnknownAttributeError se activa en esta instancia.

De lo contrario, creo que puedes crear tu propio controlador, generando algo como esto:

# 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 

Y luego dígale a idear que use ese controlador en lugar del predeterminado con:

# app/config/routes.rb
devise_for :users, :controllers => {:registrations => "registrations"}
theTRON
fuente
3
Pero, ¿cómo se asegura de que el dispositivo visualice en el directorio de dispositivos las vistas? Estoy intentando esto, pero ideo métodos como "sign_in_and_redirect (resource_name, resource)" que buscan en las vistas de la plantilla.
AnApprentice el
77
Si desea personalizar sus vistas de diseño, solo necesita generarlas primero y el dispositivo verificará su carpeta de vistas antes de cargar las vistas desde la gema. En Rails 3 es: rails generate devise:viewsy en Rails 2 (creo) es:script/generate devise:views
theTRON
2
el truco anterior no funciona con el dispositivo 1.0.8, que es la versión que funciona para los rieles 2.
William Yeung
18
Si anula un controlador Devise como este, asegúrese de copiar todas las vistas desde app / views / devise / registrations a app / views / registrations / (cambie el controlador que esté anulando).
Jamie Cobbett
31
Alternativamente, puede dejar sus vistas de diseño donde están y agregar paths.app.views << "app/views/devise"su config/application.rb.
theTRON
66

Una forma mejor y más organizada de anular la creación de controladores y vistas utilizando espacios de nombres:

Crea las siguientes carpetas:

app/controllers/my_devise
app/views/my_devise

Coloque todos los controladores que desea anular en app / controllers / my_devise y agregue MyDeviseespacio de nombres a los nombres de clase de controlador. Registrationsejemplo:

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

  ...

  def create
    # add custom create logic here
  end

  ...    

end 

Cambia tus rutas en consecuencia:

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

Copie todas las vistas requeridas app/views/my_devisede la carpeta de gemas Devise o use rails generate devise:views, elimine las vistas que no está anulando y cambie el nombre de la devisecarpeta my_devise.

De esta manera, tendrás todo perfectamente organizado en dos carpetas.

Vincent
fuente
1
Esto es similar al enfoque que estoy tomando, pero no sé qué lógica personalizada poner en el createmétodo de Devise que sobrescribí. Mi controlador creado por el andamio que modifiqué funciona muy bien, pero ¿cómo lo hace funcionar con el resourcenegocio de Devise ?
Kyle Carlson
@Vincent gracias, si quiero anular solo un método, ¿escribo solo el método que quiero anular, y todo lo demás funcionará normalmente? Su ayuda muy apreciada
BKSpurgeon
MyDevise::RegistrationsController < Devise::RegistrationsControllercrea un error de dependencia circular. ¿Estoy haciendo algo mal?
ianrandmckenzie
34

Creo que hay una mejor solución que reescribir el Controlador de Registros. Hice exactamente lo mismo (solo tengo Organización en lugar de Compañía).

Si configura correctamente su forma anidada, a nivel de modelo y vista, todo funciona de maravilla.

Mi modelo de usuario:

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

Mi modelo de organización:

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

Mi opinión: 'idear / registros / 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" %>
thb
fuente
3
Mover la lógica de compilación de la vista al modelo sería más limpio, consulte stackoverflow.com/questions/3544265#3764837
meleyal
Generé los dispositivos de diseño y ahora la acción de creación de controladores se activa cuando el usuario hace clic en Registrarse. ¿Hay alguna forma (como anular / algún código de ejemplo) que pueda usar Devise para cifrar la contraseña y hacer comprobaciones de la contraseña y otros campos? y guardarlo en la base de datos modelo?
HP
¿Cómo puede acceder a la variable local resourceen la vista en lugar de una variable de instancia de clase @resource?
Chloe
12

Puede generar vistas y controladores para diseñar la personalización.

Utilizar

rails g devise:controllers users -c=registrations

y

rails g devise:views 

Copiará controladores y vistas particulares de gem a su aplicación.

A continuación, dígale al enrutador que use este controlador:

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

Métodos muy simples Solo ve a la terminal y escribe el siguiente

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

Siguiente para usar vistas personalizadas

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

ahora en su archivo route.rb

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

También puede agregar otros controladores. Esto hará que se usen controladores en la carpeta de usuarios y vistas en la carpeta de usuarios.

Ahora puede personalizar sus vistas como desee y agregar su lógica a los controladores en la carpeta de controladores / usuarios. ¡A disfrutar!

Pradeep Sapkota
fuente