0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Microposts機能(rails)

Posted at

この記事では、Micropostsにおける投稿機能について、簡単に理解したのでその確認として理解を深めることを目的としている。

投稿機能は以下の手順デコーディングを行う

  1. Micropostモデル、contentカラム、user_idカラム(外部キー)を作る
  2. UserテーブルとMicropostテーブルを関連付ける
  3. UsersコントローラーのshowアクションにMicropostの中身を表示させるための「@microposts」を記載する
  4. Usersフォルダーのviewのshow.html.erbにも@micropostsを記載する
  5. Micropostsコントローラーを作り、_micropost.html.erbにmicropostテーブルのcontentカラムの中身を表示させるファイルを作る
  6. Homeページをアップデートする

1.Micropostモデル、contentカラム、user_idカラム(外部キー)を作る

$ rails g model Micropost content:string user_id:integer

$ rails db:migrate:reset db:seed

↑データベースをいじったので一度migrateファイルをリセットしておく

Microposは誰の投稿化を知るために必ずuser_idを持たなければいけないので以下のコードを打ち込む

class Micropost < ActiveRecord::Base
***    validates :user_id, presence: true
end

UserテーブルとMicropostテーブルを関連付けをする

models/micropost.rb
class Micropost < ApplicationRecord
***  belongs_to :user
  validates :user_id, presence: true
end
models/user.rb
class User < ApplicationRecord
***  has_many :microposts, *dependent: :destroy
  ...
end

最新の投稿が投稿欄の一番上に表示されるようにする

class Micropost < ApplicationRecord
 belogns_to :user
*** default_scope -> { order('created_at DESC')}
 validates :user_id, presence: true
end

*dependent: :destroyを使うことによりuserが退会した場合にそのuserが投稿した内容も同時に削除されるようにする

投稿文字数をTwitterのように140文字以内でしか投稿できないようにする

class Micropost < ApplicationRecord
 belongs_to :user
 default_scope -> {order('created_at DESC')}
*** validates :content, presence: true, length: { maximum: 140 }
    validates :user_id, presence: true
end

3. UsersコントローラーのshowアクションにMicropostの中身(content)を表示させるための「@microposts」を記載する

class UsersController < 
ApplicationController

///
   def show
        @user = User.find(params[:id])
        @microposts = @user.microposts.paginate(page: params[:page], per_page: 12)
        #userに紐づくすべての投稿をpaginateで取得する。
   end
views/users/show.html.erb

<% provide(:title, @user.name)%>
<div class="container pt-4">
<div class="row">
    <aside class="span">
        <section>
            <h1>
                <%= gravatar_for @user %>
                <%= @user.name%>
            </h1>
        </section>
    </aside>

<div class="col-9">
    <div>
        <% if @user.microposts.any?%>
   #モデルにデータが存在する→true/存在しないfalseを返すメソッド

        <h3>Microposts (<%= @user.microposts.count %>)</h3>
        <ol class="microposts">
            <%= render @microposts%> 
        </ol>
        <%= will_paginate @microposts%>
        <% end %>
    </div>
    </div>

5. Micropostsコントローラーを作り、_micropost.html.erbにmicropostテーブルのcontentカラムの中身を表示させるファイルを作る

terminal
rails g controller Microposts

=>createアクションとdestroyアクションを作るためにmicropostsコントローラーを作る

views/microposts/_micropost.html.erb
<li>
   <h4><%= micropost.content%></h4>
   #micropostテーブルのcontentカラムの内容を表示
   <span class="timestamp">
        Posted <%= time_ago_in_words(micropost.created_at) %> ago.
    #created_atで作成日時を表示する際に、Twitterのように「~前」と表示する方法 ※ex:約19時間前
   </span>
</li>

=> showページでmicroposts投稿内容と作成日を表示させる
microposts.JPG

▼Fakerでダミーデータを作成する

db/seeds.rb
  users = User.order(:created_at).take(7)
  50.times do
    content = Faker::Lorem.sentence(3)
    users.each { |user| user.microposts.create!(content:content) }
  end
$rails db:migrate:reset db:seed

=> データベースの中身を変更したのでリセットする

ダミー.JPG

createとdestroyのルーティングをresourcesメソッドを使って定義する

config/routes.rb
///
resources :users

resources :sessions, only: [:new, :create, :destroy]

resources :microposts, only: [:create, :destroy]
///

6. Homeページをアップデートする

views/static_pages/home.html.erb
<% provide(:title, 'Home')%>
<% if logged_in?%>
    <div class="row">
        <aside class="col-3">
            <section>
                <%= render 'shared/user_info' %>
            </section>
            <section>
                <%= render 'shared/micropost_form' %>
            </section>
        </aside>


     <!-- Microposts here -->

    </div>
    <% else %>
    <h1 style="text-align:center;">Awesome Blog</h1>
        <p>
            Welcome to Awesome Blog!<br>
        </p>
        <p>
            This Blog is made for all people who want to get good shape of the body!!
        </p>

=>userがログインしているときは投稿機能とユーザーの情報を表示するがログインしていないときはAwesome Blogを表示するようにする

views/shared/_user_info.html.erb
   <%= link_to gravatar_for(@user, size: 52), @user%>
   <h1>
      <%= @user.name%> #usersデーブルのnameカラム
   </h1>
   <span>
        <%= pluralize(@user.microposts.count, "micropost")%>
     #pluralizeヘルパー...最初の引数に整数があると、それに基づいて2番目の引数である英単語が複数形に変化したものが渡される。
   </span>
