brick 1.0.13 → 1.0.14

Sign up to get free protection for your applications and to get access to all the features.
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