[RUBY] Hash-Tag-Suche wie Insta und Twitter in Rails implementiert (kein Juwel)

Überblick

Ich besuche derzeit eine Programmierschule namens DMM WEB CAMP Wie auf Instagram und Twitter für das Portfolio verwendet, das das Thema für den dritten Monat ist Hash-Tag-ähnlich implementiert. Ich hoffe, es wird für diejenigen hilfreich sein, die es in Zukunft implementieren werden.

Referenzseite

Implementieren Sie Hash-Tags in insta-ähnlichen Beschriftungen, die mit Rails erstellt wurden https://qiita.com/goppy001/items/791c946abdb41c9495bb

Der allgemeine Ablauf ist der gleiche wie auf der obigen Site, aber der Teil, der nicht gut funktioniert hat, wurde geändert.

Abschlusszeichnung

Bildschirm posten

スクリーンショット 2020-06-24 11.28.23.png

Bildschirm "Details veröffentlichen"

スクリーンショット 2020-06-24 11.28.55.png

Bildschirm "Hash-Tag-Liste" und "Hash-Tag-Post-Liste"

スクリーンショット 2020-06-24 11.29.11.png

Vorbereitungen DB

Posttabelle スクリーンショット 2020-06-24 11.36.41.png

Ursprünglich war es eine Tabellenstruktur mit nur body und user_id, aber wir haben eine Hashbody-Spalte zum Eingeben von Hash-Tags hinzugefügt. Übrigens wird das Bild aufgrund der Spezifikationen des Portfolios in einer anderen Tabelle gespeichert, aber es gibt kein Problem, selbst wenn sich die Bildspalte in dieser Tabelle befindet.

Modell erstellen (DB)

Hash-Tag-Modell

$rails g model Hashtag hashname:string

Erstellen Sie ein Modell zum Speichern von Hash-Tags. Das Hashtag wird in der Spalte Hashname gespeichert.

Migrationsdatei bearbeiten

create_hashtags.rb


class CreateHashtags < ActiveRecord::Migration[5.2]
  def change
    create_table :hashtags do |t|
      t.string :hashname

      t.timestamps
    end
    add_index :hashtags, :hashname, unique: true
  end
end

Zwischentabelle erstellen

$ rails g model HashtagPostImage post_image:references hashtag:references

Eine Zwischentabelle zwischen der Hashtag-Tabelle und der PostImage-Tabelle. Die Befehle hier unterscheiden sich geringfügig in dem Artikel, auf den ich verwiesen habe. Da es sich um eine Zwischentabelle handelt, werden Hashtag und Postimage-ID als externe Schlüssel verwendet. Da es sich um einen Referenztyp handelt, geben Sie zum Zeitpunkt der Erstellung hashtag_id ein Bitte beachten Sie, dass der Name der ausgefüllten Spalte hashtag_id_id lautet.

Migrationsdatei

create_hashtag_post_images.rb


class CreateHashtagPostImages < ActiveRecord::Migration[5.2]
  def change
    create_table :hashtag_post_images do |t|
      t.references :post_image, foreign_key: true
      t.references :hashtag, foreign_key: true
    end
  end
end

Meine große

$ rails db:migrate

DB erstellt

スクリーンショット 2020-07-01 12.13.30.png

Modellassoziations- und Validierungseinstellungen

Hash-Tag-Modell

hashtag.rb


class Hashtag < ApplicationRecord
  validates :hashname, presence: true, length: { maximum: 50 }
  has_many :hashtag_post_images, dependent: :destroy
  has_many :post_images, through: :hashtag_post_images
end

Vorerst habe ich die Obergrenze auf 50 Zeichen festgelegt.

Zwischentisch

hashtag_post_image.rb


class HashtagPostImage < ApplicationRecord
  belongs_to :post_image
  belongs_to :hashtag
  validates :post_image_id, presence: true
  validates :hashtag_id, presence: true
end

PostImage-Modell

post_image.rb


class PostImage < ApplicationRecord
  has_many :hashtag_post_images, dependent: :destroy
  has_many :hashtags, through: :hashtag_post_images
end

Dem PostImage-Modell wurde Folgendes hinzugefügt

post_image.rb


