[RUBY] [Rails] Implementierungsverfahren der Funktion zum Markieren von Posts ohne Gem + die Funktion zum Eingrenzen und Anzeigen von Posts nach Tags

Überblick

__ ・ Implementieren Sie eine Funktion, mit der Sie Ihre eigenen Beiträge markieren können. __ __ __ ・ Implementieren Sie eine Funktion, mit der Sie die Suche anhand der an den Beitrag angehängten Tags eingrenzen können. __ __

Annahme

·Umgebung Ruby 2.6-Serie Schienen 5.2 Serie

·Bibliothek  Slim

__ ・ Rails-Anwendungsvorlage der oben genannten Umgebung __ Vorgehensweise zum Einrichten der Rails-Anwendung und zum Installieren von devise and Slim

__ ↓ Abgeschlossenes Bild ↓ __ ezgif.com-video-to-gif (2).gif

Implementierung

1. Modelldesign und Assoziation

スクリーンショット 2020-06-13 20.14.13.png - Benutzer: Beitrag = Benutzer hat viele Beiträge für jede Person, daher gibt es eine Beziehung von 1 zu vielen.

- Post: Tag = `Ein Post hat viele Tags, `Ein Tag hat auch viele Posts , also``` Viele-zu-viele-Beziehung. → Eine Zwischentabelle ist aufgrund der Viele-zu-Viele-Beziehung = `` TagMap``` erforderlich

→ Eine Zwischentabelle ist eine Tabelle, in der nur die externen Schlüssel (post_id und tag_id) der "Many-to-Many-Tabelle (in diesem Fall Post- und Tag-Tabelle)" gespeichert werden und die Tabellen des jeweils anderen nur mit dem externen Schlüssel verwaltet werden. Mach es möglich.

2. Modellerstellung

$ rails g devise User //Erstellen Sie ein Benutzermodell aus dem Gerät $ rails g migration add_columns_to_users name:string //Namensspalte hinzugefügt   $ rails g model Post content:string user:references //Postmodellerstellung   $ rails g model Tag tag_name:string //Tag-Modellerstellung   $ rails g model TagMap post:references tag:references //TagMap-Modellerstellung


 >> - Da Spalten nicht zu dem von devise erstellten Benutzermodell hinzugefügt werden können, muss beim Hinzufügen einer Namensspalte diese als neue Migration hinzugefügt werden.
  
 - <Tabellenname>: Für die in Referenzen angegebene Tabelle wird ein externer Schlüssel festgelegt. (Erforderlich)


### 3. Überprüfen Sie die erstellte Migrationsdatei
 > #### 3-1.users Migrationsdatei
>>```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: ""
 
    #<Kürzung>
 
  end
end

3-2. Fügen Sie der Benutzertabelle eine Namensspalte hinzu

class AddUsernameToUsers < ActiveRecord::Migration[5.2] def change add_column :users, :name, :string end end


 > #### 3-3.posts Migrationsdatei

>>```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

3-4.tags Migrationsdatei

class CreatePostTags < ActiveRecord::Migration[5.2] def change create_table :post_tags do |t| t.string :tag_name   t.timestamps end end end


 > #### 3-5.tag_maps Migrationsdatei

>>```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. Bestätigung der erstellten Modelldatei

4-1. Benutzermodelldatei

class User < ApplicationRecord

Include default devise modules. Others available are:

:confirmable, :lockable, :timeoutable, :trackable and :omniauthable

devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable   has_many :posts, dependent: :destroy end


 >> ・ `abhängige :: zerstören`: Eine Option, die an die übergeordnete Klasse angehängt werden kann, damit die untergeordnete Klasse gelöscht werden kann, wenn die übergeordnete Klasse gelöscht wird.

 > #### 4-2. Modelldatei veröffentlichen

>>```ruby:app/models/user.rb
class Post < ApplicationRecord
  belongs_to :user
 
  has_many :tag_maps, dependent: :destroy
  has_many :tags, through: :tag_maps
end

