Substituir o controlador de registros de dispositivos

236

Adicionei um campo ao formulário de inscrição com base em um modelo diferente. Consulte Como usar atributos aninhados com o modelo de criação para obter detalhes sangrentos. Esta parte está funcionando bem.

O problema agora é que, quando eu salvo, ele está falhando na ação de criação do controlador de registros que é fornecida pelo fabricante com um Activerecord::UnknownAttributeErrorcampo (empresa) nesse campo.

Estou assumindo que preciso substituir o controlador de registros ou existe uma maneira melhor / mais fácil de abordar isso?

Craig McGuff
fonte
1
Na verdade, eu escrevi um post inteiro no blog sobre este jacopretorius.net/2014/03/…
Jaco Pretorius

Respostas:

354

No seu formulário, você está passando outros atributos, através de atribuição em massa que não pertence ao seu modelo de usuário ou a nenhum dos modelos aninhados?

Nesse caso, acredito que o ActiveRecord :: UnknownAttributeError é acionado nesta instância.

Caso contrário, acho que você pode criar seu próprio controlador, gerando algo como isto:

# 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 diga ao dispositivo para usar esse controlador em vez do padrão com:

# app/config/routes.rb
devise_for :users, :controllers => {:registrations => "registrations"}
theTRON
fonte
3
Mas como você se certifica de que o visualizador de aparências esteja no diretório do visualizador para as visualizações? Eu estou tentando isso, mas invente métodos como "sign_in_and_redirect (resource_name, resource)" estão procurando visualizações para o modelo.
AnApprentice
7
Se você deseja personalizar suas visualizações de dispositivos, basta gerá-las primeiro e o dispositivo verificará sua pasta de visualizações antes de carregar as visualizações da gema. No Rails 3 é: rails generate devise:viewse no Rails 2 (eu acho) é:script/generate devise:views
theTRON
2
o hack acima não funciona com o legado 1.0.8 que é as obras de versão para rails 2.
William Yeung
18
Se você substituir um controlador Devise como este, certifique-se de copiar todas as visualizações de app / views / devise / registrations para app / views / registrations / (altere para o controlador que você estiver substituindo).
precisa
31
Como alternativa, você pode deixar suas visualizações de dispositivos onde elas estão e adicionar paths.app.views << "app/views/devise"suas config/application.rb.
theTRON 21/03
66

Uma maneira melhor e mais organizada de substituir os controladores e visualizações do Devise usando espaços de nome:

Crie as seguintes pastas:

app/controllers/my_devise
app/views/my_devise

Coloque todos os controladores que você deseja substituir em app / controllers / my_devise e adicione MyDeviseespaço para nome aos nomes de classe do controlador. Registrationsexemplo:

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

  ...

  def create
    # add custom create logic here
  end

  ...    

end 

Mude suas rotas de acordo:

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

Copie todas as visualizações necessárias app/views/my_deviseda pasta Devise gem ou use rails generate devise:views, exclua as visualizações para as quais você não está substituindo e renomeie a devisepasta my_devise.

Dessa forma, você terá tudo bem organizado em duas pastas.

Vincent
fonte
1
Isso é semelhante à abordagem que estou adotando, mas não sei qual lógica personalizada colocar no createmétodo de substituição de Devise. Meu controlador criado por andaime que eu modifiquei funciona muito bem, mas como você faz isso funcionar com os resourcenegócios da Devise ?
Kyle Carlson #
@ Vincent obrigado - se eu quiser substituir apenas um método, escrevo apenas o método que quero substituir - e tudo o resto funcionará normalmente? Sua ajuda muito apreciada
BKSpurgeon
MyDevise::RegistrationsController < Devise::RegistrationsControllercria um erro de dependência circular. Estou fazendo algo errado?
Ianrandmckenzie
34

Acredito que exista uma solução melhor do que reescrever o RegistrationsController. Fiz exatamente a mesma coisa (apenas tenho organização em vez de empresa).

Se você definir corretamente seu formulário aninhado, no nível de modelo e exibição, tudo funcionará como um encanto.

Meu modelo de usuário:

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

Meu modelo de organização:

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

Minha opinião: '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" %>
thb
fonte
3
Mover a lógica de construção da visualização para o modelo seria mais limpo, consulte stackoverflow.com/questions/3544265#3764837 #
meleyal
Gerei os controladores de dispositivos e agora a criação da ação do controlador é acionada quando o usuário clica em Inscrever-se. Existe uma maneira (como substituir / algum código de exemplo) que eu possa usar o Devise para criptografar a senha e fazer verificações de back-end da senha e de outros campos? e salvá-lo no banco de dados do modelo?
HP
Como você pode acessar a variável local resourcena exibição em vez de uma variável de instância de classe @resource?
Chloe
12

Você pode gerar visualizações e controladores para personalizar a criação.

Usar

rails g devise:controllers users -c=registrations

e

rails g devise:views 

Ele copiará controladores e visualizações específicos do gem para o seu aplicativo.

Em seguida, diga ao roteador para usar este controlador:

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

Métodos muito simples Vá ao terminal e digite o seguinte

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

Avançar para usar visualizações personalizadas

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

agora no seu arquivo route.rb

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

Você pode adicionar outros controladores também. Isso fará com que o dispositivo use controladores na pasta de usuários e visualizações na pasta de usuários.

Agora você pode personalizar suas visualizações como desejar e adicionar sua lógica aos controladores na pasta controladores / usuários. Aproveitar !

Pradeep Sapkota
fonte