ezekg 7 hours ago

I feel like this is a solution to a problem nobody really has in practice, by simply following conventions, and I've been using Ruby for over 10 years. If byroot -- who works at Shopify on the largest Rails codebase in existence -- echos the same sentiment, then maybe it should be scrapped.

  • Umofomia 4 hours ago

    I will share a concrete example where I've recently run into this problem.

    In order to make use of OpenStruct, `require 'ostruct'` first needs to be declared. Our code neglected to make that declaration, and we saw failures when it was deployed. This code, however, passed all of our tests. We discovered it was because our testing framework included rspec-expectations, which has a dependency on diff-lcs[1], and diff-lcs itself declares `require 'ostruct'`[2]. Because of this, ostruct was loaded globally before our code was tested, which silently masked the underlying issue.

    This being said, I do understand the sentiment that this feature seems superfluous and may introduce unnecessary complication, especially from a Rubyist's point of view. The underlying mental model of Ruby dependency management is different from many other languages, and it's something to keep in mind when coming from other languages that do have scope for declared dependencies.

    [1] https://github.com/rspec/rspec-expectations/blob/v3.13.3/rsp... [2] https://github.com/halostatue/diff-lcs/blob/v1.5.1/lib/diff/...

    • halostatue 4 hours ago

      `diff-lcs` no longer uses `ostruct` as of 1.6.0 (granted, that was released in February).

  • graypegg 7 hours ago

    I really like Ruby, I do sort of wish it could focus on it's own identity a bit.

    Some new features feel almost prescribed from other languages? Like, RBS and Namespaces specifically... they don't really fit the model of Ruby exactly, but they need to be there so Ruby can be presented as "having" type-safety and a-solution-for-monkey-patching. I'm all for taking inspiration from other places, but Ruby wasn't quite built around the same axioms that other programming languages started from.

    • rco8786 an hour ago

      Yea generally agree with this take. Feels like we’re getting features shoehorned in.

  • andruby 7 hours ago

    I would like to second (or _third_) this opinion.

    I've been working with Ruby for 20 years, and I've not needed something like this. This feels like adding a lot of complexity for little practical benefit. The trade-off feels off. I don't think this is worth the additional complexity.

    • usrbinenv 7 hours ago

      I disagree. I've also been working with Ruby for almost 20 years and quite a few times I came across a situation where I definitely wanted to wrap my library in a module for name-spacing and it was almost always cumbersome. I'd rather not wrap it and let others (or myself) use the library name-spaced under whatever name they choose. Right now, if you're working on a gem, you have to think really hard how to name it so its top-level classes an modules don't conflict with any other modules and classes found in the Ruby ecosystem.

      • ezekg 6 hours ago

        > Right now, if you're working on a gem, you have to think really hard how to name it so its top-level classes an modules don't conflict with any other modules and classes found in the Ruby ecosystem.

        Follow gem naming conventions and this is a non-issue -- both FooBar::Record and BazQux::Record can coexist for foo_bar and baz_qux gems, respectively. If a gem is defining other top-level constants outside of their gem module, then that's considered against convention, i.e. bad practice, and the language should not be modified to allow such a thing.

        I'd like to hear of a real use case for namespaces that existing conventions don't already solve.

        • usrbinenv 6 hours ago

          Wrapping `Record` in `Foobar` or `BazQux` is just not a good pattern, even if it's common place and is included in current guidelines. Most of the time, you don't have gems that would use the same class and thus would rather not type a long name-spaced name every time you want to use `Record`. But when you do have gems with conflicting classes, you'd have the power to wrap one of them or both in a short namespace identifier and be in charge of the naming. Using modules for wrapping is a pattern currently, but modules should primarily be used for mixins, not name-spacing.

          • vidarh an hour ago

            If you don't have a conflict, and the module is wrapping everything, nothing stops you from doing "include <yourmodule>".

            Similarly, if you want to group modules that don't conflict together under a short module name, nothing stops you from doing:

                module MyGroup
                  include Module1
                  include Module2
                  ...
                end
            
            In other words, wrapping them doesn't remove your ability to use short non-namespaced names.

            Using `include` of specific functionality into a class that will use it is furthermore an idiomatic way of avoiding that extra typing without polluting the global namespace

            For that matter, you can often achieve close to what you're arguing for as well without actually making any changes to Ruby:

               def wrap_load(path) = class_eval(File.read(path), path)
            
               module Test
                 # some_file.rb will act as-if defined within Test
                 wrap_load("./some_file.rb")
               end
            
            You can do better than that, to get closer to emulate `require` rather than `load`, and handle dependencies.

            Overall, I think the fact you can do these things suggests you could probably write a good enough plug-in `require` monkeypatch suitable for the rare cases where `include` from within a class or module without needing a language extension.

          • ezekg 6 hours ago

            What's the difference between FooBar::Record and ns1::Record? Nothing, except the latter pushes encapsulation onto the user.

            This is not the Ruby ethos.

            • usrbinenv 6 hours ago

              On a purely syntactic level snake_case gives me a clear indication this is something different (not a module). But the underlying mechanics of how namespaces would work, as I've mentioned in another comment, is that the choice of picking namespace identifiers is shifted to users of gems/libraries. I think the proposal might further benefit from maybe giving libraries default namespaces and, for example, Go does exactly this: you can import a package with the namespace prefix defined by package author, but you can also change it or import it without a namespace prefix at all.

    • fellowniusmonk 7 hours ago

      I think byroot got it exactly right with:

      >First, I'm not convinced by the motivations:

      >

      >Avoiding name conflicts between libraries: Applications can require two different libraries safely which use the same module name.

      >

      >Is this a problem that happens on a regular basis? I believe Ruby has a pretty well established convention for libraries to expose a single module with a name that correspond to their gem name.

      I really don't think we want to make it easier for newbies to alter gem naming conventions and run multiple versions of a gem within the same project, this sounds like a genuine nightmare to me. I've found from jumping in to fix broken and crippled rails projects for startups that the fuckup surface area is already high enough.

  • drogus 5 hours ago

    While I agree with the sentiment here, ie. that Ruby doesn't necessarily need namespaces, I think it's also not necessarily good to base Ruby usage on what Shopify is doing. They have so many expert Ruby devs, and whole teams that write extra tooling, that I'd argue they shouldn't be compared to pretty much most of the usage of Ruby/Rails out there

    • byroot 4 hours ago

      Shopify would benefit a ton from "some" namespaces. In a way, packwerk[0] was an attempt at bringing some namespaces benefits.

      But I don't personally think Shopify would benefit from this specific implementation of namespaces (a couple colleagues do). I'm personally not even sure Namespace is a proper term to describe that feature. It's more some sort of lightweight sandboxing to me.

      Also:

      > They have so many expert Ruby devs

      If anything, the average Ruby expertise at Shopify is likely noticeably lower than in most Ruby/Rails shop.

      [0] https://github.com/Shopify/packwerk

  • poorman an hour ago

    Try using the Pay gem and others that assume a global singleton for a multi-tenant app (as in multiple different websites under different domains with different Stripe API keys). Lots of gems assume this and their configuration is global.

    I personally would love to have this feature!

    • ezekg an hour ago

      Can you expound a bit more? It seems like Pay encapsulates itself pretty well. I'm not sure I really grok how namespaces could improve or fix whatever is broken here.

  • chao- 6 hours ago

    I shared my quick take in another comment tree, but I reread and understand the semantics a little better now, and I like it less, especially the notion that an instance of an object might transform when crossing Namespace boundaries. I get that it is similar to refinements in some ways, but this feels like it would be even more surprising, and I can foresee some gnarly bugs coming from this unless it is trivially easy to visualize the changes to an object between namespaces.

    I'm updating my opinion from "mixed feelings" to "against" on this.

  • hosh 7 hours ago

    I thought being able to do this with Nodejs was a near capability.

    Over the past two years, I have come to understand that this contributes to the nightmare that is the Nodejs ecosystem (and the browser JS exosystem in general), at least when it comes to writing reliable software.

  • 90s_dev an hour ago

    Why am I not surprised Shopify uses Rails.

  • hartator 7 hours ago

    Yeah, and I rather them focusing on performance instead of features. 2.7.8 is still the fastest and it’s getting old.

    • tiffanyh 7 hours ago

      You can see Ruby core perf improvements at the link below, going back 4-years.

      Even though this is from the YJIT folks, they include the non-jit improvements as a comparison.

      https://speed.yjit.org/history.html

    • chao- 6 hours ago

      Having upgraded one large and two small applications in the last few years, this is not my experience. Even without YJIT, just upgrading to Ruby 3.2 and beyond saw performance improvements over the same application on 2.7.

    • dalyons 7 hours ago

      Huh? How is 2.7 the fastest ? There have been tons and tons of major performance gains since then, even without getting into yjit

