레일 : 모델을 사용하면 a has_many b boogles_to c는 b에 속하는 곳에 b를 반환하고 b는 c에 속하고 b는 가장 최근에 주어진 a에 만들어 졌습니까?
-
20-09-2019 - |
문제
세 가지 모델 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입니다.
메소드 루프 로이 작업을 수행 할 수 있습니다. 이것은 명명 된 _scopes로만 할 수 있습니까? 아니면 다른 우아하고 효율적인 방법입니까?
실제 세계 (TM) 예제 A, B 및 C는 예를 들어 애완 동물 (a), 애완 동물 (b) 및 이름 (c)으로 상상할 수 있습니다. 애완 동물은 특정 시간에 애완 동물에게 제공되며, 많은 애완 동물에게 주어진 이름이 주어질 수 있습니다. 모든 애완 동물은 많은 이름을 가질 수 있습니다 (A : 관계를 통해). 주어진 이름으로 원하는 이름 모두 그 이름이 그 애완 동물의 가장 최근에 만든 페트 이름 인 애완 동물 중. 전화는 같은 것처럼 보일 수 있습니다 @name.pets.most_recently_named_as
해결책
이 작업을 수행하는 레일 방법은 애완 동물의 이름이 지정된 범위입니다.
이 같은:
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
그것은 꽤 복잡한 가입입니다. 이 정보를 저장하는 방식을 다시 생각해야한다는 지표입니다. 이름이 별도의 테이블에있는 것이 왜 그렇게 중요한가?
다음과 같은 일을하는 것이 더 나을 수 있습니다.
추가 후 name
그리고 old_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