0
votes

I have some more complex routes setup in my app, that I'm wondering could be turned into resourceful routes.

What are the ideal Rails conventions for turning these into resourceful routes?

Route 1: /grandparent-place/parent-place/place/

These routes are at the bottom of my routes.rb file, as they pull from the root path and are scoped by parents and children.

Routes.rb

get ':grandparent_id/:parent_id/:id', to: 'places#show', as: :grandparent_place
get ':parent_id/:id', to: 'places#show', as: :parent_place
get ':id', to: 'places#show', as: :place

Places_Controller.rb

def set_place
  if params[:parent_id].nil? && params[:grandparent_id].nil?
    @place            = Place.find(params[:id])

  elsif params[:grandparent_id].nil?
    @parent           = Place.find(params[:parent_id])
    @place            = @parent.children.find(params[:id])

  else
    @grandparent      = Place.find(params[:grandparent_id])
    @parent           = @grandparent.children.find(params[:parent_id])
    @place            = @parent.children.find(params[:id])

  end
end

Application_Helper.rb

def place_path(place)
    '/' + place.ancestors.map{|x| x.id.to_s}.join('/') + '/' + place.id.to_s
end

Route 2: /thread#post-123

These routes are meant to allow for only specific actions, using the parent module to specify the controller directory - and using a # anchor to scroll to the specified post.

Routes.rb

resources :threads, only: [:show] do
  resources :posts, module: :threads, only: [:show, :create, :update, :destroy]
end

Application_Helper.rb

def thread_post_path(thread, post)
  thread_path(thread) + '#post-' + post.id.to_s
end

Is it convention to override the route paths in the application helper, or is there a better way to generate the correct URLs without overriding the helpers?

1

1 Answers

0
votes

Path variables are used to specify resources and usually one variable specify one resource. For example:

get '/publishers/:publisher_id/articels/:article_id/comments/:id'

In your setup you have places as a resource.

So, in this endpoint get '/places/:id' :id specifies which place should be retrieved.

Regarding your first route it would be most appropriate to leave just one get endpoint:

resource :places, only: [:show] # => get '/places/:id'

and pass the id of the parent or grandparent as :id whenever you need to retrieve the parent or grandparent place. That way you won't need any conditions in set_place method and so have:

def set_place
  @place = Place.find(params[:id])
end

In case you need to access parents or grandparents of a place object you can build:

 get '/places/:place_id/parents/:parent_id/grandparents/:id'

or just leave get '/places/:place_id/parents/:id' and whenever you need to access a grandparent just make the call starting from your parent place instead of the child. Route setups can vary depending on your needs. Rails provides various examples on that matter: Rails Routing from the Outside In

Regarding the helpers, there isn't a general rule for overriding or not your path methods and again it mostly depends on the application's needs. I think it is a good practice to keep them intact as much as possible. In your case instead of overriding the path method you can place:

thread_posts_path(thread) + '#post-' + post.id # => /threads/7/posts#post-15

directly in your view, for example:

link_to 'MyThredPost', thread_posts_path(thread) + '#post-' + post.id