sunstone 5.1.0.4 → 5.2.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.
Files changed (33) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +5 -13
  3. data/ext/active_record/associations.rb +2 -7
  4. data/ext/active_record/associations/collection_association.rb +25 -18
  5. data/ext/active_record/attribute_methods.rb +19 -35
  6. data/ext/active_record/finder_methods.rb +138 -90
  7. data/ext/active_record/persistence.rb +16 -11
  8. data/ext/active_record/relation.rb +7 -47
  9. data/ext/active_record/relation/calculations.rb +5 -3
  10. data/ext/active_record/relation/query_methods.rb +9 -0
  11. data/ext/active_record/statement_cache.rb +4 -6
  12. data/ext/active_record/transactions.rb +9 -19
  13. data/ext/arel/nodes/select_statement.rb +26 -12
  14. data/lib/active_record/connection_adapters/sunstone/database_statements.rb +76 -25
  15. data/lib/active_record/connection_adapters/sunstone/type/json.rb +1 -1
  16. data/lib/active_record/connection_adapters/sunstone_adapter.rb +2 -3
  17. data/lib/arel/collectors/sunstone.rb +21 -19
  18. data/lib/arel/visitors/sunstone.rb +4 -8
  19. data/lib/sunstone.rb +2 -3
  20. data/lib/sunstone/connection.rb +2 -2
  21. data/lib/sunstone/exception.rb +8 -1
  22. data/lib/sunstone/version.rb +1 -1
  23. data/sunstone.gemspec +3 -3
  24. data/test/active_record/associations/has_many_test.rb +30 -2
  25. data/test/active_record/eager_loading_test.rb +10 -0
  26. data/test/active_record/persistance_test.rb +7 -7
  27. data/test/active_record/query/count_test.rb +13 -0
  28. data/test/active_record/query_test.rb +6 -6
  29. data/test/sunstone/connection/send_request_test.rb +1 -1
  30. data/test/test_helper.rb +1 -1
  31. metadata +9 -10
  32. data/ext/active_record/associations/association.rb +0 -16
  33. data/ext/active_record/batches.rb +0 -12
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: d53af8c7411662e7621971b1c2a3f39f130ea8c3
4
- data.tar.gz: 8a61637315c7faf35265b47b8334901340b41798
2
+ SHA256:
3
+ metadata.gz: f235687b97d48caa7ecf7a231928452bbaf807b8d2e6e6508a7f9159372dc600
4
+ data.tar.gz: 94eec63ac1c23762404058fe37b1558a62ec7ad564e262977e1534721949c149
5
5
  SHA512:
6
- metadata.gz: 690936bd2ba33aab551c98da50ea1871e29fdfa9207dd71c7bcd78050bfa56f219ad859c068ac33346833ffb44feb058bc2f41a46ab7c2e4f70b11c0f1449a62
7
- data.tar.gz: 6e9f804cc2b2e75584e184b9791dc3f5b2d0d682c71cd5ef1c60cb4ffdf1af23b6607bf3f650be218acb87f0173dad53b2621fffa3aa9dac40f72fc51efc4663
6
+ metadata.gz: c16d5374f32074dcd7a9e96ecf7f01dc6c77848df299454a5209913f25cdb23b333f4cc6b9a93e6f58d25b6681a11f54b8124f8352427702b22301e81a98a6a7
7
+ data.tar.gz: fb6512b92823f37cac2477010df776a703f12a3f13f455a6d7388c8edffe4a59192fa3aa2114b4f62e244aa4b9a771f32e01718e5c5f2a0ddf2ed382fe49390a
@@ -7,22 +7,14 @@ cache:
7
7
  - /home/travis/.rvm/gems
8
8
 
9
9
  rvm:
10
- - 2.4.1
10
+ - 2.4.4
11
+ - 2.5.1
11
12
 
12
13
  env:
13
14
  matrix:
14
- - RAILS_VERSION=v5.1.0 GEM=ar:mysql2
15
- - RAILS_VERSION=v5.1.0 GEM=ar:sqlite3
16
- - RAILS_VERSION=v5.1.0 GEM=ar:postgresql
17
- - RAILS_VERSION=v5.1.1 GEM=ar:mysql2
18
- - RAILS_VERSION=v5.1.1 GEM=ar:sqlite3
19
- - RAILS_VERSION=v5.1.1 GEM=ar:postgresql
20
- - RAILS_VERSION=v5.1.2 GEM=ar:mysql2
21
- - RAILS_VERSION=v5.1.2 GEM=ar:sqlite3
22
- - RAILS_VERSION=v5.1.2 GEM=ar:postgresql
23
- - RAILS_VERSION=v5.1.3 GEM=ar:mysql2
24
- - RAILS_VERSION=v5.1.3 GEM=ar:sqlite3
25
- - RAILS_VERSION=v5.1.3 GEM=ar:postgresql
15
+ - RAILS_VERSION=v5.2.0 GEM=ar:mysql2
16
+ - RAILS_VERSION=v5.2.0 GEM=ar:sqlite3
17
+ - RAILS_VERSION=v5.2.0 GEM=ar:postgresql
26
18
 
27
19
  addons:
28
20
  postgresql: "9.4"
@@ -3,12 +3,7 @@ require 'active_record/associations'
3
3
  module ActiveRecord
4
4
  module Associations
5
5
  module ClassMethods
6
- def has_and_belongs_to_many(name, scope = nil, options = {}, &extension)
7
- if scope.is_a?(Hash)
8
- options = scope
9
- scope = nil
10
- end
11
-
6
+ def has_and_belongs_to_many(name, scope = nil, **options, &extension)
12
7
  habtm_reflection = ActiveRecord::Reflection::HasAndBelongsToManyReflection.new(name, scope, options, self)
13
8
 
14
9
  builder = Builder::HasAndBelongsToMany.new name, self, options
@@ -45,7 +40,7 @@ module ActiveRecord
45
40
  end
46
41
 
47
42
  has_many name, scope, hm_options, &extension
48
- self._reflections[name.to_s].parent_reflection = habtm_reflection
43
+ _reflections[name.to_s].parent_reflection = habtm_reflection
49
44
  end
50
45
  end
51
46
  end
@@ -9,17 +9,24 @@ module ActiveRecord
9
9
  if owner.new_record?
10
10
  replace_records(other_array, original_target)
11
11
  elsif owner.class.connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter) && owner.instance_variable_defined?(:@updating) && owner.instance_variable_get(:@updating)
12
- self.instance_variable_set(:@sunstone_changed, true)
13
12
  replace_common_records_in_memory(other_array, original_target)
14
13
 
15
14
  # Remove from target
16
- (original_target - other_array).each { |record| callback(:before_remove, record) }
17
- (original_target - other_array).each { |record| target.delete(record) }
18
- (original_target - other_array).each { |record| callback(:after_remove, record) }
15
+ records_for_removal = (original_target - other_array)
16
+ if !records_for_removal.empty?
17
+ self.instance_variable_set(:@sunstone_changed, true)
18
+ records_for_removal.each { |record| callback(:before_remove, record) }
19
+ records_for_removal.each { |record| target.delete(record) }
20
+ records_for_removal.each { |record| callback(:after_remove, record) }
21
+ end
19
22
 
20
23
  # Add to target
21
- (other_array - original_target).each do |record|
22
- add_to_target(record)
24
+ records_for_addition = (other_array - original_target)
25
+ if !records_for_addition.empty?
26
+ self.instance_variable_set(:@sunstone_changed, true)
27
+ (other_array - original_target).each do |record|
28
+ add_to_target(record)
29
+ end
23
30
  end
24
31
 
25
32
  other_array
@@ -33,28 +40,28 @@ module ActiveRecord
33
40
  end
34
41
  end
35
42
 
36
-
37
- end
38
-
39
- class HasManyAssociation
40
-
41
- def insert_record(record, validate = true, raise = false)
42
- set_owner_attributes(record)
43
- set_inverse_instance(record)
44
-
43
+ def insert_record(record, validate = true, raise = false, &block)
45
44
  if record.class.connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter) && (!owner.instance_variable_defined?(:@updating) && owner.instance_variable_get(:@updating))
46
45
  true
47
46
  elsif raise
48
- record.save!(:validate => validate)
47
+ record.save!(validate: validate, &block)
49
48
  else
50
- record.save(:validate => validate)
49
+ record.save(validate: validate, &block)
51
50
  end
52
51
  end
53
52
 
53
+
54
+ end
55
+
56
+ class HasManyThroughAssociation
57
+
54
58
  private
55
59
  def save_through_record(record)
56
60
  return if record.class.connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter)
57
- build_through_record(record).save!
61
+ association = build_through_record(record)
62
+ if association.changed?
63
+ association.save!
64
+ end
58
65
  ensure
59
66
  @through_records.delete(record.object_id)
60
67
  end
@@ -5,26 +5,23 @@ module ActiveRecord
5
5
 
6
6
  # Returns a Hash of the Arel::Attributes and attribute values that have been
7
7
  # typecasted for use in an Arel insert/update method.
8
- def arel_attributes_with_values(attribute_names)
9
- attrs = {}
10
- arel_table = self.class.arel_table
11
-
12
- attribute_names.each do |name|
13
- attrs[arel_table[name]] = typecasted_attribute_value(name)
8
+ def attributes_with_values(attribute_names)
9
+ attrs = attribute_names.each_with_object({}) do |name, attrs|
10
+ attrs[name] = _read_attribute(name)
14
11
  end
15
12
 
16
13
  if self.class.connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter)
17
14
  self.class.reflect_on_all_associations.each do |reflection|
18
15
  if reflection.belongs_to?
19
16
  if association(reflection.name).loaded? && association(reflection.name).target == Thread.current[:sunstone_updating_model]
20
- attrs.delete(arel_table[reflection.foreign_key])
17
+ attrs.delete(reflection.foreign_key)
21
18
  else
22
19
  add_attributes_for_belongs_to_association(reflection, attrs)
23
20
  end
24
21
  elsif reflection.has_one?
25
22
  add_attributes_for_has_one_association(reflection, attrs)
26
23
  elsif reflection.collection?
27
- add_attributes_for_collection_association(reflection, attrs, arel_table)
24
+ add_attributes_for_collection_association(reflection, attrs, self.class.arel_table)
28
25
  end
29
26
  end
30
27
  end
@@ -50,13 +47,9 @@ module ActiveRecord
50
47
  elsif autosave != false
51
48
  if record.new_record? || (autosave && record.changed_for_autosave?)
52
49
  if record.new_record?
53
- record.send(:arel_attributes_with_values_for_create, record.attribute_names).each do |k, v|
54
- attrs[Arel::Attributes::Relation.new(k, reflection.name, false, true)] = v
55
- end
50
+ attrs["#{reflection.name}_attributes"] = record.send(:attributes_with_values_for_create, record.attribute_names)
56
51
  else
57
- record.send(:arel_attributes_with_values_for_update, record.attribute_names).each do |k, v|
58
- attrs[Arel::Attributes::Relation.new(k, reflection.name, false, true)] = v
59
- end
52
+ attrs["#{reflection.name}_attributes"] = record.send(:attributes_with_values_for_update, record.attribute_names)
60
53
  end
61
54
  end
62
55
  end
@@ -87,13 +80,9 @@ module ActiveRecord
87
80
  end
88
81
 
89
82
  if record.new_record?
90
- record.send(:arel_attributes_with_values_for_create, record.attribute_names).each do |k, v|
91
- attrs[Arel::Attributes::Relation.new(k, reflection.name, false, true)] = v
92
- end
83
+ attrs["#{reflection.name}_attributes"] = record.send(:attributes_with_values_for_create, record.attribute_names)
93
84
  else
94
- record.send(:arel_attributes_with_values_for_update, record.attribute_names).each do |k, v|
95
- attrs[Arel::Attributes::Relation.new(k, reflection.name, false, true)] = v
96
- end
85
+ attrs["#{reflection.name}_attributes"] = record.send(:attributes_with_values_for_update, record.attribute_names)
97
86
  end
98
87
  end
99
88
  end
@@ -111,22 +100,19 @@ module ActiveRecord
111
100
  end
112
101
 
113
102
  if association = association_instance_get(reflection.name)
