ドットインストールのRubyOnRails入門で躓く場所

ドットインストールのRubyOnRails入門で躓く場所があったので整理する。

コマンド関係

ps aux | grep puma #プロセスの終了番号を調べる

ルーティング

resources :リソース名 [, オプション]
resourcesはコントローラーのルーティングを自動生成する。リソース名にはコントローラーの名前を指定する

root
rootはルートのURLを指定する。引数はコントローラーとアクションを指定する

Rails.application.routes.draw do
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
  resources :posts #コントローラーのルーティングを自動生成する。
  root("posts#index") #rootのurlを指定
end

ルーティングの削減
resourcesにonlyオプションを設定するとルーティングを削減することができる

コントローラー

find()
findは引数にidを渡す。

find_byの場合はfind_by(id: params[:id])のように書くが、
findの場合は単にfind(params[:id])と書くことができる

ビュー

link_to()のPrefix指定
link_toのprefix指定
Prefixはルーティングをresourcesで自動生成したときにはじめから指定されている。プレフィックスを用いることでURLを簡単に表現できる。Prefix名_pathとすることでURLを指定可能。ただしURLPatternにidがある場合はidも指定する

form_for()でフォーム送信とフォーム作成を行う
form_for
form_tag()メソッドの引数にはリンク先を指定するが、form_forの場合は引数にモデルを指定する。(よくわからないけどインスタンス変数でも可。フォームの送信先にidを指定するときなど)またオプションでurlを指定することによって、フォームの送信先を指定。ブロック変数|f|を使用することにより、入力フォームを簡単に作成することができる。

<h2>編集する</h2>
<%= form_for @post, url:post_path(@post.id) do |f|%>
<% if @error_message%>
<span class="error_message"><%= @error_message%></span>
<%end%>
<p><%= f.text_field :title%></p>
<p><%= f.text_area :body%></p>
<p><%= f.submit%></p>
<%end%>

form_for()を使った場合の受け取りは、params[:title] のように書くとうまく受け取れないので、

params.require(:post).permit(:title, :body)のように書く必要がある。

render()
renderの引数指定は、単にアクション名のみでも可。

モデル

references
referencesはモデル作成時にカラムにreferencesを指定すると、他のテーブルへの外部キーを作成してくれる。外部キーはテーブルを紐づけるためのもので、データベースの知識がないと理解に苦しむかもしれない。

class CreateComments < ActiveRecord::Migration[5.2]
  def change
    create_table :comments do |t|
      t.string :body
      t.references :post, foreign_key: true

      t.timestamps
    end
  end
end
class Comment < ApplicationRecord
  belongs_to :post
end

モデル作成時にreferencesを使用するとモデルファイルに自動的にbelong_toが定義される。
belongs_toの意味としては上の例でいくと「commentモデルからpostモデルを参照します」という意味になる(正直ちょっとよくわからない)

has_many
has_manyはなぜかリファレンスがない。よくわからないけど「1対多の関係」というものを表すことができるようになる。

class Post < ApplicationRecord
  has_many :comments
  validates :title, {presence: true}
  validates :body, {presence: true}
end

意味的には上の例でいくと「1つのpostオブジェクトに対して複数のcommentオブジェクトが存在する」という意味になる。commentsと複数系になっている点に注目。(正直ちょっとよくわからない)。

複数のオブジェクトが存在するモデルのコントローラーを定義するときは複数系にしなければならない。

rails g controller Comments

dependent: :destroy

class Post < ApplicationRecord
  has_many :comments, dependent: :destroy
  validates :title, {presence: true}
  validates :body, {presence: true}
end

このような構文だった場合postを削除するとcommentも削除される

form_forに複数のオブジェクトを渡す

ルーティングに2つのモデルがかかれているときは、複数のモデルオブジェクトを渡す必要がある(これも正直ちょっとよくわからない)。form_forをかっこつきにしえ配列形式で記述する。

<h3>コメント</h3>
<%= form_for([@post, @post.comments.build]) do |f|%>
<% if @error_message%>
<span class="error_message"><%= @error_message%></span>
<%end%>
<p><%= f.text_area :body%></p>
<p><%= f.submit%></p>
<%end%>

form_forにurlを指定していなけど、ルーティングにresourcesを使っている場合はrailsが自動でおくりさきを判別してくれるらしい。ほんとによくからない。

build
buildはモデルオブジェクトを生成する。