advanced_ar 0.1.4 → 0.1.5

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: a06ad08bb39f4bce6113d3211ae70ee0f121389c0c6ed94794bc1528894979c4
4
- data.tar.gz: 8e7ca779b294e2c3d0bbe657dc6043294e4598766fa1ea6127af6091f3939e0e
3
+ metadata.gz: 4635f5a6d31cb307162adc165155a6ca6dae23c37d9ad406b12fe5d6b3192b5e
4
+ data.tar.gz: f4693daf2c847e2ce6743d2afcf1fa11716c45682dd580346c580d30b88047d4
5
5
  SHA512:
6
- metadata.gz: 964468ac25c780441ddfeeea1bd89a78294060db049e506930c0f4e7f70b82dc4a81bb0340c264c4faaf509f3a97753155e1366c71610637da1347aad0408c74
7
- data.tar.gz: 387abf85153e0f202d0f5865cfe1589cd60b07a454aaa128e01c8b02b067d30dcf1b2a4f18981a2ef65156fe53c9e2214f7d45848f417ba782fd2a59ac8e2287
6
+ metadata.gz: 44d3d78df56df26cb0e8273cc1bedfa66a711bca449db6078d56811382d2ef0b0ccfd78fb686a81c234ff4a183c0cbf8b7c6522de1f640cd6882794572b8c903
7
+ data.tar.gz: a57ec87822bc24078b85df731ad733a7612d0e24acd02c00a4f44891ff3ff1239b02df953ab88b82de8c2a54427fa18bdf3ac0b5b7c5613500e4553f14759aff
data/lib/advanced_ar.rb CHANGED
@@ -1,5 +1,5 @@
1
1
 
2
- Dir[File.dirname(__FILE__) + "/advanced_ar/*.rb"].each { |file| require file }
2
+ Dir[File.dirname(__FILE__) + "/advanced_ar/*.rb"].each { |file| require file }
3
3
 
4
4
  module AdvancedAR
5
5
 
@@ -14,147 +14,149 @@
14
14
  # 2. Duplicates the relevant snippets from Goldiloader into this module. See Goldiloader::AutoIncludeContext
15
15
  # The current Goldiloader implementation uses Option 1 internally, but also makes the relations lazy - even
16
16
  # if you define a prefetch, it won't actually be loaded until you attempt to access it on one of the models.
17
- module AdvancedAR::ArbitraryPrefetch
18
- class PrefetcherContext
19
- attr_accessor :model, :target_attribute
20
- attr_reader :options
21
-
22
- def initialize(model, opts)
23
- @options = opts
24
- @model = model
25
- @source_key = opts[:relation]
26
- @target_attribute = opts[:attribute]
27
- @queryset = opts[:queryset]
28
- @models = []
29
- end
17
+ module AdvancedAR
18
+ module ArbitraryPrefetch
19
+ class PrefetcherContext
20
+ attr_accessor :model, :target_attribute
21
+ attr_reader :options
22
+
23
+ def initialize(model, opts)
24
+ @options = opts
25
+ @model = model
26
+ @source_key = opts[:relation]
27
+ @target_attribute = opts[:attribute]
28
+ @queryset = opts[:queryset]
29
+ @models = []
30
+ end
30
31
 
31
- def link_models(models)
32
- Array(models).each do |m|
33
- @models << m
32
+ def link_models(models)
33
+ Array(models).each do |m|
34
+ @models << m
34
35
 
35
- # assoc = PrefetchAssociation.new(m, self, reflection)
36
- assoc = reflection.association_class.new(m, reflection)
37
- m.send(:association_instance_set, target_attribute, assoc)
36
+ # assoc = PrefetchAssociation.new(m, self, reflection)
37
+ assoc = reflection.association_class.new(m, reflection)
38
+ m.send(:association_instance_set, target_attribute, assoc)
38
39
 
39
- m.instance_eval <<-CODE, __FILE__, __LINE__ + 1
40
- def #{target_attribute}
41
- association(:#{target_attribute}).reader
42
- end
43
- CODE
40
+ m.instance_eval <<-CODE, __FILE__, __LINE__ + 1
41
+ def #{target_attribute}
42
+ association(:#{target_attribute}).reader
43
+ end
44
+ CODE
45
+ end
44
46
  end
45
- end
46
47
 
47
- def reflection
48
- @reflection ||= begin
49
- queryset = @queryset
50
- source_refl = model.reflections[@source_key.to_s]
51
- scope = lambda { |*_args|
52
- qs = queryset
53
- qs = qs.merge(source_refl.scope_for(model.unscoped)) if source_refl.scope
54
- qs
55
- }
56
- ActiveRecord::Reflection.create(
57
- options[:type],
58
- @target_attribute,
59
- scope,
60
- source_refl.options.merge(
61
- class_name: source_refl.class_name,
62
- inverse_of: nil
63
- ),
64
- model
65
- )
48
+ def reflection
49
+ @reflection ||= begin
50
+ queryset = @queryset
51
+ source_refl = model.reflections[@source_key.to_s]
52
+ scope = lambda { |*_args|
53
+ qs = queryset
54
+ qs = qs.merge(source_refl.scope_for(model.unscoped)) if source_refl.scope
55
+ qs
56
+ }
57
+ ActiveRecord::Reflection.create(
58
+ options[:type],
59
+ @target_attribute,
60
+ scope,
61
+ source_refl.options.merge(
62
+ class_name: source_refl.class_name,
63
+ inverse_of: nil
64
+ ),
65
+ model
66
+ )
67
+ end
66
68
  end
67
69
  end
68
- end
69
70
 
70
- module ActiveRecordBasePatch
71
- extend ActiveSupport::Concern
71
+ module ActiveRecordBasePatch
72
+ extend ActiveSupport::Concern
72
73
 
73
- included do
74
- class << self
75
- delegate :prefetch, to: :all
74
+ included do
75
+ class << self
76
+ delegate :prefetch, to: :all
77
+ end
76
78
  end
77
79
  end
78
- end
79
80
 
80
- module ActiveRecordRelationPatch
81
- def exec_queries
82
- return super if loaded?
81
+ module ActiveRecordRelationPatch
82
+ def exec_queries
83
+ return super if loaded?
83
84
 
84
- records = super
85
- preloader = nil
86
- (@values[:prefetches] || {}).each do |_key, opts|
87
- pfc = PrefetcherContext.new(model, opts)
88
- pfc.link_models(records)
85
+ records = super
86
+ preloader = nil
87
+ (@values[:prefetches] || {}).each do |_key, opts|
88
+ pfc = PrefetcherContext.new(model, opts)
89
+ pfc.link_models(records)
89
90
 
90
- unless defined?(Goldiloader)
91
- preloader ||= build_preloader
92
- preloader.preload(records, opts[:attribute])
91
+ unless defined?(Goldiloader)
92
+ preloader ||= build_preloader
93
+ preloader.preload(records, opts[:attribute])
94
+ end
93
95
  end
96
+ records
94
97
  end
95
- records
96
- end
97
98
 
98
- def prefetch(**kwargs)
99
- spawn.add_prefetches!(kwargs)
100
- end
99
+ def prefetch(**kwargs)
100
+ spawn.add_prefetches!(kwargs)
101
+ end
101
102
 
102
- def add_prefetches!(kwargs)
103
- return unless kwargs.present?
103
+ def add_prefetches!(kwargs)
104
+ return unless kwargs.present?
104
105
 
105
- assert_mutability!
106
- @values[:prefetches] ||= {}
107
- kwargs.each do |attr, opts|
108
- @values[:prefetches][attr] = normalize_options(attr, opts)
106
+ assert_mutability!
107
+ @values[:prefetches] ||= {}
108
+ kwargs.each do |attr, opts|
109
+ @values[:prefetches][attr] = normalize_options(attr, opts)
110
+ end
111
+ self
109
112
  end
110
- self
111
- end
112
113
 
113
- def normalize_options(attr, opts)
114
- norm = if opts.is_a?(Array)
115
- { relation: opts[0], queryset: opts[1] }
116
- elsif opts.is_a?(ActiveRecord::Relation)
117
- rel_name = opts.model.name.underscore
118
- rel = (model.reflections[rel_name] || model.reflections[rel_name.pluralize])&.name
119
- { relation: rel, queryset: opts }
120
- else
121
- opts
122
- end
114
+ def normalize_options(attr, opts)
115
+ norm = if opts.is_a?(Array)
116
+ { relation: opts[0], queryset: opts[1] }
117
+ elsif opts.is_a?(ActiveRecord::Relation)
118
+ rel_name = opts.model.name.underscore
119
+ rel = (model.reflections[rel_name] || model.reflections[rel_name.pluralize])&.name
120
+ { relation: rel, queryset: opts }
121
+ else
122
+ opts
123
+ end
123
124
 
124
- norm[:attribute] = attr
125
- norm[:type] ||= (attr.to_s.pluralize == attr.to_s) ? :has_many : :has_one
125
+ norm[:attribute] = attr
126
+ norm[:type] ||= (attr.to_s.pluralize == attr.to_s) ? :has_many : :has_one
126
127
 
127
- norm
128
+ norm
129
+ end
128
130
  end
129
- end
130
131
 
131
- module ActiveRecordMergerPatch
132
- def merge
133
- super.tap do
134
- merge_prefetches
132
+ module ActiveRecordMergerPatch
133
+ def merge
134
+ super.tap do
135
+ merge_prefetches
136
+ end
135
137
  end
136
- end
137
138
 
138
- private
139
+ private
139
140
 
140
- def merge_prefetches
141
- relation.add_prefetches!(other.values[:prefetches])
141
+ def merge_prefetches
142
+ relation.add_prefetches!(other.values[:prefetches])
143
+ end
142
144
  end
143
- end
144
145
 
145
- def self.install
146
- ::ActiveRecord::Base.include(ActiveRecordBasePatch)
147
- ::ActiveRecord::Relation.prepend(ActiveRecordRelationPatch)
148
- ::ActiveRecord::Relation::Merger.prepend(ActiveRecordMergerPatch)
146
+ def self.install
147
+ ::ActiveRecord::Base.include(ActiveRecordBasePatch)
148
+ ::ActiveRecord::Relation.prepend(ActiveRecordRelationPatch)
149
+ ::ActiveRecord::Relation::Merger.prepend(ActiveRecordMergerPatch)
149
150
 
150
- return unless defined? ::Goldiloader
151
+ return unless defined? ::Goldiloader
151
152
 
152
- ::Goldiloader::AssociationLoader.module_eval do
153
- def self.has_association?(model, association_name) # rubocop:disable Naming/PredicateName
154
- model.association(association_name)
155
- true
156
- rescue ::ActiveRecord::AssociationNotFoundError => _err
157
- false
153
+ ::Goldiloader::AssociationLoader.module_eval do
154
+ def self.has_association?(model, association_name) # rubocop:disable Naming/PredicateName
155
+ model.association(association_name)
156
+ true
157
+ rescue ::ActiveRecord::AssociationNotFoundError => _err
158
+ false
159
+ end
158
160
  end
159
161
  end
160
162
  end
@@ -1,94 +1,96 @@
1
- module AdvancedAR::BatchedDestruction
2
- extend ActiveSupport::Concern
1
+ module AdvancedAR
2
+ module BatchedDestruction
3
+ extend ActiveSupport::Concern
3
4
 
4
- included do
5
- define_model_callbacks :bulk_destroy
6
- define_model_callbacks :destroy_batch
5
+ included do
6
+ define_model_callbacks :bulk_destroy
7
+ define_model_callbacks :destroy_batch
7
8
 
8
- before_destroy_batch do
9
- # TODO Delete Dependant Relations
10
- model_class.reflections.each do |name, reflection|
11
- options = reflection.options
9
+ before_destroy_batch do
10
+ # TODO Delete Dependant Relations
11
+ model_class.reflections.each do |name, reflection|
12
+ options = reflection.options
13
+ end
12
14
  end
13
15
  end
14
- end
15
16
 
16
- class_methods do
17
- def bulk_destroy(**kwargs)
18
- return to_sql
19
- bulk_destroy_internal(self, **kwargs)
20
- end
17
+ class_methods do
18
+ def bulk_destroy(**kwargs)
19
+ return to_sql
20
+ bulk_destroy_internal(self, **kwargs)
21
+ end
21
22
 
22
- # Hook for performing the actual deletion of items, may be used to facilitate soft-deletion.
23
- # Must not call destroy().
24
- # Default implementation is to delete the batch using delete_all(id: batch_ids).
25
- def destroy_bulk_batch(batch, options)
26
- delete_ids = batch.map(&:id)
27
- where(id: delete_ids).delete_all()
28
- end
23
+ # Hook for performing the actual deletion of items, may be used to facilitate soft-deletion.
24
+ # Must not call destroy().
25
+ # Default implementation is to delete the batch using delete_all(id: batch_ids).
26
+ def destroy_bulk_batch(batch, options)
27
+ delete_ids = batch.map(&:id)
28
+ where(id: delete_ids).delete_all()
29
+ end
29
30
 
30
- private
31
+ private
31
32
 
32
- def bulk_destroy_internal(items, **kwargs)
33
- options = {}
34
- options.merge!(kwargs)
35
- ClassCallbackExector.run_callbacks(model_class, :bulk_destroy, options: options) do
36
- if items.respond_to?(:find_in_batches)
37
- items.find_in_batches do |batch|
38
- _destroy_batch(batch, options)
33
+ def bulk_destroy_internal(items, **kwargs)
34
+ options = {}
35
+ options.merge!(kwargs)
36
+ ClassCallbackExector.run_callbacks(model_class, :bulk_destroy, options: options) do
37
+ if items.respond_to?(:find_in_batches)
38
+ items.find_in_batches do |batch|
39
+ _destroy_batch(batch, options)
40
+ end
41
+ else
42
+ _destroy_batch(items, options)
39
43
  end
40
- else
41
- _destroy_batch(items, options)
42
44
  end
43
45
  end
44
- end
45
46
 
46
- def _destroy_batch(batch, options)
47
- ClassCallbackExector.run_callbacks(model_class, :destroy_batch, {
48
- model_class: model_class,
49
- batch: batch,
50
- }) do
51
- model_class.destroy_bulk_batch(batch, options)
47
+ def _destroy_batch(batch, options)
48
+ ClassCallbackExector.run_callbacks(model_class, :destroy_batch, {
49
+ model_class: model_class,
50
+ batch: batch,
51
+ }) do
52
+ model_class.destroy_bulk_batch(batch, options)
53
+ end
52
54
  end
53
- end
54
55
 
55
- private
56
+ private
56
57
 
57
- def model_class
58
- try(:model) || self
58
+ def model_class
59
+ try(:model) || self
60
+ end
59
61
  end
60
- end
61
62
 
62
- def destroy(*args, legacy: false, **kwargs)
63
- if legacy
64
- super(*args)
65
- else
66
- self.class.send(:bulk_destroy_internal, [self], **kwargs)
63
+ def destroy(*args, legacy: false, **kwargs)
64
+ if legacy
65
+ super(*args)
66
+ else
67
+ self.class.send(:bulk_destroy_internal, [self], **kwargs)
68
+ end
67
69
  end
68
- end
69
70
 
70
- private
71
+ private
71
72
 
72
- # These classes are some Hackery to allow us to use callbacks against the Model classes instead of Model instances
73
- class ClassCallbackExector
74
- include ActiveSupport::Callbacks
73
+ # These classes are some Hackery to allow us to use callbacks against the Model classes instead of Model instances
74
+ class ClassCallbackExector
75
+ include ActiveSupport::Callbacks
75
76
 
76
- attr_reader :callback_class
77
- delegate :__callbacks, to: :callback_class
78
- delegate_missing_to :callback_class
77
+ attr_reader :callback_class
78
+ delegate :__callbacks, to: :callback_class
79
+ delegate_missing_to :callback_class
79
80
 
80
- def initialize(cls, env)
81
- @callback_class = cls
82
- env.keys.each do |k|
83
- define_singleton_method(k) do
84
- env[k]
81
+ def initialize(cls, env)
82
+ @callback_class = cls
83
+ env.keys.each do |k|
84
+ define_singleton_method(k) do
85
+ env[k]
86
+ end
85
87
  end
88
+ @options = options
86
89
  end
87
- @options = options
88
- end
89
90
 
90
- def self.run_callbacks(cls, callback, env={}, &blk)
91
- new(cls, env).run_callbacks(callback, &blk)
91
+ def self.run_callbacks(cls, callback, env={}, &blk)
92
+ new(cls, env).run_callbacks(callback, &blk)
93
+ end
92
94
  end
93
95
  end
94
96
  end
@@ -29,29 +29,31 @@
29
29
  # end
30
30
  # end
31
31
  #
32
- module AdvancedAR::CustomPreloaders
33
- module AssociationBuilderExtension
34
- def self.build(model, reflection); end
32
+ module AdvancedAR
33
+ module CustomPreloaders
34
+ module AssociationBuilderExtension
35
+ def self.build(model, reflection); end
35
36
 
36
- def self.valid_options
37
- [:preloader]
37
+ def self.valid_options
38
+ [:preloader]
39
+ end
38
40
  end
39
- end
40
41
 
41
- module PreloaderExtension
42
- def preloader_for(reflection, owners)
43
- cust_preloader = reflection.options[:preloader]
44
- if cust_preloader.present?
45
- cust_preloader = cust_preloader.constantize if cust_preloader.is_a?(String)
46
- cust_preloader
47
- else
48
- super
42
+ module PreloaderExtension
43
+ def preloader_for(reflection, owners)
44
+ cust_preloader = reflection.options[:preloader]
45
+ if cust_preloader.present?
46
+ cust_preloader = cust_preloader.constantize if cust_preloader.is_a?(String)
47
+ cust_preloader
48
+ else
49
+ super
50
+ end
49
51
  end
50
52
  end
51
- end
52
53
 
53
- def self.install
54
- ActiveRecord::Associations::Builder::Association.extensions << AssociationBuilderExtension
55
- ActiveRecord::Associations::Preloader.prepend(CustomPreloaders::PreloaderExtension)
54
+ def self.install
55
+ ActiveRecord::Associations::Builder::Association.extensions << AssociationBuilderExtension
56
+ ActiveRecord::Associations::Preloader.prepend(CustomPreloaders::PreloaderExtension)
57
+ end
56
58
  end
57
59
  end
@@ -1,3 +1,3 @@
1
1
  module AdvancedAR
2
- VERSION = "0.1.4".freeze
2
+ VERSION = "0.1.5".freeze
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: advanced_ar
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ethan Knapp