[英]Rails ActiveRecord Association
好的,這是我的問題。 我有3種不同的模型,人員,角色,客戶端和商店。 客戶有很多商店,也可以有很多人。 商店有很多人。 人們扮演着各種角色。 1個人可以在多個商店工作,並且每個商店可能扮演不同的角色。
例如。 喬可能是一家商店的助理經理,而另一家商店的經理。 我想做的是通過做類似的事情來扮演正確的角色
Store.find(1).people.find(1).roles(例如,將返回“助理經理”)或
Store.find(2).people.find(1).roles(例如,將返回“ manager”)。 在ActiveRecord中可以這樣做嗎?
我創建了一個表:roles_people,它具有以下定義:
\n create_table:roles_people,:id => false做| t |\n t.references:角色\n t.references:person\n t.references:store\n t.references:客戶\n 結束\n
但是我不知道如何使用此表使關聯正常工作。 誰能指出我正確的方向?
謝謝
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])
我可能會在商店模型中添加一種方法,以使其變得更容易一些:
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對象,那么這沒什么大不了的。
希望這個答案就足夠了:)
我認為您想要的是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
has_and_belongs_to_many
是您的朋友。
class Person < ActiveRecord::Base
has_and_belongs_to_many :roles
end
這樣,您可以通過調用Person.roles.all
獲得該人的所有角色。 結果查詢將使用people_roles
表。 您也可以使用has_many :through
但必須自己為聯接表構建模型類,並自己維護所有關聯。 有時有必要,有時則沒有必要。 取決於實際模型的復雜性。
您需要在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
好問題。 您不能完全按照自己的意願做,但我想我們可以接近。 為了完整性,我將重述一下您的數據結構:
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
您會看到該角色不需要指向客戶端的鏈接,因為可以直接從商店中找到該鏈接(我假設一個存儲僅由一個客戶端“擁有”)。
現在,一個role
既鏈接到一個person
又鏈接到一個store
,因此一個人在每個商店中可以具有不同的角色。 為了以一種干凈的方式找到這些,我將使用一個輔助函數:
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
)的上下文中,我們不再具有商店的任何概念(我們如何到達那里)。
希望這可以幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.