2015/11/07

Rails3とRails4のhas_manyオプションの差分を吸収する

Rails3とRails4の違いの1つに has_many のオプションがあります。
# Rails3
class Course < ActiveRecord::Base
has_many :students, order: :name, include: [:parents, :brothers], dependent: :destroy
end
# Rails4
class Course < ActiveRecord::Base
has_many :students, ->{ order(:name).includes(:parents, :brothers) }, dependent: :destroy
end
Rails4では orderinclude が使えなくなってるんですね。

しかし、1つのソースでRails3とRails4に対応したい場合どうしようか?
module AssocOpts
extend ActiveSupport::Concern
module ClassMethods
def assoc_opts(options)
return [options] if Gem::Version.new(Rails.version) < Gem::Version.new('4.0.0')
order_option = options.delete(:order)
include_option = options.delete(:include)
if order_option && include_option
[Proc.new { order(order_option).includes(include_option) }, options]
elsif order_option
[Proc.new { order(order_option) }, options]
elsif include_option
[Proc.new { includes(include_option) }, options]
else
[options]
end
end
end
end
view raw assoc_opts.rb hosted with ❤ by GitHub
# Rails3 and Rails4
class Course < ActiveRecord::Base
include AssocOpts
has_many :students, *assoc_opts(order: :name, include: [:parents, :brothers], dependent: :destroy)
end
とまあこんな感じでどうでしょう?

1 件のコメント :