Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Initial pass of Rails3 compat. Note that no tests are running as RSpe…

…c isn't cooperating with me just yet.
  • Loading branch information...
commit 95753f37934e26089a2d005f89efb7279250c026 1 parent 2faaa56
Michael Bleigh mbleigh authored
57 README.rdoc
View
@@ -5,17 +5,19 @@ It takes aspects from account_location, request_routing, and other snippets
found around the web and combines them to provide a single, simple solution
for subdomain-based route and url management.
+**Note**: SubdomainFu has been rewritten to be compatible with Rails 3. If
+you are looking to use it on Rails 2.x, please install version v0.5.x instead.
+
== Installation
SubdomainFu is available both as a traditional plugin and a GemPlugin. To
-install it as a traditional plugin (Rails 2.1 or later):
+install it as a traditional plugin:
- script/plugin install git://github.com/mbleigh/subdomain-fu.git
+ script/plugin install git://github.com/intridea/subdomain-fu.git
-To use it as a gem, add it to your config/environment.rb:
-
- config.gem 'subdomain-fu'
+To use it as a gem, add it to your Gemfile:
+ gem 'subdomain-fu'
== Examples
@@ -51,7 +53,7 @@ You have access to current_subdomain and current_domain methods.
[current_subdomain] returns all subdomains. For the URL http://awesome.website.stuff.example.com, it will return "awesome.website.stuff"
-[current_domain] returns all subdomains except for the subdomain, including the TLD. For the URL http://awesome.website.stuff.example.com, it will return "website.stuff.example.com"
+[current_domain] returns the domain excluding for the subdomain, including the TLD. For the URL http://awesome.website.stuff.example.com, it will return "website.stuff.example.com"
If what you really want is the entire domain, then use <tt>request.domain</tt> in
your controllers. The purpose of current_domain is to only strip off the first
@@ -59,52 +61,53 @@ subdomain, if any, and return what's left.
== Configuration
-You may need to configure SubdomainFu based on your development setup. The
-configuration required is:
+You may need to configure SubdomainFu based on your development setup. To configure
+SubdomainFu simply call a block in an initializer like so:
+
+ SubdomainFu.configure do |config|
+ config.option_name = value
+ end
-=== TLD Size
+Some available options are enumerated below.
+
+=== tld_size
A hash for each environment of the size of the top-level domain name.
(something.com = 1, localhost = 0, etc.)
- SubdomainFu.tld_size = 1 # sets for current environment
- SubdomainFu.tld_sizes = {:development => 0,
+ config.tld_size = 1 # sets for current environment
+ config.tld_sizes = {:development => 0,
:test => 0,
:production => 1} # set all at once (also the defaults)
-=== Mirrors
+=== mirrors
Mirrors are the subdomains that are equivalent to no subdomain (i.e. they 'mirror')
the usage of the root domain.
- SubdomainFu.mirrors = %w(www site we) # Defaults to %w(www)
+ config.mirrors = %w(www site we) # Defaults to %w(www)
-=== Preferred Mirror
+=== preferred_mirror
SubdomainFu also understands the notion of a 'preferred mirror', that is, if you
always want your links going to 'www.yourdomain.com' instead of 'yourdomain.com',
you can set the preferred mirror like so:
- SubdomainFu.preferred_mirror = "www"
+ config.preferred_mirror = "www"
Now when you create a link with <tt>:subdomain => false</tt> in the options the subdomain
will default to the preferred mirror.
-== Routing
-
-SubdomainFu can also work within Rails' routing for subdomain-specific routes. For instance, if you only wanted your administrative tools available in the "admin" subdomain you could add this to your <tt>config/routes.rb</tt> file:
+== Routing (Deprecated)
- map.with_options :conditions => {:subdomain => 'admin'} do |admin|
- admin.resources :posts
- admin.resources :users
- end
-
-In addition to specifying a string, you could also specify <tt>false</tt> to require no subdomain (this includes mirrors that you've set up such as www) or a regular expression to match a range of subdomains.
+Subdomain constraint routing has been removed from the scope of this plugin as Rails 3
+provides the functionality by default. For more info, see this blog post:
+http://yehudakatz.com/2009/12/26/the-rails-3-router-rack-it-up/
== Resources
-* GitHub Repository: http://github.com/mbleigh/subdomain-fu
-* RDocs: http://rdoc.info/projects/mbleigh/subdomain-fu
+* GitHub Repository: http://github.com/intridea/subdomain-fu
+* RDocs: http://rdoc.info/projects/intridea/subdomain-fu
-Copyright (c) 2008 Michael Bleigh (http://www.mbleigh.com/) and
+Copyright (c) 2008-2010 Michael Bleigh (http://www.mbleigh.com/) and
Intridea, Inc. (http://www.intridea.com/). Released under the MIT license
22 config/database.yml
View
@@ -0,0 +1,22 @@
+# SQLite version 3.x
+# gem install sqlite3-ruby (not necessary on OS X Leopard)
+development:
+ adapter: sqlite3
+ database: db/development.sqlite3
+ pool: 5
+ timeout: 5000
+
+# Warning: The database defined as "test" will be erased and
+# re-generated from your development database when you run "rake".
+# Do not set this db to the same as development or production.
+test:
+ adapter: sqlite3
+ database: db/test.sqlite3
+ pool: 5
+ timeout: 5000
+
+production:
+ adapter: sqlite3
+ database: db/production.sqlite3
+ pool: 5
+ timeout: 5000
2  install.sh
View
@@ -1,2 +0,0 @@
-# I use this to make life easier when installing and testing from source:
-rm -rf subdomain-fu-*.gem && gem build subdomain-fu.gemspec && sudo gem uninstall subdomain-fu && sudo gem install subdomain-fu-0.5.2.gem --no-ri --no-rdoc
98 lib/subdomain-fu.rb
View
@@ -1,57 +1,77 @@
-require 'subdomain_fu/routing_extensions'
require 'subdomain_fu/url_rewriter'
module SubdomainFu
- # The length of the period-split top-level domain for each environment.
- # For example, "localhost" has a tld_size of zero, and "something.co.uk"
- # has a tld_size of two.
- #
- # To set a tld size for a given environment, just call SubdomainFu.tld_sizes[:environment] = value
- DEFAULT_TLD_SIZES = {:development => 0, :test => 0, :production => 1}
- mattr_accessor :tld_sizes
- @@tld_sizes = DEFAULT_TLD_SIZES.dup
-
- # Subdomains that are equivalent to going to the website with no subdomain at all.
- # Defaults to "www" as the only member.
- DEFAULT_MIRRORS = %w(www)
- mattr_accessor :mirrors
- @@mirrors = DEFAULT_MIRRORS.dup
-
- mattr_accessor :preferred_mirror
- @@preferred_mirror = nil
-
- mattr_accessor :override_only_path
- @@override_only_path = false
-
- # Returns the TLD Size of the current environment.
- def self.tld_size
- tld_sizes[RAILS_ENV.to_sym]
+ class << self
+ attr_accessor :config
+
+ def config
+ self.config = Configuration.new unless @config
+ @config
+ end
end
- # Sets the TLD Size of the current environment
- def self.tld_size=(value)
- tld_sizes[RAILS_ENV.to_sym] = value
+ # The configurable options of Subdomain Fu. Use like so:
+ #
+ # SubdomainFu.configure do |config|
+ # config.tld_size = 2
+ # config.preferred_mirror = 'www'
+ # end
+ #
+ # Available configurations are:
+ #
+ # <tt>tld_size</tt>: :: The size of the top-level domain. For example, 'localhost' is 0, 'example.com' is 1, and 'example.co.uk' is 2.
+ # <tt>mirrors</tt>: :: An array of subdomains that should be equivalent to no subdomain. Defaults to <tt>['www']</tt>.
+ # <tt>preferred_mirror</tt>: The preferred mirror subdomain to which to rewrite URLs. No subdomain is used by default.
+ # <tt>override_only_path</tt>: :: If <tt>true</tt>, changing the subdomain will emit a full URL in url_for options, even if it wouldn't have otherwise.
+ def self.configure
+ self.config ||= Configuration.new
+ yield(self.config)
+ end
+
+ class Configuration
+ attr_accessor :tld_sizes, :mirrors, :preferred_mirror, :override_only_path
+
+ @@defaults = {
+ :tld_sizes => {:development => 1, :test => 1, :production => 1},
+ :mirrors => %w(www),
+ :preferred_mirror => nil,
+ :override_only_path => false
+ }
+
+ def initialize
+ @@defaults.each_pair do |k, v|
+ self.send("#{k}=", v)
+ end
+ end
+
+ def tld_size=(size)
+ tld_sizes[Rails.env.to_sym] = size
+ end
+
+ def tld_size
+ tld_sizes[Rails.env.to_sym]
+ end
end
# Is the current subdomain either nil or not a mirror?
def self.has_subdomain?(subdomain)
- subdomain != false && !subdomain.blank? && !SubdomainFu.mirrors.include?(subdomain)
+ subdomain != false && !subdomain.blank? && !SubdomainFu.config.mirrors.include?(subdomain)
end
def self.is_mirror?(subdomain)
- subdomain != false && !subdomain.blank? && SubdomainFu.mirrors.include?(subdomain)
+ subdomain != false && !subdomain.blank? && SubdomainFu.config.mirrors.include?(subdomain)
end
# Is the subdomain a preferred mirror
def self.preferred_mirror?(subdomain)
- subdomain == SubdomainFu.preferred_mirror || SubdomainFu.preferred_mirror.nil?
+ subdomain == SubdomainFu.config.preferred_mirror || SubdomainFu.config.preferred_mirror.nil?
end
# Gets the subdomain from the host based on the TLD size
def self.subdomain_from(host)
return nil if host.nil? || /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.match(host)
parts = host.split('.')
- sub = parts[0..-(SubdomainFu.tld_size+2)].join(".")
+ sub = parts[0..-(SubdomainFu.config.tld_size+2)].join(".")
sub.blank? ? nil : sub
end
@@ -63,19 +83,19 @@ def self.non_mirror_subdomain_from(host)
def self.host_without_subdomain(host)
parts = host.split('.')
- parts[-(SubdomainFu.tld_size+1)..-1].join(".")
+ parts[-(SubdomainFu.config.tld_size+1)..-1].join(".")
end
# Rewrites the subdomain of the host unless they are equivalent (i.e. mirrors of each other)
def self.rewrite_host_for_subdomains(subdomain, host)
if needs_rewrite?(subdomain, host)
- change_subdomain_of_host(subdomain || SubdomainFu.preferred_mirror, host)
+ change_subdomain_of_host(subdomain || SubdomainFu.config.preferred_mirror, host)
else
if has_subdomain?(subdomain) || preferred_mirror?(subdomain_from(host)) ||
(subdomain.nil? && has_subdomain?(subdomain_from(host)))
host
else
- change_subdomain_of_host(SubdomainFu.preferred_mirror, host)
+ change_subdomain_of_host(SubdomainFu.config.preferred_mirror, host)
end
end
end
@@ -95,14 +115,14 @@ def self.same_subdomain?(subdomain, host)
end
def self.override_only_path?
- self.override_only_path
+ config.override_only_path
end
def self.needs_rewrite?(subdomain, host)
case subdomain
when nil
#rewrite when there is a preferred mirror set and there is no subdomain on the host
- return true if self.preferred_mirror && subdomain_from(host).nil?
+ return true if config.preferred_mirror && subdomain_from(host).nil?
return false
when false
h = subdomain_from(host)
@@ -111,7 +131,7 @@ def self.needs_rewrite?(subdomain, host)
#rewrite when there is a subdomain in the host, and it is not a preferred mirror
return true if !preferred_mirror?(h)
#rewrite when there is a preferred mirror set and the subdomain of the host is not a mirror
- return true if self.preferred_mirror && !is_mirror?(h)
+ return true if config.preferred_mirror && !is_mirror?(h)
#no rewrite if host already has mirror subdomain
#it { SubdomainFu.needs_rewrite?(false,"www.localhost").should be_false }
return false if is_mirror?(h)
@@ -129,7 +149,7 @@ def self.crazy_rewrite_rule(subdomain, host)
end
def self.current_subdomain(request)
- subdomain = request.subdomains(SubdomainFu.tld_size).join(".")
+ subdomain = request.subdomains(SubdomainFu.config.tld_size).join(".")
if has_subdomain?(subdomain)
subdomain
else
61 lib/subdomain_fu/routing_extensions.rb
View
@@ -1,61 +0,0 @@
-# Thanks to Jamis Buck for ideas on this stuff
-# http://weblog.jamisbuck.org/2006/10/26/monkey-patching-rails-extending-routes-2
-# This is not yet a working part of SubdomainFu.
-
-module SubdomainFu
- module RouteExtensions
- def self.included(base)
- base.alias_method_chain :recognition_conditions, :subdomain
- end
-
- def recognition_conditions_with_subdomain
- result = recognition_conditions_without_subdomain
- result << "conditions[:subdomain] === env[:subdomain]" if conditions[:subdomain] && conditions[:subdomain] != true && conditions[:subdomain] != false
- result << "SubdomainFu.has_subdomain?(env[:subdomain])" if conditions[:subdomain] == true
- result << "!SubdomainFu.has_subdomain?(env[:subdomain])" if conditions[:subdomain] == false
- result
- end
- end
-
- module RouteSetExtensions
- def self.included(base)
- base.alias_method_chain :extract_request_environment, :subdomain
- end
-
- def extract_request_environment_with_subdomain(request)
- env = extract_request_environment_without_subdomain(request)
- env.merge(:host => request.host, :domain => request.domain, :subdomain => SubdomainFu.current_subdomain(request))
- end
- end
-
- module MapperExtensions
- def quick_map(has_unless, *args, &block)
- options = args.find{|a| a.is_a?(Hash)}
- namespace_str = options ? options.delete(:namespace).to_s : args.join('_or_')
- namespace_str += '_' unless namespace_str.blank?
- mapped_exp = args.map(&:to_s).join('|')
- conditions_hash = { :subdomain => ( has_unless ? /[^(#{mapped_exp})]/ : /(#{mapped_exp})/) }
- with_options(:conditions => conditions_hash, :name_prefix => namespace_str, &block)
- end
- # Adds methods to Mapper to apply an options with a method. Example
- # map.subdomain :blog { |blog| blog.resources :pages }
- # or
- # map.unless_subdomain :blog { |not_blog| not_blog.resources :people }
- def subdomain(*args, &block)
- quick_map(false, *args, &block)
- end
- def unless_subdomain(*args, &block)
- quick_map(true, *args, &block)
- end
- end
-end
-
-ActionController::Routing::RouteSet::Mapper.send :include, SubdomainFu::MapperExtensions
-ActionController::Routing::RouteSet.send :include, SubdomainFu::RouteSetExtensions
-ActionController::Routing::Route.send :include, SubdomainFu::RouteExtensions
-
-# UrlRewriter::RESERVED_OPTIONS is only available in Rails >= 2.2
-# http://www.portallabs.com/blog/2008/12/02/fixing-subdomain_fu-with-named-routes-rails-22/
-if Rails::VERSION::MAJOR >= 2 and Rails::VERSION::MINOR >= 2
- ActionController::UrlRewriter::RESERVED_OPTIONS << :subdomain
-end
65 lib/subdomain_fu/url_rewriter.rb
View
@@ -1,48 +1,33 @@
+require 'action_controller/metal/url_for'
+require 'action_controller/url_rewriter'
+
module ActionController
- module UrlWriter
- def url_for_with_subdomains(options)
- if SubdomainFu.needs_rewrite?(options[:subdomain], options[:host] || default_url_options[:host]) || options[:only_path] == false
- options[:only_path] = false if SubdomainFu.override_only_path?
- options[:host] = SubdomainFu.rewrite_host_for_subdomains(options.delete(:subdomain), options[:host] || default_url_options[:host])
- else
- options.delete(:subdomain)
- end
- url_for_without_subdomains(options)
- end
- alias_method_chain :url_for, :subdomains
- end
+ # module UrlFor
+ # def url_for_with_subdomains(options)
+ # if SubdomainFu.needs_rewrite?(options[:subdomain], options[:host] || default_url_options[:host]) || options[:only_path] == false
+ # options[:only_path] = false if SubdomainFu.override_only_path?
+ # options[:host] = SubdomainFu.rewrite_host_for_subdomains(options.delete(:subdomain), options[:host] || default_url_options[:host])
+ # else
+ # options.delete(:subdomain)
+ # end
+ # url_for_without_subdomains(options)
+ # end
+ # alias_method_chain :url_for, :subdomains
+ # end
class UrlRewriter #:nodoc:
- private
-
- def rewrite_url_with_subdomains(options)
- if SubdomainFu.needs_rewrite?(options[:subdomain], (options[:host] || @request.host_with_port)) || options[:only_path] == false
- options[:only_path] = false if SubdomainFu.override_only_path?
- options[:host] = SubdomainFu.rewrite_host_for_subdomains(options.delete(:subdomain), options[:host] || @request.host_with_port)
- # puts "options[:host]: #{options[:host].inspect}"
- else
- options.delete(:subdomain)
- end
- rewrite_url_without_subdomains(options)
- end
- alias_method_chain :rewrite_url, :subdomains
- end
-
- if Rails::VERSION::MAJOR >= 2 and Rails::VERSION::MINOR <= 1
- # hack for http://www.portallabs.com/blog/2008/10/22/fixing-subdomain_fu-with-named-routes/
- module Routing
- module Optimisation
- class PositionalArgumentsWithAdditionalParams
- def guard_condition_with_subdomains
- # don't allow optimisation if a subdomain is present - fixes a problem
- # with the subdomain appearing in the query instead of being rewritten
- # see http://mbleigh.lighthouseapp.com/projects/13148/tickets/8-improper-generated-urls-with-named-routes-for-a-singular-resource
- guard_condition_without_subdomains + " && !args.last.has_key?(:subdomain)"
- end
-
- alias_method_chain :guard_condition, :subdomains
+ class << self
+ def rewrite_with_subdomains(options, path_segments=nil)
+ if SubdomainFu.needs_rewrite?(options[:subdomain], (options[:host] || @request.host_with_port)) || options[:only_path] == false
+ options[:only_path] = false if SubdomainFu.override_only_path?
+ options[:host] = SubdomainFu.rewrite_host_for_subdomains(options.delete(:subdomain), options[:host] || @request.host_with_port)
+ # puts "options[:host]: #{options[:host].inspect}"
+ else
+ options.delete(:subdomain)
end
+ rewrite_without_subdomains(options, path_segments)
end
+ alias_method_chain :rewrite, :subdomains
end
end
end
6 rails/init.rb
View
@@ -1,6 +1,6 @@
+require 'action_controller/base'
+
#Allow whatever Ruby Package tool is being used ot manage load paths. gem auto adds the gem's lib dir to load path.
require 'subdomain-fu' unless defined?(SubdomainFu)
-ActionController::Base.send :include, SubdomainFu::Controller
-
-RAILS_DEFAULT_LOGGER.info("** SubdomainFu: initialized properly")
+ActionController::Base.send :include, SubdomainFu::Controller
8 spec/spec_helper.rb
View
@@ -1,14 +1,14 @@
begin
require File.dirname(__FILE__) + '/../../../../spec/spec_helper'
-rescue LoadError
- puts "You need to install rspec in your base app"
- exit
+#rescue LoadError
+# puts "You need to install RSpec in your base app. Add 'rspec-rails' to your Gemfile."
+# exit
end
plugin_spec_dir = File.dirname(__FILE__)
ActiveRecord::Base.logger = Logger.new(plugin_spec_dir + "/debug.log")
-ActionController::Routing::Routes.draw do |map|
+Rails3::Application.routes.draw do |map|
map.needs_subdomain '/needs_subdomain', :controller => "fu", :action => "awesome"
map.no_subdomain '/no_subdomain', :controller => "fu", :action => "lame"
map.needs_awesome '/needs_awesome', :controller => "fu", :action => "lame"
Please sign in to comment.
Something went wrong with that request. Please try again.