2013-09-18 4 views
1

Каждый пример, который я нашел из синтаксиса setter =, очень прост, т.е.Ruby setter = метод не называется

def name=(value) 
    @name = value 
end 

Можете ли вы сделать что-то более сложное с этим синтаксисом? В частности, можете ли вы использовать его без соответствующей переменной экземпляра? Может ли он быть частным? Можете ли вы сделать какую-то проверку?

Я пишу контроллер Rails, который можно расширить, чтобы предоставить базовую функциональность CRUD модели, которая маршрутизируется как ресурс. Он использует атрибут class_attribute для установки имени модели, которую он будет контролировать, и создает переменную экземпляра, основанную на имени модели. Это выглядит примерно так:

class ResourceController 
    class_attribute :model_class_name 

    def new 
    resource = self.model_class_name.new 
    end 

    protected 
    def self.init_resource(options={}) 
     self.model_class_name = options[:model_class_name] 
    end 

    private 
    def resource 
     instance_variable_get(resource_instance_var) 
    end 

    def resource=(value) 
     instance_variable_set(resource_instance_var ,value) 
    end 

    def resource_instance_var 
     "@#{self.resource_class.name.underscore}".to_sym 
    end 
end 

С выше структуры кода я получаю NoMethodError в представлении, поскольку View имеет переменную экземпляра Nil. Использование logger.debug Я могу трассировать стек до resource = ..., но resource= не вызывается.

Если я урочу сахар и использую set_resource(value) все работает нормально. Я слишком много спрашиваю о синтаксисе setter =, или есть какая-то другая проблема, которую я не вижу?

ответ

1
  • Можете ли вы использовать его без соответствующей переменной экземпляра?

    Да. Назначьте его переменной экземпляра с любым именем.

  • Может быть, частный?

    Да и номер. Вы можете определить частный метод формы foo=. , но вы никогда не сможете назвать его обычным способом (т. Е. Без использования send или добавления скобок). Когда выражение неоднозначно между ссылкой/присваиванием локальной переменной и вызовом метода, оно будет интерпретироваться как ссылка/присвоение локальной переменной. Метод Setter такого типа всегда нуждается в явном приемнике. Вот почему вы получили ошибку. Метод setter не был вызван, потому что вы не писали получателя явно.

  • Можете ли вы сделать какую-то проверку?

    Да. Поместите любой код проверки перед назначением переменной экземпляра.

+0

Ну, их можно назвать «foo = (« bar »)' ... –

+0

Это имеет большое значение. Спасибо. Еще один вопрос, вы говорите '.send' является единственным способом вызова метода, но изнутри метода экземпляра в том же классе, почему бы не работать 'self.resource ='? Или, скажем, метод защищен вместо частного, почему бы «super.resource =' работать в расширяющемся классе? –

+0

@BorisStitnicky Я думаю, что вы правы. Я пропустил это. Добавил это к ответу. – sawa

0
def something=(arg) 
    # do anything 
end 

Методы заканчивающиеся = имеют определенные особенности, что делает их особенно подходящими для сеттеров. К ним относятся:

  • Они ожидают, что 1 аргумент
  • Они всегда автоматически возвращать этот аргумент в качестве возвращаемого значения.

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

+0

зная, что очевидным поведением является установка любого класса в качестве конечного автомата. –

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