Rails Engine can share Routes, but not Routing Concerns - ruby-on-rails

I'm trying to share routing concerns of my engine with the host application.
What I'd like to achieve is the following:
# MyGem/config/routes.rb
Rails.application.routes.draw do
concern :commentable do
resources :comments
end
end
# HostApp/config/routes.rb
Rails.application.routes.draw do
resources :posts, concerns: :commentable
end
Which results in No concern named commentable was found!.
I've tested just using the resource without the concern, and I can tell that the host is inheriting my routes, just not concerns.
This could be a load order issue, if the engine routes are loaded last. Which would explain why I could still see the resources comments.
The only thing I can think of is a building a method similar to devise_for :model.
Something along the lines of mygem_concerns, I suppose.
If anyone has any other suggestions I would truly appreciate the help.

Related

Rails 4: Nesting resource, change URI but not controller

I am trying to place my tasks into my dashboard/admin routes, for example rather than todos/, todos/new, etc. I would like dashboard/todos/, dashboard/todos/new etc. etc.
I have tried to do that here like so;
namespace :dashboard do
resources :todos
end
Though this also changes the controller, which I don't want - I only want to nest the todos inside of the dashboard controller
Can anyone point me in the right direction please?
You can use scope or path as described in the Rails Guides
scope '/dashboard' do
resources :todos
end
or
resources :todos, path: '/dashboard/todos'
This will generate the routes with the path /dashboard/todos which maps to todos_controller
If you want to route /admin/todos to TodosController you can use scopeinstead of namespace:
scope '/admin' do
resources :todos
end
You could check the rails documentations about this point : http://guides.rubyonrails.org/routing.html#controller-namespaces-and-routing

Shortening Rails Routes

How might I be able to shorten these extremely lengthy routes in my rails application?
# routes.rb
resources :courses do
resources :sections do
resources :lessons do
resources :sub_lessons
end
end
end
I recommend to follow the rails oficial guides. It is considered a good practice to avoid nesting resources more than 1 level deep. That said, if you really need this level of nesting you can use the shallow option. this way at least your routes will be cleaner. As noted in the documentation cited above:
One way to avoid deep nesting (as recommended above) is to generate the collection actions scoped under the parent, so as to get a sense of the hierarchy, but to not nest the member actions. In other words, to only build routes with the minimal amount of information to uniquely identify the resource
You could try something like this:
resources :courses, shallow: true do
resources :sections, shallow: true do
resources :lessons, shallow: true do
resources :sub_lessons
end
end
end
Just play around with this a little and use rake routes to see how your routes are looking like.
However, what you should ask yourself is, for example do I need to have lessons routed under sections? May be its better to split them, something like:
resources :courses do
resources :sections
end
resources :lessons do
resources :sub_lessons
end
It all depends on the scope you need in what action, for example if at certain action you need to limit lessons based on courses but not in sections, then you will only need the course id passed as a parameter.

Resource in and outside namespace

I have the following routes.rb:
resources :users
namespace :vmt do
resources :dashboards do
resources :users
resources :evaluation_units
resources :orga_units
end
end
I want to set the user in an overall context and nested in a single dashboard context within a namespace. The users-Controller is not in the namespace. So when I open the path /vmt/dashboards/1/users in browser, I get the following Routing Error
uninitialized constant Vmt::UsersController
So how can I specify, that in this resource
namespace :vmt do
resources :dashboards do
resources :users
that the controller is not in a namespace? I tried to set the controller explecitly with
resources :users, controller: 'user'
but it's still in the vmt namespace.
Using scopes will point rails to the proper url, but does not seem to provide the same useful route url helpers. We can, however, use / to point to the 'top level' controller.
Say you have two routes we want to display the users on:
/users and /admin/users
resources: users
namespace :admin do
resources :users, controller: '/users' # 'users' alone would look for a '/admin/users_controller'
end
With this, we can continue to use the url helper admin_users_path
(Note: Not a rails expert, there may be a way to create url helpers for scopes, or some other solution. Above tested on rails 5.2)
My original answer didn't work in the end, once you're inside a namespaced scope within a route you can't get out anymore.
The easiest way to re-use your logic is to create a Vmt::UsersController like so:
class Vmt::UsersController < ::UsersController
end
You can specify a different module with the module key.
For example:
resources :users, module: nil
Edit: I'm not 100% sure if this will work inside a namespace. If not, you can change it to a scope, and add the module explicitly to the other resources.

Rails "/blog" path uninitialized constant Blog

I am trying to setup a rails blog at the "website.com/blog" url
I already have my models and controller setup to work to where going to
website.com/posts
Gives me all my posts and going to
website.com/posts/1/
Shows me that post, etc, etc. What I want to happen is that when I go to
website.com/blog/
I should see the posts index (and the original URL should no longer work). Similarly I want to go to
website.com/blog/posts/1/
To see that post and so on and so forth.
Right now this is my routes file:
Rails.application.routes.draw do
namespace :blog do
resources :posts do
resources :comments
end
end
get "/blog", to: "posts#index"
end
When I go to "/blog/" I get a Routing Error saying "uninitialized constant Blog". Do I need to create a blog model and controller and migrate to complete this? I'd rather not since it's really just running the posts requests from that new URL. Am I going about this the wrong way?
I ended up finding the answer to my own question here: http://guides.rubyonrails.org/routing.html#controller-namespaces-and-routing
Using this seems to work just fine:
scope '/blog' do
resources :posts do
resources :comments
end
end
get "/blog", to: "posts#index"
The answer ended up being found here: http://guides.rubyonrails.org/routing.html#controller-namespaces-and-routing
As usual the solution was incredibly simple and made me feel like an idiot for not knowing what to do immediately:
scope '/blog' do
resources :posts do
resources :comments
end
end
get "/blog", to: "posts#index"

How to route multiple levels of nested resources in Rails 3?

I know I can specify nested resources on routes.rb in Rails 3 this way:
resources :users do
resources :posts
end
However, I would like to add comments to posts. What should I write in my routes.rb file? Is this the correct way? Can I keep nesting them?
resources :users do
resources :posts do
resources :comments
end
end
You can keep nesting the way you have shown and things will work fine. There are quite a few sources that will tell you not to go crazy nesting routes though. Take a look at Rails Best Practices for example (I think the article was created for rails 2 but the principals still apply). Jamis Buck also blogged about this a while ago.
Yes, you can keep nesting and nesting and nesting and so forth.
Yes. What you wrote is the correct way.
I've been interested in this same problem and I think you're suppose to do:
resources :users do
resources :posts
end
resources :posts do
resources :comments
end
Check out the API on Resources.

Resources