Rails チュートリアル13章
今回は13章をやっていく中で必要だと思ったところをメモしていきます。
・複合キーインデックス
micropostのマイグレーションファイル
class CreateMicroposts < ActiveRecord::Migration[6.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
複数のキーをセットで扱うことができる。
こうすることでuser_idに紐付けられたmicropostsを作成順(今回は作成の逆順にする)で取り出す
・default scope
Micropostモデル
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
このようにして作成の逆順で取り出すよう設定している。
・time_ago_in_wordsメソッド
app/views/microposts/_micropost.html.erbapp/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>
何分前とかって出るようにする。例えば3分前、3時間前、3日前。
マクロポストの作成(build)
root_pathのhomeでuserに紐ずくmicropostを作成する。
何かに紐付いたものを生成する場合、newではなくbuildになる。
作成はhomeで保存はmicropostのcreate
app/controllers/static_pages_controller.rb
class StaticPagesController < ApplicationController def home @micropost = current_user.microposts.build if logged_in?
buildになっている end def help end def about end def contact end end
app/views/static_pages/home.html.erb
<% if logged_in? %> <div class="row"> <aside class="col-md-4"> <section class="user_info"> <%= render 'shared/user_info' %> </section> <section class="micropost_form"> <%= render 'shared/micropost_form' %> </section> </aside> </div> <% else %> <div class="center jumbotron"> <h1>Welcome to the Sample App</h1> <h2> This is the home page for the <a href="https://railstutorial.jp/">Ruby on Rails Tutorial</a> sample application. </h2> <%= link_to "Sign up now!", signup_path, class: "btn btn-lg btn-primary" %> </div> <%= link_to image_tag("rails.svg", alt: "Rails logo", width: "200px"), "https://rubyonrails.org/" %> <% end %>
app/views/shared/_user_info.html.erb
<%= link_to gravatar_for(current_user, size: 50), current_user %> <h1><%= current_user.name %></h1> <span><%= link_to "view my profile", current_user %></span> <span><%= pluralize(current_user.microposts.count, "micropost") %></span>
app/views/shared/_micropost_form.html.erb
<%= form_with(model: @micropost, local: true) do |f| %> <%= render 'shared/error_messages', object: f.object %> <div class="field"> <%= f.text_area :content, placeholder: "Compose new micropost..." %> </div> <%= f.submit "Post", class: "btn btn-primary" %> <% end %>
app/controllers/microposts_controller.rb
class MicropostsController < ApplicationController
before_action :logged_in_user, only: [:create, :destroy]
before_action :correct_user, only: :destroy
def create
@micropost = current_user.microposts.build(micropost_params)
buildを使ってる
@micropost.image.attach(params[:micropost][:image])
if @micropost.save
redirect_to root_url
else
@feed_items = current_user.feed.paginate(page: params[:page])
render 'static_pages/home'
end
end
feed
class User < ApplicationRecord . . . # 試作feedの定義 # 完全な実装は次章の「ユーザーをフォローする」を参照 def feed Micropost.where("user_id = ?", id) end private . . . end
?を使うことでidをエスケープしている
app/controllers/static_pages_controller.rb
class StaticPagesController < ApplicationController def home if logged_in? @micropost = current_user.microposts.buildapp/views/static_pages/home.html.erb
このmicropostは先ほど書いたやつ(build)なので関係ない @feed_items = current_user.feed.paginate(page: params[:page]) end end def help end def about end def contact end end
<% if logged_in? %> <div class="row"> <aside class="col-md-4"> <section class="user_info"> <%= render 'shared/user_info' %> </section> <section class="micropost_form"> <%= render 'shared/micropost_form' %> </section> </aside> <div class="col-md-8"> <h3>Micropost Feed</h3> <%= render 'shared/feed' %> </div> </div> <% else %> . . . <% end %>
app/views/shared/_feed.html.erb
<% if @feed_items.any? %> <ol class="microposts"> <%= render @feed_items %> </ol> <%= will_paginate @feed_items %> <% end %>
<%= render @feed_items %>
@feed_itemsはMicropostsのクラスを持っているため、micropostsのパーシャルを呼び出すことができた。
app/views/microposts/_micropost.html.erbを呼び出してる
microposts作成失敗の場合に備えて
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 @feed_items = current_user.feed.paginate(page: params[:page]) render 'static_pages/home' end end def destroy end private def micropost_params params.require(:micropost).permit(:content) end end
ページネートでエラーが出るので解決。
micropostsをcreateするcreateアクションがMicropostsコントローラーにあるので、Micropostsコントローラーでページネートしようとしている。
そこで、コントローラーとアクションを指定してあげることで解決する。
app/views/shared/_feed.html.erb
<% if @feed_items.any? %> <ol class="microposts"> <%= render @feed_items %> </ol> <%= will_paginate @feed_items, params: { controller: :static_pages, action: :home } %> <% end %>