ruby-on-railsrubyruby-on-rails-3routesnamed-routing

How to generate the proper `url_for` a nested resource?


I am using Ruby on Rails 3.2.2 and I would like to generate a proper url_for URL for a nested resource. That is, I have:

# config/routes.rb
resources :articles do
  resources :user_associations
end

# app/models/article.rb
class Article < ActiveRecord::Base
  ...
end

# app/models/articles/user_association.rb
class Articles::UserAssociation < ActiveRecord::Base
  ...
end

Note: generated named routes are like article_user_associations, article_user_association, edit_article_user_association, ...

When in my view I use:

url_for([@article, @article_association])

Then I get the following error:

NoMethodError
undefined method `article_articles_user_association_path' for #<#<Class:0x000...>

However, if I state routers this way

# config/routes.rb
resources :articles do
  resources :user_associations, :as => :articles_user_associations
end

the url_for method works as expected and it generates, for instance, the URL /articles/1/user_associations/1.

Note: in this case, generated named routes are like article_articles_user_associations, article_articles_user_association, edit_article_articles_user_association, ...

However, I think it isn't "good" the way routers are builded / named in the latter / working case. So, is it possible in some way to make the url_for method to work by generating named routes like article_user_association (and not like article_articles_user_association)?


I read the Official Documentation related to the ActionDispatch::Routing::UrlFor method (in particular the "URL generation for named routes" section), but I cannot find out a solution. Maybe there is a way to "say" to Rails to use a specific named router as-like it makes when you want to change the primary key column of a table with the self.primary_key statement...

# app/models/articles/user_association.rb
class Articles::UserAssociation < ActiveRecord::Base
  # self.primary_key = 'a_column_name'
  self.named_router = 'user_association'

  ...
end

Solution

  • Your UserAssociation model is in the Articles namespace, which gets included in the named route:

    # app/models/articles/user_association.rb
    class Articles::UserAssociation < ActiveRecord::Base
      ...
    end
    
    #        route =>           articles_user_association
    # nested route =>   article_articles_user_association
    

    If you remove the namespace, you will get the route helper you are looking for:

    # app/models/articles/user_association.rb
    class UserAssociation < ActiveRecord::Base
      ...
    end
    
    #        route =>           user_association
    # nested route =>   article_user_association
    

    Unless you have a really good reason for keeping UserAssociation in a namespace, don't.