__ ・ Mit der Option `through wird die Tag-Tabelle über die Tabelle tag_maps zugeordnet. Auf diese Weise können Sie die mit Post verknüpften Tags mithilfe von "Post.tags" abrufen. Dies kann verwendet werden, wenn Sie das Tag an den Beitrag anhängen und es auf dem Bildschirm mit den Beitragsdetails anzeigen möchten. __ __

__ ・ Wenn Sie die Option through verwenden, müssen Sie sie zuerst der Zwischentabelle zuordnen. __ __

__- Durch Hinzufügen der abhängigen :: destroy-Option zur Zwischentabelle wird die Beziehung zwischen Post und Tag gleichzeitig mit dem Löschen von Post gelöscht. __ __

4-4.Tag Modelldatei

class Tag < ApplicationRecord has_many :tag_maps, dependent: :destroy, foreign_key: 'tag_id' has_many :posts, through: :tag_maps end


 >> __` ・ Nach der Zuordnung zur Tabelle tag_maps wird sie über tag_maps` der Tabelle posts zugeordnet. Sie können die mit den Tags verknüpften Posts mit "Tag.posts" abrufen. Dies kann verwendet werden, wenn Sie nach Posts mit einem bestimmten Tag suchen möchten, z. B. "Sport". __ __

 > #### 4-5. TagMap-Modelldatei

>>```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

__ ・ Da es mehreren Posts und mehreren Tags gehört, ist es miteins_zu verknüpft. __ __

__ ・ Wenn Sie die Beziehung zwischen Post und Tag aufbauen, müssen unbedingt zwei externe Schlüssel vorhanden sein. Überprüfen Sie diese. __ __

5. Routing-Einstellungen

Rails.application.routes.draw do devise_for :users   root to: 'posts#index'   resources :posts end


 >> __ ・ Legen Sie zu diesem Zeitpunkt vorerst das von devise bereitgestellte Routing, den Stammpfad und den Pfad zur Beitragsressource fest. __ __

## Implementieren Sie zunächst die Funktion, mit der Beiträge markiert werden können

### 6. Erstellen Sie einen Controller

 > #### 6-1. Schreiben Sie den Code zum Erstellen von Posts und Tags in die Erstellungsaktion des Posts-Controllers.

>>```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

__ Lassen Sie uns den obigen Code aufschlüsseln. __ __

@post = current_user.posts.new(post_params)

 >> __ · Durch Festlegen von `current_user.posts` wird die ID des angemeldeten Benutzers in der user_id der posts-Tabelle gespeichert. Wenn jedoch` User und Post nicht zugeordnet sind, tritt ein Fehler auf. Masu`. Starke Parameter werden als Argument verwendet. __ __

>>```ruby:Holen Sie sich die Tags, die gesendet wurden
tag_list = params[:post][:tag_name].split(nil)

__ ・ params [: post] [: tag_name]: Verweisen Sie im Formular auf das @ post-Objekt und senden Sie den Tag-Namen zusammen. Erhalten Sie ihn also in diesem Formular. Zum Beispiel wird es wie "Sport", "Studium", "Arbeit" gesendet. __ __

__ ・ .split (nil): Ordnen Sie die gesendeten Werte durch Leerzeichen getrennt an. Im obigen Beispiel fühlt es sich an wie ["Sport" "Studium" "Arbeit"]. Der Grund für das Anordnen ist, dass beim späteren Speichern dieses Werts in der Datenbank dieser nacheinander durch iterative Verarbeitung abgerufen werden muss. __ __

@post.save_tag(tag_list)

 __ ・ `Prozess zum Speichern des zuvor in der Datenbank erfassten Arrays von Tags`. Die Definition von save_tag, die die Verarbeitung ausführt, wird später beschrieben. __ __

 > #### 6-2. Schreiben Sie den Code, um den Beitrag und das Tag in der Indexaktion abzurufen.

>>```ruby:app/controllers/posts_controller.rb
def index
    @tag_list = Tag.all              #Lassen Sie alle die Tag-Liste in der Ansicht anzeigen.
    @posts = Post.all                #Holen Sie sich alle, um die Post-Liste in der Ansicht anzuzeigen.
    @post = current_user.posts.new   #Formular anzeigen_Wird für Modell mit verwendet.
end

def show @post = Post.find(params[:id]) #Holen Sie sich den Beitrag, auf den Sie geklickt haben. @post_tags = @post.tags #Holen Sie sich das Tag, das dem angeklickten Beitrag zugeordnet ist. end


### 7. Definieren Sie die Instanzmethode save_tag in der Post-Modelldatei.

 > __ ・ Definieren Sie den Inhalt der Instanzmethode save_tag, die weiter oben in der Aktion create beschrieben wurde. __ __

>```ruby:app/models/post.rb
class Post < ApplicationRecord
 
  #<Kürzung>
 
  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?

 > __ ・ Wenn mit @post ein Tag verknüpft ist, das zuvor durch die Erstellungsaktion gespeichert wurde, rufen Sie alle "Tag-Namen als Array" ab. __ __

>```ruby:Holen Sie sich alte Tags
old_tags = current_tags - sent_tags

__ ・ Alte_Tags sind die Tags, die im aktuell erfassten @post vorhanden sind, mit Ausnahme der gesendeten Tags. __ __

new_tags = sent_tags - current_tags

 > __ ・ New_tags sind die Tags, die gesendet werden, mit Ausnahme der derzeit vorhandenen Tags. __ __

>```ruby:Alte Tags löschen
old_tags.each do |old|
    self.tags.delete Tag.find_by(tag_name: old)
end

__- Alte Tags löschen. __ __

new_tags.each do |new| new_post_tag = Tag.find_or_create_by(tag_name: new) self.post_tags << new_post_tag end

 > __- Speichern Sie das neue Tag in der Datenbank. __ __

 > __ ・ Der Grund, warum es Zeit braucht, alte und neue Tags wie oben beschrieben zu erfassen und zu löschen, anstatt nur Tags einzeln zu erfassen und zu speichern, ist beispielsweise beim Bearbeiten eines Beitrags. Weil es funktionieren muss.
 Es tut mir jedoch leid, diesmal werde ich die Implementierung der Bearbeitungsfunktion weglassen. __ __

### 8. Erstellen Sie eine Ansicht.

 > #### 8-1. Erstellen Sie eine Ansicht der Beitragsliste.

>>```ruby:app/views/posts/index.html.slim
h3-Tag-Liste
- @tag_list.each do |list|
  span
    = link_to list.tag_name, tag_posts_path(tag_id: list.id)
    = "(#{list.posts.count})"
 
hr
 
h3 post
= form_with(model: @post, url: posts_path, local: true) do |f|
  = f.text_area :content
  br
  = "Sie können mehrere Tags hinzufügen, indem Sie ein Leerzeichen eingeben."
  = "Beispiel: Musik, Literatursport"
  = f.text_field :tag_name
  br
  = f.submit
 
hr
 
h3 Beitragsliste
- @posts.each do |post|
    = link_to post.content, post

Lassen Sie uns den obigen Code aufschlüsseln.

 >> __ ・ Zeigt alle von der Indexaktion erfassten Tags an und enthält außerdem einen Link zum Pfad zum Anzeigen von Posts, die sich auf dieses Tag beziehen. Klicken Sie auf diesen Link, um die mit diesem "Tag" verknüpften Beiträge anzuzeigen. Das Festlegen des Routings zum Abrufen dieses Links und das Erstellen der Aktion wird später beschrieben. __ __

 >> __ ・ `" (# {list.posts.count}) "` zählt und zeigt an, wie viele Beiträge derzeit dieses Tag haben. __ __

>>```ruby:Neues Postformular (kann markiert werden)
= form_with(model: @post, url: posts_path, local: true) do |f|
  = f.text_area :content
  br
  = "Sie können mehrere Tags hinzufügen, indem Sie ein Leerzeichen eingeben."
  = "Beispiel: Musik, Literatursport"
  = f.text_field :tag_name
  br
  = f.submit

__ ・ = f.text_field: tag_name: Durch Schreiben dieser Zeile werden die im Formular eingegebenen Tags als Parameter params [: post] [: tag_name] an die Aktion create gesendet. .. __ __

8-2. Erstellen Sie eine Ansicht der Post-Detailseite.

h1 post details   p= @post.content   br   = "Etikett: "

 >> __ ・ Der Teil, der das Tag anzeigt, entspricht der in der Listenanzeige beschriebenen Methode. In diesem Fall unterscheidet sich der Teil "Tag, der einem bestimmten Beitrag zugeordnet ist". __ __

 __ · Damit ist die Implementierung der Funktion abgeschlossen, mit der Sie Beiträge markieren können. __ __

## Implementieren Sie eine Funktion zum Eingrenzen und Anzeigen von Posts nach Tags

### 1. Routing hinzufügen.

>```ruby:config/routes.rb
Rails.application.routes.draw do
  devise_for :users
  root to: 'posts#index'
  resources :posts
 
  #Weiterleiten an Aktionen zum Anzeigen von Posts, die nach Tags gefiltert wurden
  resources :tags do
    get 'posts', to: 'posts#search'
  end
end

__ ・ Durch Verschachteln können Sie den Pfad verwenden, um zur Postseite zu wechseln, die einem bestimmten Tag mit dem Namen "tag_posts_path (tag_id: tag.id)" zugeordnet ist, wie zuvor beschrieben. __ __

2. Erstellen Sie eine Suchaktion im Posts-Controller.

def search @tag_list = Tag.all #Holen Sie sich alle Tags, um alle Tags auf dieser Post-List-Anzeigeseite anzuzeigen @tag = Tag.find(params[:tag_id]) #Holen Sie sich das angeklickte Tag @posts = @tag.posts.all #Alle Beiträge anzeigen, die dem angeklickten Tag zugeordnet sind end


### 3. Erstellen Sie eine Seitenansicht, in der eine Liste von Posts angezeigt wird, die durch Tags eingegrenzt sind.

 > __ ・ Erstellen Sie zunächst eine Datei search.html.slim im Verzeichnis app / views / posts. __ __

>```ruby:app/views/posts/search.html.slim
h2 post liste
 
