chupakabra_tools 0.0.9 → 0.0.14

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile.lock CHANGED
@@ -1,11 +1,13 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- chupakabra_tools (0.0.8)
4
+ chupakabra_tools (0.0.14)
5
5
  active_enum
6
6
  activerecord
7
7
  activesupport
8
+ nokogiri
8
9
  russian
10
+ will_paginate
9
11
 
10
12
  GEM
11
13
  remote: https://rubygems.org/
@@ -26,10 +28,14 @@ GEM
26
28
  arel (3.0.2)
27
29
  builder (3.0.4)
28
30
  i18n (0.6.4)
31
+ mini_portile (0.5.0)
29
32
  multi_json (1.7.7)
33
+ nokogiri (1.6.0)
34
+ mini_portile (~> 0.5.0)
30
35
  russian (0.6.0)
31
36
  i18n (>= 0.5.0)
32
37
  tzinfo (0.3.37)
38
+ will_paginate (3.0.4)
33
39
 
34
40
  PLATFORMS
35
41
  ruby
@@ -1,11 +1,11 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  lib = File.expand_path('../lib', __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'chupakabra_tools/version'
4
+
5
5
 
6
6
  Gem::Specification.new do |gem|
7
7
  gem.name = "chupakabra_tools"
8
- gem.version = ChupakabraTools::VERSION
8
+ gem.version = '0.0.14'
9
9
  gem.authors = ["Mitrofanov Dmitry"]
10
10
  gem.email = ["mdima@it-guru.biz"]
11
11
  gem.description = %q{Chupakbara Tools Set for Easy Life}
@@ -21,5 +21,7 @@ Gem::Specification.new do |gem|
21
21
  gem.add_dependency "activerecord"
22
22
  gem.add_dependency "active_enum"
23
23
  gem.add_dependency "russian"
24
+ gem.add_dependency "nokogiri"
25
+ gem.add_dependency "will_paginate"
24
26
 
25
27
  end
@@ -1,15 +1,23 @@
1
- require "chupakabra_tools/version"
2
-
3
1
  require "chupakabra_tools/time_interval"
4
2
  require "chupakabra_tools/predefined_time_intervals"
5
3
  require "chupakabra_tools/security"
6
4
  require "chupakabra_tools/http"
7
- require "chupakabra_tools/validattions"
5
+ require "chupakabra_tools/validations"
8
6
  require "chupakabra_tools/number_as_text"
9
7
  require "chupakabra_tools/active_record"
10
8
  require "chupakabra_tools/convert"
11
9
  require "chupakabra_tools/transliterator"
12
10
  require "chupakabra_tools/logging"
11
+ require "chupakabra_tools/class_helper"
12
+ require "chupakabra_tools/data_type"
13
+ require "chupakabra_tools/json_status"
14
+ require 'chupakabra_tools/set_management_result'
15
+ require "chupakabra_tools/active_enum_extended"
16
+ require "chupakabra_tools/internet_file_process_status"
17
+ require "chupakabra_tools/deletion_status"
18
+
19
+ require "chupakabra_tools/xml/xml_parser"
20
+
13
21
 
14
22
 
15
23
 
@@ -0,0 +1,53 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require "active_enum"
3
+
4
+ class ChupakabraTools::ActiveEnumExtended < ActiveEnum::Base
5
+
6
+
7
+ def self.id_by_tag(tag)
8
+ self.all.each do |item|
9
+ return item[0] if item[2][:tag] == tag
10
+ end
11
+ nil
12
+ end
13
+
14
+ def self.tag_by_id(id)
15
+ self.all.each do |item|
16
+ return item[2][:tag] if item[0] == id
17
+ end
18
+ nil
19
+ end
20
+
21
+ def self.all_tags
22
+ self.all.map{ |item| item[2][:tag] }
23
+ end
24
+
25
+ def self.all_ids
26
+ self.all.map{ |item| item[0] }
27
+ end
28
+
29
+ def self.for_select
30
+ self.all.map{ |item| [item[1], item[2][:tag]] }
31
+ end
32
+
33
+ def self.to_hash(data = nil)
34
+ unless data
35
+ return self.all.map{ |item| {id: item[0], name: item[1], tag: item[2][:tag]} }
36
+ end
37
+ if data.is_a?(String)
38
+ self.all.each do |item|
39
+ if item[2][:tag] == data
40
+ return {id: item[0], name: item[1], tag: item[2][:tag]}
41
+ end
42
+ end
43
+ end
44
+ if data.is_a?(Integer)
45
+ self.all.each do |item|
46
+ if item[0] == data
47
+ return {id: item[0], name: item[1], tag: item[2][:tag]}
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+
@@ -0,0 +1,241 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ module ChupakabraTools::ClassHelper
4
+ def self.class_to_i18n(class_name)
5
+ unless (class_name && class_name.is_a?(String) || class_name.class.to_s.downcase == "class")
6
+ raise class_name if class_name
7
+ raise "class_name is null"
8
+ end
9
+ class_name.to_s.underscore.gsub('/', '.')
10
+ end
11
+
12
+ def self.controller_to_i18n(controller)
13
+ controller_class = nil
14
+ unless controller
15
+ raise "supplied controller is null"
16
+ end
17
+
18
+ begin
19
+ if controller.is_a?(Class) && controller < ApplicationController
20
+ controller_class = controller
21
+ elsif controller.class < ApplicationController
22
+ controller_class = controller.class
23
+ end
24
+ rescue
25
+ end
26
+
27
+ if controller_class
28
+ i18n_string = ::ChupakabraTools::ClassHelper.class_to_i18n(controller_class)
29
+ i18n_string.gsub!("_controller", "") if i18n_string
30
+ i18n_string
31
+ end
32
+ end
33
+
34
+ def self.controller_underscore(controller)
35
+ if controller && controller.respond_to?(:controller_name)
36
+ underscore_string = controller.controller_name.to_s.underscore
37
+ underscore_string.gsub!("_controller", "")
38
+ underscore_string
39
+ end
40
+ end
41
+
42
+ def self.controller_full_path_underscore(controller)
43
+ if controller
44
+ underscore_string = controller.to_s.underscore
45
+ underscore_string.gsub!("_controller", "")
46
+ "/#{controller.to_s.underscore.gsub!("_controller", "")}"
47
+ end
48
+ end
49
+
50
+ def self.has_action(klass, action)
51
+ klass && action && klass.respond_to?(action)
52
+ end
53
+
54
+ def self.has_action?(klass, action)
55
+ klass && action && klass.respond_to?(action)
56
+ end
57
+
58
+ def self.entry_has_db_attribute(entry, attribute)
59
+ if entry && attribute
60
+
61
+ end
62
+ false
63
+ end
64
+
65
+
66
+ def self.class_is_subclass_of(parent, child)
67
+ if parent.nil? || child.nil?
68
+ return false
69
+ end
70
+ child < parent
71
+ end
72
+
73
+ def self.class_belongs_to_module(modul, klass)
74
+ parent_module = klass.parent
75
+ while (true)
76
+ if parent_module == modul
77
+ return true
78
+ end
79
+ parent_module = parent_module.parent
80
+ break if parent_module == Object
81
+ end
82
+ false
83
+ end
84
+
85
+
86
+ def self.load_all_active_record_models
87
+ librbfiles = File.join("#{Rails.root}/app/models/", "**", "*.rb")
88
+ results = []
89
+
90
+ Dir.glob(librbfiles).each do |file|
91
+ begin
92
+ klass_string = file.gsub("#{Rails.root}/app/models/", "")[0..-4].camelize
93
+ klass = eval(klass_string)
94
+ instance = klass.new
95
+
96
+ results.push klass if instance.is_a?(ActiveRecord::Base)
97
+ rescue => ex
98
+
99
+ end
100
+ end
101
+ results
102
+ end
103
+
104
+ def self.property_required?(model, property)
105
+ if model && property
106
+ validators = model.class.validators_on(property)
107
+ validators.each do |v|
108
+ if v.is_a?(ActiveModel::Validations::PresenceValidator)
109
+ return true
110
+ end
111
+ end
112
+ end
113
+ false
114
+ end
115
+
116
+
117
+ def self.get_class_hierarchy_for_class(klass)
118
+ classes_2_inspect = []
119
+ if klass
120
+ classes_2_inspect.push(klass)
121
+ sc = klass
122
+ while (true) do
123
+ sc = sc.superclass
124
+ classes_2_inspect.push(sc)
125
+ if sc == ApplicationController
126
+ break
127
+ end
128
+ end
129
+ end
130
+ classes_2_inspect
131
+ end
132
+
133
+ def self.get_obligatory_filters_for_controller_class(klass)
134
+
135
+ found_obligatory_filters=[]
136
+ ::ChupakabraTools::ClassHelper.get_class_hierarchy_for_class(klass).each do |cl|
137
+ if cl.respond_to?(:obligatory_filters_set)
138
+ cl.obligatory_filters_set.each do |filter|
139
+ found_obligatory_filters.push(filter)
140
+ end
141
+ end
142
+ end
143
+ found_obligatory_filters
144
+ end
145
+
146
+
147
+ def self.test_app_classes_for_errors
148
+ results = []
149
+
150
+
151
+ Dir.glob(File.join("#{Rails.root}/app/models/", "**", "*.rb")).each do |file|
152
+ begin
153
+ klass_string = file.gsub("#{Rails.root}/app/models/", "")[0..-4].camelize
154
+ klass = eval(klass_string)
155
+ instance = klass.new if klass < ActiveRecord::Base && !klass.abstract_class == true
156
+ #
157
+ #results.push klass if instance.is_a?(ActiveRecord::Base)
158
+ rescue Exception => e
159
+ results << "**************************************************************"
160
+ results << "ERROR: #{e}"
161
+ results << "FILE: #{file}"
162
+ results << e.to_s
163
+ results << "**************************************************************"
164
+ end
165
+ end
166
+
167
+ Dir.glob(File.join("#{Rails.root}/app/helpers/", "**", "*.rb")).each do |file|
168
+ begin
169
+ klass_string = file.gsub("#{Rails.root}/app/helpers/", "")[0..-4].camelize
170
+ klass = eval(klass_string)
171
+ instance = klass.new if klass < ActiveRecord::Base && !klass.abstract_class == true
172
+ #
173
+ #results.push klass if instance.is_a?(ActiveRecord::Base)
174
+ rescue Exception => e
175
+ results << "**************************************************************"
176
+ results << "ERROR: #{e}"
177
+ results << "FILE: #{file}"
178
+ results << e.to_s
179
+ results << "**************************************************************"
180
+ end
181
+ end
182
+
183
+
184
+ Dir.glob(File.join("#{Rails.root}/app/controllers/", "**", "*.rb")).each do |file|
185
+ begin
186
+ klass_string = file.gsub("#{Rails.root}/app/controllers/", "")[0..-4].camelize
187
+ klass = eval(klass_string)
188
+ instance = klass.new if klass < ActiveRecord::Base && !klass.abstract_class == true
189
+ #
190
+ #results.push klass if instance.is_a?(ActiveRecord::Base)
191
+ rescue Exception => e
192
+ results << "**************************************************************"
193
+ results << "ERROR: #{e}"
194
+ results << "FILE: #{file}"
195
+ results << e.to_s
196
+ results << "**************************************************************"
197
+ end
198
+ end
199
+
200
+
201
+ Rails.logger.info(results)
202
+ results
203
+ end
204
+
205
+
206
+ def self.test_gem_classes_for_errors
207
+ results = []
208
+ Dir.glob(File.join("#{Rails.root}/lib/", "**", "*.rb")).each do |file|
209
+ begin
210
+ klass_string = file.gsub("#{Rails.root}/app/models/", "")[0..-4].camelize
211
+ klass = eval(klass_string)
212
+ instance = klass.new if klass < ActiveRecord::Base && !klass.abstract_class == true
213
+ #
214
+ #results.push klass if instance.is_a?(ActiveRecord::Base)
215
+ rescue Exception => e
216
+ results << "**************************************************************"
217
+ results << "ERROR: #{e}"
218
+ results << "FILE: #{file}"
219
+ results << e.to_s
220
+ results << "**************************************************************"
221
+ end
222
+ end
223
+ Rails.logger.info(results)
224
+ results
225
+ end
226
+
227
+ def self.grep(data, template)
228
+ grep_values = []
229
+
230
+ if data.is_a?(Array)
231
+ data.each do |dt|
232
+ value = dt.to_s
233
+ if value.index(template)
234
+ grep_values.push(value)
235
+ end
236
+ end
237
+ end
238
+ grep_values
239
+ end
240
+
241
+ end
@@ -0,0 +1,12 @@
1
+ require 'chupakabra_tools/active_enum_extended'
2
+
3
+ class ChupakabraTools::DataType < ::ChupakabraTools::ActiveEnumExtended
4
+ value id: 1, name: I18n.t('chupakabra_tools.data_types.1'), tag: 'integer'
5
+ value id: 2, name: I18n.t('chupakabra_tools.data_types.2'), tag: 'string'
6
+ value id: 3, name: I18n.t('chupakabra_tools.data_types.3'), tag: 'boolean'
7
+ value id: 4, name: I18n.t('chupakabra_tools.data_types.4'), tag: 'text'
8
+ value id: 5, name: I18n.t('chupakabra_tools.data_types.5'), tag: 'decimal'
9
+ value id: 6, name: I18n.t('chupakabra_tools.data_types.6'), tag: 'date'
10
+ value id: 7, name: I18n.t('chupakabra_tools.data_types.7'), tag: 'datetime'
11
+
12
+ end
@@ -0,0 +1,6 @@
1
+ # -*- encoding : utf-8 -*-
2
+ class ChupakabraTools::DeletionStatus < ::ChupakabraTools::ActiveEnumExtended
3
+ value id: 1, name: I18n.t('chupakabra_tools.deletion_statuses.1'), tag: 'actual'
4
+ value id: 2, name: I18n.t('chupakabra_tools.deletion_statuses.2'), tag: 'deleted'
5
+ value id: 3, name: I18n.t('chupakabra_tools.deletion_statuses.3'), tag: 'purged'
6
+ end
@@ -0,0 +1,8 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ class ChupakabraTools::EducationLevel < ::SharedZone::ActiveEnumExtended
4
+ value id: 1, name: I18n.t('chupakabra_tools.education_level.1'), tag: 'elementary_school'
5
+ value id: 2, name: I18n.t('chupakabra_tools.education_level.2'), tag: 'high_school'
6
+ value id: 3, name: I18n.t('chupakabra_tools.education_level.3'), tag: 'special'
7
+ value id: 4, name: I18n.t('chupakabra_tools.education_level.4'), tag: 'college'
8
+ end
@@ -0,0 +1,9 @@
1
+ class ChupakabraTools::InternetFileProcessStatus < ::ChupakabraTools::ActiveEnumExtended
2
+ value id: 1, name: I18n.t('chupakabra_tools.internet_file_process_status.1'), tag: 'not_processed'
3
+ value id: 2, name: I18n.t('chupakabra_tools.internet_file_process_status.2'), tag: 'downloading'
4
+ value id: 3, name: I18n.t('chupakabra_tools.internet_file_process_status.3'), tag: 'download_error'
5
+ value id: 4, name: I18n.t('chupakabra_tools.internet_file_process_status.4'), tag: 'downloaded'
6
+ value id: 5, name: I18n.t('chupakabra_tools.internet_file_process_status.5'), tag: 'parsing'
7
+ value id: 6, name: I18n.t('chupakabra_tools.internet_file_process_status.6'), tag: 'parse_error'
8
+ value id: 7, name: I18n.t('chupakabra_tools.internet_file_process_status.7'), tag: 'parsed'
9
+ end
@@ -0,0 +1,11 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'chupakabra_tools/active_enum_extended'
3
+
4
+ class ChupakabraTools::JsonStatus < ::ChupakabraTools::ActiveEnumExtended
5
+ value id: 1, name: I18n.t('chupakabra_tools.json_statuses.1'), tag: 'need_authentication'
6
+ value id: 2, name: I18n.t('chupakabra_tools.json_statuses.2'), tag: 'ok'
7
+ value id: 3, name: I18n.t('chupakabra_tools.json_statuses.3'), tag: 'redirected'
8
+ value id: 4, name: I18n.t('chupakabra_tools.json_statuses.4'), tag: 'access_denied'
9
+ value id: 5, name: I18n.t('chupakabra_tools.json_statuses.5'), tag: 'error'
10
+ value id: 6, name: I18n.t('chupakabra_tools.json_statuses.6'), tag: 'not_found'
11
+ end
@@ -2,22 +2,22 @@ require "chupakabra_tools/time_interval"
2
2
  require "active_enum"
3
3
 
4
4
  class ChupakabraTools::PredefinedTimeIntervals < ActiveEnum::Base
5
- value id: 1, name: I18n.t('chupakabra.time_intervals.this_hour'), seo_tag: 'this_hour', time_line: 'present', scale: 'hour', value: ChupakabraTools::TimeInterval.this_hour
6
- value id: 2, name: I18n.t('chupakabra.time_intervals.last_hour'), seo_tag: 'last_hour', time_line: 'past', scale: 'hour', value: ChupakabraTools::TimeInterval.previous_hour
7
- value id: 3, name: I18n.t('chupakabra.time_intervals.next_hour'), seo_tag: 'next_hour', time_line: 'future', scale: 'hour', value: ChupakabraTools::TimeInterval.next_hour
8
- value id: 4, name: I18n.t('chupakabra.time_intervals.today'), seo_tag: 'today', time_line: 'present', scale: 'day', value: ChupakabraTools::TimeInterval.today
9
- value id: 5, name: I18n.t('chupakabra.time_intervals.tomorrow'), seo_tag: 'tomorrow', time_line: 'future', scale: 'day', value: ChupakabraTools::TimeInterval.tomorrow
10
- value id: 6, name: I18n.t('chupakabra.time_intervals.yesterday'), seo_tag: 'yesterday', time_line: 'past', scale: 'day', value: ChupakabraTools::TimeInterval.yesterday
11
- value id: 7, name: I18n.t('chupakabra.time_intervals.this_week'), seo_tag: 'this_week', time_line: 'present', scale: 'week', value: ChupakabraTools::TimeInterval.this_week
12
- value id: 8, name: I18n.t('chupakabra.time_intervals.last_week'), seo_tag: 'last_week', time_line: 'past', scale: 'week', value: ChupakabraTools::TimeInterval.previous_week
13
- value id: 9, name: I18n.t('chupakabra.time_intervals.next_week'), seo_tag: 'next_week', time_line: 'future', scale: 'week', value: ChupakabraTools::TimeInterval.next_week
14
- value id: 10, name: I18n.t('chupakabra.time_intervals.this_month'), seo_tag: 'this_month', time_line: 'present', scale: 'month', value: ChupakabraTools::TimeInterval.this_month
15
- value id: 11, name: I18n.t('chupakabra.time_intervals.last_month'), seo_tag: 'last_month', time_line: 'past', scale: 'month', value: ChupakabraTools::TimeInterval.previous_month
16
- value id: 12, name: I18n.t('chupakabra.time_intervals.next_month'), seo_tag: 'next_month', time_line: 'future', scale: 'month', value: ChupakabraTools::TimeInterval.next_month
17
- value id: 13, name: I18n.t('chupakabra.time_intervals.this_quarter'), seo_tag: 'this_quarter', time_line: 'present', scale: 'quarter', value: ChupakabraTools::TimeInterval.this_quarter
18
- value id: 14, name: I18n.t('chupakabra.time_intervals.last_quarter'), seo_tag: 'last_quarter', time_line: 'past', scale: 'quarter', value: ChupakabraTools::TimeInterval.previous_quarter
19
- value id: 15, name: I18n.t('chupakabra.time_intervals.next_quarter'), seo_tag: 'next_quarter', time_line: 'future', scale: 'quarter', value: ChupakabraTools::TimeInterval.next_quarter
20
- value id: 16, name: I18n.t('chupakabra.time_intervals.this_year'), seo_tag: 'this_year', time_line: 'present', scale: 'year', value: ChupakabraTools::TimeInterval.this_year
21
- value id: 17, name: I18n.t('chupakabra.time_intervals.last_year'), seo_tag: 'last_year', time_line: 'past', scale: 'year', value: ChupakabraTools::TimeInterval.previous_year
22
- value id: 18, name: I18n.t('chupakabra.time_intervals.next_year'), seo_tag: 'next_year', time_line: 'future', scale: 'year', value: ChupakabraTools::TimeInterval.next_year
5
+ value id: 1, name: I18n.t('chupakabra_tools.time_intervals.this_hour'), seo_tag: 'this_hour', time_line: 'present', scale: 'hour', value: ChupakabraTools::TimeInterval.this_hour
6
+ value id: 2, name: I18n.t('chupakabra_tools.time_intervals.last_hour'), seo_tag: 'last_hour', time_line: 'past', scale: 'hour', value: ChupakabraTools::TimeInterval.previous_hour
7
+ value id: 3, name: I18n.t('chupakabra_tools.time_intervals.next_hour'), seo_tag: 'next_hour', time_line: 'future', scale: 'hour', value: ChupakabraTools::TimeInterval.next_hour
8
+ value id: 4, name: I18n.t('chupakabra_tools.time_intervals.today'), seo_tag: 'today', time_line: 'present', scale: 'day', value: ChupakabraTools::TimeInterval.today
9
+ value id: 5, name: I18n.t('chupakabra_tools.time_intervals.tomorrow'), seo_tag: 'tomorrow', time_line: 'future', scale: 'day', value: ChupakabraTools::TimeInterval.tomorrow
10
+ value id: 6, name: I18n.t('chupakabra_tools.time_intervals.yesterday'), seo_tag: 'yesterday', time_line: 'past', scale: 'day', value: ChupakabraTools::TimeInterval.yesterday
11
+ value id: 7, name: I18n.t('chupakabra_tools.time_intervals.this_week'), seo_tag: 'this_week', time_line: 'present', scale: 'week', value: ChupakabraTools::TimeInterval.this_week
12
+ value id: 8, name: I18n.t('chupakabra_tools.time_intervals.last_week'), seo_tag: 'last_week', time_line: 'past', scale: 'week', value: ChupakabraTools::TimeInterval.previous_week
13
+ value id: 9, name: I18n.t('chupakabra_tools.time_intervals.next_week'), seo_tag: 'next_week', time_line: 'future', scale: 'week', value: ChupakabraTools::TimeInterval.next_week
14
+ value id: 10, name: I18n.t('chupakabra_tools.time_intervals.this_month'), seo_tag: 'this_month', time_line: 'present', scale: 'month', value: ChupakabraTools::TimeInterval.this_month
15
+ value id: 11, name: I18n.t('chupakabra_tools.time_intervals.last_month'), seo_tag: 'last_month', time_line: 'past', scale: 'month', value: ChupakabraTools::TimeInterval.previous_month
16
+ value id: 12, name: I18n.t('chupakabra_tools.time_intervals.next_month'), seo_tag: 'next_month', time_line: 'future', scale: 'month', value: ChupakabraTools::TimeInterval.next_month
17
+ value id: 13, name: I18n.t('chupakabra_tools.time_intervals.this_quarter'), seo_tag: 'this_quarter', time_line: 'present', scale: 'quarter', value: ChupakabraTools::TimeInterval.this_quarter
18
+ value id: 14, name: I18n.t('chupakabra_tools.time_intervals.last_quarter'), seo_tag: 'last_quarter', time_line: 'past', scale: 'quarter', value: ChupakabraTools::TimeInterval.previous_quarter
19
+ value id: 15, name: I18n.t('chupakabra_tools.time_intervals.next_quarter'), seo_tag: 'next_quarter', time_line: 'future', scale: 'quarter', value: ChupakabraTools::TimeInterval.next_quarter
20
+ value id: 16, name: I18n.t('chupakabra_tools.time_intervals.this_year'), seo_tag: 'this_year', time_line: 'present', scale: 'year', value: ChupakabraTools::TimeInterval.this_year
21
+ value id: 17, name: I18n.t('chupakabra_tools.time_intervals.last_year'), seo_tag: 'last_year', time_line: 'past', scale: 'year', value: ChupakabraTools::TimeInterval.previous_year
22
+ value id: 18, name: I18n.t('chupakabra_tools.time_intervals.next_year'), seo_tag: 'next_year', time_line: 'future', scale: 'year', value: ChupakabraTools::TimeInterval.next_year
23
23
  end