问题
Assume, I have the following class:
class MyClass
attr_accessor :vars
def initialize
@vars = []
end
def add_var var
@vars << var
end
end
I want to access inners vars like this:
x = MyClass.new('root')
x.add_var 'test'
x.add_var 'something'
x.add_var Myclass.new('google')
x.google.add_var 'nice'
puts x.test
puts x.something
puts x.google.nice
Generally speaking, is it possible? What/where should I dig for?
回答1:
It's part of the standard Ruby library, and it's called OpenStruct:
#!/usr/bin/ruby1.8
require 'ostruct'
x = OpenStruct.new
x.google = OpenStruct.new
x.google.nice = 'Nice. Real nice'
p x.google.nice # "Nice. Real nice"
You can also initialize attributes in the constructor:
x = OpenStruct.new(:google=>OpenStruct.new(:nice=>'Nice. Real nice'))
p x.google.nice # => "Nice. Real nice"
回答2:
If you want to implement something like this yourself you should find out more about method_missing. This method gets called when a method cannot be found. Using some clever code to find the called method name in your @vars
and react on that.
This is probably the same method used by the plugin weppos is talking about.
回答3:
Sure you can. This is exactly what, for instance, this plugin does for application-wide configuration settings.
回答4:
you can do this with instance_varibable_set and instance_variable_get:
MyClass.instance_variable_set(:@var_name, "value")
回答5:
Just dynamically define a new method and have it return the object you want:
class MyClass
attr_accessor :vars
attr_reader :name
def initialize(name)
@name = name
@vars = []
end
def add_var(var)
@vars << var
if var.instance_of?(MyClass)
class << self; self; end.send(:define_method, var.name.to_sym) {
var
}
end
end
end
x = MyClass.new(:x)
x.add_var MyClass.new(:google)
x.google.add_var MyClass.new(:nice)
x.google.nice.name #=> :nice
来源:https://stackoverflow.com/questions/2108986/ruby-access-magic