サカナ未遂

プログラミング、筋トレ、子育て

独習Ruby on Railsを読んだ

こないだ現場Railsを読んだら、Railsに知らないことや忘れてるところが結構あった。 blog.tera-chan3700.com

一応業務でRails触ってるけど、既存コードの改修だったりでなんとなくこなせていたけど、業務で使ってる以上のことが全然成長してないので、まだまだ基礎的なとこ固めようと思い、今度は独習Ruby on Railsを読むことにした。

独習Ruby on Rails

独習Ruby on Rails

  • 作者:小餅 良介
  • 発売日: 2019/06/19
  • メディア: 単行本(ソフトカバー)

3章までは、軽く読んだのでまとめてない。 4章以降で初めて知ったことなどメモしておく。

4章

rails dbconsole(rails db)

実装されてるDBのコマンドラインツールを起動してくれる。 SQLite3/MySQL/PostgreSQLの3種類が対象。 --sandboxオプションは使用できない。

rails stats

現在のアプリケーションのRubyコード統計情報を表示するコマンド。

rails notes

ソースコードに埋め込んだコメントの中からTODO、FIXME、OPTIMIZEのキーワードがあるものを抽出し内容と場所を一覧で表示してくれる。

6章

フォームオブジェクト

現場Railsでもちょっとだけ記載があったフォームオブジェクト。 特定のモデルに限定されないか、DBの登録に直接関係ない入力のバリデーションは入力専用のオブジェクト(フォームオブジェクト)を使うことで整理ができる。 利用承諾など、チェックボックスだけがあり、対応するモデルがない場合などに使える。 app/forms/acceptance.rb みたいな感じでファイルを作成し、ActiveModelを継承させることでバリデーションの機能を実装することができる。

Validateクラスで共通の独自ヘルパーを実装

app/validators配下にActionModel::EachValidatorを継承したクラスを作り、validate_eachを実装することでモデル共通のバリデーションを作成することができる。 バリデーションをまとめることができるのは知らなかった。

コールバッククラスの共通化

バリデーションと同様コールバックも共通化できる。 app/callbacks配下にクラスを作成し、中にバリデーションの処理を実装する。

class MessageOut
  def self.before_validation(obj)
    # バリデーション処理
  end
end

呼び出し側

class Book < ApplicationREcord
  before_validation MessageOut

  ....
end

こんな感じ。

7章

ポリモーフィック関連

子モデルで複数の親モデルを持つ時にポリモーフィック関連を使う。 userモデル、bookモデルを親に持つpictureモデルを作る場合、以下のようにmigrationファイルを作成

class CreatePictures < ActiveRecord::Migration[6.1]
  def change
    create_table :pictures do |t|
      t.references :imageable, polymorphic: true
      t.string :path_name

      t.timestamps
    end
  end
end

db:migrationするとPictureモデルは以下のようになる

class Picture < ApplicationRecord
  belongs_to :imageable, polymorphic: true
end

各親モデルにPictureモデルへの関連と行う。 bookモデル

class Book < ApplicationRecord
  has_many :pictures, as: :imageable
end

userモデル

class User < ApplicationRecord
  has_many :pictures, as: :imageable
end

こうすることによって、PictureはUserとBookを親に持つことができる。

仮想属性

テーブルカラムを持たない仮想的な属性(attributes API)を作ることができる。 Addressモデルに対してattributeを追加することで使用できる。

class Address < ApplicationRecord
  attribute :location, :string, default: '東京都葛飾区'
end

8章

コレクションルートとメンバールート

  • コレクションルート 複数のリソースを対象とするルートかidを持っていない新規リソースに対するルート

  • メンバールート idパラメータで特定できるルート

shallowルート

親子関係にあるリソースで子リソースをidで一意に特定できる場合、子のIDだけでアクセスできるようにするのにshallowを使う。

shallow do
  resources :user do
    resources :hobbies
  end
end

または

resources :users, shallow: true do
  resources :hobbies
end

のように設定する。

リソースフルルートのグループ化

名前空間によるリソースルートのグループ化を行った場合、名前空間はコントローラのファイルが配置されるディレクトリ名に相当する。 なのでコントローラは「名前空間名」ディレクトリに移動させる必要がある。

リソースルートだけをグループ化したい場合はscopeメソッドを使う。 scopeの場合だとコントローラの配置移動の必要はない。

ルートの共通化

同じ目的のルートパス名を複数で使用する場合は、concernを使うことで共通化できる。

# 共通ルート
concern :searchable do
  get 'search', on: :collection
end

# 各リソースフルルートで共通ルートを紐付ける
resources :user,s concerns: :searchable
resources :books, concerns: :searchable

9章

respond_toメソッド

リクエストされるフォーマットによてレスポンスを柔軟に変更することができる。

def show
  @user = User.find(params[:id])
  respond_to do |format|
    format.html
    format.json {render json: @user}
  end
end

上記のコードの場合

  1. http://localhost:3000/users/1
  2. http://localhost:3000/users/1.json

で1の場合html、2の場合jsonでレスポンスを返してくれる。

10章以降

viewに関するとことか、とりあえず直近の業務では触ることないのでサラッと読んで終わり。 必要な時が来たら読み直そうと思う。

所感

現場Railsを読んだばかりだし同じような内容の箇所は飛ばして読んだが、 一つ一つの機能がより細かく説明されている。特に章末の練習問題がためになる。 写経だけしてプログラム動かすとできた気になるが、練習問題で自分で考えてコード書くとやっぱり身に付く。 scaffoldでさえ本見ないと、どうやるんだっけ?となってるので良い機会だった。 同じ技術の本を続けて読むと、1冊目は結構時間かかるけど、2冊目以降はある程度知ってる箇所飛ばして知らないとこにフォーカスできるので、この流れで次はパーフェクトRuby on Raisを読んでみようかと思う。