23
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ActiveRecordで関連しているモデルのコレクションに対してメソッドを定義する

Last updated at Posted at 2015-10-22

Association extensions

Parent has_many childrenみたいな関係のモデルでparent.childrenに対してメソッドを定義したいことがよくあります。
たとえばchildrenの属性によって絞りこんだり(children.malesで性別が男性のchildのみを返す)、またはchildrenに関連する他のモデルを取得したり(children.schoolsでchildrenが通っている学校のコレクションを返す)など。

そんなとき、Association extensionsという機能を使うと上手くメソッドを定義できます。

Association extensionとは、関連として取得するモデルのコレクション(ActiveRecord_Associations_CollectionProxy)を自分が定義したメソッドやモジュールで拡張することが出来る機能のことです。

例題のモデル定義

以下のようなモデル定義があるとします。

class Parent < ActiveRecord::Base
  has_many :children
end

class Child < ActiveRecord::Base
  has_many :parents
  belongs_to :school
end


class School < ActiveRecord::Base
  has_many :children
end


parent = Parent.first
parent.children #=> [Child, Child, Child]
parent.children.first.school #=> School

メソッドで拡張する

ではchildrenを性別が男性かどうかによってフィルタするメソッドmalesを定義して、拡張してみます。

class Parent < ActiveRecord::Base
  has_many :children do
    def males
      self.where(:gender, 'male')
    end
  end
.
.
.
end

Parent.first.children.males #=> [Child, Child]

上記のように定義すると以下のようにするchildrenに対して定義したmalesメソッドを呼ぶことができます。
ちなみにmalesメソッド内でのselfはchildrenになります。

モジュールで拡張する

上記のようにメソッドで拡張することも出来ますが、childrenはSchoolモデルでも使われているため同じメソッドを重複して定義することになります。
そういうときはchildrenを拡張するモジュールを作り、そのなかでメソッドを定義すると重複を失くすことが出来ます。

module ChildrenExtension
  def males
    self.where(:gender, 'male')
  end
end

class Parent < ActiveRecord::Base
  has_many :children, -> { extending ChildrenExtension }
.
.
.
end

class School < ActiveRecord::Base
  has_many :children, -> { extending ChildrenExtension }
end


Parent.first.children.males #=> [Child, Child]
School.first.children.males #=> [Child, Child]

23
17
0

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
23
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?