ブシトラの日記

エンジニア1年生の雑多記事

パーフェクトRails1章

メモしてく 

 

 ls -1FA

初めて見た

qiita.com

 

bundlerとは

gem同士の互換性を保ちながらパッケージの種類やバージョンを管理してくれる仕組み

qiita.com

 

bin/rails と bundle exec rails  の違いについて

あまり意識したことなかった。なるほどな

qiita.com

 

statsとは

アプリケーションの概要(クラス数)を知れるの知らなかった

qiita.com

 

 

 

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を出力

jbuilderjson 出力(たまに使う)

- @my_likes.each do |food|
  = render partial: 'foods/food', locals: {food: food}
 
- @my_likes.each do |food|
  = render 'foods/food', food: food
 
== render @my_likes

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 の基礎

railsguides.jp

 

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::Modelincludeすると、以下のような機能を使えるようになります。

  • モデル名の調査
  • 変換
  • 翻訳
  • バリデーション

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"}

qiita.com

 

シリアライズはよくないらしい。

9 Translationモジュール

Person.human_attribute_name('name') # => "Name"

よく使うやつ

10 Lintテスト

11 SecurePasswordモジュール

bcryptっていうgemに依存している

感想

ActiveModelことができることを一言で表すと、

 

「active record の実現を助けてくれるモジュール群」

Railsガイド6.0読み直す ~6章 Active Record クエリインターフェイス

railsguides.jp

 

書いていく。読み応えがありそう

 

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 テーブルを結合する

結合は毎回よくわからなくなる

qiita.com

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 の関連付け~

railsguides.jp

 

書いていく。

 

関連付けを使う理由

モデルとモデルの間には関連付けを行なう必要がありますが、その理由を御存じでしょうか。それは、関連付けを行う事であなたのコードでの共通操作をよりシンプルで簡単にするからです。

 だよねー。

関連付けの種類

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つの関連付けだけで表現できます。

qiita.com

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

 

わかりやすい

morizyun.github.io

 

qiita.com

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

https://railsguides.jp/association_basics.html#belongs-to%E9%96%A2%E9%80%A3%E4%BB%98%E3%81%91%E3%81%AE%E8%A9%B3%E7%B4%B0

 

めちゃくちゃある。。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

これもまためちゃくちゃある。読むの疲れるレベル

 

4.3 has_many 関連付けの詳細

 

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 マイグレーション~ - ブシトラの日記

 

railsguides.jp

読んでいく。

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)