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 +4 -4
- data/lib/brick/config.rb +8 -0
- data/lib/brick/extensions.rb +91 -46
- data/lib/brick/version_number.rb +1 -1
- data/lib/brick.rb +7 -0
- data/lib/generators/brick/install_generator.rb +5 -0
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '09600b354a3f70f8680f3dd7a9be9349e6666c013c09a7c9a0dc240e811344ee'
|
4
|
+
data.tar.gz: 0f6ec90f3d38338797a10ec4fc338fae6fdea5b9fddb376c2044fe719afaaa8b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
data/lib/brick/extensions.rb
CHANGED
@@ -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
|
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
|
-
#
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
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
|
-
|
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
|
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
|
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
|
-
|
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
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
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
|
-
|
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
|
-
|
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
|
data/lib/brick/version_number.rb
CHANGED
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
|