brick 1.0.13 → 1.0.14

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2c22e9b6dcc1ca819d7cdc6852def21d10e5c5c23f6fc7489b1fe5ae52b6c68e
4
- data.tar.gz: 2242f7c0045e294fc505a479054a43d7d4355a0f7b6bf8407122f6f426eea541
3
+ metadata.gz: '09600b354a3f70f8680f3dd7a9be9349e6666c013c09a7c9a0dc240e811344ee'
4
+ data.tar.gz: 0f6ec90f3d38338797a10ec4fc338fae6fdea5b9fddb376c2044fe719afaaa8b
5
5
  SHA512:
6
- metadata.gz: 6b42dcae433ac8c0fbc91dbf9952451548af6e72eadb466f98c8c6d084be7217df192aa6fc141a18d1e76bd25a551746cf155799045d66f88f41ede99b36b39e
7
- data.tar.gz: 7ab155441e2868af3fe0b2a5339ec6614c18ff9d641a076f678ef6baa7b943cad88c97443db3c70506206c54f2b754a1892490d977f3e714fb66c889fe107fa5
6
+ metadata.gz: 7189638a98c3899d49473a48638dce78da4ed109ed1d4a69185015f9b19428d658fa40ef0f70aa1652a478754b6c1b683a963424ec3e627c56e97b3c2528bba7
7
+ data.tar.gz: a843f0ec11b7e40bc4cf0a7387ab33e87edd4d9a36de1e24d10c899d969e148015da346fe7b7915f9ffd5a769818e8948de36beb1a368d38a6bb3ab3a97ca7c5
data/lib/brick/config.rb CHANGED
@@ -91,6 +91,14 @@ module Brick
91
91
  @mutex.synchronize { @model_descrips = descrips }
92
92
  end
93
93
 
94
+ def sti_namespace_prefixes
95
+ @mutex.synchronize { @sti_namespace_prefixes ||= {} }
96
+ end
97
+
98
+ def sti_namespace_prefixes=(prefixes)
99
+ @mutex.synchronize { @sti_namespace_prefixes = prefixes }
100
+ end
101
+
94
102
  def skip_database_views
95
103
  @mutex.synchronize { @skip_database_views }
96
104
  end
@@ -136,38 +136,67 @@ module ActiveRecord
136
136
 
137
137
  alias _brick_find_sti_class find_sti_class
138
138
  def find_sti_class(type_name)
139
- ::Brick.sti_models[type_name] = { base: self } unless type_name.blank?
140
- module_prefixes = type_name.split('::')
141
- module_prefixes.unshift('') unless module_prefixes.first.blank?
142
- candidate_file = Rails.root.join('app/models' + module_prefixes.map(&:underscore).join('/') + '.rb')
143
- if File.exists?(candidate_file)
144
- # Find this STI class normally
139
+ if ::Brick.sti_models.key?(type_name)
145
140
  _brick_find_sti_class(type_name)
146
141
  else
147
- # Build missing prefix modules if they don't yet exist
148
- this_module = Object
149
- module_prefixes[1..-2].each do |module_name|
150
- mod = if this_module.const_defined?(module_name)
151
- this_module.const_get(module_name)
152
- else
153
- this_module.const_set(module_name.to_sym, Module.new)
154
- end
142
+ # This auto-STI is more of a brute-force approach, building modules where needed
143
+ # The more graceful alternative is the overload of ActiveSupport::Dependencies#autoload_module! found below
144
+ ::Brick.sti_models[type_name] = { base: self } unless type_name.blank?
145
+ module_prefixes = type_name.split('::')
146
+ module_prefixes.unshift('') unless module_prefixes.first.blank?
147
+ module_name = module_prefixes[0..-2].join('::')
148
+ if ::Brick.config.sti_namespace_prefixes&.key?(module_name) ||
149
+ ::Brick.config.sti_namespace_prefixes&.key?(module_name[2..-1]) # Take off the leading '::' and see if this matches
150
+ _brick_find_sti_class(type_name)
151
+ elsif File.exists?(candidate_file = Rails.root.join('app/models' + module_prefixes.map(&:underscore).join('/') + '.rb'))
152
+ _brick_find_sti_class(type_name) # Find this STI class normally
153
+ else
154
+ # Build missing prefix modules if they don't yet exist
155
+ this_module = Object
156
+ module_prefixes[1..-2].each do |module_name|
157
+ mod = if this_module.const_defined?(module_name)
158
+ this_module.const_get(module_name)
159
+ else
160
+ this_module.const_set(module_name.to_sym, Module.new)
161
+ end
162
+ end
163
+ # Build STI subclass and place it into the namespace module
164
+ this_module.const_set(module_prefixes.last.to_sym, klass = Class.new(self))
165
+ klass
155
166
  end
156
- # Build missing prefix modules if they don't yet exist
157
- this_module.const_set(module_prefixes.last.to_sym, klass = Class.new(self))
158
- klass
159
167
  end
