turbograft 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b2589fafda558edc016e256e95e3e3d05fb231b0
4
+ data.tar.gz: 68146f1fa64c8132aea61ebf0d48f4a4622792c6
5
+ SHA512:
6
+ metadata.gz: d0559b8235247a2e0a6cde2491bccd14846137a0e5433791694210e111f0a99e383bb2577c2b44349b034c6bb9cd7ac2280148ab8c484e52bd833519637c1018
7
+ data.tar.gz: e2c0ff61852c4b7ec643ee8cc486af92c1d5905b454bc485ef4cdece46fb72fade63b9cd40f4680fa676cba523f841670abc0571042d34701d58f59188f5f1e5
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2014 Shopify Inc.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,42 @@
1
+ # TurboGraft
2
+
3
+ It's like turbolinks, but with partial page replacement and tests
4
+
5
+ `Graft` - (noun) a shoot or twig inserted into a slit on the trunk or stem of a living plant, from which it receives sap.
6
+
7
+ In botony, one can take parts of a tree and splice it onto another tree. The DOM is a tree. In this library, we're cutting off sub-trees of the DOM and splicing new ones on.
8
+
9
+ ## Status
10
+ [![Gem Version](https://badge.fury.io/rb/turbograft.svg)](http://badge.fury.io/rb/turbograft)
11
+ [![Build Status](https://api.travis-ci.org/Shopify/turbograft.svg)](http://travis-ci.org/Shopify/turbograft)
12
+
13
+ ## Installation
14
+
15
+ Add this line to your application's Gemfile:
16
+
17
+ gem 'turbograft'
18
+
19
+ And then execute:
20
+
21
+ $ bundle
22
+
23
+ Or install it yourself as:
24
+
25
+ $ gem install turbograft
26
+
27
+ ## Usage
28
+
29
+ TODO
30
+
31
+ ## Example App
32
+
33
+ cd test/example
34
+ bundle exec rails server
35
+
36
+ ## Contributing
37
+
38
+ 1. Fork it ( http://github.com/<my-github-username>/turbograft/fork )
39
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
40
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
41
+ 4. Push to the branch (`git push origin my-new-feature`)
42
+ 5. Create new Pull Request
@@ -0,0 +1,10 @@
1
+ module TurboGraft
2
+ # Sets a request_method cookie containing the request method of the current request.
3
+ # The Turbolinks script will not initialize if this cookie is set to anything other than GET.
4
+ module Cookies
5
+ private
6
+ def set_request_method_cookie
7
+ cookies[:request_method] = request.request_method
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,15 @@
1
+ module TurboGraft
2
+ # Provides a means of using Turbolinks to perform redirects. The server
3
+ # will respond with a JavaScript call to Turbolinks.visit(url).
4
+ module Redirection
5
+ extend ActiveSupport::Concern
6
+
7
+ def redirect_via_turbolinks_to(url = {}, response_status = {})
8
+ redirect_to(url, response_status)
9
+
10
+ self.status = 200
11
+ self.response_body = "Turbolinks.visit('#{location}');"
12
+ response.content_type = Mime::JS
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,3 @@
1
+ module TurboGraft
2
+ VERSION = '0.0.4'
3
+ end
@@ -0,0 +1,21 @@
1
+ module TurboGraft
2
+ # Changes the response status to 403 Forbidden if all of these conditions are true:
3
+ # - The current request originated from Turbolinks
4
+ # - The request is being redirected to a different domain
5
+ module XDomainBlocker
6
+ private
7
+ def same_origin?(a, b)
8
+ a = URI.parse URI.escape(a)
9
+ b = URI.parse URI.escape(b)
10
+ [a.scheme, a.host, a.port] == [b.scheme, b.host, b.port]
11
+ end
12
+
13
+ def abort_xdomain_redirect
14
+ to_uri = response.headers['Location'] || ""
15
+ current = request.headers['X-XHR-Referer'] || ""
16
+ unless to_uri.blank? || current.blank? || same_origin?(current, to_uri)
17
+ self.status = 403
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,46 @@
1
+ module TurboGraft
2
+ # Intercepts calls to _compute_redirect_to_location (used by redirect_to) for two purposes.
3
+ #
4
+ # 1. Corrects the behavior of redirect_to with the :back option by using the X-XHR-Referer
5
+ # request header instead of the standard Referer request header.
6
+ #
7
+ # 2. Stores the return value (the redirect target url) to persist through to the redirect
8
+ # request, where it will be used to set the X-XHR-Redirected-To response header. The
9
+ # Turbolinks script will detect the header and use replaceState to reflect the redirected
10
+ # url.
11
+ module XHRHeaders
12
+ extend ActiveSupport::Concern
13
+
14
+ def _compute_redirect_to_location(*args)
15
+ options, request = _normalize_redirect_params(args)
16
+
17
+ store_for_turbolinks begin
18
+ if options == :back && request.headers["X-XHR-Referer"]
19
+ super(*[(request if args.length == 2), request.headers["X-XHR-Referer"]].compact)
20
+ else
21
+ super(*args)
22
+ end
23
+ end
24
+ end
25
+
26
+ private
27
+ def store_for_turbolinks(url)
28
+ session[:_turbolinks_redirect_to] = url if request.headers["X-XHR-Referer"]
29
+ url
30
+ end
31
+
32
+ def set_xhr_redirected_to
33
+ if session[:_turbolinks_redirect_to]
34
+ response.headers['X-XHR-Redirected-To'] = session.delete :_turbolinks_redirect_to
35
+ end
36
+ end
37
+
38
+ # Ensure backwards compatibility
39
+ # Rails < 4.2: _compute_redirect_to_location(options)
40
+ # Rails >= 4.2: _compute_redirect_to_location(request, options)
41
+ def _normalize_redirect_params(args)
42
+ options, req = args.reverse
43
+ [options, req || request]
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,15 @@
1
+ module TurboGraft
2
+ # Corrects the behavior of url_for (and link_to, which uses url_for) with the :back
3
+ # option by using the X-XHR-Referer request header instead of the standard Referer
4
+ # request header.
5
+ module XHRUrlFor
6
+ def self.included(base)
7
+ base.alias_method_chain :url_for, :xhr_referer
8
+ end
9
+
10
+ def url_for_with_xhr_referer(options = {})
11
+ options = (controller.request.headers["X-XHR-Referer"] || options) if options == :back
12
+ url_for_without_xhr_referer options
13
+ end
14
+ end
15
+ end
data/lib/turbograft.rb ADDED
@@ -0,0 +1,36 @@
1
+ require "rails"
2
+ require "active_support"
3
+
4
+ require "turbograft/version"
5
+ require "turbograft/xhr_headers"
6
+ require "turbograft/xhr_url_for"
7
+ require "turbograft/cookies"
8
+ require "turbograft/x_domain_blocker"
9
+ require "turbograft/redirection"
10
+
11
+ module TurboGraft
12
+ class Engine < ::Rails::Engine
13
+ initializer :turbograft do |config|
14
+ ActiveSupport.on_load(:action_controller) do
15
+ ActionController::Base.class_eval do
16
+ include XHRHeaders, Cookies, XDomainBlocker, Redirection
17
+ before_filter :set_xhr_redirected_to, :set_request_method_cookie
18
+ after_filter :abort_xdomain_redirect
19
+ end
20
+
21
+ ActionDispatch::Request.class_eval do
22
+ def referer
23
+ self.headers['X-XHR-Referer'] || super
24
+ end
25
+ alias referrer referer
26
+ end
27
+ end
28
+
29
+ ActiveSupport.on_load(:action_view) do
30
+ (ActionView::RoutingUrlFor rescue ActionView::Helpers::UrlHelper).module_eval do
31
+ include XHRUrlFor
32
+ end
33
+ end unless RUBY_VERSION =~ /^1\.8/
34
+ end
35
+ end
36
+ end
metadata ADDED
@@ -0,0 +1,227 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: turbograft
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.4
5
+ platform: ruby
6
+ authors:
7
+ - Kristian Plettenberg-Dussault
8
+ - Justin Li
9
+ - Nicholas Simmons
10
+ - Tyler Mercier
11
+ - Anthony Cameron
12
+ - Patrick Donovan
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+ date: 2014-09-24 00:00:00.000000000 Z
17
+ dependencies:
18
+ - !ruby/object:Gem::Dependency
19
+ name: coffee-rails
20
+ requirement: !ruby/object:Gem::Requirement
21
+ requirements:
22
+ - - ">="
23
+ - !ruby/object:Gem::Version
24
+ version: '0'
25
+ type: :runtime
26
+ prerelease: false
27
+ version_requirements: !ruby/object:Gem::Requirement
28
+ requirements:
29
+ - - ">="
30
+ - !ruby/object:Gem::Version
31
+ version: '0'
32
+ - !ruby/object:Gem::Dependency
33
+ name: bundler
34
+ requirement: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - ">="
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ type: :development
40
+ prerelease: false
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rake
48
+ requirement: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ type: :development
54
+ prerelease: false
55
+ version_requirements: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: '0'
60
+ - !ruby/object:Gem::Dependency
61
+ name: rails
62
+ requirement: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ type: :development
68
+ prerelease: false
69
+ version_requirements: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ - !ruby/object:Gem::Dependency
75
+ name: jquery-rails
76
+ requirement: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ type: :development
82
+ prerelease: false
83
+ version_requirements: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ - !ruby/object:Gem::Dependency
89
+ name: minitest-reporters
90
+ requirement: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ type: :development
96
+ prerelease: false
97
+ version_requirements: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ - !ruby/object:Gem::Dependency
103
+ name: capybara
104
+ requirement: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ type: :development
110
+ prerelease: false
111
+ version_requirements: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ - !ruby/object:Gem::Dependency
117
+ name: selenium-webdriver
118
+ requirement: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ version: '0'
123
+ type: :development
124
+ prerelease: false
125
+ version_requirements: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - ">="
128
+ - !ruby/object:Gem::Version
129
+ version: '0'
130
+ - !ruby/object:Gem::Dependency
131
+ name: teaspoon
132
+ requirement: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - ">="
135
+ - !ruby/object:Gem::Version
136
+ version: '0'
137
+ type: :development
138
+ prerelease: false
139
+ version_requirements: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - ">="
142
+ - !ruby/object:Gem::Version
143
+ version: '0'
144
+ - !ruby/object:Gem::Dependency
145
+ name: sqlite3
146
+ requirement: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - ">="
149
+ - !ruby/object:Gem::Version
150
+ version: '0'
151
+ type: :development
152
+ prerelease: false
153
+ version_requirements: !ruby/object:Gem::Requirement
154
+ requirements:
155
+ - - ">="
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
158
+ - !ruby/object:Gem::Dependency
159
+ name: thin
160
+ requirement: !ruby/object:Gem::Requirement
161
+ requirements:
162
+ - - ">="
163
+ - !ruby/object:Gem::Version
164
+ version: '0'
165
+ type: :development
166
+ prerelease: false
167
+ version_requirements: !ruby/object:Gem::Requirement
168
+ requirements:
169
+ - - ">="
170
+ - !ruby/object:Gem::Version
171
+ version: '0'
172
+ - !ruby/object:Gem::Dependency
173
+ name: byebug
174
+ requirement: !ruby/object:Gem::Requirement
175
+ requirements:
176
+ - - ">="
177
+ - !ruby/object:Gem::Version
178
+ version: '0'
179
+ type: :development
180
+ prerelease: false
181
+ version_requirements: !ruby/object:Gem::Requirement
182
+ requirements:
183
+ - - ">="
184
+ - !ruby/object:Gem::Version
185
+ version: '0'
186
+ description: It's like turbolinks, but with partial page replacement and tests
187
+ email:
188
+ - tylermercier@gmail.com
189
+ executables: []
190
+ extensions: []
191
+ extra_rdoc_files: []
192
+ files:
193
+ - lib/turbograft.rb
194
+ - lib/turbograft/cookies.rb
195
+ - lib/turbograft/redirection.rb
196
+ - lib/turbograft/version.rb
197
+ - lib/turbograft/x_domain_blocker.rb
198
+ - lib/turbograft/xhr_headers.rb
199
+ - lib/turbograft/xhr_url_for.rb
200
+ - README.md
201
+ - MIT-LICENSE
202
+ homepage: https://github.com/Shopify/turbograft
203
+ licenses:
204
+ - MIT
205
+ metadata: {}
206
+ post_install_message:
207
+ rdoc_options: []
208
+ require_paths:
209
+ - lib
210
+ required_ruby_version: !ruby/object:Gem::Requirement
211
+ requirements:
212
+ - - ">="
213
+ - !ruby/object:Gem::Version
214
+ version: '0'
215
+ required_rubygems_version: !ruby/object:Gem::Requirement
216
+ requirements:
217
+ - - ">="
218
+ - !ruby/object:Gem::Version
219
+ version: '0'
220
+ requirements: []
221
+ rubyforge_project:
222
+ rubygems_version: 2.0.14
223
+ signing_key:
224
+ specification_version: 4
225
+ summary: turbolinks with partial page replacement
226
+ test_files: []
227
+ has_rdoc: