[Day15 Rails Tutorial]第十三章完|いよいよ投稿機能を実装[13.1〜13.5]

Day15です!

いよいよ終盤!明日までに終わらせたい!

今日もがんばっていきましょー!

読んでいただいている方、いつもありがとうございます!

初心者なもので、たまに間違った内容もあるかと思います。

その際にはコメントやTwitterでご指摘いただけると幸いです!

 

[Day15]第十三章13.1〜13.5作業ログ

今回は投稿機能を追加していきます

前回までのチュートリアルで、ユーザー の作成とか削除とかに関する実装は完了しました。

今回はログインしているユーザーから、投稿ができるようにしていきます。

ここでは、めっちゃくちゃ序盤にやった、ブログの投稿機能に似た箇所も登場するので、楽しみです。

 

Micropostモデルの作成

とりあえずは、投稿を保存するためのMicropostモデルを作成していきます。

1つ注意点があって、投稿はどのユーザーがしたものなのかを紐づけておきたいこと。

そのために、ちょびちょび設定があります。

rails generate model Micropost content:text user:references

app/models/micropost.rb
class Micropost < ApplicationRecord
  belongs_to :user
  validates :user_id, presence: true
  validates :content, presence: true, length: { maximum: 140 }
end
”db/migrate/[timestamp_create_microposts.rb”]
class CreateMicroposts < ActiveRecord::Migration[5.0]
  def change
    create_table :microposts do |t|
      t.text :content
      t.references :user, foreign_key: true
 
      t.timestamps
    end
    add_index :microposts, [:user_id, :created_at]
  end
end

rails db:migrate

 

User/Micropostの関連付け

さっきのbelongs_toとここで設定するhas_manyでUser/Micropostを関連付けます。

app/models/user.rb
class User < ApplicationRecord
  has_many :microposts
  ...
end

これによって、ユーザーと投稿が関連付けられました。

belongs_to/has_many関連付けを使うことで、次に示すようなメソッドをRailsで使えるようになります。

 

Micropostを降順にする

今のままだと、投稿は古い順版に表示されます。

ツイッターやブログみたいに新しい投稿がはじめに表示されるようにします。

app/models/micropost.rb
class Micropost < ApplicationRecord
  belongs_to :user
  default_scope -> { order(created_at: :desc) }
  validates :user_id, presence: true
  validates :content, presence: true, length: { maximum: 140 }
end

->はラムダ式と言うみたいです。むずかしめらしいのでまた今度理解しよう。

 

ユーザーが削除されたら、そのユーザーの投稿も消えるように

ユーザーが削除されたときに、そのユーザーに紐付いた (そのユーザーが投稿した) マイクロポストも一緒に削除されるようにしたいです。

データベースの節約やセキュリティ面で大事。

こんな感じで依存関係を示してあげると実装できるそう。

app/models/user.rb
class User < ApplicationRecord
  has_many :microposts, dependent: :destroy
  ...
end

 

投稿を表示していく

showアクションで投稿を表示できるようにします。

app/views/users/show.html.erb
<% provide(:title, @user.name) %>
<div class="row">
  <aside class="col-md-4">
    <section class="user_info">
      <h1>
        <%= gravatar_for @user %>
        <%= @user.name %>
      </h1>
    </section>
  </aside>
  <div class="col-md-8">
    <% if @user.microposts.any? %>
      <h3>Microposts (<%= @user.microposts.count %>)</h3>
      <ol class="microposts">
        <%= render @microposts %>
      </ol>
      <%= will_paginate @microposts %>
    <% end %>
  </div>
</div>

ここで、マイクロソフトを表示するパーシャルはこんな感じ。

app/views/microposts/_micropost.html.erb
<li id="micropost-<%= micropost.id %>">
  <%= link_to gravatar_for(micropost.user, size: 50), micropost.user %>
  <span class="user"><%= link_to micropost.user.name, micropost.user %></span>
  <span class="content"><%= micropost.content %></span>
  <span class="timestamp">
    Posted <%= time_ago_in_words(micropost.created_at) %> ago.
  </span>
