2月 102013
webサービスに独自query言語を実装したい事とか、稀によくあるけどevalすると危ないし、きっちりパーサ書くのも面倒
Rubyだと、Object::__send__ Symbol が使えるのかなという話になった
__send__だとprivateの関数も呼び出せちゃうとかあるけど、どうなんですかね。
ORMapperに渡してDBの中身を返すような用途を想定している。
今日食べる物が蓄積されて配列で返ってくるquery
puts "## メソッドチェーン"
p Meshiya.new.zanmai.kazusuke(3).marutaka.foods
puts "## __send__ :symbol で関数呼び出せる"
p Meshiya.__send__(:new).__send__(:zanmai).__send__(:kazusuke, 3).__send__(:marutaka).__send__(:foods)
puts "## eval"
puts "## 引数つきの関数はparseが面倒なので省略"
query = "zanmai.kazusuke.marutaka.foods"
p eval "Meshiya.new."+query
puts "## __send__で安全に呼び出し"
arr = query.split('.')
arr.unshift Meshiya.new
p arr.inject{|a,b|
a.__send__ b.to_sym
}
結果
## メソッドチェーン
["肉", "ホルモン", "ホルモン", "ホルモン", "魚"]
## __send__ :symbol で関数呼び出せる
["肉", "ホルモン", "ホルモン", "ホルモン", "魚"]
## eval
## 引数つきの関数はparseが面倒なので省略
["肉", "ホルモン", "魚"]
## __send__で安全に呼び出し
["肉", "ホルモン", "魚"]
meshiya.rb はこれ
# -*- coding: utf-8 -*-
class Meshiya
attr_reader :foods
def initialize
@foods = []
end
def zanmai(count=1)
count.times do
@foods << "肉"
end
self
end
def kazusuke(count=1)
count.times do
@foods << "ホルモン"
end
self
end
def marutaka(count=1)
count.times do
@foods << "魚"
end
self
end
end