All the attr_* class methods do is define precisely the instance methods the author wrote by hand. Indeed, if attr_reader, attr_writer, and attr_accessor weren't part of Ruby's Module class you could write them yourself, like so: https://gist.github.com/jfarmer/6b4deeb8bcfbe030f876
If using an "eval" method seems smelly to you, you can achieve the same result in pure Ruby using define_method, instance_exec, and instance_variable_get. There are good practical reasons to use module_eval, though.
Regardless, I think the author's point was more that there's nothing "special" about getters and setters in Ruby. They're just plain ol' methods. As a class of methods we write them often enough that we've also defined a higher-order method that takes an instance variable name as input and dynamically defines those getters and setters on the underlying object.
We wouldn't "lose" anything by not having attr_reader and friends, though. Our code would just be slightly more verbose.
If using an "eval" method seems smelly to you, you can achieve the same result in pure Ruby using define_method, instance_exec, and instance_variable_get. There are good practical reasons to use module_eval, though.
Regardless, I think the author's point was more that there's nothing "special" about getters and setters in Ruby. They're just plain ol' methods. As a class of methods we write them often enough that we've also defined a higher-order method that takes an instance variable name as input and dynamically defines those getters and setters on the underlying object.
We wouldn't "lose" anything by not having attr_reader and friends, though. Our code would just be slightly more verbose.