irjustin 7 hours ago

I wish ruby went with hard/explicit imports like python or js.

Solves this problem and "magic" that so many complain about while retaining all the other great things to love about Ruby.

  • PufPufPuf 4 minutes ago

    Most definitely. When I worked with existing Ruby codebases, it was surprisingly hard to answer the question "where is this defined" when every import is dumped into a single global namespace. I had no idea where stuff came from, and neither the IDE.

  • zoky an hour ago

    I mean, nothing is stopping you from doing something like:

      require 'foo'
      Bar = Foo::Bar
  • bm5k 7 hours ago

    Ew. No.

frou_dh 8 hours ago

I remember Matz gave a presentation touching on how Ruby was inspired by Lisp and particularly Emacs Lisp, which was the one he had access to. You still can feel a similarity up to now, with the single big old dynamic namespace where you can monkey-patch anything if you feel like it.

  • sctb 6 hours ago

    Even this proposed feature is very similar to Common Lisp packages.

usrbinenv 6 hours ago

To add to my other comments ITT, I was thinking how the proposed name-spacing in Ruby would work is, in one way, diametrically different from Go where you'd normally import a package with the name that was chosen by the package author. But, at the same time, you could choose to import it under a different name or with no namespace at all, using the dot prefix. I'm not sure which is better. I suppose I could agree Go has a better default when it comes to namespaces.

  • vidarh an hour ago

    It's not straightforward to prevent the original name from existing, though you can play games with File.read() and class_eval, but if you just want it to be available under a different name, and don't mind that the old one is there too, you can just do:

        require 'foo'
    
        module MyPreferredNamespace
          include Foo
        end
