[…] const definition is compile-time, and calling method is run time, right?
That is correct, but I think you may be misunderstanding. While constants are defined at compile-time, they are not assigned at compile-time. The return type of methods are also defined at compile-time, which is why you can declare a constant to be the result of calling a method, however, the method will only be invoked during run-time (and only if the constant is used).
This means you can declare a constant to be the result of calling gets
!
The call will occur when either the constant is first referenced or when the constant is assigned (though there still needs to be a reference later in the code).
Y = gets # <- Won't be called as there is no reference to Y.
puts "This will print *before* we set X"
print "Enter a value for X: "
X = gets
puts "This will print *after* we set X"
puts "So what was X? #{X}"
puts "The method isn't called twice: #{X}"
puts "\n-----------\n\n"
puts "PI = #{PI}"
puts "Before PI assignment line"
PI = 3.1415
The reason you can’t assign a local variable to a constant is because local variables are – according to the language referece – only defined when you assign them a value, which happens during run-time.
Hope that clears it up 
Slightly off topic, but it may also be worth knowing that constants in Crystal aren’t transitive. What this means is that while constants cannot be reassigned, the data they reference can still be modified. Consider the following example:
PRIME_NUMBERS = [2, 3, 5, 7, 11]
puts PRIME_NUMBERS # => [2, 3, 5, 7, 11]
PRIME_NUMBERS << 13
puts PRIME_NUMBERS # => [2, 3, 5, 7, 11, 13]