aenea 0.2.0

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/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,77 @@
1
+ module Model
2
+ module HasOne
3
+ extend ActiveSupport::Concern
4
+
5
+ class Association
6
+ attr_reader :target, :assoc
7
+
8
+ def initialize(target, assoc, options = {})
9
+ @target = target
10
+ @assoc = assoc.to_sym
11
+
12
+ class_name = options[:class_name] || assoc.to_s.camelize
13
+ klass = class_name.constantize
14
+
15
+ builder_method_name = "build_#{assoc}".to_sym
16
+ validate_method_name = "validate_associated_#{assoc}".to_sym
17
+
18
+ target.send :attr_accessor, assoc
19
+ define_builder builder_method_name, assoc, klass
20
+ define_attributes_writer builder_method_name
21
+ define_present_method assoc
22
+ define_nil_method assoc
23
+ define_validate_method validate_method_name, assoc
24
+
25
+ if validate_options = options[:validate]
26
+ target.validate validate_method_name, validate_options.is_a?(Hash) ? validate_options : {}
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ def define_builder(builder_method_name, assoc, klass)
33
+ # def build_thing(attrs = {})
34
+ target.send :define_method, builder_method_name do |attrs = {}|
35
+ send "#{assoc}=", klass.new(attrs)
36
+ end
37
+ end
38
+
39
+ def define_attributes_writer(builder_method_name)
40
+ # def thing_attributes=(params)
41
+ target.send :define_method, "#{assoc}_attributes=" do |params|
42
+ send builder_method_name, params
43
+ end
44
+ end
45
+
46
+ def define_present_method(assoc)
47
+ # def things_present?
48
+ target.send :define_method, "#{assoc}_present?" do
49
+ send(assoc).present?
50
+ end
51
+ end
52
+
53
+ def define_nil_method(assoc)
54
+ # def things_empty?
55
+ target.send :define_method, "#{assoc}_nil?" do
56
+ send(assoc).nil?
57
+ end
58
+ end
59
+
60
+ def define_validate_method(validate_method_name, assoc)
61
+ # def validate_associated_thing
62
+ target.send :define_method, validate_method_name do
63
+ return unless obj = send(assoc)
64
+ errors.add assoc, 'is invalid' unless obj.valid?
65
+ end
66
+ end
67
+ end
68
+
69
+ module ClassMethods
70
+ def has_one(name, options = {})
71
+ (self.associations_registry ||= {})[name] = :has_one
72
+
73
+ Association.new self, name, options
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,7 @@
1
+ module Sluggable
2
+ extend ActiveSupport::Concern
3
+
4
+ def to_param
5
+ url
6
+ end
7
+ end
@@ -0,0 +1,278 @@
1
+ module Countries
2
+ # https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3
3
+ VALUES = [
4
+ ['ABW', 'Aruba'],
5
+ ['AFG', 'Afghanistan'],
6
+ ['AGO', 'Angola'],
7
+ ['AIA', 'Anguilla'],
8
+ ['ALA', 'Åland Islands'],
9
+ ['ALB', 'Albania'],
10
+ ['AND', 'Andorra'],
11
+ ['ARE', 'United Arab Emirates'],
12
+ ['ARG', 'Argentina'],
13
+ ['ARM', 'Armenia'],
14
+ ['ASM', 'American Samoa'],
15
+ ['ATA', 'Antarctica'],
16
+ ['ATF', 'French Southern Territories'],
17
+ ['ATG', 'Antigua and Barbuda'],
18
+ ['AUS', 'Australia'],
19
+ ['AUT', 'Austria'],
20
+ ['AZE', 'Azerbaijan'],
21
+ ['BDI', 'Burundi'],
22
+ ['BEL', 'Belgium'],
23
+ ['BEN', 'Benin'],
24
+ ['BES', 'Bonaire, Sint Eustatius and Saba'],
25
+ ['BFA', 'Burkina Faso'],
26
+ ['BGD', 'Bangladesh'],
27
+ ['BGR', 'Bulgaria'],
28
+ ['BHR', 'Bahrain'],
29
+ ['BHS', 'Bahamas'],
30
+ ['BIH', 'Bosnia and Herzegovina'],
31
+ ['BLM', 'Saint Barthélemy'],
32
+ ['BLR', 'Belarus'],
33
+ ['BLZ', 'Belize'],
34
+ ['BMU', 'Bermuda'],
35
+ ['BOL', 'Bolivia, Plurinational State of'],
36
+ ['BRA', 'Brazil'],
37
+ ['BRB', 'Barbados'],
38
+ ['BRN', 'Brunei Darussalam'],
39
+ ['BTN', 'Bhutan'],
40
+ ['BVT', 'Bouvet Island'],
41
+ ['BWA', 'Botswana'],
42
+ ['CAF', 'Central African Republic'],
43
+ ['CAN', 'Canada'],
44
+ ['CCK', 'Cocos (Keeling) Islands'],
45
+ ['CHE', 'Switzerland'],
46
+ ['CHL', 'Chile'],
47
+ ['CHN', 'China'],
48
+ ['CIV', 'Côte d\'Ivoire'],
49
+ ['CMR', 'Cameroon'],
50
+ ['COD', 'Congo, the Democratic Republic of the'],
51
+ ['COG', 'Congo'],
52
+ ['COK', 'Cook Islands'],
53
+ ['COL', 'Colombia'],
54
+ ['COM', 'Comoros'],
55
+ ['CPV', 'Cabo Verde'],
56
+ ['CRI', 'Costa Rica'],
57
+ ['CUB', 'Cuba'],
58
+ ['CUW', 'Curaçao'],
59
+ ['CXR', 'Christmas Island'],
60
+ ['CYM', 'Cayman Islands'],
61
+ ['CYP', 'Cyprus'],
62
+ ['CZE', 'Czechia'],
63
+ ['DEU', 'Germany'],
64
+ ['DJI', 'Djibouti'],
65
+ ['DMA', 'Dominica'],
66
+ ['DNK', 'Denmark'],
67
+ ['DOM', 'Dominican Republic'],
68
+ ['DZA', 'Algeria'],
69
+ ['ECU', 'Ecuador'],
70
+ ['EGY', 'Egypt'],
71
+ ['ERI', 'Eritrea'],
72
+ ['ESH', 'Western Sahara'],
73
+ ['ESP', 'Spain'],
74
+ ['EST', 'Estonia'],
75
+ ['ETH', 'Ethiopia'],
76
+ ['FIN', 'Finland'],
77
+ ['FJI', 'Fiji'],
78
+ ['FLK', 'Falkland Islands (Malvinas)'],
79
+ ['FRA', 'France'],
80
+ ['FRO', 'Faroe Islands'],
81
+ ['FSM', 'Micronesia, Federated States of'],
82
+ ['GAB', 'Gabon'],
83
+ ['GBR', 'United Kingdom'],
84
+ ['GEO', 'Georgia'],
85
+ ['GGY', 'Guernsey'],
86
+ ['GHA', 'Ghana'],
87
+ ['GIB', 'Gibraltar'],
88
+ ['GIN', 'Guinea'],
89
+ ['GLP', 'Guadeloupe'],
90
+ ['GMB', 'Gambia'],
91
+ ['GNB', 'Guinea-Bissau'],
92
+ ['GNQ', 'Equatorial Guinea'],
93
+ ['GRC', 'Greece'],
94
+ ['GRD', 'Grenada'],
95
+ ['GRL', 'Greenland'],
96
+ ['GTM', 'Guatemala'],
97
+ ['GUF', 'French Guiana'],
98
+ ['GUM', 'Guam'],
99
+ ['GUY', 'Guyana'],
100
+ ['HKG', 'Hong Kong'],
101
+ ['HMD', 'Heard Island and McDonald Islands'],
102
+ ['HND', 'Honduras'],
103
+ ['HRV', 'Croatia'],
104
+ ['HTI', 'Haiti'],
105
+ ['HUN', 'Hungary'],
106
+ ['IDN', 'Indonesia'],
107
+ ['IMN', 'Isle of Man'],
108
+ ['IND', 'India'],
109
+ ['IOT', 'British Indian Ocean Territory'],
110
+ ['IRL', 'Ireland'],
111
+ ['IRN', 'Iran, Islamic Republic of'],
112
+ ['IRQ', 'Iraq'],
113
+ ['ISL', 'Iceland'],
114
+ ['ISR', 'Israel'],
115
+ ['ITA', 'Italy'],
116
+ ['JAM', 'Jamaica'],
117
+ ['JEY', 'Jersey'],
118
+ ['JOR', 'Jordan'],
119
+ ['JPN', 'Japan'],
120
+ ['KAZ', 'Kazakhstan'],
121
+ ['KEN', 'Kenya'],
122
+ ['KGZ', 'Kyrgyzstan'],
123
+ ['KHM', 'Cambodia'],
124
+ ['KIR', 'Kiribati'],
125
+ ['KNA', 'Saint Kitts and Nevis'],
126
+ ['KOR', 'Korea, Republic of'],
127
+ ['KWT', 'Kuwait'],
128
+ ['LAO', 'Lao People\'s Democratic Republic'],
129
+ ['LBN', 'Lebanon'],
130
+ ['LBR', 'Liberia'],
131
+ ['LBY', 'Libya'],
132
+ ['LCA', 'Saint Lucia'],
133
+ ['LIE', 'Liechtenstein'],
134
+ ['LKA', 'Sri Lanka'],
135
+ ['LSO', 'Lesotho'],
136
+ ['LTU', 'Lithuania'],
137
+ ['LUX', 'Luxembourg'],
138
+ ['LVA', 'Latvia'],
139
+ ['MAC', 'Macao'],
140
+ ['MAF', 'Saint Martin (French part)'],
141
+ ['MAR', 'Morocco'],
142
+ ['MCO', 'Monaco'],
143
+ ['MDA', 'Moldova, Republic of'],
144
+ ['MDG', 'Madagascar'],
145
+ ['MDV', 'Maldives'],
146
+ ['MEX', 'Mexico'],
147
+ ['MHL', 'Marshall Islands'],
148
+ ['MKD', 'Macedonia, the former Yugoslav Republic of'],
149
+ ['MLI', 'Mali'],
150
+ ['MLT', 'Malta'],
151
+ ['MMR', 'Myanmar'],
152
+ ['MNE', 'Montenegro'],
153
+ ['MNG', 'Mongolia'],
154
+ ['MNP', 'Northern Mariana Islands'],
155
+ ['MOZ', 'Mozambique'],
156
+ ['MRT', 'Mauritania'],
157
+ ['MSR', 'Montserrat'],
158
+ ['MTQ', 'Martinique'],
159
+ ['MUS', 'Mauritius'],
160
+ ['MWI', 'Malawi'],
161
+ ['MYS', 'Malaysia'],
162
+ ['MYT', 'Mayotte'],
163
+ ['NAM', 'Namibia'],
164
+ ['NCL', 'New Caledonia'],
165
+ ['NER', 'Niger'],
166
+ ['NFK', 'Norfolk Island'],
167
+ ['NGA', 'Nigeria'],
168
+ ['NIC', 'Nicaragua'],
169
+ ['NIU', 'Niue'],
170
+ ['NLD', 'Netherlands'],
171
+ ['NOR', 'Norway'],
172
+ ['NPL', 'Nepal'],
173
+ ['NRU', 'Nauru'],
174
+ ['NZL', 'New Zealand'],
175
+ ['OMN', 'Oman'],
176
+ ['PAK', 'Pakistan'],
177
+ ['PAN', 'Panama'],
178
+ ['PCN', 'Pitcairn'],
179
+ ['PER', 'Peru'],
180
+ ['PHL', 'Philippines'],
181
+ ['PLW', 'Palau'],
182
+ ['PNG', 'Papua New Guinea'],
183
+ ['POL', 'Poland'],
184
+ ['PRI', 'Puerto Rico'],
185
+ ['PRK', 'Korea, Democratic People\'s Republic of'],
186
+ ['PRT', 'Portugal'],
187
+ ['PRY', 'Paraguay'],
188
+ ['PSE', 'Palestine, State of'],
189
+ ['PYF', 'French Polynesia'],
190
+ ['QAT', 'Qatar'],
191
+ ['REU', 'Réunion'],
192
+ ['ROU', 'Romania'],
193
+ ['RUS', 'Russian Federation'],
194
+ ['RWA', 'Rwanda'],
195
+ ['SAU', 'Saudi Arabia'],
196
+ ['SDN', 'Sudan'],
197
+ ['SEN', 'Senegal'],
198
+ ['SGP', 'Singapore'],
199
+ ['SGS', 'South Georgia and the South Sandwich Islands'],
200
+ ['SHN', 'Saint Helena, Ascension and Tristan da Cunha'],
201
+ ['SJM', 'Svalbard and Jan Mayen'],
202
+ ['SLB', 'Solomon Islands'],
203
+ ['SLE', 'Sierra Leone'],
204
+ ['SLV', 'El Salvador'],
205
+ ['SMR', 'San Marino'],
206
+ ['SOM', 'Somalia'],
207
+ ['SPM', 'Saint Pierre and Miquelon'],
208
+ ['SRB', 'Serbia'],
209
+ ['SSD', 'South Sudan'],
210
+ ['STP', 'Sao Tome and Principe'],
211
+ ['SUR', 'Suriname'],
212
+ ['SVK', 'Slovakia'],
213
+ ['SVN', 'Slovenia'],
214
+ ['SWE', 'Sweden'],
215
+ ['SWZ', 'Swaziland'],
216
+ ['SXM', 'Sint Maarten (Dutch part)'],
217
+ ['SYC', 'Seychelles'],
218
+ ['SYR', 'Syrian Arab Republic'],
219
+ ['TCA', 'Turks and Caicos Islands'],
220
+ ['TCD', 'Chad'],
221
+ ['TGO', 'Togo'],
222
+ ['THA', 'Thailand'],
223
+ ['TJK', 'Tajikistan'],
224
+ ['TKL', 'Tokelau'],
225
+ ['TKM', 'Turkmenistan'],
226
+ ['TLS', 'Timor-Leste'],
227
+ ['TON', 'Tonga'],
228
+ ['TTO', 'Trinidad and Tobago'],
229
+ ['TUN', 'Tunisia'],
230
+ ['TUR', 'Turkey'],
231
+ ['TUV', 'Tuvalu'],
232
+ ['TWN', 'Taiwan, Province of China'],
233
+ ['TZA', 'Tanzania, United Republic of'],
234
+ ['UGA', 'Uganda'],
235
+ ['UKR', 'Ukraine'],
236
+ ['UMI', 'United States Minor Outlying Islands'],
237
+ ['URY', 'Uruguay'],
238
+ ['USA', 'United States of America'],
239
+ ['UZB', 'Uzbekistan'],
240
+ ['VAT', 'Holy See'],
241
+ ['VCT', 'Saint Vincent and the Grenadines'],
242
+ ['VEN', 'Venezuela, Bolivarian Republic of'],
243
+ ['VGB', 'Virgin Islands, British'],
244
+ ['VIR', 'Virgin Islands, U.S.'],
245
+ ['VNM', 'Viet Nam'],
246
+ ['VUT', 'Vanuatu'],
247
+ ['WLF', 'Wallis and Futuna'],
248
+ ['WSM', 'Samoa'],
249
+ ['YEM', 'Yemen'],
250
+ ['ZAF', 'South Africa'],
251
+ ['ZMB', 'Zambia'],
252
+ ['ZWE', 'Zimbabwe'],
253
+ ]
254
+
255
+ def self.select_values
256
+ @select_values ||= VALUES.map {|a| a.reverse }.sort_by(&:first)
257
+ end
258
+
259
+ def self.valid?(code)
260
+ (@codes ||= select_values.map(&:last)).include?(code)
261
+ end
262
+
263
+ def self.[](code)
264
+ (@values ||= Hash[VALUES])[code]
265
+ end
266
+
267
+ def self.usa
268
+ 'USA'
269
+ end
270
+
271
+ def self.usa?(code)
272
+ usa == code
273
+ end
274
+
275
+ def self.non_usa_select_values
276
+ @non_us_select_values ||= select_values.reject {|name, code| usa?(code) }
277
+ end
278
+ end
@@ -0,0 +1,10 @@
1
+ class CountryValidator < ActiveModel::EachValidator
2
+ def validate_each(record, attribute, value)
3
+ if value.blank?
4
+ record.errors[attribute] << 'is required' unless options[:allow_blank] || options[:allow_nil]
5
+ return
6
+ end
7
+
8
+ record.errors[attribute] << (options[:message] || 'is not a valid country') unless Countries.valid?(value)
9
+ end
10
+ end
@@ -0,0 +1,88 @@
1
+ module DatabaseFunctionHelper
2
+ def self.select_function(*args)
3
+ obj = Object.new
4
+ obj.extend(DatabaseFunctionHelper)
5
+
6
+ obj.select_function(*args)
7
+ end
8
+
9
+ def select_function(*args)
10
+ options = args.last.is_a?(Hash) ? args.pop : {}
11
+
12
+ sql = [ 'SELECT', function_sql(*args) ].join(' ')
13
+ results = ActiveRecord::Base.connection.execute(sql)
14
+
15
+ if type = options[:one]
16
+ return nil unless results.first
17
+ return cast_one(type, results.first.values.first)
18
+ elsif type = options[:values]
19
+ return cast_values(type, results)
20
+ end
21
+
22
+ results
23
+ end
24
+
25
+ protected
26
+
27
+ def function_sql(*args)
28
+ function_name = "func_#{args.shift}" # add standard prefix
29
+ args_sql = to_args_sql(*args)
30
+ sql = [ function_name, '(', args_sql, ')' ].join
31
+ Rails.logger.debug sql
32
+
33
+ sql
34
+ end
35
+
36
+ def to_args_sql(*args)
37
+ args.collect do |a|
38
+ case a
39
+ when nil
40
+ 'NULL'
41
+ when true
42
+ "'t'"
43
+ when false
44
+ "'f'"
45
+ else
46
+ if a.is_a? Hash
47
+ [ to_args_sql(a.values.first), '::', a.keys.first.to_s ].join
48
+ elsif a.is_a? Array
49
+ "'{#{a.join(',')}}'"
50
+ else
51
+ "'#{a}'"
52
+ end
53
+ end
54
+ end.join(', ')
55
+ end
56
+
57
+ def cast_one(type, string)
58
+ return nil if string.nil?
59
+
60
+ case type
61
+ when :boolean
62
+ return string == 't'
63
+ when :date
64
+ return Date.parse(string)
65
+ when :datetime
66
+ return Time.parse(string)
67
+ when :decimal
68
+ return BigDecimal.new(string)
69
+ when :float
70
+ return string.to_f
71
+ when :integer
72
+ return string.to_i
73
+ when :time_of_day
74
+ return Tod::TimeOfDay.parse(string)
75
+ when :time_window
76
+ return TimeWindow.parse_tuple(string)
77
+ when :timestamp
78
+ return Time.parse(string)
79
+ end
80
+
81
+ string
82
+ end
83
+
84
+ def cast_values(type, results)
85
+ values = results.values.map(&:first)
86
+ values.collect {|val| cast_one(type, val) }
87
+ end
88
+ end