anoubis 1.0.1 → 1.0.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +10 -0
  3. data/app/controllers/anoubis/application_controller.rb +4 -0
  4. data/app/controllers/anoubis/core/index/actions.rb +1 -1
  5. data/app/controllers/anoubis/core/index_controller.rb +3 -3
  6. data/app/controllers/anoubis/data/actions.rb +947 -0
  7. data/app/controllers/anoubis/data/callbacks.rb +66 -0
  8. data/app/controllers/anoubis/data/convert.rb +422 -0
  9. data/app/controllers/anoubis/data/defaults.rb +215 -0
  10. data/app/controllers/anoubis/data/get.rb +529 -0
  11. data/app/controllers/anoubis/data/load.rb +87 -0
  12. data/app/controllers/anoubis/data/set.rb +47 -0
  13. data/app/controllers/anoubis/data/setup.rb +102 -0
  14. data/app/controllers/anoubis/data_controller.rb +21 -0
  15. data/app/controllers/anoubis/etc/field.rb +7 -0
  16. data/app/controllers/anoubis/output/basic.rb +1 -1
  17. data/app/controllers/anoubis/sso/client/index_controller.rb +2 -2
  18. data/app/controllers/anoubis/sso/server/login_controller.rb +5 -5
  19. data/app/controllers/anoubis/sso/server/user_controller.rb +2 -2
  20. data/app/controllers/anoubis/tenant/index_controller.rb +3 -3
  21. data/app/models/anoubis/application_record.rb +141 -0
  22. data/app/services/anoubis/log_service.rb +97 -0
  23. data/app/services/anoubis/request_service.rb +134 -0
  24. data/config/locales/en.yml +20 -6
  25. data/config/locales/ru.yml +25 -13
  26. data/config/routes.rb +19 -19
  27. data/lib/anoubis/version.rb +1 -1
  28. metadata +32 -33
  29. data/app/controllers/anoubis/core/data/actions.rb +0 -962
  30. data/app/controllers/anoubis/core/data/callbacks.rb +0 -68
  31. data/app/controllers/anoubis/core/data/convert.rb +0 -407
  32. data/app/controllers/anoubis/core/data/defaults.rb +0 -217
  33. data/app/controllers/anoubis/core/data/get.rb +0 -531
  34. data/app/controllers/anoubis/core/data/load.rb +0 -89
  35. data/app/controllers/anoubis/core/data/set.rb +0 -49
  36. data/app/controllers/anoubis/core/data/setup.rb +0 -104
  37. data/app/controllers/anoubis/core/data_controller.rb +0 -28
  38. data/app/controllers/anoubis/sso/client/data/actions.rb +0 -5
  39. data/app/controllers/anoubis/sso/client/data/callbacks.rb +0 -5
  40. data/app/controllers/anoubis/sso/client/data/convert.rb +0 -5
  41. data/app/controllers/anoubis/sso/client/data/defaults.rb +0 -5
  42. data/app/controllers/anoubis/sso/client/data/get.rb +0 -5
  43. data/app/controllers/anoubis/sso/client/data/load.rb +0 -26
  44. data/app/controllers/anoubis/sso/client/data/set.rb +0 -5
  45. data/app/controllers/anoubis/sso/client/data/setup.rb +0 -5
  46. data/app/controllers/anoubis/sso/client/data_controller.rb +0 -21
  47. data/app/controllers/anoubis/tenant/data/actions.rb +0 -11
  48. data/app/controllers/anoubis/tenant/data/callbacks.rb +0 -11
  49. data/app/controllers/anoubis/tenant/data/convert.rb +0 -11
  50. data/app/controllers/anoubis/tenant/data/defaults.rb +0 -11
  51. data/app/controllers/anoubis/tenant/data/get.rb +0 -11
  52. data/app/controllers/anoubis/tenant/data/load.rb +0 -52
  53. data/app/controllers/anoubis/tenant/data/set.rb +0 -11
  54. data/app/controllers/anoubis/tenant/data/setup.rb +0 -11
  55. data/app/controllers/anoubis/tenant/data_controller.rb +0 -28
  56. data/app/controllers/anoubis/tenants_controller.rb +0 -7
  57. data/app/controllers/anoubis/users_controller.rb +0 -7
  58. data/app/mailers/anoubis/application_mailer.rb +0 -8