views/shared/_micropost_form.html.erb
 <%= form_for(@micropost) do |f| %> #特定のモデルに特化したフォームを作りたい → form_for
    <div>
        <%= f.text_area :content, placeholder: "Compose new micropost...", class: "w-100"%>
    </div>
    <%= f.submit "Post", class: "btn btn-block btn-primary" %>
 <% end %>

=>form_forメソッドを使うとモデルのインスタンスを渡すだけで自動的にRailsが処理してくれる(RESTfulなリソースを使っている場合)
form_for(@micropost)の@micropostがすでに保存されていた場合にはupdateアクション、未保存の時はcreateアクションを、Railsは自動的に選んでくれる※@micropostは後でhomeコントローラーで定義する

user_info.JPG

micropostsコントローラーのcreate,destroyアクションにアクセスできるのはログインを正しくしたユーザだけに制限する

controllers/microposts_controller.rb
 before_action :only_loggedin_users, only: [:create, :destroy]
 
 def create
 end

 def destroy
 end

=>before_actionをすることによりURLから直接アクセスされることを防ぐ(ログインしていなければログインページにとぶ)

micropostsコントローラーの中身を記載していく

controllers/microposts_controller.rb
 before_action :only_loggedin_users, only: [:create, :destroy]
 
 def create
    @micropost = current_user.microposts.build(micropost_params)
     #microposts_paramsとは下のprivateで定義したもの
     #.build≒.new
    if @micropost.save
        flash[:success] = "Successfully saved!"
        redirect_to root_url
    else
        flash[:danger] = "Invalid content. Try again."
        redirect_to root_url
    end
 end

 def destroy
 end

 private
 def micropost_params
    params.require(:micropost).permit(:content)
 end

=>投稿内容を@micropostに格納し保存するに成功したらflashメッセージを表示させ(flash[:success]=)homeページに投稿を反映させる(redirect_to root_url)

controllers/static_pages_controller
 class StaticPagesController < ApplicationController
    def home
        @micropost = current_user.microposts.build if logged_in? #1対多の場合では、「関連付けメソッド名.build」となる
    end

    def about
    end

    def contact
    end
 end

=>現在ログインしているユーザーモデルに紐づく投稿のオブジェクトを作成する

▼すべての投稿を表示する

views/static_pages/home.html.erb
<% if logged_in?%>
    <div class="row">
        <aside class="col-3">
            <section>
                <%= render 'shared/user_info' %>
            </section>
            <section>
                <%= render 'shared/micropost_form' %>
            </section>
        </aside>


     <!-- Microposts here -->
     <div class="col-9">
        <h3>Micropost Feed</h3>
***        <%= render 'shared\feed'%>
     </div>

    </div>
    <% else %>

=>_feed.html.erbに投稿一覧を表示するようにする

controllers/static_pages_controller
 def home
     #@micropost = current_user.microposts.build if logged_in?
     if logged_in?
          @micropost = current_user.microposts.build
          @feed_items = current_user.feed.paginate(page: params[:page], per_page: 12)
          #user.rbで定義したfeedメソッドをの取得結果を@feed_itemsに格納する
          @user = current_user
     end
 end

=>homeアクションのリファクタリングを行う。

models/user.rb#feed
///
 def feed
      Micropost.where("user_id = ?", id)
 end
///

=>この部分がいまいち理解できない

views/shared/_feed.html.erb
    <% if @feed_items.any? %>
       <ol>
           <%= render partial: 'shared/feed_item', collection: @feed_items %>
       </ol>
       <%= will_pagenate @feed_items %>
    <% end %>
views/shared/_feed_item.html.erb
   <li class="col-12 my-4">
      <%= link_to gravatar_for(feed_item.user), feed_item.user %>
      <span class="user">
          <%= link_to feed_item.user.name, feed_item.user %>
      </span>
      <h4><%= feed_item.content %></h4>
      <span class="timestamp">
          Posted <%= time_ago_in_words(feed_item.created_at) %> ago.
      </span>
   </li>

feed.JPG
👇
feed_item.JPG

controllers/microposts_controller.rb#create
///
def create
    @micropost = current_user.microposts.build(micropost_params)
    if @micropost.save
        flash[:success] = "Successfully saved!"
        redirect_to root_url
    else
***        @feed_items = []
        flash[:danger] = "Invalid content. Try again."
        redirect_to root_url
    end
 end
///

=>@feed_items = []を加えることで@feed_itemsの中に何も入っていない(nil)の時に発生するエラーを防ぐ

削除機能を作る

views/microposts/_microposts.html.erb
<li>
   <h4><%= micropost.content%></h4>
   <span class="timestamp">
        Posted <%= time_ago_in_words(micropost.created_at) %> ago.
   </span>
***
   <% if current_user?(micropost.user) %>
       <%= link_to "delete", micropost, method: :delete,
                                        data: { confirm:"Are you sure?"} 
                                        title: micropost.contentn %>
   <% end %>
***
</li>

=>ログインしているユーザーのshowページにだけ削除機能があらわれるようにする

views/shared/_feed_item.html.erb
<li class="col-12 my-4">
      <%= link_to gravatar_for(feed_item.user), feed_item.user %>
      <span class="user">
          <%= link_to feed_item.user.name, feed_item.user %>
      </span>
      <h4><%= feed_item.content %></h4>
      <span class="timestamp">
          Posted <%= time_ago_in_words(feed_item.created_at) %> ago.
      </span>
***
      <% if current_user?(feed_item.user) %>
          <%= link_to "delete", feed_item, method: :delete,
                                           data: { confirm: "You sure?"}
                                           title: feed_item.content %>
       <% end %>
***
 </li>

destroyアクションの中身を記載する

controllers/microposts_controller.rb#destroy
 def destroy
     Micropost.find(params[:id]).destroy
     redirect_to root_url
 end
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?