gameplan-subdomain-fu 0.5.4

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG ADDED
@@ -0,0 +1,20 @@
1
+ == 2009-09-13
2
+
3
+ * Added current_domain method
4
+ * Added controller & view usage to readme
5
+ * Added more tests
6
+ * Fixing load paths
7
+
8
+ == 2009-08-26
9
+
10
+ * Fixed needs_rewrite? method
11
+ * Added is_mirror? method
12
+ * Added tests, and fixed failing tests
13
+
14
+ == 2009-08-24
15
+
16
+ * Merged forks that added lots of features, tests, and fixes
17
+
18
+ == 2008-06-25
19
+
20
+ * Removed stray puts
data/MIT-LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2008 Michael Bleigh (http://www.mbleigh.com) and
2
+ Intridea, Inc (http://www.intridea.com)
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining
5
+ a copy of this software and associated documentation files (the
6
+ "Software"), to deal in the Software without restriction, including
7
+ without limitation the rights to use, copy, modify, merge, publish,
8
+ distribute, sublicense, and/or sell copies of the Software, and to
9
+ permit persons to whom the Software is furnished to do so, subject to
10
+ the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,110 @@
1
+ = SubdomainFu
2
+
3
+ SubdomainFu provides a modern implementation of subdomain handling in Rails.
4
+ It takes aspects from account_location, request_routing, and other snippets
5
+ found around the web and combines them to provide a single, simple solution
6
+ for subdomain-based route and url management.
7
+
8
+ == Installation
9
+
10
+ SubdomainFu is available both as a traditional plugin and a GemPlugin. To
11
+ install it as a traditional plugin (Rails 2.1 or later):
12
+
13
+ script/plugin install git://github.com/mbleigh/subdomain-fu.git
14
+
15
+ To use it as a gem, add it to your config/environment.rb:
16
+
17
+ config.gem 'subdomain-fu'
18
+
19
+
20
+ == Examples
21
+
22
+ SubdomainFu works inside of Rails's URL Writing mechanisms to provide an easy and seamless
23
+ way to link and otherwise understand cross-subdomain routing. You can use the :subdomain
24
+ option both in named and non-named routes as well as in generated resources routes.
25
+
26
+ Let's say my domain is 'intridea.com'. Here are some examples of the use of the :subdomain
27
+ option:
28
+
29
+ url_for(:controller => "my_controller",
30
+ :action => "my_action",
31
+ :subdomain => "awesome") # => http://awesome.intridea.com/my_controller/my_action
32
+
33
+ Now let's say I'm at http://awesome.intridea.com/ and I want back to the root.
34
+ Specifying "false" will remove any current subdomain:
35
+
36
+ users_url(:subdomain => false) # => http://intridea.com/users
37
+
38
+ Note that this plugin does not honor the :only_path notion of routing when doing
39
+ so would go against the intent of the command. For example, if I were at http://intridea.com
40
+ again:
41
+
42
+ users_path(:subdomain => "fun") # => http://fun.intridea.com/users
43
+ users_path(:subdomain => false) # => /users
44
+
45
+ In this way you can rest assured that you will never misdirect your links to the
46
+ same subdomain when you meant to change it.
47
+
48
+ == Use in controllers and views
49
+
50
+ You have access to current_subdomain and current_domain methods.
51
+
52
+ [current_subdomain] returns all subdomains. For the URL http://awesome.website.stuff.example.com, it will return "awesome.website.stuff"
53
+
54
+ [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"
55
+
56
+ If what you really want is the entire domain, then use <tt>request.domain</tt> in
57
+ your controllers. The purpose of current_domain is to only strip off the first
58
+ subdomain, if any, and return what's left.
59
+
60
+ == Configuration
61
+
62
+ You may need to configure SubdomainFu based on your development setup. The
63
+ configuration required is:
64
+
65
+ === TLD Size
66
+
67
+ A hash for each environment of the size of the top-level domain name.
68
+ (something.com = 1, localhost = 0, etc.)
69
+
70
+ SubdomainFu.tld_size = 1 # sets for current environment
71
+ SubdomainFu.tld_sizes = {:development => 0,
72
+ :test => 0,
73
+ :production => 1} # set all at once (also the defaults)
74
+
75
+ === Mirrors
76
+
77
+ Mirrors are the subdomains that are equivalent to no subdomain (i.e. they 'mirror')
78
+ the usage of the root domain.
79
+
80
+ SubdomainFu.mirrors = %w(www site we) # Defaults to %w(www)
81
+
82
+ === Preferred Mirror
83
+
84
+ SubdomainFu also understands the notion of a 'preferred mirror', that is, if you
85
+ always want your links going to 'www.yourdomain.com' instead of 'yourdomain.com',
86
+ you can set the preferred mirror like so:
87
+
88
+ SubdomainFu.preferred_mirror = "www"
89
+
90
+ Now when you create a link with <tt>:subdomain => false</tt> in the options the subdomain
91
+ will default to the preferred mirror.
92
+
93
+ == Routing
94
+
95
+ 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:
96
+
97
+ map.with_options :conditions => {:subdomain => 'admin'} do |admin|
98
+ admin.resources :posts
99
+ admin.resources :users
100
+ end
101
+
102
+ 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.
103
+
104
+ == Resources
105
+
106
+ * GitHub Repository: http://github.com/mbleigh/subdomain-fu
107
+ * RDocs: http://rdoc.info/projects/mbleigh/subdomain-fu
108
+
109
+ Copyright (c) 2008 Michael Bleigh (http://www.mbleigh.com/) and
110
+ Intridea, Inc. (http://www.intridea.com/). Released under the MIT license
data/Rakefile ADDED
@@ -0,0 +1,56 @@
1
+ require 'rake'
2
+ require 'spec/rake/spectask'
3
+
4
+ desc 'Default: run specs.'
5
+ task :default => :spec
6
+
7
+ desc 'Run the specs'
8
+ Spec::Rake::SpecTask.new(:spec) do |t|
9
+ t.spec_opts = ['--colour --format progress --loadby mtime --reverse']
10
+ t.spec_files = FileList['spec/**/*_spec.rb']
11
+ end
12
+
13
+ begin
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gemspec|
16
+ gemspec.name = "subdomain-fu"
17
+ gemspec.rubyforge_project = 'subdomain-fu'
18
+ gemspec.summary = "SubdomainFu is a Rails plugin that provides subdomain routing and URL writing helpers."
19
+ gemspec.email = "michael@intridea.com"
20
+ gemspec.homepage = "http://github.com/mbleigh/subdomain-fu"
21
+ gemspec.files = FileList["[A-Z]*", "{lib,spec,rails}/**/*"] - FileList["**/*.log"]
22
+ gemspec.description = "SubdomainFu is a Rails plugin to provide all of the basic functionality necessary to handle multiple subdomain applications (such as Basecamp-esque subdomain accounts and more)."
23
+ gemspec.authors = ["Michael Bleigh"]
24
+ end
25
+ Jeweler::GemcutterTasks.new
26
+ rescue LoadError
27
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
28
+ end
29
+
30
+
31
+ # These are new tasks
32
+ begin
33
+ require 'rake/contrib/sshpublisher'
34
+ namespace :rubyforge do
35
+
36
+ desc "Release gem and RDoc documentation to RubyForge"
37
+ task :release => ["rubyforge:release:gem", "rubyforge:release:docs"]
38
+
39
+ namespace :release do
40
+ desc "Publish RDoc to RubyForge."
41
+ task :docs => [:rdoc] do
42
+ config = YAML.load(
43
+ File.read(File.expand_path('~/.rubyforge/user-config.yml'))
44
+ )
45
+
46
+ host = "#{config['username']}@rubyforge.org"
47
+ remote_dir = "/var/www/gforge-projects/the-perfect-gem/"
48
+ local_dir = 'rdoc'
49
+
50
+ Rake::SshDirPublisher.new(host, remote_dir, local_dir).upload
51
+ end
52
+ end
53
+ end
54
+ rescue LoadError
55
+ puts "Rake SshDirPublisher is unavailable or your rubyforge environment is not configured."
56
+ end
data/VERSION.yml ADDED
@@ -0,0 +1,5 @@
1
+ ---
2
+ :major: 0
3
+ :build:
4
+ :minor: 5
5
+ :patch: 4
@@ -0,0 +1,163 @@
1
+ require 'subdomain_fu/routing_extensions'
2
+ require 'subdomain_fu/url_rewriter'
3
+
4
+ module SubdomainFu
5
+ # The length of the period-split top-level domain for each environment.
6
+ # For example, "localhost" has a tld_size of zero, and "something.co.uk"
7
+ # has a tld_size of two.
8
+ #
9
+ # To set a tld size for a given environment, just call SubdomainFu.tld_sizes[:environment] = value
10
+ DEFAULT_TLD_SIZES = {:development => 0, :test => 0, :production => 1}
11
+ mattr_accessor :tld_sizes
12
+ @@tld_sizes = DEFAULT_TLD_SIZES.dup
13
+
14
+ # Subdomains that are equivalent to going to the website with no subdomain at all.
15
+ # Defaults to "www" as the only member.
16
+ DEFAULT_MIRRORS = %w(www)
17
+ mattr_accessor :mirrors
18
+ @@mirrors = DEFAULT_MIRRORS.dup
19
+
20
+ mattr_accessor :preferred_mirror
21
+ @@preferred_mirror = nil
22
+
23
+ mattr_accessor :override_only_path
24
+ @@override_only_path = false
25
+
26
+ # Returns the TLD Size of the current environment.
27
+ def self.tld_size
28
+ tld_sizes[RAILS_ENV.to_sym]
29
+ end
30
+
31
+ # Sets the TLD Size of the current environment
32
+ def self.tld_size=(value)
33
+ tld_sizes[RAILS_ENV.to_sym] = value
34
+ end
35
+
36
+ # Is the current subdomain either nil or not a mirror?
37
+ def self.has_subdomain?(subdomain)
38
+ subdomain != false && !subdomain.blank? && !SubdomainFu.mirrors.include?(subdomain)
39
+ end
40
+
41
+ def self.is_mirror?(subdomain)
42
+ subdomain != false && !subdomain.blank? && SubdomainFu.mirrors.include?(subdomain)
43
+ end
44
+
45
+ # Is the subdomain a preferred mirror
46
+ def self.preferred_mirror?(subdomain)
47
+ subdomain == SubdomainFu.preferred_mirror || SubdomainFu.preferred_mirror.nil?
48
+ end
49
+
50
+ # Gets the subdomain from the host based on the TLD size
51
+ def self.subdomain_from(host)
52
+ return nil if host.nil? || /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.match(host)
53
+ parts = host.split('.')
54
+ sub = parts[0..-(SubdomainFu.tld_size+2)].join(".")
55
+ sub.blank? ? nil : sub
56
+ end
57
+
58
+ # Gets only non-mirror subdomains from the host based on the TLD size
59
+ def self.non_mirror_subdomain_from(host)
60
+ sub = subdomain_from(host)
61
+ has_subdomain?(sub) ? sub : nil
62
+ end
63
+
64
+ def self.host_without_subdomain(host)
65
+ parts = host.split('.')
66
+ parts[-(SubdomainFu.tld_size+1)..-1].join(".")
67
+ end
68
+
69
+ # Rewrites the subdomain of the host unless they are equivalent (i.e. mirrors of each other)
70
+ def self.rewrite_host_for_subdomains(subdomain, host)
71
+ if needs_rewrite?(subdomain, host)
72
+ change_subdomain_of_host(subdomain || SubdomainFu.preferred_mirror, host)
73
+ else
74
+ if has_subdomain?(subdomain) || preferred_mirror?(subdomain_from(host)) ||
75
+ (subdomain.nil? && has_subdomain?(subdomain_from(host)))
76
+ host
77
+ else
78
+ change_subdomain_of_host(SubdomainFu.preferred_mirror, host)
79
+ end
80
+ end
81
+ end
82
+
83
+ # Changes the subdomain of the host to whatever is passed in.
84
+ def self.change_subdomain_of_host(subdomain, host)
85
+ subdomain_string = (subdomain && subdomain.respond_to?(:to_param)) ? subdomain.to_param : subdomain
86
+
87
+ host = SubdomainFu.host_without_subdomain(host)
88
+ host = "#{subdomain_string}.#{host}" if subdomain_string
89
+ host
90
+ end
91
+
92
+ # Is this subdomain equivalent to the subdomain found in this host string?
93
+ def self.same_subdomain?(subdomain, host)
94
+ subdomain = nil unless subdomain
95
+ (subdomain == subdomain_from(host)) ||
96
+ (!has_subdomain?(subdomain) && !has_subdomain?(subdomain_from(host)))
97
+ end
98
+
99
+ def self.override_only_path?
100
+ self.override_only_path
101
+ end
102
+
103
+ def self.needs_rewrite?(subdomain, host)
104
+ case subdomain
105
+ when nil
106
+ #rewrite when there is a preferred mirror set and there is no subdomain on the host
107
+ return true if self.preferred_mirror && subdomain_from(host).nil?
108
+ return false
109
+ when false
110
+ h = subdomain_from(host)
111
+ #if the host has a subdomain
112
+ if !h.nil?
113
+ #rewrite when there is a subdomain in the host, and it is not a preferred mirror
114
+ return true if !preferred_mirror?(h)
115
+ #rewrite when there is a preferred mirror set and the subdomain of the host is not a mirror
116
+ return true if self.preferred_mirror && !is_mirror?(h)
117
+ #no rewrite if host already has mirror subdomain
118
+ #it { SubdomainFu.needs_rewrite?(false,"www.localhost").should be_false }
119
+ return false if is_mirror?(h)
120
+ end
121
+ return self.crazy_rewrite_rule(subdomain, host)
122
+ else
123
+ return self.crazy_rewrite_rule(subdomain, host)
124
+ end
125
+ end
126
+
127
+ #This is a black box of crazy! So I split some of the simpler logic out into the case statement above to make my brain happy!
128
+ def self.crazy_rewrite_rule(subdomain, host)
129
+ (!has_subdomain?(subdomain) && preferred_mirror?(subdomain) && !preferred_mirror?(subdomain_from(host))) ||
130
+ !same_subdomain?(subdomain, host)
131
+ end
132
+
133
+ def self.current_subdomain(request)
134
+ subdomain = request.subdomains(SubdomainFu.tld_size).join(".")
135
+ if has_subdomain?(subdomain)
136
+ subdomain
137
+ else
138
+ nil
139
+ end
140
+ end
141
+
142
+ #Enables subdomain-fu to more completely replace DHH's account_location plugin
143
+ def self.current_domain(request)
144
+ domain = ""
145
+ domain << request.subdomains[1..-1].join(".") + "." if request.subdomains.length > 1
146
+ domain << request.domain + request.port_string
147
+ end
148
+
149
+ module Controller
150
+ def self.included(controller)
151
+ controller.helper_method(:current_subdomain)
152
+ controller.helper_method(:current_domain)
153
+ end
154
+
155
+ protected
156
+ def current_subdomain
157
+ SubdomainFu.current_subdomain(request)
158
+ end
159
+ def current_domain
160
+ SubdomainFu.current_domain(request)
161
+ end
162
+ end
163
+ end
@@ -0,0 +1,61 @@
1
+ # Thanks to Jamis Buck for ideas on this stuff
2
+ # http://weblog.jamisbuck.org/2006/10/26/monkey-patching-rails-extending-routes-2
3
+ # This is not yet a working part of SubdomainFu.
4
+
5
+ module SubdomainFu
6
+ module RouteExtensions
7
+ def self.included(base)
8
+ base.alias_method_chain :recognition_conditions, :subdomain
9
+ end
10
+
11
+ def recognition_conditions_with_subdomain
12
+ result = recognition_conditions_without_subdomain
13
+ result << "conditions[:subdomain] === env[:subdomain]" if conditions[:subdomain] && conditions[:subdomain] != true && conditions[:subdomain] != false
14
+ result << "SubdomainFu.has_subdomain?(env[:subdomain])" if conditions[:subdomain] == true
15
+ result << "!SubdomainFu.has_subdomain?(env[:subdomain])" if conditions[:subdomain] == false
16
+ result
17
+ end
18
+ end
19
+
20
+ module RouteSetExtensions
21
+ def self.included(base)
22
+ base.alias_method_chain :extract_request_environment, :subdomain
23
+ end
24
+
25
+ def extract_request_environment_with_subdomain(request)
26
+ env = extract_request_environment_without_subdomain(request)
27
+ env.merge(:host => request.host, :domain => request.domain, :subdomain => SubdomainFu.current_subdomain(request))
28
+ end
29
+ end
30
+
31
+ module MapperExtensions
32
+ def quick_map(has_unless, *args, &block)
33
+ options = args.find{|a| a.is_a?(Hash)}
34
+ namespace_str = options ? options.delete(:namespace).to_s : args.join('_or_')
35
+ namespace_str += '_' unless namespace_str.blank?
36
+ mapped_exp = args.map(&:to_s).join('|')
37
+ conditions_hash = { :subdomain => ( has_unless ? /[^(#{mapped_exp})]/ : /(#{mapped_exp})/) }
38
+ with_options(:conditions => conditions_hash, :name_prefix => namespace_str, &block)
39
+ end
40
+ # Adds methods to Mapper to apply an options with a method. Example
41
+ # map.subdomain :blog { |blog| blog.resources :pages }
42
+ # or
43
+ # map.unless_subdomain :blog { |not_blog| not_blog.resources :people }
44
+ def subdomain(*args, &block)
45
+ quick_map(false, *args, &block)
46
+ end
47
+ def unless_subdomain(*args, &block)
48
+ quick_map(true, *args, &block)
49
+ end
50
+ end
51
+ end
52
+
53
+ ActionController::Routing::RouteSet::Mapper.send :include, SubdomainFu::MapperExtensions
54
+ ActionController::Routing::RouteSet.send :include, SubdomainFu::RouteSetExtensions
55
+ ActionController::Routing::Route.send :include, SubdomainFu::RouteExtensions
56
+
57
+ # UrlRewriter::RESERVED_OPTIONS is only available in Rails >= 2.2
58
+ # http://www.portallabs.com/blog/2008/12/02/fixing-subdomain_fu-with-named-routes-rails-22/
59
+ if Rails::VERSION::MAJOR >= 2 and Rails::VERSION::MINOR >= 2
60
+ ActionController::UrlRewriter::RESERVED_OPTIONS << :subdomain
61
+ end
@@ -0,0 +1,48 @@
1
+ module ActionController
2
+ module UrlWriter
3
+ def url_for_with_subdomains(options)
4
+ if SubdomainFu.needs_rewrite?(options[:subdomain], options[:host] || default_url_options[:host]) || options[:only_path] == false
5
+ options[:only_path] = false if SubdomainFu.override_only_path?
6
+ options[:host] = SubdomainFu.rewrite_host_for_subdomains(options.delete(:subdomain), options[:host] || default_url_options[:host])
7
+ else
8
+ options.delete(:subdomain)
9
+ end
10
+ url_for_without_subdomains(options)
11
+ end
12
+ alias_method_chain :url_for, :subdomains
13
+ end
14
+
15
+ class UrlRewriter #:nodoc:
16
+ private
17
+
18
+ def rewrite_url_with_subdomains(options)
19
+ if SubdomainFu.needs_rewrite?(options[:subdomain], (options[:host] || @request.host_with_port)) || options[:only_path] == false
20
+ options[:only_path] = false if SubdomainFu.override_only_path?
21
+ options[:host] = SubdomainFu.rewrite_host_for_subdomains(options.delete(:subdomain), options[:host] || @request.host_with_port)
22
+ # puts "options[:host]: #{options[:host].inspect}"
23
+ else
24
+ options.delete(:subdomain)
25
+ end
26
+ rewrite_url_without_subdomains(options)
27
+ end
28
+ alias_method_chain :rewrite_url, :subdomains
29
+ end
30
+
31
+ if Rails::VERSION::MAJOR >= 2 and Rails::VERSION::MINOR <= 1
32
+ # hack for http://www.portallabs.com/blog/2008/10/22/fixing-subdomain_fu-with-named-routes/
33
+ module Routing
34
+ module Optimisation
35
+ class PositionalArgumentsWithAdditionalParams
36
+ def guard_condition_with_subdomains
37
+ # don't allow optimisation if a subdomain is present - fixes a problem
38
+ # with the subdomain appearing in the query instead of being rewritten
39
+ # see http://mbleigh.lighthouseapp.com/projects/13148/tickets/8-improper-generated-urls-with-named-routes-for-a-singular-resource
40
+ guard_condition_without_subdomains + " && !args.last.has_key?(:subdomain)"
41
+ end
42
+
43
+ alias_method_chain :guard_condition, :subdomains
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
data/rails/init.rb ADDED
@@ -0,0 +1,6 @@
1
+ #Allow whatever Ruby Package tool is being used ot manage load paths. gem auto adds the gem's lib dir to load path.
2
+ require 'subdomain-fu' unless defined?(SubdomainFu)
3
+
4
+ ActionController::Base.send :include, SubdomainFu::Controller
5
+
6
+ RAILS_DEFAULT_LOGGER.info("** SubdomainFu: initialized properly")
data/spec/spec.opts ADDED
@@ -0,0 +1,7 @@
1
+ --colour
2
+ --format
3
+ specdoc
4
+ --loadby
5
+ mtime
6
+ --reverse
7
+ --backtrace
@@ -0,0 +1,42 @@
1
+ begin
2
+ require File.dirname(__FILE__) + '/../../../../spec/spec_helper'
3
+ rescue LoadError
4
+ puts "You need to install rspec in your base app"
5
+ exit
6
+ end
7
+
8
+ plugin_spec_dir = File.dirname(__FILE__)
9
+ ActiveRecord::Base.logger = Logger.new(plugin_spec_dir + "/debug.log")
10
+
11
+ ActionController::Routing::Routes.draw do |map|
12
+ map.needs_subdomain '/needs_subdomain', :controller => "fu", :action => "awesome"
13
+ map.no_subdomain '/no_subdomain', :controller => "fu", :action => "lame"
14
+ map.needs_awesome '/needs_awesome', :controller => "fu", :action => "lame"
15
+
16
+ map.resources :foos do |fu|
17
+ fu.resources :bars
18
+ end
19
+
20
+ map.connect '/', :controller => "site", :action => "home", :conditions => {:subdomain => false}
21
+ map.connect '/', :controller => "app", :action => "home", :conditions => {:subdomain => true}
22
+ map.connect '/', :controller => "mobile", :action => "home", :conditions => {:subdomain => "m"}
23
+
24
+ map.connect '/subdomain_here', :controller => "app", :action => "success", :conditions => {:subdomain => true}
25
+ map.connect '/no_subdomain_here', :controller => "site", :action => "success", :conditions => {:subdomain => false}
26
+ map.connect '/m_subdomain_here', :controller => "mobile", :action => "success", :conditions => {:subdomain => "m"}
27
+ map.connect '/numbers_only_here', :controller => "numbers", :action => "success", :conditions => {:subdomain => /[0-9]+/}
28
+
29
+ map.connect '/:controller/:action/:id'
30
+ end
31
+
32
+ class Paramed
33
+ def initialize(param)
34
+ @param = param
35
+ end
36
+
37
+ def to_param
38
+ @param || "param"
39
+ end
40
+ end
41
+
42
+ include ActionController::UrlWriter
@@ -0,0 +1,251 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe "SubdomainFu" do
4
+ before do
5
+ SubdomainFu.tld_sizes = SubdomainFu::DEFAULT_TLD_SIZES.dup
6
+ SubdomainFu.mirrors = SubdomainFu::DEFAULT_MIRRORS.dup
7
+ SubdomainFu.preferred_mirror = nil
8
+ end
9
+
10
+ describe "TLD Sizes" do
11
+ before do
12
+ SubdomainFu.tld_sizes = SubdomainFu::DEFAULT_TLD_SIZES.dup
13
+ end
14
+
15
+ it { SubdomainFu.tld_sizes.should be_kind_of(Hash) }
16
+
17
+ it "should have default values for development, test, and production" do
18
+ SubdomainFu.tld_sizes[:development].should == 0
19
+ SubdomainFu.tld_sizes[:test].should == 0
20
+ SubdomainFu.tld_sizes[:production].should == 1
21
+ end
22
+
23
+ it "#tld_size should be for the current environment" do
24
+ SubdomainFu.tld_size.should == SubdomainFu.tld_sizes[RAILS_ENV.to_sym]
25
+ end
26
+
27
+ it "should be able to be set for the current environment" do
28
+ SubdomainFu.tld_size = 5
29
+ SubdomainFu.tld_size.should == 5
30
+ SubdomainFu.tld_sizes[:test].should == 5
31
+ end
32
+ end
33
+
34
+ describe "#has_subdomain?" do
35
+ it "should be true for non-mirrored subdomains" do
36
+ SubdomainFu.has_subdomain?("awesome").should be_true
37
+ end
38
+
39
+ it "should be false for mirrored subdomains" do
40
+ SubdomainFu.has_subdomain?(SubdomainFu.mirrors.first).should be_false
41
+ end
42
+
43
+ it "shoud be false for a nil or blank subdomain" do
44
+ SubdomainFu.has_subdomain?("").should be_false
45
+ SubdomainFu.has_subdomain?(nil).should be_false
46
+ SubdomainFu.has_subdomain?(false).should be_false
47
+ end
48
+ end
49
+
50
+ describe "#subdomain_from" do
51
+ it "should return the subdomain based on the TLD of the current environment" do
52
+ SubdomainFu.subdomain_from("awesome.localhost").should == "awesome"
53
+ SubdomainFu.tld_size = 2
54
+ SubdomainFu.subdomain_from("awesome.localhost.co.uk").should == "awesome"
55
+ SubdomainFu.tld_size = 1
56
+ SubdomainFu.subdomain_from("awesome.localhost.com").should == "awesome"
57
+ SubdomainFu.tld_size = 0
58
+ end
59
+
60
+ it "should join deep subdomains with a period" do
61
+ SubdomainFu.subdomain_from("awesome.coolguy.localhost").should == "awesome.coolguy"
62
+ end
63
+
64
+ it "should return nil for no subdomain" do
65
+ SubdomainFu.subdomain_from("localhost").should be_nil
66
+ end
67
+ end
68
+
69
+ it "#host_without_subdomain should chop of the subdomain and return the rest" do
70
+ SubdomainFu.host_without_subdomain("awesome.localhost:3000").should == "localhost:3000"
71
+ SubdomainFu.host_without_subdomain("something.awful.localhost:3000").should == "localhost:3000"
72
+ end
73
+
74
+ describe "#preferred_mirror?" do
75
+ describe "when preferred_mirror is false" do
76
+ before do
77
+ SubdomainFu.preferred_mirror = false
78
+ end
79
+
80
+ it "should return true for false" do
81
+ SubdomainFu.preferred_mirror?(false).should be_true
82
+ end
83
+ end
84
+ end
85
+
86
+ describe "#rewrite_host_for_subdomains" do
87
+ it "should not change the same subdomain" do
88
+ SubdomainFu.rewrite_host_for_subdomains("awesome","awesome.localhost").should == "awesome.localhost"
89
+ end
90
+
91
+ it "should not change an equivalent (mirrored) subdomain" do
92
+ SubdomainFu.rewrite_host_for_subdomains("www","localhost").should == "localhost"
93
+ end
94
+
95
+ it "should change the subdomain if it's different" do
96
+ SubdomainFu.rewrite_host_for_subdomains("cool","www.localhost").should == "cool.localhost"
97
+ end
98
+
99
+ it "should remove the subdomain if passed false when it's not a mirror" do
100
+ SubdomainFu.rewrite_host_for_subdomains(false,"cool.localhost").should == "localhost"
101
+ end
102
+
103
+ it "should not remove the subdomain if passed false when it is a mirror" do
104
+ SubdomainFu.rewrite_host_for_subdomains(false,"www.localhost").should == "www.localhost"
105
+ end
106
+
107
+ it "should not remove the subdomain if passed nil when it's not a mirror" do
108
+ SubdomainFu.rewrite_host_for_subdomains(nil,"cool.localhost").should == "cool.localhost"
109
+ end
110
+
111
+ describe "when preferred_mirror is false" do
112
+ before do
113
+ SubdomainFu.preferred_mirror = false
114
+ end
115
+
116
+ it "should remove the subdomain if passed false when it is a mirror" do
117
+ SubdomainFu.rewrite_host_for_subdomains(false,"www.localhost").should == "localhost"
118
+ end
119
+
120
+ it "should not remove the subdomain if passed nil when it's not a mirror" do
121
+ SubdomainFu.rewrite_host_for_subdomains(nil,"cool.localhost").should == "cool.localhost"
122
+ end
123
+ end
124
+ end
125
+
126
+ describe "#change_subdomain_of_host" do
127
+ it "should change it if passed a different one" do
128
+ SubdomainFu.change_subdomain_of_host("awesome","cool.localhost").should == "awesome.localhost"
129
+ end
130
+
131
+ it "should remove it if passed nil" do
132
+ SubdomainFu.change_subdomain_of_host(nil,"cool.localhost").should == "localhost"
133
+ end
134
+
135
+ it "should add it if there isn't one" do
136
+ SubdomainFu.change_subdomain_of_host("awesome","localhost").should == "awesome.localhost"
137
+ end
138
+
139
+ it "should use to_param on the object passed to subdomain if it respond to it" do
140
+ @some_other_object = Paramed.new("p_is_awesome")
141
+
142
+ SubdomainFu.change_subdomain_of_host(@some_other_object,"localhost").should == "p_is_awesome.localhost"
143
+ end
144
+
145
+ end
146
+
147
+ describe "#current_subdomain" do
148
+ it "should return the current subdomain if there is one" do
149
+ request = mock("request", :subdomains => ["awesome"])
150
+ SubdomainFu.current_subdomain(request).should == "awesome"
151
+ end
152
+
153
+ it "should return nil if there's no subdomain" do
154
+ request = mock("request", :subdomains => [])
155
+ SubdomainFu.current_subdomain(request).should be_nil
156
+ end
157
+
158
+ it "should return nil if the current subdomain is a mirror" do
159
+ request = mock("request", :subdomains => ["www"])
160
+ SubdomainFu.current_subdomain(request).should be_nil
161
+ end
162
+
163
+ it "should return the whole thing (including a .) if there's multiple subdomains" do
164
+ request = mock("request", :subdomains => ["awesome","rad"])
165
+ SubdomainFu.current_subdomain(request).should == "awesome.rad"
166
+ end
167
+ end
168
+
169
+ describe "#current_domain" do
170
+ it "should return the current domain if there is one" do
171
+ request = mock("request", :subdomains => [], :domain => "example.com", :port_string => "")
172
+ SubdomainFu.current_domain(request).should == "example.com"
173
+ end
174
+
175
+ it "should return empty string if there is no domain" do
176
+ request = mock("request", :subdomains => [], :domain => "", :port_string => "")
177
+ SubdomainFu.current_domain(request).should == ""
178
+ end
179
+
180
+ it "should return the current domain if there is only one level of subdomains" do
181
+ request = mock("request", :subdomains => ["www"], :domain => "example.com", :port_string => "")
182
+ SubdomainFu.current_domain(request).should == "example.com"
183
+ end
184
+
185
+ it "should return everything but the first level of subdomain when there are multiple levels of subdomains" do
186
+ request = mock("request", :subdomains => ["awesome","rad","cheese","chevy","ford"], :domain => "example.com", :port_string => "")
187
+ SubdomainFu.current_domain(request).should == "rad.cheese.chevy.ford.example.com"
188
+ end
189
+
190
+ it "should return the domain with port if port is given" do
191
+ request = mock("request", :subdomains => ["awesome","rad","cheese","chevy","ford"], :domain => "example.com", :port_string => ":3000")
192
+ SubdomainFu.current_domain(request).should == "rad.cheese.chevy.ford.example.com:3000"
193
+ end
194
+ end
195
+
196
+ describe "#same_subdomain?" do
197
+ it { SubdomainFu.same_subdomain?("www","www.localhost").should be_true }
198
+ it { SubdomainFu.same_subdomain?("www","localhost").should be_true }
199
+ it { SubdomainFu.same_subdomain?("awesome","www.localhost").should be_false }
200
+ it { SubdomainFu.same_subdomain?("cool","awesome.localhost").should be_false }
201
+ it { SubdomainFu.same_subdomain?(nil,"www.localhost").should be_true }
202
+ it { SubdomainFu.same_subdomain?("www","awesome.localhost").should be_false }
203
+ end
204
+
205
+ describe "#needs_rewrite?" do
206
+ it { SubdomainFu.needs_rewrite?("www","www.localhost").should be_false }
207
+ it { SubdomainFu.needs_rewrite?("www","localhost").should be_false }
208
+ it { SubdomainFu.needs_rewrite?("awesome","www.localhost").should be_true }
209
+ it { SubdomainFu.needs_rewrite?("cool","awesome.localhost").should be_true }
210
+ it { SubdomainFu.needs_rewrite?(nil,"www.localhost").should be_false }
211
+ it { SubdomainFu.needs_rewrite?(nil,"awesome.localhost").should be_false }
212
+ it { SubdomainFu.needs_rewrite?(false,"awesome.localhost").should be_true }
213
+ it { SubdomainFu.needs_rewrite?(false,"www.localhost").should be_false }
214
+ it { SubdomainFu.needs_rewrite?("www","awesome.localhost").should be_true }
215
+
216
+ describe "when preferred_mirror is false" do
217
+ before do
218
+ SubdomainFu.preferred_mirror = false
219
+ end
220
+
221
+ it { SubdomainFu.needs_rewrite?("www","www.localhost").should be_false }
222
+ it { SubdomainFu.needs_rewrite?("www","localhost").should be_false }
223
+ it { SubdomainFu.needs_rewrite?("awesome","www.localhost").should be_true }
224
+ it { SubdomainFu.needs_rewrite?("cool","awesome.localhost").should be_true }
225
+ it { SubdomainFu.needs_rewrite?(nil,"www.localhost").should be_false }
226
+ it { SubdomainFu.needs_rewrite?(nil,"awesome.localhost").should be_false }
227
+ it { SubdomainFu.needs_rewrite?(false,"awesome.localhost").should be_true }
228
+ #Only one different from default set of tests
229
+ it { SubdomainFu.needs_rewrite?(false,"www.localhost").should be_true }
230
+ it { SubdomainFu.needs_rewrite?("www","awesome.localhost").should be_true }
231
+ end
232
+
233
+ describe "when preferred_mirror is string" do
234
+ before do
235
+ SubdomainFu.preferred_mirror = "www"
236
+ end
237
+
238
+ it { SubdomainFu.needs_rewrite?("www","www.localhost").should be_false }
239
+ it { SubdomainFu.needs_rewrite?("awesome","www.localhost").should be_true }
240
+ # Following is different from default set of tests
241
+ it { SubdomainFu.needs_rewrite?("www","localhost").should be_true }
242
+ it { SubdomainFu.needs_rewrite?("cool","awesome.localhost").should be_true }
243
+ it { SubdomainFu.needs_rewrite?(nil,"www.localhost").should be_false }
244
+ it { SubdomainFu.needs_rewrite?(nil,"awesome.localhost").should be_false }
245
+ it { SubdomainFu.needs_rewrite?(false,"awesome.localhost").should be_true }
246
+ it { SubdomainFu.needs_rewrite?(false,"www.localhost").should be_false }
247
+ it { SubdomainFu.needs_rewrite?("www","awesome.localhost").should be_true }
248
+ end
249
+
250
+ end
251
+ end
@@ -0,0 +1,149 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe "SubdomainFu URL Writing" do
4
+ before do
5
+ SubdomainFu.tld_size = 1
6
+ SubdomainFu.mirrors = SubdomainFu::DEFAULT_MIRRORS.dup
7
+ SubdomainFu.override_only_path = true
8
+ SubdomainFu.preferred_mirror = nil
9
+ default_url_options[:host] = "example.com"
10
+ end
11
+
12
+ describe "#url_for" do
13
+ it "should be able to add a subdomain" do
14
+ url_for(:controller => "something", :action => "other", :subdomain => "awesome").should == "http://awesome.example.com/something/other"
15
+ end
16
+
17
+ it "should be able to remove a subdomain" do
18
+ url_for(:controller => "something", :action => "other", :subdomain => false, :host => "awesome.example.com").should == "http://example.com/something/other"
19
+ end
20
+
21
+ it "should not change a mirrored subdomain" do
22
+ url_for(:controller => "something", :action => "other", :subdomain => false, :host => "www.example.com").should == "http://www.example.com/something/other"
23
+ end
24
+
25
+ it "should should not force the full url with :only_path if override_only_path is false (default)" do
26
+ SubdomainFu.override_only_path = false
27
+ url_for(:controller => "something", :action => "other", :subdomain => "awesome", :only_path => true).should == "/something/other"
28
+ end
29
+
30
+ it "should should force the full url, even with :only_path if override_only_path is true" do
31
+ SubdomainFu.override_only_path = true
32
+ url_for(:controller => "something", :action => "other", :subdomain => "awesome", :only_path => true).should == "http://awesome.example.com/something/other"
33
+ end
34
+ end
35
+
36
+ describe "Standard Routes" do
37
+ it "should be able to add a subdomain" do
38
+ needs_subdomain_url(:subdomain => "awesome").should == "http://awesome.example.com/needs_subdomain"
39
+ end
40
+
41
+ it "should be able to remove a subdomain" do
42
+ default_url_options[:host] = "awesome.example.com"
43
+ needs_subdomain_url(:subdomain => false).should == "http://example.com/needs_subdomain"
44
+ end
45
+
46
+ it "should not change a mirrored subdomain" do
47
+ default_url_options[:host] = "www.example.com"
48
+ needs_subdomain_url(:subdomain => false).should == "http://www.example.com/needs_subdomain"
49
+ end
50
+
51
+ it "should should force the full url, even with _path" do
52
+ needs_subdomain_path(:subdomain => "awesome").should == needs_subdomain_url(:subdomain => "awesome")
53
+ end
54
+
55
+ it "should not force the full url if it's the same as the current subdomain" do
56
+ default_url_options[:host] = "awesome.example.com"
57
+ needs_subdomain_path(:subdomain => "awesome").should == "/needs_subdomain"
58
+ end
59
+
60
+ it "should force the full url if it's a different subdomain" do
61
+ default_url_options[:host] = "awesome.example.com"
62
+ needs_subdomain_path(:subdomain => "crazy").should == "http://crazy.example.com/needs_subdomain"
63
+ end
64
+
65
+ it "should not force the full url if the current subdomain is nil and so is the target" do
66
+ needs_subdomain_path(:subdomain => nil).should == "/needs_subdomain"
67
+ end
68
+
69
+ it "should not force the full url if no :subdomain option is given" do
70
+ needs_subdomain_path.should == "/needs_subdomain"
71
+ default_url_options[:host] = "awesome.example.com"
72
+ needs_subdomain_path.should == "/needs_subdomain"
73
+ end
74
+ end
75
+
76
+ describe "Resourced Routes" do
77
+ it "should be able to add a subdomain" do
78
+ foo_path(:id => "something", :subdomain => "awesome").should == "http://awesome.example.com/foos/something"
79
+ end
80
+
81
+ it "should be able to remove a subdomain" do
82
+ default_url_options[:host] = "awesome.example.com"
83
+ foo_path(:id => "something", :subdomain => false).should == "http://example.com/foos/something"
84
+ end
85
+
86
+ it "should work when passed in a paramable object" do
87
+ foo_path(Paramed.new("something"), :subdomain => "awesome").should == "http://awesome.example.com/foos/something"
88
+ end
89
+
90
+ it "should work when passed in a paramable object" do
91
+ foo_path(Paramed.new("something"), :subdomain => "awesome").should == "http://awesome.example.com/foos/something"
92
+ end
93
+
94
+ it "should work when passed in a paramable object and no subdomain to a _path" do
95
+ default_url_options[:host] = "awesome.example.com"
96
+ foo_path(Paramed.new("something")).should == "/foos/something"
97
+ end
98
+
99
+ it "should work when passed in a paramable object and no subdomain to a _url" do
100
+ default_url_options[:host] = "awesome.example.com"
101
+ foo_url(Paramed.new("something")).should == "http://awesome.example.com/foos/something"
102
+ end
103
+
104
+ it "should work on nested resource collections" do
105
+ foo_bars_path(Paramed.new("something"), :subdomain => "awesome").should == "http://awesome.example.com/foos/something/bars"
106
+ end
107
+
108
+ it "should work on nested resource members" do
109
+ foo_bar_path(Paramed.new("something"),Paramed.new("else"), :subdomain => "awesome").should == "http://awesome.example.com/foos/something/bars/else"
110
+ end
111
+ end
112
+
113
+ describe "Preferred Mirror" do
114
+ before do
115
+ SubdomainFu.preferred_mirror = "www"
116
+ SubdomainFu.override_only_path = true
117
+ end
118
+
119
+ it "should switch to the preferred mirror instead of no subdomain" do
120
+ default_url_options[:host] = "awesome.example.com"
121
+ needs_subdomain_url(:subdomain => false).should == "http://www.example.com/needs_subdomain"
122
+ end
123
+
124
+ it "should switch to the preferred mirror automatically" do
125
+ default_url_options[:host] = "example.com"
126
+ needs_subdomain_url.should == "http://www.example.com/needs_subdomain"
127
+ end
128
+
129
+ it "should work when passed in a paramable object and no subdomain to a _url" do
130
+ default_url_options[:host] = "awesome.example.com"
131
+ foo_url(Paramed.new("something")).should == "http://awesome.example.com/foos/something"
132
+ end
133
+
134
+ it "should force a switch to no subdomain on a mirror if preferred_mirror is false" do
135
+ SubdomainFu.preferred_mirror = false
136
+ default_url_options[:host] = "www.example.com"
137
+ needs_subdomain_url(:subdomain => false).should == "http://example.com/needs_subdomain"
138
+ end
139
+
140
+ after do
141
+ SubdomainFu.preferred_mirror = nil
142
+ end
143
+ end
144
+
145
+ after do
146
+ SubdomainFu.tld_size = 0
147
+ default_url_options[:host] = "localhost"
148
+ end
149
+ end
metadata ADDED
@@ -0,0 +1,76 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gameplan-subdomain-fu
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 5
8
+ - 4
9
+ version: 0.5.4
10
+ platform: ruby
11
+ authors:
12
+ - Michael Bleigh
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-05-12 00:00:00 +08:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description: SubdomainFu is a Rails plugin to provide all of the basic functionality necessary to handle multiple subdomain applications (such as Basecamp-esque subdomain accounts and more).
22
+ email: michael@intridea.com
23
+ executables: []
24
+
25
+ extensions: []
26
+
27
+ extra_rdoc_files:
28
+ - README.rdoc
29
+ files:
30
+ - CHANGELOG
31
+ - MIT-LICENSE
32
+ - README.rdoc
33
+ - Rakefile
34
+ - VERSION.yml
35
+ - lib/subdomain-fu.rb
36
+ - lib/subdomain_fu/routing_extensions.rb
37
+ - lib/subdomain_fu/url_rewriter.rb
38
+ - rails/init.rb
39
+ - spec/spec.opts
40
+ - spec/spec_helper.rb
41
+ - spec/subdomain_fu_spec.rb
42
+ - spec/url_rewriter_spec.rb
43
+ has_rdoc: true
44
+ homepage: http://github.com/mbleigh/subdomain-fu
45
+ licenses: []
46
+
47
+ post_install_message:
48
+ rdoc_options:
49
+ - --charset=UTF-8
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ segments:
57
+ - 0
58
+ version: "0"
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ segments:
64
+ - 0
65
+ version: "0"
66
+ requirements: []
67
+
68
+ rubyforge_project: subdomain-fu
69
+ rubygems_version: 1.3.6
70
+ signing_key:
71
+ specification_version: 3
72
+ summary: SubdomainFu is a Rails plugin that provides subdomain routing and URL writing helpers.
73
+ test_files:
74
+ - spec/spec_helper.rb
75
+ - spec/subdomain_fu_spec.rb
76
+ - spec/url_rewriter_spec.rb