装置登録コントローラーのオーバーライド


236

別のモデルに基づくサインアップフォームにフィールドを追加しました。詳細については、デバイスモデルネストされた属性をどのように使用するかを参照してください。この部分は正常に動作しています。

保存すると問題が発生しますActiverecord::UnknownAttributeError。このフィールド(会社)のdeviseによって提供される登録コントローラーの作成アクションが失敗します。

登録コントローラをオーバーライドする必要があると思いますか、これに取り組むべきより良い/簡単な方法はありますか?


回答:


354

あなたのフォームでは、ユーザーモデルまたはネストされたモデルに属さない一括割り当てを介して、他の属性を渡していますか?

もしそうなら、このインスタンスで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 

そしてdeviseにデフォルトの代わりにそのコントローラーを使用するように伝えます:

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

3
しかし、どのようにしてdeviseがdevise dirでビューを探すことを確認しますか?私はこれを試していますが、「sign_in_and_redirect(resource_name、resource)」のような工夫されたメソッドがテンプレートのビューを探しています。
AnApprentice

7
deviseビューをカスタマイズしたい場合は、最初にそれらを生成するだけで、gemsからビューをロードする前にdeviseがビューフォルダをチェックします。Railsの3で、それはだ:rails generate devise:viewsとRailsで2(私は思う)それはです:script/generate devise:views
theTRON

2
上記のハックは、レール2のバージョン作品で工夫1.0.8では動作しません
ウィリアム・ヨン

18
このようにDeviseコントローラーをオーバーライドする場合は、必ずすべてのビューをapp / views / devise / registrationsからapp / views / registrations /にコピーしてください(オーバーライドするコントローラーの変更)。
ジェイミーコベット

31
または、デバイスビューをそのままにして、に追加することもできpaths.app.views << "app/views/devise"ますconfig/application.rb
theTRON

66

名前空間を使用してDeviseコントローラーとビューをオーバーライドする、より適切で組織化された方法:

次のフォルダを作成します。

app/controllers/my_devise
app/views/my_devise

オーバーライドするすべてのコントローラーをapp / controllers / 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_deviseDevise gemフォルダーにコピーするか、使用してrails generate devise:views、オーバーライドしないビューを削除し、deviseフォルダーの名前をに変更しますmy_devise

これにより、すべてが2つのフォルダに整理されます。


1
これは私が取っているアプローチに似ていますが、私がcreate上書きしたDevise'sのメソッドにどのカスタムロジックを組み込むかわかりません。私が変更した足場作成のコントローラーはうまく機能しますが、どのようにしてDeviseのresourceビジネスで機能させることができますか?
カイルカールソン2013年

@Vincentありがとう-1つのメソッドのみをオーバーライドする場合、オーバーライドするメソッドのみを記述しますか?それ以外はすべて通常どおり機能しますか?あなたの支援に感謝
BKSpurgeon

MyDevise::RegistrationsController < Devise::RegistrationsController循環依存エラーを作成します。私は何か間違ったことをしていますか?
ianrandmckenzie

34

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

私の見解: '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
ビルドロジックをビューからモデルに移動する方がきれい
です。stackoverflow.com/ questions / 3544265

デバイスコントローラーを生成し、ユーザーが[サインアップ]をクリックしたときにコントローラーアクションの作成をトリガーしました (オーバーライド/コード例のように)Deviseを使用してパスワードを暗号化し、パスワードと他のフィールドのバックエンドチェックを行う方法はありますか?モデルデータベースに保存しますか?
HP

resourceクラスインスタンス変数の代わりに、ビューのローカル変数にどのようにアクセスできます@resourceか?
クロエ

12

デバイスのカスタマイズ用にビューとコントローラーを生成できます。

使用する

rails g devise:controllers users -c=registrations

そして

rails g devise:views 

特定のコントローラーとビューをgemからアプリケーションにコピーします。

次に、このコントローラーを使用するようにルーターに指示します。

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

11

非常に単純な方法ターミナルに行き、次のように入力するだけです

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" }

他のコントローラーも追加できます。これにより、ユーザーフォルダーのコントローラーとユーザーフォルダーのビューを使用するようになります。

これで、必要に応じてビューをカスタマイズし、controllers / usersフォルダーのコントローラーにロジックを追加できます。楽しい !

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.