semiquaver 8 hours ago

This is a really interesting feature addressing something Ruby has long-lacked.

But I think the more interesting story is the widespread opposition to the way this was forced through in spite of major conceptual problems, bugs and performance regressions.

  • monooso 8 hours ago

    Identifying it as an experimental feature (disabled by default) seems like a reasonable way to make progress and iron out any problems.

Alifatisk 8 hours ago

First the Data class and now this, very interesting to see! Is there any certain use case where this is well suitable? Because we already have Modules and from my understanding, can be used to namespace things. Or is the appeal here that you can perform the namespacing dynamically through ”require”?

  • choward 6 hours ago

    Ruby doesn't have real modules. You're right, that they are just namespaces. They are global variables with extra typing.

    If you use a third party library, when you require something, you have no idea what "modules" or other values it creates polluting the global namespace. This at least assigns those values to a local variable where they can be accessed and doesn't make them global.

    That said, I'm not a fan of ruby and all the workarounds to try to make it like a more sane language that it isn't.

  • vinceguidry 8 hours ago

    It allows you to namespace things that aren't themselves namespaced. That way you can just require things that, might say, have the same module names as your own code without worry. I'm curious if this namespace mechanism could, say, isolate monkey patches. Probably not, but it would be nifty.

    • chao- 8 hours ago

      >I'm curious if this namespace mechanism could, say, isolate monkey patches.

      Wasn't that the purpose of refinements? Perhaps I am misremembering, because I never had a need to reach for refinements myself.

      • vinceguidry 7 hours ago

        You still need to rely on the library maintainers to use them. This mechanism allows you to sandbox a library that doesn't.

  • usrbinenv 7 hours ago

    Using Ruby modules to namespace things is certainly possible, but is very often cumbersome. Modules also "hardcode" a namespace: that is, if I use modules for name-spacing, it will always be "MyModule::MyClass" everywhere -- or, in other words, namespacing is controlled by library author, not user. The proposed feature shifts that control to library user.

    • vidarh 40 minutes ago

      > if I use modules for name-spacing, it will always be "MyModule::MyClass" everywhere

      It will be identified as such by e.g. the default `inspect`, but nothing stops you from `include`-ing MyModule into another module or class, or even the global scope so that you can reference MyClass without MyModule.

gitroom 5 hours ago

Honestly after 15 years in ruby, changes like this always make me wonder who they're for. Saw way more value in the old-school simplicity - you ever feel like new language features just pile on more headaches than they fix?

baggy_trough 8 hours ago

