0xSina
0xSina

Reputation: 21553

rails routing nested resources duplicate

I want to support:

POST images/1/comments/2/like

and

POST comments/2/like

They both point to same resources with same action. How can I do that in rails route file?

  resources :images do
    resources :comments do
      member do
        post 'like'
      end
    end
  end

This will work for

POST images/1/comments/2/like

but how can I also for when I don't specify the images/1 part?

Upvotes: 3

Views: 1452

Answers (4)

frbl
frbl

Reputation: 1292

You can make it more beautiful actually. According to http://ruby-journal.com/how-to-dry-your-rails-routes/, this also works:

comments = Proc.new do
  member do
    post 'like'
  end
end

resources :comments, &comments

resources :images do
  comments.call
end

and in Rails 4 you could use concerns

concern :comments_concern do
  member do
    post 'like'
  end
end

resources :comments, concerns: :comments_concern

resources :images, concerns: :comments_concern do
  #do more stuff here
end

I didn't test this, but it might help. Have a look at the website mentioned. Good luck

-frbl

Upvotes: 2

zeantsoi
zeantsoi

Reputation: 26193

I would consider reworking which RESTful routes for Comment you're nesting, and which you're not. I'm assuming your models look something like this:

# app/models/image.rb
class Image < ActiveRecord::Base
    has_many :comments
end

# app/models/comment.rb
class Comment < ActiveRecord::Base
    belongs_to :image
end

Because your Image and Comment models possess a one-to-many relationship, I can see why you'd think to nest the comments resource route within the images one. However, of all the CRUD actions in comments_controller.rb, only create actually requires that a parent image ID be explicitly passed in. From a RESTful perspective, only the new and create actions require that a image_id is passed to the action. The edit, update, delete, and like actions can all take place independently of the parent image.

Consider the alternative routing schematic instead:

# config/routes.rb
resources :images do
  resources :comments, :only => [:index, :new, :create]
end

resources :comments, :only => [:show, :edit, :update, :destroy] do
  member do
    post 'like'
  end
end

Now, only the comment actions that are explicitly depended on a parent ID are actually nested within the images routes. The remainder of the comment actions are directly routed to the comments controller without passing in the parent ID. Your routes are no longer duplicated, and each action will have exactly one route declared for it.

Upvotes: 1

Heartcroft
Heartcroft

Reputation: 1712

Not sure there is a much more beautiful way than repeating this below:

resources :comments do
  member do
    post 'like'
  end
end

Like so:

resources :images do
  resources :comments do
    member do
      post 'like'
    end
  end
end

resources :comments do
  member do
    post 'like'
  end
end

Upvotes: 0

Ganesh Kunwar
Ganesh Kunwar

Reputation: 2653

simply add resources :images it may work

Upvotes: 0

Related Questions