2016-10-31 2 views
0

Я пытаюсь получить доступ к методам класса в блоке define_singleton_method, но он, похоже, не работает.Как получить доступ к методам класса в блоке define_singleton_method в Ruby

Вот пример.

class Test 
    attr_accessor :tags 

    def initialize 
    @tags = [] 
    @tags.define_singleton_method(:<<) do |val| 
     val = tosymbol(val) 
     push(val) 
    end 
    end 

    def tosymbol(value) 
    value = value.to_s 
    value = value.gsub!(/\s+/,'_') || value 
    value = value.downcase! || value 

    return value.to_sym 
    end 
end 

Но когда я использую его, я получаю сообщение об ошибке.

test = Test.new 
test.tags<<"Hello World" 
NoMethodError: undefined method `tosymbol' for []:Array 
    from /home/joebloggs/GitHub/repo/file.rb:183:in `block in initialize' 
    from (irb):9 
    from /home/joebloggs/.rvm/rubies/ruby-2.3.0/bin/irb:11:in `<main>' 

Я попытался изменить val = tosymbol(val) к val = Test::tosymbol(val), но это не сработало, я получаю undefined method 'tosymbol' for Test:Class

Я мог бы переписать то, что tosymbol делает, но это не будет очень DRY. Где я иду не так? Благодарю.

+0

Попробуйте 'Def self.tosymbol', а затем вызвать' Test :: tosymbol (значение) '. Что вы на самом деле пытаетесь сделать? Возможно, мы можем предложить лучший способ. –

+0

'def self.tosymbol' не работает, к сожалению. То, что я хочу сделать, - запустить метод проверки на то, что было перенесено на переменную экземпляра. На данный момент я пытаюсь сделать это, переопределив метод экземпляров '<<'. Проблема в том, что я хочу повторно использовать код, который у меня есть в другом месте, и 'define_singleton_method', кажется, не может ничего видеть вне себя. –

ответ

2

Куда я иду не так?

Вы (повторно) определение способа <<, например, из Array класса, не Test класс.

При этом вы пытаетесь получить доступ к методу tosymbol, который не определен в классе Array, но в классе Test.

То, что вы хотите, вероятно (читайте судя по вашему образцу кода), чтобы определить << метод для экземпляров Test класса:

def initialize 
    @tags = [] 
end 

def <<(val) 
    tags << tosymbol(val) 
end 

test = Test.new 
test << "Hello World" 
#=> [:hello_world] 

EDIT

Для того, чтобы ваш пример вам просто нужно назначить экземпляр переменной и вызвать метод tosymbol с правильным приемником:

def initialize 
    @tags = [] 
    test = self # <============ 
    @tags.define_singleton_method(:<<) do |val| 
    val = test.tosymbol(val) 
    push(val) 
    end 
end 

Сейчас:

test.tags << 'Hello World' 
#=> [:hello_world] 
+0

Извините, но это не работает для меня. Теги '<<' на тегах просто действуют так, как это обычно делается для массива, ничего в методе 'def << (val)' не выполняется (даже puts). –

+0

@ I_do_python Извините, я отредактировал ответ, Он должен просто быть 'test <<« Hello World »' –

+0

Хорошо, теперь это работает, спасибо. В любом случае, чтобы сделать это специфичным для переменной экземпляра? По-видимому, это означало бы, что в классе может быть только одна переменная экземпляра массива. Пользователю также не ясно, что ваше добавление к переменной тегов (т. Е. Результат 'test << 4' можно найти в' test.tags'). –

Смежные вопросы