Rails 4 - 使用Acts作为Taggable gem并使用select_tag从集合中选择标记

时间:2014-06-29 20:23:22

标签: ruby-on-rails ruby acts-as-taggable-on html-select

在我的rails应用中,我有两个模型:TeamPost,每个Post可以有多个标记,每个Team可以有多个Posts 。在我的团队的节目动作中,我想提供一个select_tag,用户可以使用该select_tag为其帖子选择所有已创建标签的一个标签。当用户使用Acts as Taggable On选择标记时,我只想显示也包含该标记的帖子。我使用HAML gem。

我目前拥有的是这个(我使用= 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

我还没有使用{{1}}。有可能以某种方式做我想做的事吗?那怎么样?

1 个答案:

答案 0 :(得分:2)

这有两个方面:显示正确的标签列表,并按所选标签过滤帖子。

显示正确的标签列表

您想要创建一个<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"

如果我们有一个&#39;标签,请更新控制器操作以过滤帖子。参数:

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">元素,然后在这些表单中的select元素上侦听change events