def stats(ppg) in both cases is the same thing, i.e. the beginning of a method definition for a method named stats that takes one argument or parameter that will be named ppg inside the method body.
stats(28) in both cases is the same thing, i.e. a call to a method named stats with the literal Fixnum 28 passed as its argument, whereupon it will be assigned to the variable ppg inside the method body from the definition.
In Ruby, every expression involves two distinct phenomena: side effects, and return values. The expression a = 1 has a side effect of assigning the value of 1 to the variable a, and a return value of 1. Not every method in Ruby has a side effect, but every method does have a return value — either an explicit return value (by using return), or else the return value of the last expression evaluated in the method body.
puts is an unfortunate method in Ruby, because it is used in so many beginner examples, yet its behavior is confusing. It has a side effect of printing its argument to stdout, but its return value is nil (which often confuses beginners, who expect it to return the value of its argument).
The difference between your first method and second method is that the first method, because it uses puts internally, has the side effect of printing a string to stdout and a return value of nil, while the second method has no side effect, but a return value of the string itself.
Therefore, when you call your first method without puts in front, the side effect of printing the string occurs and you see the output. When you call your second method, there is no printing side effect, so in order to have the string printed to stdout, you have to call puts. The argument to puts is the return value of your stats method, i.e. the string you wanted to print.