brick 1.0.2 → 1.0.3

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