如何将关系计数过滤的结果返回到RAILS中的视图?

met*_*ord 5 ruby-on-rails ruby-on-rails-3

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

我想要的是让控制器中的索引操作仅返回满足此条件的结果.

我试过这个:

#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
Run Code Online (Sandbox Code Playgroud)

谢谢.

MrY*_*iji 11

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

Project.where(:is_available?)
Run Code Online (Sandbox Code Playgroud)

在where方法中,您必须传递参数哈希或一串(SQL)条件.你在这里要做的是选择方法is_available的所有项目?返回true.问题是该方法is_available?是一个Ruby方法(在您的模型中定义).由于它是一个Ruby函数,因此无法在SQL中调用它.where方法期望SQL条件,而不是ruby代码.

(感谢@benzado的评论)


要解决您的问题:

这是您正在寻找的,仅在db级别计算:

Project.joins(:workers)
       .select('projects.*')
       .group('projects.id')
       .having('COUNT(workers.*) > 2')
Run Code Online (Sandbox Code Playgroud)

这应该返回至少有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
Run Code Online (Sandbox Code Playgroud)

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

#in your controller
def index
   @projects = Project.having_more_than_x_workers(2)
end
Run Code Online (Sandbox Code Playgroud)