在我的rails应用程序中,我有两个模型:Team
和Post
,每个Post
可以有多个标签,每个Team
可以有许多Posts
。在我的团队的show动作中,我想展示一个select_tag
,用户可以用它从所有创建的标签中选择一个标签。当用户使用select_tag
选择一个标签时,我只想显示同样具有该标签的帖子。我使用Acts as Taggable On
gem.
我现在有这个(我使用HAML
):
= select_tag "tags", options_from_collection_for_select(@posts, "tags", :tag_list)
给我一个选择,看起来像这样:
[row 1] Tag 1
[row 2] Tag 1, Tag 2
[...]
我想要的是一个像这样的选择列表:
[row 1] Tag 1
[row 2] Tag 2
[row 3] Tag 3
[...]
我不怎么用select_tag
。有可能做我想做的事吗?那会是什么样子?
这有两个方面:显示正确的标记列表,并根据所选标记过滤帖子。
显示正确的标签列表
您想要创建一个<select>
元素,它只包含该团队帖子的标签。options_from_collection_for_select
接受3个参数:一个集合,一个获取每个选项值的方法,以及一个获取每个选项名称的方法。所以您应该将一组标签传递给options_from_collection_for_select
,而不是一组帖子。这组标签不应该是所有的标签-只有那些你的团队的帖子。幸运的是,acts_as_taggable_on
提供了这样做的方法,因此您可以构建标记云。
所以你要更新你的控制器,让它看起来像这样:
class TeamController < ApplicationController
def show
@team = Team.find params[:id]
@posts = team.posts
@team_tags = team.posts.tag_counts_on(:tags)
end
end
和更新你的视图使用@team_tags
代替:
= select_tag "tag", options_from_collection_for_select(@team_tags, 'id', 'name')
这将给您一个选择框,其中填充了特定于该团队的标签。
通过标签筛选文章
现在我们有了正确的标签列表,我们希望能够按标签过滤帖子。<select>
标签应该在一个表单中;您可以创建一个新的控制器动作来处理该表单,或者相应地调整您的show
方法。后者有点棘手,所以我在这里采用了这种方法。让我们更新您的视图,使假设更清晰:
= form_tag team_path(@team), method: 'get', class: 'tag_form' do
= select_tag "tag", options_from_collection_for_select(@team_tags, 'id', 'name', @tag)
= submit_tag "Filter posts"
并更新控制器动作来过滤帖子,如果我们有一个'tags'参数:
class TeamController < ApplicationController
def show
@team = Team.find params[:id]
@team_tags = team.posts.tag_counts_on(:tags)
if params[:tag]
@tag = Tag.find params[:tag]
@posts = team.posts.tagged_with @tag.name
else
@tag = nil
@posts = team.posts
end
end
end
请注意,我们将选择的标签作为实例变量@tag
传入,并在options_from_collection_for_select
中使用它来选择正确的标签,如果我们选择了一个过滤器。
锦上添花
您可以使用一点jQuery和CoffeeScript来隐藏提交按钮,并使过滤在用户选择新标签时自动发生,这将稍微改善您的用户体验。添加到app/assets/javascripts/teams.js.coffee
:
$ ->
$forms = $('.tag_form')
$forms.each (i, el) ->
$('input[type=submit]', el).hide()
$('select', el).on 'change', (ev) ->
$(el).submit()
通过查找所有具有tag_form
类的元素,删除每个元素中的所有<input type="submit">
元素,然后监听这些表单中选择元素的更改事件。