k_domain 0.0.14 → 0.0.23

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 (59) hide show
  1. checksums.yaml +4 -4
  2. data/.builders/config/_.rb +3 -0
  3. data/.builders/setup.rb +30 -0
  4. data/.gitignore +1 -0
  5. data/.rubocop.yml +4 -3
  6. data/Gemfile +1 -1
  7. data/Guardfile +1 -0
  8. data/README.md +15 -0
  9. data/STORIES.md +35 -6
  10. data/k_domain.gemspec +1 -1
  11. data/lib/k_domain/domain_model/load.rb +8 -2
  12. data/lib/k_domain/domain_model/transform.rb +34 -51
  13. data/lib/k_domain/domain_model/transform_steps/_.rb +8 -6
  14. data/lib/k_domain/domain_model/transform_steps/step.rb +47 -2
  15. data/lib/k_domain/domain_model/transform_steps/{step1_attach_db_schema.rb → step1_db_schema.rb} +2 -1
  16. data/lib/k_domain/domain_model/transform_steps/{step5_attach_dictionary.rb → step20_dictionary.rb} +7 -3
  17. data/lib/k_domain/domain_model/transform_steps/step2_domain_models.rb +123 -0
  18. data/lib/k_domain/domain_model/transform_steps/{step8_locate_rails_models.rb → step4_rails_resource_models.rb} +4 -4
  19. data/lib/k_domain/domain_model/transform_steps/step5_rails_resource_routes.rb +36 -0
  20. data/lib/k_domain/domain_model/transform_steps/step6_rails_structure_models.rb +90 -0
  21. data/lib/k_domain/domain_model/transform_steps/step7_rails_structure_controllers.rb +109 -0
  22. data/lib/k_domain/domain_model/transform_steps/{step3_attach_columns.rb → step8_domain_columns.rb} +40 -73
  23. data/lib/k_domain/rails_code_extractor/_.rb +5 -0
  24. data/lib/k_domain/rails_code_extractor/extract_controller.rb +59 -0
  25. data/lib/k_domain/rails_code_extractor/extract_model.rb +69 -0
  26. data/lib/k_domain/rails_code_extractor/shim_loader.rb +30 -0
  27. data/lib/k_domain/raw_db_schema/load.rb +8 -2
  28. data/lib/k_domain/raw_db_schema/transform.rb +9 -8
  29. data/lib/k_domain/schemas/_.rb +3 -2
  30. data/lib/k_domain/schemas/database.rb +86 -0
  31. data/lib/k_domain/schemas/domain/erd_file.rb +2 -0
  32. data/lib/k_domain/schemas/domain.rb +154 -0
  33. data/lib/k_domain/schemas/domain_model.rb +6 -5
  34. data/lib/k_domain/schemas/rails_resource.rb +43 -6
  35. data/lib/k_domain/schemas/rails_structure.rb +172 -0
  36. data/lib/k_domain/version.rb +1 -1
  37. data/lib/k_domain.rb +2 -0
  38. data/templates/custom/action_controller.rb +36 -0
  39. data/templates/custom/controller_interceptors.rb +78 -0
  40. data/templates/custom/model_interceptors.rb +71 -0
  41. data/templates/load_schema.rb +7 -0
  42. data/templates/old_printspeek_schema copy.rb +231 -0
  43. data/templates/old_printspeek_schema.rb +233 -0
  44. data/templates/rails/action_controller.rb +301 -0
  45. data/templates/rails/active_record.rb +348 -0
  46. data/templates/ruby_code_extractor/attach_class_info.rb +13 -0
  47. data/templates/ruby_code_extractor/behaviour_accessors.rb +39 -0
  48. data/templates/simple/controller_interceptors.rb +2 -0
  49. metadata +30 -17
  50. data/lib/k_domain/domain_model/transform_steps/step2_attach_models.rb +0 -62
  51. data/lib/k_domain/domain_model/transform_steps/step4_attach_erd_files.rb +0 -454
  52. data/lib/k_domain/schemas/database/_.rb +0 -7
  53. data/lib/k_domain/schemas/database/foreign_key.rb +0 -14
  54. data/lib/k_domain/schemas/database/index.rb +0 -14
  55. data/lib/k_domain/schemas/database/schema.rb +0 -31
  56. data/lib/k_domain/schemas/database/table.rb +0 -32
  57. data/lib/k_domain/schemas/domain/domain.rb +0 -11
  58. data/lib/k_domain/schemas/domain/models/column.rb +0 -49
  59. data/lib/k_domain/schemas/domain/models/model.rb +0 -111
