2016-10-24 1 views
0

Si j'ai un OpenStruct:méthode de get-all getter sur openstruct?

require 'ostruct' 
open_struct = OpenStruct.new 

Je peux remplacer [] qui fonctionne dans certains cas

open_struct.define_singleton_method(:[]) do |*args| 
    puts args.map(&:class) 
    puts args 
end 

open_struct.a = 1 
open_struct[:a] 
# => Symbol 
# a 

Mais cette méthode [] n'est pas appelée lorsque vous utilisez la syntaxe dot-méthode:

open_struct.a 
# => 1 

J'essaie de faire une classe qui hérite d'OpenStruct et qui fonctionne plutôt comme un objet Javascript (en gros je suis t rying pour éliminer la nécessité d'exécuter call sur un proc qui est stocké en tant que valeur)

Répondre

1

tout d'abord - OpenStruct fonctionne déjà très bien comme JavaScript (étant donné que #[] est synonyme de #call):

JS:

foo = {} 
foo.bar = function() { console.log("Hello, world!"); }; 
foo.bar(); 
// => Hello, world! 

Ruby:

foo = OpenStruct.new 
foo.bar = proc { puts "Hello, world!" } 
foo.bar[] 
# => Hello, world! 

Si vous voulez dire fonctionne plus comme Ruby ... vous pouvez passer outre new_ostruct_member:

require 'ostruct' 

class AutoCallableOpenStruct < OpenStruct 
    protected def new_ostruct_member(name) 
    name = name.to_sym 
    unless respond_to?(name) 
     define_singleton_method(name) { 
     val = @table[name] 
     if Proc === val && val.arity == 0 
      val.call 
     else 
      val 
     end 
     } 
     define_singleton_method("#{name}=") { |x| modifiable[name] = x } 
    end 
    name 
    end 
end 

a = AutoCallableOpenStruct.new 
a.name = "max" 
a.helloworld = proc { puts "Hello, world!" } 
a.hello = proc { |name| puts "Hello, #{name}!" } 

a.name    # non-Proc, retrieve 
# => max 
a.helloworld  # nullary proc, autocall 
# => Hello, world! 
a.hello[a.name]  # non-nullary Proc, retrieve (#[] invokes) 
# => Hello, max! 

juste être conscient que OpenStruct Ruby ralentit votre programme, et ne doit pas être utilisé si vous pouvez l'éviter.