domain_switcher 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.rdoc ADDED
@@ -0,0 +1,11 @@
1
+ = DomainSwitcher
2
+
3
+ Rack based domain switcher with configuration
4
+
5
+ * Add a website and a domain object in the context
6
+ * Switch cache namespace
7
+ * Switch cookie domain
8
+
9
+ == Usage for Rails 2.3:
10
+
11
+ config.middleware.use 'DomainSwitcher::Middleware'
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rspec/core/rake_task'
4
+
5
+ desc "Run specs"
6
+ RSpec::Core::RakeTask.new do |t|
7
+ t.pattern = "spec/**/*_spec.rb"
8
+ t.verbose = true
9
+ end
10
+
11
+ task :default => :spec
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'domain_switcher'
@@ -0,0 +1,36 @@
1
+ module DomainSwitcher
2
+ module Cache
3
+
4
+ def self.init
5
+ $domain_switcher_cache_systems = {}
6
+ end
7
+
8
+ def self.switch(website)
9
+ namespace = website.cache_prefix || website.symbol
10
+
11
+ if (c = RAILS_CACHE)
12
+ if !$domain_switcher_cache_systems.key?(namespace)
13
+ Rails.logger.info "DomainSwitcher: Create new cache system for namespace : #{c.class} | #{namespace}"
14
+
15
+ # MemcachedStore => Tested and working with Memcached gem only
16
+ $domain_switcher_cache_systems[namespace] = if ActiveSupport::Cache::MemCacheStore === c
17
+ d = RAILS_CACHE.instance_variable_get('@data')
18
+ if d.prefix_key == namespace
19
+ Rails.logger.info "DomainSwitcher: Use existing cache => namespace is the same: #{namespace}"
20
+ RAILS_CACHE
21
+ else
22
+ c.class.new(d.instance_variable_get('@servers'), d.instance_variable_get('@options').merge(:namespace => namespace, :prefix_key => namespace))
23
+ end
24
+ elsif c.is_a? ActiveSupport::Cache::FileStore
25
+ c.class.new("tmp/cache/#{namespace}")
26
+ else
27
+ c
28
+ end
29
+ end
30
+ ActionController::Caching.send(:class_variable_set, :@@cache_store, (Thread.current[:domain_switcher_cache] = $domain_switcher_cache_systems[namespace]))
31
+ end
32
+
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,40 @@
1
+ module DomainSwitcher
2
+ module ConfigBuilder
3
+
4
+ # Create a bunch of method for the configuration hash
5
+ def build_config!(hash)
6
+ raise "Build config only accept hashes and not #{conf.class}" unless Hash === hash
7
+
8
+ # From: https://github.com/kwi/awesome_conf
9
+ m = Module.new do
10
+ instance_methods.each { |selector| remove_method(selector) }
11
+
12
+ hash.each do |k, v|
13
+ const_set('AC_' + k.to_s, v)
14
+ module_eval <<-END_EVAL, __FILE__, __LINE__ + 1
15
+ def #{k}
16
+ #{'AC_'+ k.to_s}
17
+ end
18
+ END_EVAL
19
+
20
+ if TrueClass === v or FalseClass === v
21
+ module_eval <<-END_EVAL, __FILE__, __LINE__ + 1
22
+ def #{k}?
23
+ #{v ? true : false}
24
+ end
25
+ END_EVAL
26
+ end
27
+ end
28
+
29
+ end
30
+
31
+ extend m
32
+ end
33
+
34
+ # Do nothing when a method is missing
35
+ def method_missing(m)
36
+ nil
37
+ end
38
+
39
+ end
40
+ end
@@ -0,0 +1,59 @@
1
+ require 'yaml'
2
+
3
+ module DomainSwitcher
4
+ class ConfigLoader
5
+
6
+ attr_reader :websites
7
+ attr_reader :domains
8
+
9
+ def initialize(config_file = 'config/websites.yml')
10
+ begin
11
+ @conf = YAML::load_file(config_file)
12
+ rescue ArgumentError => e
13
+ raise ArgumentError.new("DomainSwitcher: Malformed config file (#{config_file}): #{e}")
14
+ end
15
+ raise ArgumentError.new("DomainSwitcher: Empty config file (#{config_file})") if !@conf or @conf.size == 0
16
+
17
+ @websites = []
18
+ @domains = []
19
+ parse_conf!
20
+ end
21
+
22
+ private
23
+ def parse_conf!
24
+ @conf.each do |website, conf|
25
+ domains = conf.delete('domains')
26
+ default_domain = conf.delete('default_domain')
27
+ raise "DomainSwitcher: Website without domain: #{website}" if !domains or domains.size == 0
28
+ raise "DomainSwitcher: Website without default domain: #{website}" if !default_domain
29
+
30
+ website = Website.new(conf['name'], website, conf)
31
+
32
+ domains.each do |d|
33
+ if String === d
34
+ website << Domain.new(website, d, conf.merge(conf))
35
+ else # It's an hash like this: {"www.website1.com"=>{"name"=>"Website 1 override", "width"=>900}}
36
+ raise "DomainSwitcher: Bad indentation in the config file" if d.size != 1
37
+ website << Domain.new(website, d.first.first, d.first.last.merge(conf))
38
+ end
39
+ end
40
+
41
+ # Set the default domain for the website
42
+ website.default_domain = website.domains.find {|d| d.domain == default_domain } || website.domains.first
43
+
44
+ # Collect websites and domains
45
+ @websites << website
46
+ @domains += website.domains
47
+ end
48
+ end
49
+
50
+ public
51
+ def default_website
52
+ @default_website ||= @websites.find { |w| w.default? } || @websites.first
53
+ end
54
+
55
+ def default_domain
56
+ @default_domain ||= @domains.find { |d| d.default? } || @domains.first
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,10 @@
1
+ module DomainSwitcher
2
+ module Cookie
3
+
4
+ def self.switch(domain, env)
5
+ env['rack.session.options'].update(:domain => domain.cookie_domain)
6
+ env
7
+ end
8
+
9
+ end
10
+ end
@@ -0,0 +1,19 @@
1
+ module DomainSwitcher
2
+ class Domain
3
+ include ConfigBuilder
4
+
5
+ attr_reader :website
6
+ attr_reader :domain
7
+
8
+ def initialize(website, domain, conf = {})
9
+ @website = website
10
+ @domain = domain
11
+ build_config!(conf)
12
+ end
13
+
14
+ def cookie_domain
15
+ @cookie_domain ||= domain.split('.').last(2).join('.')
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,13 @@
1
+ module DomainSwitcher
2
+ module Helper
3
+
4
+ def domain
5
+ Thread.current[:domain_switcher_domain]
6
+ end
7
+
8
+ def website
9
+ Thread.current[:domain_switcher_website]
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,29 @@
1
+ module DomainSwitcher
2
+ class Middleware
3
+
4
+ def initialize(app, config = nil)
5
+ @app = app
6
+ @config = config || DomainSwitcher::ConfigLoader.new
7
+ @scanner = DomainSwitcher::Scanner.new(@config.domains)
8
+
9
+ DomainSwitcher::Cache.init
10
+ end
11
+
12
+ def call(env)
13
+ domain = @scanner.scan_domain(env['HTTP_HOST']) || @config.default_domain
14
+
15
+ Rails.logger.debug "DomainSwitcher: Switch context for domain: #{domain.domain} (#{domain.website.name})"
16
+
17
+ if Thread.current[:domain_switcher_domain] != domain
18
+ Thread.current[:domain_switcher_domain] = domain
19
+ Thread.current[:domain_switcher_website] = domain.website
20
+
21
+ DomainSwitcher::Cache::switch(domain.website)
22
+ env = DomainSwitcher::Cookie::switch(domain, env)
23
+ end
24
+
25
+ @app.call(env)
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,12 @@
1
+ # Override the default Rails.cache method in order to user the current memcache store
2
+ module Rails
3
+ class << self
4
+ def cache
5
+ Thread.current[:domain_switcher_cache] || RAILS_CACHE
6
+ end
7
+ end
8
+ end
9
+
10
+ ActionController::Base.send :include, DomainSwitcher::Helper
11
+ ActiveRecord::Base.send :include, DomainSwitcher::Helper
12
+ ActionView::Base.send :include, DomainSwitcher::Helper
@@ -0,0 +1,19 @@
1
+ module DomainSwitcher
2
+ class Scanner
3
+
4
+ @@domain_cache = {}
5
+
6
+ def initialize(domains)
7
+ @domains = domains
8
+
9
+ domains.each do |d|
10
+ @@domain_cache[d.domain] = d
11
+ end
12
+ end
13
+
14
+ def scan_domain(host)
15
+ @@domain_cache[host]
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,22 @@
1
+ module DomainSwitcher
2
+ class Website
3
+ include ConfigBuilder
4
+
5
+ attr_reader :name
6
+ attr_reader :symbol
7
+ attr_reader :domains
8
+ attr :default_domain, true
9
+
10
+ def initialize(name, symbol, conf = {}, domains = [])
11
+ @name = name
12
+ @symbol = symbol
13
+ @domains = domains
14
+ build_config!(conf)
15
+ end
16
+
17
+ def <<(domain)
18
+ @domains << domain
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,15 @@
1
+ module DomainSwitcher
2
+ autoload :Middleware, 'domain_switcher/middleware'
3
+ autoload :ConfigLoader, 'domain_switcher/config_loader'
4
+ autoload :ConfigBuilder, 'domain_switcher/config_builder'
5
+ autoload :Website, 'domain_switcher/website'
6
+ autoload :Domain, 'domain_switcher/domain'
7
+ autoload :Helper, 'domain_switcher/helper'
8
+ autoload :Scanner, 'domain_switcher/scanner'
9
+ autoload :Cache, 'domain_switcher/cache'
10
+ autoload :Cookie, 'domain_switcher/cookie'
11
+ autoload :Logger, 'domain_switcher/logger'
12
+ end
13
+
14
+ current_path = File.dirname(__FILE__)
15
+ require File.join(current_path, 'domain_switcher/rails')
@@ -0,0 +1,27 @@
1
+ website1:
2
+ name: Website 1
3
+ default_domain: www.website1.com
4
+ cache_prefix: first
5
+ domains:
6
+ - www.website1.com:
7
+ width: 900
8
+ name: Website 1 override
9
+ - www.website1-other-domain.com:
10
+ cookie_domain: www.website1-other-domain.com
11
+ - www.website1-other-domain-again.com
12
+ - www.website1-other-domain-again-again.com
13
+ width: 800
14
+ bool: true
15
+ bool2: false
16
+
17
+ website2:
18
+ name: Website2
19
+ default: true
20
+ default_domain: fr.website2.com
21
+ cookie_domain: 'website2cookie.com'
22
+ domains:
23
+ - www.website2.com:
24
+ default: true
25
+ - fr.website2.com
26
+ lang: fr
27
+ false_meth: false
@@ -0,0 +1,24 @@
1
+ website1:
2
+ name: Website 1
3
+ default_domain: www.website1.com
4
+ domains:
5
+ - www.website1.com:
6
+ width: 900
7
+ name: Website 1 override
8
+ - www.website1-other-domain.com:
9
+ cookie_domain: www.website1-other-domain.com
10
+ - www.website1-other-domain-again.com
11
+ - www.website1-other-domain-again-again.com
12
+ width: 800
13
+ bool: true
14
+ bool2: false
15
+
16
+ website2:
17
+ name: Website2
18
+ default: true
19
+ default_domain: fr.website2.com
20
+ domains:
21
+ - www.website2.com:
22
+ default: true
23
+ - fr.website2.com
24
+ lang: fr
@@ -0,0 +1,5 @@
1
+ bouahh
2
+ - broken_file:
3
+ broken:
4
+ - yes
5
+ malformed
File without changes
@@ -0,0 +1,86 @@
1
+ require 'spec_helper'
2
+
3
+ describe :config_loader do
4
+
5
+ context "With incorrect conf file" do
6
+ it "Raise correctly on empty" do
7
+ e = nil
8
+ begin
9
+ DomainSwitcher::ConfigLoader.new(File.join(File.dirname(__FILE__), '../config/websites_empty.yml'))
10
+ rescue Exception => e
11
+ end
12
+ e.to_s.index('DomainSwitcher: Empty config file').should_not be_nil
13
+ end
14
+
15
+ it "Raise correctly on not found config file" do
16
+ e = nil
17
+ begin
18
+ DomainSwitcher::ConfigLoader.new(File.join(File.dirname(__FILE__), '../config/websites_not_existing.yml'))
19
+ rescue Exception => e
20
+ end
21
+ e.to_s.index('No such file or directory').should_not be_nil
22
+ end
23
+
24
+ it "Raise correctly on malformed config file" do
25
+ e = nil
26
+ begin
27
+ DomainSwitcher::ConfigLoader.new(File.join(File.dirname(__FILE__), '../config/websites_broken.yml'))
28
+ rescue ArgumentError => e
29
+ end
30
+ e.to_s.index('DomainSwitcher: Malformed config file').should_not be_nil
31
+ end
32
+
33
+ it "Raise correctly on bad indentation config file" do
34
+ e = nil
35
+ begin
36
+ DomainSwitcher::ConfigLoader.new(File.join(File.dirname(__FILE__), '../config/websites_bad_indentation.yml'))
37
+ rescue Exception => e
38
+ end
39
+ e.to_s.index('DomainSwitcher: Bad indentation in the config file').should_not be_nil
40
+ end
41
+ end
42
+
43
+ context 'With a correct file' do
44
+ before :all do
45
+ @config = DomainSwitcher::ConfigLoader.new(File.join(File.dirname(__FILE__), '../config/websites.yml'))
46
+ end
47
+
48
+ it "load correctly all domains" do
49
+ @config.domains.size.should == 6
50
+ @config.domains.collect(&:domain).uniq.size.should == 6
51
+ @config.domains.first.domain.should == 'www.website1.com'
52
+ end
53
+
54
+ it "load correctly all websites" do
55
+ @config.websites.size.should == 2
56
+ @config.websites.collect(&:symbol).uniq.size.should == 2
57
+ @config.websites.first.symbol.should == 'website1'
58
+ end
59
+
60
+ it "set correctly default domain" do
61
+ @config.websites[0].default_domain.domain.should == 'www.website1.com'
62
+ @config.websites[1].default_domain.domain.should == 'fr.website2.com'
63
+ @config.default_domain.domain.should == 'www.website2.com'
64
+ end
65
+
66
+ it "set correctly default website" do
67
+ @config.default_website.symbol.should == 'website2'
68
+ end
69
+
70
+ it "conf variables are well set" do
71
+ @config.default_website.name.should == 'Website2'
72
+ @config.default_website.default.should == true
73
+ @config.default_website.lang.should == 'fr'
74
+ end
75
+
76
+ it "boolean conf variables are well set" do
77
+ @config.default_website.default?.should == true
78
+ @config.default_website.false_meth?.should == false
79
+ end
80
+
81
+ it "cookie domain can be overrided" do
82
+ @config.default_domain.cookie_domain.should == 'website2cookie.com'
83
+ end
84
+
85
+ end
86
+ end
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+
3
+ describe :domain_switcher do
4
+
5
+ before :all do
6
+ @conf = DomainSwitcher::ConfigLoader.new(File.join(File.dirname(__FILE__), '../config/websites.yml'))
7
+ @app = DomainSwitcher::Middleware.new(Proc.new {|b| [200, 'OK']}, @conf)
8
+ end
9
+
10
+ it "not create a new memcache connection if namespace is the same" do
11
+ @app.call({'HTTP_HOST' => 'www.website1.com', 'rack.session.options' => {:domain => :test, :something => true}})
12
+ Thread.current[:domain_switcher_cache].instance_variable_get('@data') == RAILS_CACHE
13
+ end
14
+
15
+ it "switch on default when nothing is found" do
16
+ @app.call({'HTTP_HOST' => 'nothing', 'rack.session.options' => {:domain => :test, :something => true}})
17
+ Thread.current[:domain_switcher_domain].should == @conf.default_domain
18
+ Thread.current[:domain_switcher_website].should == @conf.default_website
19
+ end
20
+
21
+ it "correctly switch" do
22
+ @app.call({'HTTP_HOST' => 'www.website1.com', 'rack.session.options' => {:domain => :test, :something => true}})
23
+ Thread.current[:domain_switcher_domain].domain.should == 'www.website1.com'
24
+ Thread.current[:domain_switcher_website].symbol.should == 'website1'
25
+ end
26
+
27
+ it "correctly switch the cookie domain" do
28
+ env = {'HTTP_HOST' => 'www.website1.com', 'rack.session.options' => {:domain => :test, :something => true}}
29
+ @app.call(env)
30
+ env['rack.session.options'][:domain].should == 'website1.com'
31
+ end
32
+
33
+ it "correctly switch the cache namespace" do
34
+ @app.call({'HTTP_HOST' => 'www.website1.com', 'rack.session.options' => {:domain => :test, :something => true}})
35
+ Rails.cache.instance_variable_get('@data').prefix_key.should == 'first'
36
+ @app.call({'HTTP_HOST' => 'www.website2.com', 'rack.session.options' => {:domain => :test, :something => true}})
37
+ Rails.cache.instance_variable_get('@data').prefix_key.should == 'website2'
38
+ @app.call({'HTTP_HOST' => 'www.website1.com', 'rack.session.options' => {:domain => :test, :something => true}})
39
+ Rails.cache.instance_variable_get('@data').prefix_key.should == 'first'
40
+ end
41
+
42
+
43
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ describe :helper do
4
+
5
+ before :all do
6
+ @conf = DomainSwitcher::ConfigLoader.new(File.join(File.dirname(__FILE__), '../config/websites.yml'))
7
+ @app = DomainSwitcher::Middleware.new(Proc.new {|b| [200, 'OK']}, @conf)
8
+ end
9
+
10
+ it "Check helper" do
11
+ @app.call({'HTTP_HOST' => 'www.website1.com', 'rack.session.options' => {:domain => :test, :something => true}})
12
+ ActionController::Base.new.website.symbol.should == 'website1'
13
+ ActionController::Base.new.website.should == Thread.current[:domain_switcher_website]
14
+ ActionController::Base.new.domain.should == Thread.current[:domain_switcher_domain]
15
+
16
+ @app.call({'HTTP_HOST' => 'www.website2.com', 'rack.session.options' => {:domain => :test, :something => true}})
17
+ ActionController::Base.new.website.symbol.should == 'website2'
18
+ ActionController::Base.new.website.should == Thread.current[:domain_switcher_website]
19
+ ActionController::Base.new.domain.should == Thread.current[:domain_switcher_domain]
20
+ ActionView::Base.new.website.should == Thread.current[:domain_switcher_website]
21
+ ActiveRecord::Base.new.domain.should == Thread.current[:domain_switcher_domain]
22
+ end
23
+
24
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe :scanner do
4
+
5
+ before :all do
6
+ @config = DomainSwitcher::ConfigLoader.new(File.join(File.dirname(__FILE__), '../config/websites.yml'))
7
+ @scanner = DomainSwitcher::Scanner.new(@config.domains)
8
+ end
9
+
10
+ it "return nil when not existing" do
11
+ @scanner.scan_domain(nil).should == nil
12
+ @scanner.scan_domain('something_not_existing').should == nil
13
+ end
14
+
15
+ it "return correct domain when existing" do
16
+ @scanner.scan_domain('www.website2.com').should_not be_nil
17
+ @scanner.scan_domain('www.website2.com').domain == 'www.website2.com'
18
+ @scanner.scan_domain('fr.website2.com').domain == 'fr.website2.com'
19
+ @scanner.scan_domain('www.website1-other-domain-again.com').domain == 'www.website1-other-domain-again.com'
20
+ @scanner.scan_domain('www.website1.com').domain == 'www.website1.com'
21
+ end
22
+
23
+ end
@@ -0,0 +1,56 @@
1
+ require 'rubygems'
2
+ require 'rspec'
3
+ require 'logger'
4
+
5
+ module ActionController
6
+ class Base
7
+ end
8
+
9
+ module Caching
10
+ end
11
+ end
12
+
13
+ module ActionView
14
+ class Base
15
+ end
16
+ end
17
+
18
+ module ActiveRecord
19
+ class Base
20
+ end
21
+ end
22
+
23
+ module ActiveSupport
24
+ module Cache
25
+ class MemCacheStore
26
+ def initialize(*args)
27
+ @data = Memcached.new(*args)
28
+ end
29
+ end
30
+
31
+ class Memcached
32
+ def initialize(servers, options = {})
33
+ @servers = servers
34
+ @options = options
35
+ end
36
+
37
+ def prefix_key
38
+ @options[:prefix_key]
39
+ end
40
+
41
+ end
42
+
43
+ class FileStore
44
+ end
45
+ end
46
+ end
47
+
48
+ module Rails
49
+ def self.logger
50
+ @logger ||= Logger.new(STDOUT)
51
+ end
52
+ end
53
+
54
+ RAILS_CACHE = ActiveSupport::Cache::MemCacheStore.new(['localhost'], {:test_options => true, :prefix_key => 'first'})
55
+
56
+ require File.dirname(__FILE__) + '/../init.rb'
metadata ADDED
@@ -0,0 +1,106 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: domain_switcher
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Guillaume Luccisano
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-02-24 00:00:00 -08:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: rack
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 19
30
+ segments:
31
+ - 1
32
+ - 1
33
+ - 0
34
+ version: 1.1.0
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ description: Rack based domain switcher with configuration
38
+ email: guillaume@justin.tv
39
+ executables: []
40
+
41
+ extensions: []
42
+
43
+ extra_rdoc_files: []
44
+
45
+ files:
46
+ - lib/domain_switcher/cache.rb
47
+ - lib/domain_switcher/config_builder.rb
48
+ - lib/domain_switcher/config_loader.rb
49
+ - lib/domain_switcher/cookie.rb
50
+ - lib/domain_switcher/domain.rb
51
+ - lib/domain_switcher/helper.rb
52
+ - lib/domain_switcher/middleware.rb
53
+ - lib/domain_switcher/rails.rb
54
+ - lib/domain_switcher/scanner.rb
55
+ - lib/domain_switcher/website.rb
56
+ - lib/domain_switcher.rb
57
+ - spec/config/websites.yml
58
+ - spec/config/websites_bad_indentation.yml
59
+ - spec/config/websites_broken.yml
60
+ - spec/config/websites_empty.yml
61
+ - spec/domain_switcher/config_spec.rb
62
+ - spec/domain_switcher/domain_switcher_spec.rb
63
+ - spec/domain_switcher/helper_spec.rb
64
+ - spec/domain_switcher/scanner_spec.rb
65
+ - spec/spec_helper.rb
66
+ - Rakefile
67
+ - README.rdoc
68
+ - init.rb
69
+ has_rdoc: true
70
+ homepage: http://www.justin.tv
71
+ licenses: []
72
+
73
+ post_install_message:
74
+ rdoc_options: []
75
+
76
+ require_paths:
77
+ - lib
78
+ required_ruby_version: !ruby/object:Gem::Requirement
79
+ none: false
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ hash: 3
84
+ segments:
85
+ - 0
86
+ version: "0"
87
+ required_rubygems_version: !ruby/object:Gem::Requirement
88
+ none: false
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ hash: 19
93
+ segments:
94
+ - 1
95
+ - 3
96
+ - 4
97
+ version: 1.3.4
98
+ requirements: []
99
+
100
+ rubyforge_project: domain_switcher
101
+ rubygems_version: 1.4.2
102
+ signing_key:
103
+ specification_version: 3
104
+ summary: Rack based domain switcher with configuration
105
+ test_files: []
106
+