better_record 0.7.0 → 0.7.1

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: c4e3bcdf03926a87f91b4b0b55b8c34f686142904671b0434ae92fec0e4a5ced
4
- data.tar.gz: 1a87533db8f024b44e0cc0c159ecd8392d91c96ee66094b51f7dedc606ea10e1
3
+ metadata.gz: fdba9a47098a0a01e86fcaebd7c82c5d2c896dec9b8d7df67c3235f26c94b495
4
+ data.tar.gz: a05cbc82c831fbf2d063355afe66c66bf4404432af3e78c89baf625f1eba530d
5
5
  SHA512:
6
- metadata.gz: ad743dbfece1c278d146ae8bffdc8ae9d924f97b8214e13834f1161a0bb49b5fd4dcc52487d7aacc0b8263660eb34ced8fc460d374f2622789f272dc49e8dcf4
7
- data.tar.gz: 1deddcfcb7b45e90cfdef429b0413db7e1d35685524c09a8c1c375d604a7706748a36b7f4cf8dbbcf22bb18c7fc3c6a802a377d188c9013f85509054f5afa355
6
+ metadata.gz: 294de3be50905c60b2ccfa414a1a3d362d46b7ce9a1dd088581c7d4069eed8bfe85685aab234893bd793aea2dc0d1a9f4b437d2617b59398a12ccb54985598e0
7
+ data.tar.gz: 4f7e75b61f6831e27fe088c04aea60918ffbf019dfa823bdadb0e33e4508c54239a4856ff18e9b5f7dcf11a351febbc5c3526482ab9a6c9b81fc30d28854e1df
@@ -9,157 +9,23 @@ module BetterRecord
9
9
  # == Extensions ===========================================================
10
10
 
11
11
  # == Relationships ========================================================
12
-
12
+ if (ha = BetterRecord.has_auditing_relation_by_default)
13
+ has_many self.audit_relation_name,
14
+ class_name: 'BetterRecord::LoggedAction',
15
+ primary_type: :table_name,
16
+ foreign_key: :row_id,
17
+ foreign_type: :table_name,
18
+ as: self.audit_relation_name
19
+ end
13
20
  # == Validations ==========================================================
14
- before_validation :set_booleans
15
21
 
16
22
  # == Scopes ===============================================================
17
23
 
18
24
  # == Callbacks ============================================================
19
25
 
20
26
  # == Class Methods ========================================================
21
- def self.audit_relation_name
22
- @@audit_relation_name ||= (BetterRecord.audit_relation_name.presence || :audits).to_sym
23
- end
24
-
25
- def self.boolean_columns
26
- []
27
- end
28
-
29
- def self.column_comments(prefix = '')
30
- longest_name = 0
31
- column_names.each {|nm| longest_name = nm.length if nm.length > longest_name}
32
- longest_name += 1
33
- str = ''
34
- columns.each do |col|
35
- unless col.name == 'id'
36
- spaces = "#{' ' * (longest_name - col.name.length)}"
37
- is_required = "#{col.null == false ? ', required' : ''}"
38
- is_default = "#{col.default ? ", default: #{col.default}" : ''}"
39
- str << "#{prefix}##{spaces}#{col.name}: :#{col.type}#{is_required}\n"
40
- end
41
- end
42
- str
43
- end
44
-
45
- def self.default_print
46
- column_names
47
- end
48
-
49
- def self.find_or_retry_by(*args)
50
- found = nil
51
- retries = 0
52
- begin
53
- raise ActiveRecord::RecordNotFound unless found = find_by(*args)
54
- return found
55
- rescue
56
- sleep retries += 1
57
- retry if (retries) < 5
58
- end
59
- found
60
- end
61
-
62
- def self.queue_adapter_inline?
63
- @@queue_adapter ||= Rails.application.config.active_job.queue_adapter
64
- @@queue_adapter == :inline
65
- end
66
-
67
- def self.table_name_has_schema?
68
- @@table_name_has_schema ||= (table_name =~ /\w+\.\w+/)
69
- end
70
-
71
- def self.table_name_without_schema
72
- @@table_name_without_schema ||= (table_name =~ /\w+\.\w+/) ? table_name.split('.').last : table_name
73
- end
74
-
75
- def self.table_schema
76
- @@table_schema ||= table_name_has_schema? ? table_name.split('.').first : 'public'
77
- end
78
-
79
- def self.table_size
80
- BetterRecord::TableSize.unscoped.find_by(name: table_name_without_schema, schema: table_schema)
81
- end
82
-
83
- def self.transaction(*args)
84
- super(*args) do
85
- if Current.user
86
- ip = Current.ip_address ? "'#{Current.ip_address}'" : 'NULL'
87
-
88
- ActiveRecord::Base.connection.execute <<-SQL
89
- CREATE TEMP TABLE IF NOT EXISTS
90
- "_app_user" (user_id integer, user_type text, ip_address inet);
91
-
92
- UPDATE
93
- _app_user
94
- SET
95
- user_id=#{Current.user.id},
96
- user_type='#{Current.user.class.to_s}',
97
- ip_address=#{ip};
98
-
99
- INSERT INTO
100
- _app_user (user_id, user_type, ip_address)
101
- SELECT
102
- #{Current.user.id},
103
- '#{Current.user.class.to_s}',
104
- #{ip}
105
- WHERE NOT EXISTS (SELECT * FROM _app_user);
106
- SQL
107
- end
108
-
109
- yield
110
- end
111
- end
112
27
 
113
28
  # == Instance Methods =====================================================
114
- def queue_adapter_inline?
115
- self.class.queue_adapter_inline?
116
- end
117
-
118
- %w(path url).each do |cat|
119
- self.__send__ :define_method, :"rails_blob_#{cat}" do |*args|
120
- Rails.application.routes.url_helpers.__send__ :"rails_blob_#{cat}", *args
121
- end
122
- end
123
29
 
124
- def purge(attached)
125
- attached.__send__ queue_adapter_inline? ? :purge : :purge_later
126
- end
127
-
128
- def boolean_columns
129
- self.class.boolean_columns
130
- end
131
-
132
- def default_print
133
- self.class.default_print
134
- end
135
-
136
- private
137
- # def table_name_has_schema?
138
- # self.class.table_name_has_schema?
139
- # end
140
- #
141
- # def table_schema
142
- # self.class.table_schema
143
- # end
144
- #
145
- # def table_name_without_schema
146
- # self.class.table_name_without_schema
147
- # end
148
-
149
- def set_booleans
150
- self.class.boolean_columns.each do |nm|
151
- self.__send__("#{nm}=", __send__("#{nm}=", !!Boolean.parse(__send__ nm)))
152
- end
153
- true
154
- end
155
-
156
- if (ha = BetterRecord.has_audits_by_default)
157
- has_many self.audit_relation_name,
158
- class_name: 'BetterRecord::LoggedAction',
159
- primary_type: :table_name,
160
- foreign_key: :row_id,
161
- foreign_type: :table_name,
162
- as: self.audit_relation_name
163
- end
164
30
  end
165
31
  end
@@ -0,0 +1,3 @@
1
+ Dir.glob(BetterRecord::Engine.root.join('lib', 'better_record', 'concerns', '**', '*.rb')).each do |d|
2
+ require d
3
+ end
data/lib/better_record.rb CHANGED
@@ -1,19 +1,23 @@
1
1
  require "active_support"
2
2
  require "active_record"
3
3
 
4
+ Dir.glob("#{File.expand_path(__dir__)}/core_ext/*.rb").each do |d|
5
+ require d
6
+ end
7
+
4
8
  module BetterRecord
5
9
  class << self
6
10
  attr_accessor :default_polymorphic_method,
7
11
  :db_audit_schema,
8
- :has_audits_by_default,
12
+ :has_auditing_relation_by_default,
9
13
  :audit_relation_name,
10
14
  :layout_template,
11
15
  :app_domain_name
12
16
  end
13
17
  self.default_polymorphic_method = (ENV.fetch('BR_DEFAULT_POLYMORPHIC_METHOD') { :polymorphic_name }).to_sym
14
18
  self.db_audit_schema = ENV.fetch('BR_DB_AUDIT_SCHEMA') { 'auditing' }
15
- self.has_audits_by_default = ActiveRecord::Type::Boolean.new.cast(ENV.fetch('BR_ADD_HAS_MANY') { false })
16
- self.audit_relation_name = (ENV.fetch('BR_AUDIT_RELATION_NAME') { 'audits' }).to_sym
19
+ self.has_auditing_relation_by_default = ActiveRecord::Type::Boolean.new.cast(ENV.fetch('BR_ADD_HAS_MANY') { true })
20
+ self.audit_relation_name = (ENV.fetch('BR_AUDIT_RELATION_NAME') { 'logged_actions' }).to_sym
17
21
  self.layout_template = (ENV.fetch('BR_LAYOUT_TEMPLATE') { 'better_record/layout' }).to_s
18
22
  self.app_domain_name = (ENV.fetch('APP_DOMAIN_NAME') { 'non_existant_domain.com' }).to_s
19
23
  end
@@ -1,24 +1,30 @@
1
- module ActiveRecord
2
- module Associations
3
- class AssociationScope #:nodoc:
4
- def self.get_bind_values(owner, chain)
5
- binds = []
6
- last_reflection = chain.last
1
+ require 'active_support/concern'
2
+ require 'active_record/associations'
3
+ require 'active_record/associations/association_scope'
7
4
 
8
- binds << last_reflection.join_id_for(owner)
9
- if last_reflection.type
10
- binds << BetterRecord::PolymorphicOverride.polymorphic_value(owner.class, last_reflection.options.presence)
11
- end
5
+ module BetterRecord
6
+ module AssociationsExtensions
7
+ module AssociationScopeExtensions
8
+ extend ActiveSupport::Concern
12
9
 
13
- chain.each_cons(2).each do |reflection, next_reflection|
14
- if reflection.type
15
- binds << BetterRecord::PolymorphicOverride.polymorphic_value(next_reflection.klass, (reflection.options[:primary_type].present? ? reflection.options : next_reflection.options))
10
+ included do
11
+ def self.get_bind_values(owner, chain)
12
+ binds = []
13
+ last_reflection = chain.last
14
+
15
+ binds << last_reflection.join_id_for(owner)
16
+ if last_reflection.type
17
+ binds << BetterRecord::PolymorphicOverride.polymorphic_value(owner.class, last_reflection.options.presence)
18
+ end
19
+
20
+ chain.each_cons(2).each do |reflection, next_reflection|
21
+ if reflection.type
22
+ binds << BetterRecord::PolymorphicOverride.polymorphic_value(next_reflection.klass, (reflection.options[:primary_type].present? ? reflection.options : next_reflection.options))
23
+ end
16
24
  end
25
+ binds
17
26
  end
18
- binds
19
- end
20
27
 
21
- private
22
28
  def last_chain_scope(scope, reflection, owner)
23
29
  join_keys = reflection.join_keys
24
30
  key = join_keys.key
@@ -36,6 +42,7 @@ module ActiveRecord
36
42
  scope
37
43
  end
38
44
 
45
+
39
46
  def next_chain_scope(scope, reflection, next_reflection)
40
47
  join_keys = reflection.join_keys
41
48
  key = join_keys.key
@@ -52,31 +59,9 @@ module ActiveRecord
52
59
 
53
60
  scope.joins!(join(foreign_table, constraint))
54
61
  end
55
- end
56
-
57
- module Builder
58
- class Association
59
- def self.valid_options(options)
60
- VALID_OPTIONS + [ :primary_type, :strict_primary_type ] + Association.extensions.flat_map(&:valid_options)
61
- end
62
62
  end
63
63
  end
64
-
65
- class BelongsToPolymorphicAssociation < BelongsToAssociation
66
- def klass
67
- type = owner[reflection.foreign_type]
68
- type.presence && type.capitalize.singularize.constantize
69
- end
70
-
71
- private
72
- def replace_keys(record)
73
- super
74
- owner[reflection.foreign_type] = record ? get_type_value(record) : nil
75
- end
76
-
77
- def get_type_value(record)
78
- BetterRecord::PolymorphicOverride.polymorphic_value(record.class, reflection.options)
79
- end
80
- end
81
64
  end
82
65
  end
66
+
67
+ ActiveRecord::Associations::AssociationScope.send(:include, BetterRecord::AssociationsExtensions::AssociationScopeExtensions)
@@ -0,0 +1,29 @@
1
+ require 'active_support/concern'
2
+ require 'active_record/associations'
3
+ require 'active_record/associations/belongs_to_polymorphic_association'
4
+
5
+ module BetterRecord
6
+ module AssociationsExtensions
7
+ module BelongsToPolymorphicAssociationExtensions
8
+ extend ActiveSupport::Concern
9
+
10
+ included do
11
+ def klass
12
+ type = owner[reflection.foreign_type]
13
+ type.presence && type.capitalize.singularize.constantize
14
+ end
15
+
16
+ def replace_keys record
17
+ super
18
+ owner[reflection.foreign_type] = record ? get_type_value(record) : nil
19
+ end
20
+
21
+ def get_type_value record
22
+ BetterRecord::PolymorphicOverride.polymorphic_value(record.class, reflection.options)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+
29
+ ActiveRecord::Associations::BelongsToPolymorphicAssociation.send(:include, BetterRecord::AssociationsExtensions::BelongsToPolymorphicAssociationExtensions)
@@ -0,0 +1,25 @@
1
+ require 'active_support/concern'
2
+ require 'active_record/associations'
3
+ require 'active_record/associations/builder/association'
4
+
5
+ module BetterRecord
6
+ module AssociationsExtensions
7
+ module BuilderExtensions
8
+ module AssociationExtensions
9
+ extend ActiveSupport::Concern
10
+
11
+ included do |k_to_override|
12
+ class << k_to_override
13
+ alias_method :og_valid_options, :valid_options
14
+
15
+ def valid_options(options)
16
+ og_valid_options(options) + [ :primary_type, :strict_primary_type ]
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ ActiveRecord::Associations::Builder::Association.send(:include, BetterRecord::AssociationsExtensions::BuilderExtensions::AssociationExtensions)
@@ -0,0 +1,160 @@
1
+ require 'active_support/concern'
2
+ require 'active_record/base'
3
+
4
+ module BetterRecord
5
+ module BaseExtensions
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ before_validation :set_booleans
10
+ end
11
+
12
+ class_methods do
13
+ def table_name_defined?
14
+ @table_name_defined ||= method_defined?(:table_name) || !!table_name.present?
15
+ end
16
+
17
+ def table_name_has_schema?
18
+ @table_name_has_schema ||= (table_name =~ /\w+\.\w+/)
19
+ end
20
+
21
+ def table_name_without_schema
22
+ @table_name_without_schema ||= (table_name =~ /\w+\.\w+/) ? table_name.split('.').last : table_name
23
+ end
24
+
25
+ def table_name_with_schema
26
+ @table_name_without_schema ||= "#{table_schema}.#{table_name_without_schema}"
27
+ end
28
+
29
+ def table_schema
30
+ @table_schema ||= table_name_has_schema? ? table_name.split('.').first : 'public'
31
+ end
32
+
33
+ def audit_relation_name
34
+ @@audit_relation_name ||= (BetterRecord.audit_relation_name.presence || :audits).to_sym
35
+ end
36
+
37
+ def boolean_columns
38
+ []
39
+ end
40
+
41
+ def column_comments(prefix = '')
42
+ longest_name = 0
43
+ column_names.each {|nm| longest_name = nm.length if nm.length > longest_name}
44
+ longest_name += 1
45
+ str = ''
46
+ columns.each do |col|
47
+ unless col.name == 'id'
48
+ spaces = "#{' ' * (longest_name - col.name.length)}"
49
+ is_required = "#{col.null == false ? ', required' : ''}"
50
+ is_default = "#{col.default ? ", default: #{col.default}" : ''}"
51
+ str << "#{prefix}##{spaces}#{col.name}: :#{col.type}#{is_required}\n"
52
+ end
53
+ end
54
+ str
55
+ end
56
+
57
+ def default_print
58
+ column_names
59
+ end
60
+
61
+ def find_or_retry_by(*args)
62
+ found = nil
63
+ retries = 0
64
+ begin
65
+ raise ActiveRecord::RecordNotFound unless found = find_by(*args)
66
+ return found
67
+ rescue
68
+ sleep retries += 1
69
+ retry if (retries) < 5
70
+ end
71
+ found
72
+ end
73
+
74
+ def queue_adapter_inline?
75
+ @@queue_adapter ||= Rails.application.config.active_job.queue_adapter
76
+ @@queue_adapter == :inline
77
+ end
78
+
79
+ def table_size
80
+ BetterRecord::TableSize.unscoped.find_by(name: table_name_without_schema, schema: table_schema)
81
+ end
82
+
83
+ def transaction(*args)
84
+ super(*args) do
85
+ if Current.user
86
+ ip = Current.ip_address ? "'#{Current.ip_address}'" : 'NULL'
87
+
88
+ ActiveRecord::Base.connection.execute <<-SQL
89
+ CREATE TEMP TABLE IF NOT EXISTS
90
+ "_app_user" (user_id integer, user_type text, ip_address inet);
91
+
92
+ UPDATE
93
+ _app_user
94
+ SET
95
+ user_id=#{Current.user.id},
96
+ user_type='#{Current.user.class.to_s}',
97
+ ip_address=#{ip};
98
+
99
+ INSERT INTO
100
+ _app_user (user_id, user_type, ip_address)
101
+ SELECT
102
+ #{Current.user.id},
103
+ '#{Current.user.class.to_s}',
104
+ #{ip}
105
+ WHERE NOT EXISTS (SELECT * FROM _app_user);
106
+ SQL
107
+ end
108
+
109
+ yield
110
+ end
111
+ end
112
+ end
113
+
114
+
115
+ # == Instance Methods =====================================================
116
+ def queue_adapter_inline?
117
+ self.class.queue_adapter_inline?
118
+ end
119
+
120
+ %w(path url).each do |cat|
121
+ self.__send__ :define_method, :"rails_blob_#{cat}" do |*args|
122
+ Rails.application.routes.url_helpers.__send__ :"rails_blob_#{cat}", *args
123
+ end
124
+ end
125
+
126
+ def purge(attached)
127
+ attached.__send__ queue_adapter_inline? ? :purge : :purge_later
128
+ end
129
+
130
+ def boolean_columns
131
+ self.class.boolean_columns
132
+ end
133
+
134
+ def default_print
135
+ self.class.default_print
136
+ end
137
+
138
+ private
139
+ # def table_name_has_schema?
140
+ # self.class.table_name_has_schema?
141
+ # end
142
+ #
143
+ # def table_schema
144
+ # self.class.table_schema
145
+ # end
146
+ #
147
+ # def table_name_without_schema
148
+ # self.class.table_name_without_schema
149
+ # end
150
+
151
+ def set_booleans
152
+ self.class.boolean_columns.each do |nm|
153
+ self.__send__("#{nm}=", __send__("#{nm}=", !!Boolean.parse(__send__ nm)))
154
+ end
155
+ true
156
+ end
157
+ end
158
+ end
159
+
160
+ ActiveRecord::Base.send(:include, BetterRecord::BaseExtensions)
@@ -1,3 +1,5 @@
1
+ require 'active_record/reflection'
2
+
1
3
  module ActiveRecord
2
4
  module Reflection
3
5
  class AbstractReflection
@@ -6,6 +6,7 @@ module BetterRecord
6
6
  begin
7
7
  type_val = klass.__send__(type_method)
8
8
  rescue
9
+ puts type_method, klass, type_val
9
10
  if type_val == :table_name_without_schema
10
11
  type_val = klass.table_name
11
12
  else
@@ -21,7 +22,8 @@ module BetterRecord
21
22
 
22
23
  def self.all_types(klass)
23
24
  keys = [ :polymorphic_name, :table_name ]
24
- key |= [BetterRecord.default_polymorphic_method] if BetterRecord.default_polymorphic_method.present?
25
+ keys |= [BetterRecord.default_polymorphic_method] if BetterRecord.default_polymorphic_method.present?
26
+ p keys
25
27
  values = []
26
28
  keys.each do |k|
27
29
  val = nil
@@ -1,3 +1,3 @@
1
1
  module BetterRecord
2
- VERSION = '0.7.0'
2
+ VERSION = '0.7.1'
3
3
  end
@@ -4,7 +4,7 @@ module BetterRecord
4
4
  # #
5
5
  # default_polymorphic_method: BR_DEFAULT_POLYMORPHIC_METHOD #
6
6
  # db_audit_schema: BR_DB_AUDIT_SCHEMA #
