JanGaJan.com

Is fun? JOY!

Rails4でacts-as-taggable-on Gemを使う

ユーザーに紐づくタスクに、タグ付けをするという機能を実現する方法です。
acts-as-taggable-onというgemを利用することで簡単(苦戦した…)にタグ機能は実現できるそうです。
なんとかできたっぽい…

環境は、こんな感じです。

  • Rails 4.1.6
  • ruby 2.1.2p95
  • acts-as-taggable-on 3.4.2

GithubのREADMEを参考にしました

Model

そもそもリレーション関係の設定でハマりましたが、これで良さそうです。
関係としてはuser 1-n taskとなり、taskにタグを設定します。
タグは、userごとに別々に管理します。

app/models/user.rb
1
2
3
4
5
class User < ActiveRecord::Base
  acts_as_tagger
  has_many :tasks, dependent: :destroy
  ...
end
app/models/task.rb
1
2
3
4
5
class Task < ActiveRecord::Base
  acts_as_taggable
  belongs_to :user
  ...
end

View

タグのところだけピックアップ。
(簡単なサンプル作れば良かった)
画面表示するController内のメソッドで、選択可能なタグを@user_tagsに入れています。
タグは複数選択可能にするため、checkboxを利用しました。
checkbox生成でrailsの仕組みを利用しようとしたのですが、以下の2点を実現しようとしてうまいやり方が見つからなかった…

  • labelでクリック連携
  • valueの値をタグの名前

form_for内に記述します。

app/views/tasks/_form.html.haml
1
2
3
4
5
6
7
/ @user_tagsはcontrollerで配列で設定 ex) => ["tag1", "tag2"]
- @user_tags.each do |tag|
  / tagを複数選択可能にするため、checkboxを利用
  %input{id:"tag-#{tag}" ,name:'task[tag_list][]', type:'checkbox',value:"#{tag}"}
  %label{for:"tag-#{tag}"}
    %span.task-tag
      = "#{tag}"

タグ付けよりもrailsでcheckbox使うところに時間とられた…宿題ですね。

Controller

リクエストのtask[tag_list]という値の中に、タグが含まれます。
permitで、配列をチェックしたい場合は、tag_list: []と指定してあげる必要がありました。

app/controllers/tasks_controller.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class TasksController < ApplicationController
  ...
  def create
    # current_user => User.find(session[:user_id])
    @task = current_user.tasks.build(task_params)
    @task.user = current_user
    # tagの設定処理 :withには'tag1, tag2'という形式の文字列を設定することでタグを登録できる
    current_user.tag(@task, :with => @task.tag_list.join(', '), :on => :tags)
    if @task.save
      # 成功処理
    else
      # 失敗処理
    end
  end
  ...

  private
  def task_params
    params.require(:task).permit(
      # tag_list: []を指定することで、checkboxの複数の値を配列にして、tag_listに設定可能になる
      :id, :name, :deadline, tag_list: []
    )
  end
end

もしかしたらもっといいやり方があるかもしれません。
気をつける場所はいくつかあるものの、意外と簡単かも。

補足

ユーザーが設定しているタグの一覧を取得する

1
2
@user_tags = current_user.owned_tag_list
=> ["tag1", "tag2"]

Comments