Skip to content

Commit

Permalink
Merge branch 'master' into fullpath_argument_for_annotation_tags
Browse files Browse the repository at this point in the history
  • Loading branch information
lokimeyburg committed Apr 18, 2013
2 parents bd7d528 + 1efb8b0 commit 6f534ad
Show file tree
Hide file tree
Showing 14 changed files with 304 additions and 62 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -15,3 +15,4 @@ spec/reports
test/tmp test/tmp
test/version_tmp test/version_tmp
tmp tmp
integration/
30 changes: 24 additions & 6 deletions README.md
@@ -1,21 +1,21 @@
# Ress # RESS


A system for building mobile optimized Rails applications using semantic, A system for building mobile optimized Rails applications using semantic,
media query-based device detection and server side progressive enhancement. media query-based device detection and server side component optimization.


## Background ## Background


Ress is an extension of the [devicejs](https://github.com/borismus/device.js) RESS is an extension of the [devicejs](https://github.com/borismus/device.js)
library written by [Boris Smus](http://smus.com/). It adds a back end for library written by [Boris Smus](http://smus.com/). It adds a back end for
adapting server responses based on client side feature detection. Ress allows adapting server responses based on client side feature detection. RESS allows
you to specify alternate versions of your website, along with media queries you to specify alternate versions of your website, along with media queries
for which devices should be redirected to which version. for which devices should be redirected to which version.


## How it Works ## How it Works


### HTML Annotations ### HTML Annotations


When you register alternate mobile versions of your website, Ress adds annotations When you register alternate mobile versions of your website, RESS adds annotations
to the `<head>` of your document that describe where these pages are located and to the `<head>` of your document that describe where these pages are located and
which devices should be redirected to them. which devices should be redirected to them.


Expand Down Expand Up @@ -43,7 +43,7 @@ all of the `[rel="alternate"]` links in your markup, and evalute their media que
to determine if there is an alternate version available that matches the client. to determine if there is an alternate version available that matches the client.
If there is, the user is redirected to the url for that version. If there is, the user is redirected to the url for that version.


### Server Side Components ### Server Side Component Optimization


Ress allows you to customize how your Rails application responds to mobile requests in Ress allows you to customize how your Rails application responds to mobile requests in
two ways: two ways:
Expand Down Expand Up @@ -123,6 +123,24 @@ make sure that it includes "Touch Events" and "Media Queries", eg:


http://modernizr.com/download/#-touch-mq-teststyles-prefixes http://modernizr.com/download/#-touch-mq-teststyles-prefixes


### Sessions and Cookies

In order to share sessions and cookies between the different subdomains used by the
alternate versions of your app, you need to configure the `:domain` option both in
the `config/initializers/session_store.rb` and when setting cookies. For more
information about how this works see this
[Railscast](http://railscasts.com/episodes/221-subdomains-in-rails-3).

### Development

Because RESS uses subdomains, while developing alternate versions you cannot
load your site via `localhost` or an IP address. If you want to test on
the same machine you are running your rails app on, you can load it through
http://lvh.me or install [pow](http://pow.cx/) and set up a `.dev` domain
for your app. If you need to test on a mobile device you might want to try
http://xip.io/.


## Performance considerations ## Performance considerations


The javascript included by Ress does some checks and will use client-side The javascript included by Ress does some checks and will use client-side
Expand Down
8 changes: 7 additions & 1 deletion lib/generators/ress/templates/ress.rb
Expand Up @@ -5,10 +5,16 @@


# == Canonical Subdomain # == Canonical Subdomain
# #
# If the cannonical version of your application is served under a subdomain # If the canonical version of your application is served under a subdomain
# you must set it here: # you must set it here:
# #
# config.set_canonical :subdomain => "subdomain" # config.set_canonical :subdomain => "subdomain"
#
# By default, alternate version subdomains are prepended to the canonical url.
# If you are using a canonical subdomain and you would like it to be replaced
# by the alternate subdomains, set this option to true:
#
# config.replace_canonical_subdomain = false




# == Modernizr # == Modernizr
Expand Down
19 changes: 12 additions & 7 deletions lib/ress.rb
@@ -1,9 +1,10 @@
require "action_view" require "action_view"


require "ress/version" require "ress/version"
require "ress/subdomain"
require "ress/alternate_version" require "ress/alternate_version"
require "ress/canonical_version" require "ress/canonical_version"
require "ress/category_collection" require "ress/config"
require "ress/controller_additions" require "ress/controller_additions"
require "ress/view_helpers" require "ress/view_helpers"


Expand All @@ -14,24 +15,28 @@
module Ress module Ress
extend self extend self


def category_collection def config
@categories ||= CategoryCollection.new @config ||= Config.new
end end


def canonical_version def canonical_version
category_collection.canonical_version config.canonical_version
end end


def alternate_versions def alternate_versions
category_collection.alternate_versions config.alternate_versions
end end


def include_modernizr? def include_modernizr?
category_collection.include_modernizr config.include_modernizr
end

def replace_canonical_subdomain?
config.replace_canonical_subdomain
end end


def configure def configure
yield(category_collection) yield(config)
end end


end end
31 changes: 13 additions & 18 deletions lib/ress/canonical_version.rb
Expand Up @@ -2,35 +2,30 @@ module Ress


class CanonicalVersion class CanonicalVersion


attr_reader :subdomain

def initialize(options = {}) def initialize(options = {})
@subdomain = options.fetch(:subdomain, false) @subdomain = Ress::Subdomain.create(options.fetch(:subdomain, nil))
end end


def matches?(subdomain) def matches?(req_subdomain)
if self.subdomain subdomain.matches?(req_subdomain)
self.subdomain == subdomain
else
subdomain.empty?
end
end end


# Create a tag of this format: # Create a tag of this format:
# `<link rel="canonical" href="http://www.example.com/page-1" >` # `<link rel="canonical" href="http://www.example.com/page-1" >`
def link_tag(protocol, fullpath, subdomain, view) def link_tag(protocol, fullpath, req_subdomain, view)
view.tag :link, :rel => 'canonical', :href => url(protocol, fullpath, subdomain) view.tag :link, :rel => 'canonical', :href => url(protocol, fullpath, req_subdomain)
end end


def url(protocol, fullpath, subdomain) def url(protocol, fullpath, req_subdomain)
fullpath = fullpath[(subdomain.length + 1)..-1] unless subdomain.empty? subdomain.url(protocol, fullpath, req_subdomain)
if self.subdomain
"#{protocol}#{self.subdomain}.#{fullpath}"
else
"#{protocol}#{fullpath}"
end
end end


private

def subdomain
@subdomain
end

end end


end end
4 changes: 2 additions & 2 deletions lib/ress/category_collection.rb → lib/ress/config.rb
@@ -1,8 +1,8 @@
module Ress module Ress


class CategoryCollection class Config


attr_accessor :include_modernizr attr_accessor :include_modernizr, :replace_canonical_subdomain
attr_reader :canonical_version, :alternate_versions attr_reader :canonical_version, :alternate_versions


def initialize def initialize
Expand Down
81 changes: 81 additions & 0 deletions lib/ress/subdomain.rb
@@ -0,0 +1,81 @@
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] unless subdomain.empty?
begin
return build_url(protocol, subdomain, fullpath) if matches?(subdomain)
end while( subdomain.slice!(/^[^\.]+\.?/) )
end

private

def build_url(protocol, subdomain, fullpath)
subdomain.empty? ? "#{protocol}#{fullpath}" : "#{protocol}#{subdomain}.#{fullpath}"
end

end

end

end
2 changes: 1 addition & 1 deletion lib/ress/version.rb
@@ -1,3 +1,3 @@
module Ress module Ress
VERSION = "0.0.6" VERSION = "0.0.10"
end end
1 change: 1 addition & 0 deletions lib/ress/view_helpers.rb
Expand Up @@ -9,6 +9,7 @@ def ress_annotation_tags(options={})


path = "#{request.host_with_port}#{fullpath}" path = "#{request.host_with_port}#{fullpath}"
html = if canonical_request? html = if canonical_request?
path.gsub!("#{request.subdomain}.", '') if Ress.replace_canonical_subdomain?
Ress.alternate_versions.map do |category| Ress.alternate_versions.map do |category|
category.link_tag(request.protocol, path, self) category.link_tag(request.protocol, path, self)
end.join end.join
Expand Down
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 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 describe '#matches?' do


context 'with no canonical subdomain' do context 'with no canonical subdomain' do
Expand Down
@@ -1,8 +1,8 @@
require_relative '../../lib/ress' require_relative '../../lib/ress'


describe Ress::CategoryCollection do describe Ress::Config do


let(:collection) { Ress::CategoryCollection.new } let(:collection) { Ress::Config.new }


describe '#add_alternate' do describe '#add_alternate' do


Expand All @@ -27,12 +27,12 @@
describe 'canonical_version' do describe 'canonical_version' do


it 'defaults to a canonical_version with no subdomain' 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 end


it 'can be altered through set_canonical' do it 'can be altered through set_canonical' do
collection.set_canonical :subdomain => 'foo' collection.set_canonical :subdomain => 'foo'
collection.canonical_version.subdomain.should == 'foo' collection.canonical_version.matches?('foo').should be_true
end end


end end
Expand Down

0 comments on commit 6f534ad

Please sign in to comment.