Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 如何检查联接上的条件?_Ruby On Rails_Ruby - Fatal编程技术网

Ruby on rails 如何检查联接上的条件?

Ruby on rails 如何检查联接上的条件?,ruby-on-rails,ruby,Ruby On Rails,Ruby,我正在尝试在我的小部件搜索中为用户设置过滤。我希望他们能够点击一些标签,并且只返回应用了正确标签的结果 各表的设置如下: 小部件有许多标记,通过标记 通过标记,标记有许多小部件 标记是一个联接表 在我的控制器中,我迭代小部件,并检查标记连接的条件: @widgets = Widget.all @current_tags = [1,5,7,10,15] # Passed in from params @current_tags.each do |t| @widgets = @widgets

我正在尝试在我的小部件搜索中为用户设置过滤。我希望他们能够点击一些标签,并且只返回应用了正确标签的结果

各表的设置如下:

  • 小部件有许多标记,通过标记
  • 通过标记,标记有许多小部件
  • 标记是一个联接表
在我的控制器中,我迭代小部件,并检查标记连接的条件:

@widgets = Widget.all
@current_tags = [1,5,7,10,15] # Passed in from params
@current_tags.each do |t|
  @widgets = @widgets.joins(:tags).where("tags.id=?", t)
end
我只希望返回具有所有这些标记的小部件

这对于一个标记似乎很好,但一旦单击另一个标记,一旦选择了多个标记,就会产生问题。例如,这将按预期返回小部件1:

# Widget 1 is joined to tags 1,5,7,9
@current_tags = [5]
这不会返回任何结果,即使它应该返回小部件1:

# Widget 1 has tags 1,5,7,9
@current_tags = [5,7]

我在检查标记和小部件之间的连接时是否做错了什么?

您可能对gem上作为标记的行为感兴趣,但对于您的问题,这是一个棘手的问题!当然,您可以使用一个强大的Rails习惯用法,但这里有一个蛮力方法:

unless @current_tags.empty?
  # set initial state to widgets that match the first tag
  @widgets = @widgets.joins(:tags).where("tags.id=?", @current_tags.shift)
  @current_tags.each do |t|
    # then keep only widgets in initial state AND the next tag
    @widgets &= @widgets.joins(:tags).where("tags.id=?", t)
  end
end

您希望将查询更改为:

@current_tags = [1,5,7,10,15]
@widgets = Widget.joins(:tags).where("tags.id IN (?)", @current_tags)

它正在按用户选择的标签查找小部件。

如果每个小部件仅链接一次标签,您可以执行以下操作:

@widgets=
小装置
.select('widgets.id')
.joins(“taggings.widget上的内部连接标记\u id=widgets.id”)
.where(tag_id:@current_tags)
.group(“widgets.id”)
.具有(“计数(*)={@current_tags.length}”)
编写此代码的另一种方法:

widget\u id=
标记
.选择(:小部件\u id)
.where(tag_id:@current_tags)
.group(:小部件\u id)
.具有(“计数(*)={@current_tags.length}”)
@widgets=Widget.where(id:Widget\u id)

一种有点尴尬的方法是,使您的循环链
位于顶部,如下所示:

@widgets = Widget.all
@current_tags = [1,5,7,10,15]
@current_tags.each do |t|
  @widgets = @widgets.where(
    widget.taggings.where(tag_id: t).exists # << a bit of Arel for ya
  )
end
@widgets=Widget.all
@当前_标签=[1,5,7,10,15]
@当前|u标记。每个标记都有| t|
@widgets=@widgets.where(

widget.taggings.where(tag_id:t).exists#这会给您一个OR,海报要求提供AND:“我只希望返回具有所有这些标记的widget。”