Rails routing-filter, parameters not present
I'm trying to sort out the routing for a multinational web store which only has a presence in certain countries. Each store is different and has a different catalogue of products and there is also a world-wide store for all other countries. I have set up Nginx to prepend the two letter country code from an lookup of the user's IP address so that my Rails app can figure which store to direct the visitor to. I then use Sven Fuch's excellent routing-filter to capture that code, do a lookup against a global SHOPS object and if a match is found then the country code is used, otherwise they get the default (world-wide) store. My routing filter currently looks like this:
module RoutingFilter
class Country < Filter
countries_pattern ||= %r(^/(?i)([a-zA-Z]{2})(?=/|$))
def around_recognize(path, env, &block)
country = "#{extract_segment!(countries_pattern, path)}".upcase
yield(path, env).tap do |params|
params[:shop] = SHOPS.fetch(country.to_sym) || DEFAULT_SHOP
end
end
def around_generate(params, &block)
puts params
shop = params.delete(:shop)
yield.tap do |result|
prepend_segment!(result, shop[:country_code]) if shop
end
end
end
end
Now the curious thing is, the params collection does not contain a :shop param when the around_generate method is executed. My code is directly based on the pagination filter included with the routing-filter gem (I'm not using the开发者_高级运维 locale filter as each of these stores is also multilingual - i18n is handled using accept-language header instead). The original pagination filter by Sven Fuchs looks like this:
module RoutingFilter
class Pagination < Filter
PAGINATION_SEGMENT = %r(/page/([\d]+)/?$)
def around_recognize(path, env, &block)
page = extract_segment!(PAGINATION_SEGMENT, path)
yield(path, env).tap do |params|
params[:page] = page.to_i if page
end
end
def around_generate(params, &block)
page = params.delete(:page)
yield.tap do |result|
append_segment!(result, "page/#{page}") if append_page?(page)
end
end
protected
def append_page?(page)
page && page.to_i != 1
end
end
end
In my filter, shop = params.delete(:shop) results in a Nil object error and I can see from "puts params" that it is indeed not present. Does anyone have any suggestions as to why I'm unable to store and retrieve the :shop param?
Edit: I should mention that I have checked that the parameter gets set correctly in around_recognize - a "puts" of the params collection here does indeed contain the correct :shop object.
If you don't pass a :shop param to url_for (or whatever url generation helper you use here) it won't be passed to around_generate either. around_generate wraps around the url generation part of the routing system.
The Pagination filter assumes the same, e.g. it would be called like blog_posts_path(:page => 2).
But maybe that's not what you want. If you have a look at the Locale filter then this assumes that you sometimes pass a locale to the url helper but sometimes you don't. If :locale is not given it will look it up from I18n.locale which is the current locale set for this request. Maybe you want something similar here?
You could also have a look at the controller's default_url_options. IIRC you can set a default option here, too, so maybe this could work for you. I'm not using this approach anywhere though, so I'm just guessing.
HTH
精彩评论