Bygg Instagram av Ruby on Rails (del 3)

Visa-ta bort inlägg och skapa hashtaggar för inlägg och sök inlägg

Tidigare inlägg:

  • Del 1: medium.com/luanotes/build-instagram-by-ruby-on-rails-part-1
  • Del 2: medium.com/luanotes/build-instagram-by-ruby-on-rails-part-2
  • Fullständig kod på Github: https://github.com/thanhluanuit/instuigram

Innehållsförteckning:

  • Lägg till visa Post sida: Visa detaljerad information om Post.
  • Lägg till radera postfunktion.
  • Skapa Hashtags för inlägg.
  • Implementera Search Posts-funktionen.

Vad lär du dig efter att ha läst artikeln?

  • CRUD i aktiv post: Läs / radera inlägg och CRUD Hashtags
  • Association in Active Record: The has_many: through association
  • Aktiv postfråga: Hämta data från databasen med Active Record

Visa inläggdetaljer

Steg 1: Lägg till show action i Posts controller

klass PostsController 

I den här åtgärden släpps en postvariabel med params-id.

Steg 2: Lägg till show Visa: (app / visningar / inlägg / show.html.erb)

Sidans layout: till vänster på sidan visar inläggsbilden och till höger på sidan visar användarinformation och inläggsbeskrivning.

Full HTML-kod:

<% = image_tag @ post.image, class: 'image'%> <% om @ post.user.avatar.attached? %> <% = link_to user_path (@ post.user) do%> <% = image_tag @ post.user.avatar%> <% end%> <% end%> <% = link_to @ post.user.username, user_path (@ post.user), klass: 'användarnamn'%> <% = @ post.beskrivning%>

CSS-kod: (app / tillgångar / stilark / posts.scss)

