mustache_render 0.0.21 → 0.0.22
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +22 -0
- data/lib/generators/mustache_render/install/templates/active_record/migration.rb +65 -0
- data/lib/generators/mustache_render/install/templates/config/initializers/mustache_render.rb +8 -14
- data/lib/generators/mustache_render/install/templates/models/active_record/mustache_render_folder.rb +6 -0
- data/lib/generators/mustache_render/install/templates/models/active_record/mustache_render_manager.rb +6 -0
- data/lib/generators/mustache_render/install/templates/models/active_record/mustache_render_template.rb +6 -0
- data/lib/generators/mustache_render/install/templates/models/active_record/mustache_render_template_version.rb +6 -0
- data/lib/generators/mustache_render/install_generator.rb +14 -2
- data/lib/mustache_render.rb +5 -14
- data/lib/mustache_render/ables.rb +7 -0
- data/lib/mustache_render/ables/render_able.rb +161 -0
- data/lib/mustache_render/config.rb +24 -62
- data/lib/mustache_render/errors.rb +5 -0
- data/lib/mustache_render/errors/mustache_template_miss_error.rb +6 -0
- data/lib/mustache_render/mustache.rb +85 -79
- data/lib/mustache_render/mustache/data.rb +155 -61
- data/lib/mustache_render/mustache/parser.rb +0 -4
- data/lib/mustache_render/mustache/template.rb +2 -7
- data/lib/mustache_render/populator.rb +7 -0
- data/lib/mustache_render/utils.rb +15 -0
- data/lib/mustache_render/{core_ext/base_controller_ext.rb → utils/action_controller_util.rb} +7 -6
- data/lib/mustache_render/utils/array_util.rb +15 -0
- data/lib/mustache_render/utils/fields_filter_util.rb +127 -0
- data/lib/mustache_render/version.rb +1 -1
- data/spec/lib/ables/render_able_spec.rb +183 -0
- data/spec/lib/mustache/basic_render_spec.rb +26 -1
- data/spec/lib/mustache/data_spec.rb +5 -5
- data/spec/lib/mustache/file_render_spec.rb +11 -2
- data/spec/lib/resources/templates/mustache_render_ables/1.mustache +11 -0
- data/spec/lib/utils/field_filter_spec.rb +71 -0
- data/spec/spec_helper.rb +0 -21
- metadata +69 -59
- data/README.md +0 -23
- data/lib/mustache_render/adapter.rb +0 -75
- data/lib/mustache_render/populator_base.rb +0 -88
- data/spec/lib/config_spec.rb +0 -14
- data/spec/lib/resources/templates/basic/8.mustache +0 -1
@@ -1,7 +1,7 @@
|
|
1
1
|
# -*- encoding : utf-8 -*-
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
2
|
+
require "#{File.dirname(__FILE__)}/mustache/template"
|
3
|
+
require "#{File.dirname(__FILE__)}/mustache/context"
|
4
|
+
require "#{File.dirname(__FILE__)}/mustache/data"
|
5
5
|
|
6
6
|
module MustacheRender
|
7
7
|
class Mustache
|
@@ -20,19 +20,21 @@ module MustacheRender
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def render(data = template, ctx = {})
|
23
|
-
|
24
|
-
impl_template_render data, ctx
|
25
|
-
end
|
26
|
-
end
|
23
|
+
self.template = data
|
27
24
|
|
28
|
-
|
29
|
-
def partials_tree
|
25
|
+
return self.template.render(context) if ctx == {}
|
30
26
|
|
27
|
+
begin
|
28
|
+
context.push(ctx)
|
29
|
+
self.template.render(context)
|
30
|
+
ensure
|
31
|
+
context.pop
|
32
|
+
end
|
31
33
|
end
|
32
34
|
|
33
35
|
# Context accessors.
|
34
36
|
#
|
35
|
-
# view =
|
37
|
+
# view = Mustache.new
|
36
38
|
# view[:name] = "Jon"
|
37
39
|
# view.template = "Hi, {{name}}!"
|
38
40
|
# view.render # => "Hi, Jon!"
|
@@ -51,15 +53,6 @@ module MustacheRender
|
|
51
53
|
@context ||= Context.new(self)
|
52
54
|
end
|
53
55
|
|
54
|
-
# 使用default_media 进行渲染
|
55
|
-
def self.impl_render(name, context={})
|
56
|
-
self.new.send :impl_render, name, context
|
57
|
-
end
|
58
|
-
|
59
|
-
def impl_render name, context={}
|
60
|
-
send "#{::MustacheRender.config.default_render_media}_render".to_sym, name, context
|
61
|
-
end
|
62
|
-
|
63
56
|
# Given a file name and an optional context, attempts to load and
|
64
57
|
# render the file as a template.
|
65
58
|
def self.file_render(name, context = {})
|
@@ -69,10 +62,22 @@ module MustacheRender
|
|
69
62
|
# Given a file name and an optional context, attempts to load and
|
70
63
|
# render the file as a template.
|
71
64
|
def file_render(name, context = {})
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
65
|
+
@media = :file
|
66
|
+
render(partial(name), context)
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.db_render(full_path, context={})
|
70
|
+
self.new.db_render full_path, context
|
71
|
+
end
|
72
|
+
|
73
|
+
def db_render(full_path, context={})
|
74
|
+
@media = :db
|
75
|
+
render(partial(full_path), context)
|
76
|
+
end
|
77
|
+
|
78
|
+
def impl_read_db_template name
|
79
|
+
db_template = ::MustacheRenderTemplate.find_with_full_path(name)
|
80
|
+
db_template.try :content
|
76
81
|
end
|
77
82
|
|
78
83
|
def self.generate_template_name(name, template_extension)
|
@@ -98,7 +103,7 @@ module MustacheRender
|
|
98
103
|
File.read full_path
|
99
104
|
rescue
|
100
105
|
if config.raise_on_file_template_miss?
|
101
|
-
raise ::MustacheRender::
|
106
|
+
raise ::MustacheRender::MustacheTemplateMissError.new("miss read file template error: #{full_path}")
|
102
107
|
else
|
103
108
|
''
|
104
109
|
end
|
@@ -106,23 +111,10 @@ module MustacheRender
|
|
106
111
|
end
|
107
112
|
|
108
113
|
def read_template_from_media name, media
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
case media
|
115
|
-
when :file
|
116
|
-
# if ::MustacheRender.config.file_template_cache?
|
117
|
-
# self.class.fetch_partial_cache name, media, :expires_in => ::MustacheRender.config.file_template_cache_expires_in do
|
118
|
-
# impl_read_file_template name
|
119
|
-
# end
|
120
|
-
# else
|
121
|
-
# impl_read_file_template name
|
122
|
-
# end
|
123
|
-
|
124
|
-
impl_read_file_template name
|
125
|
-
end
|
114
|
+
::MustacheRender.logger.debug "MustacheRender render -> read template from #{media}: #{name}"
|
115
|
+
case media
|
116
|
+
when :file
|
117
|
+
impl_read_file_template name
|
126
118
|
end
|
127
119
|
end
|
128
120
|
|
@@ -132,6 +124,7 @@ module MustacheRender
|
|
132
124
|
def partial(name)
|
133
125
|
name = self.class.generate_template_name name, config.file_template_extension
|
134
126
|
|
127
|
+
# return self.read_template_from_media name, media
|
135
128
|
@_cached_partials ||= {}
|
136
129
|
(@_cached_partials[media] ||= {})[name] ||= self.read_template_from_media name, media
|
137
130
|
end
|
@@ -149,6 +142,56 @@ module MustacheRender
|
|
149
142
|
CGI.escapeHTML(str)
|
150
143
|
end
|
151
144
|
|
145
|
+
#
|
146
|
+
# Private API
|
147
|
+
#
|
148
|
+
|
149
|
+
# When given a symbol or string representing a class, will try to produce an
|
150
|
+
# appropriate view class.
|
151
|
+
# e.g.
|
152
|
+
# Mustache.view_namespace = Hurl::Views
|
153
|
+
# Mustache.view_class(:Partial) # => Hurl::Views::Partial
|
154
|
+
def self.view_class(name)
|
155
|
+
if name != classify(name.to_s)
|
156
|
+
name = classify(name.to_s)
|
157
|
+
end
|
158
|
+
|
159
|
+
# Emptiness begets emptiness.
|
160
|
+
if name.to_s == ''
|
161
|
+
return Mustache
|
162
|
+
end
|
163
|
+
|
164
|
+
file_name = underscore(name)
|
165
|
+
|
166
|
+
name = "#{view_namespace}::#{name}"
|
167
|
+
|
168
|
+
if const = const_get!(name)
|
169
|
+
const
|
170
|
+
elsif File.exists?(file = "#{view_path}/#{file_name}.rb")
|
171
|
+
require "#{file}".chomp('.rb')
|
172
|
+
const_get!(name) || Mustache
|
173
|
+
else
|
174
|
+
Mustache
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
# Supercharged version of Module#const_get.
|
179
|
+
#
|
180
|
+
# Always searches under Object and can find constants by their full name,
|
181
|
+
# e.g. Mustache::Views::Index
|
182
|
+
#
|
183
|
+
# name - The full constant name to find.
|
184
|
+
#
|
185
|
+
# Returns the constant if found
|
186
|
+
# Returns nil if nothing is found
|
187
|
+
def self.const_get!(name)
|
188
|
+
name.split('::').inject(Object) do |klass, name|
|
189
|
+
klass.const_get(name)
|
190
|
+
end
|
191
|
+
rescue NameError
|
192
|
+
nil
|
193
|
+
end
|
194
|
+
|
152
195
|
# Has this template already been compiled? Compilation is somewhat
|
153
196
|
# expensive so it may be useful to check this before attempting it.
|
154
197
|
def self.compiled?
|
@@ -180,7 +223,7 @@ module MustacheRender
|
|
180
223
|
end.join('::')
|
181
224
|
end
|
182
225
|
|
183
|
-
#
|
226
|
+
# TemplatePartial => template_partial
|
184
227
|
# Template::Partial => template/partial
|
185
228
|
# Takes a string but defaults to using the current class' name.
|
186
229
|
def self.underscore(classified = name)
|
@@ -219,42 +262,5 @@ module MustacheRender
|
|
219
262
|
def self.inheritable_config_for(attr_name, default)
|
220
263
|
superclass.respond_to?(attr_name) ? superclass.send(attr_name) : default
|
221
264
|
end
|
222
|
-
|
223
|
-
private
|
224
|
-
|
225
|
-
def impl_logger options={}
|
226
|
-
level = options[:level] || :debug
|
227
|
-
|
228
|
-
result = nil
|
229
|
-
|
230
|
-
if block_given?
|
231
|
-
start_at = Time.now
|
232
|
-
result = yield
|
233
|
-
ms = ((Time.now - start_at) * 1000).to_i
|
234
|
-
MustacheRender.logger.send level, impl_format_log_entry(
|
235
|
-
"#{options[:operation]} (#{ms}ms)", options[:message]
|
236
|
-
)
|
237
|
-
end
|
238
|
-
|
239
|
-
result
|
240
|
-
end
|
241
|
-
|
242
|
-
def impl_format_log_entry(operation, message = nil)
|
243
|
-
" \033[4;34;1m#{operation}\033[0m \033[0;1m#{message}\033[0m"
|
244
|
-
end
|
245
|
-
|
246
|
-
def impl_template_render(data=template, ctx={})
|
247
|
-
self.template = data
|
248
|
-
|
249
|
-
return self.template.render(context) if ctx == {}
|
250
|
-
|
251
|
-
begin
|
252
|
-
context.push(ctx)
|
253
|
-
self.template.render(context)
|
254
|
-
ensure
|
255
|
-
context.pop
|
256
|
-
end
|
257
|
-
end
|
258
|
-
|
259
265
|
end
|
260
266
|
end
|
@@ -1,93 +1,187 @@
|
|
1
1
|
# -*- encoding : utf-8 -*-
|
2
2
|
module MustacheRender
|
3
|
-
class Mustache
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
3
|
+
class Mustache::Data < ::Hash
|
4
|
+
def initialize(options={})
|
5
|
+
self.merge! options
|
6
|
+
end
|
7
|
+
|
8
|
+
[:render, :file_render, :impl_render].each do |method_name|
|
9
|
+
define_method method_name do |path_or_template|
|
10
|
+
::MustacheRender::Mustache.send method_name, path_or_template, self
|
8
11
|
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def []=(name, value)
|
15
|
+
super(name.to_sym, value)
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_ary
|
19
|
+
end
|
9
20
|
|
10
|
-
|
11
|
-
|
12
|
-
|
21
|
+
def [](name)
|
22
|
+
super(name.to_sym)
|
23
|
+
end
|
24
|
+
|
25
|
+
def deep_merge(other_hash)
|
26
|
+
self.deep_dup.deep_merge!(other_hash)
|
27
|
+
end
|
28
|
+
|
29
|
+
# 深层的合并
|
30
|
+
def deep_merge!(other_hash)
|
31
|
+
other_hash = self.class.new(other_hash) unless other_hash.is_a?(self.class)
|
32
|
+
|
33
|
+
other_hash.each_pair do |k,v|
|
34
|
+
tv = self[k]
|
35
|
+
|
36
|
+
unless v.is_a?(self.class)
|
37
|
+
v = self.class.new(v) if v.is_a?(Hash)
|
13
38
|
end
|
39
|
+
|
40
|
+
self[k] = tv.is_a?(self.class) && v.is_a?(self.class) ? tv.deep_merge(v) : v
|
14
41
|
end
|
15
42
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
43
|
+
self
|
44
|
+
end
|
45
|
+
|
46
|
+
def deep_dup
|
47
|
+
impl_deep_dup self
|
48
|
+
end
|
49
|
+
|
50
|
+
def method_missing method_name, *args, &block
|
51
|
+
# 如果方法是赋值, 则直接赋值
|
52
|
+
if method_name.to_s.end_with?('=')
|
53
|
+
self[method_name.to_s.chop!] = args.first
|
54
|
+
else
|
55
|
+
result = self[method_name.to_sym]
|
56
|
+
|
57
|
+
if result.is_a?(Hash) && !(result.is_a?(self.class))
|
58
|
+
self[method_name] = self.class.new(result)
|
59
|
+
elsif result.nil?
|
60
|
+
self[method_name] = self.class.new
|
61
|
+
else
|
62
|
+
result
|
20
63
|
end
|
21
|
-
# self.stringify_keys!
|
22
|
-
result
|
23
64
|
end
|
65
|
+
end
|
24
66
|
|
25
|
-
|
26
|
-
|
27
|
-
|
67
|
+
def stringify_keys!
|
68
|
+
impl_stringify_keys! self
|
69
|
+
end
|
28
70
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
71
|
+
def symbolize_keys!
|
72
|
+
impl_symbolize_keys! self
|
73
|
+
end
|
74
|
+
|
75
|
+
#
|
76
|
+
# origin_hash_symbolize
|
77
|
+
# origin_hash_stringify
|
78
|
+
# origin_hash_symbolize! key全是 symbol的
|
79
|
+
# origin_hash_stringify! key全市 string 的
|
80
|
+
#
|
81
|
+
[:symbolize, :stringify].each do |method_name|
|
82
|
+
define_method "origin_hash_#{method_name}".to_sym do
|
83
|
+
self.deep_dup.send "origin_hash_#{method_name}!".to_sym
|
37
84
|
end
|
38
85
|
|
39
|
-
#
|
40
|
-
|
41
|
-
# data.site = {
|
42
|
-
# :name => 'abc'
|
43
|
-
# }
|
44
|
-
#
|
45
|
-
# 等价于
|
46
|
-
#
|
47
|
-
# data['site'] = {
|
48
|
-
# :name => 'abc'
|
49
|
-
# }
|
50
|
-
#
|
51
|
-
def method_missing method_name, *args, &block
|
52
|
-
# 如果方法是赋值, 则直接赋值
|
53
|
-
if method_name.to_s[-1,1] == "="
|
54
|
-
self[method_name.to_s.chop!] = args.first
|
55
|
-
else
|
56
|
-
result = self[method_name.to_s]
|
57
|
-
|
58
|
-
if result.is_a?(Hash)
|
59
|
-
self[method_name.to_s] = Data.new(result)
|
60
|
-
elsif result.nil? # 如果为空的话,则生成一个新的对象
|
61
|
-
self[method_name.to_s] = Data.new {}
|
62
|
-
else
|
63
|
-
result
|
64
|
-
end
|
65
|
-
end
|
86
|
+
define_method "origin_hash_#{method_name}!".to_sym do
|
87
|
+
self.send "impl_origin_hash_#{method_name}".to_sym, self
|
66
88
|
end
|
89
|
+
end
|
67
90
|
|
68
|
-
|
69
|
-
|
91
|
+
#
|
92
|
+
# deep_stringify_keys
|
93
|
+
# deep_stringify_keys!
|
94
|
+
#
|
95
|
+
[:stringify, :symbolize].each do |method_name|
|
96
|
+
method_name_impl = "impl_#{method_name}_keys".to_sym
|
97
|
+
method_name_new_soft = "deep_#{method_name}_keys".to_sym
|
98
|
+
method_name_new = "deep_#{method_name}_keys!".to_sym
|
99
|
+
|
100
|
+
define_method method_name_new_soft do
|
101
|
+
self.deep_dup.send method_name_new
|
70
102
|
end
|
71
103
|
|
72
|
-
|
73
|
-
|
104
|
+
define_method method_name_new do
|
105
|
+
tmp = self.send method_name_impl, self
|
106
|
+
|
107
|
+
tmp.keys.each do |key|
|
108
|
+
tmp[key] = self.send method_name_impl, tmp[key]
|
109
|
+
end
|
110
|
+
|
111
|
+
tmp
|
74
112
|
end
|
113
|
+
end
|
75
114
|
|
76
|
-
|
115
|
+
private
|
116
|
+
|
117
|
+
def impl_deep_dup v
|
118
|
+
if v.is_a?(::Hash)
|
119
|
+
tv = v.dup
|
120
|
+
|
121
|
+
v.each do |key, value|
|
122
|
+
tv[key] = impl_deep_dup value
|
123
|
+
end
|
124
|
+
|
125
|
+
tv
|
126
|
+
elsif v.is_a?(::Array)
|
127
|
+
v.map do |_v|
|
128
|
+
impl_deep_dup _v
|
129
|
+
end
|
130
|
+
else
|
131
|
+
v
|
132
|
+
end
|
133
|
+
end
|
77
134
|
|
78
|
-
|
135
|
+
[:stringify, :symbolize].each do |method_name|
|
136
|
+
typify_method = {:symbolize => :to_sym, :stringify => :to_s}[method_name]
|
137
|
+
method_name_new = "impl_origin_hash_#{method_name}".to_sym
|
138
|
+
define_method method_name_new do |v|
|
79
139
|
if v.is_a?(::Hash)
|
140
|
+
tv = Hash.new
|
141
|
+
|
80
142
|
v.keys.each do |key|
|
81
|
-
|
143
|
+
tv[key.send(typify_method)] = self.send(method_name_new, v[key])
|
82
144
|
end
|
145
|
+
|
146
|
+
tv
|
83
147
|
elsif v.is_a?(::Array)
|
84
|
-
v.
|
85
|
-
|
148
|
+
v.map do |_v|
|
149
|
+
self.send(method_name_new, _v)
|
86
150
|
end
|
151
|
+
else
|
152
|
+
v
|
87
153
|
end
|
88
154
|
end
|
155
|
+
end
|
156
|
+
|
157
|
+
[:stringify, :symbolize].each do |method_name|
|
158
|
+
typify_clazz = {:stringify => ::String, :symbolize => ::Hash}[method_name]
|
159
|
+
method_name_new = "impl_#{method_name}_keys".to_sym
|
160
|
+
typify_method = {:symbolize => :to_sym, :stringify => :to_s}[method_name]
|
161
|
+
|
162
|
+
define_method method_name_new do |v|
|
163
|
+
if v.is_a?(Hash)
|
164
|
+
v.keys.each do |key|
|
165
|
+
kv = v.delete key
|
89
166
|
|
167
|
+
unless key.is_a?(typify_clazz)
|
168
|
+
if(kv.is_a?(::Hash) && !(kv.is_a?(self.class)))
|
169
|
+
kv = self.class.new(kv)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
v[key.send(typify_method)] = self.send method_name_new, kv
|
174
|
+
end
|
175
|
+
elsif v.is_a?(Array)
|
176
|
+
v = v.map do |_v|
|
177
|
+
self.send method_name_new, _v
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
v
|
182
|
+
end
|
90
183
|
end
|
184
|
+
|
91
185
|
end
|
92
186
|
end
|
93
187
|
|