【问题标题】:Rails scope overriding selectRails 范围覆盖选择
【发布时间】:2012-05-01 12:25:58
【问题描述】:

我有一个具有 has_many 关系的模型,以及确定它是否有任何子级的范围,例如:

  scope :with_nomination, :include => [:nomination], :conditions => "nominations.service_id IS NOT NULL"

使用它,我可以执行Service.with_nomination 之类的操作,并收到一份包含提名儿童的所有服务列表。

问题是,当我在本质上执行Service.select("id, firstName, lastName").with_nomination ActiveRecord 之类的操作时,SELECT * FROM services 非常糟糕并且没有使用我煞费苦心设置的索引。

如何改写我的查询或修改我的范围以使用 .select() 命令?

【问题讨论】:

  • 我不是这方面的专家,并且会听从其他人的意见以提供真实的答案,但我认为您需要先对您的范围进行 join 或 lambda,然后才能使用 select以您希望的方式。我以前在 github 上的源代码中看到过它,但我自己还没有实现它。只是在等待更好的答复时的想法。

标签: mysql ruby-on-rails optimization named-scope


【解决方案1】:

结果在我使用的语法中,选择是不可能的,所以它会选择 * 并且任何进一步的选择都已被覆盖。

我像这样重写了范围:

scope :no_nomination, joins("LEFT JOIN nominations ON nominations.service_id = services.id").where("nominations.service_id IS NULL")
# important distinction here, the left join allows you to find those records without children

scope :with_nomination, joins(:nomination).where("nominations.service_id IS NOT NULL")

使用这种语法可以让我做类似Service.select(:id,:user,:otherfield).with_nomination的事情

【讨论】:

    【解决方案2】:

    8 年后...

    这很难看,但您也可以使用to_sql 将生成的ActiveRecord::Relation 转换为sql,然后使用ActiveRecord::Base.connection.execute 手动运行命令。

    它可能看起来像这样:

    query = Service.select("id, firstName, lastName").with_nomination.to_sql
    records = ActiveRecord::Base.connection.execute(query)
    records.first["firstName"] # => First Name
    

    这并不能消除作用域检索到的多余列,并且您必须使用字符串键访问每个字段,但是嘿,至少您仍然可以访问它们!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-28
      相关资源
      最近更新 更多