【问题标题】:Rails named_scope across multiple tablesRails named_scope 跨多个表
【发布时间】:2010-06-13 01:29:49
【问题描述】:

我正在尝试通过在 Rails 2.3.x 中使用 named_scopes 来整理我的代码,但我正在努力处理 has_many :through 关联。我想知道我是不是把瞄准镜放错地方了……

下面是一些伪代码。问题是 :accepted 命名范围被复制了两次......我当然可以调用 :accepted 不同的东西,但这些是桌面上的状态,将它们称为不同的东西似乎是错误的。谁能阐明我是否正确执行以下操作?

我知道 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 返回一个没有“接受”方法的 Persons 数组:

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

一种解决方案是在 Person 类中将两个不同的命名范围称为不同的东西,甚至创建单独的关联(即 has_many :accepted_members 和 has_many :accepted_contacts),但这似乎很老套,实际上我有很多不只是接受(即禁止成员、忽略连接、待处理、请求等)

【问题讨论】:

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


    【解决方案1】:

    您回答了自己的问题:

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

    是的,他们应该是。这将使您可以随心所欲地调用它们。从逻辑上讲,这也是他们所属的地方。

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

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

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

    【讨论】:

    • 不,这不起作用 - 你得到一个错误 - 我已经更新了我的问题以显示错误是什么。 >> Person.find(2).contacts.accepted NoMethodError: undefined method `accepted' for #<0x108641f28>
    【解决方案2】:

    我确信这不是最好的方法,我相信您可以在 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)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多