2010-06-13 48 views
2

我想通過在Rails 2.3.x中使用named_scopes來清理我的代碼,但是我正在用has_many:through關聯來掙扎。我想知道如果我把示波器放在錯誤的地方...跨多個表的Rails named_scope

下面是一些僞代碼。問題是:被接受的命名範圍被複制了兩次......我當然可以調用:接受了一些不同的東西,但是這些都是表格上的狀態,將它們稱爲不同的東西似乎是錯誤的。任何人都可以闡明我是否正確地進行了以下操作?

我知道Rails 3已經出來,但它仍然處於測試階段,這是一個很大的項目,所以我不能在生產環境中使用它。

class Person < ActiveRecord::Base 
    has_many :connections 
    has_many :contacts, :through => :connections 

    named_scope :accepted, :conditions => ["connections.status = ?", Connection::ACCEPTED] 
    # the :accepted named_scope is duplicated 
    named_scope :accepted, :conditions => ["memberships.status = ?", Membership::ACCEPTED] 
end 

class Group < ActiveRecord::Base 
    has_many :memberships 
    has_many :members, :through => :memberships 
end 

class Connection < ActiveRecord::Base 
    belongs_to :person 
    belongs_to :contact, :class_name => "Person", :foreign_key => "contact_id" 
end 

class Membership < ActiveRecord::Base 
    belongs_to :person 
    belongs_to :group 
end 

我試圖運行一些像person.contacts.accepted和group.members.accepted這兩個不同的東西。 named_scopes不在Membership和Connection類中嗎?

但是,如果您嘗試將指定的範圍放入成員資格和連接類中,則會出現此錯誤(因爲Person.find(2).contacts返回沒有「已接受」方法的人員數組:

>> Person.find(2).contacts.accepted 
NoMethodError: undefined method `accepted' for #<Class:0x108641f28> 

一個解決方法就是調用Person類不同,甚至是創建單獨的協會兩個不同的命名範圍的東西(即的has_many:accepted_members和的has_many:accepted_contacts),但它似乎hackish的和現實中我有很多不僅僅是被接受的(即被禁止的成員,被忽略的連接,未決的,要求的等等)

回答

0

您回答了您自己的問題:

Shouldn't the named_scopes be in the Membership and Connection classes?

是的,他們應該是。這將讓你打電話給他們,只要你想。它在邏輯上也屬於它們。

如果你想在人的東西,同時檢查,你可以這樣做:

named_scope :accepted, :conditions => ["connections.status = ? OR memberships.status = ?", Connection::ACCEPTED, Membership::ACCEPTED]

也許你想這是一個與?不確定。

+0

沒有這不起作用 - 你得到一個錯誤 - 我已經更新了我的問題,以顯示錯誤是什麼。 >> Person.find(2).contacts.accepted NoMethodError:未定義的方法'接受'爲# wakiki 2010-06-13 06:23:42

+0

並且如果您將兩個範圍合併爲一個,如第二個建議中所示,則會出現未知列錯誤: >> Person.find(2).contacts.accepted ActiveRecord :: StatementInvalid:Mysql :: Error:'where clause'中的未知列'memberships.status':SELECT SQL_NO_CACHE'people'。* FROM'people' INNER JOIN'connections' ON'people'.id ='connections'.contact_id WHERE((''connections'.person_id = 2))AND((connections.status = 0或memberships.status = 0)AND((''connections'。 person_id = 2))) – wakiki 2010-06-13 06:32:03

+0

您錯過了從Person到Membership的關聯。成員資格屬於某個人,但Person不具有____或have_many成員資格。您可能還需要在命名範圍內使用':joins'來使其工作。你想要做的是絕對有可能的。 – x1a4 2010-06-13 07:53:09

0

我敢肯定,這是不是最好的方式,我相信你可以persongroup模型做到這一點,但我也相信,下面就爲你工作:

# models 
class Person < ActiveRecord::Base 
    has_many :connections 
    has_many :contacts, :through => :connections 

    has_many :memberships 
    has_many :groups, :through => :memberships 
end 

class Group < ActiveRecord::Base 
    has_many :memberships 
    has_many :members, :through => :memberships 
end 

class Connection < ActiveRecord::Base 
    belongs_to :person 
    belongs_to :contact, :class_name => "Person", :foreign_key => "contact_id" 

    named_scope :accepted, :conditions => ["status = ?", Connection::ACCEPTED] 
end 

class Membership < ActiveRecord::Base 
    belongs_to :person 
    belongs_to :group 

    named_scope :accepted, :conditions => ["status = ?", Membership::ACCEPTED] 
end 

# controller 
# get person's accepted contacts 
@person = Person.first 
@person.connections.accepted.map(&:contact) 

# get group's accepted members 
@group = Group.first 
@group.memberships.accepted.map(&:person)