rabl 0.11.1 → 0.11.2

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.
@@ -21,7 +21,7 @@ module Rabl
21
21
  end
22
22
  end
23
23
 
24
- def write(key, value, options={})
24
+ def write(key, value, options = {})
25
25
  if defined?(Rails)
26
26
  Rails.cache.write(key, value, options)
27
27
  end
@@ -80,7 +80,7 @@ module Rabl
80
80
  @replace_nil_values_with_empty_strings = false
81
81
  @replace_empty_string_values_with_nil_values = false
82
82
  @exclude_nil_values = false
83
- @exclude_empty_values_in_collections = false
83
+ @exclude_empty_values_in_collections = false
84
84
  end
85
85
 
86
86
  # @return The JSON engine used to encode Rabl templates into JSON
data/lib/rabl/engine.rb CHANGED
@@ -1,124 +1,158 @@
1
1
  module Rabl
2
2
  class Engine
3
- include Rabl::Partials
4
- include Rabl::Helpers::Escaper
3
+ include Helpers
4
+ include Partials
5
+ include Helpers::Escaper
5
6
 
6
7
  # List of supported rendering formats
7
8
  FORMATS = [:json, :xml, :plist, :bson, :msgpack]
8
9
 
9
10
  # Constructs a new ejs engine based on given vars, handler and declarations
10
11
  # Rabl::Engine.new("...source...", { :format => "xml", :root => true, :view_path => "/path/to/views" })
11
- def initialize(source, options={})
12
- @_source = source
13
- @_options = options
14
- @_view_path = options[:view_path]
12
+ def initialize(source, options = {})
13
+ @_source = source
14
+ @_settings = {}
15
+ @_options = options
16
+
17
+ @_view_path = options[:view_path]
18
+ @_context_scope = options[:scope]
19
+
20
+ @_cache_read_on_render = true
15
21
  end
16
22
 
17
- def source=(string)
18
- @_source = string
23
+ def source=(source)
24
+ @_source = source
19
25
  end
20
26
 
21
- # Renders the representation based on source, object, scope and locals
22
- # Rabl::Engine.new("...source...", { :format => "xml" }).apply(scope, { :foo => "bar", :object => @user })
23
- def apply(scope, locals, &block)
24
- reset_options!(scope)
25
- set_instance_variables!(scope, locals, &block)
27
+ # Renders the representation based on source, object, context_scope and locals
28
+ # Rabl::Engine.new("...source...", { :format => "xml" }).apply(context_scope, { :foo => "bar", :object => @user })
29
+ def apply(context_scope, locals, &block)
30
+ set_instance_variables!(context_scope, locals)
31
+
32
+ reset_settings!
33
+ reset_options!
34
+
35
+ eval_source(locals, &block)
36
+
26
37
  instance_exec(root_object, &block) if block_given?
27
38
 
28
39
  self
29
40
  end
30
41
 
31
42
  # Renders the representation based on a previous apply
32
- # Rabl::Engine.new("...source...", { :format => "xml" }).apply(scope, { :foo => "bar", :object => @user }).render
33
- def render(scope = nil, locals = nil, &block)
34
- apply(scope, locals) if scope || locals
35
- cache_results { self.send("to_#{@_options[:format]}", @_options) }
43
+ # Rabl::Engine.new("...source...", { :format => "xml" }).apply(context_scope, { :foo => "bar", :object => @user }).render
44
+ def render(context_scope = nil, locals = nil, &block)
45
+ apply(context_scope, locals, &block) if context_scope || locals || block
46
+
47
+ cache_results do
48
+ send("to_#{@_options[:format]}")
49
+ end
36
50
  end
37
51
 
38
- # Returns the cache key of the engine
39
52
  def cache_key
40
- _cache = @_cache if defined?(@_cache)
41
- cache_key, _ = *_cache || nil
42
- return nil if cache_key.nil?
43
- Array(cache_key) + [@_options[:root_name], @_options[:format]]
53
+ return unless defined?(@_cache_key)
54
+
55
+ @_full_cache_key ||= begin
56
+ cache_key = Array(@_cache_key) + [@_options[:root_name], @_options[:format]]
57
+
58
+ if digestor_available? && defined?(lookup_context)
59
+ template = @_options[:template] || @virtual_path
60
+
61
+ digest = \
62
+ if Gem::Version.new(Rails.version) >= Gem::Version.new('4.1')
63
+ Digestor.digest(:name => template, :finder => lookup_context)
64
+ else
65
+ Digestor.digest(template, :rabl, lookup_context)
66
+ end
67
+
68
+ cache_key << digest
69
+ end
70
+
71
+ cache_key
72
+ end
44
73
  end
45
74
 
46
75
  # Returns a hash representation of the data object
47
76
  # to_hash(:root => true, :child_root => true)
48
- def to_hash(options={})
49
- options = options.merge(@_options)
77
+ def to_hash(options = {})
78
+ options = @_options.merge(options)
79
+
50
80
  data = root_object
51
- builder = Rabl::Builder.new(options)
81
+
52
82
  options[:root_name] = determine_object_root(data, root_name, options[:root])
53
83
 
54
- if is_object?(data) || !data # object @user
55
- result = builder.build(data, options)
56
- elsif is_collection?(data) # collection @users
57
- result = if template_cache_configured? && Rabl.configuration.use_read_multi
58
- read_multi(*data, options)
59
- else
60
- data.map { |object| builder.build(object, options) }
84
+ result = \
85
+ if is_object?(data) || !data # object @user
86
+ Builder.new(data, @_settings, options).to_hash
87
+ elsif is_collection?(data) # collection @users
88
+ MultiBuilder.new(data, @_settings, options).to_a
61
89
  end
62
- result = result.map(&:presence).compact if Rabl.configuration.exclude_empty_values_in_collections
63
- end
64
- Rabl.configuration.escape_all_output ? escape_output(result) : result
90
+
91
+ result = escape_output(result) if Rabl.configuration.escape_all_output
92
+
93
+ result
94
+ end
95
+
96
+ def to_dumpable(options = {})
97
+ options = {
98
+ :child_root => Rabl.configuration.include_child_root
99
+ }.merge(options)
100
+
101
+ result = to_hash(options)
102
+ result = { collection_root_name => result } if collection_root_name
103
+ result
65
104
  end
66
105
 
67
106
  # Returns a json representation of the data object
68
107
  # to_json(:root => true)
69
- def to_json(options={})
70
- include_root = Rabl.configuration.include_json_root
71
- include_child_root = Rabl.configuration.include_child_root
72
- options = options.reverse_merge(:root => include_root, :child_root => include_child_root)
73
- result = collection_root_name ? { collection_root_name => to_hash(options) } : to_hash(options)
108
+ def to_json(options = {})
109
+ options = { :root => Rabl.configuration.include_json_root }.merge(options)
110
+ result = to_dumpable(options)
74
111
  format_json(result)
75
112
  end
76
113
 
77
114
  # Returns a msgpack representation of the data object
78
115
  # to_msgpack(:root => true)
79
- def to_msgpack(options={})
80
- include_root = Rabl.configuration.include_msgpack_root
81
- include_child_root = Rabl.configuration.include_child_root
82
- options = options.reverse_merge(:root => include_root, :child_root => include_child_root)
83
- result = collection_root_name ? { collection_root_name => to_hash(options) } : to_hash(options)
84
- Rabl.configuration.msgpack_engine.pack result
116
+ def to_msgpack(options = {})
117
+ options = { :root => Rabl.configuration.include_msgpack_root }.merge(options)
118
+ result = to_dumpable(options)
119
+ Rabl.configuration.msgpack_engine.pack(result)
85
120
  end
86
121
  alias_method :to_mpac, :to_msgpack
87
122
 
88
123
  # Returns a plist representation of the data object
89
124
  # to_plist(:root => true)
90
- def to_plist(options={})
91
- include_root = Rabl.configuration.include_plist_root
92
- include_child_root = Rabl.configuration.include_child_root
93
- options = options.reverse_merge(:root => include_root, :child_root => include_child_root)
94
- result = defined?(@_collection_name) ? { @_collection_name => to_hash(options) } : to_hash(options)
125
+ def to_plist(options = {})
126
+ options = { :root => Rabl.configuration.include_plist_root }.merge(options)
127
+ result = to_dumpable(options)
95
128
  Rabl.configuration.plist_engine.dump(result)
96
129
  end
97
130
 
98
131
  # Returns an xml representation of the data object
99
132
  # to_xml(:root => true)
100
- def to_xml(options={})
101
- include_root = Rabl.configuration.include_xml_root
102
- include_child_root = include_root && Rabl.configuration.include_child_root
103
- options = options.reverse_merge(:root => include_root, :child_root => include_child_root)
133
+ def to_xml(options = {})
134
+ options = {
135
+ :root => (include_root = Rabl.configuration.include_xml_root),
136
+ :child_root => include_root && Rabl.configuration.include_child_root
137
+ }.merge(options)
138
+
104
139
  xml_options = Rabl.configuration.default_xml_options.merge(:root => collection_root_name || root_name)
