问题
With the following code:
def index
@q = ""
@q = params[:search][:q] if params[:search]
q = @q
@search = Sunspot.search(User) do
keywords q
end
@users = @search.results
end
If @q is used instead of q, the search always returns results for an empty query (""). Why is this? Is the @q variable unavailable to the do...end block?
回答1:
It depends on how the block is being called. If it is called using the yield
keyword or the Proc#call
method, then you'll be able to use your instance variables in the block. If it's called using Object#instance_eval
or Module#class_eval
then the context of the block will be changed and you won't be able to access your instance variables.
@x = "Outside the class"
class Test
def initialize
@x = "Inside the class"
end
def a(&block)
block.call
end
def b(&block)
self.instance_eval(&block)
end
end
Test.new.a { @x } #=> "Outside the class"
Test.new.b { @x } #=> "Inside the class"
In your case, it looks like Sunspot.search
is calling your block in a different context using instance_eval
, because the block needs easy access to that keywords
method.
回答2:
As Jeremy says, Sunspot executes its search DSL in a new scope.
In order to use an instance variable in the Sunspot.search block, you'll need to pass it an argument. Something like this should work (not tested):
@q = params[:search][:q] if params[:search]
@search = Sunspot.search(User) do |query|
query.keywords @q
end
@users = @search.results
See here for a better explanation: http://groups.google.com/group/ruby-sunspot/msg/d0444189de3e2725
来源:https://stackoverflow.com/questions/5150483/instance-variable-not-available-inside-a-ruby-block