__ ・ Implémentez une fonction qui vous permet de marquer vos propres messages. __ __ ・ Implémentez une fonction qui vous permet d'affiner la recherche en utilisant les balises attachées au message. __
·environnement Série Ruby 2.6 Série Rails 5.2
·Bibliothèque Slim
__ ・ Modèle d'application Rails de l'environnement ci-dessus __ Procédure pour configurer l'application Rails et installer l'appareil et Slim
__ ↓ Image terminée ↓ __
-User: Post
= L'utilisateur a beaucoup de messages pour chaque personne, donc il y a une relation `1 to many
`.
- Post: Tag
=
Un message a de nombreux tags ``, `` `` Un tag a aussi de nombreux messages
, donc`
Relation plusieurs-à-plusieurs.
→ Une table intermédiaire est requise en raison de la relation plusieurs-à-plusieurs =
TagMap```
→ Une table intermédiaire est une table qui ne stocke que les clés externes (post_id et tag_id) de la table many-to-many (table post et tag dans ce cas)
, et gère les tables de l'autre uniquement avec la clé externe. Rend le possible.
$ rails g devise User //Créer un modèle utilisateur à partir de l'appareil $ rails g migration add_columns_to_users name:string //colonne de nom ajoutée $ rails g model Post content:string user:references //Création de modèle après $ rails g model Tag tag_name:string //Création de modèles de balises $ rails g model TagMap post:references tag:references //Création de modèles TagMap
>> -Puisque les colonnes ne peuvent pas être ajoutées au modèle utilisateur créé par appareil, lors de l'ajout d'une colonne de nom, il est nécessaire de l'ajouter en tant que nouvelle migration.
- <Nom de la table>: Une clé externe est définie pour la table spécifiée dans les références. (Obligatoire)
### 3. Vérifiez le fichier de migration créé
> #### 3-1. Fichier de migration des utilisateurs
>>```db/migrate/[timestamps]_create_devise_users.rb
class DeviseCreateUsers < ActiveRecord::Migration[5.2]
def change
create_table :users do |t|
## Database authenticatable
t.string :email, null: false, default: ""
t.string :encrypted_password, null: false, default: ""
#<réduction>
end
end
3-2. Ajouter une colonne de nom au tableau des utilisateurs
class AddUsernameToUsers < ActiveRecord::Migration[5.2] def change add_column :users, :name, :string end end
> Fichier de migration #### 3-3.posts
>>```ruby:db/migrate/[timestamps]_create_posts.rb
class CreatePosts < ActiveRecord::Migration[5.2]
def change
create_table :posts do |t|
t.text :content
t.references :user, foreign_key: true
t.timestamps
end
end
end
Fichier de migration #### 3-4.tags
class CreatePostTags < ActiveRecord::Migration[5.2] def change create_table :post_tags do |t| t.string :tag_name t.timestamps end end end
> Fichier de migration #### 3-5.tag_maps
>>```ruby:db/migrate/[timestamps]_create_tag_maps.rb
class CreatePostTagMaps < ActiveRecord::Migration[5.2]
def change
create_table :tag_maps do |t|
t.references :post, foreign_key: true
t.references :tag, foreign_key: true
t.timestamps
end
end
end
4-1. Fichier de modèle utilisateur
class User < ApplicationRecord
devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable has_many :posts, dependent: :destroy end
>> ・ `dependant :: destroy`: Une option qui peut être attachée à la classe parent afin que la classe enfant puisse être supprimée lorsque la classe parent est supprimée.
> #### 4-2. Fichier modèle de publication
>>```ruby:app/models/user.rb
class Post < ApplicationRecord
belongs_to :user
has_many :tag_maps, dependent: :destroy
has_many :tags, through: :tag_maps
end
__ ・ L'option
through est utilisée pour s'associer à la table des tags via la table tag_maps. En faisant cela, vous pouvez obtenir les balises associées à Post en utilisant
Post.tags`. Cela peut être utilisé lorsque vous souhaitez attacher l'étiquette à la publication et l'afficher sur l'écran des détails de la publication. __
__ ・ Lors de l'utilisation de l'option through, il faut d'abord l'associer à la table intermédiaire. __
__- En ajoutant l'option dependant :: destroy à la table intermédiaire, la relation entre Post et Tag sera supprimée en même temps que Post est supprimé. __
4-4.Fichier modèle de balise
class Tag < ApplicationRecord has_many :tag_maps, dependent: :destroy, foreign_key: 'tag_id' has_many :posts, through: :tag_maps end
>> __` ・ Après avoir été associé à la table tag_maps, il est associé à la table posts via tag_maps`. Vous pouvez obtenir les messages associés aux balises avec `Tag.posts`. Cela peut être utilisé lorsque vous souhaitez rechercher des articles avec une balise spécifique, telle que "sports". __
> #### 4-5. Fichier modèle TagMap
>>```ruby:app/models/tag_map.rub
class PostTagMap < ApplicationRecord
belongs_to :post
belongs_to :tag
validates :post_id, presence: true
validates :tag_id, presence: true
end
__ ・ Puisqu'il appartient à plusieurs messages et à plusieurs balises, il est associé à appartient_to. __
__ ・ Lors de la construction de la relation entre Post et Tag, il est absolu qu'il existe deux clés externes, alors validez-les. __
Rails.application.routes.draw do devise_for :users root to: 'posts#index' resources :posts end
>> __ ・ À ce stade, pour le moment, définissez le routage fourni par le dispositif, le chemin racine et le chemin vers la ressource des messages. __
## Tout d'abord, implémentez à partir de la fonction qui peut baliser les messages
### 6. Créez un contrôleur
> #### 6-1. Écrivez le code pour créer des messages et des balises dans l'action de création du contrôleur de messages.
>>```ruby:app/controllers/posts_controller.rb
class PostsController < ApplicationController
def create
@post = current_user.posts.new(post_params)
tag_list = params[:post][:tag_name].split(nil)
if @post.save
@post.save_tag(tag_list)
redirect_back(fallback_location: root_path)
else
redirect_back(fallback_location: root_path)
end
end
private
def post_params
params.require(:post).permit(:content)
end
end
__ Décomposons le code ci-dessus. __
@post = current_user.posts.new(post_params)
>> __ · En définissant `current_user.posts`, l'identifiant de l'utilisateur connecté sera sauvegardé dans le user_id de la table des messages, mais si ʻUser et Post ne sont pas associés, une erreur se produira. Masu`. Les paramètres forts sont utilisés comme argument. __
>>```ruby:Récupérez les tags qui ont été envoyés
tag_list = params[:post][:tag_name].split(nil)
__ ・
params [: post] [: tag_name]
: Depuis le formulaire, référez-vous à l'objet @post et envoyez le nom de la balise ensemble, alors récupérez-le sous cette forme. Par exemple, il est envoyé comme "" sports "" étude "" travail "". __
__ ・
.split (nil)
: Dispose les valeurs envoyées séparées par des espaces. Dans l'exemple ci-dessus, cela ressemble à ["sports" "étude" "travail"]. La raison de l'organisation est que lors de l'enregistrement ultérieur de cette valeur dans la base de données, il est nécessaire de la récupérer un par un par un traitement itératif. __
@post.save_tag(tag_list)
__ ・ `Processus pour enregistrer le tableau de balises acquises précédemment dans la base de données`. La définition de save_tag qui effectue le traitement sera décrite plus loin. __
> #### 6-2. Écrivez le code pour obtenir le message et la balise dans l'action d'indexation.
>>```ruby:app/controllers/posts_controller.rb
def index
@tag_list = Tag.all #Get all pour afficher la liste des balises dans la vue.
@posts = Post.all #Obtenez tout pour afficher la liste des articles dans la vue.
@post = current_user.posts.new #Voir le formulaire_Utilisé pour le modèle avec.
end
def show @post = Post.find(params[:id]) #Obtenez le message sur lequel vous avez cliqué. @post_tags = @post.tags #Obtenez la balise associée au post sur lequel vous avez cliqué. end
### 7. Définissez la méthode d'instance save_tag dans le fichier de modèle Post.
> __ ・ Définissez le contenu de la méthode d'instance save_tag décrite plus haut dans l'action de création. __
>```ruby:app/models/post.rb
class Post < ApplicationRecord
#<réduction>
def save_tag(sent_tags)
current_tags = self.tags.pluck(:tag_name) unless self.tags.nil?
old_tags = current_tags - sent_tags
new_tags = sent_tags - current_tags
old_tags.each do |old|
self.post_tags.delete PostTag.find_by(post_tag_name: old)
end
new_tags.each do |new|
new_post_tag = PostTag.find_or_create_by(post_tag_name: new)
self.post_tags << new_post_tag
end
end
end
current_tags = self.tags.pluck(:tag_name) unless self.tags.nil?
> __ ・ Si une balise associée à @post a été enregistrée par l'action de création plus tôt, récupérez tous les "noms de balises sous forme de tableau". __
>```ruby:Obtenir d'anciennes balises
old_tags = current_tags - sent_tags
__ ・ Old_tags sont les tags qui existent dans le @post actuellement acquis, à l'exclusion des tags envoyés. __
new_tags = sent_tags - current_tags
> __ ・ Les nouveaux_tags sont les balises qui sont envoyées, à l'exclusion des balises qui existent actuellement. __
>```ruby:Supprimer les anciennes balises
old_tags.each do |old|
self.tags.delete Tag.find_by(tag_name: old)
end
__- Supprimer les anciennes balises. __
new_tags.each do |new| new_post_tag = Tag.find_or_create_by(tag_name: new) self.post_tags << new_post_tag end
> __- Enregistrez la nouvelle balise dans la base de données. __
> __ ・ La raison pour laquelle il faut du temps pour acquérir et supprimer les anciennes balises et les nouvelles balises comme décrit ci-dessus, au lieu de simplement acquérir et enregistrer les balises une par une, est, par exemple, lors de l'édition d'un article. Parce qu'il faut que ça marche.
Cependant, je suis désolé, j'omettrai cette fois l'implémentation de la fonction d'édition. __
### 8. Créez une vue.
> #### 8-1. Créez une vue de la liste des articles.
>>```ruby:app/views/posts/index.html.slim
liste de balises h3
- @tag_list.each do |list|
span
= link_to list.tag_name, tag_posts_path(tag_id: list.id)
= "(#{list.posts.count})"
hr
poteau h3
= form_with(model: @post, url: posts_path, local: true) do |f|
= f.text_area :content
br
= "Vous pouvez ajouter plusieurs balises en entrant un espace."
= "Exemple: musique, sports littéraires"
= f.text_field :tag_name
br
= f.submit
hr
Liste des messages h3
- @posts.each do |post|
= link_to post.content, post
Décomposons le code ci-dessus.
>> __ ・ Toutes les balises acquises par l'action d'index sont affichées, et ʻun lien vers le chemin pour afficher les messages liés à cette balise est fourni`. Cliquer sur ce lien vous amènera à afficher les messages associés à cette «balise». La définition du routage pour obtenir ce lien et la création de l'action seront décrites plus loin. __
>> __ ・ `" (# {list.posts.count}) "` compte et affiche le nombre de messages qui ont actuellement cette balise. __
>>```ruby:Nouveau formulaire de message (peut être étiqueté)
= form_with(model: @post, url: posts_path, local: true) do |f|
= f.text_area :content
br
= "Vous pouvez ajouter plusieurs balises en entrant un espace."
= "Exemple: musique, sports littéraires"
= f.text_field :tag_name
br
= f.submit
__ ・
= f.text_field: tag_name
: En écrivant cette ligne, les balises saisies dans le formulaire seront envoyées à l'action de création en tant que paramètres params [: post] [: tag_name]. .. __
8-2. Créez une vue de la page de détail de l'article.
Détails de l'article h1 p= @post.content br = "marque: "
>> __ ・ La partie qui affiche l'étiquette est la même que la méthode décrite dans l'affichage de la liste. Dans ce cas, la partie appelée «tag associé à un article spécifique» est différente. __
__ · Ceci termine l'implémentation de la fonction qui vous permet de baliser les messages. __
## Mettre en œuvre une fonction pour affiner et afficher les articles par balises
### 1. Ajoutez un routage.
>```ruby:config/routes.rb
Rails.application.routes.draw do
devise_for :users
root to: 'posts#index'
resources :posts
#Acheminement vers des actions pour afficher les publications filtrées par balises
resources :tags do
get 'posts', to: 'posts#search'
end
end
__ ・ En imbriquant, vous pouvez utiliser le chemin pour passer à la page de publication associée à une balise spécifique appelée
tag_posts_path (tag_id: tag.id)
comme décrit précédemment. __
def search @tag_list = Tag.all #Obtenir toutes les balises pour afficher toutes les balises sur cette page d'affichage de la liste de publications @tag = Tag.find(params[:tag_id]) #Obtenez le tag cliqué @posts = @tag.posts.all #Afficher tous les messages associés à la balise cliquée end
### 3. Créez une vue de page qui affiche une liste de publications restreinte par des balises.
> __ ・ Commencez par créer un fichier search.html.slim dans le répertoire app / views / posts. __
>```ruby:app/views/posts/search.html.slim
Liste des messages h2
#Liste de balises
- @tag_list.each do |list|
span
= link_to list.tag_name, tag_posts_path(post_tag_id: list.id)
= "(#{list.posts.count})"
br
#Liste de messages réduite par tag
= "La balise est ─"
strong= "#{@tag.tag_name}"
= "─ Liste des messages"
br
- @posts.each do |post|
= link_to post.content, post
br
= link_to 'domicile', root_path
__ ・ La partie liste de balises est la même que la partie index. __
= "La balise est ─" strong= "#{@tag.tag_name}" = "─ Liste des messages"
> __ ・ Dans cette partie, la balise correspondante est affichée afin que vous puissiez voir quel type de balise a été réduit. __
__ · Ceci termine l'implémentation de la fonction d'affichage des publications réduites par des balises. Comme vous pouvez le voir, il y a des chevauchements dans la vue, donc si vous partialisez et refactorisez ces parties, la vue sera plus propre et meilleure. __
## Article très utile
[Notes sur l'implémentation de la fonction de balise dans Rails sans utiliser de gem](https://qiita.com/tobita0000/items/daaf015fb98fb918b6b8)