Skip to content

Commit

Permalink
can now pass a regex to the canonical subdomain
Browse files Browse the repository at this point in the history
  • Loading branch information
Matthew Robertson committed Feb 5, 2013
1 parent 6ea5aca commit db0905e
Show file tree
Hide file tree
Showing 7 changed files with 209 additions and 36 deletions.
1 change: 1 addition & 0 deletions 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"
Expand Down
32 changes: 14 additions & 18 deletions lib/ress/canonical_version.rb
Expand Up @@ -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
78 changes: 78 additions & 0 deletions 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
16 changes: 1 addition & 15 deletions 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
Expand Down
4 changes: 2 additions & 2 deletions spec/ress/category_collection_spec.rb
Expand Up @@ -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
Expand Down
112 changes: 112 additions & 0 deletions 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
2 changes: 1 addition & 1 deletion spec/ress_spec.rb
Expand Up @@ -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
Expand Down

0 comments on commit db0905e

Please sign in to comment.