[HN Gopher] An Overview of Ruby on Rails 7.1 Features. Part III
       ___________________________________________________________________
        
       An Overview of Ruby on Rails 7.1 Features. Part III
        
       Author : mariuz
       Score  : 60 points
       Date   : 2023-01-23 20:06 UTC (2 hours ago)
        
 (HTM) web link (manny.codes)
 (TXT) w3m dump (manny.codes)
        
       | siaw23 wrote:
       | Rails has matured through the years, I'm convinced it's the right
       | framework for any project if you already know it, you can get by
       | with Hotwire for the FE and not run after React and the rest.
       | Happy to be a Rails dev to be honest.
        
         | jemmyw wrote:
         | It's good with React too when you need more interactivity.
        
           | siaw23 wrote:
           | I believe you can do anything React can with Stimulus + Turbo
           | these days. I don't do much FE but I've been tracking Hotwire
           | for some time now.
        
             | sharps_xp wrote:
             | perhaps for most things but probably not to the extent of
             | something like excalidraw, which uses react
        
               | splitrocket wrote:
               | Yes, but in that case, you can use only the complexity
               | where you need it, instead of globally.
        
         | Gigachad wrote:
         | Rails is extremely easy to get started with but after a few
         | years the lack of types on Ruby cripples every single Rails app
         | I've ever worked on. You can have as many unit tests and
         | browser automation tests as possible, but updating any gem is a
         | dice roll despite doing as much due diligence possible. And
         | it's always something extremely trivial like a method changing
         | its parameters without announcing it in the change log for some
         | reason. Something almost any other language would warn you
         | about.
         | 
         | I've been doing Rails dev for 7 years now but I just don't see
         | it winning over TypeScript/nodejs frameworks. The only
         | advantage Rails still holds is the out of the box batteries
         | included package. But once a TS framework gets this, Rails will
         | be in decline.
        
       | gregmolnar wrote:
       | So many great features. Rails still seems to be the best choice
       | to build a web app.
        
         | dieselgate wrote:
         | Completely agree with you! It's kind of an interesting time
         | because my current Org is moving away from a large established
         | Rails codebase - and it makes sense given needs. But Rails is
         | still such a good option for building web apps. It will
         | definitely stick around
         | 
         | Edit: i really like seeing "overview" posts like these to get
         | up to speed on new features because many devs seem to rarely
         | work on "up-to-date" versions
        
           | LeonenTheDK wrote:
           | Just curious, I'm not into Rails or Ruby at all, but given an
           | established codebase, what's the reasoning for a big move
           | like that? My org is doing a similar shift (C#, the legacy
           | .NET Framework -> Elixir) and while I quite like Elixir I
           | don't think the language change itself is doing much for us.
        
             | dieselgate wrote:
             | Wish I was more aware of the decision making process for
             | everything but believe the move is to foster more of a
             | micro frontend architecture where separate js
             | packages/federated components make up the client
             | experience. The Rails side of things is really used as an
             | orchestration layer for the views and to handle business
             | logic while also consuming a .NET database layer for
             | services.
             | 
             | It's not really the "normal" way of using Rails but seems
             | to function quite well on a "large scale". I agree it's
             | probably not just the language change itself that's the
             | reason but also due to the agility/advantages of Node
             | compared to a Rails "monolith" - and I'm already starting
             | to speak outside my familiarity of the architectural goals
             | of everything
        
       | revskill wrote:
       | RoR is nice, but it lacks one of the most important abstraction
       | layer: The schema layer for HTTP. Currently the default is to mix
       | model params with http params. It's bad default.
       | 
       | Of course you can use dry-schema for that purpose, but i do think
       | the framework should enforce that for the whole ecosystem to
       | follow.
        
         | hakunin wrote:
         | I've had great success building form objects with portrayal
         | (https://github.com/scottscheapflights/portrayal) and
         | ActiveModel. You can put validations into them, and auto-filter
         | the params by making a `from_params(params)`-type constructor.
         | In it you can call require/permit with `portrayal.keywords`.
         | You're right that it'd be nice to have this out of the box, but
         | this is just a few lines of glue code to setup. I'm in the
         | process of making a new app template that does that.
        
           | revskill wrote:
           | This gem is just for construction, no validation ?
           | 
           | Schema layer purpose is to enforce invariant at the boundary
           | of HTTP.
        
             | hakunin wrote:
             | The gem is just for declaring struct keywords (slightly
             | more featureful than vanilla structs). Validation is left
             | up to ActiveModel::Model. I would do a setup like this:
             | class ApplicationForm           extend Portrayal
             | include ActiveModel::Model                class << self
             | def from_params(params)
             | new(**filter_params(params))             end
             | def filter_params(params)               params
             | .require(model_name.param_key)
             | .permit(*portrayal.keywords)                 .to_hash
             | .transform_keys(&:to_sym)             end           end
             | end              class MyForm < ApplicationForm
             | keyword :first_name           keyword :last_name
             | validates :first_name, :last_name, presence: true
             | end
             | 
             | Can use it in a controller action like
             | form = MyForm.from_params(params)         if form.valid?...
             | # the usual
             | 
             | One of the good things about this approach is that you can
             | also use this object in form_for/form_with in your views.
        
               | hakunin wrote:
               | That said, there are similar objects one can make without
               | using the "form" moniker, for API submissions for
               | example. Granted, I also wish a solution was built-in.
        
             | [deleted]
        
         | jbverschoor wrote:
         | Yeah, the whole permitted params is actually is pretty shitty
         | workaround against something else.
         | 
         | We're missing the 'form' part. Validations should be done
         | against forms, not models. Default forms can easily be derived
         | from models, which is nice for simple apps, but this is really
         | something that's lacking in rails.
         | 
         | Permitted params exists because there is no form (dry-schema
         | for example). There's ActiveModel, but it's not the same, and
         | it's not ad-hoc / bound to the view/controller layer of things.
        
           | joshmn wrote:
           | For a form object I've shipped this and it's been lovely
           | across multiple domains: https://gist.github.com/joshmn/ae1c2
           | a27a6a4da22d1542d430b4df...
           | 
           | Smells/tastes/quacks like ActiveModel.
        
           | revskill wrote:
           | It's the main reason for bad legacy of many of Rails
           | applications in the wild (noone wants to maintain the model
           | code inside the view/controller). And it's HARD to understand
           | why ? Omasake is bad omasake when you mix "unrelated
           | concerns" together.
        
             | canadianfella wrote:
             | [dead]
        
           | rubyfan wrote:
           | Sounds like you want MVVM vs. the default MVC pattern Rails
           | ships. I think there are a few options out there which are
           | bolt on for Rails but nothing out of the box.
        
           | bvirb wrote:
           | I inherited a project where all the validations were in the
           | forms and it meant that you couldn't reliably use the model
           | layer without the forms layer (you'd end up saving invalid
           | data). We eventually moved the validations to the model layer
           | and dropped the forms abstraction. It didn't feel like the
           | right separation of concerns when we had to pretend data was
           | moving through forms to reliably interact directly with the
           | model layer.
           | 
           | The enforcement of allowed params (and type casting from
           | strings) definitely seemed like it was in the right place
           | per-action in the control layer though, so we kept that from
           | the forms even though we implemented it in the controllers.
           | 
           | I wonder if we just didn't understand the idea though? Or
           | maybe if the original implementers didn't implement it right?
        
         | ezekg wrote:
         | I also wasn't a fan of how Rails handles params, so I ended up
         | writing my own lib. And I'm actually working on open sourcing
         | it and extracting into a gem.                   typed_params {
         | param :data, type: :hash do             param :first_name,
         | type: :string, optional: true             param :last_name,
         | type: :string, optional: true             param :email, type:
         | :string, format: { with: /@/ }             param :password,
         | type: :string, length: { minimum: 8 }             with if: -> {
         | current_bearer&.admin? } do               param :metadata,
         | type: :hash, allow_blank: true, optional: true
         | param :role, type: :string, inclusion: { in: %w[admin user] },
         | optional: true,                 transform: -> (_, role) {
         | [:role_attributes, { role: }] }               param
         | :permissions, type: :array, optional: true, if: -> {
         | current_account.ent? } do                 items type: :string
         | end             end           end         }         def create
         | # ... controller code here         end
         | 
         | Each param schema has to be defined by source, e.g. request
         | body vs query string. And params aren't intermixed (including
         | routing params).
        
           | revskill wrote:
           | We want a generic interface: Think Rack for params
           | parsing/serializing, then you could easily parse any params
           | into your own data structure. Stringly types are out of
           | scope.
        
             | ezekg wrote:
             | Why do you need something so generic? Can you share a use
             | case?
        
         | Spivak wrote:
         | Yeah, I'm pretty sure every Rails shop has invented some flavor
         | of APIObjectSerializer based on JSON-API, REST, or whatever
         | because doing it ad-hoc will make you pull your hair out.
        
       | moomoo11 wrote:
       | I have a question and anecdote.
       | 
       | I've been on teams in the past that had to deal with rails apps
       | (legacy code usually) and I found ruby to be really difficult to
       | understand. There are so many ways to do one thing, and with the
       | rails addition there are now so many conventions to follow. Then
       | when those conventions don't work anymore, and the code base goes
       | off the rails (no pun intended) and the out of the box
       | conventions no longer make sense.
       | 
       | Granted most of my experience is writing Go, followed by dart,
       | swift, and typescript. I have a hard time navigating codebase of
       | a dynamic language and it's a pita to have to rely on tests (not
       | everyone writes good tests).
       | 
       | I use Go for all my backend tasks and it is not only fast
       | performance, but really easy to be productive in because there is
       | usually one way to do things and the std lib is amazing.
       | 
       | Where does rails fit in? Like I can build an entire production
       | ready backend service that can scale in like 2 days with Go that
       | is easy to deploy and maintain, and not need to bring in any big
       | Go framework or libs besides like uuid, managed sdk, or db
       | driver.
       | 
       | Why would someone choose rails over Go or even node JS with
       | express and a few middlewares? (In 2023)
        
         | revskill wrote:
         | Ruby is OOP.
         | 
         | Go is procedural.
         | 
         | They're different.
        
       | flamebreath447 wrote:
       | Maybe this is a bit close-minded to say.
       | 
       | Even with the evolution of Ruby on Rails and adding more rich
       | feature sets, I wouldn't recommend it as an out of the box Webapp
       | BECAUSE upgrading to newer versions of RoR sucks.
       | 
       | The more time I invest in trying to like RoR the more I end up
       | having to fork gems to patch them because upgrades cannot be made
       | smoothly.
       | 
       | It so easily integrates ActiveRecord, and heavily encourages it,
       | that when you want to pull out of using it it's a huge pain.
       | 
       | Test suite combines unit and integration testing.
       | 
       | It's been a net loss imho to learn and work with it over the
       | years.
       | 
       | I've been waiting to be persuaded otherwise.
       | 
       | Edit: apparently people disagree with me but haven't countered
       | the points, is HN just full of Ruby fans?
        
         | ydnaclementine wrote:
         | I would say the most annoying bit is around javascript. For
         | example I would like to move a rails 6.1 project to 7, and also
         | replace webpacker with esbuild. I'm pretty sure I will just
         | create a fresh 7 project and start copy pastaing files over,
         | then do the javascript stuff delicately (the default javascript
         | setup in rails 7 is also quite strange)
         | 
         | But upgrading pure API Rails projects is much less painful
        
         | onnnon wrote:
         | This is because Rails does not have a strict backwards
         | compatibility policy like many other frameworks. It's done on
         | purpose to stay relevant, aka "Progress over stability".
         | 
         | https://rubyonrails.org/doctrine#progress-over-stability
        
           | Gigachad wrote:
           | That would be fine, if it was possible to actually work out
           | what changes you need to make. But Rails will have breaking
           | changes every release that aren't mentioned in the docs. I've
           | spent around 200+ hours over the last year trying to update
           | our app from 5.1 to 5.2. And it's not some kind of
           | megaproject on the scale of Github, its an ordinary app
           | around 10 years old.
           | 
           | Every single Rails update is extremely painful and issues
           | will slip through every unit test and browser automation you
           | can come up with. Stuff that would be trivially catchable
           | with type checking.
        
         | hakunin wrote:
         | Not sure why you're downvoted either, it's a legit concern. One
         | way to address it is by being very conservative and picky with
         | gems. A good example is Hey's Gemfile (the app made by Rails
         | creators):
         | https://gist.github.com/dhh/782fb925b57450da28c1e15656779556.
         | It's a good (albeit slightly outdated) example of not straying
         | too far from defaults, while not reinventing the wheel either.
        
           | Gigachad wrote:
           | You have to be super careful with gems because every single
           | one you add risks blocking you from updating rails. Resulting
           | you either having to wait for them to get updated, or if they
           | are abandoned, you have to remove them and rewrite all the
           | code that depends on them. I've spent so long replacing all
           | the code in our app which is built on abandoned gems.
        
             | hakunin wrote:
             | True. I tend to stay away from gems that try to integrate
             | into multiple parts of your app to provide some sort of
             | comprehensive solution. The kinds of gems I recommend are:
             | 1) libraries (you call into them when you need them) 2)
             | mounted apps on a url, isolated from the rest of your app
             | 3) generators (a nice example:
             | https://github.com/lazaronixon/authentication-zero).
        
           | [deleted]
        
         | siaw23 wrote:
         | I've never had problems with upgrades, in fact the latest
         | version of Rails make upgrading a breeze. What Rails app
         | version are you trying to upgrade? Happy to help. Rails also
         | has an upgrade guide that's quite good:
         | https://guides.rubyonrails.org/upgrading_ruby_on_rails.html
         | 
         | And you can use https://railsdiff.org/ to check what you're
         | missing in upgrade apps. Anything other thing that breaks would
         | most like come from another gem, which doesn't make it Rails'
         | fault or Ruby itself, in the case of Ruby, you can track
         | everything to the source to fix it. Ruby keeps a change log
         | diligently. Everything is trackable, at least in my experience.
        
       ___________________________________________________________________
       (page generated 2023-01-23 23:01 UTC)