2010-06-13 50 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)