after_create do
    post_image = PostImage.find_by(id: id)
    #Erkennt in Hashbody eingegebene Hash-Tags
    hashtags = hashbody.scan(/[##][\w\p{Han}Ah-Gae-゚]+/)
    hashtags.uniq.map do |hashtag|
      #Hash-Tag ist am Anfang#Nach dem Entfernen speichern
      tag = Hashtag.find_or_create_by(hashname: hashtag.downcase.delete('#'))
      post_image.hashtags << tag
    end
  end
  #Aktion aktualisieren
  before_update do
    post_image = PostImage.find_by(id: id)
    post_image.hashtags.clear
    hashtags = hashbody.scan(/[##][\w\p{Han}Ah-Gae-゚]+/)
    hashtags.uniq.map do |hashtag|
      tag = Hashtag.find_or_create_by(hashname: hashtag.downcase.delete('#'))
      post_image.hashtags << tag
    end
  end

Es ist markiert, damit diese Aktion beim Erstellen und Aktualisieren ausgeführt wird.

・ Post_image = PostImage.find_by (id: id) Hier können Sie den von Ihnen erstellten Beitrag finden.

・ Hashtags = hashbody.scan (/ [# #] [\ w \ p {Han} a-ga- ゚] + /) Suchen Sie hier nach dem eingegebenen Hash-Tag und dem Eingabewert mit [# #] am Anfang. Hashbody ist der Spaltenname meiner Datenbank, dies hängt also von der Anwendung ab. Jede Spalte für die Texteingabe in der Post-Tabelle reicht aus.

・ Hashtags.uniq.map do |hashtag|

Hash-Tag wird gespeichert, nachdem das führende # entfernt wurde

  tag = Hashtag.find_or_create_by(hashname: hashtag.downcase.delete('#'))
  post_image.hashtags << tag
end

Durch Wiederholen mit Map werden mehrere Hash-Tags im Postimage gespeichert.

・ Post_image.hashtags.clear Zum Zeitpunkt der Aktualisierung scheint das Hash-Tag einmal gelöscht worden zu sein.

Routenbeschreibung

routes.rb


get '/post_image/hashtag/:name' => 'post_images#hashtag'
get '/post_image/hashtag' => 'post_images#hashtag'

In meinem Fall wollte ich eine Hash-Tag-Listenseite erstellen, also habe ich zwei Routen vorbereitet.

Bearbeiten des PostImage-Hilfsprogramms

post_images_helper.rb


module PostImagesHelper
  def render_with_hashtags(hashbody)
    hashbody.gsub(/[##][\w\p{Han}Ah-Gae-゚]+/) { |word| link_to word, "/post_image/hashtag/#{word.delete("#")}",data: {"turbolinks" => false} }.html_safe
  end
end

link_to word, "/post_image/hashtag/#{word.delete("#")}" Die URL hier hängt vom Inhalt der Anwendung ab. Wenn Sie auf das Hash-Tag klicken, gelangen Sie hier zur URL. Geben Sie die URL ein, die Sie zuvor in route geschrieben haben.

PostImag-Controller

controllers/post_images_controller.rb



class PostImagesController < ApplicationController
  def new
    @postimagenew = PostImage.new
    @postimagenew.post_image_images.new
  end

  def create
    @postimagenew = PostImage.new(post_image_params)
    @postimagenew.user_id = current_user.id

    if @postimagenew.save
      redirect_to post_images_path
    else
      render('post_images/new')
    end
  end

  def destroy
    @postimage = PostImage.find(params[:id])
    @postimage.destroy
    redirect_to post_images_path
  end

private
 def post_image_params
    params.require(:post_image).permit(:body, :hashbody, :user_id, post_image_images_images: [], hashtag_ids: [])
 end

Machen Sie sich keine Sorgen um post_image_images_images: [], um die Bilder in den starken Parametern als Array in einer anderen Tabelle zu speichern. hashtag_ids wird eingegeben, da beim Erstellen von PostImage mehrere Hash-Tags registriert werden.

View

Formular posten

views/post_images/new.html.erb



<div class= "row">
	<div class="col-lg-2 col-md-2">
	</div>
	<div class="col-xs-12 col-lg-8 col-md-8 col-sm-12">
		<div class= "postimage-new-box">
			<% if @postimagenew.errors.any? %>
  				<div id="error_explanation">
    				<h3><%= @postimagenew.errors.count %>Konnte aufgrund eines Eingabefehlers nicht posten</h3>
  					<ul>
    					<% @postimagenew.errors.full_messages.each do |msg| %>
      					<li><%= msg %></li>
    					<% end %>
    				</ul>
 				</div>
			<% end %>
			<h3>Neuer Beitrag</h3>
			<div class="previw">
			</div>
			<%= form_with model:@postimagenew, local: true do |f| %>
				<div class="attachment-field">
					<p>Wählen Sie ein Bild aus (mehrere können angegeben werden)</p>
					<%= f.attachment_field :post_image_images_images, multiple:true %>
				</div>
				<br>
				<br>
				<div class= "postimage-body-box">
					<p>Bitte geben Sie die Details der Post ein</p>
					<%= f.text_area :body, size:"55x12" %>
					<br>
					<p>Hash-Tag-Eingabefeld</p>
					<%= f.text_area :hashbody, size:"55x3" %>
					<br>
					<div class= "postimage-new">
					<%= f.submit "Neuer Beitrag" ,class:'postimage-new-button' %>
					</div>
			<% end %>
				</div>
		</div>
	</div>
	<div class="col-lg-2 col-md-2">
	</div>
</div>

Wo soll das Hash-Tag im Post-Body angezeigt werden?

スクリーンショット 2020-06-24 11.28.55.png

Das Folgende ist in Ansicht geschrieben.

ruby:post_images/show.html.erb


<%= render_with_hashtags(@postimage.hashbody) %>

Das obige ruft die zuvor mit helper erstellte Methode auf. Der Controller für post_images / show ist übrigens hier.

controllers/post_images_controller.rb


def show
    @postimage = PostImage.find(params[:id])
end

Ich denke, dass es einfach die Informationen im Hashtag-Eingabefeld von @postimage an Hellber weitergibt.

Hash-Tag-Listenseite

スクリーンショット 2020-06-24 11.29.11.png

Wenn Sie darauf klicken, sieht es so aus. スクリーンショット 2020-06-24 13.12.07.png

Fügen Sie dem PostImage-Controller eine Hashtag-Aktion hinzu

post_images_controller.rb


def hashtag
    @user = current_user
    if params[:name].nil?
      @hashtags = Hashtag.all.to_a.group_by{ |hashtag| hashtag.post_images.count}
    else
      @hashtag = Hashtag.find_by(hashname: params[:name])
      @postimage = @hashtag.post_images.page(params[:page]).per(20).reverse_order
      @hashtags = Hashtag.all.to_a.group_by{ |hashtag| hashtag.post_images.count}
    end
  end

Die Notation hier hängt von der von Ihnen erstellten Site ab. Ich wollte eine Seite erstellen, auf der Sie die Liste der Hash-Tags sehen können. Im Fall von params [: name] .nil? Es gibt einen bedingten Zweig, in dem post_image nicht angezeigt wird. Obwohl es sich um group_by handelt, können Hash-Tags in der Reihenfolge der Anzahl der mit Hash-Tags verknüpften Beiträge angezeigt werden. Es ist so geschrieben.

Hashtag-Ansicht

post_images/hashtag.html.erb


<div class="row">
		<% if params[:name] == nil %>

		<% else %>
		<div class= "col-xs-12 col-lg-12 col-md-12 col-sm-12">
			<div class="hashtag-post-box">
				<h3 class="search-title">#<%= @hashtag.hashname %>:  <%= @postimage.count %>Fall</h3>
				<div class="flex-box">
				<% @postimage.each do |postimage| %>
					<div class= "post-image-index-post-box">
						<p class="index-post-box-top">
							<%= postimage.created_at.strftime("%Y/%m/%d") %>
						</p>
						<span class='far fa-comments index-comment-count' id='comment-count_<%= postimage.id %>' style="color: #777777;">
							<%= render 'post_image_comments/comment-count', postimage:postimage %>
						</span>

						<span id = "favorite-button_<%= postimage.id %>"class="post-box-top-favorite">
							<%= render 'post_image_favorites/favorite',postimage: postimage %>
						</span>
		    			<%= link_to post_image_path(postimage),data: {"turbolinks" => false}  do %>
				  			<ul class="slider">
									<% postimage.post_image_images.each do |post| %>
										<li>
										<%= attachment_image_tag post, :image ,size:'430x360', format:'jpg',class:"image" %>
									</li>
								<% end %>
							</ul>
						<% end %>
						<p class="hashtag-post-box-name">
							<%= link_to user_path(postimage.user) do %>
								<%= attachment_image_tag postimage.user, :profile_image,size:'30x30', format:'jpg',fallback:'no_image.jpg',class:'min-image' %>
								<span class="index-post-box-user"><%= postimage.user.name %>
								</span>
							<% end %>
						</p>
						<div class="image-show-body-hash" style="padding:2%">
							<%= simple_format(postimage.body.truncate(50))%>
							<% if postimage.body.length > 50 %>
								<span class="text-prev"><%= link_to 'Weiterlesen', post_image_path(postimage), data: {"turbolinks" => false} %>
								</span>
							<% end %>
						</div>
					</div>
				<% end %>
				</div>
			</div>
			<div class="image-index-pagination" data-turbolinks="false">
				<%= paginate @postimage,class:"paginate" %>
			</div>
		</div>
		<% end %>
	</div>
	<div class="row">
		<div class= "col-xs-12 col-lg-12 col-md-12 col-sm-12">
			<div class= "hashtag-name">
				<% @hashtags.sort.reverse.each do |count| %>
						<% count[1].each do |hashtag| %>
						<p><%= link_to  "##{hashtag.hashname} (#{hashtag.post_images.count})Fall","/post_image/hashtag/#{hashtag.hashname}",data: {"turbolinks" => false} %>
						</p>
						<% end %>
				<% end %>
			</div>
		</div>
	</div>
</div>

Es tut mir leid, dass ich verwirrt bin, weil ich Klassennamen verwendet habe und so weiter. Die wichtigen Punkte sind wie folgt.

post_images/hashtag.html.erb


<% if params[:name] == nil %>

<% else %>

<% end %>

Mit dieser Notation wird eine bedingte Verzweigung mit post_image / hashtag und post_image / hashtag /: name durchgeführt, die zuvor in der Route geschrieben wurden. Durch Schreiben der Verarbeitung, wenn params in jedem Controller und in jeder Ansicht gleich Null ist, wird ein Fehler verhindert.

post_image/hashtag.html.erb



<div class= "hashtag-name">
	<% @hashtags.sort.reverse.each do |count| %>
		<% count[1].each do |hashtag| %>
			<p><%= link_to  "##{hashtag.hashname} (#{hashtag.post_images.count})Fall","/post_image/hashtag/#{hashtag.hashname}",data: {"turbolinks" => false} %>
			</p>
        <% end %>
	<% end %>
</div>

Die Liste der Hash-Tags wird hier angezeigt. Die Anzeige wird in absteigender Reihenfolge der Beiträge angezeigt, die mit Hash-Tags verknüpft sind.

Zusammenfassung

Wenn Sie das Eingabefeld für das Hash-Tag nicht trennen, bleibt das Hash-Tag als Satz in der Beschreibung des Beitrags, sodass ich es in Form einer Speicherung in einer anderen Spalte implementiert habe. Der Hashbody wird absichtlich dort versteckt, wo der Hashtag zusammen mit dem Beitrag angezeigt wird. Es sind falsche Turbolinks, die in der Ansicht häufig vorkommen, aber js funktioniert nicht gut und es ist geschrieben, sodass Sie es ignorieren können.

Es tut mir leid, wenn es Teile gibt, die im ersten Beitrag schwer zu verstehen sind. Ich hoffe, es ist hilfreich für diejenigen, die von nun an ein Portfolio erstellen.

Nachtrag

2020/7/1 Die Migrationsdatei der Zwischentabelle wurde behoben. Es gab ein Phänomen, das nicht zerstört werden konnte, wenn id False gesetzt war, also haben wir es korrigiert. Gleichzeitig habe ich dem Modell has_many abhängige :: Zerstörer hinzugefügt.

Wir haben auch einen Controller und eine Ansicht für den Hashtag- und Post-Save-Teil hinzugefügt. Wir bitten um Entschuldigung für die Unannehmlichkeiten.

Recommended Posts

Hash-Tag-Suche wie Insta und Twitter in Rails implementiert (kein Juwel)
[Für Anfänger von Rails] Mehrfachsuchfunktion ohne Gem implementiert
[Rails 6.0] Ich habe versucht, eine Tag-Suchfunktion zu implementieren (eine Funktion zum Eingrenzen nach Tags) [no gem]
Kalenderimplementierung und bedingte Verzweigung im einfachen Kalender von Rails Gem
[Rails] Suche aus mehreren Spalten + Bedingungen mit Gem und Ransack
Edelstein oft in Schienen verwendet
Aktivieren Sie jQuery und Bootstrap in Rails 6 (Rails 6).
Entfernen Sie "Assets" und "Turbolinks" in "Rails6".
CRUD-Funktion und MVC in Rails