I need to allow users to select tags for their posts, but from closed list (let's say only admin can add new tags, or they are predefined in other way). Each post can have many tags, so it needs to be multiselector. Unfortunately, after adding select2-rails tags weren't able to be saved in DB. How can I fix it? This doesn't work for me.
PostsController:
class PostsController < ApplicationController
before_action :find_post, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, only: [:new, :create, :edit, :update, :destroy]
def index
@posts = Post.page(params[:page]).per(10)
@tags = ActsAsTaggableOn::Tag.all
end
def new
@post = current_user.posts.new
@tags = ActsAsTaggableOn::Tag.all
end
def create
@post = current_user.posts.new(post_params)
if @post.save
redirect_to @post, notice: _('Post created')
else
render :new, notice: _('Something went wrong')
end
end
def show
@tags = ActsAsTaggableOn::Tag.all
end
def edit
authorize @post
@tags = ActsAsTaggableOn::Tag.all
end
def update
if @post.update(post_params)
redirect_to @post, notice: _('Post updated')
else
render :edit, notice: _('Something went wrong')
end
end
def destroy
authorize @post
if @post.destroy
redirect_to root_path, notice: _('Post deleted')
else
redirect_to @post, notice: _('Something went wrong')
end
end
private
def post_params
params.require(:post).permit(:title, :header, :content, :tag_list)
end
def find_post
@post = Post.friendly.find(params[:id])
end
end
Model:
class Post < ActiveRecord::Base
extend FriendlyId
friendly_id :title, use: :slugged
acts_as_ordered_taggable_on :tags
belongs_to :user
validates :title, :header, :content, presence: true
validates :title, uniqueness: true
end
View:
= simple_form_for @post do |f|
= f.input :title
= f.input :header
= f.input :content, input_html: { rows: 10 }
= f.input :tag_list, collection: @tags, input_html: { multiple: true, class: 'tags' }
= f.submit 'Save', class: 'btn btn-warning'
= link_to _('Back'), :back
application.js :
$(document).ready(function(){
$('.tags').select2({
placeholder: 'Click to select',
theme: 'bootstrap'
});
});
Well, it was much easier than I thought. All I had to do was permit tag_list
as an array tag_list: []
(default syntax :tag_list
won't save tags in DB, as it was described here and here), but only this change caused strange behaviour - saving tags ids instead of names. Second thing, which was not mentioned in above links, is to explicity define label and value method for selector (it is important, because on default it would pass ids of tags, not tags names, so it will create new tags with names identical to ids of previous tags).
In controller:
def post_params
params.require(:post).permit(:title, :header, :content, tag_list: [])
end
And in View:
= simple_form_for @post do |f|
= f.input :title
= f.input :header
= f.input :content, input_html: { rows: 10 }
= f.input :tag_list, collection: @tags, value_method: :name, label_method: :name, input_html: { multiple: true, class: 'tags' }
= f.submit 'Save', class: 'btn btn-warning'
= link_to _('Back'), :back