J'ai implémenté une fonction de recherche de balises dans une application que je suis en train de développer, je vais donc la résumer ici sous forme de mémorandum. Je n'ai pas osé utiliser des gemmes, j'ai donc pu comprendre l'essentiel.
【environnement】
Lorsque vous entrez une balise dans le nouveau formulaire de publication, la balise saisie sera reflétée dans la liste des publications et la barre latérale. C'est une fonction qui vous permet d'affiner les publications avec cette balise en cliquant sur la balise reflétée dans la barre latérale.
Entrez une balise à partir du formulaire de publication
La balise saisie dans ↑ est affichée dans la barre latérale et dans la liste des articles En cliquant sur la balise affichée dans la barre latérale, vous pouvez restreindre les articles qui incluent cette balise. (Puisqu'il s'agit d'un échantillon, un seul cas)
Je parlerai en supposant que le modèle Item et le modèle Post ont déjà été créés. (Ici, il s'agit d'un modèle d'article. Veuillez le remplacer vous-même.)
Tout d'abord, créez le modèle Tag et le modèle Tagmap comme d'habitude.
$ rails g model Tagmap item:references tag:references
$ rails g model tag tag_name:string
Puisque Tagmap est associé au modèle Item et au modèle Tag, les références sont attachées au type de données. Si vous faites cela, Rails fera du bon travail, donc si vous voulez en savoir plus, veuillez google.
class CreateTagmaps < ActiveRecord::Migration[6.0]
def change
create_table :tagmaps do |t|
t.references :item, null: false, foreign_key: true
t.references :tag, null: false, foreign_key: true
t.timestamps
end
end
end
Ceci est indexé.
class CreateTags < ActiveRecord::Migration[6.0]
def change
create_table :tags do |t|
t.string :tag_name, null: false
t.timestamps
end
add_index :tags, :tag_name, unique: true
end
end
Puis migrez comme d'habitude.
$ rails db:migrate
item.rb
has_many :tagmaps, dependent: :destroy
has_many :tags, through: :tagmaps
tag.rb
class Tag < ApplicationRecord
has_many :tagmaps, dependent: :destroy
has_many :items, through: :tagmaps
end
tag est également associé aux tagmaps. ↑
En utilisant approfondie, vous pouvez accéder aux éléments via des tagmaps.
tagmap.rb
class Tagmap < ApplicationRecord
belongs_to :item
belongs_to :tag
end
↑ Rails décrira automatiquement la pièce appart_to dans le formulaire des références!
items_controller.rb
def index
if params[:search].present?
items = Item.items_serach(params[:search])
elsif params[:tag_id].present?
@tag = Tag.find(params[:tag_id])
items = @tag.items.order(created_at: :desc)
else
items = Item.all.order(created_at: :desc)
end
@tag_lists = Tag.all
@items = Kaminari.paginate_array(items).page(params[:page]).per(10)
end
Je vais expliquer le code ici. L'action d'index utilise l'instruction if pour séparer les trois modèles et la valeur affectée à la variable d'élément est modifiée en fonction de ce résultat.
items_controller
def create
@item = Item.new(item_params)
tag_list = params[:item][:tag_name].split(nil)
@item.image.attach(params[:item][:image])
@item.user_id = current_user.id
if @item.save
@item.save_items(tag_list)
redirect_to items_path
else
flash.now[:alert] = 'La publication a échoué'
render 'new'
end
end
Le point dans l'action de création du contrôleur d'éléments est la partie affectation à la variable tag_list sur la troisième ligne. ruby's ** String # split ** divise la chaîne par le séparateur spécifié par le premier argument (nil cette fois) et renvoie le résultat sous forme de tableau de chaînes. Si vous spécifiez un bloc, au lieu de renvoyer un tableau, le bloc est appelé avec une chaîne divisée. De plus, si vous envoyez des données de balise séparées par un caractère vierge de 1 octet «» du formulaire, elles seront séparées par une chaîne de caractères vide après avoir supprimé les espaces de début et de fin. Cette fois, nous allons l'utiliser.
Les paramètres envoyés depuis le nouveau formulaire de publication sont séparés par un caractère vide (nil), arrangés et enregistrés dans la base de données à l'aide de la méthode ** save_items ** définie dans la classe Item. (Demandez à l'utilisateur de saisir des balises sous la forme séparées par des espaces.)
item.rb
#Recherche floue pour la méthode de recherche, le titre et le contenu
def self.items_serach(search)
Item.where(['title LIKE ? OR content LIKE ?', "%#{search}%", "%#{search}%"])
end
def save_items(tags)
current_tags = self.tags.pluck(:tag_name) unless self.tags.nil?
old_tags = current_tags - tags
new_tags = tags - current_tags
# Destroy
old_tags.each do |old_name|
self.tags.delete Tag.find_by(tag_name:old_name)
end
# Create
new_tags.each do |new_name|
item_tag = Tag.find_or_create_by(tag_name:new_name)
self.tags << item_tag
end
end
↑ Lors de la sauvegarde des données de tag, s'il existe même un seul nom de tag parmi les données de tag envoyées depuis le formulaire, utilisez la méthode de prélèvement de la colonne tag_name de la table tags pour extraire toutes les données une fois et définissez-le sur current_tags. Remplacer. (Si tout est nouveau, ce sera nul.) Vous pouvez définir d'anciennes balises (old_tags) en soustrayant le tableau de balises transmises par le contrôleur en tant qu'argument de current_tags, qui est un ensemble de données de balises qui existe déjà. C'est parce que ruby peut extraire des éléments communs en soustrayant un tableau.
** Exemple concret: **
tags(tag_list = params[:item][:tag_name].split(nil)Arrangement qui vient du contrôleur) = ["Rails" "ruby" "React"]
current_tags(Données de point qui existent actuellement dans la base de données) = ["Rails" "ruby" "Vue.js"]
old_tags = ["Rails" "ruby" "Vue.js" "Docker"] - ["Rails" "ruby" "React"]
old_tags = ["Rails" "ruby"]
↑ L'élément commun des deux tableaux reste (les anciennes balises déjà existantes peuvent être calculées)
** Extrait de la description du nouveau formulaire de publication (UIkit est utilisé pour le framework CSS) **
.uk-form.new_post_form
= form_with(model: [@tag,@item], local: true) do |f|
.uk-margin-small
= f.text_field :title, placeholder: "Entrez un titre (jusqu'à 35 caractères)", class: 'uk-input'
.uk-margin-small
= f.text_field :tag_name, placeholder: "Saisissez jusqu'à 5 balises liées à la technologie de programmation et aux exigences de recrutement, séparées par des espaces(Exemple de rubis Rails)", class: 'uk-input uk-form-small'
** Extrait de vue partielle de la barre latérale **
haml:index.html.haml
%li.search_friend_by_categorize
.uk-text-secondary.uk-text-bold
Recherche par tag
%ul.uk-flex.uk-flex-wrap
- @tag_lists.each do |list|
%li
= link_to list.tag_name, items_path(tag_id: list.id), class: 'tag_list'
Affichage des balises dans une liste d'articles publiés
haml:index.html.haml
%p.tag_list_box
- item.tags.each do |tag|
= link_to "##{tag.tag_name}", items_path(tag), class: 'smaller tag_list'
La vue ressemble à ceci. Ce n'est pas particulièrement difficile!
Je l'ai écrit à la hâte, il peut donc y avoir des erreurs. Si vous avez des suggestions ou des impressions, je vous serais reconnaissant de bien vouloir commenter! !!
Recommended Posts