jamesfzhang
jamesfzhang

Reputation: 4501

Strange Rails Routes Behavior

Following the Rails Guide on routing for nested resources, I have two models and my routes like so:

# media.rb
class Media < ActiveRecord::Base
  has_many :captions, class_name: "Captions", dependent: :destroy
end

# captions.rb
class Captions < ActiveRecord::Base
  belongs_to :media
end

# routes.rb
resources :medias do
   resources :captions
end

When I run rake routes | grep captions I get the following, which seems incorrect. Some of my actions aren't nested the way I expect them to:

   media_captions  GET     /medias/:media_id/captions(.:format)      captions#index
                   POST    /medias/:media_id/captions(.:format)      captions#create
new_media_caption  GET     /medias/:media_id/captions/new(.:format)  captions#new
    edit_captions  GET     /captions/:id/edit(.:format)              captions#edit
         captions  GET     /captions/:id(.:format)                   captions#show
                   PUT     /captions/:id(.:format)                   captions#update
                   DELETE  /captions/:id(.:format)                   captions#destroy

As you can see, the index and create actions are properly nested but the other actions are not. Can anyone explain why this is happening?

Upvotes: 1

Views: 81

Answers (3)

Kyle Macey
Kyle Macey

Reputation: 8154

I think routes are constructed this way to make it explicit that the caption is being edited, regardless as to which medias it belongs to.

Consider a has_and_belongs_to_many relationship, where a caption could belong to multiple medias. If you had the following routes:

/medias/1/captions/10/edit
/medias/5/captions/10/edit

You would still only be editing Caption 10. The routes then become redundant. We can write this simply as

/captions/10/edit

However, using an index action nested under a member route means "show me the captions for this media", so that needs to be explicitly stated:

/medias/1/captions

Or for actions such as new or create, we're saying "make a caption for this media". Again we need a specific route.

/medias/1/captions/new

And from the looks of things, you could be running into quite a bit of issues with pluralization. I would consider either adjusting your routes to fit convention, or devise a new standard for nomenclature.

Upvotes: 0

Daiku
Daiku

Reputation: 1227

I believe it stems from the fact that the plural of "media" is "media". You can check that in the rails console:

2.0.0-p0 :001 > include ActionView::Helpers::TextHelper
2.0.0-p0 :002 > pluralize(2, "media")
 => "2 media" 

So Rails thinks it's a singular resource.

Upvotes: 0

Helios de Guerra
Helios de Guerra

Reputation: 3475

Is it because your "Captions" class is plural? You're in for some pain if you're not following conventions. Your caption class file name should be caption.rb and look like so:

class Caption < ActiveRecord::Base
  belongs_to :media
end

Upvotes: 2

Related Questions