aenea 0.2.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.
Files changed (50) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +39 -0
  3. data/Rakefile +24 -0
  4. data/app/assets/config/aenea_manifest.js +0 -0
  5. data/app/helpers/inline_boolean_input.rb +9 -0
  6. data/app/helpers/markdown_input.rb +21 -0
  7. data/app/helpers/non_input_input.rb +7 -0
  8. data/app/models/concerns/acts_as_only_flagged.rb +65 -0
  9. data/app/models/concerns/can_be_inactive.rb +8 -0
  10. data/app/models/concerns/has_external_id.rb +9 -0
  11. data/app/models/concerns/has_obfuscated_id.rb +51 -0
  12. data/app/models/concerns/model.rb +51 -0
  13. data/app/models/concerns/model/belongs_to.rb +38 -0
  14. data/app/models/concerns/model/enum.rb +24 -0
  15. data/app/models/concerns/model/has_many.rb +127 -0
  16. data/app/models/concerns/model/has_one.rb +77 -0
  17. data/app/models/concerns/sluggable.rb +7 -0
  18. data/app/models/countries.rb +278 -0
  19. data/app/models/country_validator.rb +10 -0
  20. data/app/models/database_function_helper.rb +88 -0
  21. data/app/models/google_maps_api.rb +19 -0
  22. data/app/models/google_maps_api/geocode.rb +29 -0
  23. data/app/models/google_maps_api/time_zone.rb +29 -0
  24. data/app/models/json_api.rb +16 -0
  25. data/app/models/phone_number_validator.rb +10 -0
  26. data/app/models/us_state_validator.rb +10 -0
  27. data/app/models/us_states.rb +75 -0
  28. data/app/models/zip_code_validator.rb +12 -0
  29. data/lib/aenea.rb +12 -0
  30. data/lib/aenea/active_admin.rb +23 -0
  31. data/lib/aenea/active_admin/index_as_table.rb +9 -0
  32. data/lib/aenea/active_admin/index_as_table/sortable_columns.rb +29 -0
  33. data/lib/aenea/active_admin/resource_controller.rb +9 -0
  34. data/lib/aenea/active_admin/resource_controller/find_sluggable.rb +21 -0
  35. data/lib/aenea/active_admin/resource_dsl.rb +11 -0
  36. data/lib/aenea/active_admin/resource_dsl/sortable_actions.rb +53 -0
  37. data/lib/aenea/active_admin/resource_dsl/use_parent_actions.rb +79 -0
  38. data/lib/aenea/date.rb +14 -0
  39. data/lib/aenea/engine.rb +20 -0
  40. data/lib/aenea/enum.rb +13 -0
  41. data/lib/aenea/enum/changes.rb +61 -0
  42. data/lib/aenea/enum/ext.rb +68 -0
  43. data/lib/aenea/enum/groups.rb +53 -0
  44. data/lib/aenea/markdown_attr.rb +43 -0
  45. data/lib/aenea/time.rb +9 -0
  46. data/lib/aenea/time_of_day.rb +41 -0
  47. data/lib/aenea/time_window.rb +86 -0
  48. data/lib/aenea/version.rb +3 -0
  49. data/lib/tasks/aenea_tasks.rake +4 -0
  50. metadata +203 -0
@@ -0,0 +1,14 @@
1
+ class Date
2
+ def beginning_of_month
3
+ Date.new(self.year, self.month, 1)
4
+ end
5
+
6
+ def end_of_month
7
+ next_month = self + 1.month
8
+ Date.new(next_month.year, next_month.month, 1) - 1.day
9
+ end
10
+
11
+ def self.today_in_pacific_tz
12
+ Time.now.in_pacific_tz.to_date
13
+ end
14
+ end
@@ -0,0 +1,20 @@
1
+ module Aenea
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace Aenea
4
+
5
+ config.to_prepare do
6
+ ActiveSupport.on_load(:active_record) do
7
+ include Aenea::Enum
8
+ include Aenea::MarkdownAttr
9
+
10
+ ActiveRecord::Type.register :time_of_day, Tod::TimeOfDay::Type
11
+ ActiveModel::Type.register :time_of_day, Tod::TimeOfDay::Type
12
+
13
+ ActiveRecord::Type.register :time_window, Aenea::TimeWindow::Type
14
+ ActiveModel::Type.register :time_window, Aenea::TimeWindow::Type
15
+
16
+ Aenea::ActiveAdmin.install
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,13 @@
1
+ require 'aenea/enum/changes'
2
+ require 'aenea/enum/ext'
3
+ require 'aenea/enum/groups'
4
+
5
+ module Aenea
6
+ module Enum
7
+ extend ActiveSupport::Concern
8
+
9
+ include Changes
10
+ include Ext
11
+ include Groups
12
+ end
13
+ end
@@ -0,0 +1,61 @@
1
+ module Aenea
2
+ module Enum
3
+ module Changes
4
+ extend ActiveSupport::Concern
5
+
6
+ class_methods do
7
+ def record_enum_changed_at(enum, name)
8
+ # validates activated_at, presence: true, if: :active?
9
+ column = "#{name}_at".to_sym
10
+ validates column, presence: true, if: "#{name}?".to_sym
11
+
12
+ # before_validation populate_status_activated_at
13
+ populate_method = "populate_#{enum}_#{column}".to_sym
14
+ before_validation populate_method, if: "will_save_#{enum}_as_#{name}?".to_sym
15
+
16
+ # def populate_status_activated_at
17
+ define_method populate_method do
18
+ send("#{column}=", Time.now) unless send(column).present?
19
+ end
20
+
21
+ # def formatted_activated_at
22
+ define_method "formatted_#{column}" do
23
+ Formatter.timestamp send(column)
24
+ end
25
+
26
+ # def activated_on
27
+ date_method = "#{name}_on"
28
+ define_method date_method do
29
+ send(column).try(:to_date)
30
+ end
31
+
32
+ # def formatted_activated_on
33
+ define_method "formatted_#{date_method}" do
34
+ Formatter.date send(date_method)
35
+ end
36
+
37
+ # def short_formatted_activated_on
38
+ define_method "short_formatted_#{date_method}" do
39
+ Formatter.short_date send(date_method)
40
+ end
41
+ end
42
+
43
+ def validate_enum_change(enum, name, valid_previous_names)
44
+ method = "validate_#{enum}_change_to_#{name}".to_sym
45
+
46
+ # validate :validate_status_change_to_active
47
+ validate method, if: "will_save_#{enum}_as_#{name}?".to_sym
48
+
49
+ # def validate_status_change_to_active
50
+ define_method method do
51
+ name_in_database = send("#{enum}_in_database")
52
+
53
+ unless valid_previous_names.include?(name_in_database)
54
+ errors.add(enum, "cannot change from #{name_in_database.to_s.titleize} to #{send(enum).to_s.titleize}")
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,68 @@
1
+ module Aenea
2
+ module Enum
3
+ module Ext
4
+ extend ActiveSupport::Concern
5
+
6
+ class_methods do
7
+ def enum(*args)
8
+ super
9
+
10
+ defined_enums.keys.each do |name|
11
+ will_save_change_method = "will_save_change_to_#{name}?"
12
+ saved_change_method = "saved_change_to_#{name}?"
13
+
14
+ # def will_save_status_as_nil?
15
+ define_method "will_save_#{name}_as_nil?" do
16
+ send(will_save_change_method) && send(name).nil?
17
+ end
18
+
19
+ # def will_save_status_as_non_nil?
20
+ define_method "will_save_#{name}_as_non_nil?" do
21
+ send(will_save_change_method) && !send(name).nil?
22
+ end
23
+
24
+ # def saved_status_as_nil?
25
+ define_method "saved_#{name}_as_nil?" do
26
+ send(saved_change_method) && send(name).nil?
27
+ end
28
+
29
+ # def saved_status_as_non_nil?
30
+ define_method "saved_#{name}_as_non_nil?" do
31
+ send(saved_change_method) && !send(name).nil?
32
+ end
33
+
34
+ enum_method = name.to_s.pluralize
35
+ send(enum_method).keys.each do |key|
36
+ # def save_as_active
37
+ define_method "save_as_#{key}" do
38
+ update(name => key)
39
+ end
40
+
41
+ # def will_save_status_as_active?
42
+ define_method "will_save_#{name}_as_#{key}?" do
43
+ send(will_save_change_method) && send("#{key}?")
44
+ end
45
+
46
+ # def saved_status_as_active?
47
+ define_method "saved_#{name}_as_#{key}?" do
48
+ send(saved_change_method) && send("#{key}?")
49
+ end
50
+ end
51
+
52
+ define_method "formatted_#{name}" do
53
+ send(name).try(:titleize)
54
+ end
55
+
56
+ define_singleton_method("#{name}_select_values") do
57
+ send(enum_method).keys.map {|k| [k.titleize, k] }
58
+ end
59
+
60
+ define_singleton_method("#{name}_filter_values") do
61
+ send(enum_method).map {|k, v| [k.titleize, v] }
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,53 @@
1
+ module Aenea
2
+ module Enum
3
+ module Groups
4
+ extend ActiveSupport::Concern
5
+
6
+ class_methods do
7
+ def enum_group(modifier, enum, *keys)
8
+ enum_plural = enum.to_s.pluralize # statuses
9
+ group = [ modifier, enum_plural ].join('_') # inactive_statuses
10
+ singular_group = [ modifier, enum ].join('_') # inactive_status
11
+ keys = keys.flatten.freeze
12
+
13
+ keys.each do |key|
14
+ raise "invalid #{enum}: #{key}" unless send(enum_plural).keys.include?(key)
15
+ end
16
+
17
+ # def self.inactive_statuses
18
+ define_singleton_method group do
19
+ keys.dup
20
+ end
21
+
22
+ # scope :inactive, -> { where(status: inactive_statuses) }
23
+ scope modifier, -> { where(enum => send(group)) }
24
+
25
+ # def inactive?
26
+ define_method "#{modifier}?" do
27
+ self.class.send(group).include?(send(enum)) # self.class.inactive_statuses.include?(status)
28
+ end
29
+
30
+ # def will_save_status_as_inactive?
31
+ define_method "will_save_#{enum}_as_#{modifier}?" do
32
+ self.class.send(group).inject(false) {|result, e| result = result || send("will_save_#{enum}_as_#{e}?") }
33
+ end
34
+
35
+ # def saved_status_as_inactive?
36
+ define_method "saved_#{enum}_as_#{modifier}?" do
37
+ self.class.send(group).inject(false) {|result, e| result = result || send("saved_#{enum}_as_#{e}?") }
38
+ end
39
+
40
+ # def inactive_status_select_values
41
+ define_singleton_method("#{singular_group}_select_values") do
42
+ send(group).map {|k| [ k.titleize, k ] }
43
+ end
44
+
45
+ # def inactive_status_filter_values
46
+ define_singleton_method("#{singular_group}_filter_values") do
47
+ send(group).map {|k| [ k.titleize, send(enum_plural)[k] ] }
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,43 @@
1
+ require 'kramdown'
2
+
3
+ module Aenea
4
+ module MarkdownAttr
5
+ extend ActiveSupport::Concern
6
+ include ActionView::Helpers::SanitizeHelper
7
+
8
+ class_methods do
9
+ def markdown_attr(attr_base_name)
10
+ attr_name = "#{attr_base_name}_as_md"
11
+
12
+ doc_method = "#{attr_base_name}_doc"
13
+ define_method doc_method do
14
+ return nil unless md = send(attr_name)
15
+
16
+ var_name = :"@#{doc_method}"
17
+ value = instance_variable_get var_name
18
+ return value if value
19
+
20
+ instance_variable_set var_name, Kramdown::Document.new(md)
21
+ end
22
+
23
+ html_method = "#{attr_base_name}_as_html"
24
+ define_method html_method do
25
+ return nil unless doc = send(doc_method)
26
+
27
+ var_name = :"@#{html_method}"
28
+ value = instance_variable_get var_name
29
+ return value if value
30
+
31
+ instance_variable_set var_name, doc.to_html.html_safe
32
+ end
33
+
34
+ text_method = "#{attr_base_name}_as_text"
35
+ define_method text_method do
36
+ return nil unless html = send(html_method)
37
+
38
+ strip_tags html
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,9 @@
1
+ class Time
2
+ def self.pacific_tz_id
3
+ 'America/Los_Angeles'
4
+ end
5
+
6
+ def in_pacific_tz
7
+ in_time_zone Time.pacific_tz_id
8
+ end
9
+ end
@@ -0,0 +1,41 @@
1
+ require 'tod'
2
+ require 'tod/core_extensions'
3
+
4
+ module Tod
5
+ class TimeOfDay
6
+ def to_ampm
7
+ am_or_pm = hour < 12 ? 'am' : 'pm'
8
+ ampm_hour = hour == 0 ? 12 : (hour > 12 ? hour - 12 : hour)
9
+
10
+ sprintf('%d:%02d%s', ampm_hour, minute, am_or_pm)
11
+ end
12
+
13
+ def to_select_value
14
+ [to_ampm, to_s]
15
+ end
16
+
17
+ class Type < ActiveModel::Type::Value
18
+ def cast(value)
19
+ if value.blank?
20
+ nil
21
+ elsif value.is_a?(Tod::TimeOfDay)
22
+ value
23
+ elsif value.is_a?(String)
24
+ begin
25
+ Tod::TimeOfDay.parse(value)
26
+ rescue StandardError => e
27
+ ApplicationRecord.logger.warn "error casting #{value.inspect}: #{e.message}"
28
+ ensure
29
+ nil
30
+ end
31
+ else
32
+ raise "invalid value type #{value.class.name}: #{value.inspect}"
33
+ end
34
+ end
35
+
36
+ def serialize(value)
37
+ value.blank? ? nil : value.to_s
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,86 @@
1
+ module Aenea
2
+ class TimeWindow
3
+ SEPARATOR = ' - '
4
+
5
+ attr_reader :starting, :ending
6
+
7
+ def initialize(start_tod, end_tod_or_window_in_seconds)
8
+ @starting = start_tod.dup
9
+
10
+ if end_tod_or_window_in_seconds.is_a?(Tod::TimeOfDay)
11
+ @ending = end_tod_or_window_in_seconds.dup
12
+ else
13
+ @ending = @starting + end_tod_or_window_in_seconds # number of seconds
14
+ end
15
+
16
+ if ending < starting
17
+ raise ArgumentError.new("invalid window #{starting} - #{ending}")
18
+ end
19
+
20
+ self.freeze
21
+ end
22
+
23
+ def self.parse(str)
24
+ new(*str.split(SEPARATOR).collect {|s| Tod::TimeOfDay.parse(s) })
25
+ end
26
+
27
+ # a row of PL/pgsql return type table(time, time), returned as a varchar
28
+ # using SELECT func_... rather than SELECT * FROM func_... - the returned
29
+ # values are in the form "(11:00:00,13:00:00)"
30
+ def self.parse_tuple(str)
31
+ elements = str.sub(/^\(/, '').sub(/\)$/, '').split(',')
32
+ new(*elements.map {|s| Tod::TimeOfDay.parse(s) })
33
+ end
34
+
35
+ def ==(obj)
36
+ self.starting == obj.starting && ending == obj.ending
37
+ end
38
+
39
+ def <=>(obj)
40
+ start_comp = self.starting <=> obj.starting
41
+ return start_comp if start_comp != 0
42
+
43
+ self.ending <=> obj.ending
44
+ end
45
+
46
+ def to_s
47
+ starting.to_s + SEPARATOR + ending.to_s
48
+ end
49
+
50
+ def to_ampm
51
+ starting.to_ampm + SEPARATOR + ending.to_ampm
52
+ end
53
+
54
+ def to_select_value
55
+ [to_ampm, to_s]
56
+ end
57
+
58
+ def inspect
59
+ "<#{to_s}>"
60
+ end
61
+
62
+ class Type < ActiveModel::Type::ImmutableString
63
+ def cast(value)
64
+ if value.blank?
65
+ nil
66
+ elsif value.is_a?(String)
67
+ begin
68
+ TimeWindow.parse(value)
69
+ rescue StandardError => e
70
+ ApplicationRecord.logger.warn "error casting #{value.inspect}: #{e.message}"
71
+ ensure
72
+ nil
73
+ end
74
+ elsif value.is_a?(TimeWindow)
75
+ value
76
+ else
77
+ raise "invalid value type #{value.class.name}: #{value.inspect}"
78
+ end
79
+ end
80
+
81
+ def serialize(value)
82
+ value.blank? ? nil : value.to_s
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,3 @@
1
+ module Aenea
2
+ VERSION = '0.2.0'
3
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :aenea do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,203 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: aenea
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Anthony Wang
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-02-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '6.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '6.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: kramdown
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.17'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.17'
41
+ - !ruby/object:Gem::Dependency
42
+ name: tod
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.2'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.2'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pg
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.1'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.1'
69
+ - !ruby/object:Gem::Dependency
70
+ name: activeadmin
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '2.4'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '2.4'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec-rails
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.8'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '3.8'
97
+ - !ruby/object:Gem::Dependency
98
+ name: factory_bot_rails
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '4.11'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '4.11'
111
+ - !ruby/object:Gem::Dependency
112
+ name: listen
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description: Aenea
126
+ email:
127
+ - anthony@anthonywang.com
128
+ executables: []
129
+ extensions: []
130
+ extra_rdoc_files: []
131
+ files:
132
+ - README.md
133
+ - Rakefile
134
+ - app/assets/config/aenea_manifest.js
135
+ - app/helpers/inline_boolean_input.rb
136
+ - app/helpers/markdown_input.rb
137
+ - app/helpers/non_input_input.rb
138
+ - app/models/concerns/acts_as_only_flagged.rb
139
+ - app/models/concerns/can_be_inactive.rb
140
+ - app/models/concerns/has_external_id.rb
141
+ - app/models/concerns/has_obfuscated_id.rb
142
+ - app/models/concerns/model.rb
143
+ - app/models/concerns/model/belongs_to.rb
144
+ - app/models/concerns/model/enum.rb
145
+ - app/models/concerns/model/has_many.rb
146
+ - app/models/concerns/model/has_one.rb
147
+ - app/models/concerns/sluggable.rb
148
+ - app/models/countries.rb
149
+ - app/models/country_validator.rb
150
+ - app/models/database_function_helper.rb
151
+ - app/models/google_maps_api.rb
152
+ - app/models/google_maps_api/geocode.rb
153
+ - app/models/google_maps_api/time_zone.rb
154
+ - app/models/json_api.rb
155
+ - app/models/phone_number_validator.rb
156
+ - app/models/us_state_validator.rb
157
+ - app/models/us_states.rb
158
+ - app/models/zip_code_validator.rb
159
+ - lib/aenea.rb
160
+ - lib/aenea/active_admin.rb
161
+ - lib/aenea/active_admin/index_as_table.rb
162
+ - lib/aenea/active_admin/index_as_table/sortable_columns.rb
163
+ - lib/aenea/active_admin/resource_controller.rb
164
+ - lib/aenea/active_admin/resource_controller/find_sluggable.rb
165
+ - lib/aenea/active_admin/resource_dsl.rb
166
+ - lib/aenea/active_admin/resource_dsl/sortable_actions.rb
167
+ - lib/aenea/active_admin/resource_dsl/use_parent_actions.rb
168
+ - lib/aenea/date.rb
169
+ - lib/aenea/engine.rb
170
+ - lib/aenea/enum.rb
171
+ - lib/aenea/enum/changes.rb
172
+ - lib/aenea/enum/ext.rb
173
+ - lib/aenea/enum/groups.rb
174
+ - lib/aenea/markdown_attr.rb
175
+ - lib/aenea/time.rb
176
+ - lib/aenea/time_of_day.rb
177
+ - lib/aenea/time_window.rb
178
+ - lib/aenea/version.rb
179
+ - lib/tasks/aenea_tasks.rake
180
+ homepage: https://github.com/wangthony/aenea
181
+ licenses: []
182
+ metadata: {}
183
+ post_install_message:
184
+ rdoc_options: []
185
+ require_paths:
186
+ - lib
187
+ required_ruby_version: !ruby/object:Gem::Requirement
188
+ requirements:
189
+ - - ">="
190
+ - !ruby/object:Gem::Version
191
+ version: '0'
192
+ required_rubygems_version: !ruby/object:Gem::Requirement
193
+ requirements:
194
+ - - ">="
195
+ - !ruby/object:Gem::Version
196
+ version: '0'
197
+ requirements: []
198
+ rubyforge_project:
199
+ rubygems_version: 2.7.8
200
+ signing_key:
201
+ specification_version: 4
202
+ summary: Aenea
203
+ test_files: []