복붙노트

[RUBY-ON-RAILS] 액티브가 포함되어 있습니다. 포함 된 열을 지정합니다

RUBY-ON-RAILS

액티브가 포함되어 있습니다. 포함 된 열을 지정합니다

나는 모델의 프로필을 가지고있다. 프로필 has_one 사용자. 사용자 모델은 필드의 이메일을 가지고있다. 언제 전화

Profile.some_scope.includes(:user)

그것은 호출

SELECT users.* FROM users WHERE users.id IN (some ids)

하지만 내 사용자 모델은 내가 렌더링에 사용하지 오전 많은 분야가 있습니다. 그것은 사용자로부터 만 이메일을로드 할 수 있습니까? 그래서, SQL은 같아야합니다

SELECT users.email FROM users WHERE users.id IN (some ids)

해결법

  1. ==============================

    1.레일 쿼리를 포함에 대한 옵션을 전달하는 기능을 가지고 있겠지. 그러나 우리는 모델에 따라 협회의 선언이 PARAMS를 전달할 수 있습니다.

    레일 쿼리를 포함에 대한 옵션을 전달하는 기능을 가지고 있겠지. 그러나 우리는 모델에 따라 협회의 선언이 PARAMS를 전달할 수 있습니다.

    이 시나리오의 경우, 프로파일 모델에서 사용자 모델과 새로운 관계를 만들려면 다음과 같이해야합니다

    belongs_to :user_only_fetch_email, :select => "users.id, users.email", :class_name => "User"
    

    그냥 하나 더 연결을 생성하지만 사용자 모델 만 가리 킵니다. 당신은 쿼리 할 수 ​​있도록,

    Profile.includes(:user_only_fetch_email)
    

    또는

    Profile.includes(:user_only_fetch_email).find(some_profile_ids)
    
  2. ==============================

    2.특정 속성을 선택합니다, 당신은 포함하기보다는 조인 사용해야합니다.

    특정 속성을 선택합니다, 당신은 포함하기보다는 조인 사용해야합니다.

    이 asciicast에서 :

    조인 사용 :

    Profile.some_scope.joins(:users).select("users.email")
    
  3. ==============================

    3.당신은 추가해야 할 모델에 속한다.

    당신은 추가해야 할 모델에 속한다.

    간단한 협회 :

    belongs_to :user_restricted, -> { select(:id, :email) }, class_name: 'User'
    

    다형성 (: commentable 예) 협회 :

    belongs_to :commentable_restricted, -> { select(:id, :title) }, polymorphic: true, foreign_type: :commentable_type, foreign_key: :commentable_id
    

    당신은 당신이 원하는 이름을 belongs_to 무엇이든 선택할 수 있습니다. (: user_restricted), Comment.recent.includes (: commentable_restricted 등) 위의 예를 들어, Article.featured.includes처럼 사용할 수 있습니다

  4. ==============================

    4.레일이 포함 된 경우 특정 열을 선택 지원하지 않습니다. 당신은 그냥 게으른 부하의, 알고있다.

    레일이 포함 된 경우 특정 열을 선택 지원하지 않습니다. 당신은 그냥 게으른 부하의, 알고있다.

    그것은 데이터가 실제로 사용하기 전에 관련 데이터를로드하기 위해 액티브 :: 협회 :: 프리 로더 모듈을 사용합니다. 방법으로 :

    def preload(records, associations, preload_scope = nil)
        records = Array.wrap(records).compact
    
        if records.empty?
          []
        else
          records.uniq!
          Array.wrap(associations).flat_map { |association|
            preloaders_on association, records, preload_scope
          }
        end
     end
    

    프리로드의 세 번째 PARAMS을 preload_scope, 열을 지정 선택하는 방법입니다. 그러나 게으른 부하는 더 이상 할 수 없습니다.

    relation = Profile.where(id: [1,2,3])
    user_columns = {:select=>[:updated_at, :id, :name]}
    preloader = ActiveRecord::Associations::Preloader.new
    preloader.preload(relation, :user, user_columns)
    

    그것은 단지 하나의 연관에 대해, 당신은. 그러나 전달 된 지정 열을 선택합니다. 한 번에 지원 로딩 여러 복잡한 협회에 액티브 :: 협회 :: 프리 로더에 대한 패치를 만들 필요가있다.

    다음 패치에 대한 예입니다

    그것을 사용하는 방법, 예를

  5. ==============================

    5.나 자신, 그래서 그것을 사용하시기 바랍니다 기능을 원했다. 클래스에서이 방법을 포함

    나 자신, 그래서 그것을 사용하시기 바랍니다 기능을 원했다. 클래스에서이 방법을 포함

    문자열 형식의 #ACCEPTS의 인수 "ASSOCIATION_NAME : COLUMN_NAME-COLUMN_NAME"

    def self.includes_with_select(*m)
        association_arr = []
        m.each do |part|
          parts = part.split(':')
          association = parts[0].to_sym
          select_columns = parts[1].split('-')
          association_macro = (self.reflect_on_association(association).macro)
          association_arr << association.to_sym
          class_name = self.reflect_on_association(association).class_name 
          self.send(association_macro, association, -> {select *select_columns}, class_name: "#{class_name.to_sym}")
        end
        self.includes(*association_arr)
      end
    

    그리고 당신처럼 호출 할 수있을 것입니다 : Contract.includes_with_select ( '사용자 : ID-이름 상태', '확인 : 확인-ID'), 그리고 그 지정된 열을 선택합니다.

  6. ==============================

    6.Mohanaj의 예를 사용하여이 작업을 수행 할 수 있습니다 :

    Mohanaj의 예를 사용하여이 작업을 수행 할 수 있습니다 :

    belongs_to :user_only_fetch_email, -> { select [:id, :email] }, :class_name => "User"
    
  7. from https://stackoverflow.com/questions/12400860/activerecord-includes-specify-included-columns by cc-by-sa and MIT license