Rendered at 15:06:39 GMT+0000 (Coordinated Universal Time) with Cloudflare Workers.
Fire-Dragon-DoL 10 hours ago [-]
Isn't the whole routing to file idea what PHP was doing (with Apache) for a very long time?
onli 8 hours ago [-]
Sure, though even in a classic project I'm maintaining the index.php is used as entry point for a lot of suburls, which the routing hidden behind that. URL-Rewriting than hides the index.php from the URL, so that's intransparent to the user.
I think the url->file matching is a good idea.
chao- 21 hours ago [-]
Always cool to see a fresh approach to organizing Ruby projects!
Like the author, I have experimented with app structures that better suit my project needs than Rails' conventions (having spent more than half my career partially-or-mostly using Ruby, and most of that using Rails). Sometimes that meant building within Rails and bending it to my desires. Sometimes that meant a blank-slate project layout of my own with some glue bits to talk to Rack. Most of the time the juice was not worth the squeeze, but hope springs eternal.
The one-to-one URL-path-to-folder idea feels neat. I think it would be neat for smaller and/or strictly-API-based projects, but I'm not sure I would prefer it as a strict requirement for large projects. It definitely got my noggin joggin'!
Eschewing one-psuedo-namespace-constant-per-file as a unit of encapsulation and orchestrating your own import and export also got me thinking, but more skeptically. Working in languages that embrace a free-form import/export, I have found that I prefer the one-encapsulated-unit-per-file style. I am going to dig into the Syntropy implementation and see if it inspires me to feel differently about this.
Additionally:
>A further disadvantage is that since everything is global, you might risk touching or referencing classes you shouldn’t, and since dependencies are implicit, those “references by error” may go unnoticed and cause some unexpected (read: undefined) behaviour.
I suspect the author knows this, but it is not the full story to say that "everything is global". Constants are global in that the Ruby VM's has only one hierarchy that for constant lookup. And because Ruby doesn't have namespaces (yet; we'll see what comes of Box), people reuse the constant hierarchy to approximate a namespace.
Local variables and instance variables in your "main" object scope are not global, either. Not only are the isolated from other object instances, the variables of the "main" object are not accessible from the class/singleton scope when declaring a class or module!
And none of these were decisions made by Rails.
>This approach automates the loading of dependencies, using the directory structure as a representation of the app’s namespace (i.e. classes and modules).
If only this were true! The file at app/models/user.rb is not required to declare the constant App::Models::User or even Models::User. One of Rails' three original sins is the layout conventions of the app/ folder, and the conventions built on that.
Yes, technically almost all of it can be configured with some difficulty. My experiments with alternative project layouts using Rails have had mixed success. When you place models and associated core behavior `domain/core/` instead of `app/models`, it's a coin-flip as to whether another developer sees that and says "Oh neat!" or is annoyed. Or when you place pairs of Ruby "view models" and ERB "view templates" in the same directory (e.g. `views/posts/show.rb` alongside `views/posts/show.html.erb`) it throws some people off, even though to me it feels obviously and unquestionably more organized.
chao- 14 hours ago [-]
Played with this a while, and the metaprogramming supporting this is fun :) Once again proving that you can dream up a wild idea, and Ruby will support you in achieving your dreams.
Looking at Syntropy::ModuleLoader, "modules" get to pretend they are in some main-like flat scope, but actually are executing in the instance scope of a Syntropy::ModuleContext. A consequence of this is that it is difficult to imagine these modules (and their exports) interoperating with plain Ruby code that doesn't have access to the `#import` (or needs to eschew it for some reason).
This seems fine in the context of a "closed loop" framework: expect to only ever consume a Syntropy module's `#export` in another Syntropy module, and only using Syntropy's `#import`. That seems like the happy path, but it is a tradeoff: you really need to buy into this "module" system all the way.
There might be an escape hatch, if plain Ruby code (i.e. not another Syntropy module) has access to the instance of ModuleLoader. With that, you can grab an export value via `#load`, which seems fine as long as the thing you need to `#load` isn't a module or class.
Specific to exporting a module or class, it feels natural for me to want to assign it to a capitalized constant when importing. I expected this not to work, as Ruby will reject instance scope `SomeModule = 'some_value'` if I write it as source code (SyntaxError, dynamic constant assignment). However, when I `#instance_eval("SomeModule = 'some_value'")` it as a string (as Syntropy::ModuleContext does), Ruby accepts it? I'm surprised!
The downside is that these end up as some kind of shadow constants, relative to each instance of Syntropy::ModuleContext? That is, they can only ever be accessed by name inside of a string passed to `#instance_eval`. I need to think longer about what the implications are. It's certainly interesting.
I think the url->file matching is a good idea.
Like the author, I have experimented with app structures that better suit my project needs than Rails' conventions (having spent more than half my career partially-or-mostly using Ruby, and most of that using Rails). Sometimes that meant building within Rails and bending it to my desires. Sometimes that meant a blank-slate project layout of my own with some glue bits to talk to Rack. Most of the time the juice was not worth the squeeze, but hope springs eternal.
The one-to-one URL-path-to-folder idea feels neat. I think it would be neat for smaller and/or strictly-API-based projects, but I'm not sure I would prefer it as a strict requirement for large projects. It definitely got my noggin joggin'!
Eschewing one-psuedo-namespace-constant-per-file as a unit of encapsulation and orchestrating your own import and export also got me thinking, but more skeptically. Working in languages that embrace a free-form import/export, I have found that I prefer the one-encapsulated-unit-per-file style. I am going to dig into the Syntropy implementation and see if it inspires me to feel differently about this.
Additionally:
>A further disadvantage is that since everything is global, you might risk touching or referencing classes you shouldn’t, and since dependencies are implicit, those “references by error” may go unnoticed and cause some unexpected (read: undefined) behaviour.
I suspect the author knows this, but it is not the full story to say that "everything is global". Constants are global in that the Ruby VM's has only one hierarchy that for constant lookup. And because Ruby doesn't have namespaces (yet; we'll see what comes of Box), people reuse the constant hierarchy to approximate a namespace.
Local variables and instance variables in your "main" object scope are not global, either. Not only are the isolated from other object instances, the variables of the "main" object are not accessible from the class/singleton scope when declaring a class or module!
And none of these were decisions made by Rails.
>This approach automates the loading of dependencies, using the directory structure as a representation of the app’s namespace (i.e. classes and modules).
If only this were true! The file at app/models/user.rb is not required to declare the constant App::Models::User or even Models::User. One of Rails' three original sins is the layout conventions of the app/ folder, and the conventions built on that.
Yes, technically almost all of it can be configured with some difficulty. My experiments with alternative project layouts using Rails have had mixed success. When you place models and associated core behavior `domain/core/` instead of `app/models`, it's a coin-flip as to whether another developer sees that and says "Oh neat!" or is annoyed. Or when you place pairs of Ruby "view models" and ERB "view templates" in the same directory (e.g. `views/posts/show.rb` alongside `views/posts/show.html.erb`) it throws some people off, even though to me it feels obviously and unquestionably more organized.
Looking at Syntropy::ModuleLoader, "modules" get to pretend they are in some main-like flat scope, but actually are executing in the instance scope of a Syntropy::ModuleContext. A consequence of this is that it is difficult to imagine these modules (and their exports) interoperating with plain Ruby code that doesn't have access to the `#import` (or needs to eschew it for some reason).
This seems fine in the context of a "closed loop" framework: expect to only ever consume a Syntropy module's `#export` in another Syntropy module, and only using Syntropy's `#import`. That seems like the happy path, but it is a tradeoff: you really need to buy into this "module" system all the way.
There might be an escape hatch, if plain Ruby code (i.e. not another Syntropy module) has access to the instance of ModuleLoader. With that, you can grab an export value via `#load`, which seems fine as long as the thing you need to `#load` isn't a module or class.
Specific to exporting a module or class, it feels natural for me to want to assign it to a capitalized constant when importing. I expected this not to work, as Ruby will reject instance scope `SomeModule = 'some_value'` if I write it as source code (SyntaxError, dynamic constant assignment). However, when I `#instance_eval("SomeModule = 'some_value'")` it as a string (as Syntropy::ModuleContext does), Ruby accepts it? I'm surprised!
The downside is that these end up as some kind of shadow constants, relative to each instance of Syntropy::ModuleContext? That is, they can only ever be accessed by name inside of a string passed to `#instance_eval`. I need to think longer about what the implications are. It's certainly interesting.