LoginSignup
0
0

More than 3 years have passed since last update.

Railsチュートリアルメモ - 第13章

Posted at

メモの目次記事はこちら

公式Railsチュートリアル第13章へのリンク

サマリ

  • マイクロソフトの表示、投稿、削除
    • モデルの関連付け(has_manyおよびbelongs_to
    • モデルを使ったレコードの取得(取得条件、並び順、取得件数の指定)
    • ラムダ式 (Stabby lambda) を使ったProcオブジェクトの生成
  • Homeページの動的な出し分け
  • CarrierWaveを使った画像ファイルのアップロード
  • ImageMagick(+MiniMagick)を使った画像ファイルのリサイズ
  • 本番環境でのfogを使ったS3への画像アップロード

ポイント

  • rails generate modelの際、referencesを指定するとFKの指定を行ってくれる

e.g. rails generate model Micropost content:text user:referencesを実行した場合

class Micropost < ApplicationRecord
   belongs_to :user
end
  • モデルの関連付けを行うと、1対Nの1側からN側のオブジェクトを生成することができ、N側のオブジェクトには1側のオブジェクトのidが設定される。

    • e.g.
      • user.microposts.create
      • user.microposts.create! => !をつけると生成失敗時に例外を発生させる
      • user.microposts.build
        • buildメソッドはオブジェクトを返すがデータベースに反映はしない
  • モデル内でdefault_scopeを指定することで、並び順を指定することができる

default_scope -> { order(created_at: :desc) }
  • ->というラムダ式は、ブロックを引数に取り、Procオブジェクトを返す
  • Procオブジェクトは、callメソッドが呼ばれたとき、ブロック内の処理を評価する
  • モデルの関連付けをした1対多の1側にdependent: :destroyを付与しておくと、1側のオブジェクトが削除された際に、多側のオブジェクトも一緒に削除される
  • orderメソッド、takeメソッドを使って取得するレコードの並び順と件数を指定できる
User.order(:created_at).take(6)
  • whereメソッドでレコードの取得条件を指定できる。?句を使うことで、変数をエスケープし、SQLインジェクションを防ぐことができる。
  def feed
    Micropost.where("user_id = ?", id)
  end
  • フォーム内でバリデーションエラーがあった場合、form_forのブロック変数のobject属性にエラーが入る
  • errorパーシャルなどにrenderから変数を引き渡す場合、第二引数にハッシュを指定する e.g.
  <%= form_for(@user) do |f| %>
  <%= render 'shared/error_messages', object: f.object %>
  <% end %>
<% if object.errors.any? %>
<div id="error_explanation">
    <ul>
        <% object.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
        <% end %>
    </ul>
</div>
<% end %>

renderには以下の使い方がある

  1. 引数ががアクション名(new, editなど) => アクションに対応したerbの描画
  2. 引数がパーシャル => パーシャルの描画(第二引数に与えた変数をパーシャル内で使用できる)
  3. 引数がインスタンス変数 => インスタンス変数に対応したパーシャルを探して描画
    • e.g. render @feed_items@feed_itemsの中身がmicropostであれば_micropostパーシャルを探して描画
  • フォームが含まれる画面を描画する際は、form_for(@インスタンス変数)の@インスタンス変数をbuildして空のオブジェクトを用意してから描画する必要がある。
  • フォームが送信されたら改めてparamsから取得した値を使用して@インスタンス変数をbuildしsaveする。
  • erb内のlink_toメソッドにdata: { confirm: "You sure?" }を渡すとリンククリック時に確認のダイアログが表示される
  • redirect_to request.referrerと記載すると、一つ前のページにリダイレクトさせられる

  • CarrierWaveを使った画像ファイルの取り扱い手順

    • Gemfileにcarrierwaveを追加し、bundle install
    • rails generate uploader Xxxでアップローダーを作成
    • モデルにmount_uploader :picture, PictureUploaderを追加
    • ビューにimage_tagを追加
      • <%= image_tag micropost.picture.url if micropost.picture? %>
<span class="picture">
    <%= f.file_field :picture %>
</span>
  • モデルに独自定義したバリデーションを追加する場合は、validatesではなくvalidateを使用する

感想

  • 終盤のコンテンツだけあってなかなか内容が盛りだくさんだった。
  • リスト13.50で空の配列(@feed_items = [])を追加している箇所は、_feed.html.erbの方を以下のように変えた方がわかりやすい気がした。
<% if @feed_items && @feed_items.any? %>
  • ただ、これだと空の配列追加と同様、フィードの一覧が表示されないので、普通にredirect_to root_urlでHomeにリダイレクトすればよいのではと思ってやってみたが、リダイレクトするとflashメッセージが表示されずエラーが発生したことがわからない。やはりrender 'static_pages/home'は必要なよう。

  • uploader導入後のローカルテストがredになり以下のERRORが表示された。

    • NameError: uninitialized constant Micropost::PictureUploader app/models/micropost.rb:4:in <class:Micropost>' app/models/micropost.rb:1:in'
  • サーバーを再起動しても解消せず原因が分からなかったが、一度VSCodeのすべてのターミナルを閉じてから再度開き直して実行したところgreenになった。

  • herokuにpushした際、以下のエラーが発生した。

remote:  !
remote:  !     Failed to install gems via Bundler.
remote:  !
(省略)
To https://git.heroku.com/xxx.git
 ! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to 'https://git.heroku.com/xxx.git'
  • herokuはpushされた際にbundle installも実行するようで、そこでこけるとpushがエラーになる模様(たしかにここまで一度もherokuでbundle installをしなかったが、勝手にやってくれていたらしい)
  • bundle installがこけた原因はheroku config:setでAWSクレデンシャルを環境変数に設定していなかったことが原因のようで設定してからpushすると正常に動作した。
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