Live data from Hacker News

Friendly attributes pattern in Ruby

brunosutic.com

51–60 of 78 posts

Re: Friendly attributes pattern in Ruby

#51
post #48

I'll add another cautionary word in with everyone else who is panning this implementation. 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.

> but it locks you out of ever using the same type twice in your signature.

I don't see how you drew that conclusion. It seems to me the author provided several examples of this not being the case. Care to elucidate?

Re: Friendly attributes pattern in Ruby

#53
post #34

Earlier quoted context omitted.

The usual response to this complaint in the Ruby/Rails community is that optimizing for nanoseconds, or even milliseconds doesn't matter when the same operation also involves multiple database queries or API calls. Let's take this example from the article: Billing::Plan.find_or_create_all_by_attrs!( 1.month => {standard: 10, pro: 50, enterprise: 100}, 1.year => {standard: 100, pro: 500, enterprise: 1000} ) This ensur…

This attitude towards wastefulness is how you have web apps that could run in a single machine but struggle to run in a server cluster. And after a couple years even Postgres is struggling because the amount of queries is too massive because of abstractions that don’t lend themselves to optimization. Also it’s how you have codebases that could be maintained by two or three suddenly needing dozens because the testing…

The reality is most companies and products never blow bast the point of needed to ditch Rails. The argument made at the time was scaling horizontally is cheaper than hiring new devs, and you probably will never need to scale that much horizontally.

Test suite bloat is a different problem that stems from the lack of incremental typing which I think is what ultimately killed Ruby and Rails.

Any big Rails codebase can be a nightmare to grok unless people have been diligent about documenting what different methods return.

Re: Friendly attributes pattern in Ruby

#54
post #34

Earlier quoted context omitted.

The usual response to this complaint in the Ruby/Rails community is that optimizing for nanoseconds, or even milliseconds doesn't matter when the same operation also involves multiple database queries or API calls. Let's take this example from the article: Billing::Plan.find_or_create_all_by_attrs!( 1.month => {standard: 10, pro: 50, enterprise: 100}, 1.year => {standard: 100, pro: 500, enterprise: 1000} ) This ensur…

This attitude towards wastefulness is how you have web apps that could run in a single machine but struggle to run in a server cluster. And after a couple years even Postgres is struggling because the amount of queries is too massive because of abstractions that don’t lend themselves to optimization. Also it’s how you have codebases that could be maintained by two or three suddenly needing dozens because the testing…

Again, though, these bottlenecks are because of how the system queries the database, not how methods are dispatched.

I agree on the ORM abstractions causing huge performance issues, but it has nothing to do with Ruby’s dynamic method declarations.

Re: Friendly attributes pattern in Ruby

#55

Off-topic, but unlike the example pricing plans, don’t make your SaaS’s “standard” plan $10/month. If you want a place to start, start with $50/month. 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.)

As an end user, there's no way I'd pay $50/month for any SaaS.

Lots of people feel the same.

Which leads me to another piece of advice: don’t do B2C. Sell to businesses who will be far more willing to pay higher prices, will churn at a lower rate, and will - in general - require less support.

Re: Friendly attributes pattern in Ruby

#56
So the underlying assumption is that there is always at least one attribute that serves as a "discriminator" between the billing plans, right? Is it possible to represent something like this then?

```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

Re: Friendly attributes pattern in Ruby

#57
post #53
post #34

Earlier quoted context omitted.

This attitude towards wastefulness is how you have web apps that could run in a single machine but struggle to run in a server cluster. And after a couple years even Postgres is struggling because the amount of queries is too massive because of abstractions that don’t lend themselves to optimization. Also it’s how you have codebases that could be maintained by two or three suddenly needing dozens because the testing…

The reality is most companies and products never blow bast the point of needed to ditch Rails. The argument made at the time was scaling horizontally is cheaper than hiring new devs, and you probably will never need to scale that much horizontally. Test suite bloat is a different problem that stems from the lack of incremental typing which I think is what ultimately killed Ruby and Rails. Any big Rails codebase can b…

Nothing has “killed Ruby on Rails”.

Ridiculous comment.

Re: Friendly attributes pattern in Ruby

#58
post #56

So the underlying assumption is that there is always at least one attribute that serves as a "discriminator" between the billing plans, right? Is it possible to represent something like this then? ```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

Your input would work exactly as you wrote it if passed to `Billing::Plan.find_or_create_all_by_attrs!`, just add commas at the end of lines.

If you want to make it even shorter, you have a few options - it really just comes down to preference:

  # Option 1. my personal favorite, follows structure of
  # intervals and plans on a pricing page.
  1.month => {red: 10, blue: 120},
  1.year => {red: 120, blue: 300}

  # Option 2. this is fine too
  red: {1.month => 10, 1.year => 120},
  blue: {1.month => 120, 1.year => 300}

  # Option 3. possible and works, but hurts my brain, NOT recommended
  10 => {red: 1.month},
  120 => {red: 1.year, blue: 1.month},
  300 => {blue: 1.year}
> there is always at least one attribute that serves as a "discriminator" between the billing plans, right

Just a note: if you try to create two plans with the same attributes, that would error because of ActiveRecord uniqueness validations (and DB constraints). No point in having multiple identical plans.

Re: Friendly attributes pattern in Ruby

#59

Haters gonna hate. My take: DSLs are a useful way to make code easier to read, and more importantly easier to write correctly . Exploring this space and sharing your learnings is useful and valuable.

Article author here - thank you for putting it this way. This is exactly the attitude I wanted to convey: it's something I tried and really liked for this specific use case. I shared because I hope it might inspire others.

"Friendly Attributes" is not the "new way", not to be used "everywhere now", does not "apply to all scenarios".

If you like it, maybe you'll use it once in the next five years when the opportunity arises.

Re: Friendly attributes pattern in Ruby

#60

This is...not for me. It follows a big pattern in Ruby/Rails culture where to understand the code, you first have to understand the magic. And, it's never all that obvious where to go to try and understand the magic, because the magic itself has been imported by magic. 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…

That's one thing which ruby unfortunately did not adopt from Smalltalk. In Smalltalk (at least, in the dialects I'm familiar with), the "method categories" metadata is used to signal that we're adding new methods (or overwriting existing ones) to classes that are outside the scope of this package (ie: classes you didn't create as part of your app).

That way, it's easy to trace, forwards (from package to all the methods it introduces) & backwards (from method to package), who introduced a method, where, and why.

Other than that, I think a lot of this aversion to "ruby magic" is a bit overblown. The ability to cleanly remold any part of the system with minimal friction, to suit the app you're building right now - that's a KEY part of what makes it special.

Its like all these polemics warning wannabe lispers away from using macros. Lisp, Smalltalk, and ruby, all give you very powerful shotguns to express your creative ideas. If you can't stop blowing your own foot off, then pick a different language with a different paradigm.

Post reply on HN