5

基本上,我在模型上定义了一个属性,它根据另一个表中的值返回 true 或 false。

我想要的是让我的 Index 操作在控制器中只返回那些满足这个条件的结果。

我试过这个:

#What I've tried on my Controller:
def index
   @projects = Project.where(:is_available?)
end

#What I've on my Controller:
def index
   @projects = Project.all
end

#What I've on my Model:
def is_available?
   workers.count<2 ? true : false
end

谢谢。

4

2 回答 2

11

为什么你的代码不起作用?

Project.where(:is_available?)

在 where 方法中,您必须传递参数散列或 (SQL) 条件字符串。您在这里尝试做的是选择方法 is_available 的所有项目?返回真。问题是该方法is_available?是一个 Ruby 方法(在您的模型中定义)。由于它是一个 Ruby 函数,因此不能在 SQL 内部调用它。where 方法需要 SQL 条件,而不是 ruby​​ 代码。

(感谢@benzado 的评论)


要解决您的问题:

这就是您要查找的内容,仅在 db 级别计算:

Project.joins(:workers)
       .select('projects.*')
       .group('projects.id')
       .having('COUNT(workers.*) > 2')

这应该返回至少有 2 名工作人员关联的所有项目。


如何改善这一点?

您可以设置此查询的范围,以便在任何地方轻松使用它:

#in your model
class Project < ActiveRecord::Base
  scope :having_more_than_x_workers, lambda do |workers_count|
    joins(:workers).select('projects.*').group('projects.id').having("COUNT(workers.*) > #{workers_count || 0}")
  end

end

要使用它,例如在您的控制器中:

#in your controller
def index
   @projects = Project.having_more_than_x_workers(2)
end
于 2013-02-11T18:13:11.467 回答
3

Rails 查询方法(如where)通过创建数据库查询来工作;换句话说,where除非属性确实存在于您的数据模型中,否则您不能使用其中的属性。否则,数据库不知道它,无法为您执行过滤。

在您的情况下,您应该在Project执行“可用?”的类上定义一个方法。查询,因此您可以使用您的方法代替where. 你可以这样做:

class Project < ActiveRecord::Base
  def self.available_projects
     where('workers_count > 2')
  end
end

有关如何编写查询或如何将其定义为命名范围的详细信息,请参阅MrYoshiji 的答案。

于 2013-02-11T18:21:14.917 回答