brunosutic

Joined 15 years ago

Karma
1,230
Submissions
112
Member since
Dec 9
I work on: https://railsbilling.com Personal website: https://brunosutic.com

Get in touch: hacker.news AT brunosutic.com

View on Hacker News

Recent submissions

Comment · 7 months ago
Hetzner
Comment · 7 months ago
I tried lnav about 7-8 years ago and as a terminal junkie I really liked the features.

The only breaking thing was a huge (almost bloated) memory consumption. At that time lnav basically just kept everything in memory. Does anyone did that change?

Comment · 10 months ago
Comment · 11 months ago
How do you guys handle past due / grace period if there are no webhooks? Like, do you notify the end-user that their card failed and they need to update their card? Or do you let Stripe send emails?

What's your approach to 3DS and related race-conditions for subscriptions? In my experience 3DS is by far the biggest problem for subscription integrations - not the webhooks.

Comment · 11 months ago
Comment · 11 months ago
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.

Comment · 11 months ago
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.

Comment · 11 months ago
This is supported and would work with no implementation changes. The "Friendly Attributes" idea is very flexible.

Just a small Ruby syntax correction for your example:

  Billing::Plan.find_or_create_all_by_attrs!(
    standard: {1.month => 10, 1.year => 100},
    ...
  )
Comment · 11 months ago
> I would consider monthly Enterprise & yearly Enterprise the same plan, with modified cost & billing frequency.

How would you then call the objects that store costs and billing frequency? :)

Here's what Stripe uses:

- Product: "describes the goods or services". This is where you define a (plan) name and features.

- Price: defines the amount, currency, and (optional) billing interval. Since interval is optional, Prices can be used to define both recurring, and one-off purchases.

Technically, using Prices for recurring, and one-off payments is a brilliant idea. The problem is, no one refers to recurring payments as "prices". Everyone calls a "$50 per year" option a "plan".

Comment · 11 months ago
Comment · 11 months ago
Hi, I'm the author of the article and the software library. I confirm I actually do use the examples from the article in my code.

Here's the example that runs in hundreds of integration tests:

  expect(billing_pricing_plans).to eq billing_plans(
    1.month => [:free, :premium, :pro, :enterprise],
    1.year => [:free, :premium, :pro, :enterprise]
  )
It asserts what plans the customers see on the pricing page.
Comment · 11 months ago
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 ensures six billing plans are created. That means 6 DB queries and 6 Stripe API queries, at a minimum.

Live from the official Hacker News API

A modern reader for Hacker News · SvelteKit + Skeleton