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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 36447b749972f091f6d4c7c9127a7abfd5291d159f4ab81e0fb423feae7c2c03
4
- data.tar.gz: eb2d1c36e67dd692ac765198c132c801c8633e32ecd199f42605f7659e7f3abd
3
+ metadata.gz: ff255b32c913dbb0e02d3f197d035faf43dc44afc4041cda3f57e92fc9df893a
4
+ data.tar.gz: 763b5579402a7668abf3d266665879643b8d44ed04686a35f2df145b1ddfee72
5
5
  SHA512:
6
- metadata.gz: da45315cae612125917448549f3be6cf163c6dc30ac97794f57544321b2c21536600903e9eb30a379fc6a0845656fe7704df863db13ad62a70c623f4f9cba454
7
- data.tar.gz: 64ec86f256752004d07447e94788e453f3e6cf9006082629f5e46791b36d6ce8031e22753217d5f23be5b672f65b35ddb9a55b696db5de0bb85686f854154fee
6
+ metadata.gz: f513e360dcba221bbd5061eb2ef3ef349a7c18ec6babae32273e877ba5b8cd0071f337f11c63460157afaa55cb0e8eea7dc99d80f64231270fc76218ef84397e
7
+ data.tar.gz: eb684612e551f8c884b618985884ad88b5ed827680fb4056f91f6c575fb479d18b92e6d4fa6de222ec24a7991f419723447313780fdbe5b7a0a903561dcb3dd7
@@ -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
- next unless klass._brick_get_fks.include?(k)
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
- Brick.enable_models = app.config.brick.fetch(:enable_models, true)
11
- Brick.enable_controllers = app.config.brick.fetch(:enable_controllers, true)
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
- # Dynamically create generic templates
15
- # ====================================
16
- if (Brick.enable_views = app.config.brick.fetch(:enable_views, true))
17
- ActionView::LookupContext.class_exec do
18
- alias :_brick_template_exists? :template_exists?
19
- def template_exists?(*args, **options)
20
- unless (is_template_exists = _brick_template_exists?(*args, **options))
21
- # Need to return true if we can fill in the blanks for a missing one
22
- # args will be something like: ["index", ["categories"]]
23
- model = args[1].map(&:camelize).join('::').singularize.constantize
24
- if (
25
- is_template_exists = model && (
26
- ['index', 'show'].include?(args.first) || # Everything has index and show
27
- # Only CRU stuff has create / update / destroy
28
- (!model.is_view? && ['new', 'create', 'edit', 'update', 'destroy'].include?(args.first))
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
- instance_variable_set(:@_brick_model, model)
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
- alias :_brick_find_template :find_template
38
- def find_template(*args, **options)
39
- if @_brick_model
40
- model_name = @_brick_model.name
41
- pk = @_brick_model.primary_key
42
- obj_name = model_name.underscore
43
- table_name = model_name.pluralize.underscore
44
- # This gets has_many as well as has_many :through
45
- # %%% weed out ones that don't have an available model to reference
46
- bts, hms = @_brick_model.reflect_on_all_associations.each_with_object([{}, {}]) do |a, s|
47
- case a.macro
48
- when :belongs_to
49
- # Build #brick_descrip if needed
50
- unless a.klass.instance_methods(false).include?(:brick_descrip)
51
- descrip_col = (a.klass.columns.map(&:name) - a.klass._brick_get_fks -
52
- (::Brick.config.metadata_columns || []) -
53
- [a.klass.primary_key]).first&.to_sym
54
- if descrip_col
55
- a.klass.define_method :brick_descrip do
56
- send(descrip_col)
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
- s.first[a.foreign_key] = [a.name, a.klass]
62
- when :has_many
63
- s.last[a.name] = a
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
- s
66
- end
67
- # Weed out has_manys that go to an associative table
68
- hms.select { |k, v| v.options[:through] }.each { |_k, hmt| hms.delete(hmt.options[:through]) }
69
- show_obj_blurb = "<td><%= link_to \"#\{#{obj_name}.class.name\} ##\{#{obj_name}.id\}\", #{obj_name} %></td>\n"
70
- hms_headers = hms.each_with_object(+'') { |hm, s| s << "<th>HM #{hm.first}</th>\n" }
71
- hms_columns = hms.each_with_object(+'') do |hm, s|
72
- s << "<td>
73
- <%= link_to \"#\{#{obj_name}.#{hm.first}.count\} #{hm.first}\", #{hm.last.klass.name.underscore.pluralize}_path({ #{hm.last.foreign_key}: #{obj_name}.#{pk} }) %>
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
- end
100
+ end
76
101
 
77
- inline = case args.first
78
- when 'index'
79
- "<p style=\"color: green\"><%= notice %></p>
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
- <td></td>
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
- <% if is_need_id_col %>
115
- <td>#{show_obj_blurb}</td>
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
- <% is_first = true; #{obj_name}.attributes.each do |k, val| %>
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
- # "<%= @#{@_brick_model.name.underscore.pluralize}.inspect %>"
140
- when 'show'
141
- "<%= @#{@_brick_model.name.underscore}.inspect %>"
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
- if (::Brick.enable_routes = app.config.brick.fetch(:enable_routes, true))
156
- ActionDispatch::Routing::RouteSet.class_exec do
157
- alias _brick_finalize_routeset! finalize!
158
- def finalize!(*args, **options)
159
- unless @finalized
160
- existing_controllers = routes.each_with_object({}) { |r, s| c = r.defaults[:controller]; s[c] = nil if c }
161
- ::Rails.application.routes.append do
162
- # %%% TODO: If no auto-controllers then enumerate the controllers folder in order to build matching routes
163
- # If auto-controllers and auto-models are both enabled then this makes sense:
164
- relations = (::Brick.instance_variable_get(:@relations) || {})[ActiveRecord::Base.connection_pool.object_id] || {}
165
- relations.each do |k, v|
166
- unless existing_controllers.key?(controller_name = k.underscore.pluralize)
167
- options = {}
168
- options[:only] = [:index, :show] if v.key?(:isView)
169
- send(:resources, controller_name.to_sym, **options)
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
- # Do not consider database views when auto-creating models
180
- ::Brick.skip_database_views = app.config.brick.fetch(:skip_database_views, false)
181
-
182
- # Specific database tables and views to omit when auto-creating models
183
- ::Brick.exclude_tables = app.config.brick.fetch(:exclude_tables, [])
184
-
185
- # Columns to treat as being metadata for purposes of identifying associative tables for has_many :through
186
- ::Brick.metadata_columns = app.config.brick.fetch(:metadata_columns, ['created_at', 'updated_at', 'deleted_at'])
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
- # Find associative tables that can be set up for has_many :through
199
- ::Brick.relations.each do |_key, tbl|
200
- tbl_cols = tbl[:cols].keys
201
- fks = tbl[:fks].each_with_object({}) { |fk, s| s[fk.last[:fk]] = fk.last[:inverse_table] if fk.last[:is_bt]; s }
202
- # Aside from the primary key and the metadata columns created_at, updated_at, and deleted_at, if this table only has
203
- # foreign keys then it can act as an associative table and thus be used with has_many :through.
204
- if fks.length > 1 && (tbl_cols - fks.keys - (::Brick.config.metadata_columns || []) - tbl[:pkey].values.first).length.zero?
205
- fks.each { |fk| tbl[:hmt_fks][fk.first] = fk.last }
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
@@ -5,7 +5,7 @@ module Brick
5
5
  module VERSION
6
6
  MAJOR = 1
7
7
  MINOR = 0
8
- TINY = 2
8
+ TINY = 3
9
9
 
10
10
  # PRE is nil unless it's a pre-release (beta, RC, etc.)
11
11
  PRE = nil
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.2
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-13 00:00:00.000000000 Z
11
+ date: 2022-03-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord