breezy_template 0.2.0 → 0.3.0
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.
- checksums.yaml +4 -4
- data/lib/breezy_template.rb +285 -211
- data/lib/breezy_template/active_support.rb +3 -3
- data/lib/breezy_template/blank.rb +11 -0
- data/lib/breezy_template/breezy_template.rb +7 -0
- data/lib/breezy_template/cache_extension.rb +75 -27
- data/lib/breezy_template/configuration.rb +3 -1
- data/lib/breezy_template/deferment_extension.rb +14 -12
- data/lib/breezy_template/dependency_tracker.rb +5 -2
- data/lib/breezy_template/digestor.rb +2 -1
- data/lib/breezy_template/errors.rb +24 -0
- data/lib/breezy_template/handler.rb +4 -2
- data/lib/breezy_template/key_formatter.rb +34 -0
- data/lib/breezy_template/partial_extension.rb +57 -19
- data/lib/breezy_template/search_extension.rb +3 -3
- data/test/dependency_tracker_test.rb +80 -64
- data/test/{breezy_template_test.rb → extensions_test.rb} +130 -77
- data/test/template_test.rb +714 -0
- data/test/test_helper.rb +0 -1
- metadata +31 -25
- data/lib/breezy_template/version.rb +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5615a0d5186cccdec50df4bc728c6d472f877254
|
4
|
+
data.tar.gz: ae3d4643bfa89ebbf2d38fd285b74ee909a73b06
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4e639ce8e936ebb85324b90830425f005b3f17d7e1366ddb2f9d1d0a096cf4275e56b64ccc0c64aa32c66c365f94c6ca1c7e933a7ea71c50ef35101940f1d7d8
|
7
|
+
data.tar.gz: 30b7c0e630b346d037447f26ca3a5265c8d0839c42c3218060fcbd37e2b5dd431819e7ab27136789b202dd8295794fb49d74d4f17c0c5178b74648867ce7805c
|
data/lib/breezy_template.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
|
-
require '
|
2
|
-
|
3
|
-
require '
|
4
|
-
require '
|
1
|
+
require 'breezy_template/breezy_template'
|
2
|
+
|
3
|
+
require 'breezy_template/blank'
|
4
|
+
require 'breezy_template/key_formatter'
|
5
|
+
require 'breezy_template/errors'
|
6
|
+
|
5
7
|
require 'breezy_template/active_support'
|
6
8
|
require 'breezy_template/digestor'
|
7
9
|
require 'breezy_template/configuration'
|
@@ -11,258 +13,330 @@ require 'breezy_template/cache_extension'
|
|
11
13
|
require 'breezy_template/deferment_extension'
|
12
14
|
require 'breezy_template/search_extension'
|
13
15
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
ActionView::Template.register_template_handler :props, BreezyTemplate::Handler
|
20
|
-
require 'breezy_template/dependency_tracker'
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
16
|
+
require 'digest/md5'
|
17
|
+
require 'action_view'
|
18
|
+
require 'active_support'
|
19
|
+
require 'multi_json'
|
20
|
+
require 'ostruct'
|
24
21
|
|
25
|
-
|
26
|
-
|
27
|
-
prepend PartialExtension
|
22
|
+
class BreezyTemplate
|
23
|
+
include PartialDigestor
|
28
24
|
|
29
|
-
|
30
|
-
|
31
|
-
|
25
|
+
prepend PartialExtension
|
26
|
+
prepend CacheExtension
|
27
|
+
prepend SearchExtension
|
28
|
+
prepend DefermentExtension
|
32
29
|
|
33
|
-
|
34
|
-
|
35
|
-
|
30
|
+
class << self
|
31
|
+
attr_accessor :template_lookup_options
|
32
|
+
end
|
36
33
|
|
37
|
-
|
34
|
+
self.template_lookup_options = { handlers: [:breezy, :props] }
|
38
35
|
|
39
|
-
|
40
|
-
|
41
|
-
@js = []
|
42
|
-
@path = []
|
43
|
-
@joints = {}
|
44
|
-
@extensions = {}
|
45
|
-
super(*args)
|
46
|
-
end
|
36
|
+
@@key_formatter = nil
|
37
|
+
@@ignore_nil = false
|
47
38
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
39
|
+
def initialize(context, options = {})
|
40
|
+
@context = context
|
41
|
+
@js = []
|
42
|
+
@path = []
|
43
|
+
@joints = {}
|
53
44
|
|
54
|
-
|
55
|
-
|
56
|
-
|
45
|
+
@attributes = {}
|
46
|
+
@key_formatter = options.fetch(:key_formatter){ @@key_formatter ? @@key_formatter.clone : nil}
|
47
|
+
@ignore_nil = options.fetch(:ignore_nil, @@ignore_nil)
|
57
48
|
|
58
|
-
|
59
|
-
|
60
|
-
end
|
49
|
+
yield self if ::Kernel.block_given?
|
50
|
+
end
|
61
51
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
52
|
+
# Yields a builder and automatically turns the result into a JSON string
|
53
|
+
def self.encode(*args, &block)
|
54
|
+
new(*args, &block).target!
|
55
|
+
end
|
56
|
+
|
57
|
+
BLANK = Blank.new
|
58
|
+
NON_ENUMERABLES = [ ::Struct, ::OpenStruct ].to_set
|
59
|
+
|
60
|
+
def set!(key, value = BLANK, *args)
|
61
|
+
result = if ::Kernel.block_given?
|
62
|
+
_result(value, *args, &::Proc.new)
|
63
|
+
else
|
64
|
+
if _is_collection?(value) && !args.last.is_a?(::Hash)
|
65
|
+
_scope{ array! value, *args }
|
66
|
+
# elsif args.empty?
|
67
|
+
# _result(value, *args)
|
68
|
+
# elsif !args.last.is_a? ::Hash
|
69
|
+
# _merge_block(key){ extract! value, *args }
|
68
70
|
else
|
69
|
-
|
70
|
-
|
71
|
+
_result(value, *args)
|
72
|
+
# value
|
71
73
|
end
|
72
|
-
ensure
|
73
|
-
# ::Byebug.byebug
|
74
|
-
@extensions = {}
|
75
|
-
@path.pop
|
76
74
|
end
|
77
75
|
|
78
|
-
|
79
|
-
|
80
|
-
@extensions = {}
|
81
|
-
parent_attributes, parent_formatter = @attributes, @key_formatter
|
82
|
-
@attributes = BLANK
|
83
|
-
yield
|
84
|
-
@attributes
|
85
|
-
ensure
|
86
|
-
# ::Byebug.byebug
|
87
|
-
@extensions = parent_extensions
|
88
|
-
@attributes, @key_formatter = parent_attributes, parent_formatter
|
89
|
-
end
|
90
|
-
|
91
|
-
def set!(key, value = BLANK, *args)
|
92
|
-
_ensure_valid_key(key)
|
93
|
-
result = if ::Kernel.block_given?
|
94
|
-
_result(value, &::Proc.new)
|
95
|
-
else
|
96
|
-
_result(value)
|
97
|
-
end
|
76
|
+
_set_value key, result
|
77
|
+
end
|
98
78
|
|
99
|
-
|
79
|
+
def _result(value, *args)
|
80
|
+
if ::Kernel.block_given?
|
81
|
+
_scope { yield self }
|
82
|
+
elsif ::BreezyTemplate === value
|
83
|
+
# json.age 32
|
84
|
+
# json.person another_jbuilder
|
85
|
+
# { "age": 32, "person": { ... }
|
86
|
+
value.attributes!
|
87
|
+
else
|
88
|
+
# json.age 32
|
89
|
+
# { "age": 32 }
|
90
|
+
value
|
100
91
|
end
|
92
|
+
end
|
101
93
|
|
102
|
-
|
103
|
-
|
104
|
-
|
94
|
+
def method_missing(*args)
|
95
|
+
key = args[0]
|
96
|
+
@path.push(key)
|
97
|
+
if ::Kernel.block_given?
|
98
|
+
args = _args_for_set_with_block(*args)
|
99
|
+
set!(*args, &::Proc.new)
|
100
|
+
else
|
101
|
+
args = _args_for_set(*args)
|
102
|
+
set!(*args)
|
105
103
|
end
|
104
|
+
ensure
|
105
|
+
@path.pop
|
106
|
+
end
|
106
107
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
elsif ::Jbuilder === value
|
111
|
-
# json.age 32
|
112
|
-
# json.person another_jbuilder
|
113
|
-
# { "age": 32, "person": { ... }
|
114
|
-
value.attributes!
|
115
|
-
else
|
116
|
-
# json.age 32
|
117
|
-
# { "age": 32 }
|
118
|
-
value
|
119
|
-
end
|
120
|
-
end
|
108
|
+
def key_format!(*args)
|
109
|
+
@key_formatter = KeyFormatter.new(*args)
|
110
|
+
end
|
121
111
|
|
122
|
-
|
123
|
-
|
124
|
-
|
112
|
+
# Same as the instance method key_format! except sets the default.
|
113
|
+
def self.key_format(*args)
|
114
|
+
@@key_formatter = KeyFormatter.new(*args)
|
115
|
+
end
|
116
|
+
|
117
|
+
def empty!
|
118
|
+
attributes = @attributes
|
119
|
+
@attributes = {}
|
120
|
+
attributes
|
121
|
+
end
|
125
122
|
|
126
|
-
|
127
|
-
|
128
|
-
|
123
|
+
def ignore_nil!(value = true)
|
124
|
+
@ignore_nil = value
|
125
|
+
end
|
129
126
|
|
130
|
-
|
131
|
-
|
127
|
+
# Same as instance method ignore_nil! except sets the default.
|
128
|
+
def self.ignore_nil(value = true)
|
129
|
+
@@ignore_nil = value
|
130
|
+
end
|
131
|
+
|
132
|
+
def child!
|
133
|
+
@attributes = [] unless ::Array === @attributes
|
134
|
+
@attributes << _scope{ yield self }
|
135
|
+
end
|
132
136
|
|
133
|
-
array = if ::Kernel.block_given?
|
134
|
-
_map_collection(collection, options, &::Proc.new)
|
135
|
-
elsif attributes.any?
|
136
|
-
_map_collection(collection, options) { |element| extract! element, *attributes }
|
137
|
-
else
|
138
|
-
collection.to_a
|
139
|
-
end
|
140
137
|
|
141
|
-
|
142
|
-
|
138
|
+
def array!(collection = [], *attributes)
|
139
|
+
options = attributes.first || {}
|
140
|
+
|
141
|
+
collection = [] if collection.nil?
|
142
|
+
collection = _prepare_collection_for_map(collection)
|
143
|
+
array = if ::Kernel.block_given?
|
144
|
+
_map_collection(collection, options, &::Proc.new)
|
145
|
+
# elsif attributes.any?
|
146
|
+
# if (!attributes.last.is_a? ::Hash)
|
147
|
+
# _map_collection(collection) { |element|
|
148
|
+
# extract! element, *attributes
|
149
|
+
# }
|
150
|
+
# else
|
151
|
+
# _map_collection(collection, options) { |element|
|
152
|
+
# extract! element, *attributes
|
153
|
+
# }
|
154
|
+
# end
|
155
|
+
else
|
156
|
+
collection.to_a
|
143
157
|
end
|
144
158
|
|
145
|
-
|
146
|
-
|
159
|
+
merge! array #remove this depednacy
|
160
|
+
end
|
147
161
|
|
148
|
-
|
149
|
-
|
162
|
+
def extract!(object, *attributes)
|
163
|
+
if ::Hash === object
|
164
|
+
_extract_hash_values(object, attributes)
|
165
|
+
else
|
166
|
+
_extract_method_values(object, attributes)
|
150
167
|
end
|
168
|
+
end
|
151
169
|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
170
|
+
# def call(object, *attributes)
|
171
|
+
# if ::Kernel.block_given?
|
172
|
+
# array! object, &::Proc.new
|
173
|
+
# else
|
174
|
+
# extract! object, *attributes
|
175
|
+
# end
|
176
|
+
# end
|
177
|
+
|
178
|
+
# Returns the nil JSON.
|
179
|
+
def nil!
|
180
|
+
@attributes = nil
|
181
|
+
end
|
157
182
|
|
158
|
-
|
159
|
-
end
|
183
|
+
alias_method :null!, :nil!
|
160
184
|
|
161
|
-
|
162
|
-
|
163
|
-
|
185
|
+
def attributes!
|
186
|
+
@attributes
|
187
|
+
end
|
164
188
|
|
165
|
-
|
166
|
-
|
167
|
-
#todo: check this
|
168
|
-
if ::Hash === args[1] && _extended_options?(args[1])
|
169
|
-
options = args[1]
|
170
|
-
[key, BLANK, options]
|
171
|
-
else
|
172
|
-
[key, BLANK]
|
173
|
-
end
|
174
|
-
end
|
189
|
+
def target!
|
190
|
+
js = _breezy_return(@attributes)
|
175
191
|
|
176
|
-
|
177
|
-
|
178
|
-
|
192
|
+
@js.push(js)
|
193
|
+
"(function(){var joints={};var cache={};var defers=[];#{@js.join}})()"
|
194
|
+
end
|
179
195
|
|
180
|
-
|
181
|
-
|
182
|
-
|
196
|
+
# Merges hash or array into current builder.
|
197
|
+
# No longer works on Breezy
|
198
|
+
def merge!(hash_or_array)
|
199
|
+
@attributes = _merge_values(@attributes, hash_or_array)
|
200
|
+
end
|
183
201
|
|
184
|
-
|
185
|
-
end
|
186
|
-
end
|
202
|
+
private
|
187
203
|
|
188
|
-
|
189
|
-
|
190
|
-
|
204
|
+
def _extract_hash_values(object, attributes)
|
205
|
+
attributes.each{ |key| _set_value key, object.fetch(key) }
|
206
|
+
end
|
191
207
|
|
192
|
-
|
193
|
-
|
194
|
-
|
208
|
+
def _extract_method_values(object, attributes)
|
209
|
+
attributes.each{ |key| _set_value key, object.public_send(key) }
|
210
|
+
end
|
195
211
|
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
@path[-1] = "#{id_name}=#{id_val}"
|
203
|
-
else
|
204
|
-
@path[-1] = i
|
205
|
-
end
|
206
|
-
|
207
|
-
_mapping_element(element, options, &::Proc.new)
|
208
|
-
|
209
|
-
end - [BLANK]
|
210
|
-
ensure
|
211
|
-
@path.pop
|
212
|
-
end
|
212
|
+
def _merge_block(key)
|
213
|
+
current_value = _blank? ? BLANK : @attributes.fetch(_key(key), BLANK)
|
214
|
+
raise NullError.build(key) if current_value.nil?
|
215
|
+
new_value = _scope{ yield self }
|
216
|
+
_merge_values(current_value, new_value)
|
217
|
+
end
|
213
218
|
|
219
|
+
def _merge_values(current_value, updates)
|
220
|
+
# Always use the new values. This is because cached values
|
221
|
+
# are no longer a Ruby object. They are JS values and can't
|
222
|
+
# be merged.
|
214
223
|
|
215
|
-
|
216
|
-
|
217
|
-
end
|
224
|
+
updates
|
225
|
+
end
|
218
226
|
|
219
|
-
|
220
|
-
|
221
|
-
|
227
|
+
def _key(key)
|
228
|
+
@key_formatter ? @key_formatter.format(key) : key.to_s
|
229
|
+
end
|
222
230
|
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
opts[:partial] = options[:partial]
|
235
|
-
end
|
236
|
-
|
237
|
-
key = case key
|
238
|
-
when ::Array
|
239
|
-
key
|
240
|
-
when ::Proc
|
241
|
-
key
|
242
|
-
else
|
243
|
-
[key]
|
244
|
-
end
|
245
|
-
|
246
|
-
options[:cache] = [key, opts]
|
247
|
-
options
|
248
|
-
end
|
231
|
+
def _set_value(key, value)
|
232
|
+
raise NullError.build(key) if @attributes.nil?
|
233
|
+
raise ArrayError.build(key) if ::Array === @attributes
|
234
|
+
return if @ignore_nil && value.nil? or _blank?(value)
|
235
|
+
@attributes = {} if _blank?
|
236
|
+
@attributes[_key(key)] = value
|
237
|
+
end
|
238
|
+
|
239
|
+
def _prepare_collection_for_map(collection)
|
240
|
+
collection
|
241
|
+
end
|
249
242
|
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
key
|
260
|
-
end
|
243
|
+
def _map_collection(collection, options = {})
|
244
|
+
@path.push(nil)
|
245
|
+
collection.map.with_index do |element, i|
|
246
|
+
if options.has_key? :key
|
247
|
+
id_name = options[:key]
|
248
|
+
id_val = element[id_name]
|
249
|
+
@path[-1] = "#{id_name}=#{id_val}"
|
250
|
+
else
|
251
|
+
@path[-1] = i
|
261
252
|
end
|
262
253
|
|
254
|
+
_mapping_element(element, options, &::Proc.new)
|
255
|
+
|
256
|
+
end - [BLANK]
|
257
|
+
ensure
|
258
|
+
@path.pop
|
259
|
+
end
|
260
|
+
|
261
|
+
def _mapping_element(element, options)
|
262
|
+
_scope { yield element }
|
263
|
+
end
|
264
|
+
|
265
|
+
def _scope
|
266
|
+
parent_attributes, parent_formatter = @attributes, @key_formatter
|
267
|
+
@attributes = BLANK
|
268
|
+
yield
|
269
|
+
@attributes
|
270
|
+
ensure
|
271
|
+
@attributes, @key_formatter = parent_attributes, parent_formatter
|
272
|
+
end
|
273
|
+
|
274
|
+
def _is_collection?(object)
|
275
|
+
_object_respond_to?(object, :map, :count) && NON_ENUMERABLES.none?{ |klass| klass === object }
|
276
|
+
end
|
263
277
|
|
264
|
-
|
265
|
-
|
278
|
+
def _blank?(value=@attributes)
|
279
|
+
BLANK == value
|
280
|
+
end
|
281
|
+
|
282
|
+
def _blank
|
283
|
+
BLANK
|
284
|
+
end
|
285
|
+
|
286
|
+
def _object_respond_to?(object, *methods)
|
287
|
+
methods.all?{ |m| object.respond_to?(m) }
|
288
|
+
end
|
289
|
+
|
290
|
+
def _args_for_set_with_block(*args)
|
291
|
+
# return args
|
292
|
+
key = args[0]
|
293
|
+
# #todo: check this
|
294
|
+
# #
|
295
|
+
if ::Hash === args[1] && _extended_options?(args[1])
|
296
|
+
options = args[1]
|
297
|
+
[key, BLANK, options]
|
298
|
+
else
|
299
|
+
[key, BLANK]
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
def _args_for_set(*args)
|
304
|
+
return args
|
305
|
+
# if args.length >= 3
|
306
|
+
# return args
|
307
|
+
# # key, value, options = args
|
308
|
+
# #
|
309
|
+
# # [key, value, options]
|
310
|
+
# else
|
311
|
+
# key, value = args
|
312
|
+
#
|
313
|
+
# [key, value]
|
314
|
+
# end
|
315
|
+
end
|
316
|
+
|
317
|
+
def _extended_options?(value)
|
318
|
+
false
|
319
|
+
end
|
320
|
+
|
321
|
+
def _breezy_return(results)
|
322
|
+
"return (#{_dump(results)});"
|
323
|
+
end
|
324
|
+
|
325
|
+
def _dump(value)
|
326
|
+
::MultiJson.dump(value)
|
327
|
+
end
|
328
|
+
|
329
|
+
def _logger
|
330
|
+
::ActionView::Base.logger
|
331
|
+
end
|
332
|
+
|
333
|
+
class Engine < ::Rails::Engine
|
334
|
+
initializer :breezy_template do |app|
|
335
|
+
ActiveSupport.on_load(:action_view) do
|
336
|
+
ActionView::Template.register_template_handler :breezy, BreezyTemplate::Handler
|
337
|
+
ActionView::Template.register_template_handler :props, BreezyTemplate::Handler
|
338
|
+
require 'breezy_template/dependency_tracker'
|
266
339
|
end
|
340
|
+
end
|
267
341
|
end
|
268
342
|
end
|