В моем приложении блога есть записи, и каждый пост может иметь теги. Когда пользователь находится в новой или редактируемой форме публикации, у него в настоящее время есть средства для выбора или отмены выбора тегов для связи с публикацией. Между моделями записей и тегов существует отношение многие ко многим, и я использую bootstrap, bootstrap_form и bootstrap -select. Это все работает, казалось бы, очень хорошо. Проблема в том, что когда пользователь назначает теги для своего сообщения, эти теги в настоящее время уже должны существовать (в противном случае ему придется прервать публикацию и go добавить теги ... плохой пользовательский опыт). Я пытаюсь придумать способ дать пользователю возможность создавать новые теги и / или выбирать уже существующие теги и применять их к сообщению, все в одной форме сообщения в поле collection_select, все одновременно.
По-видимому, я задаю неправильные вопросы в Google ... разве это не является распространенной потребностью, уже решена?
Я прошу указаний по предоставлению "добавить новый тег" функциональность для другого функционального поля collection_select. Как лучше go об этом?
Контроллер сообщений:
class PostsController < ApplicationController
before_action :set_post, only: %i[edit update interim destroy]
# GET /posts
# GET /posts.json
def index
if user_signed_in? && current_user.admin_role
if params[:tag]
@posts = Post.tagged_with(params[:tag]).all.order('updated_at DESC').page params[:page]
else
@posts = Post.all.order('updated_at DESC').page params[:page]
end
else
if params[:tag]
@posts = Post.tagged_with(params[:tag]).where(published: true).order('updated_at DESC').page params[:page]
else
@posts = Post.where(published: true).order('updated_at DESC').page params[:page]
end
end
end
# GET /posts/new
def new
@post = current_user.posts.build
@categories = Category.pluck(:name, :id)
end
# GET /posts/1/edit
def edit
@categories = Category.pluck(:name, :id)
@cat = @post.category_id
end
# POST /posts
# POST /posts.json
def create
@post = current_user.posts.create(post_params)
respond_to do |format|
if @post.save
if params[:interim]
format.html { redirect_to edit_post_path(@post), notice: 'Post was successfully created.' }
format.json { redirect_to edit_post_path(@post), status: :created, location: @post, notice: 'Post was successfully created.' }
elsif params[:complete]
format.html { redirect_to @post, notice: 'Post was successfully created.' }
format.json { render :show, status: :created, location: @post }
end
else
format.html { render :new }
format.json { render json: @post.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /posts/1
# PATCH/PUT /posts/1.json
def update
respond_to do |format|
if @post.update(post_params)
if params[:interim]
format.html { redirect_to edit_post_path(@post), notice: 'Post was successfully updated.' }
format.json { redirect_to edit_post_path(@post), status: :ok, location: @post, notice: 'Post was successfully updated.' }
elsif params[:complete]
format.html { redirect_to @post, notice: 'Post was successfully updated.' }
format.json { render :show, status: :ok, location: @post }
end
else
format.html { render :edit }
format.json { render json: @post.errors, status: :unprocessable_entity }
end
end
end
# DELETE /posts/1
# DELETE /posts/1.json
def destroy
@post.destroy
respond_to do |format|
format.html { redirect_to posts_url, notice: 'Post was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def set_post
@post = Post.find(params[:id])
end
def post_params
params.require(:post).permit(:title, :content, :user_id, :published, :category_id, :tag_list, :tag, { tag_ids: [] }, :tag_ids,
comment_attributes: [:id, :title, :user_id, :content, :post_id, :parent_id, :ancestry, :commentable, :commentable_id, :commentable_type])
end
end
Нет контроллера тегов (пока не требуется)
Модель сообщения:
class Post < ApplicationRecord
has_many :taggings
has_many :tags, through: :taggings
has_rich_text :content
include PgSearch::Model
multisearchable :against => [:title, :content]
def self.published(post)
post.published
end
def self.tagged_with(name)
Tag.find_by!(name: name).posts
end
def self.tag_counts
Tag.select('tags.*, count(taggings.tag_id) as count').joins(:taggings).group('taggings.tag_id')
end
def tag_list
tags.map(&:name).join(', ')
end
def tag_list=(names)
self.tags = names.split(',').map do |n|
Tag.where(name: n.strip).first_or_create!
end
end
end
Модель тега:
class Tag < ApplicationRecord
has_many :taggings
has_many :posts, through: :taggings
end
Модель тегирования:
class Tagging < ApplicationRecord
belongs_to :tag
belongs_to :post
end
Частичная форма публикации (фактические новые и редактируемые представления ничего не делают, кроме как визуализируют эту форму):
<%= bootstrap_form_for @post, local: true, html: { class: 'form-horizontal' } do |f| %>
<%= f.text_field :title %>
<%= f.rich_text_area :content, control_class: 'trix-content-edit' %>
<%= f.collection_select :category_id, Category.all, :id, :name %>
<%= f.form_group :published, label: { text: "Publication Status" } do %>
<%= f.radio_button :published, true, label: "Published" %>
<%= f.radio_button :published, false, label: "Draft" %>
<% end %>
<%= f.collection_select :tag_ids, Tag.order(:name), :id, :name, {label: 'Tags', include_blank: true}, {class: 'selectpicker show-tick', multiple: 'multiple', title: 'Make your selection...', 'data-live-search': 'true', 'data-actions-box': 'true'} %>
<br><br>
<%= f.submit "Save and Resume Editing", name: "interim", class: "btn btn-primary" %>
<%= f.submit "Save and Quit", name: "complete", class: "btn btn-primary" %>
<br><br>
<% end %>
В настоящее время нет форм для тега.