3

私には3つのモデルA、B、CがありA has_many Bます。B belongs to C、およびB has a created_on timestamp。Chas_manyAからB。

AがCに属するBを持ち、BがそのAに対して最後に作成されたBである すべてのAを返したい。

メソッドループでこれを行うことができます。これはnamed_scopesだけで実行できますか?それとも他のエレガントで効率的な方法ですか?

実世界(TM)の要求に従って、例A、B、およびCは、たとえば、ペット(A)、ペット名(B)、および名前(C)として想像できます。PetsNamesは特定の時間にペットに付けられ、任意の名前を多くのペットに付けることができます。どのペットも多くの名前を持つことができます(: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

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 に答える