#Tag-Liste
- @tag_list.each do |list|
  span
    = link_to list.tag_name, tag_posts_path(post_tag_id: list.id)
    = "(#{list.posts.count})"
br
#Beitragsliste nach Tag eingegrenzt
= "Das Tag ist ─"
strong= "#{@tag.tag_name}"
= "─ Beitragsliste"
br
- @posts.each do |post|
  = link_to post.content, post
br
= link_to 'Zuhause', root_path

__ ・ Der Tag-Listen-Teil ist der gleiche wie der Index-Teil. __ __

= "Das Tag ist ─" strong= "#{@tag.tag_name}" = "─ Beitragsliste"

 > __ ・ In diesem Teil wird das entsprechende Tag angezeigt, damit Sie sehen können, welche Art von Tag eingegrenzt wurde. __ __

 __ · Damit ist die Implementierung der Funktion zum Anzeigen von durch Tags eingegrenzten Posts abgeschlossen. Wie Sie sehen können, gibt es einige Überlappungen in der Ansicht. Wenn Sie diese Teile also partialisieren und umgestalten, sieht die Ansicht sauberer und besser aus. __ __

## Artikel, der sehr hilfreich war
 [Hinweise zur Implementierung der Tag-Funktion in Rails ohne Verwendung von gem](https://qiita.com/tobita0000/items/daaf015fb98fb918b6b8)


Recommended Posts

[Rails] Implementierungsverfahren der Funktion zum Markieren von Posts ohne Gem + die Funktion zum Eingrenzen und Anzeigen von Posts nach Tags
[Rails 6.0] Ich habe versucht, eine Tag-Suchfunktion zu implementieren (eine Funktion zum Eingrenzen nach Tags) [no gem]
[Rails] So zeigen Sie eine Liste der Beiträge nach Kategorie an
[Rails] Implementierung der Tag-Funktion mit Acts-as-Taggable-On und der Funktion zur Vervollständigung der Tag-Eingabe mit Tag-It
[Rails] Ich werde die Prozedur zum Implementieren der Follow-Funktion mit form_with erklären.
Verwenden Sie die where-Methode, um anhand des Werts eines anderen Modells einzugrenzen.
[Rails] Implementierungsverfahren, wenn der Buchungsfunktion öffentliche / private Funktionen hinzugefügt werden
[Rails] Implementierung der Drag & Drop-Funktion (mit Wirkung)
Implementierungsrichtlinie zum dynamischen Speichern und Anzeigen der Zeitzone in Rails
[Rails] Implementierung der Kategoriefunktion
[Rails] Implementierung der Tutorial-Funktion
[Rails] Implementierung einer ähnlichen Funktion
Speicherort der Methodendefinition Zusammenfassung der zu überprüfenden Informationen Wenn im Projekt und in Rails / Gem definiert
[Rails] So erhalten Sie die URL der Übergangsquelle und leiten sie um
[Rails] So lassen Sie die Anzeige der Zeichenfolge der link_to-Methode weg
[Rails] Lesen Sie das RSS der Site und geben Sie den Inhalt an die Vorderseite zurück
[Schienen] Verwenden Sie die Auswahlmethode nicht nur, um die Spalten einzugrenzen!
twitter-4 Auswahl von Fehlern mit der von omniauth gem erstellten Twitter-Anmeldefunktion und wie man damit umgeht
[Rails] Implementierung der CSV-Importfunktion
[Rails] Asynchrone Implementierung der Like-Funktion
[Rails] Über die Implementierung der Like-Funktion
[Rails] Implementierung der Benutzerrückzugsfunktion
[Rails] Implementierung der CSV-Exportfunktion
Implementierung der Funktionsfunktion [Rails] gem ancestry category
[Rails] Memo zur Implementierung der Kommentarfunktion
Strict_loading-Funktion zur Unterdrückung des Auftretens von N + 1-Problemen, die von Schienen hinzugefügt wurden 6.1
[Rails] Artikel für Anfänger, um den Fluss von form_with zu organisieren und zu verstehen
So machen Sie https zum Schema der URL, die vom URL-Helfer von Rails generiert wurde