Moduleをincludeした先のコンテキストでメソッドを実行したい

  def validate_length(def_attr_length)
    attr_symbol = get_attr_symbol_from_attr_length(def_attr_length)
    if eval(def_attr_length) < (send(attr_symbol) || "").jlength
      errors.add(attr_symbol,"が文字数制限を超えています。")
      return false
    end
    return true
  end

この場合、def_attr_length(実際には呼び元の定数をあらわす文字列がはいる)が
Moduleのコンテキストで評価されてしまい、こんな定数はこのモジュールにないよといわれる。


ここで、eval(def_attr_length) => self.send(***)と変えると、インスタンスメソッドで
ないのでない。self.class.sendにしても、結局定数はメソッドでないので、この形では
呼べない


この場合、2つの方法があった。
1つめは、bindingを使う。evalは第2引数にコンテキストを渡すことができる。
そのコンテキストを得るメソッドがbinding。なので、呼び元のbindingの結果をここのeval
の引数に渡せばいい。こんな感じになる。

  def validate_length(def_attr_length, bind)
    attr_symbol = get_attr_symbol_from_attr_length(def_attr_length)
    if eval(def_attr_length, bind) < (send(attr_symbol) || "").jlength
      errors.add(attr_symbol,"が文字数制限を超えています。")
      return false
    end
    return true
  end

もう一つは、eval_classメソッドを使う。この場合は、これのレシーバのコンテキスト
を使うので次のようにする。
eval(def_attr_length) => self.class.class_eval(***)
selfはinclude先のクラスが入るので、これで、include先のクラスの定数を持ってこれる。

わかりやすくすればこうか。

  def validate_length(def_attr_length)
    attr_symbol = get_attr_symbol_from_attr_length(def_attr_length)
    if self.class.class_eval(def_attr_length) < (self.send(attr_symbol) || 
"").jlength
      self.errors.add(attr_symbol,"が文字数制限を超えています。")
      return false
    end
    return true
  end

http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-list/43286
これによると、selfは取り込み先のクラスを参照できないように書いてあるが、
実際はいけるよ。