140
+
105
141
  result = to_hash(options)
142
+
106
143
  result.to_xml(xml_options)
107
144
  end
108
145
 
109
146
  # Returns a bson representation of the data object
110
147
  # to_bson(:root => true)
111
- def to_bson(options={})
112
- include_root = Rabl.configuration.include_bson_root
113
- include_child_root = Rabl.configuration.include_child_root
114
- options = options.reverse_merge(:root => include_root, :child_root => include_child_root)
115
- result = if collection_root_name
116
- { collection_root_name => to_hash(options) }
117
- elsif is_collection?(root_object) && root_object.is_a?(Array)
118
- { root_name => to_hash(options) }
119
- else
120
- to_hash(options)
121
- end
148
+ def to_bson(options = {})
149
+ options = { :root => Rabl.configuration.include_bson_root }.merge(options)
150
+ result = to_dumpable(options)
151
+
152
+ if !collection_root_name && is_collection?(root_object) && root_object.is_a?(Array)
153
+ result = { root_name => result }
154
+ end
155
+
122
156
  Rabl.configuration.bson_engine.serialize(result).to_s
123
157
  end
124
158
 
@@ -130,6 +164,7 @@ module Rabl
130
164
  current_data = (@_locals[:object].nil? || template_data == false) ? template_data : @_locals[:object]
131
165
  @_data_object = data_object(current_data)
132
166
  @_data_name = data_name(template_data.is_a?(Hash) && !current_data.is_a?(Hash) ? template_data : current_data)
167
+
133
168
  if @_data_name == false
134
169
  @_object_root_name = false
135
170
  @_collection_name = false
@@ -142,7 +177,7 @@ module Rabl
142
177
  def root_object
143
178
  return @_data_object if defined?(@_data_object)
144
179
 
145
- data = @_locals[:object].nil? ? self.default_object : @_locals[:object]
180
+ data = @_locals[:object].nil? ? default_object : @_locals[:object]
146
181
  @_data_object = data_object(data)
147
182
  end
148
183
 
@@ -160,11 +195,13 @@ module Rabl
160
195
  # collection @users => :people
161
196
  # collection @users, :root => :person
162
197
  # collection @users, :object_root => :person
163
- def collection(data, options={})
198
+ def collection(data, options = {})
164
199
  @_collection_name = options[:root] if options[:root]
165
- @_collection_name ||= data.values.first if data.respond_to?(:each_pair)
200
+ @_collection_name ||= data.values.first if data.is_a?(Hash)
201
+
166
202
  @_object_root_name = options[:object_root] if options.has_key?(:object_root)
167
- self.object(Array(data_object(data)))
203
+
204
+ object(Array(data_object(data)))
168
205
  end
169
206
 
170
207
  # Sets the cache key to be used by ActiveSupport::Cache.expand_cache_key
@@ -176,7 +213,8 @@ module Rabl
176
213
  # options is passed through to the cache store
177
214
  def cache(key = nil, options = nil)
178
215
  key ||= root_object # if called but missing, use object
179
- @_cache = [key, options]
216
+ @_cache_key = key
217
+ @_cache_options = options
180
218
  end
181
219
 
182
220
  # Indicates an attribute or method should be included in the json output
@@ -185,11 +223,17 @@ module Rabl
185
223
  # attribute :foo => :bar, :bar => :baz, :if => lambda { |r| r.foo }
186
224
  def attribute(*args)
187
225
  if args.first.is_a?(Hash) # :foo => :bar, :bar => :baz
188
- attr_aliases, conds = args.first.except(:if, :unless), args.first.slice(:if, :unless)
189
- attr_aliases.each_pair { |k,v| self.attribute(k, conds.merge(:as => v)) }
226
+ attr_aliases = args.first.except(:if, :unless)
227
+ conditions = args.first.slice(:if, :unless)
228
+
229
+ attr_aliases.each do |key, as|
230
+ attribute(key, conditions.merge(:as => as))
231
+ end
190
232
  else # array of attributes i.e :foo, :bar, :baz
191
- attr_options = args.extract_options!
192
- args.each { |name| @_options[:attributes][name] = attr_options }
233
+ options = args.extract_options!
234
+ args.each do |name|
235
+ @_settings[:attributes] << { :name => name, :options => options }
236
+ end
193
237
  end
