最近、開発でRuby on Railsを使用しています。
備忘録の為に、ActiveRecord関連のナレッジについてまとめていきます。
accepts_nested_attributes_for
親子関係にあるModelのデータを画面で入力し、一回のsubmitで更新する場合がある。
その場合は、以下のようにhas_many
とaccepts_nested_attributes_for
も指定する。
class User < ApplicationRecord
has_many: addresses
accepts_nested_attributes_for : addresses, reject_if: :all_blank
end
上記を指定するとviewでfields_for
を使ってネスト表示することが可能。
alias_attribute
alias_attribute
はフィールドにaliasで別名を定義するときに使います。
class User < ApplicationRecord
alias_attribute :status, :member_type
end
元々のフィールドのバリデーションの設定を引き継ぐので、処理に応じて分けたい場合は便利ですね。
attr_accessor
DB存在しないカラム等に、画面のみで使用するプロパティとして設定するときに使用します。
class User < ApplicationRecord
attr_accessor :use_phone_number
end
enum
Modelの定義方法
enum
とは列挙型と呼ばれるデータ型です。
ActiveRecordでは、カラムに登録可能なデータ群を定義するときに使います。
class User < ApplicationRecord
enum member_type: {guest: 0, admin: 1, master: 2}
end
定義できる値は上記の数値(integer
)以外に、論理値(boolean
)、文字列(string
)、さらには以下のように配列でも定義可能です。
class User < ApplicationRecord
enum member_type: [:guest, :admin, :master]
end
値の使用方法
user = User.new(member_type: :admin)
user.member_type // 1
user.admin? // true
user.master! // 値を:masterへ変更
検索条件
enum
を定義しているカラムは、クエリーとしても使用可能です。
User.active.guest
includes
belongs_to
やhas_one
、has_many
で指定したModelも一緒に参照する際に使用する。
class User < ApplicationRecord
has_many: addresses
end
def index
users = User.all
users.each do |user|
puts user.name
user.addresses.each do |address|
puts address.zipcode
end
end
end
上記のようなケースの場合、User.all
でselect * from users
がSQLとして実行されます。
その後、@users.each
内部でhas_many
のaddress
テーブルに対してeachの回数分、select * from adreesses where adreesses.id = ?
がSQLとして実行されます。
これはN+1問題
と呼ばれるケースですね。
(N+1問題
についてはここでは割愛します。)
それを解消するために、includesを使用します。以下のように変更します。
def index
users = User.all.includes(:addresses)
…
end
そうするとUser.all
の実行時に、以下の2つのSQLが実行されます。
select * from users;
select * from addresses where id in (...)
SQLの実行回数が抑えられますが、検索条件がin
のため、インデックスが効かない場合があるので、使用時には少し注意しましょう。
scope
scope
とはActiveRecordのクエリーの条件を関数のように汎用的に使える機能です。
class User < ApplicationRecord
scope :active, -> { where(deleted: false) }
end
上記はusers
テーブルでdeleted
フラグが有効でない、アクティブユーザーを検索するクエリーをscope
にまとめたものです。
コントローラーで以下のように使えます。
users = User.active
Concern
ConcernはActiveRecordではなく、ActiveSupportのオブジェクトなのですが、Modelでも使う機会が多いので、記載しておきます。
Concernとは各Model間、Controller-Model間で共通に使う処理がある場合に定義して使います。
Rubyにはmix-inと呼ばれる共通処理群をモジュールとして組み込む機能があります。
以下のようにして使うことが出来ます。
include action