Я заметил (и подтвердил в коде пятна) следующее поведение
class Foo < ActiveRecord::Base
def bar
search_str = "foo"
Boo.search do
keywords(search_str)
p self.id
p self
end
end
end
В приведенном выше коде блок DSL может обращаться к переменным, определенным в контексте.Но внутренний блок self
указывает на экземпляр класса Sunspot::DSL::Search
(вместо экземпляра класса Foo
). Когда я пытаюсь получить доступ к self.id
вместо получения id
Foo
объект;Я получаю id
объекта Sunspot::DSL::Search
.
Я думаю, что Sunpot использует магию обмена / делегирования привязки в методе Util.instance_eval_or_call
.
Мне любопытно, почему Sunspot делает это ипочему нет предупреждения об этом поведении в документации.
Редактировать:
Метод поиска Sunspot можно найти по этой ссылке
Код ниже проиллюстрирует мою точку зрения.В методе foo
у меня есть блок, который ведет себя как ожидалось.В методе bar
блок не ведет себя.
class Order < ActiveRecord::Base
def foo
p self.class.name # prints Order
# The `self` inside the block passed to the each method
# points to an object of type Order (as expected)
# This is the normal block behavior.
[1,2,3].each do |val|
p self.class.name # prints Order
end
end
def bar
p self.class.name # prints Order
# the `self` inside the block passed to the search method
# points to an object of type Sunspot::DSL::Search.
# This is NOT the normal block behavior.
Order.search do
keywords("hello")
p self.class.name # prints Sunspot::DSL::Search
end
end
Note2
Я нашел код в дереве исходного кода Sunspot, который изменяет обычный блокповедение.Мой вопрос о причине фальсификации привязки следующим образом.
Note3
В частности, я обнаружил проблему при вызове метода id
в стороне блока.Метод search
делегирует вызов метода внутри блока объекту DSL, и если он не находит метод, то вызов повторно делегируется в контекст вызова.Метод поиска удаляет все, кроме основных методов, из объекта DSL перед регистрацией кода делегирования.Метод id
не удаляется.Это вызывает проблему.Для всех остальных методов делегирование работает нормально.
Это поведение не описано в документации по методу Sunspot.