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フレームワークと言う枠を飛び越えて、Rubyimproveした新しい言語になろうとしているかのようで。


必要に迫られてRailsのコードを読む事もあるが、Railsのコードは一行一行から思想が滲み出ていて、読んでいて単純に楽しい。勉強にもなる。RailsだってやっぱりRubyで出来ているんだよな、なんて事を思った。