Нет ничего волшебного или в модели рельсов, это просто обычный класс с кучей уже существующих методов,
Итак, вопрос в том, "могу ли я определить_метод в классе"?
Часть 1: Да, можно.
Важным отличием является то, что вы можете определить метод в классе , а не в экземпляре метод
Например:
class Cow
define_method "speak" do
"MOOOO"
end
end
Cow.new.speak
=> "MOOOO"
Это должно работать нормально. Обратите внимание, что вы определяете его для класса Cow, так что любые другие уже имеющиеся у вас Cows будут автоматически добавлять этот метод.
Часть 2. Что вы делаете, если хотите определить метод из метода экземпляра?
Вы не можете определить методы из метода экземпляра, поэтому вам нужно захватить класс и использовать его для определения метода. Как это:
class Cow
def add_speak
self.class.send(:define_method, :speak) do
"MOOOO added"
end
end
end
Cow.new.speak
NoMethodError: undefined method 'speak' for #<Cow:0xb7c48530>
Cow.new.add_speak
Cow.new.speak
=> "MOOOO added"
Проблема решена. Проницательные читатели заметят, что в этом примере я использую send(:define_method)
- это необходимо, потому что define_method
является приватным, а приватные методы доступны только тому, в чем они находятся. В этом случае define_method
находится в класс, мы в экземпляре, поэтому мы не можем получить к нему прямой доступ.
Как и выше, мы добавляем метод непосредственно к классу, поэтому все другие уже существующие коровы также автоматически добавят метод talk.
Часть 3. Что вы делаете, если хотите определить метод только для 1 объекта, а не для всех объектов этого класса?
Пример:
class Cow
def add_speak_just_me
class << self
define_method "speak" do
"MOOOO added for just me"
end
end
end
end
Cow.new.speak
NoMethodError: undefined method 'speak' for #<Cow:0xb7c72b78>
c = Cow.new
c.add_speak_just_me
c.speak
=> "MOOOO added for just me" # it works, hooray
Cow.new.speak # this new cow doesn't have the method, it hasn't been automatically added
NoMethodError: undefined method `speak' for #<Cow:0xb7c65b1c>
Как это работает? Вниз по кроличьей норе вы идете!
Прочитайте это: http://dannytatom.me/metaid/ и удачи. Это помогает, когда вы понимаете, что «добавление метода» в экземпляр вообще не добавляет его в экземпляр: -)