Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
13
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

posted at

Railsのwith_options

with_optionsという便利メソッドの存在を知る。

Object.with_options`を使うとオプションパラメタをまとめる事ができます。

例えばこういうのを、

class Account < ActiveRecord::Base
  has_many :customers, dependent: :destroy
  has_many :products,  dependent: :destroy
  has_many :invoices,  dependent: :destroy
  has_many :expenses,  dependent: :destroy
end

こう書けます。

class Account < ActiveRecord::Base
  with_options dependent: :destroy do |assoc|
    assoc.has_many :customers
    assoc.has_many :products
    assoc.has_many :invoices
    assoc.has_many :expenses
  end
end

with_optionsの引数に渡したHashのオプションの値がブロック内に適用されます。上の例ではhash_manydependentオプションを共通化しましたが、他のパターンでも適用できます。例えば、モデルの例では他にもvalidatesメソッドのオプションを共通化など使えます。

動作としては、with_optionsに引数として与えたHashを、ブロック内の各メソッドの引数のオプションHashにdeepマージする挙動なのでモデル以外でも使えます。

定義はactivesupport/lib/active_support/core_ext/object/with_options.rbにある。

ただハマりポイントもあり

  • deepマージする挙動なので、with_optionsとブロック内メソッドで同じkeyでオプションを定義すると片方が適用されない
  • Rails 4.1 以前ではレシーバオブジェクト経由で本来のメソッドを呼ぶことが必須
    • Rails 4.1ではwith_optionsからブロックへ渡されるレシーバオブジェクト(上の例のassoc)経由で本来のメソッドを呼ぶ必要あり(上の例のassoc.has_many。レシーバ省略してメソッドを呼ぶと効かない。
    • Rails 4.2 からはレシーバ省略可能

実際、Rails HEADのドキュメントにはレシーバ無しで呼べると書かれててて、4.1でそう書いたら動かなくてハマりました。

参考文献

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
13
Help us understand the problem. What are the problem?