114
- if new_record? || (association.instance_variable_defined?(:@sunstone_changed) && association.instance_variable_get(:@sunstone_changed)) || reflection.options[:autosave] || association.target.any?(&:changed_for_autosave?) || association.target.any?(&:new_record?)
115
- attrs[Arel::Attributes::EmptyRelation.new(arel_table, reflection.name, true, true)] = [] if association.target.empty?
116
-
117
- association.target.each_with_index do |record, idx|
118
- next if record.destroyed?
119
-
120
- if record.new_record?
121
- record.send(:arel_attributes_with_values_for_create, record.send(:keys_for_partial_write) + [record.class.primary_key]).each do |k, v|
122
- attrs[Arel::Attributes::Relation.new(k, reflection.name, idx, true)] = v
123
- end
124
- else
125
- record.send(:arel_attributes_with_values_for_update, record.send(:keys_for_partial_write) + [record.class.primary_key]).each do |k, v|
126
- attrs[Arel::Attributes::Relation.new(k, reflection.name, idx, true)] = v
103
+ if new_record? || (association.instance_variable_defined?(:@sunstone_changed) && association.instance_variable_get(:@sunstone_changed)) || association.target.any?(&:changed_for_autosave?) || association.target.any?(&:new_record?)
104
+ attrs["#{reflection.name}_attributes"] = if association.target.empty?
105
+ []
106
+ else
107
+ association.target.select { |r| !r.destroyed? }.map do |record|
108
+ if record.new_record?
109
+ record.send(:attributes_with_values_for_create, record.send(:keys_for_partial_write) + [record.class.primary_key])
110
+ else
111
+ record.send(:attributes_with_values_for_update, record.send(:keys_for_partial_write) + [record.class.primary_key])
127
112
  end
128
113
  end
129
114
  end
115
+
130
116
  association.instance_variable_set(:@sunstone_changed, false)
131
117
  end
132
118
 
@@ -134,8 +120,6 @@ module ActiveRecord
134
120
  association.reset_scope if association.respond_to?(:reset_scope)
135
121
  end
136
122
  end
137
-
138
-
139
123
 
140
124
  end
141
125
  end
@@ -17,7 +17,7 @@ module ActiveRecord
17
17
  return ["1=0"] if attributes.empty?
18
18
 
19
19
  attributes.flat_map do |key, value|
20
- if value.is_a?(Hash)
20
+ if value.is_a?(Hash) && !table.has_column?(key)
21
21
  ka = associated_predicate_builder(key).expand_from_hash(value)
22
22
  if self.table.instance_variable_get(:@klass).connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter)
23
23
  ka.each { |k|
@@ -27,6 +27,38 @@ module ActiveRecord
27
27
  }
28
28
  end
29
29
  ka
30
+ elsif table.associated_with?(key)
31
+ # Find the foreign key when using queries such as:
32
+ # Post.where(author: author)
33
+ #
34
+ # For polymorphic relationships, find the foreign key and type:
35
+ # PriceEstimate.where(estimate_of: treasure)
36
+ associated_table = table.associated_table(key)
37
+ if associated_table.polymorphic_association?
38
+ case value.is_a?(Array) ? value.first : value
39
+ when Base, Relation
40
+ value = [value] unless value.is_a?(Array)
41
+ klass = PolymorphicArrayValue
42
+ end
43
+ end
44
+
45
+ klass ||= AssociationQueryValue
46
+ queries = klass.new(associated_table, value).queries.map do |query|
47
+ expand_from_hash(query).reduce(&:and)
48
+ end
49
+ queries.reduce(&:or)
50
+ elsif table.aggregated_with?(key)
51
+ mapping = table.reflect_on_aggregation(key).mapping
52
+ queries = Array.wrap(value).map do |object|
53
+ mapping.map do |field_attr, aggregate_attr|
54
+ if mapping.size == 1 && !object.respond_to?(aggregate_attr)
55
+ build(table.arel_attribute(field_attr), object)
56
+ else
57
+ build(table.arel_attribute(field_attr), object.send(aggregate_attr))
58
+ end
59
+ end.reduce(&:and)
60
+ end
61
+ queries.reduce(&:or)
30
62
  else
31
63
  build(table.arel_attribute(key), value)
32
64
  end
@@ -39,98 +71,113 @@ end
39
71
  module ActiveRecord
40
72
  module FinderMethods
41
73
 
42
- def find_with_associations
43
- join_dependency = nil
44
- aliases = nil
45
- relation = if connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter)
46
- arel.eager_load = Arel::Nodes::EagerLoad.new(eager_load_values)
47
- self
48
- else
49
- join_dependency = construct_join_dependency(joins_values)
50
- aliases = join_dependency.aliases
51
- apply_join_dependency(select(aliases.columns), join_dependency)
74
+ class SunstoneJoinDependency
75
+ def initialize(klass)
76
+ @klass = klass
52
77
  end
53
78
 
