brick 1.0.108 → 1.0.109

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: 1e9a085e3f9ba811623d8ebc5d840018348d207b6b1ecab97c066894c44c6ab0
4
- data.tar.gz: 83f32dc71791730d7370f3375b3c19e6cc00e8062efe5b01bdb4cf5aa40b92b9
3
+ metadata.gz: 1621b6af75759b90c788ce080db85608731c2bfc026c82d7bcea011a89c2162e
4
+ data.tar.gz: a4242388d2fa29a12229c620d91b5d572e9e2f7688783beb6963817cf3fac340
5
5
  SHA512:
6
- metadata.gz: dda58c12995437cb95ce60224543d64ef2ed16b0792a083e0def39e7be4569ceaaad86098f6470daf45c358db1d10a1ff350195c0c61ccd3363cbcfae0c344c2
7
- data.tar.gz: 673a82fbbd268c4c8ba590c8eb980fe6e71a62caff710d32ff3b21b3c67927a22ec02380d5d8f8366a1dcadaece238aab3e737f92e879de9da5893dcde0251fa
6
+ metadata.gz: fa089c1bc9663e764b783c639ca9ca24c18a5cbbc788281e11620b33277e87282b6e1a0195d12686b72f53a5ae4a5bcb9e8343e9ef9bb4d97f53fb69ad4619fe
7
+ data.tar.gz: 784eed99a879191dff95b5dfd061f8025d52d3e30eb16b7a754b425c2f4ad58e03e8631949d807f130dc86e55cb3a5e08d215a3f1729b4465c58dc3cecffb96d
@@ -42,9 +42,36 @@ end
42
42
  # file by having the line "require 'brick/compatibility'" to be the last line in that
43
43
  # file.
44
44
  require 'bigdecimal'
45
- if ::Gem::Version.new(RUBY_VERSION) >= ::Gem::Version.new('2.6') &&
46
- ActiveRecord.version < ::Gem::Version.new('5.0')
47
- def BigDecimal.new(*args, **kwargs)
48
- BigDecimal(*args, **kwargs)
45
+ if ActiveRecord.version < ::Gem::Version.new('5.0')
46
+ if ::Gem::Version.new(RUBY_VERSION) >= ::Gem::Version.new('2.6')
47
+ def BigDecimal.new(*args, **kwargs)
48
+ BigDecimal(*args, **kwargs)
49
+ end
50
+
51
+ if ::Gem::Version.new(RUBY_VERSION) >= ::Gem::Version.new('3.1')
52
+ # @@schemes fix for global_id gem < 1.0
53
+ URI.class_variable_set(:@@schemes, {}) unless URI.class_variables.include?(:@@schemes)
54
+ if Gem::Specification.all_names.find { |g| g.start_with?('puma-') }
55
+ require 'rack/handler/puma'
56
+ module Rack::Handler::Puma
57
+ class << self
58
+ alias _brick_run run
59
+ def run(app, *args, **options)
60
+ options.merge!(args.pop) if args.last.is_a?(Hash)
61
+ _brick_run(app, **options)
62
+ end
63
+ end
64
+ end
65
+ end
66
+
67
+ require 'json'
68
+ if JSON::Parser.method(:initialize).parameters.length < 2 && JSON.method(:parse).arity == -2
69
+ JSON.class_exec do
70
+ def self.parse(source, opts = {})
71
+ ::JSON::Parser.new(source, **opts).parse
72
+ end
73
+ end
74
+ end
75
+ end
49
76
  end
50
77
  end
@@ -421,7 +421,10 @@ module ActiveRecord
421
421
  is_distinct = nil
422
422
  wheres = {}
423
423
  params.each do |k, v|
424
- next if ['_brick_schema', '_brick_order', 'controller', 'action'].include?(k)
424
+ next if ['_brick_schema', '_brick_order',
425
+ '_brick_erd', '_brick_exclude', '_brick_unexclude',
426
+ '_brick_page', '_brick_page_size', '_brick_offset', '_brick_limit',
427
+ '_brick_is_api', 'controller', 'action'].include?(k)
425
428
 
