adv_attr_accessorの実装から感じるRailsの哲学
ActionMailerのソースを読んでいたら、
adv_attr_accessor :bcc
と言うコードが合ったので、このadv_attr_accessorという謎のメソッドを調べてみた。
短かいコードだったので全文引用してしまう。
module ActionMailer module AdvAttrAccessor #:nodoc: def self.included(base) base.extend(ClassMethods) end module ClassMethods #:nodoc: def adv_attr_accessor(*names) names.each do |name| ivar = "@#{name}" define_method("#{name}=") do |value| instance_variable_set(ivar, value) end define_method(name) do |*parameters| raise ArgumentError, "expected 0 or 1 parameters" unless parameters.length <= 1 if parameters.empty? if instance_variables.include?(ivar) instance_variable_get(ivar) end else instance_variable_set(ivar, parameters.first) end end end end end end end
setterはCで書かれたデフォルトのアクセッサをそのままRuby版に置き換えたようなコードだ。
一方、getterは独自実装になっており、引数がある場合はその引数を変数にセットすると言う内容。
つまり、目的は#=の代わりに
class C adv_attr_accessor :bcc def do_something bcc "hoge@hoge.com" #== bcc = "hoge@hoge.com" end
と書きたい、と言う事のようだ。
ActionMailerのサンプルでは以下のようなコードがよく出てくる。
def mail(message) recipients message[:address] from message[:from] subject message[:subject] body message[:body] end
DSLっぽいインターフェースを実現したい、と言う為だけに新しいアクセッサを用意する辺りがRailsらしい。こう言った強引さがRails以前からのRubyistからすると不満なのだろう。Railsがフレームワークと言う枠を飛び越えて、Rubyをimproveした新しい言語になろうとしているかのようで。
必要に迫られてRailsのコードを読む事もあるが、Railsのコードは一行一行から思想が滲み出ていて、読んでいて単純に楽しい。勉強にもなる。RailsだってやっぱりRubyで出来ているんだよな、なんて事を思った。