2

好的,这是我的问题。我有 3 个不同的模型,人员、角色、客户和商店。客户有很多商店,也可以有很多人。商店有很多人。人们有不同的角色。1人可以在多个商店工作,他们在每个商店可能有不同的角色。

例如。Joe 可能是一家商店的助理经理和另一家商店的经理。我想做的是通过做类似的事情来拉取正确的角色

Store.find(1).people.find(1).roles
(例如,将返回“助理经理”)或

Store.find(2).people.find(1).roles
(例如,将返回“经理”)。这可以在 ActiveRecord 中进行吗?

我创建了一个表 :roles_people ,它具有以下定义:

create_table :roles_people, :id => false do |t|
      t.references :角色
      t.references:人
      t.references:存储
      t.references:客户端
结尾

但是,我无法弄清楚如何使用此表使关联正常工作。谁能指出我正确的方向?

谢谢

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;)

您将需要设置迁移和数据库结构来反映这些关系。对于每个表上belongs_to:object_id字段,都引用了相应表的 id。

您的查询将需要类似于:

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

我可能会在 store 模型中添加一个方法来使这更容易一些:

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)

我会说最后一种方法是最理想的,因为它只导致一个查询,而其他每个选项在每次角色查找时对数据库执行两个查询(一个用于查找商店,一个用于获取角色一个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

Nice question. You can't do exactly what you wanted, but i guess we can come close. For completeness, i am going to recap your datastructure:

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

You see that the role does not need the link to the client, because that can be found straightaway from the store (i am assuming a stored is "owned" by only one client).

Now a role is linked both to a person and a store, so a person can have different roles per store. And to find these in a clean way, i would use a helper function:

class Person
  has_many :roles
  has_many :stores

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

So you can't write something like

store.people.first.roles

to get the roles of the first person working for that store. But writing something like:

store.people.first.roles_for(store)

is not too hard i hope.

The reason why this is so is because in the context of the person (-> store.people.first) we no longer have any notion of the store (how we got there).

Hope this helps.

于 2011-03-06T19:45:58.813 回答
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 回答