And on the topic of improving my vocabulary, something I recently witnessed my coworker Brian write:
define_method :attribute_with_foo=
send(:attribute_without_foo=, arg)
more_code
end
alias_method_chain :attribute=, :foo
This piece of code was practically gibberish to me, so many foreign concepts wrapped in one small block. Going through it piece by piece:
define_method
This is something you can do instead of using
def method_name
&block
end
to define instance methods. In this context I guess it doesn’t make that big of a difference but define_method can be one-lined like
define_method(:method_name) { &block }
so that could possibly be useful for writing small gists. Also it could be used to dynamically define methods, but I haven’t yet encountered a use case for that.
attribute=
I don’t even know how to Google this one to learn more about it… but I guess there’s not that much to it. Basically it’s just a method definition for the equals sign. For example,
def foo= (bar)
@foo = bar
end
where foo is an instance variable of a class. Then I’m able to do
class.foo = 'bar'
More simply put, this is how you explicitly define setters. The easier way of doing it in Ruby is just to declare whether the attribute is an attr_accessor, attr_reader, or attr_writer.
send
The first argument passed is a method of the object to be invoked. All succeeding arguments are parameters to be passed to the method. This method is useful for when you want to dynamically call methods.
alias_method_chain
And finally, this I found the coolest, though apparently it has been around since at least 2006, and is considered an anti-pattern? Basically the first argument you pass it is a method, and the second is… a word? Now whenever you call the method, it’s actually calling method_with_word behind the scenes, which you define. The original method is now aliased to method_without_word, which you can even call inside of method_with_word if you want, as seen in the example, so that method_with_word basically builds on it.
This was useful to us because we had a method used pretty extensively in the codebase that we realized consistently needed another method call to go along with. It was a predefined method so we couldn’t just add to it, and doing a find and replace all could be dangerous, so this seemed like a good approach.
I can see why this method could be looked down upon since it’s practically made for monkey-patching, and no one likes that, but sometimes you can’t use inheritance..? I’ll have to look more into this later.
