tml 4.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +22 -0
  3. data/README.md +243 -0
  4. data/Rakefile +9 -0
  5. data/lib/tml.rb +56 -0
  6. data/lib/tml/api/client.rb +206 -0
  7. data/lib/tml/api/post_office.rb +71 -0
  8. data/lib/tml/application.rb +254 -0
  9. data/lib/tml/base.rb +116 -0
  10. data/lib/tml/cache.rb +143 -0
  11. data/lib/tml/cache_adapters/file.rb +89 -0
  12. data/lib/tml/cache_adapters/memcache.rb +104 -0
  13. data/lib/tml/cache_adapters/memory.rb +85 -0
  14. data/lib/tml/cache_adapters/redis.rb +108 -0
  15. data/lib/tml/config.rb +410 -0
  16. data/lib/tml/decorators/base.rb +52 -0
  17. data/lib/tml/decorators/default.rb +43 -0
  18. data/lib/tml/decorators/html.rb +102 -0
  19. data/lib/tml/exception.rb +35 -0
  20. data/lib/tml/ext/array.rb +86 -0
  21. data/lib/tml/ext/date.rb +99 -0
  22. data/lib/tml/ext/fixnum.rb +47 -0
  23. data/lib/tml/ext/hash.rb +99 -0
  24. data/lib/tml/ext/string.rb +56 -0
  25. data/lib/tml/ext/time.rb +89 -0
  26. data/lib/tml/generators/cache/base.rb +117 -0
  27. data/lib/tml/generators/cache/file.rb +159 -0
  28. data/lib/tml/language.rb +175 -0
  29. data/lib/tml/language_case.rb +105 -0
  30. data/lib/tml/language_case_rule.rb +76 -0
  31. data/lib/tml/language_context.rb +117 -0
  32. data/lib/tml/language_context_rule.rb +56 -0
  33. data/lib/tml/languages/en.json +1363 -0
  34. data/lib/tml/logger.rb +109 -0
  35. data/lib/tml/rules_engine/evaluator.rb +162 -0
  36. data/lib/tml/rules_engine/parser.rb +65 -0
  37. data/lib/tml/session.rb +199 -0
  38. data/lib/tml/source.rb +106 -0
  39. data/lib/tml/tokenizers/data.rb +96 -0
  40. data/lib/tml/tokenizers/decoration.rb +204 -0
  41. data/lib/tml/tokenizers/dom.rb +346 -0
  42. data/lib/tml/tokens/data.rb +403 -0
  43. data/lib/tml/tokens/method.rb +61 -0
  44. data/lib/tml/tokens/transform.rb +223 -0
  45. data/lib/tml/translation.rb +67 -0
  46. data/lib/tml/translation_key.rb +178 -0
  47. data/lib/tml/translator.rb +47 -0
  48. data/lib/tml/utils.rb +130 -0
  49. data/lib/tml/version.rb +34 -0
  50. metadata +121 -0
