Возможно ли сделать что-то подобное в Ruby (1.9.2-p290)?
class SomeClass
include SomeModuleThatProvidesLotOfConstants
def build(&block)
singleton_class.instance_eval(&block)
end
end
obj = SomeClass.new
obj.build do
some_class_method SomeConstant, :an => :option
...
end
Где some_class_method
- метод, доступный для SomeClass
(не для его экземпляров)) и SomeConstant
является классом / модулем, который находится в области видимости внутри SomeClass
, но должен быть ссылками как SomeClass::SomeConstant
извне.
Я могу заставить это работать, если я всегда передам полностью-квалифицированные имена классов внутри моего блока, но я пытаюсь эффективно «изменить область» блока, когда он вызывается.Это возможно?Я уверен, что RSpec и другие подобные инструменты, которые интенсивно используют блоки, достигают чего-то вроде этого:)
Обратите внимание, что хотя я вызываю методы класса изнутри блока, я хочу, чтобы изменения влияли только на это.индивидуальный синглтон-класс, а не распространяться на все экземпляры.
РЕДАКТИРОВАТЬ |Хорошо, вот не псевдо версия того, что я пытаюсь достичь.Я пытаюсь добавить некоторые свойства DataMapper во время выполнения, но только для одноэлементных классов ... Я не хочу, чтобы они внезапно появлялись во всех экземплярах модели.
class Post
include DataMapper::Resource
property :id, Serial
property :title, String
property :created_at, DateTime
... etc ...
def virtualize(&block)
singleton_class.instance_eval(&block)
self
end
end
def suspend_post
@post = Post.get!(1).virtualize do
property :delete_comments, Boolean
end
end
Я знаю, что есть и другиеспособы создания виртуальных атрибутов (в настоящее время я использую несколько разных подходов, в зависимости от сложности), но я просто экспериментирую с несколькими идеями, чтобы не загромождать определения моей модели временными методами, которые используются только для передачи данных формыв одной конкретной части сайта и ничего не значат, когда вы читаете исходный код модели сам по себе.Один или два виртуальных атрибута в порядке, но когда они начинают монтироваться на часто используемых моделях, я начинаю исследовать такие вещи;)
В приведенном выше описании ресурс будет иметь все стандартные свойства, определенные вконкретный класс, плюс любой, добавленный в метод #virtualize
.Это ссылка на Boolean
без префикса DataMapper::Property::
, которая его отбрасывает.