Рубиновая магия доступа - PullRequest
       13

Рубиновая магия доступа

1 голос
/ 21 января 2010

Предположим, у меня есть следующий класс:

class MyClass
  attr_accessor :vars

  def initialize
    @vars = []
  end

  def add_var var
    @vars << var
  end

end

Я хочу получить доступ к внутренним переменным следующим образом:

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

Вообще говоря, возможно ли это? Что / где я должен копать?

Ответы [ 5 ]

4 голосов
/ 21 января 2010

Это часть стандартной библиотеки Ruby, и она называется 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"

Вы также можете инициализировать атрибуты в конструкторе:

x = OpenStruct.new(:google=>OpenStruct.new(:nice=>'Nice.  Real nice'))
p x.google.nice    # => "Nice.  Real nice"
1 голос
/ 21 января 2010

Если вы хотите реализовать что-то подобное самостоятельно, вы должны узнать больше о method_missing . Этот метод вызывается, когда метод не может быть найден. Использование некоторого умного кода, чтобы найти имя вызываемого метода в вашем @vars и отреагировать на это.

Вероятно, это тот же метод, который используется плагином weppos , о котором идет речь.

0 голосов
/ 21 января 2010

Просто динамически определите новый метод и верните ему нужный объект:

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
0 голосов
/ 21 января 2010

вы можете сделать это с instance_varibable_set и instance_variable_get:

MyClass.instance_variable_set (: @ var_name, "value")

0 голосов
/ 21 января 2010

Конечно, вы можете. Это именно то, что, например, этот плагин делает для настроек конфигурации всего приложения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...