2010-08-23 3 views
215

Я добавил поле в форму регистрации, основанную на другой модели, см. How do I use nested attributes with the devise model для деталей gory. Эта часть работает нормально.Переопределить контроллер регистрации регистрации

Проблема теперь, когда я сохраняю, она не работает в создании действия контроллера регистрации, который поставляется с помощью Activerecord::UnknownAttributeError в этом поле (компании).

Я предполагаю, что мне нужно переопределить контроллер регистрации, или есть лучший/более простой способ, которым я должен приблизиться к этому?

ответ

331

В вашей форме вы передаете другие атрибуты, используя массовое распределение, не принадлежащее вашей пользовательской модели, или любую из вложенных моделей?

Если это так, я считаю, что ActiveRecord :: UnknownAttributeError запускается в этом экземпляре.

В противном случае, я думаю, вы можете просто создать свой собственный контроллер, генерируя что-то вроде этого:

# 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 

а затем сказать изобрести, чтобы использовать этот контроллер вместо значения по умолчанию с:

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

Но как вы убеждаетесь, что придумайте, как выглядит дизайн в представлении для просмотров? Я пытаюсь это, но придумываю методы, такие как «sign_in_and_redirect (resource_name, resource)», которые смотрят в представлениях для шаблона. – AnApprentice

+7

Если вы хотите настроить свои разработки, вам просто нужно сгенерировать их сначала, и разработчик будет проверять вашу папку представлений перед загрузкой представлений из драгоценного камня. В Rails 3 это: «rails generate devise: views» и в Rails 2 (я думаю): «script/generate devise: views» – theTRON

+2

вышеупомянутый хак не работает с приложением 1.0.8, которое является версией для рельсов 2. –

32

Я считаю, что есть лучшее решение, чем переписывать RegistrationsController. Я сделал то же самое (у меня просто Организация, а не Компания).

Если вы правильно установили свою вложенную форму, на модели и уровне зрения, все работает как шарм.

Моя модель Пользователь:

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 

Моя организация Модель:

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 

Мое мнение: 'разработать/регистрация/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" %> 
+2

Перемещение логики сборки из представления в модель будет более чистым, см. Http://stackoverflow.com/questions/3544265#3764837 – meleyal

+0

Я сгенерировал контроллеры разработки и теперь создаю действие контроллера, когда пользователь нажимает «Зарегистрироваться». Есть ли способ (например, переопределить/некоторый примерный код), я могу использовать Devise для шифрования пароля и выполнения проверки пароля и других полей? и сохранить его в базе данных модели? –

+0

Как вы можете получить доступ к локальной переменной 'resource' в представлении вместо переменной экземпляра класса' @ resource'? – Chloe

62

А лучше и более организованный способ переопределения контроллеров и представлений Devision с использованием пространств имен:

Создайте следующие папки:

app/controllers/my_devise 
app/views/my_devise 

Поместите все контроллеры, которые вы хотите переопределить в приложение/контроллеры/my_devise и добавить MyDevise имен в контроллер имен классов. Registrations пример:

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

    ... 

    def create 
    # add custom create logic here 
    end 

    ...  

end 

Меняйте маршруты соответственно:

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

Скопируйте все необходимые виды в app/views/my_devise из папки DEViSE гема или использовать rails generate devise:views, удалите точку вы не переопределение и переименовать devise папки my_devise.

Таким образом, у вас будет все, что аккуратно организовано в две папки.

+1

Это похоже на подход, который я принимаю, но я не знаю, какую пользовательскую логику добавить в метод 'create' Devise's, который я переписал. Мой обработчик, созданный scaffold, который я модифицировал, отлично работает, но как заставить его работать с девелоперским бизнесом? –

+0

@ Vincent спасибо - если я хочу переопределить только один метод, я пишу только метод, который я хочу переопределить, - и все остальное будет работать нормально? Ваша помощь очень ценится – BKSpurgeon

1

Вы также можете сделать папку devise на вашем пути к контроллерам и скопировать/вставить в нее весь коннектор. Это не требует дополнительной настройки.

Так что только для диспетчера регистрации это будет app/controllers/devise/registrations_controller.rb, а затем скопируйте в него источник registrations_controller.rb. Вы можете получить его из github https://github.com/plataformatec/devise/blob/master/app/controllers/devise/registrations_controller.rb, или вы можете отслеживать его в своем источнике драгоценных камней, или если вы используете RubyMine при вводе строки класса class Devise::RegistrationsController, символ слева на глобусе ... щелкните по нему, и он откроет Создайте файл контроллера регистрации для вас. Затем скопируйте/вставьте.

+9

-1 для продвижения практики копирования/вставки, особенно в таком чувствительном к безопасности контексте. Если исправление применяется к Devise по соображениям безопасности, ваш код не принесет ему пользы, даже если вы обновите версию gem. Лучше использовать решение Vincent и наследовать от 'Devise :: RegistrationsController' –

+0

Плюс один, потому что вы правы, и мой ответ показывает, как люди могут найти исходный код. –

0

создать регистрацию контроллера и переопределить его унаследованный класс по предопределенной Devise :: RegistrationsController класс

# 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 

после этого множества маршрутов:

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

Все в порядке! Готово. –

9

Вы можете создать вид и контроллеры для DEViSE настройки.

Использование

rails g devise:controllers users -c=registrations 

и

rails g devise:views 

Он будет копировать отдельные контроллеры и виды из драгоценных камней для вашего приложения.

Далее сообщить маршрутизатору использовать этот контроллер:

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

Очень простые методы Просто идти к терминалу и типу следующему

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

Далее использовать пользовательские представления

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

сейчас в вашем файле route.rb

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

Вы также можете добавить другие контроллеры. Это позволит использовать контроллеры в папке пользователей и представлениях в папке пользователей.

Теперь вы можете настроить свои взгляды по своему желанию и добавить свою логику к контроллерам в папке контроллеров/пользователей. Наслаждайтесь!

Смежные вопросы