rack-modernizr 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm 1.8.7@rack-modernizr
data/README.md CHANGED
@@ -4,24 +4,62 @@
4
4
 
5
5
  rack-modernizr is a Rack Middleware that includes the Modernizr javascript and stuffs Modernizr's output into a cookie on the first page request.
6
6
 
7
- Include it in your config.ru like so:
7
+ # Installation
8
+
9
+ Include it in your application.rb like so:
10
+
11
+ module ModernizrTestApp
12
+ class Application < Rails::Application
13
+ config.middleware.use Rack::Modernizr
14
+ end
15
+ end
16
+
17
+ or in your config.ru:
18
+
19
+ # Initialize the rails application
20
+ MyApp::Application.initialize!
8
21
 
9
22
  # This file is used by Rack-based servers to start the application.
10
23
 
11
24
  require ::File.expand_path('../config/environment', __FILE__)
12
25
  require 'modernizr'
26
+
27
+ # WARNING: session storage is not working properly with config.ru initialization :/
13
28
  use Rack::Modernizr
14
29
 
15
30
  run MyApp::Application
16
31
 
17
- or environment.rb
32
+ # Usage
18
33
 
19
- # Load the rails application
20
- require File.expand_path('../application', __FILE__)
21
-
22
- config.middleware.use Rack::Modernizr
23
-
24
- # Initialize the rails application
25
- MyApp::Application.initialize!
34
+ In your rails code, Modernizr's client side detected browser functionality is now available from the Rack environment. (w00t!)
35
+
36
+ <%= request.env['X-rack-modernizr'].inspect %>
37
+
38
+ or
39
+
40
+ if 1==request.env['X-rack-modernizr']['video']['h264']
41
+ # do stuff
42
+ end
43
+
44
+ # Features
45
+
46
+ Rack-modernizr chews up 1k of cookie data (yikes!). If you are storing session data in the database or memcache, you can avoid the cookie tax by pushing modernizr data into the session:
47
+
48
+ module ModernizrTestApp
49
+ class Application < Rails::Application
50
+ config.middleware.use Rack::Modernizr, :storage => "session"
51
+ end
52
+ end
53
+
54
+ # TODO
55
+
56
+ (in no particular order)
57
+ - Cool kid .accessorize method, like [rack-flash](http://nakajima.github.com/rack-flash/).
58
+ - Better unit testing for sessions and cookies.
59
+ - Rails helper to clean up retrieval syntax
60
+ - compression to cut down on 1k cookie storage size
61
+
62
+ # Thanks
63
+
64
+ rack-modernizr was inspired by [jamesgpearce](https://github.com/jamesgpearce)'s super awesome [modernizr-server](https://github.com/jamesgpearce/modernizr-server). Some javascript was used from that project.
26
65
 
27
- rack-modernizr was inspired by [jamesgpearce](https://github.com/jamesgpearce)'s super awesome [modernizr-server](https://github.com/jamesgpearce/modernizr-server). Some javascript was used from that project.
@@ -2,33 +2,79 @@ require 'rack'
2
2
 
3
3
  module Rack
4
4
  class Modernizr
5
- include Rack::Utils
5
+ attr_accessor :stash
6
6
 
7
7
  def initialize(app, options = {})
8
8
  @app, @options = app, options
9
9
  @options[:modernizr_js_url] ||= "http://cachedcommons.org/cache/modernizr/1.5.0/javascripts/modernizr-min.js"
10
- @options[:cookie_name] ||= "Modernizr"
10
+ @options[:key_name] ||= "Modernizr"
11
+ @options[:storage] ||= "cookie"
11
12
  end
12
13
 
13
14
  def call(env)
14
15
  @req = Rack::Request.new(env)
16
+
17
+ load_modernizr_from_storage if have_modernizr?
18
+
19
+ if env['PATH_INFO'] == "/rack-modernizr-endpoint.gif"
20
+ return persist_modernizr
21
+ end
22
+
15
23
  status, headers, response = @app.call(env)
16
-
24
+
17
25
  if should_add_modernizr?(status, headers, response)
18
- response = add_modernizr(response)
26
+ response = add_modernizr response
19
27
  fix_content_length(headers, response)
20
28
  end
21
29
 
30
+
22
31
  [status, headers, response]
23
32
  end
24
33
 
34
+ def have_modernizr?
35
+ !storage[@options[:key_name]].nil?
36
+ end
37
+
38
+ def load_modernizr_from_storage
39
+ puts "load_modernizr_from_storage"
40
+ @req.env['X-rack-modernizr'] = Rack::Utils.parse_nested_query(storage[@options[:key_name]])
41
+ end
42
+
25
43
  def should_add_modernizr?(status, headers, response)
26
- !@req.cookies.has_key?( @options[:cookie_name] ) &&
27
- status==200 &&
28
- headers["Content-Type"] &&
29
- headers["Content-Type"].include?("text/html")
44
+ !storage.has_key?( @options[:key_name] ) &&
45
+ status==200 &&
46
+ headers["Content-Type"] &&
47
+ headers["Content-Type"].include?("text/html")
48
+ end
49
+
50
+ def persist_modernizr
51
+ response = Rack::Response.new ["OK"], 200, {}
52
+
53
+ s = @req.env['QUERY_STRING']
54
+
55
+ case @options[:storage]
56
+ when "session"
57
+ @req.env["rack.session"][@options[:key_name]] = s
58
+ when "cookies"
59
+ when "cookie"
60
+ response.set_cookie(@options[:key_name], {:value => s, :path => "/"})
61
+ end
62
+
63
+ response.finish # finish writes out the response in the expected format.
30
64
  end
31
-
65
+
66
+ def storage
67
+ case @options[:storage]
68
+ when "session"
69
+ @req.env["rack.session"] ||= {}
70
+ @req.env["rack.session"]
71
+ when "cookies"
72
+ when "cookie"
73
+ @req.cookies ||= {}
74
+ @req.cookies
75
+ end
76
+ end
77
+
32
78
  def fix_content_length(headers, response)
33
79
  # Set new Content-Length, if it was set before we mutated the response body
34
80
  if headers['Content-Length']
@@ -41,32 +87,27 @@ module Rack
41
87
  response.each{ |s| body << s.to_s }
42
88
  [body.gsub(/\<\/body\>/, "#{modernizr_js}</body>")]
43
89
  end
44
-
90
+
45
91
  def modernizr_js
46
- "<script src=\"#{@options[:modernizr_js_url]}\" type=\"text/javascript\"></script>" +
47
- "<script type=\"text/javascript\">#{set_cookie_js}</script>"
92
+ "<div id='modernizr_img'></div><script src=\"#{@options[:modernizr_js_url]}\" type=\"text/javascript\"></script>" +
93
+ "<script type='text/javascript'>#{set_modernizr_js}</script>"
48
94
  end
49
-
50
- def set_cookie_js
51
- "var m=Modernizr,c='';" +
52
- "for(var f in m){" +
53
- "if(f[0]=='_'){continue;}" +
54
- "var t=typeof m[f];" +
55
- "if(t=='function'){continue;}" +
56
- "c+=(c?'|':'#{@options[:cookie_name]}=')+f+':';" +
57
- "if(t=='object'){" +
58
- "for(var s in m[f]){" +
59
- "c+='/'+s+':'+(m[f][s]?'1':'0');" +
60
- "}" +
61
- "}else{" +
62
- "c+=m[f]?'1':'0';" +
63
- "}" +
64
- "}" +
65
- "c+=';path=/';" +
66
- "try{" +
67
- "document.cookie=c;" +
68
- "}catch(e){}" +
69
- ""
95
+
96
+ def set_modernizr_js
97
+ "var m=Modernizr,c='';" +
98
+ "for(var f in m){" +
99
+ "if(f[0]=='_'){continue;}" +
100
+ "var t=typeof m[f];" +
101
+ "if(t=='function'){continue;}" +
102
+ "if(t=='object'){" +
103
+ "for(var s in m[f]){" +
104
+ "c+='&'+f+'['+s+']='+(m[f][s]?'1':'0');" +
105
+ "}" +
106
+ "}else{" +
107
+ "c+='&'+f+'='+(m[f]?'1':'0');" +
108
+ "}" +
109
+ "}" +
110
+ "document.getElementById('modernizr_img').innerHTML = \"<img src='/rack-modernizr-endpoint.gif?\"+c+\"'></img>\";"
70
111
  end
71
112
  end
72
- end
113
+ end
@@ -1,3 +1,3 @@
1
1
  module Modernizr
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -36,15 +36,16 @@ context "Rack::Modernizr" do
36
36
  app = lambda { |env| [200, {'Content-Type' => 'text/html; charset=utf-8'}, [test_body]] }
37
37
  request = Rack::MockRequest.env_for("/test.html")
38
38
  body = Rack::Modernizr.new(app, :modernizr_js_url => "http://distinctive.domain.com/modernizr.js").call(request).last
39
- body[0].should.include? "distinctive.domain.com"
39
+ body[0].should.include? "http://distinctive.domain.com/modernizr.js"
40
40
  end
41
41
 
42
42
  specify "should use cookie name if initialized" do
43
43
  test_body = "<html><body>Hello World</body></html>"
44
44
  app = lambda { |env| [200, {'Content-Type' => 'text/html; charset=utf-8'}, [test_body]] }
45
- request = Rack::MockRequest.env_for("/test.html")
46
- body = Rack::Modernizr.new(app, :cookie_name => "distinctive_name").call(request).last
47
- body[0].should.include? "distinctive_name"
45
+ request = Rack::MockRequest.env_for("/rack-modernizr-endpoint.gif?a=b&c=d&e=f")
46
+ status, headers, response = Rack::Modernizr.new(app, {:key_name => "distinctive_name", :storage => "cookie"}).call(request)
47
+ headers['Set-Cookie'].should.not.be.nil
48
+ headers['Set-Cookie'].should.include? "distinctive_name"
48
49
  end
49
50
 
50
51
  specify "should work if request body is fragmented" do
@@ -80,15 +81,14 @@ context "Rack::Modernizr" do
80
81
  end
81
82
  end
82
83
 
83
-
84
+ # cookie storage
84
85
  context "when a modernizr cookie has already been set" do
85
86
  specify "should not mess with the response in any way" do
86
87
  test_body = "<html><body>Hello World</body></html>"
87
88
  app = lambda { |env| [200, {'Content-Type' => 'text/html'}, [test_body]] }
88
- request = Rack::MockRequest.env_for("/test.html", "HTTP_COOKIE" => "Modernizr=blarghfasel")
89
- body = Rack::Modernizr.new(app).call(request).last
90
- puts body[0]
91
- body[0].should.not.include? "script"
89
+ request = Rack::MockRequest.env_for("/test.html", "HTTP_COOKIE" => "Modernizr=a")
90
+ status, headers, response = Rack::Modernizr.new(app, :storage => 'cookie').call(request)
91
+ response[0].should.not.include? "script"
92
92
  end
93
93
  end
94
94
  end
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-modernizr
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 27
4
5
  prerelease: false
5
6
  segments:
6
7
  - 0
7
8
  - 0
8
- - 1
9
- version: 0.0.1
9
+ - 2
10
+ version: 0.0.2
10
11
  platform: ruby
11
12
  authors:
12
13
  - Marshall Yount
@@ -14,7 +15,7 @@ autorequire:
14
15
  bindir: bin
15
16
  cert_chain: []
16
17
 
17
- date: 2010-11-08 00:00:00 -06:00
18
+ date: 2010-11-14 00:00:00 -06:00
18
19
  default_executable:
19
20
  dependencies:
20
21
  - !ruby/object:Gem::Dependency
@@ -25,6 +26,7 @@ dependencies:
25
26
  requirements:
26
27
  - - ">="
27
28
  - !ruby/object:Gem::Version
29
+ hash: 3
28
30
  segments:
29
31
  - 0
30
32
  version: "0"
@@ -38,6 +40,7 @@ dependencies:
38
40
  requirements:
39
41
  - - ">="
40
42
  - !ruby/object:Gem::Version
43
+ hash: 59
41
44
  segments:
42
45
  - 0
43
46
  - 9
@@ -53,6 +56,7 @@ dependencies:
53
56
  requirements:
54
57
  - - ">="
55
58
  - !ruby/object:Gem::Version
59
+ hash: 3
56
60
  segments:
57
61
  - 0
58
62
  version: "0"
@@ -69,6 +73,7 @@ extra_rdoc_files: []
69
73
 
70
74
  files:
71
75
  - .gitignore
76
+ - .rvmrc
72
77
  - Gemfile
73
78
  - Gemfile.lock
74
79
  - LICENSE
@@ -92,6 +97,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
92
97
  requirements:
93
98
  - - ">="
94
99
  - !ruby/object:Gem::Version
100
+ hash: 3
95
101
  segments:
96
102
  - 0
97
103
  version: "0"
@@ -100,6 +106,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
100
106
  requirements:
101
107
  - - ">="
102
108
  - !ruby/object:Gem::Version
109
+ hash: 3
103
110
  segments:
104
111
  - 0
105
112
  version: "0"