2016-04-03 21 views
2

Yöntemleri dinamik olarak tanımlamaya ve ona bir parametre aktarmaya çalışıyorum.Dinamik olarak tanımlanmış yöntemlerde varsayılan parametreler

data = {name: 'foo', optional: 'bar'} 
@commands.send(data['name'].to_sym, data) 

Bu data çünkü böyle bir şey yapmak sürece tanımlı değil başarısız:

route denir
class Commands 
end 

@commands = Commands.new 

def route(name, &block) 
    Commands.send(:define_method, name, &block) 
end 

route 'foo' do 
    puts 'oh hai' 
    puts data 
end 

, bu şimdiye yürütülecek nelerle: Bu defa ne var:

route 'foo' do |data| 
    puts 'oh hai' 
    puts data 
end 

Varsayılan parametreyi iletmenin bir yolu var mı? Sinatrarb'ın yaptığı gibi görünüyor, ama henüz koddan kafa ya da kuyruk yapamamıştım.

+1

"Varsayılan parametreyi ilet" ile ne demek istediğini anlamıyorum. –

+0

Çamur olarak temizle? :), belirsiz bir soru için üzgünüm. Sorunun bir kısmı kesinlikle sormam gereken temel sorunun ne olduğunu bilmiyorum. Cevaplar hedefe baktığından, soruyu her iki şekilde dener ve günceller – Dishcandanty

cevap

3

Sorunuz çok açık değil, ancak aradığınız işlevin genellikle instance_eval ve arkadaşları ile elde edilen sıralama olduğunu sanıyorum. instance_eval, verilen bloğu kendi aranan bağlamında değerlendirir, böylece callee'nin örnek yöntemleri ve örnek değişkenleri blok içinde kullanılabilir.

İşte gerçekten temel örnek:

"foo".instance_eval do 
    puts size 
    puts upcase 
end 
# -> 3 
# -> FOO 

size ve upcase biz bloğuna verdik parametreler değildir, onlar zaten String nesnesi bağlamında kullanılabilen yöntemleri konum. Biz örnekleri route yöntemine verilen bloklar değerlendirmek için bir bağlam olarak hizmet verebilir bir Rota sınıf tanımladığınız İşte

class Route 
    attr_reader :data 

    def initialize(name) 
    @data = { name: name, optional: "bar" } 
    end 
end 

rt = Route.new("foo") 

rt.instance_eval do 
    puts 'oh hai' 
    puts data 
end 
# -> oh hai 
# -> {:name=>"foo", :optional=>"bar"} 

:

göz önüne aldığımızda

, böyle bir şey ile başlayabilir:

def route(name, &block) 
    rt = Route.new(name) 
    Commands.send(:define_method, name) do 
    rt.instance_eval(&block) 
    end 
end 

route 'foo' do 
    puts 'oh hai' 
    puts data 
end 

route 'qux' do 
    puts "My name is %{name} and optional is %{optional}" % data 
end 

@commands = Commands.new 
@commands.foo 
# -> oh hai 
# -> {:name=>"foo", :optional=>"bar"} 

@commands.qux 
# -> My name is qux and optional is bar 
1

Blok, route yöntemine geçirdiğiniz değerdir; Eğer dolayısıyla yakut parametrelerin herhangi sayıda karşı şikayetçi olmaz istediğini geçmek serbesttir

Bir parametreyi engellemek için varsayılan bir değer atayabilirsiniz (@commands.foo aslında denir dek.):

λ = lambda do |data = 'hello'| 
    puts data 
end 

ve route bu lambda geçmesi:

:

route 'foo', &λ 
#⇒ "hello" 

AFAIK gibi hack çeşit kullanılarak açıkça yabancı binding yerel değişkeni atamak için bir yolu yoktur

block.binding.local_variable_set(:data, 'hello') 
İlgili konular