Live data from Hacker News

We fell out of love with Next.js and back in love with Ruby on Rails

hardcover.app

461–470 of 533 posts

Re: We fell out of love with Next.js and back in love with Ruby on Rails

#461

Earlier quoted context omitted.

Other people have mentioned "dynamic typing" as being the reason for this, but that's not actually true. The real reason is two Ruby features: `define_method` and `method_missing`. If you have a class `Customer` with a field `roles` that is an array of strings, you can write code like this class Customer ROLES = ["superadmin", "admin", "user"] ROLES.each do |role| define_method("is_#{role}?") do roles.include?(role)…

To add, the above code is a pretty near approximation of the literal code inside the devise codebase, which is a very standard Ruby auth system. See here: https://github.com/heartcombo/devise/blob/main/lib/devise/co... def self.define_helpers(mapping) #:nodoc: mapping = mapping.name class_eval That code is *literally* calling class_eval with a multi-line string parameter, where it inlines the helper name (like admin,…

It's been widely understood in the Ruby community for some time now that metaprogramming—like in the example above—should generally be limited to framework or library code, and avoided in regular application code.

Dynamically generated methods can provide amazing DX when used appropriately. A classic example from Rails is belongs_to, which dynamically defines methods based on the arguments provided:

class Post This generates methods like:

post.user - retrieves the associated user

post.user=(user) - sets the associated user

post.user_changed? - returns true if the user foreign key has changed.

Re: We fell out of love with Next.js and back in love with Ruby on Rails

#462

Earlier quoted context omitted.

How are you doing reusable components with the html dsl? From the little bit I’ve tried ktor this was something I could not figure out and it kinda just pushed me away since I couldn’t find anything.

To build reusable components, I end up using a mix of a lot of extension functions and Kotlin's function pointer syntax. So, the components themselves will look something like this: fun HtmlBlockTag.radioButtonWithLabel( groupName: String, id: String, hidden: Boolean = false, radioButtonFunc: (INPUT.() -> Unit)? = null, func: LABEL.() -> Unit ) { radioInput(name=groupName) { this.id = id this.hidden = hidden radioBut…

That's pretty much what I was looking for, thank you for sharing! I think that's probably the nicest way I've seen to do it, annoying that Kotlin seems to force you to add it as a child (? idk the word...) of an existing HTML tag, wish you could just import a component or something :(

Re: We fell out of love with Next.js and back in love with Ruby on Rails

#463
post #330

Earlier quoted context omitted.

> People with bad intentions can make those slow queries happen at high volume with custom tooling, they don’t have to restrict themselves to how the frontend uses the queries Depends how your system is set up. I'm used to only allowing compiled queries on production instances, in which case attackers have no way of running a different query that you don't actually use.

Do you understand that decompilers and reverse engineering are a thing? Adversaries are not restricted to using your system the way you designed your system. GraphQL queries are trivial to pull out of Wireshark and other sniffers. If you deliver it to the browser, any determined-enough adversary will have it, period. I wouldn't be surprised in the least if it is already a thing for LLM models to sniff GraphQL endpoin…

> Do you understand that decompilers and reverse engineering are a thing?

Do you understand how compiled queries in GraphQL (or even an old-school RDBMS) work? All that gets sent over the wire is the query id. There's physically no way to make the server execute a query the author didn't write.

Re: We fell out of love with Next.js and back in love with Ruby on Rails

#464
post #330

Earlier quoted context omitted.

> People with bad intentions can make those slow queries happen at high volume with custom tooling, they don’t have to restrict themselves to how the frontend uses the queries Depends how your system is set up. I'm used to only allowing compiled queries on production instances, in which case attackers have no way of running a different query that you don't actually use.

So un-graphql-ing your graphql. This shit is wild.

Shrug, databases have been doing the same thing since the 1970s (and consider also e.g. regexes). Turns out a flexible, expressive language for writing queries isn't always the most secure or performant thing to use as your wire format.

Re: We fell out of love with Next.js and back in love with Ruby on Rails

#465

Earlier quoted context omitted.

To add, the above code is a pretty near approximation of the literal code inside the devise codebase, which is a very standard Ruby auth system. See here: https://github.com/heartcombo/devise/blob/main/lib/devise/co... def self.define_helpers(mapping) #:nodoc: mapping = mapping.name class_eval That code is *literally* calling class_eval with a multi-line string parameter, where it inlines the helper name (like admin,…

It's been widely understood in the Ruby community for some time now that metaprogramming—like in the example above—should generally be limited to framework or library code, and avoided in regular application code. Dynamically generated methods can provide amazing DX when used appropriately. A classic example from Rails is belongs_to, which dynamically defines methods based on the arguments provided: class Post This g…