194
238
  end
195
239
  alias_method :attributes, :attribute
@@ -197,193 +241,181 @@ module Rabl
197
241
  # Creates an arbitrary node that is included in the json output.
198
242
  # node(:foo) { "bar" }
199
243
  # node(:foo, :if => lambda { ... }) { "bar" }
200
- def node(name = nil, options={}, &block)
201
- @_options[:node].push({ :name => name, :options => options, :block => block })
244
+ def node(name = nil, options = {}, &block)
245
+ @_settings[:node] << { :name => name, :options => options, :block => block }
202
246
  end
203
247
  alias_method :code, :node
204
248
 
205
249
  # Creates a child node that is included in json output
206
250
  # child(@user) { attribute :full_name }
207
- def child(data, options={}, &block)
208
- @_options[:child].push({ :data => data, :options => options, :block => block })
251
+ def child(data, options = {}, &block)
252
+ @_settings[:child] << { :data => data, :options => options, :block => block }
209
253
  end
210
254
 
211
255
  # Glues data from a child node to the json_output
212
256
  # glue(@user) { attribute :full_name => :user_full_name }
213
- def glue(data, options={}, &block)
214
- @_options[:glue].push({ :data => data, :options => options, :block => block })
257
+ def glue(data, options = {}, &block)
258
+ @_settings[:glue] << { :data => data, :options => options, :block => block }
215
259
  end
216
260
 
217
261
  # Extends an existing rabl template with additional attributes in the block
218
262
  # extends("users/show", :object => @user) { attribute :full_name }
219
- def extends(file, options={}, &block)
220
- extend_ops = options.merge(:view_path => options.fetch(:view_path, @_options[:view_path]))
221
- @_options[:extends].push({ :file => file, :options => extend_ops, :block => block })
263
+ def extends(file, options = {}, &block)
264
+ options = { :view_path => options[:view_path] || view_path }.merge(options)
265
+
266
+ @_settings[:extends] << { :file => file, :options => options, :block => block }
222
267
  end
223
268
 
224
269
  # Includes a helper module with a RABL template
225
270
  # helper ExampleHelper
226
- def helper(*klazzes)
227
- klazzes.each { |klazz| self.class.__send__(:include, klazz) }
271
+ def helper(*klasses)
272
+ klasses.each { |klass| self.class.__send__(:include, klass) }
228
273
  end
229
274
  alias_method :helpers, :helper
230
275
 
276
+ # Returns a hash representing the partial
277
+ # partial("users/show", :object => @user)
278
+ # options must have :object
279
+ # options can have :view_path, :child_root, :root
280
+ def partial(file, options = {}, &block)
281
+ engine = partial_as_engine(file, options, &block)
282
+ engine = engine.render if engine.is_a?(Engine)
283
+ engine
284
+ end
285
+
231
286
  # Disables reading (but not writing) from the cache when rendering.
232
- def cache_read_on_render=(c)
233
- @_cache_read_on_render = c
287
+ def cache_read_on_render=(read)
288
+ @_cache_read_on_render = read
289
+ end
290
+
291
+ def cache_read_on_render?
292
+ @_cache_read_on_render
234
293
  end
235
294
 
236
295
  protected
296
+ # Returns a guess at the default object for this template
297
+ # default_object => @user
298
+ def default_object
299
+ return unless context_scope.respond_to?(:controller)
237
300
 
238
- # Returns a guess at the default object for this template
239
- # default_object => @user
240
- def default_object
241
- if context_scope.respond_to?(:controller)
242
301
  controller_name = context_scope.controller.controller_name
243
302
  stripped_name = controller_name.split(%r{::|\/}).last
244
303
  ivar_object = instance_variable_get("@#{stripped_name}")
245
304
  ivar_object if is_object?(ivar_object)
246
305
  end
247
- end
248
306
 
249
- # Returns a guess at the format in this scope
250
- # request_format => "xml"
251
- def request_format
252
- format = self.request_params.has_key?(:format) ? context_scope.params[:format] : nil
253
- if request = context_scope.respond_to?(:request) && context_scope.request
254
- format ||= request.format.to_sym.to_s if request.respond_to?(:format)
307
+ # Returns a guess at the format in this context_scope
308
+ # request_format => "xml"
309
+ def request_format
310
+ format = request_params[:format]
311
+
312
+ if format.nil? && context_scope.respond_to?(:request)
313
+ request = context_scope.request
314
+ format = request.format.to_sym.to_s if request.respond_to?(:format)
315
+ end
316
+
317
+ format = "json" unless format && respond_to?("to_#{format}")
318
+
319
+ format
255
320
  end