</li>

あと、ページネーションもちょっと変えてあげないとだめです。

app/controllers/users_controller.rb<br />
class UsersController < ApplicationController
  ...
  def show
    @user = User.find(params[:id])
    @microposts = @user.microposts.paginate(page: params[:page])
  end
  ...
end

あとCSSもチュートリアルにあるように調節しました。

 

実際に投稿機能を実装

ここまでで投稿の表示ができるようになりました。

ここからは、投稿機能をつけていきます。

今回はビューは必要なく、createとdestroyアクションだけでOKです。

まずはルーティング。

config/routes.rb
Rails.application.routes.draw do
  root   'static_pages#home'
  get    '/help',    to: 'static_pages#help'
  get    '/about',   to: 'static_pages#about'
  get    '/contact', to: 'static_pages#contact'
  get    '/signup',  to: 'users#new'
  get    '/login',   to: 'sessions#new'
  post   '/login',   to: 'sessions#create'
  delete '/logout',  to: 'sessions#destroy'
  resources :users
  resources :account_activations, only: [:edit]
  resources :password_resets,     only: [:new, :create, :edit, :update]
  resources :microposts,          only: [:create, :destroy]
end

 

これからコントローラーの設定をしていきます。

投稿するのは、ログインユーザーに限定したいです。

この設定は、users_controller.rbと同じなので、この中身をapplication_controller.rbに移すことで、microposts_controller.rbからも使えるようになります。

app/controllers/microposts_controller.rb
class MicropostsController < ApplicationController
  before_action :logged_in_user, only: [:create, :destroy]
 
  def create
  end
 
  def destroy
  end
end

投稿機能はこんな感じで実装。

app/controllers/microposts_controller.rb
class MicropostsController < ApplicationController
  before_action :logged_in_user, only: [:create, :destroy]
 
  def create
    @micropost = current_user.microposts.build(micropost_params)
    if @micropost.save
      flash[:success] = "Micropost created!"
      redirect_to root_url
    else
      render 'static_pages/home'
    end
  end
 
  def destroy
  end
 
  private
 
    def micropost_params
      params.require(:micropost).permit(:content)
    end
end

 

削除機能の実装

app/controllers/microposts_controller.rb
class MicropostsController < ApplicationController
  before_action :logged_in_user, only: [:create, :destroy]
  before_action :correct_user,   only: :destroy
  ...
  def destroy
    @micropost.destroy
    flash[:success] = "Micropost deleted"
    redirect_to request.referrer || root_url
  end
 
  private
 
    def micropost_params
      params.require(:micropost).permit(:content)
    end
 
    def correct_user
      @micropost = current_user.microposts.find_by(id: params[:id])
      redirect_to root_url if @micropost.nil?
    end
end

 

他にもいろいろと設定がありましたが、ここでは割愛します!

今回はちょっと雑ですが、こんな感じで終了!

メモ

個別のテストを実行するコマンド

rails test test/models/micropost_test.rb

SQLインジェクション

SQLインジェクション(英: SQL Injection)とは、アプリケーションのセキュリティ上の不備を意図的に利用し、アプリケーションが想定しないSQL文を実行させることにより、データベースシステムを不正に操作する攻撃方法のこと。また、その攻撃を可能とする脆弱性のことである。

wikipedia

 

[Day15]まとめ

  • 学習範囲:13.1〜13.5
  • 学習時間:4時間10分
  • 総学習時間:63時間10分
  • 反省点:この記事が雑。まとめ直すのに時間がかかり過ぎな気がする。あんまり時間的コスパが良くない。
  • 備考:明日で1周終わらせたい。

読んでいただいている方、いつもありがとうございます!

初心者なもので、たまに間違った内容もあるかと思います。

その際にはコメントやTwitterでご指摘いただけると幸いです!

 

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です