在多个表中跨越named_scope

时间:2010-06-13 01:29:50

标签: ruby-on-rails join named-scope

我正在尝试通过在Rails 2.3.x中使用named_scopes来整理我的代码,但是我正在努力使用has_many:通过关联。我想知道我是否将示波器放在错误的位置......

下面是一些伪代码。问题是:接受命名的范围被复制两次......我当然可以称之为:接受不同的东西,但这些是桌面上的状态,并且将它们称为不同的东西似乎是错误的。有人能说清楚我是否正确地做了以下事情?

我知道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类中吗?

但是,如果您尝试将命名范围放在Membership和Connection类中,那么您会收到此错误(因为Person.find(2).contacts返回一个没有'accepted'方法的Persons数组:

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

一种解决方案是在Person类中调用两个不同的命名范围,或者甚至创建单独的关联(即.has_many:accepted_members和has_many:accepted_contacts),但它似乎是hackish,实际上我有很多不仅仅是接受(即被禁止的成员,忽略连接,待处理,请求等)

2 个答案:

答案 0 :(得分:0)

你回答了自己的问题:

  

named_scopes不应该在Membership和Connection类中吗?

是的,他们应该。这将让你按照自己的意愿打电话给他们。它在逻辑上也属于它们所属的地方。

如果你想在Person上检查两者,你可以这样做:

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

也许您希望这是一个AND?不确定。

答案 1 :(得分: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)