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