@@ -0,0 +1,66 @@
1
+ module Anoubis
2
+ module Data
3
+ ##
4
+ # Module presents all callbacks called in actions.
5
+ module Callbacks
6
+ ##
7
+ # Fires after data was received from server and placed in {Anoubis::Output::Data#data self.output.data} array.
8
+ # It's rewrote for change data before output.
9
+ def after_get_table_data
10
+
11
+ end
12
+
13
+ ##
14
+ # Fires before data will be verified and converted.
15
+ # @param data [Hash] Data for update
16
+ # @return [Hash] Processed data. If returned nil then update is terminated.
17
+ def before_update_data(data)
18
+ data
19
+ end
20
+
21
+ ##
22
+ # Fires after data was was updated on the server and placed in {Anoubis::Output::Data#data self.output.data} array.
23
+ # It's rewrote for change data before output.
24
+ def after_update_data
25
+
26
+ end
27
+
28
+ ##
29
+ # Fires after data was was created in {Anoubis::Output::Data#data self.output.data} array and before it saved to server.
30
+ # It's rewrote for change data before output.
31
+ # @param data [Hash] Data for create
32
+ # @return [Hash] Processed data. If returned nil then update is terminated.
33
+ def before_create_data(data)
34
+ data
35
+ end
36
+
37
+ ##
38
+ # Fires after data was was created on the server and placed in {Anoubis::Output::Data#data self.output.data} array.
39
+ # It's rewrote for change data before output.
40
+ def after_create_data
41
+
42
+ end
43
+
44
+ ##
45
+ # Fires right before output data to screen
46
+ def before_output
47
+
48
+ end
49
+
50
+ ##
51
+ # Fires when data output to json value
52
+ def around_output(data)
53
+ data
54
+ end
55
+
56
+ ##
57
+ # Fires when data is destroyed
58
+ def destroy_data
59
+ if !self.etc.data.data.destroy
60
+ self.output.errors.concat self.etc.data.data.errors.full_messages
61
+ self.output.result = -4
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,422 @@
1
+ module Anoubis
2
+ module Data
3
+ ##
4
+ # Data conversion moule between database and human representation
5
+ module Convert
6
+ ##
7
+ # Format a number with grouped thousands
8
+ # @param number [Float] The number being formatted.
9
+ # @param precision [Integer] Sets the number of decimal points.
10
+ # @param point [Char] Sets the separator for the decimal point.
11
+ # @param separator [Char] Sets the thousands separator.
12
+ # @return [String] A formatted version of number.
13
+ def number_format(number, precision = 2, point = ',', separator = '')
14
+ val = sprintf('%.'+precision.to_s+'f', number.round(precision)).to_s
15
+ if separator != '' && number >= 1000
16
+ whole_part, decimal_part = val.split('.')
17
+ val = [whole_part.gsub(/(\d)(?=\d{3}+$)/, '\1'+separator), decimal_part].compact.join(point)
18
+ else
19
+ val = val.gsub('.', point)
20
+ end
21
+ val
22
+ end
23
+
24
+
25
+ ##
26
+ # @!group Block of conversion database value into human view format
27
+
28
+ ##
29
+ # Convert value from database to view format according by defining field type and {Anoubis::Etc::Base#action action}
30
+ # @param key [Symbol] field's identifier in {Anoubis::Etc::Data#fields self.etc.data.fields} structure
31
+ # @param value [String] value from database
32
+ def convert_db_to_view_value(key, value)
33
+ field = self.etc.data.fields[key]
34
+ return { key => value } if !field.type
35
+ proc = format('convert_db_to_view_value_%s', field.type)
36
+ result = self.send proc, key, value
37
+ result
38
+ end
39
+
40
+ ##
41
+ # Convert value from database to view format for 'string' type
42
+ # @param key [Symbol] field's identifier in {Anoubis::Etc::Data#fields self.etc.data.fields} structure
43
+ # @param value [String] value from database
44
+ def convert_db_to_view_value_string(key, value)
45
+ return { key => '' } if !value
46
+ return { key => value }
47
+ end
48
+
49
+ ##
50
+ # Convert value from database to view format for 'boolean' type
51
+ # @param key [Symbol] field's identifier in {Anoubis::Etc::Data#fields self.etc.data.fields} structure
52
+ # @param value [Boolean] value from database
53
+ def convert_db_to_view_value_boolean(key, value)
54
+ return { key => '' } if !value
55
+ return { key => value }
56
+ end
57
+
58
+ ##
59
+ # Convert value from database to view format for 'integer' type
60
+ # @param key [Symbol] field's identifier in {Anoubis::Etc::Data#fields self.etc.data.fields} structure
61
+ # @param value [String] value from database
62
+ def convert_db_to_view_value_number(key, value)
63
+ return { key => self.etc.data.fields[key].error_text } if !value
64
+ return { key => value.to_s.to_i } if self.etc.data.fields[key].precision == 0
65
+ return { key => format('%.' + self.etc.data.fields[key].precision.to_s + 'f', value) }
66
+ end
67
+
68
+ ##
69
+ # Convert value from database to view format for 'text' type
70
+ # @param key [Symbol] field's identifier in {Anoubis::Etc::Data#fields self.etc.data.fields} structure
71
+ # @param value [String] value from database
72
+ def convert_db_to_view_value_text(key, value)
73
+ return { key => '' } if !value
74
+ return { key => value }
75
+ end
76
+
77
+ ##
78
+ # Convert value from database to view format for 'html' type
79
+ # @param key [Symbol] field's identifier in {Anoubis::Etc::Data#fields self.etc.data.fields} structure
80
+ # @param value [String] value from database
81
+ def convert_db_to_view_value_html(key, value)
82
+ return { key => '' } if !value
83
+ return { key => value }
84
+ end
85
+
86
+ ##
87
+ # Convert value from database to table format for 'listbox' type
88
+ # @param key [Symbol] field's identifier in {Anoubis::Etc::Data#fields self.etc.data.fields} structure
89
+ # @param value [String] value from database
90
+ def convert_db_to_view_value_listbox(key, value)
91
+ field = self.etc.data.fields[key]
92
+ new_value = ''
93
+ if field.options
94
+ if field.format == 'single'
95
+ new_value = field.options.list[value.to_s.to_sym] if field.options.list
96
+ else
97
+ new_value = []
98
+ if value
99
+ if field.options.list
100
+ value.each do |key|
101
+ new_value.push field.options.list[key.to_s.to_sym]
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
107
+ case self.etc.action
108
+ when 'index', 'show', 'export'
109
+ if field.format == 'single'
110
+ return { key => new_value, format('%s_raw', key).to_sym => value }
111
+ else
112
+ return { key => new_value.join(', '), format('%s_raw', key).to_sym => new_value }
113
+ end
114
+ when 'new', 'edit'
115
+ if field.format == 'single'
116
+ return { key => value.to_s, format('%s_view', key).to_sym => new_value }
117
+ else
118
+ return { key => value, format('%s_view', key).to_sym => new_value.join(', ') }
119
+ end
120
+ else
121
+ if field.format == 'single'
122
+ return { key => value.to_s, format('%s_view', key).to_sym => new_value }
123
+ else
124
+ return { key => value, format('%s_view', key).to_sym => new_value.join(', ') }
125
+ end
126
+ end
127
+ end
128
+
129
+ ##
130
+ # Convert value from database to view format for 'key' type
131
+ # @param key [Symbol] field's identifier in {Anoubis::Etc::Data#fields self.etc.data.fields} structure
132
+ # @param value [String] value from database
133
+ def convert_db_to_view_value_key(key, value)
134
+ return { key => '' } if !value
135
+ return { key => value }
136
+ end
137
+
138
+ ##
139
+ # Convert value from database to table view for datetime type
140
+ def convert_db_to_view_value_datetime(key, value)
141
+ field = self.etc.data.fields[key]
142
+ #puts key
143
+ #puts value.class
144
+ if (value.class == Date) || (value.class == ActiveSupport::TimeWithZone)
145
+ begin
146
+ new_value = convert_datetime_to_string value, field.format
147
+
148
+ if %w[month date].include? field.format
149
+ raw_value = value.year.to_s + '-' + ('%02d' % value.month) + '-' + ('%02d' % value.day)
150
+ else
151
+ #raw_value = value.year.to_s + '-' + ('%02d' % value.month) + '-' + ('%02d' % value.day) + ' ' + ('%02d' % value.hour) + ':' + ('%02d' % value.min)
152
+ raw_value = value.iso8601(2)[0..18]
153
+ end
154
+ rescue StandardError => e
155
+ #puts e
156
+ new_value = field.error_text
157
+ end
158
+ else
159
+ new_value = '';
160
+ end
161
+
162
+ case self.etc.action
163
+ when 'new', 'edit'
164
+ return { key => raw_value, format('%s_view', key).to_sym => new_value }
165
+ end
166
+ return { key => new_value, format('%s_raw', key).to_sym => value }
167
+ end
168
+
169
+ ##
170
+ # Convert value from database to view format for 'hash' type
171
+ # @param key [Symbol] field's identifier in {Anoubis::Etc::Data#fields self.etc.data.fields} structure
172
+ # @param value [String] value from database
173
+ # @return [Hash] returns text representation of database value
174
+ def convert_db_to_view_value_hash(key, value)
175
+ return { key => '' } if !value
176
+ return { key => value }
177
+ end
178
+
179
+ ##
180
+ # Converts DateTime representation to string value
181
+ # @param value [DateTime] date and time
182
+ # @param format [String] convert representation ('month' - return only month and year, 'date' - returns only date, 'datetime' - returns date and time)
183
+ # @return Returns date and time representation string
184
+ def convert_datetime_to_string(value, format)
185
+ return I18n.t('anubis.months.main')[value.month-1]+' '+value.year.to_s if format == 'month'
186
+ return value.day.to_s+' '+ I18n.t('anubis.months.second')[value.month-1]+' '+value.year.to_s if format == 'date'
187
+ return value.day.to_s+' '+ I18n.t('anubis.months.second')[value.month-1]+' '+value.year.to_s+', '+value.hour.to_s+':'+('%02d' % value.min) if format == 'datetime'
188
+
189
+ value.day.to_s+' '+ I18n.t('anubis.months.second')[value.month-1]+' '+value.year.to_s+', '+value.hour.to_s+':'+('%02d' % value.min)+':'+('%02d' % value.sec)
190
+ end
191
+
192
+
193
+
194
+
195
+
196
+
197
+
198
+
199
+
200
+
201
+
202
+
203
+
204
+
205
+ ##
206
+ # Convert value from database to table view for text type
207
+ def convert_db_to_table_value_text1(key, field, value)
208
+ return { key => '', ('raw_'+key.to_s).to_sym => '' } if !value
209
+ new_value = ERB::Util.html_escape(value).to_s.gsub(/(?:\n\r?|\r\n?)/, '<br/>')
210
+ return { key => new_value, ('raw_'+key.to_s).to_sym => value }
211
+ end
212
+
213
+
214
+
215
+
216
+
217
+ ##
218
+ # Convert value from database to table view for string type
219
+ def convert_db_to_table_value_integer1(key, field, value)
220
+ return { key => '' } if !value
221
+ return { key => value }
222
+ end
223
+
224
+
225
+
226
+
227
+ ##
228
+ # Convert value from database to table view for longlistbox type
229
+ def convert_db_to_table_value_longlistbox1(key, field, value)
230
+ return { key => '' } if !value
231
+ return { key => value }
232
+ end
233
+
234
+ ##
235
+ # Convert value from database to table view for datetime type
236
+ def convert_db_to_table_value_datetime1(key, field, value)
237
+ begin
238
+ value = case field[:format]
239
+ when 'month' then I18n.t('months.main')[value.month-1]+' '+value.year.to_s
240
+ when 'date' then value.day.to_s+' '+ I18n.t('months.second')[value.month-1]+' '+value.year.to_s
241
+ when 'datetime' then value.day.to_s+' '+ I18n.t('months.second')[value.month-1]+' '+value.year.to_s+', '+value.hour.to_s+':'+('%02d' % value.min)
242
+ else value.day.to_s+' '+ I18n.t('months.second')[value.month-1]+' '+value.year.to_s+', '+value.hour.to_s+':'+('%02d' % value.min)+':'+('%02d' % value.sec)
243
+ end
244
+ rescue
245
+ value = I18n.t('incorrect_field_format')
246
+ end
247
+ return { key => value }
248
+ end
249
+
250
+ ##
251
+ # Convert value from database to table view for float type
252
+ # @param key [Symbol] key of table field
253
+ # @param field [Tims::Etc::Table#fields] set of options of field by <b>key</b>
254
+ # @param value [Float] value from database before processing
255
+ # @return [Hash] return resulting value at format <b>{ key: processed_value, 'raw_'+key: value }</b>
256
+ def convert_db_to_table_value_float1(key, field, value)
257
+ return { key => number_format(value, field[:precision], field[:point], field[:separator]), ('raw_'+key.to_s).to_sym => value}
258
+ end
259
+
260
+ ##
261
+ # Convert value from database to edit form for datetime type
262
+ # @param key [Symbol] field's identifier
263
+ # @param field [Hash] field's options
264
+ # @param value [Any] value from database before processing
265
+ # @return [Hash] resulting value in format <b>{ key: processed_value }</b>
266
+ def convert_db_to_table_value_datetime(key, field, value)
267
+ begin
268
+ value = case field[:format]
269
+ when 'month' then I18n.t('months.main')[value.month-1]+' '+value.year.to_s
270
+ when 'date' then value.day.to_s+' '+ I18n.t('months.second')[value.month-1]+' '+value.year.to_s
271
+ when 'datetime' then value.day.to_s+' '+ I18n.t('months.second')[value.month-1]+' '+value.year.to_s+', '+value.hour.to_s+':'+('%02d' % value.min)
272
+ else value.day.to_s+' '+ I18n.t('months.second')[value.month-1]+' '+value.year.to_s+', '+value.hour.to_s+':'+('%02d' % value.min)+':'+('%02d' % value.sec)
273
+ end
274
+ rescue
275
+ value = I18n.t('incorrect_field_format')
276
+ end
277
+ return { key => value }
278
+ end
279
+
280
+ ##
281
+ # Convert value from database to edit form for float type
282
+ # @param key [Symbol] field's identifier
283
+ # @param field [Anoubis::Etc::Data#fields] field's options
284
+ # @param value [Float] value from database before processing
285
+ # @return [Hash] return resulting value at format <b>{ key+'_view': processed_value, key: value }</b>
286
+ def convert_db_to_table_value_float(key, field, value)
287
+ return { (key.to_s+'_view').to_sym => number_format(value, field[:precision], field[:point], field[:separator]), key => value}
288
+ end
289
+ # @!endgroup
290
+
291
+
292
+ ##
293
+ # @!group Block of conversion human view values to database format
294
+
295
+ ##
296
+ # Converts inputted value to database format.
297
+ # Field type is got from {Anoubis::Etc::Data#fields self.etc.data.fields} according by key.
298
+ # Resulting data is placed into {Anoubis::Etc::Data#data self.etc.data.data} attribute according by key.
299
+ # Errors are placed in {Anoubis::Output::Update#errors self.output.errors} array according by key.
300
+ # @param key [Symbol] field's identifier in {Anoubis::Etc::Data#fields self.etc.data.fields} structure
301
+ # @param value [String] value from user input
302
+ def convert_view_to_db_value(key, value)
303
+ field = self.etc.data.fields[key]
304
+ return { key => value } unless field
305
+ return { key => value } unless field.type
306
+ proc = format('convert_view_to_db_value_%s', field.type)
307
+ self.send proc, key, value
308
+ end
309
+
310
+ ##
311
+ # Converts inputted value to database format for {Anoubis::Etc::Field#type 'string' field type}.
312
+ # @param key [Symbol] field's identifier in {Anoubis::Etc::Data#fields self.etc.data.fields} structure
313
+ # @param value [String] inputted value
314
+ def convert_view_to_db_value_string(key, value)
315
+ proc = format('self.etc.data.data.%s = value', key)
316
+ #self.etc.data.data[key] = value
317
+ eval proc
318
+ end
319
+
320
+ ##
321
+ # Converts inputted value to database format for {Anoubis::Etc::Field#type 'boolean' field type}.
322
+ # @param key [Symbol] field's identifier in {Anoubis::Etc::Data#fields self.etc.data.fields} structure
323
+ # @param value [Boolean] inputted value
324
+ def convert_view_to_db_value_boolean(key, value)
325
+ proc = format('self.etc.data.data.%s = value', key)
326
+ #self.etc.data.data[key] = value
327
+ eval proc
328
+ end
329
+
330
+ ##
331
+ # Converts inputted value to database format for {Anoubis::Etc::Field#type 'number' field type}.
332
+ # @param key [Symbol] field's identifier in {Anoubis::Etc::Data#fields self.etc.data.fields} structure
333
+ # @param value [String] inputted value
334
+ def convert_view_to_db_value_number(key, value)
335
+ field = self.etc.data.fields[key]
336
+ if field.precision == 0
337
+ value = value.to_s.to_i
338
+ else
339
+ value = value.to_s.to_f
340
+ end
341
+ proc = format('self.etc.data.data.%s = value', key)
342
+ #self.etc.data.data[key] = value
343
+ eval proc
344
+ end
345
+
346
+ ##
347
+ # Converts inputted value to database format for {Anoubis::Etc::Field#type 'text' field type}.
348
+ # @param key [Symbol] field's identifier in {Anoubis::Etc::Data#fields self.etc.data.fields} structure
349
+ # @param value [String] inputted value
350
+ def convert_view_to_db_value_text(key, value)
351
+ proc = format('self.etc.data.data.%s = value', key)
352
+ #self.etc.data.data[key] = value
353
+ eval proc
354
+ end
355
+
356
+ ##
357
+ # Converts inputted value to database format for {Anoubis::Etc::Field#type 'html' field type}.
358
+ # @param key [Symbol] field's identifier in {Anoubis::Etc::Data#fields self.etc.data.fields} structure
359
+ # @param value [String] inputted value
360
+ def convert_view_to_db_value_html(key, value)
361
+ proc = format('self.etc.data.data.%s = value', key)
362
+ #self.etc.data.data[key] = value
363
+ eval proc
364
+ end
365
+
366
+ ##
367
+ # Converts inputted value to database format for {Anoubis::Etc::Field#type 'listbox' field type}
368
+ # for {Anoubis::Data::Actions#create 'create'} action
369
+ # @param key [Symbol] field's identifier in {Anoubis::Etc::Data#fields self.etc.data.fields} structure
370
+ # @param value [String] inputted value
371
+ def convert_view_to_db_value_listbox(key, value)
372
+ field = self.etc.data.fields[key]
373
+ begin
374
+ proc = format('self.etc.data.data.%s = value', field.field)
375
+ #self.etc.data.data[field.field] = value
376
+ eval proc
377
+ rescue
378
+ self.etc.data.data[field.field] = nil
379
+ end
380
+ end
381
+
382
+ ##
383
+ # Converts inputted value to database format for {Anoubis::Etc::Field#type 'key' field type}
384
+ # for {Anoubis::Data::Actions#create 'create'} action
385
+ # @param key [Symbol] field's identifier in {Anoubis::Etc::Data#fields self.etc.data.fields} structure
386
+ # @param value [String] inputted value
387
+ def convert_view_to_db_value_key(key, value)
388
+ field = self.etc.data.fields[key]
389
+ where = {}
390
+ where[field.model.title.to_s.to_sym] = value
391
+ value = field.model.model.where(where).first
392
+ proc = format('self.etc.data.data.%s = value', field.key)
393
+ eval(proc)
394
+ #begin
395
+ # self.etc.data.data[key] = value
396
+ # rescue
397
+ # self.etc.data.data[key] = nil
398
+ # end
399
+ end
400
+
401
+ ##
402
+ # Converts inputted value to database format for {Anoubis::Etc::Field#type 'datetime' field type}.
403
+ # @param key [Symbol] field's identifier in {Anoubis::Etc::Data#fields self.etc.data.fields} structure
404
+ # @param value [String] inputted value
405
+ def convert_view_to_db_value_datetime(key, value)
406
+ zone = ActiveSupport::TimeZone[self.current_user.timezone]
407
+ offset = if zone.utc_offset/3600 < 0 then (zone.utc_offset/3600).to_s else '+'+(zone.utc_offset/3600).to_s end
408
+ #puts 'convert_view_to_db_value_datetime'
409
+ #puts value
410
+ value = Time.zone.parse value
411
+ #puts value
412
+ #puts zone
413
+ #puts offset
414
+ #puts value.utc_offset if value
415
+ proc = format('self.etc.data.data.%s = value', key)
416
+ #self.etc.data.data[key] = value
417
+ eval proc
418
+ end
419
+ # @!endgroup
420
+ end
421
+ end
422
+ end