LoginSignup
8
10

More than 5 years have passed since last update.

ActiveRecordの機能まとめ

Last updated at Posted at 2017-07-01

最近、開発でRuby on Railsを使用しています。
備忘録の為に、ActiveRecord関連のナレッジについてまとめていきます。

accepts_nested_attributes_for

親子関係にあるModelのデータを画面で入力し、一回のsubmitで更新する場合がある。
その場合は、以下のようにhas_manyaccepts_nested_attributes_forも指定する。

user.rb
class User < ApplicationRecord
  has_many: addresses
  accepts_nested_attributes_for : addresses, reject_if: :all_blank
end

上記を指定するとviewでfields_forを使ってネスト表示することが可能。

alias_attribute

alias_attributeはフィールドにaliasで別名を定義するときに使います。

user.rb
class User < ApplicationRecord
  alias_attribute :status, :member_type
end

元々のフィールドのバリデーションの設定を引き継ぐので、処理に応じて分けたい場合は便利ですね。

attr_accessor

DB存在しないカラム等に、画面のみで使用するプロパティとして設定するときに使用します。

user.rb
class User < ApplicationRecord
  attr_accessor :use_phone_number
end

enum

Modelの定義方法

enumとは列挙型と呼ばれるデータ型です。
ActiveRecordでは、カラムに登録可能なデータ群を定義するときに使います。

user.rb
class User < ApplicationRecord
  enum member_type: {guest: 0, admin: 1, master: 2}
end

定義できる値は上記の数値(integer)以外に、論理値(boolean)、文字列(string)、さらには以下のように配列でも定義可能です。

User.rb
class User < ApplicationRecord
  enum member_type: [:guest, :admin, :master]
end

値の使用方法

users_controller.rb
user = User.new(member_type: :admin)
user.member_type // 1
user.admin? // true
user.master! // 値を:masterへ変更

検索条件

enumを定義しているカラムは、クエリーとしても使用可能です。

User.active.guest

includes

belongs_tohas_onehas_manyで指定したModelも一緒に参照する際に使用する。

user.rb
class User < ApplicationRecord
  has_many: addresses
end
user_controller.rb
def index
  users = User.all
  users.each do |user|
    puts user.name
    user.addresses.each do |address|
      puts address.zipcode
    end
  end
end

上記のようなケースの場合、User.allselect * from usersがSQLとして実行されます。
その後、@users.each内部でhas_manyaddressテーブルに対してeachの回数分、select * from adreesses where adreesses.id = ?がSQLとして実行されます。

これはN+1問題と呼ばれるケースですね。
N+1問題についてはここでは割愛します。)

それを解消するために、includesを使用します。以下のように変更します。

user_controller.rb
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のクエリーの条件を関数のように汎用的に使える機能です。

user.rb
class User < ApplicationRecord
  scope :active, -> { where(deleted: false) }
end

上記はusersテーブルでdeletedフラグが有効でない、アクティブユーザーを検索するクエリーをscopeにまとめたものです。
コントローラーで以下のように使えます。

users_controller.rb
users = User.active

Concern

ConcernはActiveRecordではなく、ActiveSupportのオブジェクトなのですが、Modelでも使う機会が多いので、記載しておきます。
Concernとは各Model間、Controller-Model間で共通に使う処理がある場合に定義して使います。
Rubyにはmix-inと呼ばれる共通処理群をモジュールとして組み込む機能があります。
以下のようにして使うことが出来ます。

user.rb
include action

参考

8
10
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
10