Zastąp kontroler rejestracji urządzenia


236

Dodałem pole do formularza rejestracji, które jest oparte na innym modelu, zobacz Jak używać zagnieżdżonych atrybutów w modelu opracowania dla szczegółów krwawych. Ta część działa dobrze.

Problem polega teraz na tym, że gdy zapisuję, to nie udaje się utworzyć akcji kontrolera rejestracji, który jest dostarczany przez devise z Activerecord::UnknownAttributeErrorna tym polu (firma).

Zakładam, że muszę zastąpić kontroler rejestracji, czy jest lepszy / łatwiejszy sposób, w jaki powinienem do tego podejść?


1
Właściwie napisałem cały post na blogu o tym jacopretorius.net/2014/03/…
Jaco Pretorius

Odpowiedzi:


354

Czy w swojej formie przekazujesz jakieś inne atrybuty, poprzez przypisanie masy, które nie należą do twojego modelu użytkownika lub któregokolwiek z zagnieżdżonych modeli?

Jeśli tak, uważam, że w tym przypadku wyzwalany jest ActiveRecord :: UnknownAttributeError.

W przeciwnym razie myślę, że możesz po prostu stworzyć własny kontroler, generując coś takiego:

# 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 

A następnie powiedz devise, aby używał tego kontrolera zamiast domyślnego z:

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

3
Ale w jaki sposób upewniasz się, że urządzenie wygląda w opracowanym katalogu dla widoków? Próbuję tego, ale opracowuję metody takie jak „sign_in_and_redirect (nazwa_zasobu, zasób)” szukają szablonu w widokach.
AnApprentice

7
Jeśli chcesz dostosować swoje poglądy, musisz je najpierw wygenerować, a urządzenie sprawdzi folder widoków przed załadowaniem widoków z klejnotu. W Rails 3 jest: rails generate devise:viewsa w Rails 2 (tak myślę) to:script/generate devise:views
theTRON

2
powyższy hack nie działa z devise 1.0.8, która jest wersją dla szyn 2.
William Yeung

18
Jeśli zastąpisz kontroler Devise w ten sposób, upewnij się, że skopiowałeś wszystkie widoki z aplikacji / views / devise / registrations do app / views / rejestrations / (zmień na dowolny kontroler, który zastępujesz).
Jamie Cobbett

31
Alternatywnie można pozostawić swoje poglądy opracować gdzie one są i dodać paths.app.views << "app/views/devise"w twojej config/application.rb.
theTRON

66

Lepszy i bardziej zorganizowany sposób zastępowania kontrolerów i widoków Devise przy użyciu przestrzeni nazw:

Utwórz następujące foldery:

app/controllers/my_devise
app/views/my_devise

Umieść wszystkie kontrolery, które chcesz zastąpić, w app / controllers / my_devise i dodaj MyDeviseprzestrzeń nazw do nazw klas kontrolerów. Registrationsprzykład:

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

  ...

  def create
    # add custom create logic here
  end

  ...    

end 

Zmień odpowiednio swoje trasy:

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

Skopiuj wszystkie wymagane widoki app/views/my_devisez folderu Opracuj klejnot lub użyj rails generate devise:views, usuń widoki, których nie zastępujesz, i zmień nazwę devisefolderu my_devise.

W ten sposób uporządkujesz wszystko w dwóch folderach.


1
Jest to podobne do mojego podejścia, ale nie wiem, jaką niestandardową logikę zastosować w createmetodzie Devise's, którą nadpisałem. Mój zmodyfikowany przeze mnie kontroler rusztowania działa świetnie, ale jak sprawić, by działał z resourcebiznesem Devise ?
Kyle Carlson

@Vincent dziękuję - jeśli chcę zastąpić tylko jedną metodę, czy piszę tylko metodę, którą chcę zastąpić - i czy wszystko inne będzie działać normalnie? Twoja pomoc bardzo doceniona
BKSpurgeon

MyDevise::RegistrationsController < Devise::RegistrationsControllertworzy błąd zależności cyklicznej. czy robię coś źle?
ianrandmckenzie

34

Uważam, że istnieje lepsze rozwiązanie niż przepisanie RegistrationsController. Zrobiłem dokładnie to samo (po prostu mam Organizację zamiast Firmy).

Jeśli poprawnie ustawisz swoją formę zagnieżdżoną, na poziomie modelu i widoku, wszystko działa jak urok.

Model mojego użytkownika:

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

Model mojej organizacji:

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

Mój pogląd: „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
Przeniesienie logiki kompilacji z widoku do modelu byłoby czystsze, patrz stackoverflow.com/questions/3544265#3764837
meleyal

Wygenerowałem kontrolery i teraz uruchamiam tworzenie kontrolera, gdy użytkownik kliknie Zarejestruj się. Czy istnieje sposób (np. Zastąpienie / jakiś przykładowy kod), którego można użyć w programie Devise do zaszyfrowania hasła i wykonania kontroli hasła i innych pól? i zapisujesz go w bazie danych modeli?
HP

Jak można uzyskać dostęp do zmiennej lokalnej resourcew widoku zamiast zmiennej instancji klasy @resource?
Chloe,

12

Możesz generować widoki i kontrolery w celu opracowania dostosowań.

Posługiwać się

rails g devise:controllers users -c=registrations

i

rails g devise:views 

Skopiuje określone kontrolery i widoki z gem do twojej aplikacji.

Następnie powiedz routerowi, aby używał tego kontrolera:

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

11

Bardzo proste metody Wystarczy przejść do terminala i wpisać następujący typ

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

Następnie użyj niestandardowych widoków

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

teraz w pliku route.rb

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

Możesz także dodać inne kontrolery. Umożliwi to użycie kontrolerów w folderze użytkowników i widoków w folderze użytkowników.

Teraz możesz dostosować swoje widoki do swoich potrzeb i dodać swoją logikę do kontrolerów w folderze kontrolery / użytkownicy. Cieszyć się !

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.