I've been happy with some of the great improvements to Ruby in the past year. But this one really leaves me scratching my head. It seems like a lot of complexity for what I perceive as a negative value feature. I'm concerned about damage to the gem ecosystem by encouraging gems to bundle version locked dependencies. The last thing I want is a gem deciding to have multiple versions of other gems in my app.

  • chao- 8 hours ago

    I agree and I am overall mixed on this.

    One of the tradeoffs that (imo) has been net positive in the Ruby ecosystem, is how a project has to ultimately load and run a single set of versions of all dependencies. It creates some extra maintenance work on one hand, but the result is that it encourages the ecosystem to not have to face the hell of having 3 or 5 or 10 versions of each common dependency within a project.

    I recognize that this is an occasional cost to library maintainers, but in the long-term has contributed to benefits. My perception is that Ruby libraries have smaller list of dependencies than similar libraries in some other languages. There are several reasons for this, but this ecosystem pressure to stay compatible with a range of dependency versions is one of them.

    It feels to me like this leads to a sweet spot for small- and medium-sized projects, and I can see it might have an upper limit? I have not been in the situation, but heard of situations where the largest projects inevitably run into needing specific versions of two separate libraries that don't agree on a version of a common dependency.

JohnBooty 8 hours ago

In the micro, this is definitely a useful crutch for using badly-written/badly-behaved code.

(In the example, it usefully provides a way to maintain sanity when `app1.rb` and `app2.rb` both define a global constant named `PORT`)

However, I'm not sure how much existing code is defining stuff in such a poorly considered way. (I don't mean that rhetorically. Maybe it's more pervasive than I think)

Furthermore, would adding this feature to the language actually encourage such bad behavior? (Would it even be "bad" behavior at that point?)

So I'm kind of leaning toward "I can see how this would be useful, but I don't want the language to condone such a bad practice."

  • tinco 7 hours ago

    I can rest your mind, I've being coding Ruby for 17 years now, and I've never seen two gems or even files define the same global constant in a way that wasn't intentional. It's fair to say it's not at all pervasive.

    That said, I do think there's use to this. First of all it would allow fancy platforms like RoR to make more effective use of namespaces. Right now you always need to specify the fully qualified name of a constant whenever you're defining it, which is just not aesthetically pleasing.

    Another potentially useful place for this is in migrations. If you could just move the old implementation of a thing into a subdirectory and then load it into a namespace you make references to it a lot more explicit, and you give the replacement architecture full freedom within its root namespace.

    Just to say, it's not only bad behavior that would be enabled by this feature. I definitely agree that having gems not sticking to their own modules would be a very bad thing indeed.

  • hartator 7 hours ago

    Yeah, and it kind of defeat passing PORT as a global variable. Like you might expect PORT=2917 to do effect these apps ports.

    • JohnBooty 5 hours ago

      I'd call that some pretty bad behavior; behavior that I'd like to... if not dissuade, at least not encourage.

dudeinjapan 4 hours ago

I'm against this because it will be abused, and cause chaos vis-a-vis well-established conventions in the Ruby world.

The example given in the ticket, defining a global constant PORT in the root namespace and then loading it separately into two apps--nobody actually does in Ruby this today, because it is well-known that it will cause conflicts. Any gem (Ruby library) that did this sort of thing has long-since been barked at and corrected--the solution is simply to nest the constant inside your main module e.g. MyGem::PORT.

Now, gems will be free to define whatever constants/modules/etc. they want. When someone files an issue, the response can be: "Oh you don't like that I redefined Array? Load my gem in a namespace!"

zwnow 8 hours ago