@@ -0,0 +1,301 @@
1
+ # Implement data capture methods for the Rails Action Controller class
2
+ #
3
+ # This Shim will intercept any DSL methods and convert their paramaters into a data hash
4
+ module ActionController
5
+ extend RubyCodeExtractor::AttachClassInfo
6
+
7
+ class Base
8
+ extend RubyCodeExtractor::BehaviourAccessors
9
+
10
+ def self.singleton_class
11
+ Class.new do
12
+ def send(*_p, **_o); end
13
+ end.new
14
+ end
15
+
16
+ def self.class_info
17
+ return ActionController.class_info if ActionController.class_info
18
+
19
+ ActionController.class_info = {
20
+ class_name: name
21
+ }
22
+ end
23
+
24
+ def self.after_action(name, **opts)
25
+ add(:after_action, {
26
+ name: name,
27
+ opts: opts
28
+ })
29
+ end
30
+
31
+ def self.around_action(name, **opts)
32
+ add(:around_action, {
33
+ name: name,
34
+ opts: opts
35
+ })
36
+ end
37
+
38
+ def self.before_action(name, **opts)
39
+ add(:before_action, {
40
+ name: name,
41
+ opts: opts
42
+ })
43
+ end
44
+
45
+ def self.prepend_before_action(name, **opts)
46
+ add(:prepend_before_action, {
47
+ name: name,
48
+ opts: opts
49
+ })
50
+ end
51
+
52
+ def self.skip_before_action(name, **opts)
53
+ add(:skip_before_action, {
54
+ name: name,
55
+ opts: opts
56
+ })
57
+ end
58
+
59
+ def self.before_filter(name, **opts)
60
+ add(:before_filter, {
61
+ name: name,
62
+ opts: opts
63
+ })
64
+ end
65
+
66
+ def self.skip_before_filter(name, **opts)
67
+ add(:skip_before_filter, {
68
+ name: name,
69
+ opts: opts
70
+ })
71
+ end
72
+
73
+ def self.layout(name, **opts)
74
+ set(:layout, {
75
+ name: name,
76
+ opts: opts
77
+ })
78
+ end
79
+
80
+ def self.rescue_from(type)#, &block)
81
+ # block_source = nil
82
+ # block_source = lambda_source(block, 'default_scope') if block_given?
83
+
84
+ add(:rescue_from, {
85
+ type: type#,
86
+ # block: block_source
87
+ })
88
+ end
89
+
90
+ # TODO: https://apidock.com/rails/ActionController/Helpers/ClassMethods/helper_method (MAYBE DEPRECATED?)
91
+ def self.helper_method(*names)
92
+ add(:helper_method, {
93
+ names: names
94
+ })
95
+ end
96
+
97
+ # TODO: https://apidock.com/rails/ActionController/Helpers/ClassMethods/helper
98
+ def self.helper(name)
99
+ add(:helper, {
100
+ name: name
101
+ })
102
+ end
103
+
104
+ def self.http_basic_authenticate_with(**opts)
105
+ set(:http_basic_authenticate_with, {
106
+ opts: opts
107
+ })
108
+ end
109
+
110
+ def self.protect_from_forgery(**opts)
111
+ set(:protect_from_forgery, {
112
+ opts: opts
113
+ })
114
+ end
115
+ end
116
+ end
117
+
118
+ # after_action
119
+ # after_filter
120
+ # append_after_action
121
+ # append_after_filter
122
+ # append_around_action
123
+ # append_around_filter
124
+ # append_before_action
125
+ # append_before_filter
126
+ # append_view_path
127
+ # around_action
128
+ # around_filter
129
+ # before_action
130
+ # before_filter
131
+ # controller_name
132
+ # controller_path
133
+ # helper
134
+ # helper_attr
135
+ # helper_method
136
+ # helpers
137
+ # helpers_path
138
+ # hide_action
139
+ # http_basic_authenticate_with
140
+ # layout
141
+ # prepend_after_action
142
+ # prepend_after_filter
143
+ # prepend_around_action
144
+ # prepend_around_filter
145
+ # prepend_before_action
146
+ # prepend_before_filter
147
+ # prepend_view_path
148
+ # protect_from_forgery
149
+ # protected_instance_variables
150
+ # rescue_from
151
+ # reset_callbacks
152
+ # skip_action_callback
153
+ # skip_after_action
154
+ # skip_after_filter
155
+ # skip_around_action
156
+ # skip_around_filter
157
+ # skip_before_action
158
+ # skip_before_filter
159
+ # skip_callback
160
+ # skip_filter
161
+
162
+ # METHOD LIST - Just from running self.class.methods - Object.methods on a running controller
163
+ # action
164
+ # action_methods
165
+ # add_flash_types
166
+ # after_action
167
+ # after_filter
168
+ # all_helpers_from_path
169
+ # allow_forgery_protection
170
+ # allow_forgery_protection=
171
+ # append_after_action
172
+ # append_after_filter
173
+ # append_around_action
174
+ # append_around_filter
175
+ # append_before_action
176
+ # append_before_filter
177
+ # append_view_path
178
+ # around_action
179
+ # around_filter
180
+ # asset_host
181
+ # asset_host=
182
+ # assets_dir
183
+ # assets_dir=
184
+ # before_action
185
+ # before_filter
186
+ # cache_store
187
+ # cache_store=
188
+ # call
189
+ # clear_action_methods!
190
+ # clear_helpers
191
+ # clear_respond_to
192
+ # config
193
+ # config_accessor
194
+ # configure
195
+ # controller_name
196
+ # controller_path
197
+ # default_asset_host_protocol
198
+ # default_asset_host_protocol=
199
+ # default_static_extension
200
+ # default_static_extension=
201
+ # default_url_options
202
+ # default_url_options=
203
+ # default_url_options?
204
+ # define_callbacks
205
+ # devise_group
206
+ # direct_descendants
207
+ # etag
208
+ # etag_with_template_digest
209
+ # etag_with_template_digest=
210
+ # etag_with_template_digest?
211
+ # etaggers
212
+ # etaggers=
213
+ # etaggers?
214
+ # force_ssl
215
+ # forgery_protection_strategy
216
+ # forgery_protection_strategy=
217
+ # get_callbacks
218
+ # helper
219
+ # helper_attr
220
+ # helper_method
221
+ # helpers
222
+ # helpers_path
223
+ # helpers_path=
224
+ # helpers_path?
225
+ # hidden_actions
226
+ # hidden_actions=
227
+ # hidden_actions?
228
+ # hide_action
229
+ # http_basic_authenticate_with
230
+ # include_all_helpers
231
+ # include_all_helpers=
232
+ # include_all_helpers?
233
+ # inherited
234
+ # internal_methods
235
+ # javascripts_dir
236
+ # javascripts_dir=
237
+ # layout
238
+ # log_process_action
239
+ # log_warning_on_csrf_failure
240
+ # log_warning_on_csrf_failure=
241
+ # logger
242
+ # logger=
243
+ # method_added
244
+ # middleware
245
+ # middleware_stack
246
+ # middleware_stack=
247
+ # middleware_stack?
248
+ # mimes_for_respond_to
249
+ # mimes_for_respond_to=
250
+ # mimes_for_respond_to?
251
+ # modules_for_helpers
252
+ # normalize_callback_params
253
+ # perform_caching
254
+ # perform_caching=
255
+ # prepend_after_action
256
+ # prepend_after_filter
257
+ # prepend_around_action
258
+ # prepend_around_filter
259
+ # prepend_before_action
260
+ # prepend_before_filter
261
+ # prepend_view_path
262
+ # protect_from_forgery
263
+ # protected_instance_variables
264
+ # relative_url_root
265
+ # relative_url_root=
266
+ # request_forgery_protection_token
267
+ # request_forgery_protection_token=
268
+ # rescue_from
269
+ # rescue_handlers
270
+ # rescue_handlers=
271
+ # rescue_handlers?
272
+ # reset_callbacks
273
+ # respond_to
274
+ # responder
275
+ # responder=
276
+ # responder?
277
+ # responders
278
+ # set_callback
279
+ # set_callbacks
280
+ # skip_action_callback
281
+ # skip_after_action
282
+ # skip_after_filter
283
+ # skip_around_action
284
+ # skip_around_filter
285
+ # skip_before_action
286
+ # skip_before_filter
287
+ # skip_callback
288
+ # skip_filter
289
+ # stylesheets_dir
290
+ # stylesheets_dir=
291
+ # supports_path?
292
+ # use
293
+ # use_renderer
294
+ # use_renderers
295
+ # view_cache_dependency
296
+ # view_context_class
297
+ # view_paths
298
+ # view_paths=
299
+ # visible_action?
300
+ # without_modules
301
+ # wrap_parameters
@@ -0,0 +1,348 @@
1
+ module ActiveRecord
2
+ extend RubyCodeExtractor::AttachClassInfo
3
+
4
+ class Base
5
+ extend RubyCodeExtractor::BehaviourAccessors
6
+
7
+ def self.singleton_class
8
+ Class.new do
9
+ def send(*_p, **_o); end
10
+ end.new
11
+ end
12
+
13
+ def self.class_info
14
+ return ActiveRecord.class_info if ActiveRecord.class_info
15
+
16
+ ActiveRecord.class_info = {
17
+ class_name: name
18
+ }
19
+ end
20
+
21
+ # -------------------------
22
+ # Intercept methods
23
+ # -------------------------
24
+
25
+ def self.clear_active_connections!; end
26
+
27
+ # -------------------------
28
+ # Behaviour storage methods
29
+ # -------------------------
30
+
31
+ # examples:
32
+ # enum status: { active: 0, archived: 1 }
33
+ # enum status: [:active, :archived]
34
+ # enum status: [:active, :archived], _suffix: true
35
+ # enum comments_status: [:active, :inactive], _prefix: :comments
36
+ def self.enum(**opts)
37
+ add(:enum, opts)
38
+ end
39
+
40
+ # def self.attr_accessor(*args)
41
+ # args.each do |arg|
42
+ # self.class_eval("def #{arg};@#{arg};end")
43
+ # self.class_eval("def #{arg}=(val);@#{arg}=val;end")
44
+ # end
45
+ # end
46
+ # def self.attr_reader(*args)
47
+ # args.each do |arg|
48
+ # self.class_eval("def #{arg};@#{arg};end")
49
+ # end
50
+ # end
51
+ # def self.attr_writer(*args)
52
+ # args.each do |arg|
53
+ # self.class_eval("def #{arg};@#{arg};end")
54
+ # self.class_eval("def #{arg}=(val);@#{arg}=val;end")
55
+ # end
56
+ # end
57
+
58
+ def self.attr_accessor(*names)
59
+ super(*names)
60
+ add(:attr_accessor, names)
61
+ end
62
+
63
+ def self.attr_reader(*names)
64
+ super(*names)
65
+ add(:attr_reader, names)
66
+ end
67
+
68
+ def self.attr_writer(*names)
69
+ super(*names)
70
+ add(:attr_writer, names)
71
+ end
72
+
73
+ def self.lambda_source(a_lambda, prefix = nil)
74
+ return nil unless a_lambda
75
+
76
+ puts 'NOT A LAMBDA' unless a_lambda.is_a?(Proc)
77
+
78
+ result = a_lambda&.source&.strip
79
+ result = result&.delete_prefix(prefix) if prefix
80
+ result&.strip
81
+ end
82
+
83
+ # examples
84
+ # default_scope where(:published => true) # NOT supported
85
+ # default_scope { where(:published_at => Time.now - 1.week) }
86
+ # default_scope -> { order(:external_updated_at) }
87
+ # default_scope -> { where(:published => true) }, all_queries: true
88
+ def self.default_scope(**opts, &block)
89
+ block_source = nil
90
+ block_source = lambda_source(block, 'default_scope') if block_given?
91
+
92
+ set(:default_scope, opts.merge(block: block_source))
93
+ end
94
+
95
+ # examples
96
+ # scope :red, where(:color => 'red') # NOT SUPPORTED
97
+ # scope :dry_clean_only, joins(:washing_instructions).where('washing_instructions.dry_clean_only = ?', true) # NOT SUPPORTED
98
+ #
99
+ def self.scope(name, on_the_lamb = nil, **opts)
100
+ lamb_source = lambda_source(on_the_lamb, "scope :#{name},")
101
+
102
+ add(:scopes, {
103
+ name: name,
104
+ opts: opts,
105
+ block: lamb_source
106
+ })
107
+ end
108
+
109
+ def self.belongs_to(name, on_the_lamb = nil, **opts)
110
+ lamb_source = lambda_source(on_the_lamb, "belongs_to :#{name},")
111
+
112
+ value = {
113
+ name: name,
114
+ opts: opts,
115
+ block: lamb_source
116
+ }
117
+
118
+ value[:opts][:foreign_key] = "#{name}_id" unless value[:opts][:foreign_key]
119
+
120
+ add(:belongs_to, value)
121
+ end
122
+
123
+ def self.has_many(name, on_the_lamb = nil, **opts)
124
+ lamb_source = lambda_source(on_the_lamb, "has_many :#{name},")
125
+
126
+ add(:has_many, {
127
+ name: name,
128
+ opts: opts,
129
+ block: lamb_source
130
+ })
131
+ end
132
+
133
+ def self.has_one(name, on_the_lamb = nil, **opts)
134
+ lamb_source = lambda_source(on_the_lamb, "has_one :#{name},")
135
+
136
+ add(:has_one, {
137
+ name: name,
138
+ opts: opts,
139
+ block: lamb_source
140
+ })
141
+ end
142
+
143
+ def self.has_and_belongs_to_many(name, on_the_lamb = nil, **opts)
144
+ lamb_source = lambda_source(on_the_lamb, "has_and_belongs_to_many :#{name},")
145
+
146
+ add(:has_and_belongs_to_many, {
147
+ name: name,
148
+ opts: opts,
149
+ block: lamb_source
150
+ })
151
+ end
152
+
153
+ def self.validate(*names, **opts, &block)
154
+ block_source = nil
155
+ block_source = lambda_source(block, 'validate') if block_given?
156
+
157
+ add(:validate, {
158
+ names: names,
159
+ opts: opts,
160
+ block: block_source
161
+ })
162
+ end
163
+
164
+ def self.validates(name, **opts)
165
+ add(:validates, {
166
+ name: name,
167
+ opts: opts
168
+ })
169
+ end
170
+
171
+ def self.alias_attribute(left, right)
172
+ add(:alias_attribute, {
173
+ left: left,
174
+ right: right
175
+ })
176
+ end
177
+
178
+ def self.before_create(name)
179
+ add(:before_create, {
180
+ name: name
181
+ })
182
+ end
183
+
184
+ def self.before_save(name)
185
+ add(:before_save, {
186
+ name: name
187
+ })
188
+ end
189
+
190
+ def self.before_destroy(name)
191
+ add(:before_destroy, {
192
+ name: name
193
+ })
194
+ end
195
+
196
+ def self.before_validation(name = nil, &block)
197
+ block_source = nil
198
+ block_source = lambda_source(block, 'before_validation') if block_given?
199
+
200
+ add(:before_validation, {
201
+ name: name,
202
+ block: block_source
203
+ })
204
+ end
205
+
206
+ def self.after_create(name)
207
+ add(:after_create, {
208
+ name: name
209
+ })
210
+ end
211
+
212
+ def self.after_save(name)
213
+ add(:after_save, {
214
+ name: name
215
+ })
216
+ end
217
+
218
+ def self.after_destroy(name = nil, &block)
219
+ block_source = nil
220
+ block_source = lambda_source(block, 'after_destroy') if block_given?
221
+
222
+ add(:after_destroy, {
223
+ name: name,
224
+ block: block_source
225
+ })
226
+ end
227
+
228
+ def self.after_commit(name)
229
+ add(:after_commit, {
230
+ name: name
231
+ })
232
+ end
233
+
234
+ def self.accepts_nested_attributes_for(name, **opts)
235
+ add(:accepts_nested_attributes_for, {
236
+ name: name,
237
+ opts: opts
238
+ })
239
+ end
240
+
241
+ def self.has_secure_token(name)
242
+ add(:has_secure_token, {
243
+ name: name
244
+ })
245
+ end
246
+
247
+ # CAN THESE BE AUTOMATED LIKE INCLUDE MODULES
248
+ def self.establish_connection(connection)
249
+ class_info[:establish_connection] = connection
250
+ end
251
+
252
+ def self.store_accessor(*names)
253
+ class_info[:store_accessor] = *names
254
+ end
255
+
256
+ def self.table_name=(table_name)
257
+ class_info[:table_name] = table_name
258
+ end
259
+
260
+ def self.primary_key=(primary_key)
261
+ class_info[:primary_key] = primary_key
262
+ end
263
+
264
+ def self.require(require)
265
+ add(:require, require)
266
+ end
267
+
268
+ def self.devise(*names)
269
+ add(:devise, names)
270
+ end
271
+
272
+ def self.pg_search_scope(name, **opts)
273
+ custom_set(:pg_search_scope, {
274
+ name: name,
275
+ opts: opts
276
+ })
277
+ end
278
+
279
+ def self.acts_as_readable(**opts)
280
+ custom_set(:acts_as_readable, {
281
+ opts: opts
282
+ })
283
+ end
284
+
285
+ def self.acts_as_reader
286
+ custom_set(:acts_as_reader, {})
287
+ end
288
+
289
+ def self.acts_as_commentable
290
+ custom_set(:acts_as_commentable, {})
291
+ end
292
+
293
+ def self.acts_as_list(**opts)
294
+ custom_set(:acts_as_list, {
295
+ opts: opts
296
+ })
297
+ end
298
+
299
+ def self.has_paper_trail
300
+ custom_set(:has_paper_trail)
301
+ end
302
+
303
+ def self.validates_uniqueness_of(name, **opts)
304
+ custom_set(:validates_uniqueness_of, {
305
+ name: name,
306
+ opts: opts
307
+ })
308
+ end
309
+
310
+ def self.validates_presence_of(name, **opts)
311
+ custom_set(:validates_presence_of, {
312
+ name: name,
313
+ opts: opts
314
+ })
315
+ end
316
+
317
+ def self.validates_length_of(name, **opts)
318
+ custom_set(:validates_length_of, {
319
+ name: name,
320
+ opts: opts
321
+ })
322
+ end
323
+
324
+ def self.attr_encrypted(name, **opts)
325
+ custom_set(:attr_encrypted, {
326
+ name: name,
327
+ opts: opts
328
+ })
329
+ end
330
+
331
+ def self.validates_confirmation_of(name, **opts)
332
+ custom_set(:validates_confirmation_of, {
333
+ name: name,
334
+ opts: opts
335
+ })
336
+ end
337
+
338
+ def self.with_options(opts, &block)
339
+ block_source = nil
340
+ block_source = lambda_source(block) if block_given?
341
+
342
+ custom_add(:with_options, {
343
+ opts: opts,
344
+ block: block_source
345
+ })
346
+ end
347
+ end
348
+ end
@@ -0,0 +1,13 @@
1
+ module RubyCodeExtractor
2
+ # Class Info hash that contains the class name and any other key/values
3
+ # that could be useful when capturing Class information.
4
+ module AttachClassInfo
5
+ def class_info
6
+ @class_info ||= nil
7
+ end
8
+
9
+ def class_info=(value)
10
+ @class_info = value
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,39 @@
1
+ module RubyCodeExtractor
2
+ # When you intercept a method call, you can persist the captured paramaters
3
+ # into a Hash, the Hash Key should be the method name and the value should
4
+ # be a Hash with captured values.
5
+ #
6
+ # Use set/add for standard Rails DSL methods
7
+ # Use custom_set/custom_add for non standard or 3rd party GEM methods
8
+ module BehaviourAccessors
9
+ def set(key, value)
10
+ class_info[key] = class_info[key] || {}
11
+ class_info[key] = value
12
+ end
13
+
14
+ def add(key, value)
15
+ class_info[key] = class_info[key] || []
16
+ if value.is_a?(Array)
17
+ class_info[key] = class_info[key] + value
18
+ else
19
+ class_info[key] << value
20
+ end
21
+ end
22
+
23
+ def custom_set(key, value = {})
24
+ class_info[:custom] = {} unless class_info[:custom]
25
+ class_info[:custom][key] = class_info[:custom][key] || {}
26
+ class_info[:custom][key] = value
27
+ end
28
+
29
+ def custom_add(key, value)
30
+ class_info[:custom] = {} unless class_info[:custom]
31
+ class_info[:custom][key] = class_info[:custom][key] || []
32
+ if value.is_a?(Array)
33
+ class_info[:custom][key] = class_info[:custom][key] + value
34
+ else
35
+ class_info[:custom][key] << value
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,2 @@
1
+ class ApplicationController < ActionController::Base
2
+ end