256
- format && self.respond_to?("to_#{format}") ? format : "json"
257
- end
258
321
 
259
- # Returns the request parameters if available in the scope
260
- # request_params => { :foo => "bar" }
261
- def request_params
262
- (context_scope.params if context_scope.respond_to?(:params)) || {}
263
- end
322
+ # Returns the request parameters if available in the context_scope
323
+ # request_params => { :foo => "bar" }
324
+ def request_params
325
+ (context_scope.params if context_scope.respond_to?(:params)) || {}
326
+ end
264
327
 
265
- # Returns data as json embraced with callback when detected
266
- # format_json({ :foo => "bar" }) => "test({ foo : 'bar' })"
267
- # format_json("{ foo : "bar" }") => "test({ foo : 'bar' })"
268
- def format_json(json_output)
269
- json_engine = Rabl.configuration.json_engine
270
- json_method = json_engine.respond_to?(:dump) ? 'dump' : 'encode'
271
- json_output = json_engine.send(json_method, json_output) unless json_output.is_a?(String)
272
- use_callback = Rabl.configuration.enable_json_callbacks && request_params[:callback].present?
273
- use_callback ? "#{request_params[:callback]}(#{json_output})" : json_output
274
- end
328
+ # Returns data as json embraced with callback when detected
329
+ # format_json({ :foo => "bar" }) => "test({ foo : 'bar' })"
330
+ # format_json("{ foo : "bar" }") => "test({ foo : 'bar' })"
331
+ def format_json(json_output)
332
+ unless json_output.is_a?(String)
333
+ json_engine = Rabl.configuration.json_engine
334
+ json_output = if json_engine.respond_to?(:dump)
335
+ json_engine.dump(json_output)
336
+ else
337
+ json_engine.encode(json_output)
338
+ end
339
+ end
275
340
 
276
- # Augments respond to supporting scope methods
277
- def respond_to?(name, include_private=false)
278
- context_scope.respond_to?(name, include_private) ? true : super
279
- end
341
+ use_callback = Rabl.configuration.enable_json_callbacks && request_params[:callback].present?
342
+ json_output = "#{request_params[:callback]}(#{json_output})" if use_callback
280
343
 
281
- # Supports calling helpers defined for the template scope using method_missing hook
282
- def method_missing(name, *args, &block)
283
- context_scope.respond_to?(name, true) ? context_scope.__send__(name, *args, &block) : super
284
- end
344
+ json_output
345
+ end
285
346
 
286
- def copy_instance_variables_from(object, exclude = []) #:nodoc:
287
- vars = object.instance_variables.map(&:to_s) - exclude.map(&:to_s)
288
- vars.each { |name| instance_variable_set(name, object.instance_variable_get(name)) }
289
- end
347
+ # Augments respond to supporting context_scope methods
348
+ def respond_to?(name, include_private = false)
349
+ context_scope.respond_to?(name, include_private) || super
350
+ end
290
351
 
291
- def cache_read_on_render
292
- @_cache_read_on_render = @_cache_read_on_render.nil? ? true : @_cache_read_on_render
293
- end
352
+ # Supports calling helpers defined for the template context_scope using method_missing hook
353
+ def method_missing(name, *args, &block)
354
+ context_scope.respond_to?(name, true) ? context_scope.__send__(name, *args, &block) : super
355
+ end
294
356
 
295
- private
296
-
297
- # Resets the options parsed from a rabl template.
298
- def reset_options!(scope)
299
- @_options[:attributes] = {}
300
- @_options[:node] = []
301
- @_options[:child] = []
302
- @_options[:glue] = []
303
- @_options[:extends] = []
304
- @_options[:root_name] = nil
305
- @_options[:read_multi] = false
306
- @_options[:scope] = scope
307
- end
357
+ def copy_instance_variables_from(object, exclude = []) #:nodoc:
358
+ vars = object.instance_variables.map(&:to_s) - exclude.map(&:to_s)
359
+ vars.each { |name| instance_variable_set(name, object.instance_variable_get(name)) }
360
+ end
308
361
 