.post-show {marginal: 30px 5px 0; gräns: 1px solid #dbdbdb;
.col-md-8 {polstring: 0; .bild {bredd: 100%; }}
.användare {display: flex; stoppning: 10px 0; border-bottom: 1px solid #efefef;
.avatar {bredd: 40px; höjd: 40px; marginal: 8px; img {bredd: 100%; höjd: 100%; kant: 1px solid #efefef; gränsradie: 50%; }} .namn {padding-top: 15px; färg: # 262626; teckenstorlek: 14px; font-vikt: 600; &: sväva {textdekoration: ingen; }}}
.beskrivning {polstring: 15px 0; }}

Steg 3: Lägg till rutter: (config / routes.rb)

resurser: inlägg, bara: [: nytt,: skapa,: visa]

Uppdatering på sidan Användarprofil:

<% @ posts.each do | post |%> <% = link_to post_path (post) do%> <% = image_tag post.image%> <% end%> <% slut%>

Radera ett inlägg

Vi lägger till en funktion som hjälper användaren att ta bort sina inlägg.

Steg 1: Lägg till förstöra åtgärder i Posts controller

def förstöra @post = current_user.posts.find (params [: id]) @ post.destroy
  omdirigera_till user_path (current_user) slut

Vi hittar ett inlägg via inlägg från aktuell användare för att undvika att någon ändrar parametrar [: id] i HTML och säkrare.

@post = current_user.posts.find (params [: id])

Steg 2: Lägg till rutter: (config / routes.rb)

resurser: inlägg, bara: [: nytt,: skapa,: visa,: förstöra]

Se nya rutter tillagda:

rake rutter | grep post

Metoden för att förstöra åtgärder är DELETE.

Steg 3: Visa en länk för att ta bort inlägget på sidan Visa inlägg

Vi lägger till en länk Ta bort under beskrivningen av inläggssektionen och visar bara den här länken i inlägg från den aktuella användaren.

HTML: (app / visningar / inlägg / show.html.erb)

<% om current_user.posts.exists? (@ post.id)%> <% = link_to 'Ta bort', post_path (@post), metod:: ta bort, data: {bekräfta: 'Är du säker?' }%> <% slut%>

Denna metod för att ta bort länk: ta bort och visa bekräftelsemeddelandet innan du tar bort ett inlägg.

CSS-kod:

.delete {padding-top: 20px; a {font-size: 15px; textdekoration: understrykning; }}

Nu ser ut som:

Inlägg show sida med Ta bort länk

Lägg till Hashtags till Post

Mål:

I det här avsnittet kommer vi att lägga till Hashtags till Post genom att extrahera dem från beskrivningen av Post.

Exempel: När en användare skapar ett inlägg med beskrivningen är "Mina favorit #böcker, bra #moment". Vår applikation kommer att skapa två hashtags är bok och ögonblick.

Strömma:

  • Designdatabas
  • Skapa HashTag-modell
  • Skapa PostHashTag-modell
  • Skapa Hashtags för inlägg

Designdatabas:

Vi kan se att varje inlägg kan innehålla en eller många hashtags i beskrivningen. Och varje hashtagg kan användas i ett eller flera inlägg.

  • En post har många HashTags: en-till-många-relation
  • HashTag tillhör Posts: en-till-många-relation

Det betyder att Post med HashTag har en relation mellan många och många.

Bilden nedan är vår underdatabasdesign. Vi skapar två tabeller: HashTag och PostsHashTag-tabellen. PostsHashTag-tabellen är där lagra information om post och hashtag-relation.

Förhållandet mellan post och Hashtag

Skapa HashTag-modell

Vi kommer att använda en modellgenerator för att generera en hash_tag-modell med namnfältstypsträngen, en migrering som skapar en hash_tags-tabell och test_unit-filer. Kör kommando:

rails genererar modell hash_tag name: string

Utgången:

åberopa active_record skapa db / migrera / 20181017134507_create_hash_tags.rb skapa app / models / hash_tag.rb anropa test_unit skapa test / models / hash_tag_test.rb skapa test / fixtures / hash_tags.yml

För Active Record skapar det:

  • Modell: app / models / hash_tag.rb
  • Migration: db / migrate / 20181017134507_create_hash_tags.rb

Tips: Ibland kanske du inte kommer ihåg exakt format för kommandot för generatorn, du kan använda sorteringskommandot nedan för att se hur du använder:

rails genererar modell

Kör migrering för att skapa hash_tags-tabellen:

rails db: migrera

Skapa PostHashTag-modell

Innan jag skapar den här modellen, berättar jag om en has_many: through association-funktion. Denna förening används ofta för att skapa en många-till-många-anslutning till en annan modell. Det indikerar att den deklarerande modellen kan matchas med noll eller fler instanser av en annan modell genom att gå vidare genom en tredje modell.

I vårt fall: Mellan Post och HashTag är en många-till-många-anslutning och ansluten via en tredje modell är PostHashTag.

Skapa modellen:

rails genererar modell post_hash_tag
åberopa active_record skapa db / migrera / 20181017142241_create_post_hash_tags.rb skapa app / models / post_hash_tag.rb anropa test_unit skapa test / models / post_hash_tag_test.rb skapa test / fixtures / post_hash_tags.yml

Uppdatera db / migrate / 20181017142241_create_post_hash_tags.rb-filen:

klass CreatePostHashTags 
t.stämplar end end end

Vi lägger till ytterligare 2 linjer i migreringsfilen:

t.belongs_to: post, index: true t.belongs_to: hash_tag, index: true

Kör migrering:

rails db: migrera

Migreringen skapar en post_hash_tags-tabell med fler 2 kolumner är post_id och hash_tag_id och indexerar även 2 dessa kolumner.

Du kan se det i db / schema.rb-filen:

create_table "post_hash_tags", kraft:: kaskad do | t | t.bigint "posts_id" t.bigint "hash_tags_id" t.datetime "create_at", null: false t.datetime "updated_at", null: false t.index ["hash_tags_id"], namn: "index_post_hash_tags_on_hash_tags_id" t.index [ "posts_id"], name: "index_post_hash_tags_on_posts_id" slut

Förklara föreningen i Post, HashTag och PostHashTag

I modeller kodar du så här:

klass Post 
klass PostHashTag 
klass HashTag 

Kolla våra föreningsdeklarationer:

Vi använder rails konsol för att kontrollera våra förklaringar genom att utföra en fråga. Rails-konsolkommandot hjälper oss att interagera med din Rails-applikation från kommandoraden. Kör kommando:

rails c Laddar utvecklingsmiljö (Rails 5.2.1) 2.4.0: 001>

För post:

post = Post.last
=> # 
post.hash_tags # Returnera hash_tags för detta inlägg
=> HashTag Load (0,6ms) VÄLJ "hash_tags". * FRÅN "hash_tags" INNER JOIN "post_hash_tags" ON "hash_tags". "Id" = "post_hash_tags". "Hash_tag_id" WHERE "post_hash_tags". "Post_id" = $ 1 LIM $ 2 [["post_id", 33], ["LIMIT", 11]] => # 

För HashTag:

hash_tag = HashTag.create (namn: "rails")
=> # 
hash_tag.posts # Returnera inlägg med hash_tags
=> Postbelastning (0,3ms) VÄLJ "inlägg". * FRÅN "inlägg" INNER JOIN "post_hash_tags" ON "posts". "Id" = "post_hash_tags". "Post_id" WHERE "post_hash_tags". "Hash_tag_id" = $ 1 LIMIT $ 2 [["hash_tag_id", 2], ["LIMIT", 11]] => # 

Det fungerar!

Skapa Hashtags för inlägg

När en användare skapar ett nytt inlägg med en beskrivning så här: "Jag älskar #ruby, ruby ​​är #wuskigt". Jag förväntar mig att vårt system kommer att skapa 2 hashtags med namn är: rubin och fantastisk.

Steg 1: Extrahera Hashtags från beskrivningen av Post

Lägg till en instansmetod i Post-modellen för att extrahera hashtags:

def extra_name_hash_tags description.to_s.scan (/ # \ w + /). karta {| namn | name.gsub ("#", "")} slut

Den här metoden kommer att återgå till en rad namn hashtags. Till exempel:

post = Post.last
=> # 
post.extract_name_hash_tags
=> ["rubin", "awesome"]

Steg 2: Lägg till en återuppringning för att skapa hashtags efter att du har skapat ett inlägg.

Active Record stöder många användbara återuppringningar.

Vi använder after_commit återuppringning för vår inläggsmodell, denna återuppringning kallas efter att ett inlägg har skapats, uppdaterats eller förstörts. Men nu vill vi bara utlösa detta återuppringning när ett inlägg skapas, så vi lägger till mer: på alternativet för specifikt att skapa åtgärder. Du kan lära dig mer om after_commit i Rails api-dokument.

after_commit: create_hash_tags, på:: skapa

Definiera denna återuppringning i postmodell:

klass Post 
after_commit: create_hash_tags, on:: create def create_hash_tags # skapa hash_tags för Post end end

Metoden create_hash_tags kommer att kallas efter att ett inlägg har skapats. Lägg till logik till denna metod:

def create_hash_tags extract_name_hash_tags.each do | name | hash_tags.create (namn: namn) slutändan
def extra_name_hash_tags description.to_s.scan (/ # \ w + /). karta {| namn | name.gsub ("#", "")} slut

Förklara create_hash_tags-metoden:

  • Metoden skapar hashtags relaterade till ett inlägg baserat på resultatet av metoden extract_name_hash_tags.
  • Rad hash_tags.create (namn: namn): Eftersom ett inlägg har många hash-taggar, genom post_hash_tags-tabellen, skapar denna radkod en ny HashTag-post (H) och en ny PostHashTag-post som innehåller hash_tag_id som just skapats (H.id) och post_id är nuvarande inläggs-id.

Slutligen ser Post-modellen så här:

klass Inlägg 
def create_hash_tags extract_name_hash_tags.each do | name | hash_tags.create (namn: namn) slutändan
def extra_name_hash_tags description.to_s.scan (/ # \ w + /). karta {| namn | name.gsub ("#", "")} slutändan

Nu kommer vi tillbaka till vår ansökan, lägger till ett nytt inlägg och ser resultaten.

Sök inlägg

Mål:

För det här avsnittet kommer vi att implementera:

  • Sökfunktion som hjälper användare att söka inlägg efter hashtag (#) eller beskrivning av inlägg.
  • Aktivera hashtags i postbeskrivningen, gör att det är klickbart för att söka sidan.

Skapa sökkontroller med indexåtgärd:

rails g controller Sökindex - no-javascripts - no-stylesheets - no-helper

Uppdatera till rutter:

get 'search' => 'search # index'

Lägg till search_path till sökformuläret:

<% = form_med url: search_path, metod:: get, local: true, class: 'form-inline search-form' do | form | %> <% = form.text_field: fråga, värde: params [: fråga], klass: 'form-control mr-sm-2', platshållare: '#search'%> <% end%>

I Search Controller: (app / controllers / search_controller.rb)

Vi ska söka inlägg efter hashtagnamn eller beskrivning.

klass SearchController 

Fall 1: Sök med en hashtag (#travel), vi returnerar inlägg som har hashtags namn är fråga värde.

Frågeställningar:

query = params [: query] .gsub ('#', '')
Post.joins (: hash_tags) .where (hash_tags: {name: query})

Detta ger:

# fråga = "rubin"
VÄLJ "inlägg". * FRÅN "inlägg" INNER JOIN "post_hash_tags" ON "post_hash_tags". "Post_id" = "posts". "Id" INNER JOIN "hash_tags" ON "hash_tags". "Id" = "post_hash_tags". " hash_tag_id ”WHERE“ hash_tags ”.” name ”= $ 1 LIMIT $ 2 [[“ name ”,“ ruby ​​”], [“ LIMIT ”, 11]]

Fall 2: Sök efter beskrivning (inte en hashtag), vi returnerar inlägg som har beskrivning innehåller frågan.

@posts = Post.where ("beskrivning som?", "% # {params [: fråga]}%")

Du kan lära dig mer fråga i: guider.rubyonrails.org/active_record_querying

I Visa: (app / views / search / index.html.erb)

<% om @ posts.exists? %> Top Posts <% annars%> Oop! Inga matchande inlägg ... <% slut%>
<% @ posts.each do | post |%> <% = image_tag post.image%> <% slut%>
Sökresultatsida

Visa Hashtags i postbeskrivning

Vi gör hashtags är klickbara och länkar till sökningar i denna hashtag. Ändra inläggets beskrivning på hemsidan och inläggssidan:

<% = post.beskrivning%>

till

<% post.description.to_s.split ('') .each do | word | %> <% om word.start_with? ('#')%> <% = link_to word, search_path (fråga: word)%> <% else%> <% = word%> <% end%> <% end% >

Nu ser ett inlägg ut:

Slutsats

I den här artikeln, jag guider dig att lära dig om Association in Active Record, särskilt has_many: through association. Och hur man hämtar data från databasen med Active Record. Jag hoppas att du kan förstå djupare om Active Record.

Källkod på Github: https://github.com/thanhluanuit/instuigram

referenser:

  • Associering i aktiv post: https://guides.rubyonrails.org/association_basics.html
  • Aktivt inspelningsfrågorgränssnitt: https://guides.rubyonrails.org/active_record_querying.html