put_in/2 is a macro, not a function. The arguments are passed unevaluated, and the put_in/2 implementation operates on their syntactic representations instead. Since the first argument is users[:john].age, the macro actually does have access to users.
A good place to start is the Quote and unquote guide, and then the following section on macros. You may also find it helpful to study how the short-circuiting or AST macro works before trying to tackle put_in/2. In particular, notice that the right side is only evaluated when the left side is falsy, whereas if || were a function all of its arguments would be evaluated before the function body.
iex(1)> IO.puts "left" || IO.puts "right"
left
:ok
iex(2)> false || IO.puts "right"
right
:ok