309
- # Caches the results of the block based on object cache_key
310
- # cache_results { compile_hash(options) }
311
- def cache_results(&block)
312
- _cache = @_cache if defined?(@_cache)
313
- cache_key, cache_options = *_cache || nil
314
- if template_cache_configured? && cache_key
315
- result_cache_key = if digestor_available?
316
- cache_key_with_digest(cache_key)
317
- else # fallback for Rails 3, and Non-Rails app
318
- cache_key_simple(cache_key)
319
- end
362
+ def reset_settings!
363
+ @_settings[:attributes] = []
364
+ @_settings[:node] = []
365
+ @_settings[:child] = []
366
+ @_settings[:glue] = []
367
+ @_settings[:extends] = []
368
+ end
369
+
370
+ # Resets the options parsed from a rabl template.
371
+ def reset_options!
372
+ @_options[:root_name] = nil
373
+ @_options[:read_multi] = false
374
+ @_options[:scope] = context_scope
375
+ end
320
376
 
321
- if self.cache_read_on_render
322
- fetch_result_from_cache(result_cache_key, cache_options, &block)
377
+ # Caches the results of the block based on object cache_key
378
+ # cache_results { compile_hash(options) }
379
+ def cache_results(&block)
380
+ return yield unless template_cache_configured? && defined?(@_cache_key)
381
+
382
+ if cache_read_on_render?
383
+ fetch_result_from_cache(cache_key, @_cache_options, &block)
323
384
  else
324
- write_result_to_cache(result_cache_key, cache_options, &block)
385
+ write_result_to_cache(cache_key, @_cache_options, &block)
325
386
  end
326
- else # skip caching
327
- yield
328
387
  end
329
- end
330
388
 
331
- # Uses read_multi to render a collection of cache keys,
332
- # falling back to a normal render in the event of a miss.
333
- def read_multi(*data)
334
- options = data.extract_options!
335
- builder = Rabl::MultiBuilder.new(data, options)
336
- builder.to_a
337
- end
338
-
339
- def digestor_available?
340
- defined?(Rails) && Rails.version =~ /^[4]/
341
- end
389
+ def digestor_available?
390
+ defined?(Rails) && Rails.version =~ /^[4]/
391
+ end
342
392
 
343
- def cache_key_with_digest(cache_key)
344
- template = @_options[:template] || @virtual_path
393
+ def set_instance_variables!(context_scope, locals)
394
+ @_context_scope = context_scope
395
+ @_locals = locals
345
396
 
346
- if Gem::Version.new(Rails.version) >= Gem::Version.new('4.1')
347
- digested = Digestor.digest(:name => template, :finder => lookup_context)
348
- else
349
- digested = Digestor.digest(template, :rabl, lookup_context)
350
- end
397
+ copy_instance_variables_from(context_scope, [:@assigns, :@helpers])
351
398
 
352
- Array(cache_key) + [
353
- @_options[:root_name],
354
- @_options[:format],
355
- digested
356
- ]
357
- rescue NameError => e # Handle case where lookup_context doesn't exist
358
- raise e unless e.message =~ /lookup_context/
359
- cache_key_simple(cache_key)
360
- end # cache_key_with_digest
361
-
362
- def cache_key_simple(key)
363
- Array(key) + [@_options[:root_name], @_options[:format]]
364
- end
399
+ @_options[:format] ||= request_format
365
400
 
366
- def set_instance_variables!(scope, locals, &block)
367
- @_locals, @_scope = locals, scope
368
- self.copy_instance_variables_from(@_scope, [:@assigns, :@helpers])
369
- @_options[:format] ||= self.request_format
370
- set_locals(locals)
371
- set_source(locals, &block)
372
- end
401
+ set_locals(locals)
402
+ end
373
403
 
374
- def set_locals(locals)
375
- locals.merge!(locals.delete(:locals) || {})
376
- locals.each { |k,v| instance_variable_set(:"@#{k}", v) }
377
- end
404
+ def set_locals(locals)
405
+ locals.merge!(locals.delete(:locals) || {})
406
+ locals.each { |key, value| instance_variable_set(:"@#{key}", value) }
407
+ end
378
408
 
379
- def set_source(locals, &block)
380
- return unless @_source.present?
409
+ def eval_source(locals, &block)
410
+ # Note: locals and block may be used by the eval'ed source
411
+
412
+ return unless @_source.present?
381
413
 
382
- if @_options[:source_location]
383
- instance_eval(@_source, @_options[:source_location])
384
- else # without source location
385
- instance_eval(@_source)
414
+ if @_options[:source_location]
415
+ instance_eval(@_source, @_options[:source_location])
416
+ else
417
+ instance_eval(@_source)
418
+ end
386
419
  end
387
420
  end
388
- end
389
421
  end