ActiveRecord 객체의 배열이 주어지면 메소드 호출을 통해 쉽게 관계를 수집 할 수 있습니까?

StackOverflow https://stackoverflow.com/questions/220126

문제

다음 코드가 있다고 가정 해 봅시다.

@sites = Site.find(session[:sites]) # will be an array of Site ids
@languages = Language.for_sites(@sites)

for_sites는 해당 사이트와 관련된 언어를 반환하는 언어 모델의 명명 된 _scope이며 언어는 has_many thin을 사용하는 사이트와 관련이 있습니다. 목표는 @languages가 사이트와 관련된 언어의 뚜렷한 배열을 갖는 것입니다.

두 번째 줄에서 언어 객체를 호출하는 대신 이상적으로 말하고 싶습니다.

@sites.languages

그리고 같은 목록이 나에게 반환되었습니다. 레일 2.1 (또는 가장자리)에서 깨끗하게 할 수있는 방법이 있습니까? 나는 연관성과 이름이 지정된 스코프가 속성을 갖도록 배열 객체를 확장 할 수 있지만, 여기에 적용되지 않는 것을 놓치지 않는 한. 이를 수행하는 플러그인은 환영받을 수 있습니다. 코어에있을 필요는 없습니다.

도움이 되었습니까?

해결책

Site.Find로 반환 된 배열을 확장 할 수 있습니다.

class Site
  def find(*args)
    result = super
    result.extend LanguageAggregator if Array === result
    result
  end
end

module LanguageAggregator
  def languages
    Language.find(:all, :conditions => [ 'id in (?)', self.collect { |site| site.id } ])
  end
end

다른 팁

두 사람 모두에 named_scopes를 사용하지 않겠습니까?

class Site
  named_scope :sites, lambda{|ids| :conditions => "id in (#{ids.join(',')})"}
  named_scope :languages, :include => :languages ... (whatever your named scope does)
end

전화:

Site.sites(session[:sites]).languages

또는 언어 객체를 다시 원한다면

Site.sites(session[:sites]).languages.collect{|site| site.languages}.flatten

언어 객체에서 직접 수행 할 수도 있습니다. 사용 중 : Rails 2.1이 나오기 때문에 조인 : : 두 가지 쿼리에 포함시켜 : 조건에서 사이트를 사용할 수 없습니다.

class Language
  named_scope :for_sites, lambda{|site_ids| :joins => 'inner join sites on languages.site_id = sites.id' :conditions => "sites.id in (#{site_ids.join(',')})"}
end

전화:

Language.for_sites(session[:sites])

두 가지 예에서 나는 세션 [: 사이트]가 당신에 의해 완전히 제어되고 SQL 주입 대상이 아니라고 가정했습니다. 그렇지 않은 경우 ID 청소를 처리하십시오.

인스턴스 변수 @sites는 배열 객체이며 사이트가 아니므로 named_scope를 사용할 수 없다고 생각합니다. 이 효과를 달성하기 위해 배열 클래스를 열 수 있습니다 (Yikes)

class Array

  def languages
    ...
  end

end

추가 한 경우 a has_many 또는 has_and_belongs_to_many 언어를 사이트에 연결하면 포함을 사용하고 다음과 같은 작업을 수행 할 수 있습니다.

Site.find( :all, :conditions =>{:id => session[:sites]}, :include => :languages )

다음을 수행하기 위해 이름이 지정된 범위를 만들 수 있습니다. id => 세션 [: 사이트

class Site
  named_scope :for_ids, lambda{ |x| {:conditions => {:id => x }
end

그리고 그렇게합니다

Site.for_ids(session[:sites]).find(:all, :include => :languages)

이것이 당신에게 몇 가지 아이디어를 제공하기를 바랍니다

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top