【问题标题】:Rails 3.2 and getting AR to properly order this queryRails 3.2 并让 AR 正确排序此查询
【发布时间】:2012-05-02 03:05:26
【问题描述】:

我目前有一个范围,我正在尝试查找在关联中创建的最后一条记录,并在特定布尔值为 false 时选择它

IE Foo has_many Bar's 和 Bar's 有一个名为 bazzed 的布尔列

scope :no_baz,   joins(:bars).order("bars.id DESC").limit(1).where("bars.bazzed = 'f'")

问题在于 rails 把这个查询变成了这样的东西

SELECT "foos".* FROM "foos" INNER JOIN "bars" ON "bars"."foo_id" = "foos"."id" WHERE (bars.bazzed = 'f') ORDER BY bars.id DESC LIMIT 1

问题在于 rails 在 where 子句之后调用 order 和 limit,我正在寻找的是先执行 order 和 limit 以尝试找到最后一个设置为 false 的 bar。

是否有原生 AR 方式来执行我试图完成的查询?

编辑

我正在尝试抓取具有 bar 的 foo,其中他们的最后一个 bar 设置为 false,并且仅当该 foo 的最后一个 bar 设置为 false 时。

【问题讨论】:

  • 如果您尝试以下操作会怎样:"scope :no_baz, joins(:bars).order("bars.id DESC").where("bars.bazzed = 'f'").first ”。由于我不确定它是否有效,因此我不建议将其作为答案。 ^^
  • 仅当 bazzed 字段为 false 时才尝试获取第一条记录。这目前抓住了第一个 bazzed,不管它是否是第一个记录。

标签: sql ruby-on-rails activerecord


【解决方案1】:

好的,我建议在“foo”模型上进行查询:

Foo.bars.where("bars.bazzed = ?", 'f').all( :order => "created_at DESC").first

注意:当然,“f”可以替换为 false,具体取决于您在“bazzed”列中使用的值。

[编辑]

好的,因为我认为我更好地理解了这个问题,这里有一个建议,但针对公共方法而不是范围查询。

def no_baz
  all_no_baz_foos = Array.new
  Foo.all.each do |foo|
      last_bar = foo.bars.all.order("bars.id DESC").first
      if last_bar.bazzed == 'f'
        all_no_baz_foos << foo
      end
  end
  return all_no_baz_foos
end

此方法将返回一个包含所有 no_baz_foos 记录的数组。由于我没有测试我的代码,您可能需要更改一些内容才能使其正常工作,但我认为您明白了。

对于“范围”方法,我只是找不到正确链接查询以获得所需结果的方法。如果其他人知道如何使用示波器来实现这一点,我也会很高兴听到解决方案。

【讨论】:

  • 返回最后创建的 bar 和 bazzed 不会设置为 false 吗?我想要完成的是通过所有 foos 验证并挑选出最后创建的 bar 且 bazzed 值为 false 的 foo。所以如果 foo 的最后一个 bar.bazzed 是 't' 我不想返回那个 foo。
  • 哦……我没看懂,抱歉……嗯,bar和foo是什么关系?原因,你有“foo has_many bar”,但有“bar has_many foos”或“bar has_one foo”还是......?如果您使用更具体的示例,例如“用户有许多帖子已发布列”或类似的东西,会更容易理解。 ^^
  • 这是一个棘手的问题,范围方法真的重要吗?因为,也许,创建一个方法会更好,更容易,我会编辑我的帖子并提出建议。
  • 这样做作为一种方法绝对可以完成任务,我非常感谢到目前为止的帮助,谢谢!如果可能的话,目前仍在尝试在一个范围内执行此操作
  • 我想到了别的东西,也许你可以尝试链接范围?比如:范围:last_bar,joins(:bars).order("bars.id DESC").limit(1)。然后是另一个作用域:作用域:no_baz, last_bar.and(self.bars.bazzed != 'f')。不确定它是否更好,但绝对值得尝试,因为实际上您确实链接了两个不同的范围。 ;)
【解决方案2】:

目前使用类方法,但问题在于它返回一个数组对象,而不是我想要返回的活动记录关系。仍在尝试正确完成查询。

【讨论】:

  • thie SQL 仍然无法正常工作(现在出现语法错误)尝试执行类似范围的操作:test, find_by_sql("SELECT foos.* FROM foos INNER JOIN bar ON bars.foos = foos .id ORDER BY bar.id DESC LIMIT 1 WHERE (bars.bazzed = 'f'))") 语法错误就在 WHERE 所在的位置.. 本质上我想要类似的东西,但最后使用 where 子句
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多