rabl 0.6.10 → 0.6.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,13 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 0.6.11
4
+
5
+ * Changes send to __send__ (Thanks @alindeman)
6
+ * Change object/collection checks to :map instead of :each
7
+ * Adds support for auto-escaping attribute configuration (Thanks @databyte)
8
+ * Adds support for configuration of view_paths (Thanks @ivanvanderbyl)
9
+ * Fix issue with helpers caching check
10
+
3
11
  ## 0.6.10
4
12
 
5
13
  * Fixes expected behavior with nil and collection keyword
data/README.md CHANGED
@@ -101,6 +101,7 @@ Rabl.configure do |config|
101
101
  # Commented as these are defaults
102
102
  # config.cache_all_output = false
103
103
  # config.cache_sources = false
104
+ # config.escape_all_output = false
104
105
  # config.json_engine = nil # Any multi\_json engines
105
106
  # config.msgpack_engine = nil # Defaults to ::MessagePack
106
107
  # config.bson_engine = nil # Defaults to ::BSON
@@ -112,6 +113,7 @@ Rabl.configure do |config|
112
113
  # config.include_xml_root = false
113
114
  # config.enable_json_callbacks = false
114
115
  # config.xml_options = { :dasherize => true, :skip_types => false }
116
+ # config.view_paths = []
115
117
  end
116
118
  ```
117
119
 
@@ -122,10 +124,16 @@ output if the incoming request has a 'callback' parameter.
122
124
  If `cache_sources` is set to `true`, template lookups will be cached for improved performance.
123
125
  The cache can be reset manually by running `Rabl.reset_source_cache!` within your application.
124
126
 
125
- If `cache_all_output` is set to `true` then every template including each individual template used as part of a collection will be cached separately.
127
+ If `cache_all_output` is set to `true`, every template including each individual template used as part of a collection will be cached separately.
126
128
  Additionally, anything within child, glue and partial will also be cached separately.
127
129
  To cache just a single template, see the section titled 'Caching' below.
128
130
 
131
+ If `escape_all_output` is set to `true` and ActiveSupport is available, attribute output will be escaped using [ERB::Util.html_escape](http://corelib.rubyonrails.org/classes/ERB/Util.html).
132
+ Custom nodes will not be escaped, use `ERB::Util.h(value)`.
133
+
134
+ If `view_paths` is set to a path, this view path will be checked for every rabl template within your application.
135
+ Add to this path especially when including Rabl in an engine and using view paths within a another Rails app.
136
+
129
137
  Note that the `json_engine` option uses [multi_json](http://intridea.com/2010/6/14/multi-json-the-swappable-json-handler) engine
130
138
  defaults so that in most cases you **don't need to configure this** directly. If you wish to use yajl as
131
139
  the primary JSON encoding engine simply add that to your Gemfile:
@@ -139,7 +147,7 @@ and RABL will automatically start using that engine for encoding your JSON respo
139
147
 
140
148
  ### Format Configuration ###
141
149
 
142
- RABL supports configuration for MessagePack, BSON, and Plist. Check the
150
+ RABL supports configuration for MessagePack, BSON, and Plist. Check the
143
151
  [Format Configuration](https://github.com/nesquena/rabl/wiki/Configuring-Formats) page for more details.
144
152
 
145
153
  ## Usage ##
@@ -380,7 +388,7 @@ Note that RABL can be nested arbitrarily deep within child nodes to allow for th
380
388
 
381
389
  ### Caching ###
382
390
 
383
- RABL has built-in caching support for templates leveraging fragment caching strategies. Note that caching is currently **only available** for but support for other frameworks is planned in a future release. Simplest caching usage is:
391
+ RABL has built-in caching support for templates leveraging fragment caching strategies. Note that caching is currently **only available** for Rails but support for other frameworks is planned in a future release. Simplest caching usage is:
384
392
 
385
393
  ```ruby
386
394
  # app/views/users/show.json.rabl