426
429
  if (where_col = (ks = k.split('.')).last)[-1] == '!'
427
430
  where_col = where_col[0..-2]
@@ -448,7 +451,10 @@ module ActiveRecord
448
451
  # %%% Have once gotten this error with MSSQL referring to http://localhost:3000/warehouse/cold_room_temperatures__archive
449
452
  # ActiveRecord::StatementInvalid (TinyTds::Error: DBPROCESS is dead or not enabled)
450
453
  # Relevant info here: https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/issues/402
454
+ is_api = params['_brick_is_api']
451
455
  columns.each do |col|
456
+ next if (col.type.nil? || col.type == :binary) && is_api
457
+
452
458
  col_alias = " AS #{col.name}_" if (col_name = col.name) == 'class'
453
459
  selects << if is_mysql
454
460
  "`#{tbl_no_schema}`.`#{col_name}`#{col_alias}"
@@ -1538,9 +1544,13 @@ class Object
1538
1544
  end
1539
1545
  if (current_api_root || is_openapi) &&
1540
1546
  !params&.key?('_brick_schema') &&
1541
- (referrer_params = request.env['HTTP_REFERER']&.split('?')&.last&.split('&')&.map { |x| x.split('=') }).present?
1547
+ (referrer_params = request.env['HTTP_REFERER']&.split('?')&.last&.split('&')&.each_with_object({}) do |x, s|
1548
+ if (kv = x.split('=')).length > 1
1549
+ s[kv.first] = kv[1..-1].join('=')
1550
+ end
1551
+ end).present?
1542
1552
  if params
1543
- referrer_params.each { |k, v| params.send(:parameters)[k] = v }
1553
+ referrer_params.each { |k, v| (params.respond_to?(:parameters) ? send(:parameters) : params)[k] = v }
1544
1554
  else
1545
1555
  api_params = referrer_params&.to_h
1546
1556
  end
@@ -1651,11 +1661,12 @@ class Object
1651
1661
  order_by, _ = model._brick_calculate_ordering(ordering, true) # Don't do the txt part
1652
1662
 
1653
1663
  ar_relation = ActiveRecord.version < Gem::Version.new('4') ? model.preload : model.all
1664
+ params['_brick_is_api'] = true if (is_api = request.format == :js || current_api_root)
1654
1665
  @_brick_params = ar_relation.brick_select(params, (selects ||= []), order_by,
1655
1666
  translations = {},
1656
1667
  join_array = ::Brick::JoinArray.new)
1657
1668
 
1658
- if request.format == :js || current_api_root # Asking for JSON?
1669
+ if is_api # Asking for JSON?
1659
1670
  # Apply column renaming
1660
1671
  data = ar_relation.respond_to?(:_select!) ? ar_relation.dup._select!(*selects) : ar_relation.select(selects)
1661
1672
  if data.present? &&
@@ -1667,13 +1678,16 @@ class Object
1667
1678
  end
1668
1679
  end
1669
1680
 
1670
- # %%% Still need to figure out column filtering and transformations
1681
+ # # %%% This currently only gives a window to check security and raise an exception if someone isn't
1682
+ # # authenticated / authorised. Still need to figure out column filtering and transformations.
1671
1683
  # proc_result = if (column_filter = ::Brick.config.api_column_filter).is_a?(Proc)
1672
- # object_columns = relation.last[:cols]
1684
+ # object_columns = (relation = model&._brick_relation)[:cols]
1673
1685
  # begin
1674
1686
  # num_args = column_filter.arity.negative? ? 5 : column_filter.arity
1675
1687
  # # object_name, api_version, columns, data
1676
- # column_filter.call(*[relation.first, api_ver_path, object_columns, nil][0...num_args])
1688
+ # api_ver_path = request.path[0..-relation[:resource].length]
1689
+ # # Call the api_column_filter in the context of this auto-built controller
1690
+ # instance_exec(*[relation[:resource], relation, api_ver_path, object_columns, data][0...num_args], &column_filter)
1677
1691
  # rescue StandardError => e
