Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

practical tips for organizing routes? #5

Open
ericgj opened this issue Jul 26, 2012 · 2 comments
Open

practical tips for organizing routes? #5

ericgj opened this issue Jul 26, 2012 · 2 comments

Comments

@ericgj
Copy link
Member

ericgj commented Jul 26, 2012

The thing that seems a little daunting when I think about using Cuba is the complete flexibility of the router. And related to this, that the order of the routes becomes quite important. (The order is significant in Sinatra too of course, but there all the routes are on the same level, and they're only matching on the path). I feel like it would be very easy to get twisted up by the state machine logic, and then need to completely reorder the routes if I wasn't careful to plan them out from the start. But maybe it's just a matter of retraining my brain.

For instance, I found it a little hard to follow the logic of the cuba-app sample at first:

  on root do
    res.write view("home", title: "My Site Home")
  end

  on authenticated(User) do
    run Users
  end

  on "admin" do
    run Admins
  end

  on default do
    run Guests
  end

At first, it seemed to me like on "admin" should come before authenticated(User). Otherwise what happens when an authenticated user goes to "/admin/x" ? Shouldn't the "admin" route handler deal with this? What if an authenticated user is also an admin, and therefore should have access to "admin" routes?

Then I realized that unless there's a default route defined, the router doesn't stop when it can't find any matching routes on a branch - it just pops back up and goes to the next branch. Since the Users routes don't have a default route, even if a user is authenticated, it goes on to the next condition when no Users routes are matched. So the logic should be read something like (I think):

  1. First, handle the root path by displaying a home page.
  2. If the user isn't going to the root path, check to see if the user is authenticated. If so, check if they are going to a valid non-admin route, or trying to login as another user.
  3. If not going to the root path, not authenticated, and not going to one of the Users routes, check if they are going to an admin route. If so, check if they are trying to re-login as an admin ("/admin/login"), and handle that transaction; otherwise for any other admin path make sure they are already authenticated as an admin. If neither of these applies, then return a 401 Forbidden.
  4. Otherwise, if not going to the root path, not authenticated, or authenticated but not going to one of the Users routes, and not going to an admin route, then expose a number of routes available to non-authenticated users (Guests) such as login, signup, password recovery, password reset, etc.
  5. If none of the Guests routes match, Cuba -- reaching the end of the tree of routes -- returns a 404.

The thing is, you don't see the full logic really without going into each of the sub-route apps. Especially in the Users routes, I find it a bit confusing to not have a default route. But maybe it's the kind of thing you find what works for you and leave the basic structure alone. It does provide a clean separation of concerns.

second question

Let's say you have typical CRUD routes for some model belonging to individual users. The canoncal Posts. Would you put these routes within the Users sub-app (ie. accessible to authenticated Users) ? Or would you split out each controller into separate files, basically something like -

##### main app
on authenticated(User) do
  run Users
end

##### Users app
on "posts" do
  run Posts
end


##### Posts app
on get, root do
  # index
end

on get, "new" do
  # new
end

on post, root do
  # create
end

on ":id" do |id|

  on get, root do
    # show
  end

  on get, "edit" do
    # edit
  end

  on put, root do
    # update
  end

  on delete, root do
    # delete
  end

end
@adamakhtar
Copy link
Member

Ive been wondering about the importance of the order too. I cant remember my exact order but i did run into some problem.

Looking at your last sample code, shoudnt the the edit action come before the show action? If the request path was "post/5/edit" I think the show action will partially 'match' the incoming request path and get incorrectly called even though it was supposed to be edit. If you swap the order though things work as expected.

@ericgj
Copy link
Member Author

ericgj commented Jul 30, 2012

@RoboDisco, I think the route order is ok but would have to actually try it out. root matches '/' or empty string in path exactly rather than using a regexp-based matcher.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants