Comments (13)
@jodosha this seems like it should be an issue on https://github.com/lotus/router instead?
from hanami.
@lengarvey Lotus::Router is agnostic about Lotus applications and I'd like to keep it as it is. Probably it would require some new mechanism in Lotus::Router as base for this feature.
from hanami.
I'm giving attention for this @jodosha. Maybe on Monday I send some code draft.
from hanami.
@lucasas 👍
from hanami.
@jodosha where the application is creating this anonymous router? And where double routing dispatch is being made? Thanks dude
from hanami.
@lucasas The "anonymous router" is something like this:
# config.ru
# this router instance is anonymous
run Lotus::Router.new {
mount Backend::Application, at: '/backend'
mount Frontend::Application, at: '/'
}
It's the only way that we have now for dispatch HTTP requests for multiple applications.
The full explanation is in the README.
from hanami.
Hey @jodosha, I've implemented a draft to accomplish flatten routes, registering a lot of applications.
Some changes were made on lotus-router
to contemplate this. Now, Lotus::Router
can receive an option named mount_at
, which will be used to define a namespace for the defined routes. More details can be found here: lucasas/router@45ebf37#diff-7874fa6a25a9c35022a569e25b04bfa4
But basically, now you can do the follow:
Lotus::Routes.new(mount_at: 'backend') do
get '/flowers', to: 'flowers#index'
end
This is completelly equal with the code below:
Lotus::Routes.new do
namespace 'backend' do
get '/flowers', to: 'flowers#index'
end
end
Another change on Lotus::Router
is that it now has an each
method. This is useful to list (and copy) all routes defined into a Lotus::Router
instance. So that you can iterate over these routes:
@router.each do |route|
puts route # => it will print #to_str from Lotus::Routing::Route
end
Lotus
itself, suffered some changes too.
Lotus::Configuration
allows the user specify a mount point to the given Lotus::Application
, this information is passed to Lotus::Router
instance. More details here: lucasas@2b18990
module Backend
class Application < Lotus::Application
configure do
root File.dirname(__FILE__)
load_paths << [
'controllers',
'views'
]
layout :backend
# defining mount point of this application
mount_at 'backend'
routes do
get '/login', to: 'sessions#new', as: :login
end
end
end
end
The most important change ocurred here: lucasas@2b18990
The new class called Lotus::Routing::Builder
is where the magic happens. There, Lotus
copies all routes defined into each application storing it in a single Lotus::Router
instance, the call
method is redefined, and now is responsible to deal with all requests coming. It can be used like in the code below:
run Lotus::Routing::Builder.new {
mount Backend::Application
mount Frontend::Application
}
As each application defines its own mount_at
point, it's not needed to pass at
option when calling the method mount
. But I'm not sure about this interface. Maybe, instead of call mount_at
method inside configure
, we can pass at
option in the code above.
Next steps:
- raise an error when two applications have the same mount point (aka
mount_at
) - improve documentation of all classes
- create some integration tests to validate all those changes
I'm really want to know your opinion, realize if we are in the same page.
Thanks.
from hanami.
Hey @jodosha. Thoughts here?
from hanami.
There is a little bug here to be resolved (thanks @arthurgeek)
As my Lotus::Routing::Builder#call
method is not calling @rendering_policy.render(response)
, Lotus::View
is not working with my solution.
I've copied all routes from all applications to a single router, this router just call the recognized destination without pass through Lotus::Application#call
which calls @rendering_policy.render(response)
.
I'm visualizing all possibilities before go ahead. If you guys, specially @jodosha, have some idea to help me, would be great.
One of them is: I could instantiate a new Lotus::RenderingPolicy
, use it inside Lotus::Routing::Builder
, but it depends on Lotus::Configuration
which is unique for each application, so I think this is not a reasonable idea, since each application has its own configurations.
from hanami.
@lucasas Yes, I know, what you mean. Sorry for not making clear that this was the challenge of this feature, and instead you had to figure out it by yourself. I opened this ticket to brainstorm with you guys.
As we haven't already defined a stable architecture, my proposal is to hold on this, as it feels like premature optimization. We don't want to bend the framework too early.
from hanami.
Yes, this is really a challenge. I spent today 6 hours trying to figure out how to solve this, and I was intending to work on it in the next days.
As you said, I might give up to do it for a while. But I think that step 1 (Pass to the single applications the :at prefix, so they are aware of the prefix configuration) should be done right now.
What is your opinion?
from hanami.
As I talked with @jodosha, for while, I'll keep focus on the first feature (Pass to the single applications the :at prefix, so they are aware of the prefix configuration).
Actually, this is done, I'm gonna extract it, create some documentation and tests, before open a PR.
from hanami.
Hey @jodosha, in my solution, the first step is coupled to second one, in a way that one doesn't work without the other.
I want to explain what I've done to resolve just the first step.
I've changed Lotus::Loader
to respect a given router_namespace
defined into Lotus::Application
:
module Backend
class Application < Lotus::Application
configure do
router_namespace 'backend'
routes do
get '/login', to: 'sessions#new', as: :login
end
end
end
end
module Frontend
class Application < Lotus::Application
configure do
router_namespace 'frontend'
routes do
get '/login', to: 'sessions#new', as: :login
end
end
end
end
Into Lotus::Loader#load_rack!
I've done:
application.routes = Lotus::Router.new(
resolver: resolver,
default_app: default_app,
scheme: configuration.scheme,
host: configuration.host,
port: configuration.port
)
application.routes.namespace(configuration.router_namespace, &configuration.routes)
It's simple, all routes are defined respecting a router_namespace
. Doing that, when Backend::Router.path(:login)
is called, /backend/login
is returned, step one accomplished.
In my config.ru
file, I'm using an instance of Lotus::Routing::Builder
:
module Lotus
module Routing
class Builder
def initialize(&blk)
@router = Lotus::Router.new
instance_eval &blk
end
def mount(app)
@app = app.new
@router.mount @app, at: "/"
end
def call(env)
@router.call(env)
end
end
end
end
# config.ru
run Lotus::Routing::Builder.new {
mount Frontend::Application
mount Backend::Application
}
As you can see, all application are mounted at the same point ("/"
), what's (clearly) a problem, because http_router
will recognize request coming to the first registered application. In other words, my solution does not work.
I'm still trying to figure out which approach can solve this problem, I mean, which alternative I have to do achieve first step solution.
from hanami.
Related Issues (20)
- Could not find gem 'hanami-router (~> 2.1.0.rc)' HOT 12
- 2.1 RC1 - bundler: command not found: hanami on Heroku deploy HOT 22
- lib/tasks/ not installed
- "no implicit conversion of Symbol into String" error when using `format :json` on fresh install of Hanami 2.1 HOT 1
- Custom body parser issue
- [Documentation] FAQ + small snippets collection HOT 1
- Hanami versus Rails (long term objective: see the reddit discussion and entry, in the body of this issue request HOT 3
- Raise helpful error from db provider if the necessary database driver gem is missing
- Add db:migrate rake task
- Expand configurability of db provider HOT 1
- Register ROM commands and mappers from db/ directory
- Share DB connections between per-slice ROM containers using the same database URL
- Per-slice independent ROM setups
- Multiple slices sharing app-level ROM setup
- Automatically adjust database URL in test mode HOT 3
- Custom MIME types are not working HOT 7
- Add `Slice.source_dir` method
- Add `Slice.app?` method
- Set ROM inflector be the same as the Hanami app inflector HOT 2
- Slice ROM setup with slice-specific database
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from hanami.