brick 1.0.2 → 1.0.3
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/extensions.rb +22 -3
- data/lib/brick/frameworks/rails/engine.rb +136 -120
- data/lib/brick/version_number.rb +1 -1
- 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: ff255b32c913dbb0e02d3f197d035faf43dc44afc4041cda3f57e92fc9df893a
|
4
|
+
data.tar.gz: 763b5579402a7668abf3d266665879643b8d44ed04686a35f2df145b1ddfee72
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f513e360dcba221bbd5061eb2ef3ef349a7c18ec6babae32273e877ba5b8cd0071f337f11c63460157afaa55cb0e8eea7dc99d80f64231270fc76218ef84397e
|
7
|
+
data.tar.gz: eb684612e551f8c884b618985884ad88b5ed827680fb4056f91f6c575fb479d18b92e6d4fa6de222ec24a7991f419723447313780fdbe5b7a0a903561dcb3dd7
|
data/lib/brick/extensions.rb
CHANGED
@@ -55,19 +55,38 @@ module ActiveRecord
|
|
55
55
|
class Relation
|
56
56
|
def brick_where(params)
|
57
57
|
wheres = {}
|
58
|
+
rel_joins = []
|
58
59
|
params.each do |k, v|
|
59
|
-
|
60
|
+
if (ks = k.split('.')).length > 1
|
61
|
+
assoc_name = ks.first.to_sym
|
62
|
+
# Make sure it's a good association name and that the model has that column name
|
63
|
+
next unless klass.reflect_on_association(assoc_name)&.klass&.columns&.map(&:name)&.include?(ks.last)
|
60
64
|
|
65
|
+
rel_joins << assoc_name unless rel_joins.include?(assoc_name)
|
66
|
+
else
|
67
|
+
next unless klass._brick_get_fks.include?(k)
|
68
|
+
end
|
61
69
|
wheres[k] = v.split(',')
|
62
70
|
end
|
63
71
|
unless wheres.empty?
|
64
72
|
where!(wheres)
|
73
|
+
joins!(rel_joins) unless rel_joins.empty?
|
65
74
|
wheres # Return the specific parameters that we did use
|
66
75
|
end
|
67
76
|
end
|
68
77
|
end
|
69
78
|
end
|
70
79
|
|
80
|
+
# Rails::Application.class_exec do
|
81
|
+
# alias _brick_initialize! initialize!
|
82
|
+
# # Run Before initialize make sure our settings
|
83
|
+
# def initialize!
|
84
|
+
# # initialization code goes here
|
85
|
+
# puts "BEFORE1"
|
86
|
+
# _brick_initialize!
|
87
|
+
# end
|
88
|
+
# end
|
89
|
+
|
71
90
|
# Object.class_exec do
|
72
91
|
class Object
|
73
92
|
class << self
|
@@ -334,9 +353,9 @@ module ActiveRecord::ConnectionHandling
|
|
334
353
|
ActiveRecord::Base.connection.execute(sql).values.each { |fk| ::Brick._add_bt_and_hm(fk, relations) }
|
335
354
|
end
|
336
355
|
|
337
|
-
puts "Classes built from tables:"
|
356
|
+
puts "Classes that can be built from tables:"
|
338
357
|
relations.select { |_k, v| !v.key?(:isView) }.keys.each { |k| puts ActiveSupport::Inflector.singularize(k).camelize }
|
339
|
-
puts "Classes built from views:"
|
358
|
+
puts "Classes that can be built from views:"
|
340
359
|
relations.select { |_k, v| v.key?(:isView) }.keys.each { |k| puts ActiveSupport::Inflector.singularize(k).camelize }
|
341
360
|
# pp relations; nil
|
342
361
|
|
@@ -5,78 +5,103 @@ module Brick
|
|
5
5
|
# See http://guides.rubyonrails.org/engines.html
|
6
6
|
class Engine < ::Rails::Engine
|
7
7
|
# paths['app/models'] << 'lib/brick/frameworks/active_record/models'
|
8
|
+
puts "BEFORE - engine set config"
|
8
9
|
config.brick = ActiveSupport::OrderedOptions.new
|
9
|
-
initializer 'brick.initialisation' do |app|
|
10
|
-
|
11
|
-
|
10
|
+
# initializer 'brick.initialisation' do |app|
|
11
|
+
ActiveSupport.on_load(:before_initialize) do |app|
|
12
|
+
puts "BEFORE - engine initialisation"
|
13
|
+
::Brick.enable_models = app.config.brick.fetch(:enable_models, true)
|
14
|
+
::Brick.enable_controllers = app.config.brick.fetch(:enable_controllers, true)
|
15
|
+
::Brick.enable_views = app.config.brick.fetch(:enable_views, true)
|
16
|
+
::Brick.enable_routes = app.config.brick.fetch(:enable_routes, true)
|
17
|
+
::Brick.skip_database_views = app.config.brick.fetch(:skip_database_views, false)
|
18
|
+
|
19
|
+
# Specific database tables and views to omit when auto-creating models
|
20
|
+
::Brick.exclude_tables = app.config.brick.fetch(:exclude_tables, [])
|
21
|
+
|
22
|
+
# Columns to treat as being metadata for purposes of identifying associative tables for has_many :through
|
23
|
+
::Brick.metadata_columns = app.config.brick.fetch(:metadata_columns, ['created_at', 'updated_at', 'deleted_at'])
|
24
|
+
|
25
|
+
# Additional references (virtual foreign keys)
|
26
|
+
::Brick.additional_references = app.config.brick.fetch(:additional_references, nil)
|
12
27
|
|
13
|
-
#
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
28
|
+
# After we're initialized and before running the rest of stuff, put our configuration in place
|
29
|
+
ActiveSupport.on_load(:after_initialize) do |xyz|
|
30
|
+
puts "AFTER - engine initialisation"
|
31
|
+
# ====================================
|
32
|
+
# Dynamically create generic templates
|
33
|
+
# ====================================
|
34
|
+
if ::Brick.enable_views?
|
35
|
+
ActionView::LookupContext.class_exec do
|
36
|
+
alias :_brick_template_exists? :template_exists?
|
37
|
+
def template_exists?(*args, **options)
|
38
|
+
unless (is_template_exists = _brick_template_exists?(*args, **options))
|
39
|
+
# Need to return true if we can fill in the blanks for a missing one
|
40
|
+
# args will be something like: ["index", ["categories"]]
|
41
|
+
model = args[1].map(&:camelize).join('::').singularize.constantize
|
42
|
+
if (
|
43
|
+
is_template_exists = model && (
|
44
|
+
['index', 'show'].include?(args.first) || # Everything has index and show
|
45
|
+
# Only CRU stuff has create / update / destroy
|
46
|
+
(!model.is_view? && ['new', 'create', 'edit', 'update', 'destroy'].include?(args.first))
|
47
|
+
)
|
29
48
|
)
|
30
|
-
|
31
|
-
|
49
|
+
instance_variable_set(:@_brick_model, model)
|
50
|
+
end
|
32
51
|
end
|
52
|
+
is_template_exists
|
33
53
|
end
|
34
|
-
is_template_exists
|
35
|
-
end
|
36
54
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
55
|
+
alias :_brick_find_template :find_template
|
56
|
+
def find_template(*args, **options)
|
57
|
+
if @_brick_model
|
58
|
+
model_name = @_brick_model.name
|
59
|
+
pk = @_brick_model.primary_key
|
60
|
+
obj_name = model_name.underscore
|
61
|
+
table_name = model_name.pluralize.underscore
|
62
|
+
# This gets has_many as well as has_many :through
|
63
|
+
# %%% weed out ones that don't have an available model to reference
|
64
|
+
bts, hms = @_brick_model.reflect_on_all_associations.each_with_object([{}, {}]) do |a, s|
|
65
|
+
case a.macro
|
66
|
+
when :belongs_to
|
67
|
+
# Build #brick_descrip if needed
|
68
|
+
unless a.klass.instance_methods(false).include?(:brick_descrip)
|
69
|
+
descrip_col = (a.klass.columns.map(&:name) - a.klass._brick_get_fks -
|
70
|
+
(::Brick.config.metadata_columns || []) -
|
71
|
+
[a.klass.primary_key]).first&.to_sym
|
72
|
+
if descrip_col
|
73
|
+
a.klass.define_method :brick_descrip do
|
74
|
+
send(descrip_col)
|
75
|
+
end
|
57
76
|
end
|
58
77
|
end
|
59
|
-
end
|
60
78
|
|
61
|
-
|
62
|
-
|
63
|
-
|
79
|
+
s.first[a.foreign_key] = [a.name, a.klass]
|
80
|
+
when :has_many
|
81
|
+
s.last[a.name] = a
|
82
|
+
end
|
83
|
+
s
|
64
84
|
end
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
85
|
+
# Weed out has_manys that go to an associative table
|
86
|
+
associatives = hms.select { |k, v| v.options[:through] }.each_with_object({}) do |hmt, s|
|
87
|
+
s[hmt.first] = hms.delete(hmt.last.options[:through]) # End up with a hash of HMT names pointing to join-table associations
|
88
|
+
end
|
89
|
+
hms_headers = hms.each_with_object(+'') { |hm, s| s << "<th>HM#{'T' if hm.last.options[:through]} #{hm.first}</th>\n" }
|
90
|
+
hms_columns = hms.each_with_object(+'') do |hm, s|
|
91
|
+
hm_fk_name = if hm.last.options[:through]
|
92
|
+
associative = associatives[hm.last.name]
|
93
|
+
"'#{associative.name}.#{associative.foreign_key}'"
|
94
|
+
else
|
95
|
+
hm.last.foreign_key
|
96
|
+
end
|
97
|
+
s << "<td>
|
98
|
+
<%= link_to \"#\{#{obj_name}.#{hm.first}.count\} #{hm.first}\", #{hm.last.klass.name.underscore.pluralize}_path({ #{hm_fk_name}: #{obj_name}.#{pk} }) %>
|
74
99
|
</td>\n"
|
75
|
-
|
100
|
+
end
|
76
101
|
|
77
|
-
|
78
|
-
|
79
|
-
|
102
|
+
inline = case args.first
|
103
|
+
when 'index'
|
104
|
+
"<p style=\"color: green\"><%= notice %></p>
|
80
105
|
|
81
106
|
<h1>#{model_name.pluralize}</h1>
|
82
107
|
<% if @_brick_params&.present? %><h3>where <%= @_brick_params.each_with_object([]) { |v, s| s << \"#\{v.first\} = #\{v.last.inspect\}\" }.join(', ') %></h3><% end %>
|
@@ -104,26 +129,26 @@ module Brick
|
|
104
129
|
<% if is_first # STILL haven't been able to write a first non-key / non-metadata column?
|
105
130
|
is_first = false
|
106
131
|
is_need_id_col = true %>
|
107
|
-
<
|
132
|
+
<th></th>
|
108
133
|
<% end %>
|
109
134
|
#{hms_headers}
|
110
135
|
</tr>
|
111
136
|
|
112
137
|
<% @#{table_name}.each do |#{obj_name}| %>
|
113
138
|
<tr>
|
114
|
-
<%
|
115
|
-
|
139
|
+
<% is_first = true
|
140
|
+
if is_need_id_col
|
141
|
+
is_first = false %>
|
142
|
+
<td><%= link_to \"#\{#{obj_name}.class.name\} ##\{#{obj_name}.id\}\", #{obj_name} %></td>
|
116
143
|
<% end %>
|
117
|
-
<%
|
144
|
+
<% #{obj_name}.attributes.each do |k, val| %>
|
118
145
|
<% next if k == '#{pk}' || ::Brick.config.metadata_columns.include?(k) %>
|
146
|
+
<td>
|
119
147
|
<% if (bt = bts[k]) %>
|
120
|
-
<td>
|
121
148
|
<%= obj = bt[1].find_by(bt.last => val); link_to obj.brick_descrip, obj %>
|
122
149
|
<% elsif is_first %>
|
123
|
-
<td>
|
124
150
|
<%= is_first = false; link_to val, #{obj_name} %>
|
125
151
|
<% else %>
|
126
|
-
<td>
|
127
152
|
<%= val %>
|
128
153
|
<% end %>
|
129
154
|
</td>
|
@@ -136,73 +161,64 @@ module Brick
|
|
136
161
|
|
137
162
|
<%= link_to \"New #{obj_name}\", new_#{obj_name}_path %>
|
138
163
|
"
|
139
|
-
|
140
|
-
|
141
|
-
|
164
|
+
# "<%= @#{@_brick_model.name.underscore.pluralize}.inspect %>"
|
165
|
+
when 'show'
|
166
|
+
"<%= @#{@_brick_model.name.underscore}.inspect %>"
|
167
|
+
end
|
168
|
+
# As if it were an inline template (see #determine_template in actionview-5.2.6.2/lib/action_view/renderer/template_renderer.rb)
|
169
|
+
keys = options.has_key?(:locals) ? options[:locals].keys : []
|
170
|
+
handler = ActionView::Template.handler_for_extension(options[:type] || 'erb')
|
171
|
+
ActionView::Template.new(inline, "auto-generated #{args.first} template", handler, locals: keys)
|
172
|
+
else
|
173
|
+
_brick_find_template(*args, **options)
|
142
174
|
end
|
143
|
-
puts inline
|
144
|
-
# As if it were an inline template (see #determine_template in actionview-5.2.6.2/lib/action_view/renderer/template_renderer.rb)
|
145
|
-
keys = options.has_key?(:locals) ? options[:locals].keys : []
|
146
|
-
handler = ActionView::Template.handler_for_extension(options[:type] || 'erb')
|
147
|
-
ActionView::Template.new(inline, "auto-generated #{args.first} template", handler, locals: keys)
|
148
|
-
else
|
149
|
-
_brick_find_template(*args, **options)
|
150
175
|
end
|
151
176
|
end
|
152
177
|
end
|
153
|
-
end
|
154
178
|
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
179
|
+
if ::Brick.enable_routes?
|
180
|
+
ActionDispatch::Routing::RouteSet.class_exec do
|
181
|
+
alias _brick_finalize_routeset! finalize!
|
182
|
+
def finalize!(*args, **options)
|
183
|
+
unless @finalized
|
184
|
+
existing_controllers = routes.each_with_object({}) { |r, s| c = r.defaults[:controller]; s[c] = nil if c }
|
185
|
+
::Rails.application.routes.append do
|
186
|
+
# %%% TODO: If no auto-controllers then enumerate the controllers folder in order to build matching routes
|
187
|
+
# If auto-controllers and auto-models are both enabled then this makes sense:
|
188
|
+
relations = (::Brick.instance_variable_get(:@relations) || {})[ActiveRecord::Base.connection_pool.object_id] || {}
|
189
|
+
relations.each do |k, v|
|
190
|
+
unless existing_controllers.key?(controller_name = k.underscore.pluralize)
|
191
|
+
options = {}
|
192
|
+
options[:only] = [:index, :show] if v.key?(:isView)
|
193
|
+
send(:resources, controller_name.to_sym, **options)
|
194
|
+
end
|
170
195
|
end
|
171
196
|
end
|
172
197
|
end
|
198
|
+
_brick_finalize_routeset!(*args, **options)
|
173
199
|
end
|
174
|
-
_brick_finalize_routeset!(*args, **options)
|
175
200
|
end
|
176
201
|
end
|
177
|
-
end
|
178
202
|
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
# Additional references (virtual foreign keys)
|
189
|
-
if (ars = (::Brick.additional_references = app.config.brick.fetch(:additional_references, nil)))
|
190
|
-
ars = ars.call if ars.is_a?(Proc)
|
191
|
-
ars = ars.to_a unless ars.is_a?(Array)
|
192
|
-
ars = [ars] unless ars.empty? || ars.first.is_a?(Array)
|
193
|
-
ars.each do |fk|
|
194
|
-
::Brick._add_bt_and_hm(fk[0..2])
|
203
|
+
# Additional references (virtual foreign keys)
|
204
|
+
if (ars = ::Brick.config.additional_references)
|
205
|
+
ars = ars.call if ars.is_a?(Proc)
|
206
|
+
ars = ars.to_a unless ars.is_a?(Array)
|
207
|
+
ars = [ars] unless ars.empty? || ars.first.is_a?(Array)
|
208
|
+
ars.each do |fk|
|
209
|
+
::Brick._add_bt_and_hm(fk[0..2])
|
210
|
+
end
|
195
211
|
end
|
196
|
-
end
|
197
212
|
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
213
|
+
# Find associative tables that can be set up for has_many :through
|
214
|
+
::Brick.relations.each do |_key, tbl|
|
215
|
+
tbl_cols = tbl[:cols].keys
|
216
|
+
fks = tbl[:fks].each_with_object({}) { |fk, s| s[fk.last[:fk]] = fk.last[:inverse_table] if fk.last[:is_bt]; s }
|
217
|
+
# Aside from the primary key and the metadata columns created_at, updated_at, and deleted_at, if this table only has
|
218
|
+
# foreign keys then it can act as an associative table and thus be used with has_many :through.
|
219
|
+
if fks.length > 1 && (tbl_cols - fks.keys - (::Brick.config.metadata_columns || []) - tbl[:pkey].values.first).length.zero?
|
220
|
+
fks.each { |fk| tbl[:hmt_fks][fk.first] = fk.last }
|
221
|
+
end
|
206
222
|
end
|
207
223
|
end
|
208
224
|
end
|
data/lib/brick/version_number.rb
CHANGED
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.3
|
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-03-
|
11
|
+
date: 2022-03-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|