Usage of [@user, @post] method of generating URL's

So, given that its possible to hide away a conditional url from this:

if @user
  redirect_to user_post_path(@user,@post)
else
  redirect_to post_path(@post)
end

to this:

redirect_to [@user, @post]

How does Upcase feel about this? I feel like you’re just making things more implicit, and ultimately hiding away a conditional (contrived example aside). Would love to hear peoples thoughts

I always use the method form for this, with single objects I think it’s fine to redirect_to the object since it’s pretty clear, but with multiple objects I prefer having the route method there.

I am a big fan of the array/object syntax. It’s particularly useful in the following scenarios:

  • Sharing controller/views between nested/non-nested versions of a resource as shown in @Tom_Ridge’s example. Conditionally checking @user when calling link_to in a view/partial gets really ugly.
  • Partials that can render many types of objects. When linking to an object of unknown type, it is much cleaner just to pass the object to link_to and allow it to figure things out rather than using a case statement or some meta-programming
  • Dealing with form objects, presenters, etc where you will eventually need to render a url but you don’t want include the view context just to get access to the url helpers. It is much easier to deal with an object/array and then just pass that to link_to in the view or redirect_to in the controller.

In general, I prefer to just pass objects to methods rather than being coupled to the named url helper methods. As a bonus the object/array syntax tends to be shorter.

1 Like

@joelq given that we’re implicitly hiding conditionals here, at what point would you consider the need for extra views/controllers? Realise this question is pretty vague, but curious about your experiences.

In a lot of apps, I’ve found that the the nested and non-nested resources don’t diverge much. Generally the parts that do diverge can be abstracted by using polymorphism instead of conditionals (e.g. to_partial_path, link_to with array syntax).

If the view/controller starts accumulating a lot of conditionals, I would consider breaking up the resources. The decision is highly context-dependent though. How much is different vs how much is the same? How tangled together are the parent and child resources? Is there a lot of complexity that should be extracted into a higher-level object such as a facade or a presenter?

@joelq thats what I was kind of hoping to hear. So in a nutshell, you’re just taking a pragmatic approach and weighing up the costs of keeping the [@object, @post] method of a link , vs the cost of new classes/controllers/views.

I’ve tended to find myself on a war with conditionals of late, but im trying to be a little more pragmatic about it.

@Tom_Ridge Yes. The cost of breaking out a separate controller/views for the nested resource is almost guaranteed to be much higher than just using [@user, @post].

I prefer the object/array syntax over the route helpers so I would use them anyway even if I used an explicit conditional or broke out the controllers:

# explicit conditional

if @user.present?
  redirect_to [@user, @post]
else
  redirect_to @post
end

In this case, I think a simple redirect_to [@user, @post] is a completely valid and low cost way to clean up the conditional. It just requires the knowledge that:

link_to [nil, @post] == link_to @post
# => true

@joelq thanks heaps for the advice and feedback. Really appreciate your time.