[HN Gopher] Mastering Ruby Code Navigation: Ruby LSP Enhancement...
       ___________________________________________________________________
        
       Mastering Ruby Code Navigation: Ruby LSP Enhancements in the First
       Half of 2024
        
       Author : ksec
       Score  : 136 points
       Date   : 2024-07-24 15:30 UTC (3 days ago)
        
 (HTM) web link (railsatscale.com)
 (TXT) w3m dump (railsatscale.com)
        
       | simply-typed wrote:
       | The fact IntelliSense and jump-to-source are supported at a very
       | superficial level goes to show the heavy drawbacks of dynamic
       | types.
       | 
       | Sorbet may fix things, but at that point, just use a language
       | with more mature tooling around types, like Python or TypeScript.
       | 
       | Dynamic types offer dubious marginal benefits but bring tons of
       | downsides. The demonstrations in this article reflect that.
        
         | ecshafer wrote:
         | I like coding in Ruby a lot more than Python or Typescript.
         | From using the Ruby LSP in the article daily (though I am not
         | on the team) I can say it works quite good and I have very few
         | issues with navigating Ruby source. If I were very worried
         | about types, going to Python or Typescript seems like not a
         | very good solution. Python barely has more type support than
         | Ruby, and Ruby is making a lot of gains in this area. Might as
         | well go to an even more expressive and powerful language like
         | F#, Haskell, Ocaml, Scala, or similar.
        
           | maleldil wrote:
           | > Python barely has more type support than Ruby
           | 
           | That's not true. mypy and Pyright (the main type checkers)
           | are very ahead of Ruby's Sorbet, and Python actually has
           | proper ergonomic syntax to work with types, which Ruby
           | doesn't. It's also seeing constant development to bring more
           | powerful typing and syntax.
           | 
           | Also, typing has become part of the Python culture, which
           | means most of the big libraries have type hints. It doesn't
           | seem like that is the case with Ruby, where type hints aren't
           | as prevalent. Even the core maintainers don't like the idea
           | and want to keep it as dynamic as possible.
        
             | jshen wrote:
             | I've had the hardest time getting mypy to work well in
             | vscode. Trying pyright with neovim now, curious how it
             | goes.
        
               | teaearlgraycold wrote:
               | pyright just requires the Microsoft Python extension. In
               | my experience once you have that it works instantly.
        
               | psychoslave wrote:
               | I don't know Pyright, but is it still Python? It's
               | probably fair to bring it as Sorbet is mentioned, if
               | course. But you can't use Sorbet using a pure ruby
               | interpreter, if I'm getting it correctly, and I guess
               | it's the same for Pyright. It's that so?
        
               | thenipper wrote:
               | Mypy/pyright aren't interpreters. They're basically just
               | linters that you run against Python code to see any
               | typing issues. I don't mean that dismissively,they're
               | great tools.
        
               | maleldil wrote:
               | Pyright and mypy are typecheckers, completely orthogonal
               | to the interpreter. They work like linters that
               | statically perform type checking. By default, Python's
               | type hints are ignored at runtime (i.e. you can do `x:
               | str = 2`, and the runtime doesn't care), but there are
               | tools to perform runtime checks (e.g. beartype) and
               | libraries that make use of types as metadata (e.g.
               | dataclasses, Pydantic, FastAPI).
        
               | ReleaseCandidat wrote:
               | Instead of Pyright use Based Pyright for anything that
               | isn't Code, and in Code (not Codium) you can use Pylance
               | instead.
               | 
               | https://github.com/DetachHead/basedpyright
        
           | barrenko wrote:
           | Ruby has practically no support in a basic tool like VS Code.
           | (Love Ruby btw)
        
             | simoncion wrote:
             | I've tried the VS Code(ium) Shopify Ruby LSP plugin, and
             | it's just BAD.
             | 
             | Have you tried the 'solargraph' VS Code(ium) plugin? I've
             | found it to be pretty good. If you haven't do give it a
             | try, but do know that you need to build the YARD
             | documentation for installed "gems" for Solargraph to not be
             | dogshit.
             | 
             | As described here [0], you run 'yard gems' to build said
             | documentation. Do note that the method of having this
             | documentation always be generated doesn't seem to work with
             | "gems" installed with Bundler. Very frustrating, that.
             | 
             | [0] <https://solargraph.org/guides/yard>
        
         | pjm331 wrote:
         | Or the fact that people continue to do a lot of development in
         | these languages would suggest that the benefits are more than
         | marginal, and the lack of a few editor features is not such a
         | terrible hindrance.
        
           | ht85 wrote:
           | Strongly typed languages have a higher barrier of entry and
           | require an engineering mindset. That's anecdotal but if I
           | think of exceptionally competent people I've worked with on
           | JS projects, all of them have spent time building and
           | advocated for properly typed code bases.
           | 
           | The other camp "just hates it" because it "slows them down",
           | as it seems they spend most of their time fighting the types
           | but never get to the point where you get that huge return on
           | investment.
        
             | psychoslave wrote:
             | I don't know, the ergonomics of the type system is not the
             | same in all languages. A tool chain that report early
             | useful feedbacks in a non cryptic sentences will certainly
             | gains adoption quickly.
             | 
             | Unfortunately most of the time the result is at best
             | needlessly cryptic, with zero thought about simplicity of
             | use. Ruby has a reputation of taking care of this topic.
        
             | pmontra wrote:
             | I've been working with types and malloc for years in C,
             | then enter Java. No need to malloc anymore and everything
             | worked. Great, goodbye C. Then enter Ruby, no need to write
             | types anymore and everything worked. Great, goodbye Java.
             | 
             | That's the great picture. Looking into the details I've
             | been working with Perl, JavaScript, Python plus many other
             | less common languages. I always had a preference for
             | languages that hide complexity away from me.
             | 
             | Code completion really doesn't matter much to me. I've been
             | working for maybe ten years with an emacs package that
             | remembered words and attempted to autocomplete with the
             | most used suffix. It worked surprisingly well.
        
               | simoncion wrote:
               | In my professional experience, types are a godsend for
               | large, and/or long-running projects that have been worked
               | on by many people over the years. They reduce complexity
               | by informing you up-front of the shape of the data and/or
               | objects that a function demands and produces.
               | 
               | If the type-checking system is decent, they also
               | automatically catch a whole class of problems that will
               | only show up at runtime, and may take years to surface.
               | (Ask me about the error-handing code that detonated
               | because it contained a typo in a Ruby class name, which
               | was only discovered three years after it was
               | introduced... when that code was actually exercised
               | during an... _exciting_ outage of a system it depended
               | on.)
        
               | pansa2 wrote:
               | > _types are a godsend for large, and /or long-running
               | projects_
               | 
               | Agreed. But that doesn't mean that every language needs
               | to be statically-typed, which seems to be where we're
               | heading nowadays.
               | 
               | IMO large and/or long-running projects should be written
               | in languages with sound static type systems, not
               | scripting languages with types tacked on. Conversely, I
               | often work on projects which are neither large nor long-
               | running - for those, a dynamically-typed scripting
               | language works perfectly well.
               | 
               | > _a typo in a Ruby class name, which was only discovered
               | three years after it was introduced_
               | 
               | So the code containing this typo was never tested? That's
               | asking for trouble even if you _have_ static typing.
        
               | simoncion wrote:
               | > So the code containing this typo was never tested?
               | 
               | The code _absolutely_ was tested. However, (obviously)
               | not every possible path through the code was tested.
               | 
               | Given a long-enough timeline, you will NEVER remember to
               | test every little thing. Given sufficient code
               | complexity, it can be next to impossible to _actually_
               | exercise every code path with hand-written tests.
               | 
               | That's one of the troubles with large projects written
               | scripting languages like Ruby... you have to write an
               | assload of tests to replace what you get for free in
               | languages (even "loosely"-typed languages like Erlang)
               | that have pre-runtime type-checking (whether or not it's
               | provided by a compiler).
               | 
               | > Conversely, I often work on projects which are neither
               | large nor long-running - for those, a dynamically-typed
               | scripting language works perfectly well.
               | 
               | Oh yeah, for small things such languages are A-OK. I
               | 1000% agree with that. The big problem (that you may
               | never encounter because I bet that you're smarter than
               | the average unending parade of Project Managers) is how
               | often small projects are forced into becoming big
               | projects, and then huge projects as time goes on.
        
               | ninkendo wrote:
               | I'd add to this that there's a good reason the testing
               | culture is so strong in ruby: you absolutely need to
               | write tests for every last little 2-line method to make
               | sure you did it right. With no compilation or type
               | checking step, there's no other way to know if your code
               | is even valid.
               | 
               | Which means that IME a huge number of tests in my ruby
               | code were doing things that a type checker does
               | automatically: make sure that passing nil makes it return
               | nil, making sure that passing an array does the right
               | thing vs a string, etc etc etc.
               | 
               | I have very vivid memories of working in a large rails
               | code base and having no idea whether my change would work
               | until I actually exercised the code and realized I was
               | completely messing up the contract that some method
               | expected, so I had to slow down and write tests to
               | validate my assumptions.
               | 
               | Fast forward to now, I work in a large Rust code base,
               | and it seems like 99% of the time, if my code compiles,
               | it works flawlessly the first time. So I concentrate on
               | writing integration/functional tests, which give me a lot
               | more bang for my buck than having to write hundreds of
               | little unit tests. (I still write some unit tests, but
               | the need for it is much less... the vast majority of
               | things you'd write tests for in Ruby are things the type
               | and borrow checkers handle for you in Rust.)
        
               | simoncion wrote:
               | > ...there's a good reason the testing culture is so
               | strong in ruby:
               | 
               | "Strong" as in "You easily burn 10x more time writing
               | tests as you do code... and not because it's difficult to
               | think through how to write good tests"? If so, yes.
               | 
               | "Good"? Hell, no! That's a bad reason.
               | 
               | > ...a huge number of tests in my ruby code were doing
               | things that a type checker does automatically...
               | 
               | The folks I work with demand that we don't write these
               | tests, so they don't get written. Guess how often code
               | detonates in production because of things a typechecker
               | would have caught... despite the enormous volume of test
               | code.
               | 
               | To be crystal clear, I totally agree with your statements
               | in this comment. I started my "career" with C++ and I'm
               | so damn glad I did. Had I started with Ruby and Rails, I
               | would have come to the conclusion I was far too damn
               | stupid for this field and left to become a lawyer.
        
               | ninkendo wrote:
               | "Good" in this context didn't mean "this is a good
               | situation", but rather "if you're using ruby, it would be
               | very bad if you didn't write tests", and "bad if you
               | don't" can be roughly reworded as "good if you do", at
               | least if we're presupposing that you have to be writing
               | Ruby.
        
         | adamtaylor_13 wrote:
         | The problem is that Rails is the super power that keeps Ruby
         | alive (in my personal opinion). I'd love to use a Typescript
         | solution that has the power and opinionated style of Rails, but
         | there's nothing comparable. I think AdonisJS wants to be that,
         | but it's not battle-tested enough for me to feel comfortable
         | relying on it for production projects.
        
         | cardy31 wrote:
         | Not everyone is at a point where they are greenfield picking a
         | language for a new project. Sorbet was built by a large
         | organization (Stripe IIRC) and is used effectively by
         | organizations with large Rails codebases. I think Sorbet is a
         | great way to maintain velocity on a large Ruby codebase after
         | the initial velocity benefits of dynamic typing have ceased and
         | the dynamic typing is actually a drain on velocity.
        
         | jshen wrote:
         | There is no strong evidence to back up your claims, just
         | opinions.
        
         | viraptor wrote:
         | > Sorbet may fix things
         | 
         | Sorbet is very slow for large codebases. I keep checking it
         | from time to time, but the biggest service I'm dealing with
         | just fails to run through the initialisation. And that's
         | ignoring the idea that someone will have to clean up the
         | result. Not holding my breath for it to be functional in LSP
         | situations.
        
           | pawelduda wrote:
           | How large is large here? I'm using sorbet on fairly big
           | project and it takes like 3 seconds to scan the entire
           | codebase with "srb tc", and with their LSP in editor the
           | diagnostics refresh almost immediately before I stop typing.
           | That is, without even using Sorbet's cache
        
       | hstaab wrote:
       | How does this compare to the JetBrains solution?
        
       | milofeynman wrote:
       | I started a small service recently in rails. I'm forcing sorbet
       | with typechecking (you can still set things to false like tests
       | which sometimes are a pain to get to pass). It feels almost like
       | a typed language with LSP jump to etc. It's getting there.
        
         | Syntaf wrote:
         | How do you like using sorbet? Does it feel natural? I'm also
         | running service on rails and considering trying to integrate
         | sorbet but worry about the syntax
        
           | gls2ro wrote:
           | Not the OP but I started working with Sorbet in a Rails
           | codebase 6 months ago.
           | 
           | Learning it is easy and using it is also easy if you stay
           | away from: 1. Meta programming 2. Methods that are returning
           | different results based on some conditions.
           | 
           | the second case it can be handled by Sorbet but it makes the
           | type more complex.
           | 
           | I find this a nice side effect of Sorbet: - the moment I
           | start fighting the types or feeling to add many T.any it is a
           | signal to me that I should split my methods/objects
           | 
           | Some things that I found useful:
           | 
           | - I started to like T.enum, T.struct and somehow I am feeling
           | them missing now in a normal Rails project.
           | 
           | - I also like T.let as it helps with object shapes and
           | memoization.
           | 
           | - It also solves the inheritance and there is no need to
           | discuss what exception to throw when you want to define a
           | method that should be implemented in
           | 
           | - I would recommend the gem sorbet-results that adds a simple
           | typed monad
           | 
           | - It helps a lot refactoring
           | 
           | To get the full benefits always try to make your files with
           | typed:strict and of course use tapioca with Rails
        
       | stevebmark wrote:
       | Ruby has a lot going for it, but as other commenters point out,
       | the metaprogramming nightmares of the language have held it back
       | 10-30 years behind modern language ecosystems, depending on the
       | feature you're looking at. Celebrating "jump to source
       | definition" (sometimes working) for such a mature language is a
       | symptom of the nature of the language. Sometimes insane dynamic
       | freedom is really useful, but it comes with heavy drawbacks.
        
         | jaynetics wrote:
         | As someone who uses Ruby as well as plenty of other languages,
         | I agree that it can feel awkward not to have "go to source"
         | work reliably, but in the greater scheme of things, it's not a
         | big drain on time to do the occasional full text search or look
         | something up through programmatic introspection. In other areas
         | that might really slow you down or become blocking, Ruby's
         | ecosystem still seems OK to me. I'm thinking package
         | management, compilation or transpilation, availability of
         | battle-tested libraries etc.
         | 
         | I guess it depends on scale as well. The bigger the codebase,
         | the nicer it is to find implementations and references
         | automatically, and the bigger the company, the more likely they
         | are to have good workarounds for the shortcomings of various
         | language ecosystems or even dedicated dev experience teams, in
         | which case Ruby's potential runtime intricacies might really
         | start to weigh it down. Then again, there seems to be some
         | movement away from that all-too-dynamic stuff e.g. in the rails
         | codebase.
        
           | KronisLV wrote:
           | > it's not a big drain on time to do the occasional full text
           | search or look something up through programmatic
           | introspection
           | 
           | Okay, this won't probably be 100% on topic, but in my
           | experience how well these methods work is inversely
           | proportional to the size of the codebase and also quite badly
           | in some cases depending on how the code is written.
           | 
           | The other day I was working on a Java enterprise codebase
           | (monolith, ~300K LoC) and I shouldn't have had that many
           | issues navigating the codebase, however someone made a
           | validator that resolves the logic to a specific class at
           | runtime. So you'd basically have validator.validate(Object
           | someObject). Suddenly if I wanted to find all of the places
           | where validator.validate(MyObject myObject) is called, I
           | could not do that easily and with naming like
           | validator.validate(entity) all over the place, text search
           | didn't help much either. They had an okay type system but
           | chose not to use it, just because they wanted to pass in
           | arbitrary objects, without regard for how easy finding usages
           | will be in the future.
           | 
           | My point is, that you can probably write code that's easy or
           | hard to navigate in any language (within reason), but I'll
           | gladly take whatever tools I can get in any stack out there!
        
             | rtz121 wrote:
             | > however someone made a validator that resolves the logic
             | to a specific class at runtime. So you'd basically have
             | validator.validate(Object someObject).
             | 
             | The pains of not having multiple dispatch.
        
         | psychoslave wrote:
         | I don't think metaprogramming is the key point here, though it
         | doesn't help with this kind of issue.
         | 
         | That is, yesterday I spent the afternoon trying to follow a
         | maze of signal observers in a Vue3 project. After a moment, not
         | finding why the redirect to login page was nowhere to be found
         | in the signal obsevers of the concerned transition, it finally
         | reveled to be linked to a more broad route hook mechanism that
         | the framework provides.
         | 
         | No meta programming is involved, be it in signal observers or
         | route hook.
         | 
         | Regarding metaprogramming, Crystal keep only the parts that are
         | straightfoward to deal with in static analysis, from what I
         | grasped when skiming its elevator speech.
         | 
         | On Ruby side the great stuffs I like in it are more linked to
         | the homogeneous approach it follows. Almost everything is an
         | object and something like
         | `42.extend(:custom*module).original*action` is possible due to
         | that. It's not 100% pure object though, reserved keywords like
         | `if` can not be used as objects, that is `if.class` is not
         | valid.
        
         | eduction wrote:
         | I'm very curious how a language that's not yet 29 years old can
         | be held back 30 years.
        
           | sapiogram wrote:
           | Makes perfect sense to me, it just means the language was
           | already a year behind when it launched.
        
       | Alifatisk wrote:
       | Ruby is nice, I just find the DX to be far behind the other
       | languages. Like code completion is barely working.
        
         | jaynetics wrote:
         | Copilot is pretty good now. It will be interesting to see how
         | much classical code completion matters in the long run and
         | which languages will work best with AI.
        
           | Alifatisk wrote:
           | A solution without ai would be nice
        
       | mkl95 wrote:
       | I used to work at a Ruby shop. As a language, Ruby can be elegant
       | despite the overall weirdness, and some of my coworkers were
       | really productive with it.
       | 
       | On the other hand, the Ruby community seems stuck in the 2000s,
       | with some of the self inflicted Ruby pains and attitude being
       | fairly similar to what some Python devs were doing in the late
       | Python 2 era.
       | 
       | These days, I still like Ruby and I would enjoy building some
       | little project with it, but I would rather make a living using
       | other stuff.
        
         | WizardClickBoy wrote:
         | Curious if you have any examples of these pains? I'm not
         | familiar with the late Python 2 era but I've been writing Ruby
         | for a long time and wonder if I'm doing some of these as well.
        
       | hboon wrote:
       | I'm aware of the limitations of a dynamic language in terms of
       | the looking up references and implementations of types/functions.
       | 
       | For everyone commenting about those and who haven't, I suggest
       | trying RubyMine to set expectations on what is possible first.
        
         | simoncion wrote:
         | > I suggest trying RubyMine to set expectations on what is
         | possible first.
         | 
         | In my professional experience with large, very long-running
         | Ruby projects, RubyMine will at least once per session (and
         | usually much more than once) give you search results that are
         | no better (and sometimes worse) than if you'd just run `grep`
         | on the codebase. (e.g. "I'm pretty sure ONE of these five
         | hundred 'run' functions is the one you want! Oh, by the way, I
         | also am showing you results from every .gem file I know
         | about!")
         | 
         | It also has a bias for presenting results quickly and allowing
         | you to make queries quickly... so quickly that it often returns
         | partial results to queries with absolutely no outward
         | indication that the results are incomplete.
         | 
         | Given what it seems that the other Ruby "Intellisense" plugins
         | are having to do to well-understand real-world Ruby projects
         | (especially those who use Rails and friends), I'm sure that a
         | godawful lot of manual work and special-case knowledge has gone
         | into RubyMine's Intellisense. But, it's still not nearly enough
         | to be reliable on large projects.
        
           | hboon wrote:
           | I thought they have a little indicator that says it's a
           | partial result set?
           | 
           | > I'm pretty sure ONE of these five hundred 'run' functions
           | 
           | Yes. Same thing with all unannotated dynamic languages. Like
           | Smalltalk has a bazillion `#value` and `#value:`s, but there
           | were options to scope it down. You can do that in RubyMine,
           | but I forgot if you can do it by class/gems without manually
           | creating a scope.
           | 
           | Just saying that such navigation isn't impossible with Ruby.
        
             | simoncion wrote:
             | > I thought they have a little indicator that says it's a
             | partial result set?
             | 
             | There might be one (one would think there WOULD be one),
             | but if it does exist, it's so small and unobtrusive that
             | I've never noticed it. My coworkers who use RubyMine every
             | damn day don't seem to notice it either. If it exists, it
             | needs to get much more obvious, IMO.
             | 
             | > ...but I forgot if you can do it by class/gems without
             | manually creating a scope.
             | 
             | I know that my RubyMine-loving coworkers definitely don't
             | do whatever this is and just power through the worse-than-
             | grep results.
             | 
             | > Just saying that such navigation isn't impossible with
             | Ruby.
             | 
             | Fully-automatic trouble-free navigation of sufficiently-
             | large/complex projects is pretty much impossible with Ruby.
             | (At least in a Ruby project that lacks comprehensive,
             | correct type annotations.) I'm just saying that folks who
             | might take RubyMine for a test drive on a small or toy
             | project will be unlikely to get an accurate demonstration
             | of its limitations.
             | 
             | (In my professional experience, RubyMine is not THAT much
             | better than the 'solargraph' VSCode plugin.)
        
               | hboon wrote:
               | > but I forgot if you can do it by class/gems without
               | manually creating a scope.
               | 
               | You can choose and edit scopes with these 2 buttons --
               | https://imgur.com/a/jZute6v
        
               | simoncion wrote:
               | Ah! I've definitely seen my coworkers use that dialog, so
               | I fully expect that they're aware of (and use) that
               | button.
        
       | msie wrote:
       | Writing my own Ruby code is fine but debugging others code is a
       | PITA.
        
       | dabears wrote:
       | I was tired of feeling slowed down by grepping in large Ruby
       | code, and the artificial boundary gems create requiring a `bundle
       | open` to keep digging. I created my own Ruby LSP to solve these
       | problems: https://github.com/pheen/fuzzy_ruby_server
       | 
       | I think it works well, is stable, and I would still reach for it
       | over Shopify's LSP personally. Feel free to use it! Though as a
       | heads up, I don't work in Ruby much anymore unfortunately so I'm
       | not actively working on it or accepting issues.
        
       | aantix wrote:
       | Rubymine is the only editor I've ever used that gets the code
       | navigation consistently right without any config. You can even
       | navigate to dependency implementations. It's invaluable with
       | understanding really large code bases.
       | 
       | Excited to try this to see if it measures up.
        
       | lkrubner wrote:
       | Possibly off topic:
       | 
       | "Look up the source" in 2024 is a symptom of a wider problem.
       | Ruby was innovative in the 1990s but it is starting to fall
       | behind the times.
       | 
       | Those of us who are old enough to remember the euphoria that
       | greeted the release of Ruby on Rails in 2004 are mostly surprised
       | to see Ruby's current, limited market share. There was a moment
       | when it seemed like Ruby was going to sweep the whole world of
       | software. But that didn't happen. The mutability that made Ruby
       | so fun also makes it difficult to maintain Ruby codebases over
       | the long-term.
       | 
       | For awhile Ruby seemed relevant in fields beyond Web development,
       | such as devops. I recall 12 years ago a startup tried to recruit
       | me, they were going to revolutionize devops by building
       | automations for Chef. But the metaprogramming in Ruby made it
       | less than ideal for devops work. That startup failed. In most
       | places I now work, a combination of Ansible and Terraform
       | dominate, save where the company uses the constellation of tools
       | surrounding Kubernetes to manage everything. The places that use
       | Chef have been using Chef for 15 years, no new company chooses
       | Chef today.
       | 
       | There was a stretch after 2004 when Ruby was trying to break into
       | new areas. GTK bindings for Ruby were developed and some people
       | experimented with desktop Ruby. But that never took off.
       | 
       | Many of us who loved the metaprogramming in Ruby, but wanted a
       | better structure for that metaprogramming, moved on to other
       | languages such as Clojure.
       | 
       | Some of us loved Ruby because it allowed easier polymorphism than
       | Java did -- after all, you could use higher order functions to
       | produce functions, but without having all the ceremony of
       | building a Factory. But folks who just wanted the polymorphism of
       | functions returning functions eventually moved to NodeJS.
       | 
       | Ruby always felt fluid and magical in a way that made it seem
       | vaguely unsuitable for data science, and eventually Python came
       | to dominate data science.
       | 
       | The Ruby community witnessed the conflict between Rails and Merb,
       | and their eventual union, and eventually Rails became a
       | comfortable framework for quickly generating an API. But for
       | anything that needs high levels of write throughput, no one would
       | chose Ruby, and so other languages have taken some of the market
       | share.
       | 
       | Even on the Web, some big companies (Twitter, AirBnB) either gave
       | up on it completely, or now only use it for templating the
       | frontend, or offering an API to support the frontend. For backend
       | processing, many companies have moved away from it.
       | 
       | In short, Ruby has been losing market share for awhile. In some
       | fields, such as devops, where it used to be competitive, it has
       | almost completely disappeared. It survives only in Web
       | development, and only because of Rails.
       | 
       | None of this can be very inspiring for Ruby developers.
        
       ___________________________________________________________________
       (page generated 2024-07-27 23:12 UTC)