160
168
  end
161
169
  end
162
170
  end
163
171
  end
164
172
 
165
- # Object.class_exec do
173
+ module ActiveSupport::Dependencies
174
+ class << self
175
+ # %%% Probably a little more targeted than other approaches we've taken thusfar
176
+ # This happens before the whole parent check
177
+ alias _brick_autoload_module! autoload_module!
178
+ def autoload_module!(*args)
179
+ into, const_name, qualified_name, path_suffix = args
180
+ if (base_class = ::Brick.config.sti_namespace_prefixes&.fetch(into.name, nil)&.constantize)
181
+ ::Brick.sti_models[qualified_name] = { base: base_class }
182
+ # Build subclass and place it into the specially STI-namespaced module
183
+ into.const_set(const_name.to_sym, klass = Class.new(base_class))
184
+ # %%% used to also have: autoload_once_paths.include?(base_path) ||
185
+ autoloaded_constants << qualified_name unless autoloaded_constants.include?(qualified_name)
186
+ klass
187
+ else
188
+ _brick_autoload_module!(*args)
189
+ end
190
+ end
191
+ end
192
+ end
193
+
166
194
  class Object
167
195
  class << self
168
196
  alias _brick_const_missing const_missing
169
197
  def const_missing(*args)
170
- return Object.const_get(args.first) if Object.const_defined?(args.first)
198
+ return self.const_get(args.first) if self.const_defined?(args.first)
199
+ return Object.const_get(args.first) if Object.const_defined?(args.first) unless self == Object
171
200
 
172
201
  class_name = args.first.to_s
173
202
  # See if a file is there in the same way that ActiveSupport::Dependencies#load_missing_constant
@@ -175,43 +204,58 @@ class Object
175
204
  # that is, checking #qualified_name_for with: from_mod, const_name
176
205
  # If we want to support namespacing in the future, might have to utilise something like this:
177
206
  # path_suffix = ActiveSupport::Dependencies.qualified_name_for(Object, args.first).underscore
178
- # return Object._brick_const_missing(*args) if ActiveSupport::Dependencies.search_for_file(path_suffix)
207
+ # return self._brick_const_missing(*args) if ActiveSupport::Dependencies.search_for_file(path_suffix)
179
208
  # If the file really exists, go and snag it:
180
- return Object._brick_const_missing(*args) if ActiveSupport::Dependencies.search_for_file(class_name.underscore)
209
+ if !(is_found = ActiveSupport::Dependencies.search_for_file(class_name.underscore)) && (filepath = self.name&.split('::'))
210
+ filepath = (filepath[0..-2] + [class_name]).join('/').underscore + '.rb'
211
+ end
212
+ if is_found
213
+ return self._brick_const_missing(*args)
214
+ elsif ActiveSupport::Dependencies.search_for_file(filepath) # Last-ditch effort to pick this thing up before we fill in the gaps on our own
215
+ my_const = parent.const_missing(class_name) # ends up having: MyModule::MyClass
216
+ return my_const
217
+ end
181
218
 
182
219
  relations = ::Brick.instance_variable_get(:@relations)[ActiveRecord::Base.connection_pool.object_id] || {}
183
220
  is_controllers_enabled = ::Brick.enable_controllers? || (ENV['RAILS_ENV'] || ENV['RACK_ENV']) == 'development'
184
221
  result = if is_controllers_enabled && class_name.end_with?('Controller') && (plural_class_name = class_name[0..-11]).length.positive?
185
- # Otherwise now it's up to us to fill in the gaps
186
- if (model = ActiveSupport::Inflector.singularize(plural_class_name).constantize)
187
- # if it's a controller and no match or a model doesn't really use the same table name, eager load all models and try to find a model class of the right name.
188
- build_controller(class_name, plural_class_name, model, relations)
189
- end
190
- elsif ::Brick.enable_models?
191
- # See if a file is there in the same way that ActiveSupport::Dependencies#load_missing_constant
192
- # checks for it in ~/.rvm/gems/ruby-2.7.5/gems/activesupport-5.2.6.2/lib/active_support/dependencies.rb
193
- plural_class_name = ActiveSupport::Inflector.pluralize(model_name = class_name)
194
- singular_table_name = ActiveSupport::Inflector.underscore(model_name)
195
-
196
- # Adjust for STI if we know of a base model for the requested model name
197
- table_name = if (base_model = ::Brick.sti_models[model_name]&.fetch(:base, nil))
198
- base_model.table_name
199
- else
200
- ActiveSupport::Inflector.pluralize(singular_table_name)
201
- end
202
-
203
- # Maybe, just maybe there's a database table that will satisfy this need
204
- if (matching = [table_name, singular_table_name, plural_class_name, model_name].find { |m| relations.key?(m) })
205
- build_model(model_name, singular_table_name, table_name, relations, matching)
206
- end
207
- end
222
+ # Otherwise now it's up to us to fill in the gaps
223
+ if (model = ActiveSupport::Inflector.singularize(plural_class_name).constantize)
224
+ # if it's a controller and no match or a model doesn't really use the same table name, eager load all models and try to find a model class of the right name.
225
+ build_controller(class_name, plural_class_name, model, relations)
226
+ end
227
+ elsif ::Brick.enable_models?
228
+ # See if a file is there in the same way that ActiveSupport::Dependencies#load_missing_constant
229
+ # checks for it in ~/.rvm/gems/ruby-2.7.5/gems/activesupport-5.2.6.2/lib/active_support/dependencies.rb
230
+ plural_class_name = ActiveSupport::Inflector.pluralize(model_name = class_name)
231
+ singular_table_name = ActiveSupport::Inflector.underscore(model_name)
232
+
233
+ # Adjust for STI if we know of a base model for the requested model name
234
+ table_name = if (base_model = ::Brick.sti_models[model_name]&.fetch(:base, nil))
235
+ base_model.table_name
236
+ else
237
+ ActiveSupport::Inflector.pluralize(singular_table_name)
238
+ end
239
+
240
+ # Maybe, just maybe there's a database table that will satisfy this need
241
+ if (matching = [table_name, singular_table_name, plural_class_name, model_name].find { |m| relations.key?(m) })
242
+ build_model(model_name, singular_table_name, table_name, relations, matching)
243
+ end
244
+ end
208
245
  if result