7
- # has_audits_by_default: BR_ADD_HAS_MANY #
7
+ # has_auditing_relation_by_default: BR_ADD_HAS_MANY #
8
8
  # audit_relation_name: BR_AUDIT_RELATION_NAME #
9
9
  # layout_template: BR_LAYOUT_TEMPLATE #
10
10
  # app_domain_name: APP_DOMAIN_NAME #
@@ -23,7 +23,7 @@ module BetterRecord
23
23
  # uncomment the following line to add an association for table audits
24
24
  # directly to ActiveRecord::Base. DEFAULT - false
25
25
 
26
- # self.has_audits_by_default = true
26
+ # self.has_auditing_relation_by_default = true
27
27
 
28
28
  # uncomment the following line to change the association name for
29
29
  # auditing lookups. DEFAULT - :audits
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: better_record
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sampson Crowley
@@ -171,9 +171,8 @@ files:
171
171
  - app/views/better_record/table_sizes/index.html.erb
172
172
  - app/views/better_record/table_sizes/show.html.erb
173
173
  - app/views/layouts/better_record/application.html.erb
174
- - config/initializers/active_record/associations.rb
175
174
  - config/initializers/active_record/money_type.rb
176
- - config/initializers/active_record/reflection.rb
175
+ - config/initializers/concerns.rb
177
176
  - config/initializers/core_ext/boolean.rb
178
177
  - config/initializers/core_ext/date.rb
179
178
  - config/initializers/core_ext/integer.rb
@@ -189,6 +188,11 @@ files:
189
188
  - db/postgres-audit-trigger.psql
190
189
  - lib/better_record.rb
191
190
  - lib/better_record/batches.rb
191
+ - lib/better_record/concerns/active_record_extensions/associations_extensions/association_scope_extensions.rb
192
+ - lib/better_record/concerns/active_record_extensions/associations_extensions/belongs_to_polymorphic_extensions.rb
193
+ - lib/better_record/concerns/active_record_extensions/associations_extensions/builder_extensions/association_extensions.rb
194
+ - lib/better_record/concerns/active_record_extensions/base_extensions.rb
195
+ - lib/better_record/concerns/active_record_extensions/reflection_extensions.rb
192
196
  - lib/better_record/engine.rb
193
197
  - lib/better_record/fake_redis.rb
194
198
  - lib/better_record/migration.rb