Local variables have to be declared directly in the current scope, not inside any macros. Try:
require "uri"
class Foo
def hello
str = "你好"
encoded_str = {% if compare_versions(Crystal::VERSION, "1.2.0") < 0 %}
URI.encode(str)
{% else %}
URI.encode_path(str)
{% end %}
p encoded_str # not work, Error: undefined method 'encoded_str' for Foo
p! encoded_str # "%E4%BD%A0%E5%A5%BD", it works
end
end
foo = Foo.new
foo.hello
It’s likely that p! is a macro itself so maybe that changes something. Same as as why just wrapping your original p encoded_str line with {% begin %} / {% end %} works as well.