209
246
  built_class, code = result
210
247
  puts "\n#{code}"
211
248
  built_class
249
+ elsif ::Brick.config.sti_namespace_prefixes&.key?(class_name)
250
+ # binding.pry
251
+ # module_prefixes = type_name.split('::')
252
+ # path = self.name.split('::')[0..-2] + []
253
+ # module_prefixes.unshift('') unless module_prefixes.first.blank?
254
+ # candidate_file = Rails.root.join('app/models' + module_prefixes.map(&:underscore).join('/') + '.rb')
255
+ self._brick_const_missing(*args)
212
256
  else
213
257
  puts "MISSING! #{args.inspect} #{table_name}"
214
- Object._brick_const_missing(*args)
258
+ self._brick_const_missing(*args)
215
259
  end
216
260
  end
217
261
 
@@ -223,7 +267,8 @@ class Object
223
267
 
224
268
  # Are they trying to use a pluralised class name such as "Employees" instead of "Employee"?
225
269
  if table_name == singular_table_name && !ActiveSupport::Inflector.inflections.uncountable.include?(table_name)
226
- raise NameError.new("Class name for a model that references table \"#{matching}\" should be \"#{ActiveSupport::Inflector.singularize(model_name)}\".")
270
+ puts "Warning: Class name for a model that references table \"#{matching}\" should be \"#{ActiveSupport::Inflector.singularize(model_name)}\"."
271
+ return
227
272
  end
228
273
  if (base_model = ::Brick.sti_models[model_name]&.fetch(:base, nil))
229
274
  is_sti = true
@@ -5,7 +5,7 @@ module Brick
5
5
  module VERSION
6
6
  MAJOR = 1
7
7
  MINOR = 0
8
- TINY = 13
8
+ TINY = 14
9
9
 
10
10
  # PRE is nil unless it's a pre-release (beta, RC, etc.)
11
11
  PRE = nil
data/lib/brick.rb CHANGED
@@ -228,6 +228,13 @@ module Brick
228
228
  Brick.config.model_descrips = descrips
229
229
  end
230
230
 
231
+ # Module prefixes to build out and associate with specific base STI models
232
+ # @api public
233
+ def sti_namespace_prefixes=(snp)
234
+ Brick.config.sti_namespace_prefixes = snp
235
+ end
236
+
237
+
231
238
  # Returns Brick's `::Gem::Version`, convenient for comparisons. This is
232
239
  # recommended over `::Brick::VERSION::STRING`.
233
240
  #
@@ -135,6 +135,11 @@ module Brick
135
135
  # # user, then you can use model_descrips like this, putting expressions with property references in square brackets:
136
136
  # Brick.model_descrips = { 'User' => '[profile.firstname] [profile.lastname]' }
137
137
 
138
+ # # Module prefixes to be built out and associated when new subclasses are requested for specific base STI models
139
+ # # (If this setting exists then only these subclasses will be honoured, and other requested )
140
+ # # The prefixed :: here on the sample module name LetterTemplates is optional. Used here for clarity.
141
+ # Brick.sti_namespace_prefixes = { '::LetterTemplates' => 'LetterTemplate' }
142
+
138
143
  # # If a default route is not supplied, Brick attempts to find the most \"central\" table and wires up the default
139
144
  # # route to go to the :index action for what would be a controller for that table. You can specify any controller
140
145
  # # name and action you wish in order to override this and have that be the default route when none other has been
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: brick
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.13
4
+ version: 1.0.14
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lorin Thwaits