1678
1692
  # puts "::Brick.api_column_filter Proc error: #{e.message}"
1679
1693
  # end
@@ -1685,7 +1699,6 @@ class Object
1685
1699
  # else
1686
1700
  # relation.last[:cols]
1687
1701
  # end
1688
- # binding.pry
1689
1702
 
1690
1703
  render inline: { data: data }.to_json, content_type: ['*/*', 'text/html'].include?(request.format) ? 'application/json' : request.format
1691
1704
  return
@@ -1984,7 +1997,6 @@ end.class_exec do
1984
1997
 
1985
1998
  # return if ActiveRecord::Base.connection.current_database == 'postgres'
1986
1999
 
1987
- initializer_loaded = false
1988
2000
  orig_schema = nil
1989
2001
  if (relations = ::Brick.relations).empty?
1990
2002
  # Very first thing, load inflections since we'll be using .pluralize and .singularize on table and model names
@@ -1993,7 +2005,7 @@ end.class_exec do
1993
2005
  end
1994
2006
  # Now the Brick initializer since there may be important schema things configured
1995
2007
  if File.exist?(brick_initializer = ::Rails.root.join('config/initializers/brick.rb'))
1996
- initializer_loaded = load brick_initializer
2008
+ ::Brick.initializer_loaded = load brick_initializer
1997
2009
  end
1998
2010
  # Load the initializer for the Apartment gem a little early so that if .excluded_models and
1999
2011
  # .default_schema are specified then we can work with non-tenanted models more appropriately
@@ -2266,7 +2278,7 @@ ORDER BY 1, 2, c.internal_column_id, acc.position"
2266
2278
  end
2267
2279
  v[:class_name] = (schema_names + [singular]).map(&:camelize).join('::')
2268
2280
  end
2269
- ::Brick.load_additional_references if initializer_loaded
2281
+ ::Brick.load_additional_references if ::Brick.initializer_loaded
2270
2282
 
2271
2283
  if orig_schema && (orig_schema = (orig_schema - ['pg_catalog', 'pg_toast', 'heroku_ext']).first)
2272
2284
  puts "Now switching back to \"#{orig_schema}\" schema."
@@ -2648,8 +2660,10 @@ module Brick
2648
2660
  end
2649
2661
 
2650
2662
  def find_col_renaming(api_ver_path, relation_name)
2651
- (column_renames = ::Brick.config.api_column_renaming&.fetch(api_ver_path, nil) ||
2652
- ::Brick.config.api_column_renaming)&.fetch(relation_name, nil)
2663
+ ::Brick.config.api_column_renaming&.fetch(
2664
+ api_ver_path,
2665
+ ::Brick.config.api_column_renaming&.fetch(relation_name, nil)
2666
+ )
2653
2667
  end
2654
2668
 
2655
2669
  def _class_pk(dotted_name, multitenant)
@@ -5,7 +5,7 @@ module Brick
5
5
  module VERSION
6
6
  MAJOR = 1
7
7
  MINOR = 0
8
- TINY = 108
8
+ TINY = 109
9
9
 
10
10
  # PRE is nil unless it's a pre-release (beta, RC, etc.)
11
11
  PRE = nil
data/lib/brick.rb CHANGED
@@ -135,7 +135,7 @@ module Brick
135
135
  @existing_stis ||= Brick.config.sti_namespace_prefixes.each_with_object({}) { |snp, s| s[snp.first[2..-1]] = snp.last unless snp.first.end_with?('::') }
136
136
  end
137
137
 
138
- attr_accessor :default_schema, :db_schemas, :routes_done, :is_oracle, :is_eager_loading, :auto_models
138
+ attr_accessor :default_schema, :db_schemas, :routes_done, :is_oracle, :is_eager_loading, :auto_models, :initializer_loaded
139
139
 
140
140
  def set_db_schema(params = nil)
141
141
  # If Apartment::Tenant.current is not still the default (usually 'public') then an elevator has brought us into
@@ -682,9 +682,38 @@ In config/initializers/brick.rb appropriate entries would look something like:
682
682
  if (schema_name = v.fetch(:schema, nil))
683
683
  schema_prefix = "#{schema_name}."
684
684
  end
685
+
686
+ # Track routes being built
687
+ if (class_name = v.fetch(:class_name, nil))
688
+ if v.key?(:isView)
689
+ view_class_length = class_name.length if class_name.length > view_class_length
690
+ views
691
+ else
692
+ table_class_length = class_name.length if class_name.length > table_class_length
693
+ tables
694
+ end << [class_name, "#{schema_prefix&.tr('.', '/')}#{v[:resource]}"]
695
+ end
696
+
685
697
  options = {}
686
698
  options[:only] = [:index, :show] if v.key?(:isView)
687
- # First do the API routes if necessary
699
+
700
+ # First do the normal routes
701
+ if path_prefix
702
+ # Was: send(:scope, path: path_prefix) do
703
+ send(:namespace, path_prefix) do
704
+ brick_routes_create.call(schema_name, v[:resource], options)
705
+ sti_subclasses.fetch(class_name, nil)&.each do |sc| # Add any STI subclass routes for this relation
706
+ brick_routes_create.call(schema_name, sc.underscore.tr('/', '_').pluralize, options)
707
+ end
708
+ end
709
+ else
710
+ brick_routes_create.call(schema_name, v[:resource], options)
711
+ sti_subclasses.fetch(class_name, nil)&.each do |sc| # Add any STI subclass routes for this relation
712
+ brick_routes_create.call(schema_name, sc.underscore.tr('/', '_').pluralize, options)
713
+ end
714
+ end
715
+
716
+ # Now the API routes if necessary
688
717
  full_resource = nil
689
718
  ::Brick.api_roots&.each do |api_root|
690
719
  api_done_views = (versioned_views[api_root] ||= {})
@@ -742,7 +771,7 @@ In config/initializers/brick.rb appropriate entries would look something like:
742
771
  proc_result = if (filter = ::Brick.config.api_filter).is_a?(Proc)
743
772
  begin
744
773
  num_args = filter.arity.negative? ? 6 : filter.arity
745
- filter.call(*[unversioned, k, actions, api_ver_num, found, test_ver_num][0...num_args])
774
+ filter.call(*[unversioned, k, view_relation, actions, api_ver_num, found, test_ver_num][0...num_args])
746
775
  rescue StandardError => e
747
776
  puts "::Brick.api_filter Proc error: #{e.message}"
748
777
  end
@@ -811,33 +840,6 @@ In config/initializers/brick.rb appropriate entries would look something like:
811
840
  end
812
841
  end
813
842
  end
814
-
815
- # Track routes being built
816
- if (class_name = v.fetch(:class_name, nil))
817
- if v.key?(:isView)
818
- view_class_length = class_name.length if class_name.length > view_class_length
819
- views
820
- else
821
- table_class_length = class_name.length if class_name.length > table_class_length
822
- tables
823
- end << [class_name, "#{schema_prefix&.tr('.', '/')}#{v[:resource]}"]
824
- end
825
-
826
- # Now the normal routes
827
- if path_prefix
828
- # Was: send(:scope, path: path_prefix) do
829
- send(:namespace, path_prefix) do
830
- brick_routes_create.call(schema_name, v[:resource], options)
831
- sti_subclasses.fetch(class_name, nil)&.each do |sc| # Add any STI subclass routes for this relation
832
- brick_routes_create.call(schema_name, sc.underscore.tr('/', '_').pluralize, options)
833
- end
834
- end
835
- else
836
- brick_routes_create.call(schema_name, v[:resource], options)
837
- sti_subclasses.fetch(class_name, nil)&.each do |sc| # Add any STI subclass routes for this relation
838
- brick_routes_create.call(schema_name, sc.underscore.tr('/', '_').pluralize, options)
839
- end
840
- end
841
843
  end
842
844
 
843
845
  if ::Brick.config.add_status && instance_variable_get(:@set).named_routes.names.exclude?(:brick_status)
@@ -857,7 +859,7 @@ In config/initializers/brick.rb appropriate entries would look something like:
857
859
  if Object.const_defined?('Rswag::Ui')
858
860
  rswag_path = ::Rails.application.routes.routes.find { |r| r.app.app == Rswag::Ui::Engine }&.instance_variable_get(:@path_formatter)&.instance_variable_get(:@parts)&.join
859
861
  first_endpoint_parts = nil
860
- (doc_endpoints = Rswag::Ui.config.config_object[:urls]&.uniq!)&.each do |doc_endpoint|
862
+ (doc_endpoints = Rswag::Ui.config.config_object[:urls])&.each do |doc_endpoint|
861
863
  puts "Mounting OpenApi 3.0 documentation endpoint for \"#{doc_endpoint[:name]}\" on #{doc_endpoint[:url]}"
862
864
  send(:get, doc_endpoint[:url], { to: 'brick_openapi#index' })
863
865
  endpoint_parts = doc_endpoint[:url]&.split('/')
@@ -1192,8 +1194,13 @@ ActiveSupport.on_load(:active_record) do
1192
1194
  arsc.class_exec do
1193
1195
  def self.create(connection, callable = nil, &block)
1194
1196
  relation = (callable || block).call ::ActiveRecord::StatementCache::Params.new
1195
- bind_map = ::ActiveRecord::StatementCache::BindMap.new relation.bound_attributes
1196
- query_builder = connection.cacheable_query(self, relation.arel)
1197
+ bind_map = ::ActiveRecord::StatementCache::BindMap.new(
1198
+ # AR <= 4.2 uses relation.bind_values
1199
+ relation.respond_to?(:bound_attributes) ? relation.bound_attributes : relation.bind_values
1200
+ )
1201
+ options = [self, relation.arel]
1202
+ options.shift if connection.method(:cacheable_query).arity == 1 # Rails <= 5.0
1203
+ query_builder = connection.cacheable_query(*options)
1197
1204
  new query_builder, bind_map
1198
1205
  end
1199
1206
  end
@@ -1237,7 +1244,8 @@ ActiveSupport.on_load(:active_record) do
1237
1244
  end
1238
1245
  end
1239
1246
 
1240
- if Psych.respond_to?(:unsafe_load) && ActiveRecord.version < ::Gem::Version.new('6.1')
1247
+ if ActiveRecord.version < ::Gem::Version.new('6.1') &&
1248
+ Psych.method(:load).parameters.any? { |param| param.first == :key && param.last == :aliases }
1241
1249
  Psych.class_exec do
1242
1250
  class << self
1243
1251
  alias _original_load load
@@ -1279,7 +1287,9 @@ ActiveSupport.on_load(:active_record) do
1279
1287
  def initialize(base, associations, joins, eager_loading: true)
1280
1288
  araat = ::ActiveRecord::Associations::AliasTracker
1281
1289
  if araat.respond_to?(:create_with_joins) # Rails 5.0 and 5.1
1282
- @alias_tracker = araat.create_with_joins(base.connection, base.table_name, joins)
1290
+ cwj_options = [base.connection, base.table_name, joins]
1291
+ cwj_options << base.type_caster if araat.method(:create_with_joins).arity > 3 # Rails <= 5.1
1292
+ @alias_tracker = araat.create_with_joins(*cwj_options)
1283
1293
  @eager_loading = eager_loading # (Unused in Rails 5.0)
1284
1294
  else # Rails 4.2
1285
1295
  @alias_tracker = araat.create(base.connection, joins)
@@ -1648,21 +1658,24 @@ if ActiveRecord.version < ::Gem::Version.new('6.0') && ruby_version >= ::Gem::Ve
1648
1658
  end
1649
1659
 
1650
1660
  require 'active_model'
