むかしむかし、Ruby on Railsのポリモーフィックな関連性についての記事を書きましたが、一部はinしていたことを覚えています。
最近、私はRails 3のポリモーフィックな関連付けを処理するか、サイトで顧客と請負業者の2種類のユーザーを整理する方法を考え出す必要がありました。 この記事では、ポリモーフィックな関連付けとgem Devise(認証用)およびCanCan(許可用)に焦点を当てます。
タスクは次のとおりです。ユーザーには2つのタイプがあり、1つのフォームから登録とログインを行う必要があります。登録中にユーザーは顧客または請負業者を指定します。
したがって、ユーザーはプロジェクトでさまざまな役割を持ち、さまざまなことを行うことができました。
したがって、標準のDeviseドキュメントに従って、プロジェクトに追加しました。 Deviseが作成した移行で、次のフィールドを追加しました。
t. string :name, : null => false t.references :character, :polymorphic => true * This source code was highlighted with Source Code Highlighter .
t. string :name, : null => false t.references :character, :polymorphic => true * This source code was highlighted with Source Code Highlighter .
t. string :name, : null => false t.references :character, :polymorphic => true * This source code was highlighted with Source Code Highlighter .
t. string :name, : null => false t.references :character, :polymorphic => true * This source code was highlighted with Source Code Highlighter .
名前に加えて、ここでは、国、住所など、すべてのタイプのユーザーの他の共通プロパティを作成できます。 このフィールドには名前しかありませんでした。
ドキュメンテーション(http://apidock.com/rails/ActiveRecord/ConnectionAdapters/Table/references)によると、2行目はcharacter_idとcharacter_typeの2つのフィールドを作成します。このIDを探す場所。
その後、rake db:migrateを実行し、user.rbモデルを追加します。
*このソースコードは、 ソースコードハイライターで強調表示されました。
- クラス User <ActiveRecord :: Base
- # デフォルトの deviseモジュールを含めます 。 他に利用可能なものは:
- #:token_authenticatable 、:暗号化可能、:確認可能、:ロック可能、:タイムアウト可能、:追跡可能、およびomniauthable
- devise:database_authenticatable 、: registerable 、: recoverable 、: rememberable 、: validatable
- #モデルのアクセス可能な(または保護された )属性を設定する
- attr_accessible:name ,: email ,: password ,: remember_me ,: character_id ,: character_type ,: character ,: character_attributes
- #検証
- validates_presence_of:name ,: character_type
- validates_inclusion_of:character_type ,: in =>%w(カスタマーエグゼクティブ)
- #協会
- belongs_to:character ,: polymorphic => true 、:dependent =>:destroy
- #ネストされた属性
- accepts_nested_attributes_for:文字
- #認証ヘルパーメソッド
- defお客様?
- character_type == 「顧客」
- 終わり
- デフエグゼクティブ?
- character_type == "エグゼクティブ"
- 終わり
- 終わり
ここで、attr_accessibleに新しいフィールドを追加し、検証を追加し、関連付けを登録し、accepts_nested_attributes_forを追加しました。
attr_accessibleを変更して、一度に1つではなくバッチでデータを保存できるようにする必要があります。
必要なレコードが追加されていることを確認するために検証が必要です(そして、そのフォーマットも私たちに合っています)。
Kakbeポリモーフィック関連は、ユーザーが顧客またはアーティストのいずれかを参照する文字フィールドを持っていることを示唆しています。 実際、これはユーザーモデルへの追加であり、1つのタイプまたは別のタイプのいずれかです。
assepts_nested_attributes_forは、ネストされたフォーム(キャラクターのサブフォームが埋め込まれているユーザーのフォーム(つまり、顧客またはパフォーマーのいずれか)を作成できるようにするために必要です。
最後の2つの方法は便宜上のものであるため、コントローラーで簡単かつ迅速に判断し、使用しているユーザーのタイプを確認できます。
その後、2つのモデルを作成します:顧客とエグゼクティブ。 移行では、両方のモデルで、ユーザーの各タイプ(パスワード、出席など)に固有のデータを登録して、ユーザーと通信するために、これを登録する必要があります。
*このソースコードは、 ソースコードハイライターで強調表示されました。
- has_one:user ,: as =>:character ,: dependent =>:destroy
また、user_observer(rails g observerユーザー)を追加し、このコードを作成しました。
*このソースコードは、 ソースコードハイライターで強調表示されました。
- クラス UserObserver <ActiveRecord :: Observer
- def before_create(ユーザー)
- build_character_forユーザー
- 終わり
- プライベート
- def build_character_for(ユーザー)
- user.character = user.character_type.classify.constantize.create!
- 終わり
- 終わり
その後、私はconfig / application.rbでこのオブザーバーを接続しました:
*このソースコードは、 ソースコードハイライターで強調表示されました。
- config.active_record.observers =:user_observer
登録時に、ユーザーは自分が誰になりたいかを選択する必要があると言ったことを覚えていますか? ラジオは持っていますが、簡単に選択できます。 選択したタイプに応じて、「Customer」または「Executive」のいずれかを返す必要があります。 また、それに応じて、各ユーザーを作成する前に、そのユーザーの顧客または実行者を作成します。 上記のコードは次のように書くことができます。
*このソースコードは、 ソースコードハイライターで強調表示されました。
- user.character_type ==“ Customer”の場合
- user.character = Customer.create!
- 他に
- user.character = Executive.create!
- 終わり
しかし、それはどういうわけか長くて不便です、同意します。
Devise'omが終わったら、CanCanにアクセスできます。 また、ドキュメントに従ってインストールし、両方のタイプのユーザーに異なるルールを設定する必要があります。 たとえば、次のようなもの:
*このソースコードは、 ソースコードハイライターで強調表示されました。
- クラス能力
- CanCanを含む::能力
- def initialize(ユーザー)
- ユーザー|| =ユーザー。 新しい
- user.adminの場合 #管理者アカウント
- できる:管理する:すべて
- 他に
- user.customerの場合 #顧客アカウント
- #RESTful
- can:読み取り、ドキュメント
- can:create、ドキュメント
- can:update、Document 、: customer_id => user.character.id
- can:読み取り、コメント
- #コレクション
- can:個人、ドキュメント
- elsif user.executive? #エグゼクティブアカウント
- #RESTful
- can:読み取り、ドキュメント
- can:読み取り、コメント
- can:create、コメント
- can [:update ,: destroy]、Comment ,: executive_id => user.character.id
- #メンバー
- can:結合、ドキュメント
- can:Leave、Document
- #コレクション
- can:下書き、コメント
- can:アーカイブ、コメント
- 終わり
- 終わり
- 終わり
- 終わり
そのようなことを言ってみましょう。 したがって、顧客と実行者の両方が同じコントローラー/リソースにアクセスできますが、同時に、それぞれに対して異なるアクションが許可されます。
ビューでは、現在のユーザーが何らかのアクションを実行できるかどうかを確認するだけで十分であり、人生は楽園のように見えます。
*このソースコードは、 ソースコードハイライターで強調表示されました。
- できれば ? :参加、@ドキュメント
- = link_to“ Join”、[:join、@document]
これで、上記のルールで許可されているユーザーのみに「参加」リンクが表示されます。 コントローラーをもう少し修正する必要がありますが、すべては標準のドキュメントに従っています。
このようにして、サイト上のさまざまなブロック、および実際には何でも非表示および表示できます。
ここで、関連付けに関するいくつかの言葉:ほとんどの関連付けは、ユーザーモデルではなく、顧客とエグゼキュータのモデルに登録されるようになりました。 したがって、さらなる柔軟性が最大限の柔軟性を実現します。
記事の結果は次のとおりです。ポリモーフィックな関連付けが本当に必要であり、人生を大幅に簡素化する状況があります。 それらを熱狂的に各穴に追加するべきではありませんが、それらについて知って、それらを適用できるべきです。
関連リンク:
github.com/plataformatec/devise
github.com/ryanb/cancan
habrahabr.ru/blogs/ror/79431