【问题标题】:Active Relation: Retrieving records through an association?主动关系:通过关联检索记录?
【发布时间】:2011-09-08 22:56:10
【问题描述】:

我有以下型号:

class User < ActiveRecord::Base
  has_many :survey_takings
end

class SurveyTaking < ActiveRecord::Base
  belongs_to :survey

  def self.surveys_taken # must return surveys, not survey_takings
    where(:state => 'completed').map(&:survey)
  end

  def self.last_survey_taken
    surveys_taken.maximum(:position) # that's Survey#position
  end
end

目标是能够从控制器调用@user.survey_takings.last_survey_taken。 (这是人为的,但顺其自然;总体目标是能够调用 @user.survey_takings 上的类方法,从而可以在相关调查中使用关系。)

在当前形式下,此代码将不起作用;当我调用.map(&amp;:survey) 时,surveys_taken 将 ActiveRelation 折叠成一个数组。有没有办法为所有加入的调查返回关系?我不能这样做:

def self.surveys_taken
  Survey.join(:survey_takings).where("survey_takings.state = 'completed'")
end

因为@user.survey_takings.surveys_taken 将加入所有已完成的调查问卷,而不仅仅是@user 的已完成调查问卷。

我想我想要的是相当于

class User < ActiveRecord::Base
  has_many :survey_takings
  has_many :surveys_taken, :through => :survey_takings, :source => :surveys
end

但我无法从SurveyTaking.last_survey_taken 访问该surveys_taken 关联。

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 activerecord active-relation


    【解决方案1】:

    如果我的理解正确,您想查找某个用户完成的调查吗?如果是这样,您可以这样做:

    Survey.join(:survey_takings).where("survey_takings.state = 'completed'", :user => @user)
    

    它看起来也像:

    def self.surveys_taken
    where(:state => 'completed').map(&:survey)
    end
    

    您可能想要使用范围:

    scope :surveys_taken, where(:state => 'completed')
    

    【讨论】:

    • 类方法也可以工作(虽然我总是使用类 .map(&:survey) 部分是做什么用的。它们像示波器一样可组合。
    • 好吧,我不能对调查问卷使用范围,因为那样会返回调查问卷,而不是调查。我当然可以在控制器中执行Survey.join,但我不能在SurveyTaking.surveys_taken 中执行此操作,因为它是类方法,所以没有@user。也在更新问题..
    • 有数百种方法可以做到这一点。我指给你一个方向。您没有描述您要完成的确切事情,因此很难从损坏的代码中推断出您想要什么。您可以使用范围,它们不返回数组,而且您似乎有不需要的关联。如果您真的只是想找到给定用户完成的调查,您可以使用一行代码、一个简单的数据库查询来完成,不需要额外的代码。
    【解决方案2】:

    我想我正在寻找的是这个:

    class SurveyTaking < ActiveRecord::Base
      def self.surveys_taken
        Survey.joins(:survey_takings).where("survey_takings.state = 'completed'").merge(self.scoped)
      end
    end
    

    这样,SurveyTaking.surveys_taken 会返回任何人进行的调查,而@user.survey_takings.surveys_taken 会返回@user 进行的调查。密钥是merge(self.scoped)

    在我接受之前等待进一步的 cmets..

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-11-18
      • 1970-01-01
      • 2015-04-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多