subdomain-fu 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG ADDED
@@ -0,0 +1,13 @@
1
+ == 2009-08-26
2
+
3
+ * Fixed needs_rewrite? method
4
+ * Added is_mirror? method
5
+ * Added tests, and fixed failing tests
6
+
7
+ == 2009-08-24
8
+
9
+ * Merged forks that added lots of features, tests, and fixes
10
+
11
+ == 2008-06-25
12
+
13
+ * 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,96 @@
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 GemPlugin, add it to your environment.rb:
16
+
17
+ config.gem 'mbleigh-subdomain-fu', :source => "http://gems.github.com", :lib => "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
+ == Configuration
49
+
50
+ You may need to configure SubdomainFu based on your development setup. The
51
+ configuration required is:
52
+
53
+ === TLD Size
54
+
55
+ A hash for each environment of the size of the top-level domain name.
56
+ (something.com = 1, localhost = 0, etc.)
57
+
58
+ SubdomainFu.tld_size = 1 # sets for current environment
59
+ SubdomainFu.tld_sizes = {:development => 0,
60
+ :test => 0,
61
+ :production => 1} # set all at once (also the defaults)
62
+
63
+ === Mirrors
64
+
65
+ Mirrors are the subdomains that are equivalent to no subdomain (i.e. they 'mirror')
66
+ the usage of the root domain.
67
+
68
+ SubdomainFu.mirrors = %w(www site we) # Defaults to %w(www)
69
+
70
+ === Preferred Mirror
71
+
72
+ SubdomainFu also understands the notion of a 'preferred mirror', that is, if you
73
+ always want your links going to 'www.yourdomain.com' instead of 'yourdomain.com',
74
+ you can set the preferred mirror like so:
75
+
76
+ SubdomainFu.preferred_mirror = "www"
77
+
78
+ Now when you create a link with subdomain => false in the options the subdomain
79
+ will default to the preferred mirror.
80
+
81
+ == Routing
82
+
83
+ 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 routes.rb file:
84
+
85
+ map.with_options :conditions => {:subdomain => 'admin} do |admin|
86
+ admin.resources :posts
87
+ admin.resources :users
88
+ end
89
+
90
+ == Resources
91
+
92
+ * GitHub Repository: http://github.com/mbleigh/subdomain-fu
93
+ * RDocs: http://rdoc.info/projects/mbleigh/subdomain-fu
94
+
95
+ Copyright (c) 2008 Michael Bleigh (http://www.mbleigh.com/) and
96
+ Intridea, Inc. (http://www.intridea.com/). Released under the MIT license
data/Rakefile ADDED
@@ -0,0 +1,27 @@
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.summary = "SubdomainFu is a Rails plugin that provides subdomain routing and URL writing helpers."
18
+ gemspec.email = "michael@intridea.com"
19
+ gemspec.homepage = "http://github.com/mbleigh/subdomain-fu"
20
+ gemspec.files = FileList["[A-Z]*", "{lib,spec,rails}/**/*"] - FileList["**/*.log"]
21
+ 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)."
22
+ gemspec.authors = ["Michael Bleigh"]
23
+ end
24
+ rescue LoadError
25
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
26
+ end
27
+
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :minor: 4
3
+ :patch: 0
4
+ :major: 0
@@ -0,0 +1,150 @@
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
+ host = SubdomainFu.host_without_subdomain(host)
86
+ host = "#{subdomain}.#{host}" if subdomain
87
+ host
88
+ end
89
+
90
+ # Is this subdomain equivalent to the subdomain found in this host string?
91
+ def self.same_subdomain?(subdomain, host)
92
+ subdomain = nil unless subdomain
93
+ (subdomain == subdomain_from(host)) ||
94
+ (!has_subdomain?(subdomain) && !has_subdomain?(subdomain_from(host)))
95
+ end
96
+
97
+ def self.override_only_path?
98
+ self.override_only_path
99
+ end
100
+
101
+ def self.needs_rewrite?(subdomain, host)
102
+ case subdomain
103
+ when nil
104
+ #rewrite when there is a preferred mirror set and there is no subdomain on the host
105
+ return true if self.preferred_mirror && subdomain_from(host).nil?
106
+ return false
107
+ when false
108
+ h = subdomain_from(host)
109
+ #if the host has a subdomain
110
+ if !h.nil?
111
+ #rewrite when there is a subdomain in the host, and it is not a preferred mirror
112
+ return true if !preferred_mirror?(h)
113
+ #rewrite when there is a preferred mirror set and the subdomain of the host is not a mirror
114
+ return true if self.preferred_mirror && !is_mirror?(h)
115
+ #no rewrite if host already has mirror subdomain
116
+ #it { SubdomainFu.needs_rewrite?(false,"www.localhost").should be_false }
117
+ return false if is_mirror?(h)
118
+ end
119
+ return self.crazy_rewrite_rule(subdomain, host)
120
+ else
121
+ return self.crazy_rewrite_rule(subdomain, host)
122
+ end
123
+ end
124
+
125
+ #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!
126
+ def self.crazy_rewrite_rule(subdomain, host)
127
+ (!has_subdomain?(subdomain) && preferred_mirror?(subdomain) && !preferred_mirror?(subdomain_from(host))) ||
128
+ !same_subdomain?(subdomain, host)
129
+ end
130
+
131
+ def self.current_subdomain(request)
132
+ subdomain = request.subdomains(SubdomainFu.tld_size).join(".")
133
+ if has_subdomain?(subdomain)
134
+ subdomain
135
+ else
136
+ nil
137
+ end
138
+ end
139
+
140
+ module Controller
141
+ def self.included(controller)
142
+ controller.helper_method(:current_subdomain)
143
+ end
144
+
145
+ protected
146
+ def current_subdomain
147
+ SubdomainFu.current_subdomain(request)
148
+ end
149
+ end
150
+ 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.subdomain_from(request.host))
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,8 @@
1
+ # Add this path to ruby load path
2
+ $:.unshift "#{File.dirname(__FILE__)}/../lib"
3
+
4
+ require 'subdomain-fu' unless defined?(SubdomainFu)
5
+
6
+ ActionController::Base.send :include, SubdomainFu::Controller
7
+
8
+ 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,217 @@
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
+ end
139
+
140
+ describe "#current_subdomain" do
141
+ it "should return the current subdomain if there is one" do
142
+ request = mock("request", :subdomains => ["awesome"])
143
+ SubdomainFu.current_subdomain(request).should == "awesome"
144
+ end
145
+
146
+ it "should return nil if there's no subdomain" do
147
+ request = mock("request", :subdomains => [])
148
+ SubdomainFu.current_subdomain(request).should be_nil
149
+ end
150
+
151
+ it "should return nil if the current subdomain is a mirror" do
152
+ request = mock("request", :subdomains => ["www"])
153
+ SubdomainFu.current_subdomain(request).should be_nil
154
+ end
155
+
156
+ it "should return the whole thing (including a .) if there's multiple subdomains" do
157
+ request = mock("request", :subdomains => ["awesome","rad"])
158
+ SubdomainFu.current_subdomain(request).should == "awesome.rad"
159
+ end
160
+ end
161
+
162
+ describe "#same_subdomain?" do
163
+ it { SubdomainFu.same_subdomain?("www","www.localhost").should be_true }
164
+ it { SubdomainFu.same_subdomain?("www","localhost").should be_true }
165
+ it { SubdomainFu.same_subdomain?("awesome","www.localhost").should be_false }
166
+ it { SubdomainFu.same_subdomain?("cool","awesome.localhost").should be_false }
167
+ it { SubdomainFu.same_subdomain?(nil,"www.localhost").should be_true }
168
+ it { SubdomainFu.same_subdomain?("www","awesome.localhost").should be_false }
169
+ end
170
+
171
+ describe "#needs_rewrite?" do
172
+ it { SubdomainFu.needs_rewrite?("www","www.localhost").should be_false }
173
+ it { SubdomainFu.needs_rewrite?("www","localhost").should be_false }
174
+ it { SubdomainFu.needs_rewrite?("awesome","www.localhost").should be_true }
175
+ it { SubdomainFu.needs_rewrite?("cool","awesome.localhost").should be_true }
176
+ it { SubdomainFu.needs_rewrite?(nil,"www.localhost").should be_false }
177
+ it { SubdomainFu.needs_rewrite?(nil,"awesome.localhost").should be_false }
178
+ it { SubdomainFu.needs_rewrite?(false,"awesome.localhost").should be_true }
179
+ it { SubdomainFu.needs_rewrite?(false,"www.localhost").should be_false }
180
+ it { SubdomainFu.needs_rewrite?("www","awesome.localhost").should be_true }
181
+
182
+ describe "when preferred_mirror is false" do
183
+ before do
184
+ SubdomainFu.preferred_mirror = false
185
+ end
186
+
187
+ it { SubdomainFu.needs_rewrite?("www","www.localhost").should be_false }
188
+ it { SubdomainFu.needs_rewrite?("www","localhost").should be_false }
189
+ it { SubdomainFu.needs_rewrite?("awesome","www.localhost").should be_true }
190
+ it { SubdomainFu.needs_rewrite?("cool","awesome.localhost").should be_true }
191
+ it { SubdomainFu.needs_rewrite?(nil,"www.localhost").should be_false }
192
+ it { SubdomainFu.needs_rewrite?(nil,"awesome.localhost").should be_false }
193
+ it { SubdomainFu.needs_rewrite?(false,"awesome.localhost").should be_true }
194
+ #Only one different from default set of tests
195
+ it { SubdomainFu.needs_rewrite?(false,"www.localhost").should be_true }
196
+ it { SubdomainFu.needs_rewrite?("www","awesome.localhost").should be_true }
197
+ end
198
+
199
+ describe "when preferred_mirror is string" do
200
+ before do
201
+ SubdomainFu.preferred_mirror = "www"
202
+ end
203
+
204
+ it { SubdomainFu.needs_rewrite?("www","www.localhost").should be_false }
205
+ it { SubdomainFu.needs_rewrite?("awesome","www.localhost").should be_true }
206
+ # Following is different from default set of tests
207
+ it { SubdomainFu.needs_rewrite?("www","localhost").should be_true }
208
+ it { SubdomainFu.needs_rewrite?("cool","awesome.localhost").should be_true }
209
+ it { SubdomainFu.needs_rewrite?(nil,"www.localhost").should be_false }
210
+ it { SubdomainFu.needs_rewrite?(nil,"awesome.localhost").should be_false }
211
+ it { SubdomainFu.needs_rewrite?(false,"awesome.localhost").should be_true }
212
+ it { SubdomainFu.needs_rewrite?(false,"www.localhost").should be_false }
213
+ it { SubdomainFu.needs_rewrite?("www","awesome.localhost").should be_true }
214
+ end
215
+
216
+ end
217
+ 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,69 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: subdomain-fu
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.0
5
+ platform: ruby
6
+ authors:
7
+ - Michael Bleigh
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-08-31 00:00:00 -04:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ 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).
17
+ email: michael@intridea.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README.rdoc
24
+ files:
25
+ - CHANGELOG
26
+ - MIT-LICENSE
27
+ - README.rdoc
28
+ - Rakefile
29
+ - VERSION.yml
30
+ - lib/subdomain-fu.rb
31
+ - lib/subdomain_fu/routing_extensions.rb
32
+ - lib/subdomain_fu/url_rewriter.rb
33
+ - rails/init.rb
34
+ - spec/spec.opts
35
+ - spec/spec_helper.rb
36
+ - spec/subdomain_fu_spec.rb
37
+ - spec/url_rewriter_spec.rb
38
+ has_rdoc: true
39
+ homepage: http://github.com/mbleigh/subdomain-fu
40
+ licenses: []
41
+
42
+ post_install_message:
43
+ rdoc_options:
44
+ - --charset=UTF-8
45
+ require_paths:
46
+ - lib
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: "0"
52
+ version:
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: "0"
58
+ version:
59
+ requirements: []
60
+
61
+ rubyforge_project:
62
+ rubygems_version: 1.3.3
63
+ signing_key:
64
+ specification_version: 3
65
+ summary: SubdomainFu is a Rails plugin that provides subdomain routing and URL writing helpers.
66
+ test_files:
67
+ - spec/spec_helper.rb
68
+ - spec/subdomain_fu_spec.rb
69
+ - spec/url_rewriter_spec.rb