Ruby on rails Rails 3-嵌套选择和";。最后一句话;
我有一个场景,似乎应该在模型方面解决一些问题,但无法找到一个有效的Activerecord方法组合。my db的相关部分如下所示:Ruby on rails Rails 3-嵌套选择和";。最后一句话;,ruby-on-rails,ruby,ruby-on-rails-3,activerecord,chaining,Ruby On Rails,Ruby,Ruby On Rails 3,Activerecord,Chaining,我有一个场景,似乎应该在模型方面解决一些问题,但无法找到一个有效的Activerecord方法组合。my db的相关部分如下所示: Part: id part_id created_at ... Parttest: id part_id pass (boolean) created_at 一个零件可以有多个零件测试,而零件测试属于一个零件(在相关模型中设置为多个零件测试) 在它的生命周期中,一个零件可以被多次测试,并且可以通过、失败、通过等等。 使用rails/activerecord,我希
Part:
id
part_id
created_at
...
Parttest:
id
part_id
pass (boolean)
created_at
一个零件可以有多个零件测试,而零件测试属于一个零件(在相关模型中设置为多个零件测试)
在它的生命周期中,一个零件可以被多次测试,并且可以通过、失败、通过等等。
使用rails/activerecord,我希望检索最后一次(最近一次)Parttest通过的部件记录集。零件试验的早期记录不应考虑在内,仅供历史使用
我试过嵌套选择,但没有多大成功。我总是可以在控制器中编写逻辑代码来检查Part.all.each中的每个Part对象,并将它们放入一个数组中,但这似乎不是正确的方法。非常感谢所有帮助:)编辑:误读了你的帖子,你想这样做吗
Part.joins(:parttests)。其中(parttests:{pass:true})
将为您提供所有通过测试的部件
使用作用域尝试Part.joins(:parttests).last.where(parttests:{pass:true})
class Parttest
scope :passed_tests, -> { where(pass: true) }
end
@part = Part.find(1) # Fetch part instance
@part_tests = @part.parttests.passed_tests.last # Fetch its tests
或对关联使用条件:
class Part
has_many :passed_tests, class_name: 'Parttest', -> { where(pass: true) }
end
@part_tests = @part.passed_tests.last
更新
既然我已经正确地理解了这个问题。这个怎么样
class Part
has_many :passed_tests, class_name: 'Parttest', -> { where(pass: true) }
scope :with_last_passed_test, -> { joins(:passed_tests).last }
end
Part.with_last_passed_test
我最初发布了一个很长的SQL查询作为一个选项,但这个建议不是很清晰,所以我删除了它。这里有一种方法可以将其分解为几个小部分 假设我们从这些Parttest行开始:
id part_id created_at pass
1 1 2014-04-26 true
2 1 2014-04-27 false
3 2 2014-04-26 false
4 2 2014-04-27 true
1) 首先,我们要为每个零件查找最新的Parttest行。我们可以通过以下方式做到这一点:
# Parttest model
def self.most_recent
max_rows = select("part_id, MAX(created_at) as max_created_at").group(:part_id)
joins("INNER JOIN (#{max_rows.to_sql}) AS max_rows
ON parttests.part_id = max_rows.part_id
AND parttests.created_at = max_rows.max_created_at")
end
# Parttest model
scope :passed, -> { where(pass: true) }
选择
将获取以下值:
part_id created_at
1 2014-04-27
2 2014-04-27
join
将我们与其他Parttest列连接起来:
id part_id created_at pass
2 1 2014-04-27 false
4 2 2014-04-27 true
2) 那么我们只想保持通过测试。我们可以通过以下方式做到这一点:
# Parttest model
def self.most_recent
max_rows = select("part_id, MAX(created_at) as max_created_at").group(:part_id)
joins("INNER JOIN (#{max_rows.to_sql}) AS max_rows
ON parttests.part_id = max_rows.part_id
AND parttests.created_at = max_rows.max_created_at")
end
# Parttest model
scope :passed, -> { where(pass: true) }
将其与(1)相结合,我们只能通过调用以下命令获得最近的测试:
Parttest.most_recent.passed
这只包括从我们的示例中返回此行:
id part_id created_at pass
4 2 2014-04-27 true
3) 然后,为了找到最近测试通过的所有零件,我们可以提供以下范围:
# Part model
scope :most_recent_test_passed, -> { where("id IN (?)", PartTest.most_recent.passed.map(&:part_id)) }
仅供参考。。。您可以执行
order(在::desc创建)
而不是传递显式字符串。您的作用域中还有一个语法错误。它缺少一个,
——已修复。@Mohamad-我可能误解了你的解决方案,但它不起作用。我无法调用Part.parttests,因为parttests不是Part类的方法。上面的代码不会给我parttest,而不是通过测试的部分吗?(这是我想要的零件,不是零件测试)@SG84看我的答案!这是marknach的回答,不是我的。我添加了我自己的。此外,由于海报编辑了该代码,该代码还有另一个语法错误<代码>部件是多元化的。它应该是部分
。我想编辑一下。我认为OP想找到最近部分测试通过的部分——而不是最近每一篇文章中通过的部分测试——这是正确的——我只想考虑最近的部分测试。@ SG84:我已经更新了我的答案。试试看。“这应该行得通。”穆罕默德-谢谢你在这方面的帮助。您上面的最后一次编辑看起来是正确的,我理解(我想)它应该做什么,但是我在类中得到了两行的语法错误。“语法错误,两行都出现意外的'\n',应为=>”,所以我想可能对新的lambda语法不满意吧?我使用的是Ruby2和Rails3.2。16@SG84不客气。我认为在Rails3.x上不能使用这种语法。试试这个:有很多:通过测试,…,>条件:“pass=true”
-在这里阅读更多:如果你发现其中的答案有帮助,你介意标记一个接受的答案吗?干杯