Permalink
Browse files

can now pass a regex to the canonical subdomain

  • Loading branch information...
1 parent 6ea5aca commit db0905ebfe5e874b3e9b81f1bb3711eb52be9d8a @matthewrobertson committed Feb 5, 2013
View
1 lib/ress.rb
@@ -1,6 +1,7 @@
require "action_view"
require "ress/version"
+require "ress/subdomain"
require "ress/alternate_version"
require "ress/canonical_version"
require "ress/category_collection"
View
32 lib/ress/canonical_version.rb
@@ -2,35 +2,31 @@ module Ress
class CanonicalVersion
- attr_reader :subdomain
-
def initialize(options = {})
- @subdomain = options.fetch(:subdomain, false)
+ @subdomain = Ress::Subdomain.create(options.fetch(:subdomain, nil))
end
- def matches?(subdomain)
- if self.subdomain
- self.subdomain == subdomain
- else
- subdomain.empty?
- end
+ def matches?(req_subdomain)
+ subdomain.matches?(req_subdomain)
end
# Create a tag of this format:
# `<link rel="canonical" href="http://www.example.com/page-1" >`
- def link_tag(protocol, fullpath, subdomain, view)
- view.tag :link, :rel => 'canonical', :href => url(protocol, fullpath, subdomain)
+ def link_tag(protocol, fullpath, req_subdomain, view)
+
+ view.tag :link, :rel => 'canonical', :href => url(protocol, fullpath, req_subdomain)
end
- def url(protocol, fullpath, subdomain)
- fullpath = fullpath[(subdomain.length + 1)..-1] unless subdomain.empty?
- if self.subdomain
- "#{protocol}#{self.subdomain}.#{fullpath}"
- else
- "#{protocol}#{fullpath}"
- end
+ def url(protocol, fullpath, req_subdomain)
+ subdomain.url(protocol, fullpath, req_subdomain)
end
+ private
+
+ def subdomain
+ @subdomain
+ end
+
end
end
View
78 lib/ress/subdomain.rb
@@ -0,0 +1,78 @@
+module Ress
+
+ class Subdomain
+
+ # this class is a factory, don't instantiate it directly
+ private_class_method :new
+
+ def self.create(subdomain)
+ case subdomain
+ when String
+ StringSubdomain.new(subdomain)
+ when Regexp
+ RegexpSubdomain.new(subdomain)
+ else
+ NilSubdomain.new
+ end
+ end
+
+ class NilSubdomain
+ def matches?(subdomain)
+ subdomain.empty?
+ end
+
+ def url(protocol, fullpath, subdomain)
+ fullpath = fullpath[(subdomain.length + 1)..-1] unless subdomain.empty?
+ "#{protocol}#{fullpath}"
+ end
+ end
+
+ class StringSubdomain
+
+ attr_reader :subdomain
+
+ def initialize(subdomain)
+ @subdomain = subdomain
+ end
+
+ def matches?(subdomain)
+ self.subdomain == subdomain
+ end
+
+ def url(protocol, fullpath, subdomain)
+ fullpath = fullpath[(subdomain.length + 1)..-1] unless subdomain.empty?
+ "#{protocol}#{self.subdomain}.#{fullpath}"
+ end
+
+ end
+
+ # The main inspiration for this class is to match xip.io
+ # subdomains for many devs working in development mode with
+ # the same configuration.
+ class RegexpSubdomain
+
+ attr_reader :subdomain
+
+ def initialize(subdomain)
+ @subdomain = subdomain
+ end
+
+ def matches?(subdomain)
+ self.subdomain =~ subdomain
+ end
+
+ def url(protocol, fullpath, subdomain)
+ fullpath = fullpath[(subdomain.length + 1)..-1]
+ begin
+ if matches?(subdomain)
+ return "#{protocol}#{subdomain}.#{fullpath}"
+ end
+ subdomain = subdomain.split('.')[1..-1].join('.')
+ end while(!subdomain.empty?)
+ end
+
+ end
+
+ end
+
+end
View
16 spec/ress/canonical_version_spec.rb
@@ -1,21 +1,7 @@
-require_relative '../../lib/ress/canonical_version'
+require_relative '../../lib/ress'
describe Ress::CanonicalVersion do
- describe '#subdomain' do
-
- it 'defaults to false' do
- category = Ress::CanonicalVersion.new
- category.subdomain.should == false
- end
-
- it 'can be overridden by an optional parameter' do
- category = Ress::CanonicalVersion.new(:subdomain => 'foo')
- category.subdomain.should == 'foo'
- end
-
- end
-
describe '#matches?' do
context 'with no canonical subdomain' do
View
4 spec/ress/category_collection_spec.rb
@@ -27,12 +27,12 @@
describe 'canonical_version' do
it 'defaults to a canonical_version with no subdomain' do
- collection.canonical_version.subdomain.should be_false
+ collection.canonical_version.matches?('').should be_true
end
it 'can be altered through set_canonical' do
collection.set_canonical :subdomain => 'foo'
- collection.canonical_version.subdomain.should == 'foo'
+ collection.canonical_version.matches?('foo').should be_true
end
end
View
112 spec/ress/subdomain_spec.rb
@@ -0,0 +1,112 @@
+require_relative '../../lib/ress/subdomain'
+
+describe Ress::Subdomain do
+
+ describe '.create' do
+
+ it 'returns a NilSubdomain when the subdomain is nil' do
+ Ress::Subdomain.create(nil).should be_a(Ress::Subdomain::NilSubdomain)
+ end
+
+ it 'returns a StringSubdomain when the subdomain is a String' do
+ Ress::Subdomain.create('foo').should be_a(Ress::Subdomain::StringSubdomain)
+ end
+
+ it 'returns a RegexpSubdomain when the subdomain is a Regex' do
+ Ress::Subdomain.create(/foo/).should be_a(Ress::Subdomain::RegexpSubdomain)
+ end
+
+ end
+
+ describe Ress::Subdomain::NilSubdomain do
+
+ let(:subdomain) { Ress::Subdomain::NilSubdomain.new }
+
+ describe '#matches?' do
+ it 'matches the empty string' do
+ subdomain.matches?('').should be_true
+ subdomain.matches?('s').should be_false
+ end
+ end
+
+ describe '#url' do
+ it 'strips urls from the fullpath if there is one' do
+ subdomain.url('http://', 'foo.bar.com/some/stuff', 'foo').should ==
+ 'http://bar.com/some/stuff'
+ end
+
+ it 'concatenates the protocol and fullpath together if there is no subdomain' do
+ subdomain.url('http://', 'bar.com/some/stuff', '').should ==
+ 'http://bar.com/some/stuff'
+ end
+ end
+ end
+
+ describe Ress::Subdomain::StringSubdomain do
+
+ let(:subdomain) { Ress::Subdomain::StringSubdomain.new('foo') }
+
+ describe '#matches?' do
+
+ it 'returns true if the url is exact match of that passed to the ctor' do
+ subdomain.matches?('foo').should be_true
+ end
+
+ it 'returns false if the url is not an exact match of that passed to the ctor' do
+ subdomain.matches?('boo').should be_false
+ end
+ end
+
+ describe '#url' do
+
+ it 'strips off extra subdomains from the fullpath' do
+ subdomain.url('http://', 'm.foo.bar.com/some/stuff', 'm.foo').should ==
+ 'http://foo.bar.com/some/stuff'
+ end
+
+ it 'handles cannonical fullpaths' do
+ subdomain.url('http://', 'foo.bar.com/some/stuff', 'foo').should ==
+ 'http://foo.bar.com/some/stuff'
+ end
+
+ end
+ end
+
+ describe Ress::Subdomain::RegexpSubdomain do
+ describe '#matches?' do
+ let(:subdomain) { Ress::Subdomain::RegexpSubdomain.new(/[fb]oo/) }
+
+ it 'returns true if the subdomain matches regex that passed to the ctor' do
+ subdomain.matches?('foo').should be_true
+ subdomain.matches?('boo').should be_true
+ end
+
+ it 'returns false if the subdomain doesnt matches regex that is passed to the ctor' do
+ subdomain.matches?('baz').should be_false
+ end
+
+ it 'can handle the xip.io format' do
+ subdomain = Ress::Subdomain::RegexpSubdomain.new(/^([0-9]+\.){3}([0-9]+)/)
+ subdomain.matches?('172.30.251.3').should be_true
+
+ subdomain.matches?('mobile.172.30.251.3').should be_false
+ end
+ end
+
+ describe '#url' do
+
+ let(:subdomain) { Ress::Subdomain::RegexpSubdomain.new(/^[fb]oo/) }
+
+ it 'echos back the url for cannonical requests' do
+ subdomain.url('http://', 'foo.bar.com/some/stuff', 'foo').should ==
+ 'http://foo.bar.com/some/stuff'
+ end
+
+ it 'strips off prepended subdomains that dont matche the regex' do
+ subdomain.url('http://', 'm.a.foo.bar.com/some/stuff', 'm.a.foo').should ==
+ 'http://foo.bar.com/some/stuff'
+ end
+
+ end
+ end
+end
View
2 spec/ress_spec.rb
@@ -18,7 +18,7 @@
it 'can be altered through Ress.configure' do
Ress.configure { |r| r.set_canonical :subdomain => 'foo' }
- Ress.canonical_version.subdomain.should == 'foo'
+ Ress.canonical_version.matches?('foo').should be_true
end
end

0 comments on commit db0905e

Please sign in to comment.