I know Ruby is still used in some codebases but what's its actual relevance in the webdev/fullstack landscape? I am currently 5 months into learning Elixir/Phoenix for fullstack and I already know a few Js based frameworks. Ruby always intruiged me, but I'd like to stay employable

  • afavour 8 hours ago

    I'd say Ruby is more relevant than Elixir. But you're correct (IMO) that Ruby had a big moment but has died down since. At one point it almost felt like the default choice in startup land. Not so today.

    Ruby on Rails specifically has a batteries included approach that lets you get up and running very quickly. But my perception is that as JavaScript has leaked into the server (benefits of writing the same language on front and back end) it's eaten into Ruby's mindshare. Python also finally moved on from its 2 vs 3 nightmare and shares many of the benefits of Ruby.

    • zwnow 8 hours ago

      Yea, I am tackling Elixir to avoid learning tech specifically designed for solving scaling issues with languages not made for scaling. Elixir is wonderful for this. How's Ruby considering scaling and performance? I always compare Ruby on Rails to Laravel for some reason

      • freedomben 8 hours ago

        I did Ruby on rails professionally for many years, and have also done elix Phoenix professionally for many years now, and I would advise you to continue with Phoenix. Getting really good at elixir and Phoenix can make you an extremely powerful and employable developer. Should you find yourself in a situation where you need to switch to Ruby and rails, you will have a huge leg up because rails follow as many of the same patterns as Phoenix, and the Ruby language is very simple to learn for someone coming from elixir. Just my two cents of course

        • zwnow 7 hours ago

          Will follow this advice then, thanks for letting me know!

      • afavour 8 hours ago

        You typically choose Ruby on Rails because you want to get up and running fast, not because you want performance. That said, in most RoR codebases the performance bottleneck is networking, database etc not the language itself. As and when e.g. the database becomes a bottleneck there are various mitigations available to you.

        • ljm 6 hours ago

          In a way, Rails is the OG for rapid application development considering its influence and impact on tech startups over the 2010s.

          These days you'd build a blog in 20 minutes by vibe coding it in Cursor and deploying it on to some serverless edge compute platform or something.

          Almost 20 years ago you'd build a blog in 20 minutes by installing rails and running a few commands on the terminal to generate the UI, backend, DB schema/migrations and all that, and then `git push heroku master` to see it deployed on the web. Quickly enough you'd git gud and wouldn't need to lean on the scaffolding tools.

          At least in London there's still a pretty strong market for it, and the overlap in syntax between Ruby and Elixir is enough that you could take your pick (the Elixir shops I know of will look for experienced Ruby engineers by default because the pool of Elixir engineers is much smaller).

      • ezekg 7 hours ago

        Shopify, GitHub, Intercom, among others are built on Ruby/Rails. I think it'll scale fine.

      • pmontra 6 hours ago

        You scale Rails by adding servers (or containers) behind a load balancer and by scaling up the database server in the same ways you would do it for another server technology, including Phoenix.

        By the way, I've seen many more Rails projects than Phoenix ones but they share the same general architecture: (server or containers) + db. The only difference is that we usually run Ruby jobs inside sidekiq and we use Tasks or GenServers for Elixir jobs. We wrote our own code to restart and try again jobs that eventually failed (we can't lose a job because of a deploy or a reboot.)

        • zwnow 2 hours ago

          Well most Javascript based apps ive seen utilize stuff like Redis for scaling, this for example isn't needed with Elixir.

      • dismalaf 7 hours ago

        > How's Ruby considering scaling and performance?

        Shopify, Github, AiBnB, Square, Instacart, etc...

        There's more big apps/websites using Rails than Elixir or Phoenix...

        • zwnow 7 hours ago

          > There's more big apps/websites using Rails than Elixir or Phoenix...

          Sure, but thats a weak argument considering Ruby on Rails is considerably older than Phoenix and adoption is in decline while Phoenix grows.

          • aeonflux 3 hours ago

            Could you point out where do you get your data from? Anything to back-up your claims that Rails is in decline and Elixir/Phoenix is growing? For a time not long ago I was heavily into looking for an Elixir gig, but couldn't really find offers, while there were still tons of offers for Rails development.

          • dismalaf 5 hours ago

            It's proof that it works. The things exist.

  • skyfantom 6 hours ago

    As much as I enjoy using Elixir, I’m not sure at the moment learning Elixir over Ruby gives more options for being hired.

    Open any “Who is hiring” and compare number of Elixir positions vs Ruby.

  • graypegg 7 hours ago

    Use whatever you feel most effective in. I would say Ruby is around much more than you might expect by the sounds of it. (The usual big names touted on the Rails homepage + many start ups + agency products) though it's definitely over the hype period.

    For being employable... I'd say Ruby is going to be near the middle of the pack. Elixir is going to be near the harder-side, and JS is going to be near the easier-side... on average IMO.

    If you think ruby intrigues you, give it a try! You've got precious time + motivation for this sort of thing, but messing around with a programming language is not much effort if you're intrigued. Getting a feel for it is a sub-weekend project away. It's my favourite language for bodging, the scripts I make in ruby for little data-mashing or system things are surprisingly stable and readable, even a year or two later. (Compared to a nodejs, perl or shell script... which all tend to have understandability-half-lives of a month for me haha) Automate something you find annoying.

    • zwnow 3 hours ago

      We actually use Prawn PDF at work so I have soooome degree of contact to Ruby already, I might check it out at some point. Thanks for the detailed answer!

  • dudeinjapan 4 hours ago

    Learning a new language makes you more employable, not less :)

    • zwnow 3 hours ago

      Oh I already consider myself a Polyglot, I just need tools that make building fun. I try to leave Js frameworks in my private projects

Joker_vD 6 hours ago

As someone who can't stand Ruby, I am personally against this feature. I'd rather have my Ruby experience universally miserable, with no deception, instead of having, say, half of the language decent and sane, and another half, well, be traditional Ruby.

Edit: apparently, people who do love Ruby are also against this feature, for roughly the same reasons. Kinda funny, but entirely reasonable in hindsight.