Railsガイド6.0読み直す ~9章 レイアウトとレンダリング
1 AttributeMethodsモジュール
1 概要: 部品を組み上げる
コントローラの責務は、リクエストを扱うプロセス全体の流れを組織的に調整すること
重い処理はモデルに寄せる。これはみんなご存知Fat Controllerにしないことやね。
2 レスポンスを作成する
「設定より規約 (CoC: convention over configuration)」
render :edit render action: :edit render "edit" render "edit.html.erb" render action: "edit" render action: "edit.html.erb" render "books/edit" render "books/edit.html.erb" render template: "books/edit" render template: "books/edit.html.erb" render "/path/to/rails/app/views/books/edit" render "/path/to/rails/app/views/books/edit.html.erb" render file: "/path/to/rails/app/views/books/edit" render file: "/path/to/rails/app/views/books/edit.html.erb"
種類多すぎて草
render :edit 派
layout指定することたまにあるよね。スクールでやった。
ユーザーによって権限分けたい時とか
redirect_back(fallback_location: root_path)
たまに使うよね
3 レイアウトを構成する
アセットタグヘルパー
auto_discovery_link_tag
javascript_include_tag
stylesheet_link_tag
image_tag
video_tag
audio_tag
既知が多かった
Railsガイド6.0読み直す ~8章 Action Viewの概要
1 Action Viewについて
ERBってEmbedded Rubyの略だったんだ
2 Action ViewをRailsで使用する
特になし
3 テンプレート、パーシャル、レイアウト
builder → xmlを出力
slimだけど、上記みたいに書けるからいいよねー
4 パーシャルレイアウト
パーシャルに独自のレイアウトを適用することができます。
→初めてみた。
5 ビューのパス
prepend_view_pathメprepend_view_pathメソッドやappend_view_pathメソッドを用いることで、パスの解決時に優先して検索される別のディレクトリを追加できます。
→ 知らんかったー。使う時に思い出せるかどうか
6 Action Viewのヘルパーメソッドの概要
6.1 AssetTagHelper
6.2 AtomFeedHelper
いつ使うん?
6.3 BenchmarkHelper
テンプレート内の1つのブロックの実行時間測定と、結果のログ出力に使用します
→すげぇ
6.4 CacheHelper
ビューの断片をキャッシュするメソッド
6.5 CaptureHelper
<% @greeting = capture do %> <p>ようこそ!日付と時刻は<%= Time.now %>です</p> <% end %>
@greeting を使える → 結構便利ね
content_for も cachehelperだったのか
6.6 DateHelper
めっちゃ種類ある
6.7 DebugHelper
6.8 FormHelper
一番使うやつ
fields_forは黒魔術感
6.9 FormOptionHelper
collection_select とかめっちゃ使う
ここはかなり大事そう
6.10 FormTagHelper
Active Recordオブジェクトに依存しない点がFormHelperと異なります
ここがポイント、form内で、そのモデル以外の項目送るケースでかなり使う
6.11 JavaScriptHelper
6.12 NumberHelper
え、%とかMBとか、区切りとかあるのか!!感動した
6.13 SanitizeHelper
6.13 CsrfHelper
7 ローカライズされたビュー
helper種類多すぎ。
数値変換系のNumberHelperが一番の気付き。
Railsガイド6.0読み直す ~7章 Active Model の基礎
PostgreSQL と 複数のデータベース利用はスキップ
1 AttributeMethodsモジュール
class Person include ActiveModel::AttributeMethods attribute_method_prefix 'reset_' attribute_method_suffix '_highest?' define_attribute_methods 'age' attr_accessor :age private def reset_attribute(attribute) send("#{attribute}=", 0) end def attribute_highest?(attribute) send(attribute) > 100 end end person = Person.new person.age = 110 person.age_highest? # true person.reset_age # 0 person.age_highest? # false
使い方よくわからなかったけど、この図で理解できた。
2 Callbacksモジュール
class Person extend ActiveModel::Callbacks define_model_callbacks :update before_update :reset_me def update run_callbacks(:update) do # updateメソッドがオブジェクトに対して呼び出されるとこのメソッドが呼び出される end end def reset_me # このメソッドは、before_updateコールバックで定義されているとおり、updateメソッドがオブジェクトに対して呼び出される直前に呼び出される。 end end
updateだけじゃなく、create等でもいける。 run_callbacksの中で実行するのがミソか
3 Conversionモジュール
4 Dirtyモジュール
5 Validationsモジュール
6 Namingモジュール
7 Modelモジュール
ActiveModel::Model
をinclude
すると、以下のような機能を使えるようになります。
- モデル名の調査
- 変換
- 翻訳
- バリデーション
persisted? は オブジェクトが保存済みかどうかを確認するメソッド
8 シリアライズ
class Person include ActiveModel::Serialization attr_accessor :name def attributes {'name' => nil} end end
上のようにすることで、serializable_hash
を使ってオブジェクトのシリアライズ化ハッシュにアクセスできるようになります。
person = Person.new person.serializable_hash # => {"name"=>nil} person.name = "Bob" person.serializable_hash # => {"name"=>"Bob"}
シリアライズはよくないらしい。
9 Translationモジュール
Person.human_attribute_name('name') # => "Name"
よく使うやつ
10 Lintテスト
11 SecurePasswordモジュール
bcryptっていうgemに依存している
感想
ActiveModelことができることを一言で表すと、
「active record の実現を助けてくれるモジュール群」
Railsガイド6.0読み直す ~6章 Active Record クエリインターフェイス
書いていく。読み応えがありそう
1 データベースからオブジェクトを取り出す
clients = Client.find([1, 10])
→ え、findって複数指定できるのかww 知らなかった
client = Client.take
→ ランダムでレコードを返す。知らなかった
clients = Client.take(2)
→ 引数に最大値とれるんかw
clients = Client.first(3)
→ firstも複数とれる
User.find_each(start: 2000,finish: 5000m, batch_size: 5000) do |user| NewsMailer.weekly(user).deliver_now end
→ User.all.each do だと、メモリ大量消費するからよくない、一旦Userで全部とったあとに処理するのがfind_each。レコードの件数指定も可能。startでキーを指定(例だとidが2000から処理開始)
find_in_batchesは バッチ を個別にではなくモデルの配列としてブロックにyieldするという点が違う。
バッチ処理のところは、慎重になろう
2 条件
以下の書き方は危険であり、避ける必要があります。→SQLインジェクション?
Client.where("orders_count = #{params[:orders]}")
3 並び順
4 特定のフィールドだけを取り出す
5 Limit と Offset
Client.limit(5).offset(30)
上のコードは、最初の30クライアントをスキップして31人目から最大5人のクライアントを返します。このときのSQLは以下のようになります。
直感的
6 グループ
groupもhavingも、あまりActiveRecord使うと意識しないよなー
7 Having
8 条件を上書きする
unscope → 特定の条件を取り除くことができます
only → 条件を上書きできます
reorder → デフォルトのスコープの並び順を上書きします
reverse_order → 並び順が指定されている場合に並び順を逆にします。
rewhere → 既存のwhere条件を上書きします
知らないのいっぱいあるな
9 Nullリレーション
noneメソッドは、チェイン (chain) 可能なリレーションを返します
→ チェーンさせる時に使うらしい
10 読み取り専用オブジェクト
client = Client.readonly.first
readonlyを使うことで変更不可になる
11 レコードを更新できないようにロックする
楽観的ロック (optimistic)
→ 複数のユーザーが同じレコードを編集することを許し、データの衝突が最小限であることを仮定しています
悲観的ロック (pessimistic)
→ データベースが提供するロック機構を使用します。リレーションの構築時にlockを使用すると、選択した行に対する排他的ロックを取得できます。
トランザクション内に処理書くやつ?
12 テーブルを結合する
結合は毎回よくわからなくなる
13 関連付けを一括読み込みする
N+1問題
14 スコープ
スコープをスコープ内でチェイン (chain) させることもできます。
class Article < ApplicationRecord scope :published, -> { where(published: true) } scope :published_and_commented, -> { published.where("comments_count > 0") } end
これ便利。
引数も渡せる。
default_scope { where(active: true) }
→ あんま使わんかもだけど、デフォルト設定もできる。ただ他のscopeより優先されるので注意
15 動的検索
16 Enums
17 メソッドチェインを理解する
18 新しいオブジェクトを検索またはビルドする
find_or_create_by
→ よく使う
find_or_initialize_by
→ インスタンスは生成されるが保存されない
19 SQLで検索する
pluckはまだ謎が深い
Client.select(:id).map { |c| c.id } # または Client.select(:id).map(&:id) # または Client.select(:id, :name).map { |c| [c.id, c.name] }
上は以下に置き換えられます。
Client.pluck(:id) # または Client.pluck(:id, :name)
20 オブジェクトの存在チェック
any?
empty?
many?
あたり
21 計算
sum
average
maximun
minimum
もあるのね
22 EXPLAINを実行する
User.joins(:posts).explain でテーブルの構造見れるのは便利ね
Railsガイド6.0読み直す ~5章 Active Record の関連付け~
書いていく。
1 関連付けを使う理由
モデルとモデルの間には関連付けを行なう必要がありますが、その理由を御存じでしょうか。それは、関連付けを行う事であなたのコードでの共通操作をよりシンプルで簡単にするからです。
だよねー。
2 関連付けの種類
has_one :[子供のモデル] => 親から子供
belongs_to :[親のモデル] => 子供から親
主となる方が has_one で従となる方が belongs_to になる。
belongs_to
has_one
has_many
has_many :through
has_one :through
has_and_belongs_to_many
・belongs_to関連付けで指定するモデル名は必ず「単数形」
2-1 belongs_to
宣言を行ったモデルのすべてのインスタンスは、他方のモデルのインスタンスに「従属(belongs to)」します。
2-2 has_one
belongs_to
とは若干異なります。has_one
関連付けの場合は、その宣言が行われているモデルのインスタンスが、他方のモデルのインスタンスを「まるごと含んでいる」または「所有している」ことを示します
2-3 has_many
has_many
関連付けが使われている場合、「反対側」のモデルでは多くの場合belongs_to
が使われます。has_many
関連付けが使われている場合、そのモデルのインスタンスは、反対側のモデルの「0個以上の」インスタンスを所有します。
2-4 has_many :through
has_many :through
関連付けは、他方のモデルと「多対多」のつながりを設定する場合によく使われます。この関連付けは、2つのモデルの間に「第3のモデル」(joinモデル)が介在する点が特徴です。
2-5 has_one :through
has_one :through
関連付けは、他方のモデルに対して「1対1」のつながりを設定します。この関連付けは、2つのモデルの間に「第3のモデル」(joinモデル)が介在する点が特徴です。それによって、相手モデルの1つのインスタンスとマッチします
2-6 has_and_belongs_to_many
has_and_belongs_to_many
関連付けは、他方のモデルと「多対多」のつながりを作成しますが、through:
を指定した場合と異なり、第3のモデル(joinモデル)が介在しません(訳注: 後述するように結合用のテーブルは必要です)。
↑あまり使ったことない
2-7 has_one or belongs_to
区別の決め手となるのは外部キー(foreign key)をどちらに置くかです(外部キーは、belongs_to
を追加した方のモデルのテーブルに追加されます)。もちろんこれだけでは決められません。データの実際の意味についてもう少し考えてみる必要があります。has_one
というリレーションは、主語となるものが目的語となるものを「所有している」ということを表しています。そして、所有されている側(目的語)の方が、所有している側(主語)を指し示しているということも表しています。たとえば、「供給者がアカウントを持っている」とみなす方が、「アカウントが供給者を持っている」と考えるよりも自然です。つまり、この場合の正しい関係は以下のようになります。
class Supplier < ApplicationRecord has_one :account end class Account < ApplicationRecord belongs_to :supplier end
2-8 has_many :throughとhas_and_belongs_to_manyのどちらを選ぶか
どちらを使うかについてですが、経験上、リレーションシップのモデルそれ自体を独立したエンティティとして扱いたい(両モデルの関係そのものについて処理を行いたい)のであれば、中間にjoinモデルを使うhas_many :through
リレーションシップを選ぶのが最もシンプルです。リレーションシップのモデルで何か特別なことをする必要がまったくないのであれば、joinモデルの不要なhas_and_belongs_to_many
リレーションシップを使うのがシンプルです(ただし、こちらの場合はjoinモデルが不要な代わりに、専用のjoinテーブルを別途データベースに作成しておく必要がありますので、お忘れなきよう)。
2-9 ポリモーフィック関連付け
ポリモーフィック関連付けは、関連付けのやや高度な応用です。ポリモーフィック関連付けを使うと、ある1つのモデルが他の複数のモデルに属していることを、1つの関連付けだけで表現できます。
2-10 自己結合
データモデルを設計していると、時に自分自身に関連付けられる必要のあるモデルに出会うことがあります。たとえば、1つのデータベースモデルに全従業員を格納しておきたいが、マネージャーと部下(subordinate)の関係も追えるようにしておきたい場合が考えられます。この状況は、自己結合関連付けを用いてモデル化できます。
class Employee < ApplicationRecord has_many :subordinates, class_name: "Employee", foreign_key: "manager_id" belongs_to :manager, class_name: "Employee", optional: true end
上のように宣言しておくと、@employee.subordinates
と@employee.manager
が使えるようになります。
自己結合むずい。。
・もし、従業員にマネージャーがいたら、マネージャーを取得 → @employee.manager
・更に、マネージャーに部下がいたら、その部下も取れる
→ @employee.subordinates
わかりやすい
3 ヒントと注意事項
・reload? で更新
1. belongs_to
関連付けを使う場合は、外部キーを作成する必要があります。2. has_and_belongs_to_many
関連付けを使う場合は、適切なjoinテーブルを作成する必要があります。
Active Recordでスコープや次のオプションを使った場合、双方向の関連付けは自動的に認識されません。
:through
:foreign_key
Active Recordは:inverse_of
オプションを提供していて、これを使うと双方向の関連付けを明示的に宣言できます。
class Author < ApplicationRecord has_many :books, inverse_of: 'writer' end class Book < ApplicationRecord belongs_to :writer, class_name: 'Author', foreign_key: 'author_id' end
has_many
の関連付けを宣言するときに:inverse_of
オプションも含めることで、Active Recordは双方向の関連付けを認識するようになります。
4 関連付けの詳細情報
4.1 belongs_to
関連付けの詳細
belongs_to
関連付けは、別のモデルとの間に1対1の関連付けを作成します。データベースの用語で説明すると、この関連付けが行われているクラスには外部キーがあるということです。外部キーが自分のクラスではなく相手のクラスにあるのであれば、belongs_to
ではなくhas_one
を使う必要があります。
4.1.2 belongs_to
のオプション
belongs_to
関連付けでは以下のオプションがサポートされています。
:autosave
:class_name
:counter_cache
:dependent
:foreign_key
:primary_key
:inverse_of
:polymorphic
:touch
:validate
:optional
めちゃくちゃある。。w
4.2 has_one 関連付けの詳細
has_one
関連付けは他のモデルと1対1対応します。データベースの観点では、この関連付けでは相手のクラスが外部キーを持ちます。相手ではなく自分のクラスが外部キーを持っているのであれば、belongs_to
を使うべきです。
has_one
関連付けでは以下のオプションがサポートされます。
:as
:autosave
:class_name
:dependent
:foreign_key
:inverse_of
:primary_key
:source
:source_type
:through
:validate
これもまためちゃくちゃある。読むの疲れるレベル
books books<<(object, ...) books.delete(object, ...) books.destroy(object, ...) books=(objects) book_ids book_ids=(ids) books.clear books.empty? books.size books.find(...) books.where(...) books.exists?(...) books.build(attributes = {}, ...) books.create(attributes = {}) books.create!(attributes = {}) books.reload
ほぼ知ってたな。
5 シングルテーブル継承(STI)
感想
また読みに帰ってくる。量が多い。オプションも多い
Railsガイド6.0読み直す ~4章 Active Record マイグレーション~
3章は上記
Railsガイド6.0読み直す ~3章 Active Record マイグレーション~ - ブシトラの日記
読んでいく。
1 オブジェクトのライフサイクル
コールバックは、オブジェクトの状態が切り替わる「前」または「後」にロジックをトリガします。
ライフサイクルっていう考え方か
2 コールバックの概要
after_validation :set_location, on: [ :create, :update ]
on あんまり見たことなかった
3 利用可能なコールバック
3.1 オブジェクトの作成
before_validation
after_validation
before_save
around_save
before_create
around_create
after_create
after_save
after_commit/after_rollback
3.2 オブジェクトの更新
before_validation
after_validation
before_save
around_save
before_update
around_update
after_update
after_save
after_commit/after_rollback
3.3 オブジェクトのdestroy
before_destroy
around_destroy
after_destroy
after_commit/after_rollback
こう見ると多いな
after_saveは after_createとafter_updateの後に発動するのね
after_touch 初めて見た
4 コールバックの実行
touchとtoggleは所見
5 コールバックをスキップする
コールバックをうかつにバイパスすると、データの不整合が発生する可能性があります。
使うときは気をつける
6 コールバックの停止
コールバックで処理を停止したいときは throw :abort
します。
7 リレーションシップのコールバック
特になし
8 条件付きコールバック
Procつきのはむずいよね
before_save :normalize_card_number, if: Proc.new { paid_with_card? }
9 コールバッククラス
特になし
10 トランザクションコールバック
特になし
履歴作るときとかよく使うが、困った時にもどるのが一番よさそう(ブログの意味w)