advanced_ar 0.1.4 → 0.1.5

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: 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