Created
August 7, 2012 19:01
-
-
Save btc/3288410 to your computer and use it in GitHub Desktop.
subdomain/locale controller, view issue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
=begin | |
I've run into an architectural challenge. I'm hoping some second opinions will help me organize this logic. | |
My sites naked and www domains serve as entrypoints to numerous subdomains through which users interact with the site. | |
=end | |
models/region.rb | |
class Region < ActiveRecord::Base | |
... | |
end | |
lib/subdomain.rb | |
class Subdomain | |
def self.matches?(request) | |
request.subdomain.present? && request.subdomain != 'www' && | |
Region.active_subdomain?(request.subdomain) | |
end | |
end | |
# I've placed logic about which subdomain a user has visited in a class called Locale. | |
lib/locale.rb | |
class Locale | |
# must provide session and request options | |
def initialize(options = {}) | |
raise ArgumentError, 'No session provided' if options[:session].nil? | |
raise ArgumentError, 'No request provided' if options[:request].nil? | |
@region = case | |
when Subdomain.matches?(options[:request]) | |
region = Region.find_by_subdomain(options[:request].subdomain) | |
options[:session][:region_id] = region.id | |
region # @region = region | |
else | |
Region.find_by_id(options[:session][:region_id]) || Region.new | |
end | |
end | |
# return the region object associated with this Locale | |
def region | |
@region | |
end | |
def valid? | |
@region.present? | |
end | |
end | |
# Then I place a before_filter in Application controller so Locale gets set up for every request. | |
class ApplicationController < ActionController::Base | |
include LocaleHelper | |
protect_from_forgery | |
prepend_before_filter :set_locale | |
helper_method :within_region? | |
helper_method :initialize_data_for_listings_form | |
def set_locale | |
@locale = Locale.new(request: request, session: session) | |
end | |
def within_region? | |
Subdomain.matches?(request) | |
end | |
# send return visitors on their way | |
def redirect_return_visitors | |
return if @locale.nil? || @locale.valid? == false | |
r = Region.find_by_id(@locale.region.id) | |
saved_region = url_for subdomain: r.subdomain, | |
controller: 'listings', action: 'index' | |
redirect_to saved_region if return_visitor? | |
end | |
def render_404(message = "page not found") | |
raise ActionController::RoutingError.new(message) | |
end | |
def reject_unless_current_user_is_admin | |
render_404 unless current_user.is_admin? | |
end | |
def reject_unless_current_region_set | |
# TODO to root | |
redirect_to '/' if @locale.region == nil | |
end | |
def initialize_data_for_listings_form(controller) | |
models = Category.major.sort_by! { |c| c.name } | |
cvar = :@major_categories | |
controller.instance_variable_set(cvar, models) | |
regions = Region.find(@locale.region.id).leaves | |
regions.sort_by! { |r| r.name } | |
rvar = :@regions | |
controller.instance_variable_set(rvar, regions) | |
end | |
end | |
# Here is the locale functionality in use. | |
# locale in use dot rbs (some html.hamls) | |
# first: | |
- if within_region? | |
= @locale.region.name | |
# second: | |
%title= "sitename #{@locale.region.name}" | |
# third: | |
#region-step.step | |
%h1 Where in #{@locale.region.name}? | |
%hr | |
= f.association :region, as: :select, label: false, | |
input_html: { id: 'select-region'}, | |
collection: @regions | |
%hr | |
# fourth: | |
def initialize_data_for_listings_form(controller) | |
models = Category.major.sort_by! { |c| c.name } | |
cvar = :@major_categories | |
controller.instance_variable_set(cvar, models) | |
regions = Region.find(@locale.region.id).leaves | |
regions.sort_by! { |r| r.name } | |
rvar = :@regions | |
controller.instance_variable_set(rvar, regions) | |
end | |
the problem is, the first time someone visits the site, they haven't yet visited a particualr region, so @locale.region is nil. This causes application errors. | |
I've considered extending application_controller with a module called LocaleHelper to address this. | |
lib/locale_helper.rb | |
def current_region_name | |
if @locale.present? && @locale.region.present? | |
@locale.region.name | |
else | |
'' | |
end | |
end | |
def current_region_id | |
if @locale.present? && @locale.region.present? | |
@locale.region.id | |
else | |
'' | |
end | |
end | |
I'm sure there's a better way to accomplish this. Any ideas? |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment