Martin Westin
Martin Westin

Reputation: 1429

How does Rails infer the parent of a nested resource?

I'd love to know how Rails infers the parent of a nested resource automatically. I have done some homework down in RouteSet but in all that module_eval and dynamically generated methods I haven't figured out how it infers the parent.

This is what I am talking about specifically

Assume the evergreen Posts and Comments data hierarchy with the appropriate models and controllers.

A nested routing of these would looks like this

resources :posts do
  resources :comments
end

When I am in the context of the controller or views of the comments rails is able to infer the post like so:

post_comments_path

Which would map to the comments index under the current Post.

When I am in the context of the posts controller and views I rails can no longer infer the post for this route, requiring me to supply it.

post_comments_path # error
post_comments_path(@post) # ok

It has been suggested in other threads that the second row is the correct way to go.

I may be crazy, but I'd love to find out how Rails is able to infer the Post. I have an edge case where one or two actions are on the root controller for a menu listing routes to mostly nested stuff. I would prefer to tell Rails what the current parent is for these few actions rather than clutter my view code with explicit parent references all over the place.

Update:

I did try the basic thing of setting a post_id parameter. Verifying that it is indeed set on both request-params and params without success. I have vague memories of Rails making copies of the params so perhaps the routing helpers have a separate copy without my added parameter? (Setting a @post instance variable has no effect either. I just had to check.)

Upvotes: 2

Views: 734

Answers (1)

engineersmnky
engineersmnky

Reputation: 29308

Okay so it seems to have to do with the defaults parameter of a path.

ie.

get '/posts/:post_id/comments', to: "comments#index", as: :show_default_comments, defaults:{post_id: Post.all.first.id}

this will show you the comments index action based on the very first post so I think that when you are in the comments controller the defaults post_id is set to the current value of post_id. I would have to do more testing to confirm this.

(Copied from my comment) Found it. default_url_options Here. Confirmed that doing this does work although it broke my index view but this is as far as I am going seems default_url_options gets passed in at some point and this is where the inference occurs and you can set it using the method in the link.

defining a url_options method in the controller to set the default_url_options for a path will allow you to specify a parent dynamically for routing purposes.

Upvotes: 1

Related Questions