Rails routing: Giving default values for path helpers
Asked Answered
D

3

5

Is there some way to provide a default value to the url/path helpers?

I have an optional scope wrapping around all of my routes:

#config/routes.rb
Foo::Application.routes.draw do

  scope "(:current_brand)", :constraints => { :current_brand => /(foo)|(bar)/ } do
    # ... all other routes go here
  end

end

I want users to be able to access the site using these URLs:

/foo/some-place
/bar/some-place
/some-place

For convenience, I'm setting up a @current_brand in my ApplicationController:

# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  before_filter :set_brand

  def set_brand                                                                 
    if params.has_key?(:current_brand)                                          
      @current_brand = Brand.find_by_slug(params[:current_brand])               
    else                                                                        
      @current_brand = Brand.find_by_slug('blah')
    end
  end

 end

So far so good, but now I must modify all *_path and *_url calls to include the :current_brand parameter, even though it is optional. This is really ugly, IMO.

Is there some way I can make the path helpers automagically pick up on @current_brand?

Or perhaps a better way to define the scope in routes.rb?

Darondarooge answered 29/3, 2012 at 18:41 Comment(0)
P
7

I think you will want to do something like this:

class ApplicationController < ActionController::Base

  def url_options
    { :current_brand => @current_brand }.merge(super)
  end

end

This method is called automatically every time url is constructed and it's result is merged into the parameters.

For more info on this, look at: default_url_options and rails 3

Phile answered 30/3, 2012 at 15:9 Comment(2)
Thanks. This is the solution I ended up going with. There we lots of gotchas as well, such as needing to set this up in the mailers, and a hack to get it to work with rspec (pasted in my own answer)Darondarooge
Oh, yes, I'm sorry for not pointing this out. Glad you mentioned it for completeness.Phile
D
4

In addition to CMW's answer, to get it to work with rspec, I added this hack in spec/support/default_url_options.rb

ActionDispatch::Routing::RouteSet.class_eval do
  undef_method :default_url_options
  def default_url_options(options={})
    { :current_brand => default_brand }
  end
end
Darondarooge answered 7/4, 2012 at 19:8 Comment(0)
A
0

For those arriving here lately, this has changed in Rails 7.1

You can now explicitly set path params as a sub hash of default_url_options in the ApplicationController

class ApplicationController < ActionController::Base  
  def default_url_options
    { path_params: { account_id: @current_account } }
  end

Then you can simply remove the account_id param in your path helper

<%= link_to "Edit", edit_account_path %>
<%= link_to "Account Category", account_categories_path(@current_category)%>

You can always override the default too

<%= link_to "Edit Alt Account", edit_account_path(account_id: @alt_acct_id) %>

(This works for nested routes too if you add more params to the path_params sub-hash)

Antidote answered 3/2 at 0:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.