54
- if block_given?
55
- yield relation
56
- else
57
- if ActiveRecord::NullRelation === relation
58
- []
59
- else
60
- arel = relation.arel
61
- rows = if connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter)
62
- connection.select_all(arel, 'SQL', arel.bind_values + relation.bound_attributes)
63
- else
64
- connection.select_all(arel, 'SQL', relation.bound_attributes)
65
- end
66
- if join_dependency
67
- join_dependency.instantiate(rows, aliases)
68
- else
69
- instantiate_with_associations(rows, relation)
70
- end
71
- end
79
+ def reflections
80
+ []
72
81
  end
73
- end
82
+
83
+ def apply_column_aliases(relation)
84
+ relation
85
+ end
86
+
87
+ def instantiate(result_set, &block)
88
+ seen = Hash.new { |i, object_id|
89
+ i[object_id] = Hash.new { |j, child_class|
90
+ j[child_class] = {}
91
+ }
92
+ }
93
+
94
+ model_cache = Hash.new { |h, klass| h[klass] = {} }
95
+ parents = model_cache[@klass]
96
+
97
+ message_bus = ActiveSupport::Notifications.instrumenter
74
98
 
75
- def instantiate_with_associations(result_set, klass)
76
- seen = Hash.new { |h, parent_klass|
77
- h[parent_klass] = Hash.new { |i, parent_id|
78
- i[parent_id] = Hash.new { |j, child_klass| j[child_klass] = {} }
99
+ payload = {
100
+ record_count: result_set.length,
101
+ class_name: @klass.name
79
102
  }
80
- }
81
103
 
82
- model_cache = Hash.new { |h,kklass| h[kklass] = {} }
83
- parents = model_cache[self.base_class]
104
+ message_bus.instrument("instantiation.active_record", payload) do
105
+ result_set.each { |row_hash|
106
+ parent_key = @klass.primary_key ? row_hash[@klass.primary_key] : row_hash
107
+ parent = parents[parent_key] ||= @klass.instantiate(row_hash.select{|k,v| @klass.column_names.include?(k.to_s) }, &block)
108
+ construct(parent, row_hash.select{|k,v| !@klass.column_names.include?(k.to_s) }, seen, model_cache)
109
+ }
110
+ end
84
111
 
85
- result_set.each { |row_hash|
86
- parent = parents[row_hash[primary_key]] ||= instantiate(row_hash.select{|k,v| column_names.include?(k.to_s) })
87
- construct(parent, row_hash.select{|k,v| !column_names.include?(k.to_s) }, seen, model_cache)
88
- }
112
+ parents.values
113
+ end
89
114
 
90
- parents.values
91
- end
115
+ def construct(parent, relations, seen, model_cache)
116
+ relations.each do |key, attributes|
117
+ reflection = parent.class.reflect_on_association(key)
118
+ next unless reflection
92
119
 
93
- def construct(parent, relations, seen, model_cache)
94
- relations.each do |key, attributes|
95
- reflection = parent.class.reflect_on_association(key)
96
- next unless reflection
120
+ if reflection.collection?
121
+ other = parent.association(reflection.name)
122
+ other.loaded!
123
+ else
124
+ if parent.association_cached?(reflection.name)
125
+ model = parent.association(reflection.name).target
126
+ construct(model, attributes.select{|k,v| !model.class.column_names.include?(k.to_s) }, seen, model_cache)
127
+ end
128
+ end
97
129
 
98
- if reflection.collection?
99
- other = parent.association(reflection.name)
100
- other.loaded!
101
- else
102
- if parent.association_cached?(reflection.name)
103
- model = parent.association(reflection.name).target
104
- construct(model, attributes.select{|k,v| !model.class.column_names.include?(k.to_s) }, seen, model_cache)
130
+ if !reflection.collection?
131
+ construct_association(parent, reflection, attributes, seen, model_cache)
132
+ else
133
+ attributes.each do |row|
134
+ construct_association(parent, reflection, row, seen, model_cache)
135
+ end
105
136
  end
137
+
106
138
  end
139
+ end
140
+
141
+ def construct_association(parent, reflection, attributes, seen, model_cache)
142
+ return if attributes.nil?
107
143
 
108
- if !reflection.collection?
109
- construct_association(parent, reflection, attributes, seen, model_cache)
144
+ klass = if reflection.polymorphic?
145
+ parent.send(reflection.foreign_type).constantize.base_class
110
146
  else
111
- attributes.each do |row|
112
- construct_association(parent, reflection, row, seen, model_cache)
113
- end
147
+ reflection.klass
114
148
  end
149
+ id = attributes[klass.primary_key]
150
+ model = seen[parent.object_id][klass][id]
115
151
 
116
- end
117
- end
152
+ if model
153
+ construct(model, attributes.select{|k,v| !klass.column_names.include?(k.to_s) }, seen, model_cache)
118
154
 
119
- def construct_association(parent, reflection, attributes, seen, model_cache)
120
- return if attributes.nil?
155
+ other = parent.association(reflection.name)
121
156
 
122
- klass = if reflection.polymorphic?
123
- parent.send(reflection.foreign_type).constantize.base_class
124
- else
125
- reflection.klass
157
+ if reflection.collection?
158
+ other.target.push(model)
159
+ else
160
+ other.target = model
161
+ end
162
+
163
+ other.set_inverse_instance(model)
164
+ else
165
+ model = construct_model(parent, reflection, id, attributes.select{|k,v| klass.column_names.include?(k.to_s) }, seen, model_cache)
166
+ seen[parent.object_id][model.class.base_class][id] = model
167
+ construct(model, attributes.select{|k,v| !klass.column_names.include?(k.to_s) }, seen, model_cache)
168
+ end
126
169
  end
127
- id = attributes[klass.primary_key]
128
- model = seen[parent.class.base_class][parent.id][klass][id]
129
170
 
130
- if model
131
- construct(model, attributes.select{|k,v| !klass.column_names.include?(k.to_s) }, seen, model_cache)
132
171
 
133
- other = parent.association(reflection.name)
172
+ def construct_model(record, reflection, id, attributes, seen, model_cache)
173
+ klass = if reflection.polymorphic?
174
+ record.send(reflection.foreign_type).constantize
175
+ else
176
+ reflection.klass
177
+ end
178
+
179
+ model = model_cache[klass][id] ||= klass.instantiate(attributes)
180
+ other = record.association(reflection.name)
134
181
 
135
182
  if reflection.collection?
136
183
  other.target.push(model)
@@ -139,34 +186,35 @@ module ActiveRecord
139
186
  end
140
187
 
141
188
  other.set_inverse_instance(model)
142
- else
143
- model = construct_model(parent, reflection, id, attributes.select{|k,v| klass.column_names.include?(k.to_s) }, seen, model_cache)
144
- seen[parent.class.base_class][parent.id][model.class.base_class][id] = model
145
- construct(model, attributes.select{|k,v| !klass.column_names.include?(k.to_s) }, seen, model_cache)
189
+ model
146
190
  end
191
+
147
192
  end
148
193
 
149
-
150
- def construct_model(record, reflection, id, attributes, seen, model_cache)
151
- klass = if reflection.polymorphic?
152
- record.send(reflection.foreign_type).constantize
194
+ def apply_join_dependency(eager_loading: group_values.empty?)
195
+ if connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter)
196
+ join_dependency = SunstoneJoinDependency.new(base_class)
197
+ relation = except(:includes, :eager_load, :preload)
198
+ relation.arel.eager_load = Arel::Nodes::EagerLoad.new(eager_load_values)
153
199
  else
154
- reflection.klass
200
+ join_dependency = construct_join_dependency
201
+ relation = except(:includes, :eager_load, :preload).joins!(join_dependency)
155
202
  end
156
203
 
157
- model = model_cache[klass][id] ||= klass.instantiate(attributes)
158
- other = record.association(reflection.name)
204
+ if eager_loading && !using_limitable_reflections?(join_dependency.reflections)
205
+ if has_limit_or_offset?
206
+ limited_ids = limited_ids_for(relation)
207
+ limited_ids.empty? ? relation.none! : relation.where!(primary_key => limited_ids)
208
+ end
209
+ relation.limit_value = relation.offset_value = nil
210
+ end
159
211
 
160
- if reflection.collection?
161
- other.target.push(model)
212
+ if block_given?
213
+ yield relation, join_dependency
162
214
  else
163
- other.target = model
215
+ relation
164
216
  end
165
-
166
- other.set_inverse_instance(model)
167
- model
168
217
  end
169
-
170
218
  end
171
219
 
172
220
  end