简体   繁体   English

范围中的类方法或外连接

[英]Class Methods or Outer Joins in scopes

I've spent all day making this work and to me, the results are a little ugly. 我花了一整天的时间来完成这项工作而且对我而言,结果有点难看。 Surely there must be a better way and almost certainly, I don't know about it. 肯定有一个更好的方式,几乎可以肯定,我不知道。

I have a model - Task, which has_many (or none!) TimeLogs 我有一个模型 - 任务,has_many(或没有!)TimeLogs

until now I used an instance method to tell whether it was started? 到现在为止我使用了一个实例方法来判断它是否已经启动了? or !started? 或者!开始了?

  def started?
    time_logs.length > 0
  end

but when creating scopes, I found I couldn't implement this method into the query. 但是在创建范围时,我发现我无法在查询中实现此方法。 If there is a way, I'd really love to know because I have some similar problems on the horizon. 如果有办法,我真的很想知道,因为我有一些类似的问题即将出现。

The way I did solve this was to refactor it into a proper database scope with a join: 我解决这个问题的方法是使用连接将其重构为适当的数据库范围:

 scope :started, joins(:time_logs).uniq  

pretty neat, how about the inverse? 非常整洁,反过来怎么样?

scope :not_started, joins("LEFT OUTER JOIN time_logs ON tasks.id = time_logs.task_id").where("time_logs.task_id is null")

bleaurgh. bleaurgh。 Surely not? 当然不是吗?

It works, but I keep hoping I'll come across a NOT operator that would return everything that the first scope didn't, or a "Task.all - Task.started" kind of solution. 它有效,但我一直希望我会遇到一个NOT运算符,它会返回第一个作用域没有的东西,或者是一个“Task.all - Task.started”类型的解决方案。

我真的不认为有更好的解决方案,但这应该有很好的表现:

scope :not_started, where("ID NOT IN (SELECT task_id FROM time_logs)")

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM