lotus/router — pull request #24 by janko-m (2014-10-31 23:46:10+00:00)
Title: Inconsistency of `#namespace` and `:prefix`

*Disclaimer: I haven't included any code yet, but I will after a discussion.*

\## Problem

I read the whole lotus-router's source code, and I noticed some inconsistencies (I'm not sure if they're all bugs) that arise from the way `#namespace` and `:prefix` are implemented. I listed all of the examples I found:

1. `:prefix` doesn't actually add prefix to paths generated with HTTP methods.

```rb
router = Lotus::Router.new do
get "/bar", to: ->(env) { [200, {}, ["Hello"]] }, prefix: "/foo", as: :bar
end
router.path(:bar) #=> "/bar"
```

2. The example above doesn't actually work, I need to use `Lotus::Utils::PathPrefix`.

```rb
prefix: Lotus::Utils::PathPrefix.new("/foo")
```

3. `:prefix` tries to namespace procs and classes.

```rb
router = Lotus::Router.new do
get "/bar", to: ->(env) { [200, {}, ["Hello"]] },
prefix: Lotus::Utils::PathPrefix.new("/foo"), as: :bar
end
router.path(:bar) #=> #
```

4. `#namespace` doesn't namespace controllers on routes generated with HTTP methods.

```rb
router = Lotus::Router.new do
namespace "foo" do
get "/bar", to: "home#index", as: :bar
end
end
router.instance_variable_get("@router").named_routes[:bar].dest
\#=> "#"
end
```

5. `#resource`'s member/collection actions don't respect the global `:prefix`.

```rb
router = Lotus::Router.new do
resource "cats", prefix: "memes" do
collection do
get "cuddly"
end
end
end
router.path(:cuddly_cats) #=> "/cats/cuddly", and should be "/memes/cats/cuddly"
```

6. Nested `#namespace`s don't generate the right prefix for `#resource`.

```rb
router = Lotus::Router.new do
namespace "foo" do
namespace "bar" do
resource "cats"
end
end
end
router.path(:foo_cats) #=> "/foo/cats", should be `:foo_bar_cats` that generates "/foo/bar/cats"
```

\## Discussion

I know that some of these bugs aren't really related to each other, but I want
to put them at one place as kind of a TODO list.

\## Solution

This is an idicator that the prefix/namespace code will have to get refactored
a bit. My suggestion would be to make `#prefix` and `#namespace`:

```rb
Lotus::Router.new do
\# *only* adds a prefix to the path
prefix "/foo" do
get "/bar", to: "home#index"
end

\# adds a prefix to the path + namespaces the controller
namespace "foo" do
get "/baz", to: "home#index"
end
end
```

And I would do it in a way that what these methods do is only pass the `:prefix`/`:namespace` parameter through. That is, the above would be equivalent to

```rb
Lotus::Router.new do
get "/bar", to: "home#index", prefix: "/foo"
get "/baz", to: "home#index", namespace: "foo"
end
```

And then I was thinking that `Lotus::Router` itself takes care of passing the
right parameters to `Lotus::Routing::HttpRouter`.

What are your thoughts of this? I would really like to take this, beacause I
finally want to make a real contribution to Lotus :)