@@ -0,0 +1,71 @@
1
+ # encoding: UTF-8
2
+ #--
3
+ # Copyright (c) 2015 Translation Exchange, Inc
4
+ #
5
+ # _______ _ _ _ ______ _
6
+ # |__ __| | | | | (_) | ____| | |
7
+ # | |_ __ __ _ _ __ ___| | __ _| |_ _ ___ _ __ | |__ __ _____| |__ __ _ _ __ __ _ ___
8
+ # | | '__/ _` | '_ \/ __| |/ _` | __| |/ _ \| '_ \| __| \ \/ / __| '_ \ / _` | '_ \ / _` |/ _ \
9
+ # | | | | (_| | | | \__ \ | (_| | |_| | (_) | | | | |____ > < (__| | | | (_| | | | | (_| | __/
10
+ # |_|_| \__,_|_| |_|___/_|\__,_|\__|_|\___/|_| |_|______/_/\_\___|_| |_|\__,_|_| |_|\__, |\___|
11
+ # __/ |
12
+ # |___/
13
+ # Permission is hereby granted, free of charge, to any person obtaining
14
+ # a copy of this software and associated documentation files (the
15
+ # "Software"), to deal in the Software without restriction, including
16
+ # without limitation the rights to use, copy, modify, merge, publish,
17
+ # distribute, sublicense, and/or sell copies of the Software, and to
18
+ # permit persons to whom the Software is furnished to do so, subject to
19
+ # the following conditions:
20
+ #
21
+ # The above copyright notice and this permission notice shall be
22
+ # included in all copies or substantial portions of the Software.
23
+ #
24
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31
+ #++
32
+
33
+ class Tml::Api::PostOffice < Tml::Api::Client
34
+ POST_OFFICE_HOST = 'https://postoffice.translationexchange.com'
35
+ POST_OFFICE_API_VERSION = 'v1'
36
+
37
+ attributes :application
38
+
39
+ def templates
40
+ api('templates', {
41
+ :access_token => access_token
42
+ })
43
+ end
44
+
45
+ def channels
46
+ api('channels', {
47
+ :access_token => access_token
48
+ })
49
+ end
50
+
51
+ def deliver(template, to, tokens = {}, options = {})
52
+ api("templates/#{template}/deliver", {
53
+ :access_token => access_token,
54
+ :tokens => tokens,
55
+ :to => to,
56
+ :via => options[:via],
57
+ :from => options[:from],
58
+ :locale => options[:locale],
59
+ :realtime => options[:realtime]
60
+ }, options.merge(:method => :post))
61
+ end
62
+
63
+ def host
64
+ application.tools['postoffice'] || POST_OFFICE_HOST
65
+ end
66
+
67
+ def prepare_api_path(path)
68
+ "/api/#{POST_OFFICE_API_VERSION}#{path.first == '/' ? '' : '/'}#{path}"
69
+ end
70
+
71
+ end
@@ -0,0 +1,254 @@
1
+ # encoding: UTF-8
2
+ #--
3
+ # Copyright (c) 2015 Translation Exchange, Inc
4
+ #
5
+ # _______ _ _ _ ______ _
6
+ # |__ __| | | | | (_) | ____| | |
7
+ # | |_ __ __ _ _ __ ___| | __ _| |_ _ ___ _ __ | |__ __ _____| |__ __ _ _ __ __ _ ___
8
+ # | | '__/ _` | '_ \/ __| |/ _` | __| |/ _ \| '_ \| __| \ \/ / __| '_ \ / _` | '_ \ / _` |/ _ \
9
+ # | | | | (_| | | | \__ \ | (_| | |_| | (_) | | | | |____ > < (__| | | | (_| | | | | (_| | __/
10
+ # |_|_| \__,_|_| |_|___/_|\__,_|\__|_|\___/|_| |_|______/_/\_\___|_| |_|\__,_|_| |_|\__, |\___|
11
+ # __/ |
12
+ # |___/
13
+ # Permission is hereby granted, free of charge, to any person obtaining
14
+ # a copy of this software and associated documentation files (the
15
+ # "Software"), to deal in the Software without restriction, including
16
+ # without limitation the rights to use, copy, modify, merge, publish,
17
+ # distribute, sublicense, and/or sell copies of the Software, and to
18
+ # permit persons to whom the Software is furnished to do so, subject to
19
+ # the following conditions:
20
+ #
21
+ # The above copyright notice and this permission notice shall be
22
+ # included in all copies or substantial portions of the Software.
23
+ #
24
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31
+ #++
32
+
33
+ require 'faraday'
34
+
35
+ class Tml::Application < Tml::Base
36
+ attributes :host, :id, :key, :secret, :access_token, :name, :description, :threshold, :default_locale, :default_level, :tools
37
+ has_many :features, :languages, :featured_locales, :sources, :components, :tokens, :css, :shortcuts, :translations
38
+
39
+ def self.cache_key
40
+ 'application'
41
+ end
42
+
43
+ def self.translations_cache_key(locale)
44
+ "#{locale}/translations"
45
+ end
46
+
47
+ def fetch
48
+ update_attributes(api_client.get('applications/current', {:definition => true}, {:cache_key => self.class.cache_key}))
49
+ rescue Tml::Exception => ex
50
+ Tml.logger.error("Failed to load application: #{ex}")
51
+ self
52
+ end
53
+
54
+ def update_attributes(attrs)
55
+ super
56
+
57
+ self.attributes[:languages] = []
58
+ if hash_value(attrs, :languages)
59
+ self.attributes[:languages] = hash_value(attrs, :languages).collect{ |l| Tml::Language.new(l.merge(:application => self)) }
60
+ end
61
+
62
+ self
63
+ end
64
+
65
+ def language(locale = nil)
66
+ locale = nil if locale.strip == ''
67
+ locale ||= default_locale || Tml.config.default_locale
68
+ @languages_by_locale ||= {}
69
+ @languages_by_locale[locale] ||= api_client.get(
70
+ "languages/#{locale}",
71
+ {:definition => true},
72
+ {
73
+ :class => Tml::Language,
74
+ :attributes => {:locale => locale, :application => self},
75
+ :cache_key => Tml::Language.cache_key(locale)
76
+ }
77
+ )
78
+ rescue Tml::Exception => e
79
+ Tml.logger.error(e)
80
+ Tml.logger.error(e.backtrace)
81
+ @languages_by_locale[locale] = Tml.config.default_language
82
+ end
83
+
84
+ # Mostly used for testing
85
+ def add_language(new_language)
86
+ @languages_by_locale ||= {}
87
+ return @languages_by_locale[new_language.locale] if @languages_by_locale[new_language.locale]
88
+ new_language.application = self
89
+ self.languages << new_language
90
+ @languages_by_locale[new_language.locale] = new_language
91
+ new_language
92
+ end
93
+
94
+ def locales
95
+ @locales ||= languages.collect{|lang| lang.locale}
96
+ end
97
+
98
+ def tools
99
+ @attributes[:tools] || {}
100
+ end
101
+
102
+ def url_for(path)
103
+ "#{tools['assets']}#{path}"
104
+ end
105
+
106
+ def source(source, locale)
107
+ self.sources ||= {}
108
+ self.sources[source] ||= Tml::Source.new(
109
+ :application => self,
110
+ :source => source
111
+ ).fetch_translations(locale)
112
+ end
113
+
114
+ def component(key, register = true)
115
+ key = key.key if key.is_a?(Tml::Component)
116
+
117
+ return self.components[key] if self.components[key]
118
+ return nil unless register
119
+
120
+ self.components[key] ||= api_client.post('components/register', {:component => key}, {:class => Tml::Component, :attributes => {:application => self}})
121
+ end
122
+
123
+ def register_missing_key(source_key, tkey)
124
+ return if Tml.cache.read_only? and not Tml.session.inline_mode?
125
+
126
+ @missing_keys_by_sources ||= {}
127
+ @missing_keys_by_sources[source_key] ||= {}
128
+ @missing_keys_by_sources[source_key][tkey.key] ||= tkey
129
+ submit_missing_keys if Tml.config.submit_missing_keys_realtime
130
+ end
131
+
132
+ def register_keys(keys)
133
+ params = []
134
+ keys.each do |source_key, keys|
135
+ next unless keys.values.any?
136
+ source = Tml::Source.new(:source => source_key, :application => self)
137
+ params << {:source => source_key, :keys => keys.values.collect{|tkey| tkey.to_hash(:label, :description, :locale, :level)}}
138
+ source.reset_cache
139
+ end
140
+
141
+ api_client.post('sources/register_keys', {:source_keys => params.to_json})
142
+ rescue Tml::Exception => e
143
+ Tml.logger.error('Failed to register missing translation keys...')
144
+ Tml.logger.error(e)
145
+ Tml.logger.error(e.backtrace)
146
+ end
147
+
148
+ def submit_missing_keys
149
+ return if @missing_keys_by_sources.nil? or @missing_keys_by_sources.empty?
150
+ register_keys(@missing_keys_by_sources)
151
+ @missing_keys_by_sources = nil
152
+ end
153
+
154
+ def featured_languages
155
+ @featured_languages ||= begin
156
+ locales = api_client.get('applications/current/featured_locales', {}, {:cache_key => 'featured_locales'})
157
+ (locales.nil? or locales.empty?) ? [] : languages.select{|l| locales.include?(l.locale)}
158
+ end
159
+ rescue
160
+ []
161
+ end
162
+
163
+ def translators
164
+ @translators ||= api_client.get('applications/current/translators', {}, {:class => Tml::Translator, :attributes => {:application => self}})
165
+ rescue
166
+ []
167
+ end
168
+
169
+ def reset_translation_cache
170
+ self.sources = {}
171
+ self.translations = {}
172
+ @languages_by_locale = nil
173
+ @missing_keys_by_sources = nil
174
+ end
175
+
176
+ def fetch_translations(locale)
177
+ self.translations ||= {}
178
+ self.translations[locale] ||= begin
179
+ results = Tml.cache.fetch(Tml::Application.translations_cache_key(locale)) do
180
+ data = {}
181
+ unless Tml.cache.read_only?
182
+ api_client.paginate('applications/current/translations', :per_page => 1000) do |translations|
183
+ data.merge!(translations)
184
+ end
185
+ end
186
+ data
187
+ end
188
+
189
+ translations_by_key = {}
190
+ results.each do |key, data|
191
+ translations_data = data.is_a?(Hash) ? data['translations'] : data
192
+ translations_by_key[key] = translations_data.collect do |t|
193
+ Tml::Translation.new(
194
+ :locale => t['locale'] || locale,
195
+ :label => t['label'],
196
+ :context => t['context']
197
+ )
198
+ end
199
+ end
200
+ translations_by_key
201
+ end
202
+ rescue Tml::Exception => ex
203
+ {}
204
+ end
205
+
206
+ def cache_translations(locale, key, new_translations)
207
+ self.translations ||= {}
208
+ self.translations[locale] ||= {}
209
+ self.translations[locale][key] = new_translations.collect do |t|
210
+ Tml::Translation.new(
211
+ :locale => t['locale'] || locale,
212
+ :label => t['label'],
213
+ :context => t['context']
214
+ )
215
+ end
216
+ end
217
+
218
+ def cached_translations(locale, key)
219
+ return unless self.translations and self.translations[locale]
220
+ self.translations[locale][key]
221
+ end
222
+
223
+ def debug_translations
224
+ return 'no translations' unless self.translations
225
+ self.translations.each do |locale, keys|
226
+ pp [locale, keys.collect{|key, translations|
227
+ [key, translations.collect{|t|
228
+ [t.label, t.context]
229
+ }]
230
+ }]
231
+ end
232
+ end
233
+
234
+ def default_decoration_token(token)
235
+ hash_value(tokens, "decoration.#{token.to_s}")
236
+ end
237
+
238
+ def default_data_token(token)
239
+ hash_value(tokens, "data.#{token.to_s}")
240
+ end
241
+
242
+ def feature_enabled?(key)
243
+ hash_value(features, key.to_s)
244
+ end
245
+
246
+ def api_client
247
+ @api_client ||= Tml::Api::Client.new(:application => self)
248
+ end
249
+
250
+ def postoffice
251
+ @postoffice ||= Tml::Api::PostOffice.new(:application => self)
252
+ end
253
+
254
+ end
data/lib/tml/base.rb ADDED
@@ -0,0 +1,116 @@
1
+ # encoding: UTF-8
2
+ #--
3
+ # Copyright (c) 2015 Translation Exchange, Inc
4
+ #
5
+ # _______ _ _ _ ______ _
6
+ # |__ __| | | | | (_) | ____| | |
7
+ # | |_ __ __ _ _ __ ___| | __ _| |_ _ ___ _ __ | |__ __ _____| |__ __ _ _ __ __ _ ___
8
+ # | | '__/ _` | '_ \/ __| |/ _` | __| |/ _ \| '_ \| __| \ \/ / __| '_ \ / _` | '_ \ / _` |/ _ \
9
+ # | | | | (_| | | | \__ \ | (_| | |_| | (_) | | | | |____ > < (__| | | | (_| | | | | (_| | __/
10
+ # |_|_| \__,_|_| |_|___/_|\__,_|\__|_|\___/|_| |_|______/_/\_\___|_| |_|\__,_|_| |_|\__, |\___|
11
+ # __/ |
12
+ # |___/
13
+ # Permission is hereby granted, free of charge, to any person obtaining
14
+ # a copy of this software and associated documentation files (the
15
+ # "Software"), to deal in the Software without restriction, including
16
+ # without limitation the rights to use, copy, modify, merge, publish,
17
+ # distribute, sublicense, and/or sell copies of the Software, and to
18
+ # permit persons to whom the Software is furnished to do so, subject to
19
+ # the following conditions:
20
+ #
21
+ # The above copyright notice and this permission notice shall be
22
+ # included in all copies or substantial portions of the Software.
23
+ #
24
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31
+ #++
32
+
33
+ class Tml::Base
34
+ attr_reader :attributes
35
+
36
+ def initialize(attrs = {})
37
+ @attributes = {}
38
+ update_attributes(attrs)
39
+ end
40
+
41
+ def update_attributes(attrs = {})
42
+ attrs.each do |key, value|
43
+ #pp [self.class.name, key, self.class.attributes, self.class.attributes.include?(key.to_sym)]
44
+ next unless self.class.attributes.include?(key.to_sym)
45
+ @attributes[key.to_sym] = value
46
+ end
47
+ end
48
+
49
+ def self.attributes(*attrs)
50
+ @attribute_names ||= []
51
+ @attribute_names += attrs.collect{|a| a.to_sym} unless attrs.nil?
52
+ @attribute_names
53
+ end
54
+ def self.belongs_to(*attrs) self.attributes(*attrs); end
55
+ def self.has_many(*attrs) self.attributes(*attrs); end
56
+
57
+ def method_missing(meth, *args, &block)
58
+ method_name = meth.to_s
59
+ method_suffix = method_name[-1, 1]
60
+ method_key = method_name.to_sym
61
+ if %w(= ?).include?(method_suffix)
62
+ method_key = method_name[0..-2].to_sym
63
+ end
64
+
65
+ if self.class.attributes.index(method_key)
66
+ if method_suffix == '='
67
+ attributes[method_key] = args.first
68
+ return attributes[method_key]
69
+ end
70
+ return attributes[method_key]
71
+ end
72
+
73
+ super
74
+ end
75
+
76
+ def self.hash_value(hash, key, opts = {})
77
+ return nil unless hash.is_a?(Hash)
78
+ return hash[key.to_s] || hash[key.to_sym] if opts[:whole]
79
+
80
+ value = hash
81
+ key.to_s.split('.').each do |part|
82
+ return nil unless value.is_a?(Hash)
83
+ value = value[part.to_sym] || value[part.to_s]
84
+ end
85
+ value
86
+ end
87
+
88
+ def hash_value(hash, key, opts = {})
89
+ self.class.hash_value(hash, key, opts)
90
+ end
91
+
92
+ def to_hash(*attrs)
93
+ if attrs.nil? or attrs.empty?
94
+ # default hashing only includes basic types
95
+ keys = []
96
+ self.class.attributes.each do |key|
97
+ value = attributes[key]
98
+ next if value.kind_of?(Tml::Base) or value.kind_of?(Hash) or value.kind_of?(Array)
99
+ keys << key
100
+ end
101
+ else
102
+ keys = attrs
103
+ end
104
+
105
+ hash = {}
106
+ keys.each do |key|
107
+ hash[key] = attributes[key]
108
+ end
109
+
110
+ proc = Proc.new { |k, v| v.kind_of?(Hash) ? (v.delete_if(&proc); nil) : v.nil? }
111
+ hash.delete_if(&proc)
112
+
113
+ hash
114
+ end
115
+
116
+ end
data/lib/tml/cache.rb ADDED
@@ -0,0 +1,143 @@
1
+ # encoding: UTF-8
2
+ #--
3
+ # Copyright (c) 2015 Translation Exchange, Inc
4
+ #
5
+ # _______ _ _ _ ______ _
6
+ # |__ __| | | | | (_) | ____| | |
7
+ # | |_ __ __ _ _ __ ___| | __ _| |_ _ ___ _ __ | |__ __ _____| |__ __ _ _ __ __ _ ___
8
+ # | | '__/ _` | '_ \/ __| |/ _` | __| |/ _ \| '_ \| __| \ \/ / __| '_ \ / _` | '_ \ / _` |/ _ \
9
+ # | | | | (_| | | | \__ \ | (_| | |_| | (_) | | | | |____ > < (__| | | | (_| | | | | (_| | __/
10
+ # |_|_| \__,_|_| |_|___/_|\__,_|\__|_|\___/|_| |_|______/_/\_\___|_| |_|\__,_|_| |_|\__, |\___|
11
+ # __/ |
12
+ # |___/
13
+ # Permission is hereby granted, free of charge, to any person obtaining
14
+ # a copy of this software and associated documentation files (the
15
+ # "Software"), to deal in the Software without restriction, including
16
+ # without limitation the rights to use, copy, modify, merge, publish,
17
+ # distribute, sublicense, and/or sell copies of the Software, and to
18
+ # permit persons to whom the Software is furnished to do so, subject to
19
+ # the following conditions:
20
+ #
21
+ # The above copyright notice and this permission notice shall be
22
+ # included in all copies or substantial portions of the Software.
23
+ #
24
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31
+ #++
32
+
33
+ module Tml
34
+
35
+ CACHE_VERSION_KEY = '__tml_version__'
36
+
37
+ def self.memory
38
+ @memory ||= Tml::CacheAdapters::Memory.new
39
+ end
40
+
41
+ def self.cache
42
+ @cache ||= begin
43
+ if Tml.config.cache_enabled?
44
+ klass = Tml::CacheAdapters.const_get(Tml.config.cache[:adapter].camelcase)
45
+ klass.new
46
+ else
47
+ # blank implementation
48
+ Tml::Cache.new
49
+ end
50
+ end
51
+ end
52
+
53
+ class Cache
54
+
55
+ def version
56
+ Tml.config.cache[:version] ||= 1
57
+
58
+ @version ||= begin
59
+ v = fetch(CACHE_VERSION_KEY) do
60
+ {'version' => Tml.config.cache[:version]}
61
+ end
62
+ v['version']
63
+ end
64
+
65
+ @version ||= Tml.config.cache[:version]
66
+
67
+ if Tml.config.cache[:version] > @version
68
+ update_version(Tml.config.cache[:version])
69
+ @version = Tml.config.cache[:version]
70
+ end
71
+
72
+ @version
73
+ end
74
+
75
+ def update_version(new_version)
76
+ store(CACHE_VERSION_KEY, {'version' => new_version}, :ttl => 0)
77
+ end
78
+
79
+ def upgrade_version
80
+ update_version(version + 1)
81
+ @version = nil
82
+ end
83
+
84
+ def reset_version
85
+ @version = nil
86
+ end
87
+
88
+ def enabled?
89
+ Tml.config.cache[:enabled]
90
+ end
91
+
92
+ def cached_by_source?
93
+ true
94
+ end
95
+
96
+ def read_only?
97
+ false
98
+ end
99
+
100
+ def segmented?
101
+ true
102
+ end
103
+
104
+ def cache_name
105
+ self.class.name.split('::').last
106
+ end
107
+
108
+ def info(msg)
109
+ Tml.logger.info("#{cache_name} - #{msg}")
110
+ end
111
+
112
+ def warn(msg)
113
+ Tml.logger.warn("#{cache_name} - #{msg}")
114
+ end
115
+
116
+ def versioned_key(key, opts = {})
117
+ return key if CACHE_VERSION_KEY == key
118
+ "tml_rc_v#{version}_#{key}"
119
+ end
120
+
121
+ def fetch(key, opts = {})
122
+ return nil unless block_given?
123
+ yield
124
+ end
125
+
126
+ def store(key, data, opts = {})
127
+ # do nothing
128
+ end
129
+
130
+ def delete(key, opts = {})
131
+ # do nothing
132
+ end
133
+
134
+ def exist?(key, opts = {})
135
+ false
136
+ end
137
+
138
+ def clear(opts = {})
139
+ # do nothing
140
+ end
141
+
142
+ end
143
+ end