brick 1.0.149 → 1.0.151
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/brick/extensions.rb +111 -18
- data/lib/brick/frameworks/rails/engine.rb +9 -7
- data/lib/brick/version_number.rb +1 -1
- data/lib/brick.rb +22 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1d8abfeb02b561a0ac8214de3c4791992947cab9f288f9f57c816a883dc4592a
|
4
|
+
data.tar.gz: 1ec0f9d11eea9b1741e454ac04aa2c51380a0d9676f4e84a5de2419d3ef751bd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 758e2ab6e10589689abdb77df64731e3df2fff341998e8f815bd5f180a73df89fb1282155a9520cc43102a49b1f7283114c02146329161e2324fc2fa79c6048e
|
7
|
+
data.tar.gz: 9a77d3d4318943225427c59e676c4a067c95a22351eaea88ed14bbc6da60ee834498117704bc0fe1dd493f6e10ab65a27db4bff3b060440f4e7dfaf3b31ad184
|
data/lib/brick/extensions.rb
CHANGED
@@ -1528,12 +1528,12 @@ class Object
|
|
1528
1528
|
# end
|
1529
1529
|
end
|
1530
1530
|
|
1531
|
-
# Enable Turbo Stream if possible -- equivalent of: broadcasts_to ->(comment) { :comments }
|
1532
|
-
if Object.const_defined?(:ApplicationCable) && Object.const_defined?(:Turbo) && Turbo.const_defined?(:Broadcastable) && respond_to?(:broadcasts_to)
|
1533
|
-
|
1534
|
-
|
1535
|
-
|
1536
|
-
end
|
1531
|
+
# # %%% Enable Turbo Stream if possible -- equivalent of: broadcasts_to ->(comment) { :comments }
|
1532
|
+
# if Object.const_defined?(:ApplicationCable) && Object.const_defined?(:Turbo) && Turbo.const_defined?(:Broadcastable) && respond_to?(:broadcasts_to)
|
1533
|
+
# relation[:broadcasts] = true
|
1534
|
+
# self.broadcasts_to ->(model) { (model&.class&.name || chosen_name).underscore.pluralize.to_sym }
|
1535
|
+
# code << " broadcasts_to ->(#{chosen_name}) { #{chosen_name}&.class&.name&.underscore&.pluralize&.to_sym }\n"
|
1536
|
+
# end
|
1537
1537
|
end # class definition
|
1538
1538
|
# Having this separate -- will this now work out better?
|
1539
1539
|
built_model.class_exec do
|
@@ -2155,13 +2155,16 @@ class Object
|
|
2155
2155
|
::Brick.set_db_schema(params)
|
2156
2156
|
if request.format == :csv # Importing CSV?
|
2157
2157
|
require 'csv'
|
2158
|
+
|
2158
2159
|
# See if internally it's likely a TSV file (tab-separated)
|
2159
|
-
|
2160
|
-
|
2160
|
+
likely_separator = Hash.new { |h, k| h[k] = 0 }
|
2161
|
+
request.body.readline # Expect first row to have column headers
|
2162
|
+
5.times { ::Brick._find_csv_separator(request.body, likely_separator) unless request.body.eof? }
|
2161
2163
|
request.body.rewind
|
2162
|
-
separator = "\t" if
|
2163
|
-
|
2164
|
-
|
2164
|
+
separator = "\t" if likely_separator["\t"] > likely_separator[',']
|
2165
|
+
|
2166
|
+
result = model.df_import(CSV.parse(request.body, **{ col_sep: separator || :auto }), model.brick_import_template)
|
2167
|
+
render inline: result.to_json, content_type: request.format
|
2165
2168
|
return
|
2166
2169
|
# elsif request.format == :js # Asking for JSON?
|
2167
2170
|
# render inline: model.df_export(true).to_json, content_type: request.format
|
@@ -2238,14 +2241,9 @@ class Object
|
|
2238
2241
|
|
2239
2242
|
if is_need_params
|
2240
2243
|
code << " def #{params_name}\n"
|
2241
|
-
permits = model.columns_hash.keys.map(&:to_sym)
|
2242
|
-
permits_txt = permits.map(&:inspect) +
|
2243
|
-
model.reflect_on_all_associations.select { |assoc| assoc.macro == :has_many && assoc.options[:through] }.map do |assoc|
|
2244
|
-
permits << { "#{assoc.name.to_s.singularize}_ids".to_sym => [] }
|
2245
|
-
"#{assoc.name.to_s.singularize}_ids: []"
|
2246
|
-
end
|
2244
|
+
permits_txt = self._brick_find_permits(model, (permits = model.columns_hash.keys.map(&:to_sym)))
|
2247
2245
|
code << " params.require(:#{require_name = model.name.underscore.tr('/', '_')
|
2248
|
-
}).permit(#{permits_txt.join(', ')})\n"
|
2246
|
+
}).permit(#{permits_txt.map(&:inspect).join(', ')})\n"
|
2249
2247
|
code << " end\n"
|
2250
2248
|
self.define_method(params_name) do
|
2251
2249
|
params.require(require_name.to_sym).permit(permits)
|
@@ -2259,6 +2257,101 @@ class Object
|
|
2259
2257
|
[built_controller, code]
|
2260
2258
|
end
|
2261
2259
|
|
2260
|
+
def _brick_find_permits(model, current_permits, done_permits = [])
|
2261
|
+
unless done_permits.include?(self)
|
2262
|
+
done_permits << self
|
2263
|
+
model.reflect_on_all_associations.select { |assoc| assoc.macro == :has_many }.each_with_object([]) do |assoc, s|
|
2264
|
+
if assoc.options[:through]
|
2265
|
+
current_permits << { "#{assoc.name.to_s.singularize}_ids".to_sym => [] }
|
2266
|
+
s << "#{assoc.name.to_s.singularize}_ids: []"
|
2267
|
+
elsif assoc.active_record.instance_methods.include?(:"#{assoc.name}_attributes=")
|
2268
|
+
# Support nested attributes which use the friendly_id gem
|
2269
|
+
self._brick_nested_friendly_id if Object.const_defined?('FriendlyId') &&
|
2270
|
+
assoc.klass.instance_variable_get(:@friendly_id_config)
|
2271
|
+
new_attrib_text = self._brick_find_permits(assoc.klass, (new_permits = assoc.klass.columns_hash.keys.map(&:to_sym)), done_permits)
|
2272
|
+
new_permits << :_destroy
|
2273
|
+
current_permits << { "#{assoc.name}_attributes".to_sym => new_permits }
|
2274
|
+
s << "#{assoc.name}_attributes: #{new_attrib_text}"
|
2275
|
+
end
|
2276
|
+
end
|
2277
|
+
end
|
2278
|
+
current_permits
|
2279
|
+
end
|
2280
|
+
|
2281
|
+
def _brick_nested_friendly_id
|
2282
|
+
unless @_brick_nested_friendly_id
|
2283
|
+
::ActiveRecord::Base.class_exec do
|
2284
|
+
if private_instance_methods.include?(:assign_nested_attributes_for_collection_association)
|
2285
|
+
alias _brick_anafca assign_nested_attributes_for_collection_association
|
2286
|
+
def assign_nested_attributes_for_collection_association(association_name, attributes_collection)
|
2287
|
+
association = association(association_name)
|
2288
|
+
slug_column = association.klass.instance_variable_get(:@friendly_id_config)&.slug_column
|
2289
|
+
return _brick_anafca unless slug_column
|
2290
|
+
|
2291
|
+
# Here is the FriendlyId version of #assign_nested_attributes_for_collection_association
|
2292
|
+
options = nested_attributes_options[association_name]
|
2293
|
+
attributes_collection = attributes_collection.to_h if attributes_collection.respond_to?(:permitted?)
|
2294
|
+
|
2295
|
+
unless attributes_collection.is_a?(Hash) || attributes_collection.is_a?(Array)
|
2296
|
+
raise ArgumentError, "Hash or Array expected for attribute `#{association_name}`, got #{attributes_collection.class.name} (#{attributes_collection.inspect})"
|
2297
|
+
end
|
2298
|
+
|
2299
|
+
check_record_limit!(options[:limit], attributes_collection)
|
2300
|
+
|
2301
|
+
if attributes_collection.is_a? Hash
|
2302
|
+
keys = attributes_collection.keys
|
2303
|
+
attributes_collection = if keys.include?("id") || keys.include?(:id)
|
2304
|
+
[attributes_collection]
|
2305
|
+
else
|
2306
|
+
attributes_collection.values
|
2307
|
+
end
|
2308
|
+
end
|
2309
|
+
existing_records = if association.loaded?
|
2310
|
+
association.target
|
2311
|
+
else
|
2312
|
+
attribute_ids = attributes_collection.filter_map { |a| a["id"] || a[:id] }
|
2313
|
+
if attribute_ids.empty?
|
2314
|
+
[]
|
2315
|
+
else # Implement the same logic as "friendly" scope
|
2316
|
+
association.scope.where(association.klass.primary_key => attribute_ids)
|
2317
|
+
.or(association.scope.where(slug_column => attribute_ids))
|
2318
|
+
end
|
2319
|
+
end
|
2320
|
+
attributes_collection.each do |attributes|
|
2321
|
+
attributes = attributes.to_h if attributes.respond_to?(:permitted?)
|
2322
|
+
attributes = attributes.with_indifferent_access
|
2323
|
+
if attributes["id"].blank? && attributes[slug_column].blank?
|
2324
|
+
unless reject_new_record?(association_name, attributes)
|
2325
|
+
association.reader.build(attributes.except(*::ActiveRecord::Base::UNASSIGNABLE_KEYS))
|
2326
|
+
end
|
2327
|
+
elsif (attr_id_str = attributes["id"].to_s) &&
|
2328
|
+
(existing_record = existing_records.detect { |record| record.id.to_s == attr_id_str ||
|
2329
|
+
record.send(slug_column).to_s == attr_id_str })
|
2330
|
+
unless call_reject_if(association_name, attributes)
|
2331
|
+
# Make sure we are operating on the actual object which is in the association's
|
2332
|
+
# proxy_target array (either by finding it, or adding it if not found)
|
2333
|
+
# Take into account that the proxy_target may have changed due to callbacks
|
2334
|
+
target_record = association.target.detect { |record| record.id.to_s == attr_id_str ||
|
2335
|
+
record.send(slug_column).to_s == attr_id_str }
|
2336
|
+
if target_record
|
2337
|
+
existing_record = target_record
|
2338
|
+
else
|
2339
|
+
association.add_to_target(existing_record, skip_callbacks: true)
|
2340
|
+
end
|
2341
|
+
|
2342
|
+
assign_to_or_mark_for_destruction(existing_record, attributes, options[:allow_destroy])
|
2343
|
+
end
|
2344
|
+
else
|
2345
|
+
raise_nested_attributes_record_not_found!(association_name, attributes["id"])
|
2346
|
+
end
|
2347
|
+
end
|
2348
|
+
end # anafca
|
2349
|
+
end
|
2350
|
+
end if ::ActiveRecord::QueryMethods.instance_methods.include?(:or)
|
2351
|
+
@_brick_nested_friendly_id = true
|
2352
|
+
end
|
2353
|
+
end
|
2354
|
+
|
2262
2355
|
def _brick_get_hm_assoc_name(relation, hm_assoc, source = nil)
|
2263
2356
|
assoc_name, needs_class = if (relation[:hm_counts][hm_assoc[:inverse_table]]&.> 1) &&
|
2264
2357
|
hm_assoc[:alternate_name] != (source || name.underscore)
|
@@ -263,11 +263,11 @@ function linkSchemas() {
|
|
263
263
|
|
264
264
|
# After we're initialized and before running the rest of stuff, put our configuration in place
|
265
265
|
ActiveSupport.on_load(:after_initialize) do |app|
|
266
|
-
assets_path = File.expand_path("#{__dir__}/../../../../vendor/assets")
|
267
|
-
if (app_config = app.config).respond_to?(:assets)
|
268
|
-
|
269
|
-
|
270
|
-
end
|
266
|
+
# assets_path = File.expand_path("#{__dir__}/../../../../vendor/assets")
|
267
|
+
# if (app_config = app.config).respond_to?(:assets)
|
268
|
+
# (app_config.assets.precompile ||= []) << "#{assets_path}/images/brick_erd.png"
|
269
|
+
# (app.config.assets.paths ||= []) << assets_path
|
270
|
+
# end
|
271
271
|
|
272
272
|
# Treat ActiveStorage::Blob metadata as JSON
|
273
273
|
if ::Brick.config.table_name_prefixes.fetch('active_storage_', nil) == 'ActiveStorage' &&
|
@@ -813,7 +813,7 @@ h1, h3 {
|
|
813
813
|
margin-bottom: 0;
|
814
814
|
}
|
815
815
|
#imgErd {
|
816
|
-
background-image:url(/
|
816
|
+
background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE0AAABNCAMAAADU1xmCAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAARxaVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJYTVAgQ29yZSA2LjAuMCI+CiAgIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5zOnRpZmY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vdGlmZi8xLjAvIgogICAgICAgICAgICB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIKICAgICAgICAgICAgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyI+CiAgICAgICAgIDx0aWZmOllSZXNvbHV0aW9uPjcyPC90aWZmOllSZXNvbHV0aW9uPgogICAgICAgICA8dGlmZjpYUmVzb2x1dGlvbj43MjwvdGlmZjpYUmVzb2x1dGlvbj4KICAgICAgICAgPHRpZmY6T3JpZW50YXRpb24+MTwvdGlmZjpPcmllbnRhdGlvbj4KICAgICAgICAgPHhtcE1NOkRlcml2ZWRGcm9tIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgPHN0UmVmOmluc3RhbmNlSUQ+eG1wLmlpZDoxN0U3OEI3RjAzN0MxMUU3QTZDMDhBQjVCRDc2QkZCQjwvc3RSZWY6aW5zdGFuY2VJRD4KICAgICAgICAgICAgPHN0UmVmOmRvY3VtZW50SUQ+eG1wLmRpZDoxN0U3OEI4MDAzN0MxMUU3QTZDMDhBQjVCRDc2QkZCQjwvc3RSZWY6ZG9jdW1lbnRJRD4KICAgICAgICAgPC94bXBNTTpEZXJpdmVkRnJvbT4KICAgICAgICAgPHhtcE1NOkRvY3VtZW50SUQ+eG1wLmRpZDoxN0U3OEI4MjAzN0MxMUU3QTZDMDhBQjVCRDc2QkZCQjwveG1wTU06RG9jdW1lbnRJRD4KICAgICAgICAgPHhtcE1NOkluc3RhbmNlSUQ+eG1wLmlpZDoxN0U3OEI4MTAzN0MxMUU3QTZDMDhBQjVCRDc2QkZCQjwveG1wTU06SW5zdGFuY2VJRD4KICAgICAgICAgPHhtcDpDcmVhdG9yVG9vbD5BZG9iZSBQaG90b3Nob3AgQ1M1IFdpbmRvd3M8L3htcDpDcmVhdG9yVG9vbD4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+ChMBcXgAAAAJcEhZcwAACxMAAAsTAQCanBgAAAL9UExURUdwTDRRc1EVG6ioqFJSUmJiYn+AgURWa2uEkauorszGwmtrawonUKzY7DMRIlFTVWV9m4qKiwaN0G1raJSQiJjV7jWh2HmizPLs6CaV0QohSmdoaVdXWLWsomFdYmIgD4WCfQWa2WIoFUxylldpekeRuGtrajhztIuLizV3qc3DvThDVEyFs31+fiRViVRNViVWjwsvWxIzXxZEekeL1FZIVVRdeEZrk359fj52ppubm3l6e4qbqJOTlBlGfM3k3Nzc3K6lnk9RWaenp0FjikGDyJGRkWJiYk2L0Li4uJubnH5+flFbeNPT02tpac3NzVBGJkCCyMvLy9LS0oxETk2U3tLS0tXV1cPDw+Xl5amDftbX19na2uLj4+jo6dzd3OXl511dXd/g31paWlZXV9TU1HBwcOvr687OzdDQ0u/u7fTx79PSzcrJx6KiooWFhujn5NvW05WUk7S1t3R1d7y9vcLCv37J68vMzVJTVOLY1gMiSpmamnt7e7K6zHq+43LQ9Vyez+Pf3LGyscXGybzD1sXDw46v02vI8I+Pj7vEtNvIx7q4ubnZ54a3it3f5s+8vGS/6L6trK+6qICs1H+33cXc6KiuwAOr48fN20ee0Fao0lyz4W6s1qyrrKKlt3XdkoqnyyFoqzuTy6ixosuVeobA4YHNl8TOv3/Ck9bc4I3P7Uqq3tDIxz2FwzN/vF+VxdDe59mIfU+OxJmovxl+wX7S9WjbhovW9jihyKGalIq31uNyY36exJCatJONhTm36nKj0B2q4Mqxsae2zc/U3tvf1cqKa7zAyJS4npqyyTh2tUhMT1drj5ixtN98cEfC8U2Y5vf39355cSN0s4mDfKaomlrG8b2cmcFvaGx/m2CeZge68HG64YCNntSgoVHUdJzKnIHIh6c+BalVVaPM5qrG2CZZkyaHH3WRtYrdn5nH2rxoP22+gN1VQTyxW1aXl0iO2GaxtFuzaCCAQyXSWDOKlDZwkxIINVZPP52Io3uldtIoC1uGVxmzRP6PHn8AAADVdFJOUwAmEf6t/v4EAQVR/oT+Hl4U/v1bR/7+Kf7+a/76Q4Y2Wf1b4j71sXm0y2hF/bBwbtXN/fyGl8Sxiu382Preqfzia9iIkdP51/Povnineu+9n6H7ov5ksLfYy/7////////+/////////////////////v/////////////////////////////////////////////////////////////////////////////+/////////////////////////////////////////////////////r5xM8kAAA0qSURBVFjDpZh3WFNnG8YDMZOiLEFEsVhn1Vq1Vq1abWv3br+dc5IQsklCSEiIyAoJyAhb9h4ishVQcCAIOLC4UBFxr7bu0X6dX6/vec8JikIptecPVrh+576f5z3vez+HQmGyKBSK28eT4SsL/fiXLiaFwmD/E5NzPmU7wG8s5l/DOXy8+vhxLg8TcN5/yw0JZPwV2GoJH+fjPI7UHBWV/8HzwGIynlkgm+vv788RiURSs06bT6WuJAQynlEgO+JaUzoWhGAWE1X1mkqlmYUEMp5JIBs7ejYz3L4iyN+gy1epVMGvaYI1K5faIIF/nsfuPDr325LMo5XpvCCFThUMrHccY2L85j2TQHZna11kZFGd19lo+4oI/yiqJiYmxtGP7kdf/gwC2bLWuix1RWTX7uzMo+PTI4KkJo0fXPSQkBDxDOc/KZBtaK3P4uLqrPXri+rcz4YjgbpgegidHhIgDhC/6/mnBLLNVTWdclzdmbYTeAMClVS6OCAgQGxnZ0cbM4dBPDKjoh2oqo309ZV3ppWV7UTAur1nw+MrIhRaRzsPsdiDRqN5v+lpO0oc0OrrirLkiWGVZVYeIXBLRFBUsNiH5kHz9vHxeZMxOhxb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);
|
817
817
|
background-size: 100% 100%;
|
818
818
|
width: 2.2em;
|
819
819
|
height: 2.2em;
|
@@ -1241,7 +1241,9 @@ erDiagram
|
|
1241
1241
|
btnImport.style.display = droppedTSV.length > 0 ? \"block\" : \"none\";
|
1242
1242
|
});
|
1243
1243
|
btnImport.addEventListener(\"click\", function () {
|
1244
|
-
|
1244
|
+
var patchPath = <%= #{path_obj_name}_path(-1, format: :csv).inspect.html_safe %>;
|
1245
|
+
if (brickSchema) patchPath = changeout(patchPath, \"_brick_schema\", brickSchema);
|
1246
|
+
fetch(patchPath, {
|
1245
1247
|
method: \"PATCH\",
|
1246
1248
|
headers: { \"Content-Type\": \"text/tab-separated-values\" },
|
1247
1249
|
body: droppedTSV
|
data/lib/brick/version_number.rb
CHANGED
data/lib/brick.rb
CHANGED
@@ -742,6 +742,28 @@ In config/initializers/brick.rb appropriate entries would look something like:
|
|
742
742
|
@double_underscore_applied = true
|
743
743
|
end
|
744
744
|
end
|
745
|
+
|
746
|
+
def _find_csv_separator(stream, likely_separator)
|
747
|
+
line = nil
|
748
|
+
last_char = nil
|
749
|
+
in_quotes = false
|
750
|
+
ret = +''
|
751
|
+
while true
|
752
|
+
(line = stream.readline).each_char do |ch|
|
753
|
+
likely_separator[ch] += 2 if !in_quotes && last_char == '"' && ch != "\n"
|
754
|
+
if ch == '"'
|
755
|
+
in_quotes = !in_quotes
|
756
|
+
likely_separator[last_char] += 2 if in_quotes && last_char != "\n"
|
757
|
+
end
|
758
|
+
last_char = ch
|
759
|
+
end
|
760
|
+
ret << line
|
761
|
+
break if !in_quotes || stream.eof?
|
762
|
+
end
|
763
|
+
likely_separator[line[0]] += 1
|
764
|
+
likely_separator[line[-2]] += 1
|
765
|
+
ret
|
766
|
+
end
|
745
767
|
end
|
746
768
|
|
747
769
|
module RouteSet
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: brick
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.151
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lorin Thwaits
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-06-
|
11
|
+
date: 2023-06-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|