brick 1.0.219 → 1.0.221
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 +5 -0
- data/lib/brick/extensions.rb +55 -5
- data/lib/brick/{frameworks/rails → rails}/engine.rb +104 -10
- data/lib/brick/{frameworks/rails → rails}/form_tags.rb +4 -3
- data/lib/brick/{frameworks/rails.rb → rails.rb} +2 -2
- data/lib/brick/reflect_tables.rb +67 -2
- data/lib/brick/route_mapper.rb +9 -4
- data/lib/brick/version_number.rb +1 -1
- data/lib/brick.rb +4 -2
- data/lib/generators/brick/install_generator.rb +3 -0
- data/lib/generators/brick/seeds_generator.rb +66 -4
- metadata +11 -11
- /data/lib/brick/{frameworks/rails → rails}/controller.rb +0 -0
- /data/lib/brick/{frameworks/rails → rails}/crosstab.brk +0 -0
- /data/lib/brick/{frameworks/rails → rails}/form_builder.rb +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b4aaaeaadb65aad58b8eac139c9e0fa5c8a68995a15151149fdc49196563db7e
|
4
|
+
data.tar.gz: f2ad0ef65556495ac9d531e499ca8b38a532aab641d0e46aeca4ea5fc535efd0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0f09da443c9427e5dd0b442f626bfbeb23011bceec74e6a9a9d52d28506f823e8d4d3fcf9cfdeb2af6a4b67f3b41552b09a23df18469831b2844a718adcee1a7
|
7
|
+
data.tar.gz: 07ed1b5a35404a584c79b7c9002159832a4a5ccacc5db330ee41b7ec7ed49a2011eee27c921e5db4cb2f887e33cfbf3ef97a0f66fab5b765a2168ba350ac1c39
|
data/lib/brick/config.rb
CHANGED
@@ -482,6 +482,11 @@ module Brick
|
|
482
482
|
@mutex.synchronize { @ignore_migration_fks = relations }
|
483
483
|
end
|
484
484
|
|
485
|
+
# Add search page for general Elasticsearch / Opensearch querying
|
486
|
+
def add_search
|
487
|
+
true
|
488
|
+
end
|
489
|
+
|
485
490
|
# Add status page showing all resources and what files have been built out for them
|
486
491
|
def add_status
|
487
492
|
true
|
data/lib/brick/extensions.rb
CHANGED
@@ -744,7 +744,6 @@ module ActiveRecord
|
|
744
744
|
end
|
745
745
|
end
|
746
746
|
|
747
|
-
# core_selects = selects.dup
|
748
747
|
id_for_tables = Hash.new { |h, k| h[k] = [] }
|
749
748
|
field_tbl_names = Hash.new { |h, k| h[k] = {} }
|
750
749
|
used_col_aliases = {} # Used to make sure there is not a name clash
|
@@ -758,7 +757,6 @@ module ActiveRecord
|
|
758
757
|
if @_brick_rel_dup.respond_to?(k) # Name already taken?
|
759
758
|
# %%% Use ensure_unique here in this kind of fashion:
|
760
759
|
# cnstr_name = ensure_unique(+"(brick) #{for_tbl}_#{pri_tbl}", nil, bts, hms)
|
761
|
-
# binding.pry
|
762
760
|
next
|
763
761
|
end
|
764
762
|
|
@@ -1290,8 +1288,9 @@ Might want to add this in your brick.rb:
|
|
1290
1288
|
end
|
1291
1289
|
|
1292
1290
|
if Object.const_defined?('ActionView')
|
1293
|
-
require 'brick/
|
1294
|
-
require 'brick/
|
1291
|
+
require 'brick/rails'
|
1292
|
+
require 'brick/rails/form_tags'
|
1293
|
+
require 'brick/rails/form_builder'
|
1295
1294
|
module ::ActionView::Helpers
|
1296
1295
|
module FormTagHelper
|
1297
1296
|
include ::Brick::Rails::FormTags
|
@@ -1480,7 +1479,7 @@ end
|
|
1480
1479
|
begin
|
1481
1480
|
if plural_class_name == 'BrickOpenapi' ||
|
1482
1481
|
(
|
1483
|
-
(::Brick.config.add_status || ::Brick.config.add_orphans) &&
|
1482
|
+
(::Brick.config.add_search || ::Brick.config.add_status || ::Brick.config.add_orphans) &&
|
1484
1483
|
plural_class_name == 'BrickGem'
|
1485
1484
|
# Was: ) || (model = self.const_get(full_class_name))
|
1486
1485
|
) || (model = Object.const_get(full_class_name))
|
@@ -1741,6 +1740,52 @@ class Object
|
|
1741
1740
|
built_model = Class.new(base_model) do |new_model_class|
|
1742
1741
|
(schema_module || Object).const_set(chosen_name, new_model_class) unless is_generator
|
1743
1742
|
@_brick_relation = relation
|
1743
|
+
# Enable Elasticsearch for this one?
|
1744
|
+
access = ::Brick.elasticsearch_models&.is_a?(Hash) ? ::Brick.elasticsearch_models[name] : ::Brick.elasticsearch_models
|
1745
|
+
@_brick_es_crud ||= case access
|
1746
|
+
when String
|
1747
|
+
access
|
1748
|
+
when :all, :full
|
1749
|
+
'icrud' # Auto-create index, and full CRUD
|
1750
|
+
else
|
1751
|
+
''
|
1752
|
+
end
|
1753
|
+
unless @_brick_es_crud.blank?
|
1754
|
+
include ::Elasticsearch::Model
|
1755
|
+
code << " include Elasticsearch::Model\n"
|
1756
|
+
if @_brick_es_crud.index('i') # Enable auto-creation of indexes on import?
|
1757
|
+
class << self
|
1758
|
+
alias _original_import import
|
1759
|
+
def import(options={}, &block)
|
1760
|
+
self.__elasticsearch__.create_index! unless self.__elasticsearch__.index_exists?
|
1761
|
+
_original_import(options={}, &block)
|
1762
|
+
end
|
1763
|
+
end
|
1764
|
+
end
|
1765
|
+
if @_brick_es_crud.index('c') || @_brick_es_crud.index('u') || @_brick_es_crud.index('d')
|
1766
|
+
include ::Elasticsearch::Model::Callbacks
|
1767
|
+
code << " include Elasticsearch::Model::Callbacks\n"
|
1768
|
+
end
|
1769
|
+
if @_brick_es_crud.index('r')
|
1770
|
+
# Customer.__elasticsearch__.search('taco').to_a
|
1771
|
+
end
|
1772
|
+
# # Need some mappings for text columns
|
1773
|
+
# mappings do
|
1774
|
+
# indexes :company_name, type: 'text'
|
1775
|
+
# indexes :country, type: 'text'
|
1776
|
+
# end
|
1777
|
+
# def self.search(q)
|
1778
|
+
# s = self.__elasticsearch__.search(q)
|
1779
|
+
# binding.pry
|
1780
|
+
# s.to_a
|
1781
|
+
# # class Elasticsearch::Model::Response::Response
|
1782
|
+
# # def to_a
|
1783
|
+
# # end
|
1784
|
+
# # rescue Elastic::Transport::Transport::Errors::NotFound => e
|
1785
|
+
# # self.create_index!
|
1786
|
+
# # self.__elasticsearch__.search(q)
|
1787
|
+
# end
|
1788
|
+
end
|
1744
1789
|
if inheritable_name
|
1745
1790
|
new_model_class.define_singleton_method :inherited do |subclass|
|
1746
1791
|
super(subclass)
|
@@ -2431,6 +2476,7 @@ class Object
|
|
2431
2476
|
s << excl_parts.last
|
2432
2477
|
end
|
2433
2478
|
end
|
2479
|
+
@_brick_es = real_model.instance_variable_get(:@_brick_es_crud)
|
2434
2480
|
@_brick_bt_descrip = real_model._br_bt_descrip
|
2435
2481
|
@_brick_hm_counts = real_model._br_hm_counts
|
2436
2482
|
@_brick_join_array = join_array
|
@@ -2530,6 +2576,10 @@ class Object
|
|
2530
2576
|
session[:_brick_exclude] = excls
|
2531
2577
|
end
|
2532
2578
|
render json: { result: ::Brick.unexclude_column(table_name, col) }
|
2579
|
+
elsif is_json && (q = params['_brick_es']) # Elasticsearch
|
2580
|
+
# Make sure that the index is actually present and we allow reading before attempting
|
2581
|
+
es_result = model.__elasticsearch__.search(q).to_a if (es_perms = model.instance_variable_get(:@_brick_es_crud)).index('r')
|
2582
|
+
render json: { result: es_result }
|
2533
2583
|
else
|
2534
2584
|
real_model = model.real_model(params)
|
2535
2585
|
singular_table_name = real_model.name.underscore.split('/').last
|
@@ -582,7 +582,10 @@ window.addEventListener(\"popstate\", linkSchemas);
|
|
582
582
|
alias :_brick_lookup_context :lookup_context
|
583
583
|
def lookup_context(*args)
|
584
584
|
ret = _brick_lookup_context(*args)
|
585
|
-
|
585
|
+
if self.class < AbstractController::Base
|
586
|
+
request if respond_to?(:request) # ActionMailer does not have +request+
|
587
|
+
@_lookup_context.instance_variable_set(:@_brick_req_params, params) if request && params.present?
|
588
|
+
end
|
586
589
|
ret
|
587
590
|
end
|
588
591
|
end
|
@@ -592,12 +595,14 @@ window.addEventListener(\"popstate\", linkSchemas);
|
|
592
595
|
# Used by Rails 5.0 and above
|
593
596
|
alias :_brick_template_exists? :template_exists?
|
594
597
|
def template_exists?(*args, **options)
|
598
|
+
(::Brick.config.add_search && args.first == 'search') ||
|
595
599
|
(::Brick.config.add_status && args.first == 'status') ||
|
596
600
|
(::Brick.config.add_orphans && args.first == 'orphans') ||
|
597
601
|
(args.first == 'crosstab') ||
|
598
602
|
_brick_template_exists?(*args, **options) ||
|
599
|
-
#
|
600
|
-
(
|
603
|
+
# By default do not auto-create a template when it's searching for an application.html.erb, which comes in like: ["edit", ["games", "application"]]
|
604
|
+
# (Although specifying a class name for controllers_inherit_from will override this.)
|
605
|
+
((args[1].length == 1 || ::Brick.config.controllers_inherit_from.present? || args[1][-1] != 'application') &&
|
601
606
|
set_brick_model(args, @_brick_req_params))
|
602
607
|
end
|
603
608
|
|
@@ -654,6 +659,7 @@ window.addEventListener(\"popstate\", linkSchemas);
|
|
654
659
|
def find_template(*args, **options)
|
655
660
|
find_template_err = nil
|
656
661
|
unless (model_name = @_brick_model&.name) ||
|
662
|
+
(is_search = ::Brick.config.add_search && args[0..1] == ['search', ['brick_gem']]) ||
|
657
663
|
(is_status = ::Brick.config.add_status && args[0..1] == ['status', ['brick_gem']]) ||
|
658
664
|
(is_orphans = ::Brick.config.add_orphans && args[0..1] == ['orphans', ['brick_gem']]) ||
|
659
665
|
(is_crosstab = args[0..1] == ['crosstab', ['brick_gem']])
|
@@ -775,10 +781,14 @@ window.addEventListener(\"popstate\", linkSchemas);
|
|
775
781
|
end
|
776
782
|
s << "<option value=\"#{::Brick._brick_index(rel.first, nil, '/', nil, true)}\">#{rel.first}#{rowcount}</option>"
|
777
783
|
end.html_safe
|
784
|
+
# Options for special Brick pages
|
778
785
|
prefix = "#{::Brick.config.path_prefix}/" if ::Brick.config.path_prefix
|
779
|
-
|
780
|
-
|
781
|
-
|
786
|
+
[['Search', ::Brick.config.add_search],
|
787
|
+
['Status', ::Brick.config.add_status],
|
788
|
+
['Orphans', is_orphans],
|
789
|
+
['Crosstab', is_crosstab]].each do |table_option, show_it|
|
790
|
+
table_options << "<option value=\"#{prefix}brick_#{table_option.downcase}\">(#{table_option})</option>".html_safe if show_it
|
791
|
+
end
|
782
792
|
css = +''
|
783
793
|
css << ::Brick::Rails::BRICK_CSS
|
784
794
|
css << "<script>
|
@@ -1048,6 +1058,64 @@ end
|
|
1048
1058
|
});
|
1049
1059
|
});
|
1050
1060
|
</script>
|
1061
|
+
<% end
|
1062
|
+
# SEARCH BOX
|
1063
|
+
if @_brick_es&.index('r') # Must have at least Elasticsearch Read access %>
|
1064
|
+
<input type=\"text\" id=\"esSearch\"><a href=\"\">S</a>
|
1065
|
+
<script>
|
1066
|
+
var esSearch = document.getElementById(\"esSearch\")
|
1067
|
+
var isEsFiltered = false;
|
1068
|
+
esSearch.addEventListener(\"input\", function () {
|
1069
|
+
var gridTrs;
|
1070
|
+
if (this.value.length > 2) { # At least 3 letters in the search term
|
1071
|
+
var es = doFetch(\"POST\", {_brick_es: this.value},
|
1072
|
+
function (p) {p.text().then(function (response) {
|
1073
|
+
var result = JSON.parse(response).result;
|
1074
|
+
if (result.length > 0) {
|
1075
|
+
// Show only rows that have matches
|
1076
|
+
gridTrs = [... grid.querySelectorAll(\"tr\")];
|
1077
|
+
for (var i = 1; i < gridTrs.length; ++i) {
|
1078
|
+
var row = gridTrs[i];
|
1079
|
+
// Check all results to see if this one is in the list
|
1080
|
+
var rid = row.getAttribute(\"x-id\");
|
1081
|
+
var isHit = false;
|
1082
|
+
for (var j = 0; j < result.length; ++j) {
|
1083
|
+
if (rid == result[j]._id) {
|
1084
|
+
isHit = true;
|
1085
|
+
break;
|
1086
|
+
}
|
1087
|
+
}
|
1088
|
+
if (!isHit) row.style.display = \"none\";
|
1089
|
+
}
|
1090
|
+
isEsFiltered = true;
|
1091
|
+
} else {
|
1092
|
+
if (isEsFiltered) { // Show all rows and gray the search box
|
1093
|
+
gridTrs = [... grid.querySelectorAll(\"tr\")];
|
1094
|
+
for (var i = 1; i < gridTrs.length; ++i) {
|
1095
|
+
gridTrs[i].style.display = \"table-row\";
|
1096
|
+
}
|
1097
|
+
}
|
1098
|
+
}
|
1099
|
+
});}
|
1100
|
+
);
|
1101
|
+
} else {
|
1102
|
+
if (isEsFiltered) { // Show all rows and gray the search box
|
1103
|
+
gridTrs = [... grid.querySelectorAll(\"tr\")];
|
1104
|
+
for (var i = 1; i < gridTrs.length; ++i) {
|
1105
|
+
gridTrs[i].style.display = \"table-row\";
|
1106
|
+
}
|
1107
|
+
}
|
1108
|
+
}
|
1109
|
+
});
|
1110
|
+
esSearch.addEventListener(\"keypress\", function (e) {
|
1111
|
+
if (e.keyCode == 13) {
|
1112
|
+
// debugger
|
1113
|
+
// Go to search results page
|
1114
|
+
// var es = doFetch(\"POST\", {_brick_es: this.value});
|
1115
|
+
// console.log(es);
|
1116
|
+
}
|
1117
|
+
});
|
1118
|
+
</script>
|
1051
1119
|
<% end %>
|
1052
1120
|
</div></div>
|
1053
1121
|
#{::Brick::Rails.erd_markup(@_brick_model, prefix) if @_brick_model}
|
@@ -1113,6 +1181,32 @@ end
|
|
1113
1181
|
</html>
|
1114
1182
|
"
|
1115
1183
|
|
1184
|
+
|
1185
|
+
when 'search'
|
1186
|
+
if is_search
|
1187
|
+
# Search page - query across all indexes that appear to be related to models
|
1188
|
+
+"#{css}
|
1189
|
+
<p class=\"flashNotice\"><%= notice if request.respond_to?(:flash) %></p>#{"
|
1190
|
+
#{schema_options}" if schema_options}
|
1191
|
+
<select id=\"tbl\">#{table_options}</select>
|
1192
|
+
<h1>Search</h1>
|
1193
|
+
<table id=\"resourceName\" class=\"shadow\"><thead><tr>
|
1194
|
+
<th>Resource</th>
|
1195
|
+
<th>Description</th>
|
1196
|
+
<th>ID</th>
|
1197
|
+
</tr></thead>
|
1198
|
+
<tbody>
|
1199
|
+
<% # @results.each do |r| %>
|
1200
|
+
<tr>
|
1201
|
+
<td><%= %></td>
|
1202
|
+
<td<%= %></td>
|
1203
|
+
<td<%= %></td>
|
1204
|
+
</tr>
|
1205
|
+
<% # end %>
|
1206
|
+
</tbody></table>
|
1207
|
+
#{script}"
|
1208
|
+
end
|
1209
|
+
|
1116
1210
|
when 'status'
|
1117
1211
|
if is_status
|
1118
1212
|
# Status page - list of all resources and 5 things they do or don't have present, and what is turned on and off
|
@@ -1167,7 +1261,7 @@ end
|
|
1167
1261
|
%></td>
|
1168
1262
|
<td<%= ' class=\"dimmed\"'.html_safe unless r[6] %>><%= # Views
|
1169
1263
|
%></td>
|
1170
|
-
|
1264
|
+
</tr>
|
1171
1265
|
<% end %>
|
1172
1266
|
</tbody></table>
|
1173
1267
|
#{script}"
|
@@ -1197,7 +1291,7 @@ end
|
|
1197
1291
|
decipher.iv = "\xB4,\r2\x19\xF5\xFE/\aR\x1A\x8A\xCFV\v\x8C"
|
1198
1292
|
decipher.key = Digest::SHA256.hexdigest(::Brick.config.license).scan(/../).map { |x| x.hex }.pack('c*')
|
1199
1293
|
brick_path = Gem::Specification.find_by_name('brick').gem_dir
|
1200
|
-
decipher.update(File.binread("#{brick_path}/lib/brick/
|
1294
|
+
decipher.update(File.binread("#{brick_path}/lib/brick/rails/crosstab.brk"))[16..-1]
|
1201
1295
|
else
|
1202
1296
|
'Crosstab Charting not yet activated -- enter a valid license key in brick.rb'
|
1203
1297
|
end
|
@@ -1237,7 +1331,7 @@ end
|
|
1237
1331
|
end %>#{"
|
1238
1332
|
#{schema_options}" if schema_options}
|
1239
1333
|
<select id=\"tbl\">#{table_options}</select>
|
1240
|
-
<table id=\"resourceName\"><td><h1><%= page_title %></h1></td>
|
1334
|
+
<table id=\"resourceName\"><tr><td><h1><%= page_title %></h1></td>
|
1241
1335
|
<% rel = Brick.relations[#{model_name}.table_name]
|
1242
1336
|
if (in_app = rel.fetch(:existing, nil)&.fetch(:show, nil))
|
1243
1337
|
begin
|
@@ -1270,7 +1364,7 @@ end %>#{"
|
|
1270
1364
|
) %></td>
|
1271
1365
|
<% end
|
1272
1366
|
end %>
|
1273
|
-
</table>
|
1367
|
+
</tr></table>
|
1274
1368
|
<%
|
1275
1369
|
if (description = rel&.fetch(:description, nil)) %>
|
1276
1370
|
<span class=\"__brick\"><%= description %></span><br><%
|
@@ -99,9 +99,10 @@ module Brick::Rails::FormTags
|
|
99
99
|
# proxy = relation.instance_variable_get(:@proxy) || relation.instance_variable_set(:@proxy, {})
|
100
100
|
bi = relation.instance_variable_get(:@_brick_includes)
|
101
101
|
relation.each do |obj|
|
102
|
-
|
103
|
-
out << "<
|
104
|
-
|
102
|
+
rid = pk.map { |pk_part| obj.send(pk_part.to_sym) }
|
103
|
+
out << "<tr x-id=\"#{rid.join('/')}\">\n"
|
104
|
+
out << "<td class=\"col-sticky alternating-gray\">#{link_to('⇛', send("#{klass._brick_index(:singular)}_path".to_sym, rid),
|
105
|
+
{ class: 'big-arrow' })}</td>\n" if pk.present?
|
105
106
|
ac = obj.instance_variable_get(:@association_cache) || obj.instance_variable_set(:@association_cache, {})
|
106
107
|
# included =
|
107
108
|
bi&.each do |bi_key|
|
data/lib/brick/reflect_tables.rb
CHANGED
@@ -8,10 +8,75 @@ module Brick
|
|
8
8
|
|
9
9
|
# return if ActiveRecord::Base.connection.current_database == 'postgres'
|
10
10
|
|
11
|
+
# Utilise Elasticsearch indexes, if any
|
12
|
+
if Object.const_defined?('Elasticsearch')
|
13
|
+
if ::Elasticsearch.const_defined?('Client')
|
14
|
+
# Allow Elasticsearch gem > 7.10 to work with Opensearch
|
15
|
+
::Elasticsearch::Client.class_exec do
|
16
|
+
alias _original_initialize initialize
|
17
|
+
def initialize(arguments = {}, &block)
|
18
|
+
_original_initialize(arguments, &block)
|
19
|
+
@verified = true
|
20
|
+
@transport
|
21
|
+
end
|
22
|
+
|
23
|
+
# Auto-create when there is a missing index
|
24
|
+
alias _original_method_missing method_missing
|
25
|
+
def method_missing(name, *args, &block)
|
26
|
+
_original_method_missing(name, *args, &block)
|
27
|
+
rescue Elastic::Transport::Transport::Errors::NotFound => e
|
28
|
+
if (missing_index = args.last&.fetch(:defined_params, nil)&.fetch(:index, nil))
|
29
|
+
self.indices.create({ index: missing_index,
|
30
|
+
body: { settings: {}, mappings: { properties: {} } } })
|
31
|
+
puts "Auto-creating missing index \"#{missing_index}\""
|
32
|
+
_original_method_missing(name, *args, &block)
|
33
|
+
else
|
34
|
+
raise e
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
if ::Elasticsearch.const_defined?('Model')
|
40
|
+
# By setting the environment variable ELASTICSEARCH_URL then you can specify an Elasticsearch/Opensearch host
|
41
|
+
host = (client = ::Elasticsearch::Model.client).transport.hosts.first
|
42
|
+
es_uri = URI.parse("#{host[:protocol]}://#{host[:host]}:#{host[:port]}")
|
43
|
+
es_uri = nil if es_uri.to_s == 'http://localhost:9200'
|
44
|
+
begin
|
45
|
+
cluster_info = client.info.body
|
46
|
+
if (es_ver = cluster_info['version'])
|
47
|
+
::Brick.elasticsearch_models = :all
|
48
|
+
puts "Found Elasticsearch gem and #{'local ' unless es_uri}#{es_ver['distribution'].titleize} #{es_ver['number']} installation#{" at #{es_uri}" if es_uri}."
|
49
|
+
puts "Enable Elasticsearch support by either setting \"::Brick.elasticsearch_models = :all\" or by picking specific models by name."
|
50
|
+
|
51
|
+
# # Auto-create when trying to import and there is a missing index
|
52
|
+
# ::Elasticsearch::Model::Importing.class_exec do
|
53
|
+
# end
|
54
|
+
end
|
55
|
+
rescue StandardError => e # Errno::ECONNREFUSED
|
56
|
+
puts "Found Elasticsearch gem, but could not connect to #{'local ' unless es_uri}Elasticsearch/Opensearch server#{" at #{es_uri}" if es_uri}."
|
57
|
+
end
|
58
|
+
# require 'net/http'
|
59
|
+
# begin
|
60
|
+
# es_uri = ENV['ELASTICSEARCH_URL']
|
61
|
+
# binding.pry
|
62
|
+
# cluster_info = JSON.parse(Net::HTTP.get(URI.parse(es_uri || 'http://localhost:9200')))
|
63
|
+
# if (es_ver = cluster_info['version'])
|
64
|
+
# ::Brick.elasticsearch_models = :all
|
65
|
+
# puts "Found Elasticsearch gem and #{'local ' unless es_uri}#{es_ver['distribution'].titleize} #{es_ver['number']} installation#{" at #{es_uri}" if es_uri}."
|
66
|
+
# puts "Enable Elasticsearch support by either setting \"::Brick.elasticsearch_models = :all\" or by picking specific models by name."
|
67
|
+
# end
|
68
|
+
# rescue StandardError => e
|
69
|
+
# end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
# client = Elasticsearch::Client.new(host: 'https://my-elasticsearch-host.example')
|
73
|
+
# client.ping
|
74
|
+
# client.search(q: 'test')
|
75
|
+
|
11
76
|
# Overwrite SQLite's #begin_db_transaction so it opens in IMMEDIATE mode instead of
|
12
77
|
# the default DEFERRED mode.
|
13
78
|
# https://discuss.rubyonrails.org/t/failed-write-transaction-upgrades-in-sqlite3/81480/2
|
14
|
-
if ActiveRecord::Base.connection.adapter_name == 'SQLite'
|
79
|
+
if ActiveRecord::Base.connection.adapter_name == 'SQLite' && ActiveRecord.version >= Gem::Version.new('5.1')
|
15
80
|
arca = ::ActiveRecord::ConnectionAdapters
|
16
81
|
db_statements = arca::SQLite3.const_defined?('DatabaseStatements') ? arca::SQLite3::DatabaseStatements : arca::SQLite3::SchemaStatements
|
17
82
|
# Rails 7.1 and later
|
@@ -410,7 +475,7 @@ ORDER BY 1, 2, c.internal_column_id, acc.position"
|
|
410
475
|
v[:resource] = proposed_name_parts.last.underscore
|
411
476
|
if colliding_thing
|
412
477
|
message_start = if colliding_thing.is_a?(Module) && Object.const_defined?(:Rails) &&
|
413
|
-
colliding_thing.constants.find { |c| colliding_thing.const_get(c) < ::Rails::Application }
|
478
|
+
colliding_thing.constants.find { |c| (ctc = colliding_thing.const_get(c)).is_a?(Class) && ctc < ::Rails::Application }
|
414
479
|
"The module for the Rails application itself, \"#{colliding_thing.name}\","
|
415
480
|
else
|
416
481
|
"Non-AR #{colliding_thing.class.name.downcase} \"#{colliding_thing.name}\""
|
data/lib/brick/route_mapper.rb
CHANGED
@@ -1,10 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Brick
|
4
|
-
class << self
|
5
|
-
attr_accessor :routes_done
|
6
|
-
end
|
7
|
-
|
8
4
|
module RouteMapper
|
9
5
|
def add_brick_routes
|
10
6
|
routeset_to_use = ::Rails.application.routes
|
@@ -276,6 +272,15 @@ module Brick
|
|
276
272
|
end
|
277
273
|
|
278
274
|
if (named_routes = instance_variable_get(:@set).named_routes).respond_to?(:find)
|
275
|
+
# Generic Elasticsearch / Opensearch query page
|
276
|
+
if ::Brick.config.add_search && (search_as = "#{controller_prefix.tr('/', '_')}brick_search".to_sym)
|
277
|
+
(
|
278
|
+
!(search_route = instance_variable_get(:@set).named_routes.find { |route| route.first == search_as }&.last) ||
|
279
|
+
!search_route.ast.to_s.include?("/#{controller_prefix}brick_search/")
|
280
|
+
)
|
281
|
+
get("/#{controller_prefix}brick_search", to: 'brick_gem#search', as: search_as.to_s)
|
282
|
+
end
|
283
|
+
|
279
284
|
if ::Brick.config.add_status && (status_as = "#{controller_prefix.tr('/', '_')}brick_status".to_sym)
|
280
285
|
(
|
281
286
|
!(status_route = instance_variable_get(:@set).named_routes.find { |route| route.first == status_as }&.last) ||
|
data/lib/brick/version_number.rb
CHANGED
data/lib/brick.rb
CHANGED
@@ -92,7 +92,7 @@ require 'brick/config'
|
|
92
92
|
require 'brick/reflect_tables'
|
93
93
|
if Gem::Dependency.new('rails').matching_specs.present?
|
94
94
|
require 'rails'
|
95
|
-
require 'brick/
|
95
|
+
# require 'brick/rails'
|
96
96
|
end
|
97
97
|
module Brick
|
98
98
|
ALL_API_ACTIONS = [:index, :show, :create, :update, :destroy]
|
@@ -110,7 +110,9 @@ module Brick
|
|
110
110
|
attr_accessor :default_schema, :db_schemas, :test_schema,
|
111
111
|
:established_drf,
|
112
112
|
:is_oracle, :is_eager_loading, :auto_models, :initializer_loaded,
|
113
|
-
:table_name_lookup
|
113
|
+
:table_name_lookup,
|
114
|
+
:elasticsearch_models,
|
115
|
+
:routes_done
|
114
116
|
::Brick.auto_models = []
|
115
117
|
|
116
118
|
def get_possible_schemas
|
@@ -342,6 +342,9 @@ if ActiveRecord::Base.respond_to?(:brick_select) && !::Brick.initializer_loaded
|
|
342
342
|
# # user, then you can use model_descrips like this, putting expressions with property references in square brackets:
|
343
343
|
# Brick.model_descrips = { 'User' => '[profile.firstname] [profile.lastname]' }
|
344
344
|
|
345
|
+
# # FULL TEXT SEARCH
|
346
|
+
# Brick.elasticsearch_models = :all
|
347
|
+
|
345
348
|
# # ERD SETTINGS
|
346
349
|
|
347
350
|
# # By default the Entity Relationship Diagram fragment which is available to be shown on the Grid page includes
|
@@ -64,6 +64,8 @@ module Brick
|
|
64
64
|
stuck = {}
|
65
65
|
indexes = {} # Track index names to make sure things are unique
|
66
66
|
ar_base = Object.const_defined?(:ApplicationRecord) ? ApplicationRecord : Class.new(ActiveRecord::Base)
|
67
|
+
atrt_idx = 0 # ActionText::RichText unique index number
|
68
|
+
@has_atrts = nil # Any ActionText::RichText present?
|
67
69
|
# Start by making entries for fringe models (those with no foreign keys).
|
68
70
|
# Continue layer by layer, creating entries for models that reference ones already done, until
|
69
71
|
# no more entries can be created. (At that point hopefully all models are accounted for.)
|
@@ -88,6 +90,16 @@ module Brick
|
|
88
90
|
end
|
89
91
|
).present?
|
90
92
|
seeds << "\n"
|
93
|
+
# Search through the fringe to see if we should bump special dependent classes forward to the next fringe.
|
94
|
+
# (Currently only ActiveStorage::Attachment if there's also an ActiveStorage::VariantRecord in the same
|
95
|
+
# fringe, and always have ActionText::EncryptedRichText at the very end.)
|
96
|
+
fringe_classes = fringe.map { |f| f.klass.name }
|
97
|
+
unless (asa_idx = fringe_classes.index('ActiveStorage::Attachment')).nil?
|
98
|
+
fringe.slice!(asa_idx) if fringe_classes.include?('ActiveStorage::VariantRecord')
|
99
|
+
end
|
100
|
+
unless (atert_idx = fringe_classes.index('ActionText::EncryptedRichText')).nil?
|
101
|
+
fringe.slice!(atert_idx) if fringe_classes.length > 1
|
102
|
+
end
|
91
103
|
fringe.each do |seed_model|
|
92
104
|
tbl = seed_model.table_name
|
93
105
|
next unless ::Brick.config.exclude_tables.exclude?(tbl) &&
|
@@ -122,12 +134,14 @@ module Brick
|
|
122
134
|
klass.order(*pkey_cols).each do |obj|
|
123
135
|
unless has_rows
|
124
136
|
has_rows = true
|
125
|
-
seeds << " puts 'Seeding: #{
|
137
|
+
seeds << " puts 'Seeding: #{klass.name}'\n"
|
126
138
|
end
|
127
139
|
is_empty = false
|
128
140
|
pk_val = obj.send(pkey_cols.first)
|
141
|
+
var_name = "#{tbl.gsub('.', '__')}_#{brick_escape(pk_val)}"
|
129
142
|
fk_vals = []
|
130
143
|
data = []
|
144
|
+
updates = []
|
131
145
|
relation[:cols].each do |col, _col_type|
|
132
146
|
next if !(fk = fkeys.find { |assoc| col == assoc[:fk] }) &&
|
133
147
|
pkey_cols.include?(col)
|
@@ -142,11 +156,52 @@ module Brick
|
|
142
156
|
inv_tbl = fk[:inverse_table].gsub('.', '__')
|
143
157
|
fk_vals << "#{fk[:assoc_name]}: #{inv_tbl}_#{brick_escape(val)}" if val
|
144
158
|
else
|
145
|
-
val =
|
146
|
-
|
159
|
+
val = case val.class.name
|
160
|
+
when 'ActiveStorage::Filename'
|
161
|
+
val.to_s.inspect
|
162
|
+
when 'ActionText::RichText'
|
163
|
+
ensure_has_atrts(updates)
|
164
|
+
atrt_var = "atrt#{atrt_idx += 1}"
|
165
|
+
atrt_create = "(#{atrt_var} = #{val.class.name}.create(name: #{val.name.inspect}, body: #{val.to_trix_html.inspect
|
166
|
+
}, record_type: #{val.record_type.inspect}, record_id: #{var_name}.#{pkey_cols.first
|
167
|
+
}, created_at: DateTime.parse('#{val.created_at.inspect}'), updated_at: DateTime.parse('#{val.updated_at.inspect}')))"
|
168
|
+
updates << "#{var_name}.update(#{col}: #{atrt_create})\n"
|
169
|
+
# obj.send(col)&.embeds_blobs&.each do |blob|
|
170
|
+
updates << "atrt_ids[[#{val.id}, '#{val.class.name}']] = #{atrt_var}.id\n"
|
171
|
+
# end
|
172
|
+
next
|
173
|
+
else
|
174
|
+
val.inspect
|
175
|
+
end
|
176
|
+
data << "#{col}: #{val}" unless val == 'nil'
|
177
|
+
end
|
178
|
+
end
|
179
|
+
case klass.name
|
180
|
+
when 'ActiveStorage::VariantRecord'
|
181
|
+
ensure_has_atrts(updates)
|
182
|
+
updates << "atrt_ids[[#{obj.id}, '#{klass.name}']] = #{var_name}.id\n"
|
183
|
+
end
|
184
|
+
# Make sure that ActiveStorage::Attachment and ActionText::EncryptedRichText get
|
185
|
+
# wired up to the proper record_id
|
186
|
+
if klass.name == 'ActiveStorage::Attachment' || klass.name == 'ActionText::EncryptedRichText'
|
187
|
+
record_class = data.find { |d| d.start_with?('record_type: ') }[14..-2]
|
188
|
+
record_id = data.find { |d| d.start_with?('record_id: ') }[11..-1]
|
189
|
+
data.reject! { |d| d.start_with?('record_id: ') || d.start_with?('created_at: ') || d.start_with?('updated_at: ') }
|
190
|
+
data << "record_id: atrt_ids[[#{record_id}, '#{record_class}']]"
|
191
|
+
seeds << "#{var_name} = #{klass.name}.find_or_create_by(#{(fk_vals + data).join(', ')}) do |asa|
|
192
|
+
asa.created_at = DateTime.parse('#{obj.created_at.inspect}')#{"
|
193
|
+
asa.updated_at = DateTime.parse('#{obj.updated_at.inspect}')" if obj.respond_to?(:updated_at)}
|
194
|
+
end\n"
|
195
|
+
else
|
196
|
+
seeds << "#{var_name} = #{seed_model.klass.name}.create(#{(fk_vals + data).join(', ')})\n"
|
197
|
+
klass.attachment_reflections.each do |k, v|
|
198
|
+
if (attached = obj.send(k))
|
199
|
+
ensure_has_atrts(updates)
|
200
|
+
updates << "atrt_ids[[#{obj.id}, '#{klass.name}']] = #{var_name}.id\n"
|
201
|
+
end
|
147
202
|
end
|
148
203
|
end
|
149
|
-
seeds <<
|
204
|
+
updates.each { |update| seeds << update } # Anything that needs patching up after-the-fact
|
150
205
|
end
|
151
206
|
seeds << " # (Skipping #{seed_model.klass.name} as it has no rows)\n" unless has_rows
|
152
207
|
File.open(seed_file_path, "w") { |f| f.write seeds }
|
@@ -190,5 +245,12 @@ module Brick
|
|
190
245
|
val
|
191
246
|
end
|
192
247
|
end
|
248
|
+
|
249
|
+
def ensure_has_atrts(array)
|
250
|
+
unless @has_atrts
|
251
|
+
array << "atrt_ids = {}\n"
|
252
|
+
@has_atrts = true
|
253
|
+
end
|
254
|
+
end
|
193
255
|
end
|
194
256
|
end
|
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.221
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lorin Thwaits
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-11-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -190,14 +190,14 @@ dependencies:
|
|
190
190
|
requirements:
|
191
191
|
- - "~>"
|
192
192
|
- !ruby/object:Gem::Version
|
193
|
-
version:
|
193
|
+
version: 2.3.0
|
194
194
|
type: :development
|
195
195
|
prerelease: false
|
196
196
|
version_requirements: !ruby/object:Gem::Requirement
|
197
197
|
requirements:
|
198
198
|
- - "~>"
|
199
199
|
- !ruby/object:Gem::Version
|
200
|
-
version:
|
200
|
+
version: 2.3.0
|
201
201
|
description: 'Auto-create models, views, controllers, and routes with this slick Rails
|
202
202
|
extension
|
203
203
|
|
@@ -212,14 +212,14 @@ files:
|
|
212
212
|
- lib/brick/config.rb
|
213
213
|
- lib/brick/extensions.rb
|
214
214
|
- lib/brick/frameworks/cucumber.rb
|
215
|
-
- lib/brick/frameworks/rails.rb
|
216
|
-
- lib/brick/frameworks/rails/controller.rb
|
217
|
-
- lib/brick/frameworks/rails/crosstab.brk
|
218
|
-
- lib/brick/frameworks/rails/engine.rb
|
219
|
-
- lib/brick/frameworks/rails/form_builder.rb
|
220
|
-
- lib/brick/frameworks/rails/form_tags.rb
|
221
215
|
- lib/brick/frameworks/rspec.rb
|
222
216
|
- lib/brick/join_array.rb
|
217
|
+
- lib/brick/rails.rb
|
218
|
+
- lib/brick/rails/controller.rb
|
219
|
+
- lib/brick/rails/crosstab.brk
|
220
|
+
- lib/brick/rails/engine.rb
|
221
|
+
- lib/brick/rails/form_builder.rb
|
222
|
+
- lib/brick/rails/form_tags.rb
|
223
223
|
- lib/brick/reflect_tables.rb
|
224
224
|
- lib/brick/route_mapper.rb
|
225
225
|
- lib/brick/serializers/json.rb
|
@@ -257,7 +257,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
257
257
|
- !ruby/object:Gem::Version
|
258
258
|
version: 1.3.6
|
259
259
|
requirements: []
|
260
|
-
rubygems_version: 3.
|
260
|
+
rubygems_version: 3.2.33
|
261
261
|
signing_key:
|
262
262
|
specification_version: 4
|
263
263
|
summary: Create a Rails app from data alone
|
File without changes
|
File without changes
|
File without changes
|