I once was hackathoning with a colleague who was trying to get me excited about Rails, and he said, "look how great this is -- if you want the idea of '1 day', you can just write `1.day`!". I opened up a irb to try it out, and it didn't work. We were both confused for a bit until he figured out that it was a Rails thing, not a Ruby thing. That Rails globally punches date/time methods into integers, which he thought was cool, and I thought was abhorrent. I asked, "okay, if I came across this code, how would I be able to know that it came from Rails?" He said, there wasn't any way to really trace a method to its source definition, you just kinda have to know, and I decided this whole thing was too much of a conflict with my mental model for how humans and code and computers should work together.
plans = {
1.month => {standard: 10, pro: 50, enterprise: 100},
1.year => {standard: 100, pro: 500, enterprise: 1000}
}
plans.each do |interval, details|
details.each do |name, amount|
Billing::Plan::Factory.find_or_create_by!(name: , interval:, amount:)
end
endThis way of handling attributes is monumentally less efficient than just using keyword attributes, which are optimized by the runtime.
Unfortunately you’ll find this is every Ruby code base: tiny readability improvements that are performing allocations and wasting cycles for no real reason other than looking better.
I’ve certainly done that and it’s expected, efficient code looks “weird”. A regular “each” loop that looks complicated will be transformed into multiple array method chaining, allocating the same array many times. If you don’t do it someone else will.
Putting this kind of type-based 'magic' in the code is a bad decision that will bite you very soon. It optimizes for being 'cute' rather than being clear and maintainable, and that's a trade-off that almost never pays off.
Billing::Plan::Factory.find_or_create_by!(
name: :pro,
interval: 1.month,
amount: 50
)
It is not only the verbosity or use of trailing '!' in a method
for no real reason, IMO, but also things such as "1.month". I
understand that rails thrives as a DSL, but to me having a method
such as .month on an Integer, is simply wrong. Same with
HashWithIndifferentAccess - I understand the point, to not have
to care whether a key is a String or a Symbol, but it is simply
the wrong way to think about this. People who use HashWithIndifferentAccess
do not understand Symbols.```rb
[:red, 1.month, 10]
[:red, 1.year, 120]
[:blue, 1.month, 120]
[:blue, 1.year, 300]
```Every possible attribute (name, interval, amount) has at least two objects that share a value
This is just using operator overloading to determine keywords, but it locks you out of ever using the same type twice in your signature. Notice that :usd turns into a name. What?
This is cute, but has no place in a professional software interface.
Or, as Patrick McKenzie used to tell us over and over, “charge more”.
(Yes, yes, I know some situations, customers, product, thinking, etc are different. But with broad brushstrokes, my advice is to not even entertain such a low price.)