2

さて、ここに私の質問があります。私には、人、役割、クライアント、ストアの3つの異なるモデルがあります。クライアントには多くの店舗があり、多くの人がいることもあります。店にはたくさんの人がいます。人々にはさまざまな役割があります。1人は複数の店舗で働くことができ、店舗ごとに役割が異なる場合があります。

例えば。ジョーは、ある店舗のアシスタントマネージャーであり、別の店舗のマネージャーである可能性があります。私がしたいのは、次のようなことをして正しい役割を引き出すことです

Store.find(1).people.find(1).roles
(たとえば、「アシスタントマネージャー」を返します)または

Store.find(2).people.find(1).roles
(たとえば、「manager」を返します)。これはActiveRecordで行うことができますか?

次の定義を持つテーブル:roles_peopleを作成しました。

create_table:roles_people、:id => false do | t |
      t.references:role
      t.references:person
      t.references:store
      t.references:client
終わり

ただし、このテーブルを使用して関連付けを正しく機能させる方法がわかりません。誰かが私を正しい方向に向けることができますか?

ありがとう

4

5 に答える 5

3
class People
  belongs_to :client
  has_many :store_roles
end

class Roles
  has_many :store_roles
end

class StoreRole
  belongs_to :role
  belongs_to :people
  belongs_to :store
end

class Client
  has_many :stores
  has_many :people
end

class Store
  belongs_to :client
  has_many :store_roles
  has_many :roles, :through => :store_roles
end

ActiveRecord::Baseこれらのクラスはすべて;)から継承すると仮定します。

これらの関係を反映するように、移行とデータベースの構造を設定する必要があります。それぞれについて、適切なテーブルのIDを参照belongs_toするフィールドがテーブルにあります。:object_id

クエリは次のようになる必要があります。

Store.find(1).roles.find(:all, :conditions => ["store_roles.person_id = ?", 1])

これを少し簡単にするために、おそらくストアモデルにメソッドを追加します。

def roles_for(person_id)
  roles.find(:all, :conditions => ["store_roles.person_id = ?", person_id])
end

このようにして、以下を使用して役割を見つけることができます。

Store.find(1).roles_for(1)

または、さらに良い:

def self.roles_for(store_id, person_id)
  Role.find(:all, :joins => :store_roles, :conditions => ["store_roles.store_id = ? AND store_roles.person_id = ?", store_id, person_id])
end

これにより、ファインダーが次のように変更されます。

Store.roles_for(1, 1)

この最後の方法は、クエリが1つだけ発生するため、最も理想的ですが、他の各オプションは、ロールルックアップごとにデータベースに対して2つのクエリを実行します(1つはストアを検索し、もう1つはperson_id)。もちろん、すでにStoreオブジェクトがインスタンス化されている場合は、大したことではありません。

うまくいけば、この答えは十分でした:)

于 2011-03-08T03:42:51.267 に答える
1

私はあなたが欲しいのはhas_many:throughだと思います

class Person < ActiveRecord::Base
  has_many :roles_people
  has_many :roles, :through => :roles_people
end

class Store < ActiveRecord::Base
  has_many :roles_people
  has_many :people, :through => roles_people
end

また、RolePersonに関係を追加する必要があります。

class RolePerson < ActiveRecord::Base
  belongs_to :store
  belongs_to :person
  has_one :role
end

それはあなたが探していたものですか?

非常に役立つリンク@blog.hasmanythrough.com

于 2011-03-06T19:20:13.767 に答える
0

has_and_belongs_to_manyあなたの友だちです。

class Person < ActiveRecord::Base
  has_and_belongs_to_many :roles
end

そうすれば、を呼び出すことで、その人が持つすべての役割を取得できますPerson.roles.all。結果のクエリはpeople_rolesテーブルを使用します。使用することもできますhas_many :throughが、結合テーブルのモデルクラスを自分で作成し、すべての関連付けを自分で維持する必要があります。必要な場合もあれば、そうでない場合もあります。実際のモデルの複雑さに依存します。

于 2011-03-06T19:25:56.280 に答える
0

でテーブル名を変更する必要がありpeople_roles、ストア参照とクライアント参照の両方を削除できます。

create_table :roles_people, :id => false do |t|
  t.references :role
  t.references :person
  t.references :store
end

役割は人だけのものです。

次に、has_and_belongs_to_manyを使用する必要があります。

class Person < ActiveRecord::Base
  has_many :roles
  has_many :stores, :through => :people_roles
end

class Store < ActiveRecord::Base
  has_many :roles
  has_many :people, :through => :people_roles
end

クエリできるより:

Store.find(1).people.find(1).roles
于 2011-03-06T19:29:00.127 に答える
0

いい質問です。あなたはあなたが望んでいたことを正確に行うことはできませんが、私たちは近づくことができると思います。完全を期すために、データ構造を要約します。

class Client
  has_many :stores
end

class Store
  has_many :people
  has_many :roles
end

class Person
  has_many :roles
  has_many :stores
end

class Role
  belongs_to :store
  belongs_to :person
end

役割はクライアントへのリンクを必要としないことがわかります。これは、ストアからすぐに見つけることができるためです(ストアは、1人のクライアントのみが「所有」していると想定しています)。

これで、aはaとaのrole両方にリンクされるため、店舗ごとに異なる役割を持つことができます。そして、これらをきれいに見つけるために、私はヘルパー関数を使用します:personstore

class Person
  has_many :roles
  has_many :stores

  def roles_for(store)
    roles.where("store_id=?", store.id)
  end
end

だからあなたは次のようなものを書くことはできません

store.people.first.roles

その店で働く一人称の役割を取得します。しかし、次のようなものを書く:

store.people.first.roles_for(store)

それほど難しくはないと思います。

これがそうである理由は、人(-> store.people.first)のコンテキストでは、ストア(どのようにしてそこに到達したか)の概念がなくなったためです。

お役に立てれば。

于 2011-03-06T19:45:58.813 に答える