brick 1.0.72 → 1.0.73
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 +25 -0
- data/lib/brick/extensions.rb +180 -95
- data/lib/brick/frameworks/rails/engine.rb +56 -25
- data/lib/brick/version_number.rb +1 -1
- data/lib/brick.rb +38 -10
- data/lib/generators/brick/install_generator.rb +2 -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: 31f69b5035fcebf947e729c3ebabdf3a686c364fb9ddc6a764a2b34740fdb7c9
|
4
|
+
data.tar.gz: 87009aad044a5a110146d26dc02f62451b18e7ad67b2b07d420edff0718a18c6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 300fe830280b2ad9d265fa62166aac01ba3e511090f95efa412d1b9ed42fbd72b9f17f8fe51ac1bb358be42f012b46cffbb3c142f6fd3b11f2a442025824e8ec
|
7
|
+
data.tar.gz: abbd021f67adb2c03aae76340ba1cb1f38d0be5b5774d11c5a01a1315e02b80c293c9008021915315416da28937b40af59d821e41ad6ac0eed890be162865d98
|
data/lib/brick/config.rb
CHANGED
@@ -56,6 +56,31 @@ module Brick
|
|
56
56
|
@mutex.synchronize { @enable_routes = enable }
|
57
57
|
end
|
58
58
|
|
59
|
+
def enable_api
|
60
|
+
@mutex.synchronize { @enable_api }
|
61
|
+
end
|
62
|
+
|
63
|
+
def enable_api=(enable)
|
64
|
+
@mutex.synchronize { @enable_api = enable }
|
65
|
+
end
|
66
|
+
|
67
|
+
def api_root
|
68
|
+
ver = api_version
|
69
|
+
@mutex.synchronize { @api_root || "/api/#{ver}/" }
|
70
|
+
end
|
71
|
+
|
72
|
+
def api_root=(path)
|
73
|
+
@mutex.synchronize { @api_root = path }
|
74
|
+
end
|
75
|
+
|
76
|
+
def api_version
|
77
|
+
@mutex.synchronize { @api_version || 'v1' }
|
78
|
+
end
|
79
|
+
|
80
|
+
def api_version=(ver)
|
81
|
+
@mutex.synchronize { @api_version = ver }
|
82
|
+
end
|
83
|
+
|
59
84
|
# Additional table associations to use (Think of these as virtual foreign keys perhaps)
|
60
85
|
def additional_references
|
61
86
|
@mutex.synchronize { @additional_references }
|
data/lib/brick/extensions.rb
CHANGED
@@ -107,7 +107,8 @@ module ActiveRecord
|
|
107
107
|
bracket_name = nil
|
108
108
|
prefix = [prefix] unless prefix.is_a?(Array)
|
109
109
|
if (dsl = ::Brick.config.model_descrips[name] || brick_get_dsl)
|
110
|
-
dsl2 = +''
|
110
|
+
dsl2 = +'' # To replace our own DSL definition in case it needs to be expanded
|
111
|
+
dsl3 = +'' # To return expanded DSL that is nested from another model
|
111
112
|
klass = nil
|
112
113
|
dsl.each_char do |ch|
|
113
114
|
if bracket_name
|
@@ -129,11 +130,16 @@ module ActiveRecord
|
|
129
130
|
end
|
130
131
|
if klass.column_names.exclude?(parts.last) &&
|
131
132
|
(klass = (orig_class = klass).reflect_on_association(possible_dsl = parts.pop.to_sym)&.klass)
|
133
|
+
# Expand this entry which refers to an association name
|
132
134
|
members2, dsl2a = klass.brick_parse_dsl(build_array, prefix + [possible_dsl], translations, true)
|
133
135
|
members += members2
|
134
136
|
dsl2 << dsl2a
|
137
|
+
dsl3 << dsl2a
|
135
138
|
else
|
136
139
|
dsl2 << "[#{bracket_name}]"
|
140
|
+
if emit_dsl
|
141
|
+
dsl3 << "[#{prefix[1..-1].map { |p| "#{p.to_s}." }.join if prefix.length > 1}#{bracket_name}]"
|
142
|
+
end
|
137
143
|
members << parts
|
138
144
|
end
|
139
145
|
bracket_name = nil
|
@@ -145,15 +151,22 @@ module ActiveRecord
|
|
145
151
|
klass = self
|
146
152
|
else
|
147
153
|
dsl2 << ch
|
154
|
+
dsl3 << ch
|
148
155
|
end
|
149
156
|
end
|
150
157
|
# Rewrite the DSL in case it's now different from having to expand it
|
158
|
+
# if ::Brick.config.model_descrips[name] != dsl2
|
159
|
+
# puts ::Brick.config.model_descrips[name]
|
160
|
+
# puts dsl2.inspect
|
161
|
+
# puts dsl3.inspect
|
162
|
+
# binding.pry
|
163
|
+
# end
|
151
164
|
::Brick.config.model_descrips[name] = dsl2 unless emit_dsl
|
152
165
|
else # With no DSL available, still put this prefix into the JoinArray so we can get primary key (ID) info from this table
|
153
166
|
x = prefix.each_with_object(build_array) { |v, s| s[v.to_sym] }
|
154
167
|
x[prefix.last] = nil unless prefix.empty? # Using []= will "hydrate" any missing part(s) in our whole series
|
155
168
|
end
|
156
|
-
emit_dsl ? [members,
|
169
|
+
emit_dsl ? [members, dsl3] : members
|
157
170
|
end
|
158
171
|
|
159
172
|
# If available, parse simple DSL attached to a model in order to provide a friendlier name.
|
@@ -221,13 +234,21 @@ module ActiveRecord
|
|
221
234
|
end
|
222
235
|
|
223
236
|
def self.bt_link(assoc_name)
|
224
|
-
model_underscore = name.underscore
|
225
237
|
assoc_name = CGI.escapeHTML(assoc_name.to_s)
|
226
|
-
model_path = Rails.application.routes.url_helpers.send("#{
|
238
|
+
model_path = Rails.application.routes.url_helpers.send("#{_brick_index}_path".to_sym)
|
227
239
|
av_class = Class.new.extend(ActionView::Helpers::UrlHelper)
|
228
240
|
av_class.extend(ActionView::Helpers::TagHelper) if ActionView.version < ::Gem::Version.new('7')
|
229
241
|
link = av_class.link_to(name, model_path)
|
230
|
-
|
242
|
+
table_name == assoc_name ? link : "#{assoc_name}-#{link}".html_safe
|
243
|
+
end
|
244
|
+
|
245
|
+
def self._brick_index
|
246
|
+
tbl_parts = table_name.split('.')
|
247
|
+
tbl_parts.shift if ::Brick.apartment_multitenant && tbl_parts.first == Apartment.default_schema
|
248
|
+
if (index = tbl_parts.map(&:underscore).join('_')) == index.singularize
|
249
|
+
index << '_index' # Rails applies an _index suffix to that route when the resource name is singular
|
250
|
+
end
|
251
|
+
index
|
231
252
|
end
|
232
253
|
|
233
254
|
def self.brick_import_template
|
@@ -407,7 +428,7 @@ module ActiveRecord
|
|
407
428
|
is_distinct = nil
|
408
429
|
wheres = {}
|
409
430
|
params.each do |k, v|
|
410
|
-
next if ['_brick_schema', '_brick_order'].include?(k)
|
431
|
+
next if ['_brick_schema', '_brick_order', 'controller', 'action'].include?(k)
|
411
432
|
|
412
433
|
case (ks = k.split('.')).length
|
413
434
|
when 1
|
@@ -427,6 +448,9 @@ module ActiveRecord
|
|
427
448
|
# %%% Skip the metadata columns
|
428
449
|
if selects&.empty? # Default to all columns
|
429
450
|
tbl_no_schema = table.name.split('.').last
|
451
|
+
# %%% Have once gotten this error with MSSQL referring to http://localhost:3000/warehouse/cold_room_temperatures__archive
|
452
|
+
# ActiveRecord::StatementInvalid (TinyTds::Error: DBPROCESS is dead or not enabled)
|
453
|
+
# Relevant info here: https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/issues/402
|
430
454
|
columns.each do |col|
|
431
455
|
col_alias = " AS #{col.name}_" if (col_name = col.name) == 'class'
|
432
456
|
selects << if is_mysql
|
@@ -726,7 +750,8 @@ Module.class_exec do
|
|
726
750
|
# Vabc instead of VABC)
|
727
751
|
full_class_name = +''
|
728
752
|
full_class_name << "::#{self.name}" unless self == Object
|
729
|
-
|
753
|
+
singular_class_name = ::Brick.namify(plural_class_name, :underscore).singularize.camelize
|
754
|
+
full_class_name << "::#{singular_class_name}"
|
730
755
|
if plural_class_name == 'BrickSwagger' ||
|
731
756
|
(
|
732
757
|
(::Brick.config.add_status || ::Brick.config.add_orphans) &&
|
@@ -1111,64 +1136,63 @@ class Object
|
|
1111
1136
|
end
|
1112
1137
|
return [new_controller_class, code + "end # BrickGem controller\n"]
|
1113
1138
|
when 'BrickSwagger'
|
1114
|
-
is_swagger = true
|
1139
|
+
is_swagger = true
|
1115
1140
|
end
|
1116
1141
|
|
1117
1142
|
self.protect_from_forgery unless: -> { self.request.format.js? }
|
1118
1143
|
self.define_method :index do
|
1119
|
-
# We do all of this now so that bt_descrip and hm_counts are available on the model early in case the user
|
1120
|
-
# wants to do an ORDER BY based on any of that
|
1121
|
-
translations = {}
|
1122
|
-
join_array = ::Brick::JoinArray.new
|
1123
|
-
is_add_bts = is_add_hms = true
|
1124
|
-
# This builds out bt_descrip and hm_counts on the model
|
1125
|
-
model._brick_calculate_bts_hms(translations, join_array) if is_add_bts || is_add_hms
|
1126
|
-
|
1127
1144
|
if is_swagger
|
1128
|
-
|
1145
|
+
if !params&.key?('_brick_schema') &&
|
1146
|
+
(referrer_params = request.env['HTTP_REFERER']&.split('?')&.last&.split('&')&.map { |x| x.split('=') }).present?
|
1147
|
+
if params
|
1148
|
+
referrer_params.each { |k, v| params.send(:parameters)[k] = v }
|
1149
|
+
else
|
1150
|
+
api_params = referrer_params&.to_h
|
1151
|
+
end
|
1152
|
+
end
|
1153
|
+
::Brick.set_db_schema(params || api_params)
|
1154
|
+
json = { 'openapi': '3.0.1', 'info': { 'title': Rswag::Ui.config.config_object[:urls].last&.fetch(:name, 'API documentation'), 'version': ::Brick.config.api_version },
|
1129
1155
|
'servers': [
|
1130
|
-
{ 'url': '
|
1156
|
+
{ 'url': '{scheme}://{defaultHost}', 'variables': {
|
1157
|
+
'scheme': { 'default': request.env['rack.url_scheme'] },
|
1158
|
+
'defaultHost': { 'default': request.env['HTTP_HOST'] }
|
1159
|
+
} }
|
1131
1160
|
]
|
1132
1161
|
}
|
1133
|
-
json['paths'] = relations.inject({}) do |s,
|
1134
|
-
|
1135
|
-
|
1136
|
-
|
1137
|
-
'
|
1138
|
-
|
1139
|
-
|
1140
|
-
|
1141
|
-
|
1142
|
-
|
1143
|
-
|
1144
|
-
|
1145
|
-
|
1146
|
-
|
1147
|
-
|
1148
|
-
|
1149
|
-
'responses': { '200': { 'description': 'successful' } }
|
1162
|
+
json['paths'] = relations.inject({}) do |s, relation|
|
1163
|
+
unless ::Brick.config.enable_api == false
|
1164
|
+
table_description = relation.last[:description]
|
1165
|
+
s["#{::Brick.config.api_root}#{relation.first.tr('.', '/')}"] = {
|
1166
|
+
'get': {
|
1167
|
+
'summary': "list #{relation.first}",
|
1168
|
+
'description': table_description,
|
1169
|
+
'parameters': relation.last[:cols].map do |k, v|
|
1170
|
+
param = { 'name' => k, 'schema': { 'type': v.first } }
|
1171
|
+
if (col_descrip = relation.last.fetch(:col_descrips, nil)&.fetch(k, nil))
|
1172
|
+
param['description'] = col_descrip
|
1173
|
+
end
|
1174
|
+
param
|
1175
|
+
end,
|
1176
|
+
'responses': { '200': { 'description': 'successful' } }
|
1177
|
+
}
|
1150
1178
|
}
|
1151
|
-
|
1152
|
-
#
|
1153
|
-
|
1154
|
-
|
1155
|
-
|
1156
|
-
|
1157
|
-
|
1158
|
-
|
1159
|
-
|
1160
|
-
|
1161
|
-
|
1162
|
-
|
1163
|
-
|
1164
|
-
|
1165
|
-
|
1166
|
-
|
1167
|
-
|
1168
|
-
# }
|
1169
|
-
# ],
|
1170
|
-
}
|
1171
|
-
s
|
1179
|
+
|
1180
|
+
s["#{::Brick.config.api_root}#{relation.first.tr('.', '/')}/{id}"] = {
|
1181
|
+
'patch': {
|
1182
|
+
'summary': "update a #{relation.first.singularize}",
|
1183
|
+
'description': table_description,
|
1184
|
+
'parameters': relation.last[:cols].reject { |k, v| Brick.config.metadata_columns.include?(k) }.map do |k, v|
|
1185
|
+
param = { 'name' => k, 'schema': { 'type': v.first } }
|
1186
|
+
if (col_descrip = relation.last.fetch(:col_descrips, nil)&.fetch(k, nil))
|
1187
|
+
param['description'] = col_descrip
|
1188
|
+
end
|
1189
|
+
param
|
1190
|
+
end,
|
1191
|
+
'responses': { '200': { 'description': 'successful' } }
|
1192
|
+
}
|
1193
|
+
} unless relation.last.fetch(:isView, nil)
|
1194
|
+
s
|
1195
|
+
end
|
1172
1196
|
end
|
1173
1197
|
render inline: json.to_json, content_type: request.format
|
1174
1198
|
return
|
@@ -1176,6 +1200,14 @@ class Object
|
|
1176
1200
|
|
1177
1201
|
# Normal (non-swagger) request
|
1178
1202
|
|
1203
|
+
# We do all of this now so that bt_descrip and hm_counts are available on the model early in case the user
|
1204
|
+
# wants to do an ORDER BY based on any of that
|
1205
|
+
translations = {}
|
1206
|
+
join_array = ::Brick::JoinArray.new
|
1207
|
+
is_add_bts = is_add_hms = true
|
1208
|
+
# This builds out bt_descrip and hm_counts on the model
|
1209
|
+
model._brick_calculate_bts_hms(translations, join_array) if is_add_bts || is_add_hms
|
1210
|
+
|
1179
1211
|
# %%% Allow params to define which columns to use for order_by
|
1180
1212
|
# Overriding the default by providing a querystring param?
|
1181
1213
|
ordering = params['_brick_order']&.split(',')&.map(&:to_sym) || Object.send(:default_ordering, table_name, pk)
|
@@ -1189,8 +1221,9 @@ class Object
|
|
1189
1221
|
end
|
1190
1222
|
render inline: exported_csv, content_type: request.format
|
1191
1223
|
return
|
1192
|
-
elsif request.format == :js # Asking for JSON?
|
1193
|
-
|
1224
|
+
elsif request.format == :js || request.path.start_with?('/api/') # Asking for JSON?
|
1225
|
+
data = (model.is_view? || !Object.const_defined?('DutyFree')) ? model.limit(1000) : model.df_export(model.brick_import_template)
|
1226
|
+
render inline: data.to_json, content_type: request.format == '*/*' ? 'application/json' : request.format
|
1194
1227
|
return
|
1195
1228
|
end
|
1196
1229
|
|
@@ -1206,7 +1239,7 @@ class Object
|
|
1206
1239
|
"b_r_#{v.first}.c_t_ AS \"b_r_#{v.first}_ct\""
|
1207
1240
|
end
|
1208
1241
|
end
|
1209
|
-
instance_variable_set("@#{table_name}".to_sym, ar_relation.dup._select!(*selects, *counts))
|
1242
|
+
instance_variable_set("@#{table_name.pluralize}".to_sym, ar_relation.dup._select!(*selects, *counts))
|
1210
1243
|
if namespace && (idx = lookup_context.prefixes.index(table_name))
|
1211
1244
|
lookup_context.prefixes[idx] = "#{namespace.name.underscore}/#{lookup_context.prefixes[idx]}"
|
1212
1245
|
end
|
@@ -1221,32 +1254,34 @@ class Object
|
|
1221
1254
|
@_brick_erd = params['_brick_erd']&.to_i
|
1222
1255
|
end
|
1223
1256
|
|
1224
|
-
|
1225
|
-
|
1226
|
-
|
1227
|
-
|
1228
|
-
|
1229
|
-
|
1230
|
-
is_pk_string = nil
|
1231
|
-
if (pk_col = model&.primary_key)
|
1232
|
-
code << " def show\n"
|
1233
|
-
code << " #{find_by_name = "find_#{singular_table_name}"}\n"
|
1257
|
+
unless is_swagger
|
1258
|
+
::Brick.set_db_schema
|
1259
|
+
_, order_by_txt = model._brick_calculate_ordering(default_ordering(table_name, pk)) if pk
|
1260
|
+
code << " def index\n"
|
1261
|
+
code << " @#{table_name.pluralize} = #{model.name}#{pk&.present? ? ".order(#{order_by_txt.join(', ')})" : '.all'}\n"
|
1262
|
+
code << " @#{table_name.pluralize}.brick_select(params)\n"
|
1234
1263
|
code << " end\n"
|
1235
|
-
|
1236
|
-
|
1237
|
-
|
1238
|
-
|
1239
|
-
|
1240
|
-
|
1241
|
-
|
1242
|
-
|
1243
|
-
|
1244
|
-
|
1264
|
+
|
1265
|
+
is_pk_string = nil
|
1266
|
+
if pk.present?
|
1267
|
+
code << " def show\n"
|
1268
|
+
code << " #{find_by_name = "find_#{singular_table_name}"}\n"
|
1269
|
+
code << " end\n"
|
1270
|
+
self.define_method :show do
|
1271
|
+
::Brick.set_db_schema(params)
|
1272
|
+
id = if model.columns_hash[pk.first]&.type == :string
|
1273
|
+
is_pk_string = true
|
1274
|
+
params[:id]
|
1275
|
+
else
|
1276
|
+
params[:id]&.split(/[\/,_]/)
|
1277
|
+
end
|
1278
|
+
id = id.first if id.is_a?(Array) && id.length == 1
|
1279
|
+
instance_variable_set("@#{singular_table_name}".to_sym, find_obj)
|
1280
|
+
end
|
1245
1281
|
end
|
1246
|
-
end
|
1247
1282
|
|
1248
|
-
|
1249
|
-
|
1283
|
+
# By default, views get marked as read-only
|
1284
|
+
# unless model.readonly # (relation = relations[model.table_name]).key?(:isView)
|
1250
1285
|
code << " def new\n"
|
1251
1286
|
code << " @#{singular_table_name} = #{model.name}.new\n"
|
1252
1287
|
code << " end\n"
|
@@ -1280,7 +1315,7 @@ class Object
|
|
1280
1315
|
end
|
1281
1316
|
end
|
1282
1317
|
|
1283
|
-
if
|
1318
|
+
if pk.present?
|
1284
1319
|
# if (schema = ::Brick.config.schema_behavior[:multitenant]&.fetch(:schema_to_analyse, nil)) && ::Brick.db_schemas&.include?(schema)
|
1285
1320
|
# ActiveRecord::Base.execute_sql("SET SEARCH_PATH = ?;", schema)
|
1286
1321
|
# end
|
@@ -1327,9 +1362,9 @@ class Object
|
|
1327
1362
|
end
|
1328
1363
|
end
|
1329
1364
|
|
1330
|
-
code << "private\n" if
|
1365
|
+
code << "private\n" if pk.present? || is_need_params
|
1331
1366
|
|
1332
|
-
if
|
1367
|
+
if pk.present?
|
1333
1368
|
code << " def find_#{singular_table_name}
|
1334
1369
|
id = params[:id]&.split(/[\\/,_]/)
|
1335
1370
|
@#{singular_table_name} = #{model.name}.find(id.is_a?(Array) && id.length == 1 ? id.first : id)
|
@@ -1357,16 +1392,16 @@ class Object
|
|
1357
1392
|
private params_name
|
1358
1393
|
# Get column names for params from relations[model.table_name][:cols].keys
|
1359
1394
|
end
|
1360
|
-
#
|
1395
|
+
end # unless is_swagger
|
1361
1396
|
code << "end # #{namespace_name}#{class_name}\n"
|
1362
1397
|
end # class definition
|
1363
1398
|
[built_controller, code]
|
1364
1399
|
end
|
1365
1400
|
|
1366
1401
|
def _brick_get_hm_assoc_name(relation, hm_assoc, source = nil)
|
1367
|
-
if (relation[:hm_counts][hm_assoc[:
|
1402
|
+
if (relation[:hm_counts][hm_assoc[:inverse_table]]&.> 1) &&
|
1368
1403
|
hm_assoc[:alternate_name] != (source || name.underscore)
|
1369
|
-
plural = ActiveSupport::Inflector.pluralize(hm_assoc[:alternate_name])
|
1404
|
+
plural = "#{hm_assoc[:assoc_name]}_#{ActiveSupport::Inflector.pluralize(hm_assoc[:alternate_name])}"
|
1370
1405
|
new_alt_name = (hm_assoc[:alternate_name] == name.underscore) ? "#{hm_assoc[:assoc_name].singularize}_#{plural}" : plural
|
1371
1406
|
# uniq = 1
|
1372
1407
|
# while same_name = relation[:fks].find { |x| x.last[:assoc_name] == hm_assoc[:assoc_name] && x.last != hm_assoc }
|
@@ -1497,6 +1532,8 @@ module ActiveRecord::ConnectionHandling
|
|
1497
1532
|
r['schema']
|
1498
1533
|
end
|
1499
1534
|
relation_name = schema_name ? "#{schema_name}.#{r['relation_name']}" : r['relation_name']
|
1535
|
+
# Both uppers and lowers as well as underscores?
|
1536
|
+
apply_double_underscore_patch if relation_name =~ /[A-Z]/ && relation_name =~ /[a-z]/ && relation_name.index('_')
|
1500
1537
|
relation = relations[relation_name]
|
1501
1538
|
relation[:isView] = true if r['table_type'] == 'VIEW'
|
1502
1539
|
relation[:description] = r['table_description'] if r['table_description']
|
@@ -1513,6 +1550,7 @@ module ActiveRecord::ConnectionHandling
|
|
1513
1550
|
cols = relation[:cols] # relation.fetch(:cols) { relation[:cols] = [] }
|
1514
1551
|
cols[col_name] = [r['data_type'], r['max_length'], measures&.include?(col_name), r['is_nullable'] == 'NO']
|
1515
1552
|
# puts "KEY! #{r['relation_name']}.#{col_name} #{r['key']} #{r['const']}" if r['key']
|
1553
|
+
relation[:col_descrips][col_name] = r['column_description'] if r['column_description']
|
1516
1554
|
end
|
1517
1555
|
else # MySQL2 and OracleEnhanced act a little differently, bringing back an array for each row
|
1518
1556
|
schema_and_tables = case ActiveRecord::Base.connection.adapter_name
|
@@ -1542,6 +1580,9 @@ ORDER BY 1, 2, c.internal_column_id, acc.position"
|
|
1542
1580
|
|
1543
1581
|
if (relation_name = r[1]) =~ /^[A-Z0-9_]+$/
|
1544
1582
|
relation_name.downcase!
|
1583
|
+
# Both uppers and lowers as well as underscores?
|
1584
|
+
elsif relation_name =~ /[A-Z]/ && relation_name =~ /[a-z]/ && relation_name.index('_')
|
1585
|
+
apply_double_underscore_patch
|
1545
1586
|
end
|
1546
1587
|
# Expect the default schema for SQL Server to be 'dbo'.
|
1547
1588
|
if (::Brick.is_oracle && r[0] != schema) || (is_mssql && r[0] != 'dbo')
|
@@ -1668,7 +1709,7 @@ ORDER BY 1, 2, c.internal_column_id, acc.position"
|
|
1668
1709
|
name_parts = k.split('.')
|
1669
1710
|
idx = 1
|
1670
1711
|
name_parts = name_parts.map do |x|
|
1671
|
-
(idx += 1)
|
1712
|
+
(idx += 1) <= name_parts.length ? x : x.singularize
|
1672
1713
|
end
|
1673
1714
|
name_parts.shift if apartment && name_parts.length > 1 && name_parts.first == Apartment.default_schema
|
1674
1715
|
class_name = name_parts.map(&:camelize).join('::')
|
@@ -1696,7 +1737,7 @@ ORDER BY 1, 2, c.internal_column_id, acc.position"
|
|
1696
1737
|
def display_classes(rels, max_length)
|
1697
1738
|
rels.sort.each do |rel|
|
1698
1739
|
rel_link = rel.last.dup.map(&:underscore)
|
1699
|
-
rel_link[-1] = rel_link[-1]
|
1740
|
+
rel_link[-1] = rel_link[-1]
|
1700
1741
|
puts "#{rel.first}#{' ' * (max_length - rel.first.length)} /#{rel_link.join('/')}"
|
1701
1742
|
end
|
1702
1743
|
puts "\n"
|
@@ -1706,8 +1747,11 @@ ORDER BY 1, 2, c.internal_column_id, acc.position"
|
|
1706
1747
|
is_mssql = ActiveRecord::Base.connection.adapter_name == 'SQLServer' if is_mssql.nil?
|
1707
1748
|
sql ||= "SELECT t.table_schema AS \"schema\", t.table_name AS relation_name, t.table_type,#{"
|
1708
1749
|
pg_catalog.obj_description(
|
1709
|
-
('\"' || t.table_schema || '\".\"' || t.table_name || '\"')::regclass, 'pg_class'
|
1710
|
-
) AS table_description,
|
1750
|
+
('\"' || t.table_schema || '\".\"' || t.table_name || '\"')::regclass::oid, 'pg_class'
|
1751
|
+
) AS table_description,
|
1752
|
+
pg_catalog.col_description(
|
1753
|
+
('\"' || t.table_schema || '\".\"' || t.table_name || '\"')::regclass::oid, c.ordinal_position
|
1754
|
+
) AS column_description," if is_postgres}
|
1711
1755
|
c.column_name, c.data_type,
|
1712
1756
|
COALESCE(c.character_maximum_length, c.numeric_precision) AS max_length,
|
1713
1757
|
kcu.constraint_type AS const, kcu.constraint_name AS \"key\",
|
@@ -1751,6 +1795,43 @@ ORDER BY 1, 2, c.internal_column_id, acc.position"
|
|
1751
1795
|
ar_imtn = ActiveRecord.version >= ::Gem::Version.new('5.0') ? ActiveRecord::Base.internal_metadata_table_name : ''
|
1752
1796
|
[ar_smtn, ar_imtn]
|
1753
1797
|
end
|
1798
|
+
|
1799
|
+
def apply_double_underscore_patch
|
1800
|
+
unless @double_underscore_applied
|
1801
|
+
# Same as normal #camelize and #underscore, just that double-underscores turn into a single underscore
|
1802
|
+
ActiveSupport::Inflector.class_eval do
|
1803
|
+
def camelize(term, uppercase_first_letter = true)
|
1804
|
+
strings = term.to_s.split('__').map do |string|
|
1805
|
+
# String#camelize takes a symbol (:upper or :lower), so here we also support :lower to keep the methods consistent.
|
1806
|
+
if !uppercase_first_letter || uppercase_first_letter == :lower
|
1807
|
+
string = string.sub(inflections.acronyms_camelize_regex) { |match| match.downcase! || match }
|
1808
|
+
else
|
1809
|
+
string = string.sub(/^[a-z\d]*/) { |match| inflections.acronyms[match] || match.capitalize! || match }
|
1810
|
+
end
|
1811
|
+
string.gsub!(/(?:_|(\/))([a-z\d]*)/i) do
|
1812
|
+
word = $2
|
1813
|
+
substituted = inflections.acronyms[word] || word.capitalize! || word
|
1814
|
+
$1 ? "::#{substituted}" : substituted
|
1815
|
+
end
|
1816
|
+
string
|
1817
|
+
end
|
1818
|
+
strings.join('_')
|
1819
|
+
end
|
1820
|
+
|
1821
|
+
def underscore(camel_cased_word)
|
1822
|
+
return camel_cased_word.to_s unless /[A-Z-]|::/.match?(camel_cased_word)
|
1823
|
+
camel_cased_word.to_s.gsub("::", "/").split('_').map do |word|
|
1824
|
+
word.gsub!(inflections.acronyms_underscore_regex) { "#{$1 && '_' }#{$2.downcase}" }
|
1825
|
+
word.gsub!(/([A-Z]+)(?=[A-Z][a-z])|([a-z\d])(?=[A-Z])/) { ($1 || $2) << "_" }
|
1826
|
+
word.tr!("-", "_")
|
1827
|
+
word.downcase!
|
1828
|
+
word
|
1829
|
+
end.join('__')
|
1830
|
+
end
|
1831
|
+
end
|
1832
|
+
@double_underscore_applied = true
|
1833
|
+
end
|
1834
|
+
end
|
1754
1835
|
end
|
1755
1836
|
|
1756
1837
|
# ==========================================
|
@@ -1777,7 +1858,7 @@ module Brick
|
|
1777
1858
|
|
1778
1859
|
class << self
|
1779
1860
|
def _add_bt_and_hm(fk, relations, is_polymorphic = false, is_optional = false)
|
1780
|
-
bt_assoc_name = ::Brick.namify(fk[2],
|
1861
|
+
bt_assoc_name = ::Brick.namify(fk[2], :downcase)
|
1781
1862
|
unless is_polymorphic
|
1782
1863
|
bt_assoc_name = if bt_assoc_name.underscore.end_with?('_id')
|
1783
1864
|
bt_assoc_name[-3] == '_' ? bt_assoc_name[0..-4] : bt_assoc_name[0..-3]
|
@@ -1878,6 +1959,11 @@ module Brick
|
|
1878
1959
|
|
1879
1960
|
return if is_class || ::Brick.config.exclude_hms&.any? { |exclusion| fk[1] == exclusion[0] && fk[2] == exclusion[1] && primary_table == exclusion[2] } || hms.nil?
|
1880
1961
|
|
1962
|
+
# if fk[1].end_with?('Suppliers') && fk[4] == 'People'
|
1963
|
+
# puts fk.inspect
|
1964
|
+
# binding.pry
|
1965
|
+
# end
|
1966
|
+
|
1881
1967
|
if (assoc_hm = hms.fetch((hm_cnstr_name = "hm_#{cnstr_name}"), nil))
|
1882
1968
|
if assoc_hm[:fk].is_a?(String)
|
1883
1969
|
assoc_hm[:fk] = [assoc_hm[:fk], fk[2]] unless fk[2] == assoc_hm[:fk]
|
@@ -1885,7 +1971,6 @@ module Brick
|
|
1885
1971
|
assoc_hm[:fk] << fk[2]
|
1886
1972
|
end
|
1887
1973
|
assoc_hm[:alternate_name] = "#{assoc_hm[:alternate_name]}_#{bt_assoc_name}" unless assoc_hm[:alternate_name] == bt_assoc_name
|
1888
|
-
assoc_hm[:inverse] = assoc_bt
|
1889
1974
|
else
|
1890
1975
|
inv_tbl = if ::Brick.config.schema_behavior[:multitenant] && apartment && fk[0] == Apartment.default_schema
|
1891
1976
|
for_tbl
|
@@ -1896,7 +1981,7 @@ module Brick
|
|
1896
1981
|
inverse_table: inv_tbl, inverse: assoc_bt }
|
1897
1982
|
assoc_hm[:polymorphic] = true if is_polymorphic
|
1898
1983
|
hm_counts = relation.fetch(:hm_counts) { relation[:hm_counts] = {} }
|
1899
|
-
hm_counts[fk[1]] = hm_counts.fetch(fk[1]) { 0 } + 1
|
1984
|
+
this_hm_count = hm_counts[fk[1]] = hm_counts.fetch(fk[1]) { 0 } + 1
|
1900
1985
|
end
|
1901
1986
|
assoc_bt[:inverse] = assoc_hm
|
1902
1987
|
end
|
@@ -159,7 +159,7 @@ module Brick
|
|
159
159
|
hms_columns << hm_entry
|
160
160
|
when 'show', 'new', 'update'
|
161
161
|
hm_stuff << if hm_fk_name
|
162
|
-
"<%= link_to '#{assoc_name}', #{hm_assoc.klass.
|
162
|
+
"<%= link_to '#{assoc_name}', #{hm_assoc.klass._brick_index}_path({ #{path_keys(hm_assoc, hm_fk_name, "@#{obj_name}", pk)} }) %>\n"
|
163
163
|
else # %%% Would be able to remove this when multiple foreign keys to same destination becomes bulletproof
|
164
164
|
assoc_name
|
165
165
|
end
|
@@ -173,12 +173,13 @@ module Brick
|
|
173
173
|
# environment or whatever, then get either the controllers or routes list instead
|
174
174
|
apartment_default_schema = ::Brick.apartment_multitenant && Apartment.default_schema
|
175
175
|
table_options = (::Brick.relations.keys - ::Brick.config.exclude_tables).each_with_object({}) do |tbl, s|
|
176
|
+
binding.pry if tbl.is_a?(Symbol)
|
176
177
|
if (tbl_parts = tbl.split('.')).first == apartment_default_schema
|
177
178
|
tbl = tbl_parts.last
|
178
179
|
end
|
179
180
|
s[tbl] = nil
|
180
181
|
end.keys.sort.each_with_object(+'') do |v, s|
|
181
|
-
s << "<option value=\"#{v.underscore.gsub('.', '/')
|
182
|
+
s << "<option value=\"#{v.underscore.gsub('.', '/')}\">#{v}</option>"
|
182
183
|
end.html_safe
|
183
184
|
table_options << '<option value="brick_status">(Status)</option>'.html_safe if ::Brick.config.add_status
|
184
185
|
table_options << '<option value="brick_orphans">(Orphans)</option>'.html_safe if is_orphans
|
@@ -351,15 +352,39 @@ def hide_bcrypt(val, max_len = 200)
|
|
351
352
|
end
|
352
353
|
def display_value(col_type, val)
|
353
354
|
case col_type
|
354
|
-
when 'geometry'
|
355
|
+
when 'geometry', 'geography'
|
355
356
|
if Object.const_defined?('RGeo')
|
356
357
|
@is_mysql = ActiveRecord::Base.connection.adapter_name == 'Mysql2' if @is_mysql.nil?
|
357
|
-
if @
|
358
|
-
|
359
|
-
|
360
|
-
|
358
|
+
@is_mssql = ActiveRecord::Base.connection.adapter_name == 'SQLServer' if @is_mssql.nil?
|
359
|
+
val_err = nil
|
360
|
+
if @is_mysql || @is_mssql
|
361
|
+
# MySQL's \"Internal Geometry Format\" and MSSQL's Geography are like WKB, but with an initial 4 bytes that indicates the SRID.
|
362
|
+
if (srid = val&.[](0..3)&.unpack('I'))
|
363
|
+
val = val.force_encoding('BINARY')[4..-1].bytes
|
364
|
+
|
365
|
+
# MSSQL spatial bitwise flags, often 0C for a point:
|
366
|
+
# xxxx xxx1 = HasZValues
|
367
|
+
# xxxx xx1x = HasMValues
|
368
|
+
# xxxx x1xx = IsValid
|
369
|
+
# xxxx 1xxx = IsSinglePoint
|
370
|
+
# xxx1 xxxx = IsSingleLineSegment
|
371
|
+
# xx1x xxxx = IsWholeGlobe
|
372
|
+
# Convert Microsoft's unique geography binary to standard WKB
|
373
|
+
# (MSSQL point usually has two doubles, lng / lat, and can also have Z)
|
374
|
+
if @is_mssql
|
375
|
+
if val[0] == 1 && (val[1] & 8 > 0) && # Single point?
|
376
|
+
(val.length - 2) % 8 == 0 && val.length < 27 # And containing up to three 8-byte values?
|
377
|
+
idx = 2
|
378
|
+
new_val = [0, 0, 0, 0, 1]
|
379
|
+
new_val.concat(val[idx - 8...idx].reverse) while (idx += 8) <= val.length
|
380
|
+
val = new_val
|
381
|
+
else
|
382
|
+
val_err = '(Microsoft internal SQL geography type)'
|
383
|
+
end
|
384
|
+
end
|
385
|
+
end
|
361
386
|
end
|
362
|
-
RGeo::WKRep::WKBParser.new.parse(val)
|
387
|
+
val_err || (val ? RGeo::WKRep::WKBParser.new.parse(val.pack('c*')) : nil)
|
363
388
|
else
|
364
389
|
'(Add RGeo gem to parse geometry detail)'
|
365
390
|
end
|
@@ -448,7 +473,7 @@ function changeout(href, param, value, trimAfter) {
|
|
448
473
|
var params = hrefParts.length > 1 ? hrefParts[1].split(\"&\") : [];
|
449
474
|
if (param === undefined || param === null || param === -1) {
|
450
475
|
hrefParts = hrefParts[0].split(\"://\");
|
451
|
-
var pathParts = hrefParts[hrefParts.length - 1].split(\"/\");
|
476
|
+
var pathParts = hrefParts[hrefParts.length - 1].split(\"/\").filter(function (pp) {return pp !== \"\";});
|
452
477
|
if (value === undefined)
|
453
478
|
// A couple possibilities if it's namespaced, starting with two parts in the path -- and then try just one
|
454
479
|
return [pathParts.slice(1, 3).join('/'), pathParts.slice(1, 2)[0]];
|
@@ -562,7 +587,7 @@ erDiagram
|
|
562
587
|
<%= \"#\{model_short_name} }o..o{ #\{hm_name} : \\\"#\{hm.first}\\\"\".html_safe %><%
|
563
588
|
else # has_many
|
564
589
|
%> <%= \"#\{model_short_name} ||--o{ #\{hm_name} : \\\"#\{
|
565
|
-
|
590
|
+
hm.first.to_s unless hm.first.to_s.downcase == hm_class.name.underscore.pluralize.tr('/', '_')
|
566
591
|
}\\\"\".html_safe %><%
|
567
592
|
end %>
|
568
593
|
<% end
|
@@ -604,7 +629,7 @@ erDiagram
|
|
604
629
|
end
|
605
630
|
if Object.const_defined?('DutyFree')
|
606
631
|
template_link = "
|
607
|
-
<%= link_to 'CSV', #{
|
632
|
+
<%= link_to 'CSV', #{@_brick_model._brick_index}_path(format: :csv) %> <a href=\"#\" id=\"sheetsLink\">Sheets</a>
|
608
633
|
<div id=\"dropper\" contenteditable=\"true\"></div>
|
609
634
|
<input type=\"button\" id=\"btnImport\" value=\"Import\">
|
610
635
|
|
@@ -667,7 +692,7 @@ erDiagram
|
|
667
692
|
console.log(\"x1\", sheetUrl);
|
668
693
|
|
669
694
|
// Get JSON data
|
670
|
-
fetch(changeout(<%= #{
|
695
|
+
fetch(changeout(<%= #{@_brick_model._brick_index}_path(format: :js).inspect.html_safe %>, \"_brick_schema\", brickSchema)).then(function (response) {
|
671
696
|
response.json().then(function (data) {
|
672
697
|
gapi.client.sheets.spreadsheets.values.append({
|
673
698
|
spreadsheetId: spreadsheetId,
|
@@ -698,7 +723,7 @@ erDiagram
|
|
698
723
|
<select id=\"schema\">#{schema_options}</select>" if ::Brick.config.schema_behavior[:multitenant] && ::Brick.db_schemas.length > 1}
|
699
724
|
<select id=\"tbl\">#{table_options}</select>
|
700
725
|
<table id=\"resourceName\"><tr>
|
701
|
-
<td><h1>#{
|
726
|
+
<td><h1>#{model_name}</h1></td>
|
702
727
|
<td id=\"imgErd\" title=\"Show ERD\"></td>
|
703
728
|
</tr></table>#{template_link}<%
|
704
729
|
if (description = (relation = Brick.relations[#{model_name}.table_name])&.fetch(:description, nil)) %><%=
|
@@ -712,10 +737,10 @@ erDiagram
|
|
712
737
|
origin = (key_parts = k.split('.')).length == 1 ? #{model_name} : #{model_name}.reflect_on_association(key_parts.first).klass
|
713
738
|
if (destination_fk = Brick.relations[origin.table_name][:fks].values.find { |fk| fk[:fk] == key_parts.last }) &&
|
714
739
|
(obj = (destination = origin.reflect_on_association(destination_fk[:assoc_name])&.klass)&.find(id)) %>
|
715
|
-
<h3>for <%= link_to \"#{"#\{obj.brick_descrip\} (#\{destination.name\})\""}, send(\"#\{destination.
|
740
|
+
<h3>for <%= link_to \"#{"#\{obj.brick_descrip\} (#\{destination.name\})\""}, send(\"#\{destination._brick_index\}_path\".to_sym, id) %></h3><%
|
716
741
|
end
|
717
742
|
end %>
|
718
|
-
(<%= link_to 'See all #{
|
743
|
+
(<%= link_to 'See all #{model_name.split('::').last.pluralize}', #{@_brick_model._brick_index}_path %>)
|
719
744
|
<% end
|
720
745
|
# COLUMN EXCLUSIONS
|
721
746
|
if @_brick_excl&.present? %>
|
@@ -768,7 +793,7 @@ erDiagram
|
|
768
793
|
end
|
769
794
|
elsif col # HM column
|
770
795
|
s << \"<th#\{' x-order=\"' + col_name + '\"' if true}>#\{col[2]} \"
|
771
|
-
s << (col.first ? \"#\{col[3]}\" : \"#\{link_to(col[3], send(\"#\{col[1].
|
796
|
+
s << (col.first ? \"#\{col[3]}\" : \"#\{link_to(col[3], send(\"#\{col[1]._brick_index}_path\"))}\")
|
772
797
|
else # Bad column name!
|
773
798
|
s << \"<th title=\\\"<< Unknown column >>\\\">#\{col_name}\"
|
774
799
|
end
|
@@ -776,7 +801,11 @@ erDiagram
|
|
776
801
|
end.html_safe
|
777
802
|
%></tr></thead>
|
778
803
|
<tbody>
|
779
|
-
<%
|
804
|
+
<% # %%% Have once gotten this error with MSSQL referring to http://localhost:3000/warehouse/cold_room_temperatures__archive
|
805
|
+
# ActiveRecord::StatementTimeout in Warehouse::ColdRoomTemperatures_Archive#index
|
806
|
+
# TinyTds::Error: Adaptive Server connection timed out
|
807
|
+
# (After restarting the server it worked fine again.)
|
808
|
+
@#{table_name}.each do |#{obj_name}|
|
780
809
|
hms_cols = {#{hms_columns.join(', ')}} %>
|
781
810
|
<tr>#{"
|
782
811
|
<td><%= link_to '⇛', #{path_obj_name}_path(#{obj_pk}), { class: 'big-arrow' } %></td>" if obj_pk}
|
@@ -811,10 +840,11 @@ erDiagram
|
|
811
840
|
else
|
812
841
|
\"#\{hms_col[1] || 'View'\} #\{hms_col.first}\"
|
813
842
|
end %>
|
814
|
-
<%= link_to txt, send(\"#\{klass.
|
843
|
+
<%= link_to txt, send(\"#\{klass._brick_index}_path\".to_sym, hms_col[2]) unless hms_col[1]&.zero? %>
|
815
844
|
<% end
|
816
845
|
elsif (col = cols[col_name])
|
817
|
-
|
846
|
+
col_type = col&.sql_type == 'geography' ? col.sql_type : col&.type
|
847
|
+
%><%= display_value(col_type || col&.sql_type, val) %><%
|
818
848
|
else # Bad column name!
|
819
849
|
%>?<%
|
820
850
|
end
|
@@ -908,7 +938,7 @@ erDiagram
|
|
908
938
|
if (description = (relation = Brick.relations[#{model_name}.table_name])&.fetch(:description, nil)) %><%=
|
909
939
|
description %><br><%
|
910
940
|
end
|
911
|
-
%><%= link_to '(See all #{obj_name.pluralize})', #{
|
941
|
+
%><%= link_to '(See all #{obj_name.pluralize})', #{@_brick_model._brick_index}_path %>
|
912
942
|
#{erd_markup}
|
913
943
|
<% if obj %>
|
914
944
|
<br><br>
|
@@ -974,7 +1004,8 @@ end
|
|
974
1004
|
\"<span class=\\\"orphan\\\">Orphaned ID: #\{val}</span>\".html_safe
|
975
1005
|
end %>
|
976
1006
|
<% else
|
977
|
-
|
1007
|
+
col_type = col.sql_type == 'geography' ? col.sql_type : col.type
|
1008
|
+
case (col_type ||= col.sql_type)
|
978
1009
|
when :string, :text %>
|
979
1010
|
<% if is_bcrypt?(val) # || .readonly?
|
980
1011
|
is_revert = false %>
|
@@ -1008,8 +1039,8 @@ end
|
|
1008
1039
|
<% when :binary, :primary_key
|
1009
1040
|
is_revert = false %>
|
1010
1041
|
<% else %>
|
1011
|
-
<%=
|
1012
|
-
|
1042
|
+
<%= is_revert = false
|
1043
|
+
display_value(col_type, val) %>
|
1013
1044
|
<% end
|
1014
1045
|
end
|
1015
1046
|
if is_revert
|
@@ -1077,7 +1108,7 @@ flatpickr(\".timepicker\", {enableTime: true, noCalendar: true});
|
|
1077
1108
|
var imgErd = document.getElementById(\"imgErd\");
|
1078
1109
|
var mermaidErd = document.getElementById(\"mermaidErd\");
|
1079
1110
|
var mermaidCode;
|
1080
|
-
var cbs = {<%= callbacks.map { |k, v| \"#\{k}: \\\"#\{v.
|
1111
|
+
var cbs = {<%= callbacks.map { |k, v| \"#\{k}: \\\"#\{send(\"#\{v._brick_index}_path\".to_sym)}\\\"\" }.join(', ').html_safe %>};
|
1081
1112
|
if (imgErd) imgErd.addEventListener(\"click\", showErd);
|
1082
1113
|
function showErd() {
|
1083
1114
|
imgErd.style.display = \"none\";
|
@@ -1101,7 +1132,7 @@ flatpickr(\".timepicker\", {enableTime: true, noCalendar: true});
|
|
1101
1132
|
function (evt) {
|
1102
1133
|
location.href = changeout(changeout(
|
1103
1134
|
changeout(location.href, '_brick_order', null), // Remove any ordering
|
1104
|
-
-1, cbs[this.id]), \"_brick_erd\", \"1\");
|
1135
|
+
-1, cbs[this.id].replace(/^[\/]+/, \"\")), \"_brick_erd\", \"1\");
|
1105
1136
|
}
|
1106
1137
|
);
|
1107
1138
|
}
|
data/lib/brick/version_number.rb
CHANGED
data/lib/brick.rb
CHANGED
@@ -125,8 +125,8 @@ module Brick
|
|
125
125
|
class << self
|
126
126
|
attr_accessor :default_schema, :db_schemas, :routes_done, :is_oracle
|
127
127
|
|
128
|
-
def set_db_schema(params)
|
129
|
-
schema = params['_brick_schema'] || 'public'
|
128
|
+
def set_db_schema(params = nil)
|
129
|
+
schema = (params ? params['_brick_schema'] : ::Brick.default_schema) || 'public'
|
130
130
|
if schema && ::Brick.db_schemas&.include?(schema)
|
131
131
|
ActiveRecord::Base.execute_sql("SET SEARCH_PATH = ?;", schema)
|
132
132
|
schema
|
@@ -152,17 +152,19 @@ module Brick
|
|
152
152
|
end
|
153
153
|
|
154
154
|
# Convert spaces to underscores if the second character and onwards is mixed case
|
155
|
-
def namify(name,
|
156
|
-
|
155
|
+
def namify(name, action = nil)
|
156
|
+
has_uppers = name =~ /[A-Z]+/
|
157
|
+
has_lowers = name =~ /[a-z]+/
|
158
|
+
name.downcase! if has_uppers && action == :downcase
|
157
159
|
if name.include?(' ')
|
158
160
|
# All uppers or all lowers?
|
159
|
-
if
|
161
|
+
if !has_uppers || !has_lowers
|
160
162
|
name.titleize.tr(' ', '_')
|
161
163
|
else # Mixed uppers and lowers -- just remove existing spaces
|
162
164
|
name.tr(' ', '')
|
163
165
|
end
|
164
166
|
else
|
165
|
-
name
|
167
|
+
action == :underscore ? name.underscore : name
|
166
168
|
end
|
167
169
|
end
|
168
170
|
|
@@ -266,6 +268,26 @@ module Brick
|
|
266
268
|
!!Brick.config.enable_routes
|
267
269
|
end
|
268
270
|
|
271
|
+
# @api public
|
272
|
+
def enable_api=(path)
|
273
|
+
Brick.config.enable_api = path
|
274
|
+
end
|
275
|
+
|
276
|
+
# @api public
|
277
|
+
def enable_api
|
278
|
+
Brick.config.enable_api
|
279
|
+
end
|
280
|
+
|
281
|
+
# @api public
|
282
|
+
def api_root=(path)
|
283
|
+
Brick.config.api_root = path
|
284
|
+
end
|
285
|
+
|
286
|
+
# @api public
|
287
|
+
def api_root
|
288
|
+
Brick.config.api_root
|
289
|
+
end
|
290
|
+
|
269
291
|
# @api public
|
270
292
|
def skip_database_views=(value)
|
271
293
|
Brick.config.skip_database_views = value
|
@@ -484,7 +506,7 @@ In config/initializers/brick.rb appropriate entries would look something like:
|
|
484
506
|
# %%% TODO: If no auto-controllers then enumerate the controllers folder in order to build matching routes
|
485
507
|
# If auto-controllers and auto-models are both enabled then this makes sense:
|
486
508
|
::Brick.relations.each do |rel_name, v|
|
487
|
-
rel_name = rel_name.split('.').map { |
|
509
|
+
rel_name = rel_name.split('.').map { |rel_part| ::Brick.namify(rel_part, :underscore) }
|
488
510
|
schema_names = rel_name[0..-2]
|
489
511
|
schema_names.shift if ::Brick.apartment_multitenant && schema_names.first == Apartment.default_schema
|
490
512
|
# %%% If more than one schema has the same table name, will need to add a schema name prefix to have uniqueness
|
@@ -494,10 +516,12 @@ In config/initializers/brick.rb appropriate entries would look something like:
|
|
494
516
|
options[:only] = [:index, :show] if v.key?(:isView)
|
495
517
|
if schema_names.present? # && !Object.const_defined('Apartment')
|
496
518
|
send(:namespace, schema_names.first) do
|
497
|
-
send(:resources,
|
519
|
+
send(:resources, k.to_sym, **options)
|
498
520
|
end
|
521
|
+
send(:get, "/api/v1/#{schema_names.first}/#{k}", { to: "#{schema_names.first}/#{controller_name}#index" }) if Object.const_defined?('Rswag::Ui')
|
499
522
|
else
|
500
|
-
send(:resources,
|
523
|
+
send(:resources, k.to_sym, **options)
|
524
|
+
send(:get, "/api/v1/#{k}", { to: "#{controller_name}#index" }) if Object.const_defined?('Rswag::Ui')
|
501
525
|
end
|
502
526
|
end
|
503
527
|
if ::Brick.config.add_status && instance_variable_get(:@set).named_routes.names.exclude?(:brick_status)
|
@@ -507,7 +531,11 @@ In config/initializers/brick.rb appropriate entries would look something like:
|
|
507
531
|
get('/brick_orphans', to: 'brick_gem#orphans', as: 'brick_orphans')
|
508
532
|
end
|
509
533
|
end
|
510
|
-
|
534
|
+
if Object.const_defined?('Rswag::Ui') && doc_endpoint = Rswag::Ui.config.config_object[:urls].last
|
535
|
+
# Serves JSON swagger info from a path such as '/api-docs/v1/swagger.json'
|
536
|
+
puts "Mounting swagger info endpoint for \"#{doc_endpoint[:name]}\" on #{doc_endpoint[:url]}"
|
537
|
+
send(:get, doc_endpoint[:url], { to: 'brick_swagger#index' })
|
538
|
+
end
|
511
539
|
end
|
512
540
|
super
|
513
541
|
end
|
@@ -147,6 +147,8 @@ module Brick
|
|
147
147
|
# Brick.enable_controllers = true # Setting this to \"false\" will disable controllers in development
|
148
148
|
# Brick.enable_views = true # Setting this to \"false\" will disable views in development
|
149
149
|
|
150
|
+
# Brick.api_root = '/api/v1/' # Path from which to serve out API resources when the RSwag gem is present
|
151
|
+
|
150
152
|
# # By default models are auto-created for database views, and set to be read-only. This can be skipped.
|
151
153
|
# Brick.skip_database_views = true
|
152
154
|
|
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.73
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lorin Thwaits
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-09-
|
11
|
+
date: 2022-09-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|