Aren’t all these enhancement methods that are added dynamically to every ActiveRecord a major reason why regular AR calls are painfully slow and it’s better to use .pluck() instead? One builds a whole object from pieces, the other vomits put an array?

Re: We fell out of love with Next.js and back in love with Ruby on Rails

#466

Earlier quoted context omitted.

To build reusable components, I end up using a mix of a lot of extension functions and Kotlin's function pointer syntax. So, the components themselves will look something like this: fun HtmlBlockTag.radioButtonWithLabel( groupName: String, id: String, hidden: Boolean = false, radioButtonFunc: (INPUT.() -> Unit)? = null, func: LABEL.() -> Unit ) { radioInput(name=groupName) { this.id = id this.hidden = hidden radioBut…

That's pretty much what I was looking for, thank you for sharing! I think that's probably the nicest way I've seen to do it, annoying that Kotlin seems to force you to add it as a child (? idk the word...) of an existing HTML tag, wish you could just import a component or something :(

Kotlin calls those "Extensions" [0], and yeah, they can be pretty annoying. I first learned about them in C# and I had a bunch of frustrations with them, especially when I found some code on StackOverflow or Microsoft's docs and they'd use one of those methods and it just plain wouldn't be there for me because I hadn't downloaded the right nuget package or anything.

I've gotten more used to them and I get why they can be so great now; but there's still some real annoyances with them I just can't shake (like the import problem and the related "where is this code?!" problem)

---

Purely importing a component that's just a simple class, like you can do in Java/Typescript with their jsx and tsx files would be pretty cool, yeah. You could fake it by making a data class and adding a

  fun renderInto(tag: HtmlBlockTag) { ... }
type method, but with how Ktor's Dsl is implemented, you're still going to need to connect it into the giant StringBuilder (or whatever) that the dsl is building to.

To help me get something close to that idea, I tend to dedicate whole files to bigger components and even name the file the same as the root HtmlBlockTag Extension method (like RadioButtonWithLabel.kt if I did it for the earlier one). Those files are great because you can put a bunch of helper methods in the same file and keep it all contained, a lot like a class.

[0] https://kotlinlang.org/docs/extensions.html

Re: We fell out of love with Next.js and back in love with Ruby on Rails

#467
post #344

Earlier quoted context omitted.

The go-to is Drizzle

That's funny, I would say the go-to is Prisma. We use it heavily and have not had any issues.

I've used both and Drizzle has become the goto now in the TS community.

Re: We fell out of love with Next.js and back in love with Ruby on Rails

#468

Earlier quoted context omitted.

>Websites. Wait, is SSR a thing outside the context of websites?

There was a time when SSR was the only option. All early web apps were SSR. It gets rather painful though, which is why we don't do that anymore.

The majority of websites do in fact still do that and add interactivity with ajax. Works great (far better and far simpler than react and similar frameworks).

Re: We fell out of love with Next.js and back in love with Ruby on Rails

#469

Earlier quoted context omitted.

An additional one for me is stale state. I can leave most webpages open for days, except SPAs. Especially on mobile.

A small but silly one: breaking middle and right click functionality for links. An auction site I use loads in the list of auctions after the rest of the page loads in, and also doesn't let you open links with middle click or right click>new tab, because the anchor elements don't have href attributes. So that site is a double-dose of having to open auctions in the same tab, then going back to the list page and losing…

This is not exclusive with an SPA. Even MPAs/SSR apps can have this issue. But I guess MPAs are probably not built with post load interactivity in mind and maybe that's why its less prevalent there.

Re: We fell out of love with Next.js and back in love with Ruby on Rails

#470

Earlier quoted context omitted.

What's the business usecase for incrementing a counter? We can sit here all day and think up counterexamples, but in the real world what you're doing 99% of the time is: 1. Presenting a form, custom or static. 2. Filling out that form. 3. Loading a new page based off that form. When I open my bank app or website, this is 100% of the experience. When I open my insurance company website, this is 100% of the experience.…

> What's the business usecase for incrementing a counter? Notification count in the top right? Remaining credit on an interactive service (like the ChatGPT web interface)? So, maybe two(!) business use-cases out of thousands, but it's a pretty critical two use-cases. I agree with you though - do all normal HTML form submissions, and for those two use-cases use `setInterval` to set them from a `fetch` every $X minutes…

In my experience it's just exceedingly rare to require this. My insurance company website has a notification thing, and it's actually static. You need to refresh the page, and considering how few and far between notifications are, and how common refreshes are, it works fine.

There's an entire domain of apps where you truly need a front-end. Any desktop-like application. Like Google Sheets, or Figma. Where the user feedback loop is incredibly tight for most operations.

Post reply on HN