0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Rails】ActiveSupport#delegate

Posted at

はじめに

Object#try に代わる選択肢として下の記事で紹介されていた、ActiveSupport#delegate について調べた内容をまとめます。

定義

前提

  • UserモデルとProfileモデルが has_one で関連付けられている(userごとにprofileが一つ存在する)
  • リンクカラム( user_id )はProfileテーブルに存在する
  • user.pofile.name のようにProfileテーブルのユーザー名を取得したい
class User < ApplicationRecord
  has_one :profile
end

# delegateマクロを使わない場合、nameメソッドを追加するとuser.nameでアクセスする
def name
  profile.name
end

定義方法

  • 上記をdelegateを使って下記のように書き換える
class User < ApplicationRecord
  has_one :profile

# delegateマクロを使うとnameメソッドを下記のように書き換えができ、user.nameでアクセスする
  delegate :name, to: :profile
end

補足

:allow_nil オプション

  • 対象がnilの場合、NoMethodErrorが発生する
  • allow_nil: true を渡すと例外の代わりにnilが返る
delegate :name, to: :profile, allow_nil: true

prefix オブション

  • 生成されたメソッドの名前にプレフィックスを追加する
# profile_nameが生成される。上記の例ではuser.profile_nameでアクセスする
delegate :name, to: :profile, prefix: true
# avatar_nameが生成される。上記の例ではuser.avatar_nameでアクセスする
delegate: :name, to: :profile, prefix: avatar

:private オプション

  • デフォルトではpublicメソッドなので private: true を渡してメソッドのスコープを変更する
delegate :name, to: :profile, private: true

複数のメソッドがまとめて指定できる

delegate :name, :age, :address, :twitter, to: :profile

delegate_missing_to

  • オブジェクト内にある呼び出し可能なもの(インスタンス変数、メソッド、定数など)を対象に、スコープがpublicなものを委譲する
class User < ApplicationRecord
  has_one :profile

  delegate_missing_to :profile
end

# user.name、user.ageなどでアクセスできるようになる

おわりに

  • allow_nil: true とするとNoMethodErrorの例外が発生せず、Object#tryと結果が同じになります。しかし、より癒着が弱く、コードが明確という点から、ActiveSupport#delegateの方が適切と言えるようです。

  • user.profile.name や user.profile.try(:name) はオブジェクト間の癒着が強く好ましくないので、delegateマクロを使わない場合は下記のように書き換える方が正しいようです。

class User
def profile_name
  profile.try(:name)
  end
end
class User
def profile_name
  return nil if profile.nil? # nilになるのが正しい場合はガード節で早期にnilを返す
  profile.name
  end
end

参考

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?