@@ -490,7 +498,7 @@ Thanks to [Miso](http://gomiso.com) for allowing me to create this for our appli
490
498
  * [Nathan Esquenazi](https://github.com/nesquena) - Creator of the project
491
499
  * [Arthur Chiu](https://github.com/achiu) - Core Maintainer, Riot Testing Guru
492
500
  * [Tim Lee](https://github.com/timothy1ee) - RABL was a great name chosen by the Miso CTO.
493
- * [David Sommers](https://github.com/databyte) - Enhanced template resolution and added caching support
501
+ * [David Sommers](https://github.com/databyte) - Template resolution, caching support, and much more
494
502
  * [Rick Thomas](https://github.com/rickthomasjr) - Added options for extends and Sinatra testing
495
503
  * [Benjamin Yu](https://github.com/byu) - Added msgpack format support
496
504
  * [Chris Kimpton](https://github.com/kimptoc) - Helping with documentation and wiki
@@ -21,7 +21,7 @@ context "PostsController" do
21
21
 
22
22
  context "for index action" do
23
23
  setup do
24
- get "/posts", format: :json
24
+ get "/posts", :format => :json
25
25
  end
26
26
 
27
27
  # Attributes (regular)
@@ -74,7 +74,7 @@ context "PostsController" do
74
74
 
75
75
  context "for show action" do
76
76
  setup do
77
- get "/posts/#{@post1.id}", format: :json
77
+ get "/posts/#{@post1.id}", :format => :json
78
78
  json_output['post']
79
79
  end
80
80
 
@@ -21,7 +21,7 @@ context "PostsController" do
21
21
 
22
22
  context "for index action" do
23
23
  setup do
24
- get "/posts", format: :json
24
+ get "/posts", :format => :json
25
25
  end
26
26
 
27
27
  # Attributes (regular)
@@ -74,7 +74,7 @@ context "PostsController" do
74
74
 
75
75
  context "for show action" do
76
76
  setup do
77
- get "/posts/#{@post1.id}", format: :json
77
+ get "/posts/#{@post1.id}", :format => :json
78
78
  json_output['post']
79
79
  end
80
80
 
@@ -21,7 +21,7 @@ context "PostsController" do
21
21
 
22
22
  context "for index action" do
23
23
  setup do
24
- get "/posts", format: :json
24
+ get "/posts", :format => :json
25
25
  end
26
26
 
27
27
  # Attributes (regular)
@@ -74,7 +74,7 @@ context "PostsController" do
74
74
 
75
75
  context "for show action" do
76
76
  setup do
77
- get "/posts/#{@post1.id}", format: :json
77
+ get "/posts/#{@post1.id}", :format => :json
78
78
  json_output['post']
79
79
  end
80
80
 
@@ -17,7 +17,7 @@ context "PostsController" do
17
17
  Post.delete_all
18
18
  @post1 = Post.create(:title => "Foo", :body => "Bar", :user_id => @user1.id)
19
19
  @post2 = Post.create(:title => "Baz", :body => "Bah", :user_id => @user2.id)
20
- @post3 = Post.create(:title => "Kaz", :body => "Paz", :user_id => @user3.id)
20
+ @post3 = Post.create(:title => "Kaz", :body => "<script>alert('xss & test');</script>", :user_id => @user3.id)
21
21
  @posts = [@post1, @post2, @post3]
22
22
  end
23
23
 
@@ -74,6 +74,32 @@ context "PostsController" do
74
74
  end.includes(:created_by_admin)
75
75
  end # index action, json
76
76
 
77
+ context "escaping output in index action" do
78
+ context "for first post" do
79
+ setup do
80
+ Rabl.configuration.escape_all_output = true
81
+ get "/posts/#{@post1.id}", format: :json
82
+ json_output['post']
83
+ end
84
+
85
+ # Attributes (regular)
86
+ asserts("contains post title") { topic['title'] }.equals { @post1.title }
87
+ asserts("contains post body") { topic['body'] }.equals { @post1.body }
88
+ end
89
+
90
+ context "for third post with script tags" do
91
+ setup do
92
+ Rabl.configuration.escape_all_output = true
93
+ get "/posts/#{@post3.id}", format: :json
94
+ json_output['post']
95
+ end
96
+
97
+ # Attributes (regular)
98
+ asserts("contains post title") { topic['title'] }.equals { @post3.title }
99
+ asserts("contains escaped post body") { topic['body'] }.equals { ERB::Util.h(@post3.body) }
100
+ end
101
+ end # escaping output
102
+
77
103
  context "for show action" do
78
104
  setup do
79
105
  get "/posts/#{@post1.id}", format: :json
@@ -85,7 +111,7 @@ context "PostsController" do
85
111
  asserts("contains post body") { topic['body'] }.equals { @post1.body }
86
112
 
87
113
  # Attributes (custom name)
88
- asserts("contains post posted_at") { topic['posted_at'] }.equals { @post1.created_at.iso8601 }
114
+ asserts("contains post posted_at") { topic['posted_at'] }.equals { @post1.created_at.utc.to_s }
89
115
 
90
116
  # Child
91
117
  asserts("contains post user child username") { topic["user"]["username"] }.equals { @post1.user.username }
@@ -35,7 +35,7 @@ context "UsersController" do
35
35
  # Attributes (custom name)
36
36
  asserts("contains registered_at") do
37
37
  json_output.map { |u| u["user"]["registered_at"] }
38
- end.equals { @users.map(&:created_at).map(&:iso8601) }
38
+ end.equals { @users.map(&:created_at).map(&:utc).map(&:to_s) }
39
39
 
40
40
  # Node (renders based on attribute)
41
41
  asserts("contains role") do
@@ -64,7 +64,7 @@ context "UsersController" do
64
64
  asserts("contains email") { json_output["person"]["email"] }.equals { @user1.email }
65
65
  asserts("contains location") { json_output["person"]["location"] }.equals { @user1.location }
66
66
  # Attributes (custom name)
67
- asserts("contains registered_at") { json_output["person"]["registered_at"] }.equals { @user1.created_at.iso8601 }
67
+ asserts("contains registered_at") { json_output["person"]["registered_at"] }.equals { @user1.created_at.utc.to_s }
68
68
  # Node (renders based on attribute)
69
69
  asserts("contains role node") { json_output["person"]["role"] }.equals "normal"
70
70
 
@@ -21,7 +21,7 @@ context "PostsController" do
21
21
 
22
22
  context "for index action" do
23
23
  setup do
24
- get "/posts", format: :json
24
+ get "/posts", :format => :json
25
25
  end
26
26
 
27
27
  # Attributes (regular)
@@ -74,7 +74,7 @@ context "PostsController" do
74
74
 
75
75
  context "for show action" do
76
76
  setup do
77
- get "/posts/#{@post1.id}", format: :json
77
+ get "/posts/#{@post1.id}", :format => :json
78
78
  json_output['post']
79
79
  end
80
80
 
@@ -63,7 +63,7 @@ module Rabl
63
63
  # Indicates an attribute or method should be included in the json output
64
64
  # attribute :foo, :as => "bar"
65
65
  def attribute(name, options={})
66
- @_result[options[:as] || name] = @_object.send(name) if @_object && @_object.respond_to?(name)
66
+ @_result[options[:as] || name] = data_object_attribute(name) if @_object && @_object.respond_to?(name)
67
67
  end
68
68
  alias_method :attributes, :attribute
69
69
 
@@ -36,6 +36,8 @@ module Rabl
36
36
  attr_writer :xml_options
37
37
  attr_accessor :cache_sources
38
38
  attr_accessor :cache_all_output
39
+ attr_accessor :escape_all_output
40
+ attr_accessor :view_paths
39
41
 
40
42
  DEFAULT_XML_OPTIONS = { :dasherize => true, :skip_types => false }
41
43
 
@@ -55,6 +57,8 @@ module Rabl
55
57
  @xml_options = {}
56
58
  @cache_sources = false
57
59
  @cache_all_output = false
60
+ @escape_all_output = false
61
+ @view_paths = []
58
62
  end
59
63
 
60
64
  # @param [Symbol, String, #encode] engine_name The name of a JSON engine,
@@ -94,7 +98,7 @@ module Rabl
94
98
  #
95
99
  # @param [Symbol] option Key for a given attribute
96
100
  def [](option)
97
- send(option)
101
+ __send__(option)
98
102
  end
99
103
 
100
104
  # Returns merged default and inputted xml options
@@ -176,7 +176,7 @@ module Rabl
176
176
  # Includes a helper module with a RABL template
177
177
  # helper ExampleHelper
178
178
  def helper(*klazzes)
179
- klazzes.each { |klazz| self.class.send(:include, klazz) }
179
+ klazzes.each { |klazz| self.class.__send__(:include, klazz) }
180
180
  end
181
181
  alias_method :helpers, :helper
182
182
 
@@ -225,7 +225,7 @@ module Rabl
225
225
 
226
226
  # Supports calling helpers defined for the template scope using method_missing hook
227
227
  def method_missing(name, *args, &block)
228
- context_scope.respond_to?(name) ? context_scope.send(name, *args, &block) : super
228
+ context_scope.respond_to?(name, true) ? context_scope.__send__(name, *args, &block) : super
229
229
  end
230
230
 
231
231
  def copy_instance_variables_from(object, exclude = []) #:nodoc:
@@ -8,7 +8,12 @@ module Rabl
8
8
  # data_object(:user => :person) => @_object.send(:user)
9
9
  def data_object(data)
10
10
  data = (data.is_a?(Hash) && data.keys.size == 1) ? data.keys.first : data
11
- data.is_a?(Symbol) && @_object ? @_object.send(data) : data
11
+ data.is_a?(Symbol) && @_object ? @_object.__send__(data) : data
12
+ end
13
+
14
+ # data_object_attribute(data) => @_object.send(data)
15
+ def data_object_attribute(data)
16
+ escape_output @_object.__send__(data)
12
17
  end
13
18
 
14
19
  # data_name(data) => "user"
@@ -19,7 +24,7 @@ module Rabl
19
24
  def data_name(data)
20
25
  return nil unless data # nil or false
21
26
  return data.values.first if data.is_a?(Hash) # @user => :user
22
- data = @_object.send(data) if data.is_a?(Symbol) && @_object # :address
27
+ data = @_object.__send__(data) if data.is_a?(Symbol) && @_object # :address
23
28
  if is_collection?(data) && data.respond_to?(:first) # data collection
24
29
  data_name(data.first).to_s.pluralize if data.first.present?
25
30
  elsif is_object?(data) # actual data object
@@ -50,12 +55,12 @@ module Rabl
50
55
  # is_object?([]) => false
51
56
  # is_object?({}) => false
52
57
  def is_object?(obj)
53
- obj && !data_object(obj).respond_to?(:each)
58
+ obj && !data_object(obj).respond_to?(:map)
54
59
  end
55
60
 
56
61
  # Returns true if the obj is a collection of items
57
62
  def is_collection?(obj)
58
- obj && data_object(obj).respond_to?(:each)
63
+ obj && data_object(obj).respond_to?(:map)
59
64
  end
60
65
 
61
66
  # Returns the scope wrapping this engine, used for retrieving data, invoking methods, etc
@@ -87,7 +92,12 @@ module Rabl
87
92
 
88
93
  # Returns true if the cache has been enabled for the application
89
94
  def template_cache_configured?
90
- defined?(Rails) && defined?(ActionController) && ActionController::Base.perform_caching
95
+ defined?(Rails) && defined?(ActionController::Base) && ActionController::Base.perform_caching
96
+ end
97
+
98
+ # Escape output if configured and supported
99
+ def escape_output(data)
100
+ defined?(ERB::Util.h) && Rabl.configuration.escape_all_output ? ERB::Util.h(data) : data
91
101
  end
92
102
 
93
103
  end
@@ -30,21 +30,21 @@ module Rabl
30
30
  # Returns source for a given relative file
31
31
  # fetch_source("show", :view_path => "...") => "...contents..."
32
32
  def fetch_source(file, options={})
33
- Rabl.source_cache(file, options[:view_path]) do
33
+ view_paths = Array(options[:view_path]) + Array(Rabl.configuration.view_paths)
34
+ Rabl.source_cache(file, view_paths) do
34
35
  file_path = if defined?(Padrino) && context_scope.respond_to?(:settings)
35
36
  fetch_padrino_source(file, options)
36
37
  elsif defined?(Rails) && context_scope.respond_to?(:view_paths)
37
- view_path = Array(options[:view_path] || context_scope.view_paths.to_a)
38
- fetch_rails_source(file, options) || fetch_manual_template(view_path, file)
38
+ _view_paths = view_paths + Array(context_scope.view_paths.to_a)
39
+ fetch_rails_source(file, options) || fetch_manual_template(_view_paths, file)
39
40
  elsif defined?(Sinatra) && context_scope.respond_to?(:settings)
40
41
  fetch_sinatra_source(file, options)
41
42
  else # generic template resolution
42
- view_path = Array(options[:view_path])
43
- fetch_manual_template(view_path, file)
43
+ fetch_manual_template(view_paths, file)
44
44
  end
45
45
 
46
46
  unless File.exist?(file_path.to_s)
47
- raise "Cannot find rabl template '#{file}' within registered (#{file_path}) view paths!"
47
+ raise "Cannot find rabl template '#{file}' within registered (#{view_paths.map(&:to_s).inspect}) view paths!"
48
48
  end
49
49
 
50
50
  [File.read(file_path.to_s), file_path.to_s] if file_path
@@ -1,3 +1,3 @@
1
1
  module Rabl
2
- VERSION = "0.6.10"
2
+ VERSION = "0.6.11"
3
3
  end
@@ -4,7 +4,6 @@ require File.expand_path('../../lib/rabl/template', __FILE__)
4
4
  require File.expand_path('../models/user', __FILE__)
5
5
 
6
6
  context "Rabl::Engine" do
7
-
8
7
  helper(:rabl) { |t| RablTemplate.new("code", :format => 'bson') { t } }
9
8
 
10
9
  context "with bson defaults" do
@@ -16,7 +15,6 @@ context "Rabl::Engine" do
16
15
  end
17
16
 
18
17
  context "#object" do
19
-
20
18
  asserts "that it sets data source" do
21
19
  template = rabl %q{
22
20
  object @user
@@ -37,7 +35,6 @@ context "Rabl::Engine" do
37
35
  end
38
36
 
39
37
  context "#collection" do
40
-
41
38
  asserts "that it sets object to be casted as a simple array" do
42
39
  template = rabl %{
43
40
  collection @users
@@ -55,11 +52,9 @@ context "Rabl::Engine" do
55
52
  scope.instance_variable_set :@users, [User.new, User.new]
56
53
  template.render(scope).split("").sort
57
54
  end.equals "<\x00\x00\x00\x04people\x00/\x00\x00\x00\x030\x00\x12\x00\x00\x00\x03person\x00\x05\x00\x00\x00\x00\x00\x031\x00\x12\x00\x00\x00\x03person\x00\x05\x00\x00\x00\x00\x00\x00\x00".split("").sort
58
-
59
55
  end
60
56
 
61
57
  context "#attribute" do
62
-
63
58
  asserts "that it adds an attribute or method to be included in output" do
64
59
  template = rabl %{
65
60
  object @user
@@ -89,11 +84,9 @@ context "Rabl::Engine" do
89
84
  scope.instance_variable_set :@user, User.new(:name => 'irvine')
90
85
  template.render(scope).split("").sort
91
86
  end.equals "!\x00\x00\x00\x03user\x00\x16\x00\x00\x00\x02city\x00\a\x00\x00\x00irvine\x00\x00\x00".split("").sort
92
-
93
87
  end
94
88
 
95
89
  context "#code" do
96
-
97
90
  asserts "that it can create an arbitraty code node" do
98
91
  template = rabl %{
99
92
  code(:foo) { 'bar' }
@@ -107,11 +100,9 @@ context "Rabl::Engine" do
107
100
  }
108
101
  template.render(Object.new).split("").sort
109
102
  end.equals "\x05\x00\x00\x00\x00".split("").sort
110
-
111
103
  end
112
104
 
113
105
  context "#child" do
114
-
115
106
  asserts "that it can create a child node" do
116
107
  template = rabl %{
117
108
  object @user
@@ -136,7 +127,6 @@ context "Rabl::Engine" do
136
127
  end
137
128
 
138
129
  context "#glue" do
139
-
140
130
  asserts "that it glues data from a child node" do
141
131
  template = rabl %{
142
132
  object @user
@@ -190,7 +180,6 @@ context "Rabl::Engine" do
190
180
  end
191
181
 
192
182
  context "#object" do
193
-
194
183
  asserts "that it sets data source" do
195
184
  template = rabl %q{
196
185
  object @user
@@ -211,7 +200,6 @@ context "Rabl::Engine" do
211
200
  end
212
201
 
213
202
  context "#collection" do
214
-
215
203
  asserts "that it sets object to be casted as a simple array" do
216
204
  template = rabl %{
217
205
  collection @users
@@ -229,11 +217,9 @@ context "Rabl::Engine" do
229
217
  scope.instance_variable_set :@users, [User.new, User.new]
230
218
  template.render(scope).split("").sort
231
219
  end.equals "\"\x00\x00\x00\x04person\x00\x15\x00\x00\x00\x030\x00\x05\x00\x00\x00\x00\x031\x00\x05\x00\x00\x00\x00\x00\x00".split("").sort
232
-
233
220
  end
234
221
 
235
222
  context "#attribute" do
236
-
237
223
  asserts "that it adds an attribute or method to be included in output" do
238
224
  template = rabl %{
239
225
  object @user
@@ -263,11 +249,9 @@ context "Rabl::Engine" do
263
249
  scope.instance_variable_set :@user, User.new(:name => 'irvine')
264
250
  template.render(scope).split("").sort
265
251
  end.equals "\x16\x00\x00\x00\x02city\x00\a\x00\x00\x00irvine\x00\x00".split("").sort
266
-
267
252
  end
268
253
 
269
254
  context "#code" do
270
-
271
255
  asserts "that it can create an arbitraty code node" do
272
256
  template = rabl %{
273
257
  code(:foo) { 'bar' }
@@ -281,11 +265,9 @@ context "Rabl::Engine" do
281
265
  }
282
266
  template.render(Object.new).split("").sort
283
267
  end.equals "\x05\x00\x00\x00\x00".split("").sort
284
-
285
268
  end
286
269
 
287
270
  context "#child" do
288
-
289
271
  asserts "that it can create a child node" do
290
272
  template = rabl %{
291
273
  object @user
@@ -310,7 +292,6 @@ context "Rabl::Engine" do
310
292
  end
311
293
 
312
294
  context "#glue" do
313
-
314
295
  asserts "that it glues data from a child node" do
315
296
  template = rabl %{
316
297
  object @user
@@ -2,7 +2,6 @@ require File.expand_path('../teststrap', __FILE__)
2
2
  require File.expand_path('../models/user', __FILE__)
3
3
 
4
4
  context "Rabl::Builder" do
5
-
6
5
  helper(:builder) { |opt| Rabl::Builder.new(opt) }
7
6
  helper(:build_hash) { |obj, opt| builder(opt).build(obj) }
8
7
 
@@ -10,6 +10,7 @@ context 'Rabl::Configuration' do
10
10
  asserts(:include_json_root).equals true
11
11
  asserts(:include_xml_root).equals false
12
12
  asserts(:enable_json_callbacks).equals false
13
+ asserts(:view_paths).equals []
13
14
  asserts(:json_engine).equals { json_engine }
14
15
  end
15
16
 
@@ -5,7 +5,6 @@ require File.expand_path('../models/user', __FILE__)
5
5
  require File.expand_path('../models/ormless', __FILE__)
6
6
 
7
7
  context "Rabl::Engine" do
8
-
9
8
  helper(:rabl) { |t| RablTemplate.new { t } }
10
9
 
11
10
  context "#initialize" do
@@ -28,5 +28,51 @@ context "Rabl::Helpers" do
28
28
  asserts "returns name of an object" do
29
29
  @helper_class.data_name(@user)
30
30
  end.equals('user')
31
- end
31
+ end # data_name method
32
+
33
+ context "for is_object method" do
34
+ asserts "returns nil if no data" do
35
+ @helper_class.is_object?(nil)
36
+ end.equals(nil)
37
+
38
+ asserts "returns true for an object" do
39
+ @helper_class.is_object?(@user)
40
+ end.equals(true)
41
+
42
+ # asserts "returns true for an object with each" do
43
+ # obj = Class.new { def each; end }
44
+ # @helper_class.is_object?(obj.new)
45
+ # end.equals(true)
46
+
47
+ asserts "returns true for a hash alias" do
48
+ @helper_class.is_object?(@user => :user)
49
+ end.equals(true)
50
+
51
+ asserts "returns false for an array" do
52
+ @helper_class.is_object?([@user])
53
+ end.equals(false)
54
+ end # is_object method
55
+
56
+ context "for is_collection method" do
57
+ asserts "returns nil if no data" do
58
+ @helper_class.is_collection?(nil)
59
+ end.equals(nil)
60
+
61
+ asserts "returns false for an object" do
62
+ @helper_class.is_collection?(@user)
63
+ end.equals(false)
64
+
65
+ # asserts "returns false for an object with each" do
66
+ # obj = Class.new { def each; end }
67
+ # @helper_class.is_collection?(obj.new)
68
+ # end.equals(false)
69
+
70
+ asserts "returns false for a hash alias" do
71
+ @helper_class.is_collection?(@user => :user)
72
+ end.equals(false)
73
+
74
+ asserts "returns true for an array" do
75
+ @helper_class.is_collection?([@user])
76
+ end.equals(true)
77
+ end # is_collection method
32
78
  end
@@ -21,7 +21,7 @@ context "PostsController" do
21
21
 
22
22
  context "for index action" do
23
23
  setup do
24
- get "/posts", format: :json
24
+ get "/posts", :format => :json
25
25
  end
26
26
 
27
27
  # Attributes (regular)
@@ -74,7 +74,7 @@ context "PostsController" do
74
74
 
75
75
  context "for show action" do
76
76
  setup do
77
- get "/posts/#{@post1.id}", format: :json
77
+ get "/posts/#{@post1.id}", :format => :json
78
78
  json_output['post']
79
79
  end
80
80
 
@@ -17,7 +17,7 @@ context "PostsController" do
17
17
  Post.delete_all
18
18
  @post1 = Post.create(:title => "Foo", :body => "Bar", :user_id => @user1.id)
19
19
  @post2 = Post.create(:title => "Baz", :body => "Bah", :user_id => @user2.id)
20
- @post3 = Post.create(:title => "Kaz", :body => "Paz", :user_id => @user3.id)
20
+ @post3 = Post.create(:title => "Kaz", :body => "<script>alert('xss & test');</script>", :user_id => @user3.id)
21
21
  @posts = [@post1, @post2, @post3]
22
22
  end
23
23
 
@@ -74,6 +74,32 @@ context "PostsController" do
74
74
  end.includes(:created_by_admin)
75
75
  end # index action, json
76
76
 
77
+ context "escaping output in index action" do
78
+ context "for first post" do
79
+ setup do
80
+ Rabl.configuration.escape_all_output = true
81
+ get "/posts/#{@post1.id}", format: :json
82
+ json_output['post']
83
+ end
84
+
85
+ # Attributes (regular)
86
+ asserts("contains post title") { topic['title'] }.equals { @post1.title }
87
+ asserts("contains post body") { topic['body'] }.equals { @post1.body }
88
+ end
89
+
90
+ context "for third post with script tags" do
91
+ setup do
92
+ Rabl.configuration.escape_all_output = true
93
+ get "/posts/#{@post3.id}", format: :json
94
+ json_output['post']
95
+ end
96
+
97
+ # Attributes (regular)
98
+ asserts("contains post title") { topic['title'] }.equals { @post3.title }
99
+ asserts("contains escaped post body") { topic['body'] }.equals { ERB::Util.h(@post3.body) }
100
+ end
101
+ end # escaping output
102
+
77
103
  context "for show action" do
78
104
  setup do
79
105
  get "/posts/#{@post1.id}", format: :json
@@ -85,7 +111,7 @@ context "PostsController" do
85
111
  asserts("contains post body") { topic['body'] }.equals { @post1.body }
86
112
 
87
113
  # Attributes (custom name)
88
- asserts("contains post posted_at") { topic['posted_at'] }.equals { @post1.created_at.iso8601 }
114
+ asserts("contains post posted_at") { topic['posted_at'] }.equals { @post1.created_at.utc.to_s }
89
115
 
90
116
  # Child
91
117
  asserts("contains post user child username") { topic["user"]["username"] }.equals { @post1.user.username }
@@ -35,7 +35,7 @@ context "UsersController" do
35
35
  # Attributes (custom name)
36
36
  asserts("contains registered_at") do
37
37
  json_output.map { |u| u["user"]["registered_at"] }
38
- end.equals { @users.map(&:created_at).map(&:iso8601) }
38
+ end.equals { @users.map(&:created_at).map(&:utc).map(&:to_s) }
39
39
 
40
40
  # Node (renders based on attribute)
41
41
  asserts("contains role") do
@@ -64,7 +64,7 @@ context "UsersController" do
64
64
  asserts("contains email") { json_output["person"]["email"] }.equals { @user1.email }
65
65
  asserts("contains location") { json_output["person"]["location"] }.equals { @user1.location }
66
66
  # Attributes (custom name)
67
- asserts("contains registered_at") { json_output["person"]["registered_at"] }.equals { @user1.created_at.iso8601 }
67
+ asserts("contains registered_at") { json_output["person"]["registered_at"] }.equals { @user1.created_at.utc.to_s }
68
68
  # Node (renders based on attribute)
69
69
  asserts("contains role node") { json_output["person"]["role"] }.equals "normal"
70
70
 
@@ -4,7 +4,6 @@ require File.expand_path('../../lib/rabl/template', __FILE__)
4
4
  require File.expand_path('../models/user', __FILE__)
5
5
 
6
6
  context "Rabl::Engine" do
7
-
8
7
  helper(:rabl) { |t| RablTemplate.new("code", :format => 'msgpack') { t } }
9
8
 
10
9
  context "with msgpack defaults" do
@@ -16,7 +15,6 @@ context "Rabl::Engine" do
16
15
  end
17
16
 
18
17
  context "#object" do
19
-
20
18
  asserts "that it sets data source" do
21
19
  template = rabl %q{
22
20
  object @user
@@ -37,7 +35,6 @@ context "Rabl::Engine" do
37
35
  end
38
36
 
39
37
  context "#collection" do
40
-
41
38
  asserts "that it sets object to be casted as a simple array" do
42
39
  template = rabl %{
43
40
  collection @users
@@ -55,11 +52,9 @@ context "Rabl::Engine" do
55
52
  scope.instance_variable_set :@users, [User.new, User.new]
56
53
  template.render(scope).split("").sort
57
54
  end.equals "\x81\xA6person\x92\x81\xA6person\x80\x81\xA6person\x80".split("").sort
58
-
59
55
  end
60
56
 
61
57
  context "#attribute" do
62
-
63
58
  asserts "that it adds an attribute or method to be included in output" do
64
59
  template = rabl %{
65
60
  object @user
@@ -89,11 +84,9 @@ context "Rabl::Engine" do
89
84
  scope.instance_variable_set :@user, User.new(:name => 'irvine')
90
85
  template.render(scope).split("").sort
91
86
  end.equals "\x81\xA4user\x81\xA4city\xA6irvine".split("").sort
92
-
93
87
  end
94
88
 
95
89
  context "#code" do
96
-
97
90
  asserts "that it can create an arbitraty code node" do
98
91
  template = rabl %{
99
92
  code(:foo) { 'bar' }
@@ -107,11 +100,9 @@ context "Rabl::Engine" do
107
100
  }
108
101
  template.render(Object.new).split("").sort
109
102
  end.equals "\x80".split("").sort
110
-
111
103
  end
112
104
 
113
105
  context "#child" do
114
-
115
106
  asserts "that it can create a child node" do
116
107
  template = rabl %{
117
108
  object @user
@@ -137,7 +128,6 @@ context "Rabl::Engine" do
137
128
  end
138
129
 
139
130
  context "#glue" do
140
-
141
131
  asserts "that it glues data from a child node" do
142
132
  template = rabl %{
143
133
  object @user
@@ -191,7 +181,6 @@ context "Rabl::Engine" do
191
181
  end
192
182
 
193
183
  context "#object" do
194
-
195
184
  asserts "that it sets data source" do
196
185
  template = rabl %q{
197
186
  object @user
@@ -212,7 +201,6 @@ context "Rabl::Engine" do
212
201
  end
213
202
 
214
203
  context "#collection" do
215
-
216
204
  asserts "that it sets object to be casted as a simple array" do
217
205
  template = rabl %{
218
206
  collection @users
@@ -230,11 +218,9 @@ context "Rabl::Engine" do
230
218
  scope.instance_variable_set :@users, [User.new, User.new]
231
219
  template.render(scope).split("").sort
232
220
  end.equals "\x81\xA6person\x92\x80\x80".split("").sort
233
-
234
221
  end
235
222
 
236
223
  context "#attribute" do
237
-
238
224
  asserts "that it adds an attribute or method to be included in output" do
239
225
  template = rabl %{
240
226
  object @user
@@ -264,11 +250,9 @@ context "Rabl::Engine" do
264
250
  scope.instance_variable_set :@user, User.new(:name => 'irvine')
265
251
  template.render(scope).split("").sort
266
252
  end.equals "\x81\xA4city\xA6irvine".split("").sort
267
-
268
253
  end
269
254
 
270
255
  context "#code" do
271
-
272
256
  asserts "that it can create an arbitraty code node" do
273
257
  template = rabl %{
274
258
  code(:foo) { 'bar' }
@@ -282,11 +266,9 @@ context "Rabl::Engine" do
282
266
  }
283
267
  template.render(Object.new).split("").sort
284
268
  end.equals "\x80".split("").sort
285
-
286
269
  end
287
270
 
288
271
  context "#child" do
289
-
290
272
  asserts "that it can create a child node" do
291
273
  template = rabl %{
292
274
  object @user
@@ -311,7 +293,6 @@ context "Rabl::Engine" do
311
293
  end
312
294
 
313
295
  context "#glue" do
314
-
315
296
  asserts "that it glues data from a child node" do
316
297
  template = rabl %{
317
298
  object @user
@@ -62,4 +62,27 @@ context "Rabl::Partials" do
62
62
  end
63
63
  teardown { Object.send(:remove_const, :Sinatra) }
64
64
  end
65
+
66
+ context "fetch source using configured view paths" do
67
+ helper(:tmp_path) { @tmp_path ||= Pathname.new(Dir.mktmpdir) }
68
+
69
+ setup do
70
+ Rabl.configure do |config|
71
+ config.view_paths = tmp_path
72
+ end
73
+
74
+ ::Sinatra = stub(Class.new)
75
+ File.open(tmp_path + "test.rabl", "w") do |f|
76
+ f.puts "content"
77
+ end
78
+ File.open(tmp_path + "test.json.rabl", "w") do |f|
79
+ f.puts "content2"
80
+ end
81
+ TestPartial.new.fetch_source('test')
82
+ end
83
+ asserts('detects file.json.rabl first') { topic }.equals do
84
+ ["content2\n", (tmp_path + 'test.json.rabl').to_s]
85
+ end
86
+ teardown { Object.send(:remove_const, :Sinatra) }
87
+ end
65
88
  end
@@ -4,7 +4,6 @@ require File.expand_path('../../lib/rabl/template', __FILE__)
4
4
  require File.expand_path('../models/user', __FILE__)
5
5
 
6
6
  context "Rabl::Engine" do
7
-
8
7
  helper(:rabl) { |t| RablTemplate.new("code", :format => 'plist') { t } }
9
8
 
10
9
  context "with plist defaults" do
@@ -16,7 +15,6 @@ context "Rabl::Engine" do
16
15
  end
17
16
 
18
17
  context "#object" do
19
-
20
18
  asserts "that it sets data source" do
21
19
  template = rabl %q{
22
20
  object @user
@@ -37,7 +35,6 @@ context "Rabl::Engine" do
37
35
  end
38
36
 
39
37
  context "#collection" do
40
-
41
38
  asserts "that it sets object to be casted as a simple array" do
42
39
  template = rabl %{
43
40
  collection @users
@@ -55,11 +52,9 @@ context "Rabl::Engine" do
55
52
  scope.instance_variable_set :@users, [User.new, User.new]
56
53
  template.render(scope).split("").sort
57
54
  end.equals "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>person</key>\n\t<array>\n\t\t<dict>\n\t\t\t<key>person</key>\n\t\t\t<dict/>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>person</key>\n\t\t\t<dict/>\n\t\t</dict>\n\t</array>\n</dict>\n</plist>\n".split("").sort
58
-
59
55
  end
60
56
 
61
57
  context "#attribute" do
62
-
63
58
  asserts "that it adds an attribute or method to be included in output" do
64
59
  template = rabl %{
65
60
  object @user
@@ -89,11 +84,9 @@ context "Rabl::Engine" do
89
84
  scope.instance_variable_set :@user, User.new(:name => 'irvine')
90
85
  template.render(scope).split("").sort
91
86
  end.equals "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>user</key>\n\t<dict>\n\t\t<key>city</key>\n\t\t<string>irvine</string>\n\t</dict>\n</dict>\n</plist>\n".split("").sort
92
-
93
87
  end
94
88
 
95
89
  context "#code" do
96
-
97
90
  asserts "that it can create an arbitraty code node" do
98
91
  template = rabl %{
99
92
  code(:foo) { 'bar' }
@@ -107,21 +100,18 @@ context "Rabl::Engine" do
107
100
  }
108
101
  template.render(Object.new).split("").sort
109
102
  end.equals "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict/>\n</plist>\n".split("").sort
110
-
111
103
  end
112
104
 
113
105
  context "#child" do
114
-
115
106
  asserts "that it can create a child node" do
116
107
  template = rabl %{
117
108
  object @user
118
- attribute :name
119
109
  child(@user) { attribute :city }
120
110
  }
121
111
  scope = Object.new
122
112
  scope.instance_variable_set :@user, User.new(:name => 'leo', :city => 'LA')
123
113
  template.render(scope).split("").sort
124
- end.equals "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>user</key>\n\t<dict>\n\t\t<key>name</key>\n\t\t<string>leo</string>\n\t\t<key>user</key>\n\t\t<dict>\n\t\t\t<key>city</key>\n\t\t\t<string>LA</string>\n\t\t</dict>\n\t</dict>\n</dict>\n</plist>\n".split("").sort
114
+ end.equals "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>user</key>\n\t<dict>\n\t\t<key>user</key>\n\t\t<dict>\n\t\t\t<key>city</key>\n\t\t\t<string>LA</string>\n\t\t</dict>\n\t</dict>\n</dict>\n</plist>\n".split("").sort
125
115
 
126
116
  asserts "that it can create a child node with different key" do
127
117
  template = rabl %{
@@ -132,12 +122,10 @@ context "Rabl::Engine" do
132
122
  scope = Object.new
133
123
  scope.instance_variable_set :@user, User.new(:name => 'leo', :city => 'LA')
134
124
  template.render(scope)
135
-
136
125
  end.equals "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>user</key>\n\t<dict>\n\t\t<key>name</key>\n\t\t<string>leo</string>\n\t\t<key>person</key>\n\t\t<dict>\n\t\t\t<key>city</key>\n\t\t\t<string>LA</string>\n\t\t</dict>\n\t</dict>\n</dict>\n</plist>\n"
137
126
  end
138
127
 
139
128
  context "#glue" do
140
-
141
129
  asserts "that it glues data from a child node" do
142
130
  template = rabl %{
143
131
  object @user
@@ -191,7 +179,6 @@ context "Rabl::Engine" do
191
179
  end
192
180
 
193
181
  context "#object" do
194
-
195
182
  asserts "that it sets data source" do
196
183
  template = rabl %q{
197
184
  object @user
@@ -212,7 +199,6 @@ context "Rabl::Engine" do
212
199
  end
213
200
 
214
201
  context "#collection" do
215
-
216
202
  asserts "that it sets object to be casted as a simple array" do
217
203
  template = rabl %{
218
204
  collection @users
@@ -230,11 +216,9 @@ context "Rabl::Engine" do
230
216
  scope.instance_variable_set :@users, [User.new, User.new]
231
217
  template.render(scope)
232
218
  end.equals "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>person</key>\n\t<array>\n\t\t<dict/>\n\t\t<dict/>\n\t</array>\n</dict>\n</plist>\n"
233
-
234
219
  end
235
220
 
236
221
  context "#attribute" do
237
-
238
222
  asserts "that it adds an attribute or method to be included in output" do
239
223
  template = rabl %{
240
224
  object @user
@@ -264,11 +248,9 @@ context "Rabl::Engine" do
264
248
  scope.instance_variable_set :@user, User.new(:name => 'irvine')
265
249
  template.render(scope)
266
250
  end.equals "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>city</key>\n\t<string>irvine</string>\n</dict>\n</plist>\n"
267
-
268
251
  end
269
252
 
270
253
  context "#code" do
271
-
272
254
  asserts "that it can create an arbitrary code node" do
273
255
  template = rabl %{
274
256
  code(:foo) { 'bar' }
@@ -282,21 +264,18 @@ context "Rabl::Engine" do
282
264
  }
283
265
  template.render(Object.new)
284
266
  end.equals "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict/>\n</plist>\n"
285
-
286
267
  end
287
268
 
288
269
  context "#child" do
289
-
290
270
  asserts "that it can create a child node" do
291
271
  template = rabl %{
292
272
  object @user
293
- attribute :name
294
273
  child(@user) { attribute :city }
295
274
  }
296
275
  scope = Object.new
297
276
  scope.instance_variable_set :@user, User.new(:name => 'leo', :city => 'LA')
298
277
  template.render(scope).split("").sort
299
- end.equals "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>name</key>\n\t<string>leo</string>\n\t<key>user</key>\n\t<dict>\n\t\t<key>city</key>\n\t\t<string>LA</string>\n\t</dict>\n</dict>\n</plist>\n".split("").sort
278
+ end.equals "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>user</key>\n\t<dict>\n\t\t<key>city</key>\n\t\t<string>LA</string>\n\t</dict>\n</dict>\n</plist>\n".split("").sort
300
279
 
301
280
  asserts "that it can create a child node with different key" do
302
281
  template = rabl %{
@@ -311,7 +290,6 @@ context "Rabl::Engine" do
311
290
  end
312
291
 
313
292
  context "#glue" do
314
-
315
293
  asserts "that it glues data from a child node" do
316
294
  template = rabl %{
317
295
  object @user
@@ -3,6 +3,7 @@ require 'pathname'
3
3
 
4
4
  context "Rabl::Renderer" do
5
5
  helper(:tmp_path) { @tmp_path ||= Pathname.new(Dir.mktmpdir) }
6
+
6
7
  context "#render" do
7
8
  asserts 'renders empty array' do
8
9
  source = %q{
@@ -60,14 +61,12 @@ context "Rabl::Renderer" do
60
61
  attribute :name, :as => 'city'
61
62
  }
62
63
 
63
- scope = Object.new
64
64
  user = User.new(:name => 'irvine')
65
65
 
66
66
  renderer = Rabl::Renderer.new(source, nil, { :format => 'json', :locals => {:object => user} })
67
67
  renderer.render.split("").sort
68
68
  end.equals "{\"user\":{\"city\":\"irvine\"}}".split("").sort
69
69
 
70
-
71
70
  asserts 'loads source from file' do
72
71
  File.open(tmp_path + "test.json.rabl", "w") do |f|
73
72
  f.puts %q{
@@ -82,6 +81,23 @@ context "Rabl::Renderer" do
82
81
  renderer.render.split("").sort
83
82
  end.equals "{\"user\":{\"age\":24,\"name\":\"irvine\"}}".split("").sort
84
83
 
84
+ asserts 'uses globally configured view paths' do
85
+ Rabl.configure do |config|
86
+ config.view_paths << tmp_path
87
+ end
88
+
89
+ File.open(tmp_path + "test.rabl", "w") do |f|
90
+ f.puts %q{
91
+ attributes :age
92
+ }
93
+ end
94
+
95
+ user = User.new(:name => 'irvine')
96
+
97
+ renderer = Rabl::Renderer.new('test', user)
98
+ renderer.render.split("").sort
99
+ end.equals "{\"user\":{\"age\":24,\"name\":\"irvine\"}}".split("").sort
100
+
85
101
 
86
102
  asserts 'handles paths for extends' do
87
103
  File.open(tmp_path + "test.json.rabl", "w") do |f|
@@ -185,5 +201,4 @@ context "Rabl::Renderer" do
185
201
  Rabl::Renderer.plist(user, 'test', :view_path => tmp_path)
186
202
  end.equals "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>user</key>\n\t<dict>\n\t\t<key>age</key>\n\t\t<integer>24</integer>\n\t\t<key>name</key>\n\t\t<string>ivan</string>\n\t</dict>\n</dict>\n</plist>\n"
187
203
  end
188
-
189
204
  end
@@ -18,4 +18,4 @@ module Kernel
18
18
  ensure
19
19
  $VERBOSE = old_verbose
20
20
  end
21
- end unless Kernel.respond_to? :silence_warnings
21
+ end unless Kernel.respond_to? :silence_warnings
@@ -5,7 +5,6 @@ class Scope
5
5
  end
6
6
 
7
7
  context "RablTemplate" do
8
-
9
8
  asserts "that it registers for .rabl files" do
10
9
  Tilt['test.rabl']
11
10
  end.equals RablTemplate
@@ -44,7 +43,6 @@ context "RablTemplate" do
44
43
  end
45
44
 
46
45
  context "#render compiled" do
47
-
48
46
  # asserts "that it can be passed locals" do
49
47
  # template = RablTemplate.new { "code(:name) { @name }" }
50
48
  # template.render(Scope.new, :object => 'Bob')
@@ -61,8 +59,5 @@ context "RablTemplate" do
61
59
  template = RablTemplate.new { "code(:lol) { 'Hey ' + yield + '!' }" }
62
60
  template.render(Scope.new) { 'Joe' }
63
61
  end.matches %r{"lol":"Hey Joe!"}
64
-
65
62
  end
66
-
67
-
68
63
  end
@@ -27,4 +27,3 @@ end
27
27
  class Riot::Context
28
28
  # Custom context code here
29
29
  end
30
-
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: rabl
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.6.10
5
+ version: 0.6.11
6
6
  platform: ruby
7
7
  authors:
8
8
  - Nathan Esquenazi
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2012-04-19 00:00:00 Z
13
+ date: 2012-05-10 00:00:00 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activesupport