3

我有三个模型 A、B 和 C,其中A has_many B; B belongs to C, 和B has a created_on timestamp. C has_many A 到 B。

我想返回所有A,其中A有一个属于C的B,而B是该A最近创建的B。

我可以用方法循环来做到这一点。这可以仅使用 named_scopes 完成吗?还是其他一些优雅/有效的方式?

根据对真实世界 (TM) 示例的请求,A、B 和 C 可以想象为例如 Pets (A)、PetsName (B) 和 Names (C)。PetsNames 在特定时间赋予 Pets,任何给定的 Name 都可以赋予多个 Pets。任何宠物都可以有多个名称(一个 :through 关系)。对于给定的名称,我想要该名称是该宠物最近创建的 PetName 的所有宠物电话可能看起来像@name.pets.most_recently_named_as

4

1 回答 1

4

Rails 执行此操作的方法是在宠物上使用命名范围。

像这样的东西:

class Pets
  has_many :pet_names
  has_many :names, :through => :pet_names

  named_scope :with_current_name, lambda {|name| 
    { :joins => "JOIN (pet_names pna, names) " +
        "ON (pna.pet_id = pets.id AND pna.name_id = names.id) " +
        "LEFT JOIN pet_names pnb " +
        "ON (pnb.pet_id = pets.id AND pna.created_at < pnb.created_at)", 
      :conditions => ["pnb.id IS NULL AND names.id = ? ", name]
    }
  }
end

Pets.with_current_name(@name)
@name.pets.with_current_name(@name)

为了保持以名称为中心,您始终可以在 C/Name 上定义一个调用命名范围的方法。

你总是可以做

class Name < ActiveRecord::Base
  has_many :pet_names
  has_many :pets, :through => :pet_names

  def currently_named_pets
    Pets.with_current_name(self)
  end
end

@name.currently_named_pets

这是一个相当复杂的连接。这表明您可能应该重新考虑存储此信息的方式。为什么将名称放在单独的表中如此重要?

你可能会更好地做这样的事情:

nameold_name列添加到 Pet 后:

class Pet < ActiveRecord::Base
  serialize :old_name, Array
  def after_initialization 
    @old_name ||= []
  end

  def name= new_name
    self.old_name << new_name
    self.name = new_name
  end

  named_scope :with_name, lambda {|name|
     { :conditions => {:name => name}}
  }
end
于 2010-02-13T18:27:05.663 回答