1651
- require 'active_model/type'
1652
- require 'active_model/type/value'
1653
- class ActiveModel::Type::Value
1654
- def initialize(*args, precision: nil, limit: nil, scale: nil)
1655
- @precision = precision
1656
- @scale = scale
1657
- @limit = limit
1661
+ begin
1662
+ require 'active_model/type'
1663
+ require 'active_model/type/value'
1664
+ class ActiveModel::Type::Value
1665
+ def initialize(*args, precision: nil, limit: nil, scale: nil)
1666
+ @precision = precision
1667
+ @scale = scale
1668
+ @limit = limit
1669
+ end
1658
1670
  end
1671
+ rescue LoadError => e # AR <= 4.2 doesn't have ActiveModel::Type
1659
1672
  end
1660
1673
 
1661
1674
  if Object.const_defined?('I18n')
1662
1675
  module I18n::Base
1663
1676
  alias _brick_translate translate
1664
1677
  def translate(key = nil, *args, throw: false, raise: false, locale: nil, **options)
1665
- options.merge!(args.pop) if args.length > 0 && args.last.is_a?(Hash)
1678
+ options.merge!(args.pop) if args.last.is_a?(Hash)
1666
1679
  _brick_translate(key = nil, throw: false, raise: false, locale: nil, **options)
1667
1680
  end
1668
1681
  end
@@ -1673,8 +1686,12 @@ if ActiveRecord.version < ::Gem::Version.new('6.0') && ruby_version >= ::Gem::Ve
1673
1686
 
1674
1687
  # Creates the authenticity token for the current request.
1675
1688
  def form_authenticity_token(*args, form_options: {}) # :doc:
1676
- form_options.merge!(args.pop) if args.length > 0 && args.last.is_a?(Hash)
1677
- masked_authenticity_token(session, form_options: form_options)
1689
+ if method(:masked_authenticity_token).arity == 1
1690
+ masked_authenticity_token(session) # AR <= 4.2 doesn't use form_options
1691
+ else
1692
+ form_options.merge!(args.pop) if args.last.is_a?(Hash)
1693
+ masked_authenticity_token(session, form_options: form_options)
1694
+ end
1678
1695
  end
1679
1696
  end
1680
1697
 
@@ -1684,7 +1701,7 @@ if ActiveRecord.version < ::Gem::Version.new('6.0') && ruby_version >= ::Gem::Ve
1684
1701
  encrypted = if method(:_encrypt).arity == 1
1685
1702
  _encrypt(value) # Rails <= 5.1
1686
1703
  else
1687
- if args.length > 0 && args.last.is_a?(Hash)
1704
+ if args.last.is_a?(Hash)
1688
1705
  expires_at ||= args.last[:expires_at]
1689
1706
  expires_in ||= args.last[:expires_in]
1690
1707
  purpose ||= args.last[:purpose]
@@ -1697,7 +1714,7 @@ if ActiveRecord.version < ::Gem::Version.new('6.0') && ruby_version >= ::Gem::Ve
1697
1714
  if const_defined?('Messages')
1698
1715
  class Messages::Metadata
1699
1716
  def self.wrap(message, *args, expires_at: nil, expires_in: nil, purpose: nil)
1700
- if args.length > 0 && args.last.is_a?(Hash)
1717
+ if args.last.is_a?(Hash)
1701
1718
  expires_at ||= args.last[:expires_at]
1702
1719
  expires_in ||= args.last[:expires_in]
1703
1720
  purpose ||= args.last[:purpose]
@@ -139,7 +139,7 @@ module Brick
139
139
  # Settings for the Brick gem
140
140
  # (By default this auto-creates models, controllers, views, and routes on-the-fly.)
141
141
 
142
- if ActiveRecord::Base.respond_to?(:brick_select)
142
+ if ActiveRecord::Base.respond_to?(:brick_select) && !::Brick.initializer_loaded
143
143
  # Mode -- generally :on or :off, or only in :development. Also available is :diag_env which enables only
144
144
  # when the environment variable BRICK is set.
145
145
  Brick.mode = :development
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.108
4
+ version: 1.0.109
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lorin Thwaits
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-01-21 00:00:00.000000000 Z
11
+ date: 2023-01-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord