datastax_rails 2.0.12 → 2.0.15
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Rakefile +5 -5
- data/lib/blankslate.rb +8 -11
- data/lib/cql-rb_extensions.rb +5 -3
- data/lib/datastax_rails/associations/association.rb +93 -101
- data/lib/datastax_rails/associations/association_scope.rb +7 -7
- data/lib/datastax_rails/associations/belongs_to_association.rb +46 -48
- data/lib/datastax_rails/associations/builder/association.rb +32 -31
- data/lib/datastax_rails/associations/builder/belongs_to.rb +19 -20
- data/lib/datastax_rails/associations/builder/collection_association.rb +32 -32
- data/lib/datastax_rails/associations/builder/has_and_belongs_to_many.rb +21 -21
- data/lib/datastax_rails/associations/builder/has_many.rb +39 -40
- data/lib/datastax_rails/associations/builder/has_one.rb +30 -31
- data/lib/datastax_rails/associations/builder/singular_association.rb +31 -33
- data/lib/datastax_rails/associations/collection_association.rb +129 -135
- data/lib/datastax_rails/associations/collection_proxy.rb +21 -21
- data/lib/datastax_rails/associations/has_and_belongs_to_many_association.rb +26 -26
- data/lib/datastax_rails/associations/has_many_association.rb +38 -38
- data/lib/datastax_rails/associations/has_one_association.rb +31 -32
- data/lib/datastax_rails/associations/singular_association.rb +31 -30
- data/lib/datastax_rails/associations.rb +27 -24
- data/lib/datastax_rails/attribute_assignment.rb +17 -17
- data/lib/datastax_rails/attribute_methods/definition.rb +4 -4
- data/lib/datastax_rails/attribute_methods/dirty.rb +34 -33
- data/lib/datastax_rails/attribute_methods/primary_key.rb +3 -8
- data/lib/datastax_rails/attribute_methods/read.rb +10 -12
- data/lib/datastax_rails/attribute_methods/typecasting.rb +36 -35
- data/lib/datastax_rails/attribute_methods/write.rb +5 -6
- data/lib/datastax_rails/attribute_methods.rb +52 -56
- data/lib/datastax_rails/base.rb +122 -125
- data/lib/datastax_rails/callbacks.rb +15 -9
- data/lib/datastax_rails/cassandra_only_model.rb +6 -6
- data/lib/datastax_rails/collection.rb +5 -7
- data/lib/datastax_rails/column.rb +130 -118
- data/lib/datastax_rails/connection/statement_cache.rb +3 -3
- data/lib/datastax_rails/connection.rb +42 -33
- data/lib/datastax_rails/cql/alter_column_family.rb +19 -21
- data/lib/datastax_rails/cql/base.rb +8 -11
- data/lib/datastax_rails/cql/column_family.rb +11 -10
- data/lib/datastax_rails/cql/consistency.rb +2 -2
- data/lib/datastax_rails/cql/create_column_family.rb +15 -15
- data/lib/datastax_rails/cql/create_index.rb +5 -5
- data/lib/datastax_rails/cql/create_keyspace.rb +7 -7
- data/lib/datastax_rails/cql/delete.rb +16 -29
- data/lib/datastax_rails/cql/drop_column_family.rb +2 -2
- data/lib/datastax_rails/cql/drop_index.rb +2 -2
- data/lib/datastax_rails/cql/drop_keyspace.rb +2 -2
- data/lib/datastax_rails/cql/insert.rb +10 -16
- data/lib/datastax_rails/cql/select.rb +21 -33
- data/lib/datastax_rails/cql/truncate.rb +2 -2
- data/lib/datastax_rails/cql/update.rb +16 -24
- data/lib/datastax_rails/cql/use_keyspace.rb +2 -2
- data/lib/datastax_rails/cql.rb +2 -2
- data/lib/datastax_rails/dynamic_model.rb +32 -29
- data/lib/datastax_rails/errors.rb +6 -6
- data/lib/datastax_rails/grouped_collection.rb +3 -3
- data/lib/datastax_rails/inheritance.rb +9 -9
- data/lib/datastax_rails/payload_model.rb +24 -20
- data/lib/datastax_rails/persistence.rb +116 -110
- data/lib/datastax_rails/railtie.rb +7 -7
- data/lib/datastax_rails/reflection.rb +61 -59
- data/lib/datastax_rails/relation/batches.rb +12 -13
- data/lib/datastax_rails/relation/facet_methods.rb +44 -33
- data/lib/datastax_rails/relation/finder_methods.rb +95 -91
- data/lib/datastax_rails/relation/modification_methods.rb +5 -5
- data/lib/datastax_rails/relation/search_methods.rb +102 -102
- data/lib/datastax_rails/relation/spawn_methods.rb +25 -24
- data/lib/datastax_rails/relation/stats_methods.rb +9 -8
- data/lib/datastax_rails/relation.rb +165 -170
- data/lib/datastax_rails/rsolr_client_wrapper.rb +3 -3
- data/lib/datastax_rails/schema/cassandra.rb +44 -43
- data/lib/datastax_rails/schema/migrator.rb +52 -52
- data/lib/datastax_rails/schema/solr.rb +55 -47
- data/lib/datastax_rails/schema_cache.rb +1 -3
- data/lib/datastax_rails/scoping/default.rb +2 -3
- data/lib/datastax_rails/scoping/named.rb +3 -5
- data/lib/datastax_rails/scoping.rb +11 -12
- data/lib/datastax_rails/serialization.rb +34 -31
- data/lib/datastax_rails/serializers/xml_serializer.rb +178 -175
- data/lib/datastax_rails/timestamps.rb +4 -4
- data/lib/datastax_rails/types/dirty_collection.rb +57 -57
- data/lib/datastax_rails/types/dynamic_list.rb +1 -1
- data/lib/datastax_rails/types/dynamic_map.rb +5 -7
- data/lib/datastax_rails/types/dynamic_set.rb +2 -2
- data/lib/datastax_rails/util/solr_repair.rb +3 -3
- data/lib/datastax_rails/validations/associated.rb +8 -6
- data/lib/datastax_rails/validations/uniqueness.rb +8 -8
- data/lib/datastax_rails/validations.rb +9 -10
- data/lib/datastax_rails/version.rb +2 -1
- data/lib/datastax_rails/wide_storage_model.rb +6 -6
- data/lib/datastax_rails.rb +13 -9
- data/lib/schema_migration.rb +3 -3
- data/spec/datastax_rails/associations/belongs_to_association_spec.rb +2 -2
- data/spec/datastax_rails/associations/collection_association_spec.rb +14 -14
- data/spec/datastax_rails/associations/has_many_association_spec.rb +20 -20
- data/spec/datastax_rails/associations_spec.rb +11 -11
- data/spec/datastax_rails/attribute_methods_spec.rb +25 -25
- data/spec/datastax_rails/base_spec.rb +24 -24
- data/spec/datastax_rails/callbacks_spec.rb +21 -21
- data/spec/datastax_rails/column_spec.rb +133 -132
- data/spec/datastax_rails/connection/statement_cache_spec.rb +2 -2
- data/spec/datastax_rails/cql/base_spec.rb +4 -4
- data/spec/datastax_rails/cql/delete_spec.rb +19 -0
- data/spec/datastax_rails/cql/select_spec.rb +8 -8
- data/spec/datastax_rails/cql/update_spec.rb +8 -10
- data/spec/datastax_rails/dynamic_model_spec.rb +36 -22
- data/spec/datastax_rails/inheritance_spec.rb +11 -14
- data/spec/datastax_rails/persistence_spec.rb +73 -74
- data/spec/datastax_rails/relation/batches_spec.rb +13 -13
- data/spec/datastax_rails/relation/facet_methods_spec.rb +43 -35
- data/spec/datastax_rails/relation/finder_methods_spec.rb +77 -78
- data/spec/datastax_rails/relation/modification_methods_spec.rb +19 -19
- data/spec/datastax_rails/relation/search_methods_spec.rb +160 -160
- data/spec/datastax_rails/relation/spawn_methods_spec.rb +18 -18
- data/spec/datastax_rails/relation_spec.rb +119 -116
- data/spec/datastax_rails/schema/migrator_spec.rb +30 -30
- data/spec/datastax_rails/schema/solr_spec.rb +15 -15
- data/spec/datastax_rails/scoping/default_spec.rb +9 -9
- data/spec/datastax_rails/types/dynamic_list_spec.rb +12 -12
- data/spec/datastax_rails/types/dynamic_map_spec.rb +10 -10
- data/spec/datastax_rails/types/dynamic_set_spec.rb +22 -10
- data/spec/datastax_rails/validations/uniqueness_spec.rb +25 -25
- data/spec/datastax_rails/wide_storage_model_spec.rb +11 -0
- data/spec/datastax_rails_spec.rb +2 -2
- data/spec/dummy/config/application.rb +2 -3
- data/spec/dummy/config/boot.rb +1 -1
- data/spec/dummy/config/environments/development.rb +3 -3
- data/spec/dummy/config/environments/test.rb +1 -1
- data/spec/dummy/config/initializers/session_store.rb +1 -1
- data/spec/dummy/config/initializers/wrap_parameters.rb +1 -1
- data/spec/factories/audit_logs.rb +6 -0
- data/spec/factories/hobbies.rb +6 -0
- data/spec/factories/people.rb +5 -0
- data/spec/feature/dynamic_fields_spec.rb +4 -4
- data/spec/feature/overloaded_tables_spec.rb +11 -12
- data/spec/spec_helper.rb +17 -14
- data/spec/support/datastax_test_hook.rb +2 -2
- data/spec/support/default_consistency_shared_examples.rb +11 -11
- data/spec/support/models.rb +31 -32
- metadata +40 -6
- data/lib/datastax_rails/attribute_methods/before_type_cast.rb +0 -71
- data/lib/datastax_rails/log_subscriber.rb +0 -0
- data/spec/dummy/ks/migrate/20111117224534_models.rb +0 -20
@@ -1,8 +1,8 @@
|
|
1
|
-
module DatastaxRails::Associations::Builder
|
1
|
+
module DatastaxRails::Associations::Builder # rubocop:disable Style/ClassAndModuleChildren
|
2
2
|
class SingularAssociation < Association #:nodoc:
|
3
|
-
#self.valid_options += [:remote, :dependent, :counter_cache, :primary_key, :inverse_of]
|
3
|
+
# self.valid_options += [:remote, :dependent, :counter_cache, :primary_key, :inverse_of]
|
4
4
|
self.valid_options += [:dependent, :denorm]
|
5
|
-
|
5
|
+
|
6
6
|
def constructable?
|
7
7
|
true
|
8
8
|
end
|
@@ -11,7 +11,7 @@ module DatastaxRails::Associations::Builder
|
|
11
11
|
super
|
12
12
|
define_constructors if constructable?
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
def build
|
16
16
|
relation = super
|
17
17
|
configure_denorm
|
@@ -19,38 +19,36 @@ module DatastaxRails::Associations::Builder
|
|
19
19
|
end
|
20
20
|
|
21
21
|
private
|
22
|
-
|
23
|
-
def configure_denorm
|
24
|
-
if options[:denorm]
|
25
|
-
unless options[:denorm].is_a?(Hash)
|
26
|
-
raise ArgumentError, "The :denorm option expects a hash in the form {:attr_on_other_model => :virtual_attr_on_this_model}"
|
27
|
-
end
|
28
|
-
|
29
|
-
# options[:denorm].each do |remote, local|
|
30
|
-
# # Default everything to a string. If it should be something different, the developer can declare the attribute manually.
|
31
|
-
# model.send(:string, local)
|
32
|
-
# model.send(:class_eval, <<-eoruby, __FILE__, __LINE__ + 1)
|
33
|
-
# def #{local}
|
34
|
-
# eoruby
|
35
|
-
# end
|
36
|
-
|
37
|
-
end
|
38
|
-
end
|
39
22
|
|
40
|
-
|
41
|
-
|
23
|
+
def configure_denorm
|
24
|
+
return unless options[:denorm]
|
25
|
+
options[:denorm].is_a?(Hash) || fail(ArgumentError, 'The :denorm option expects a hash in the form ' \
|
26
|
+
'{:attr_on_other_model => :virtual_attr_on_this_model}')
|
42
27
|
|
43
|
-
|
44
|
-
|
45
|
-
|
28
|
+
# options[:denorm].each do |remote, local|
|
29
|
+
# # Default everything to a string. If it should be something different,
|
30
|
+
# # the developer can declare the attribute manually.
|
31
|
+
# model.send(:string, local)
|
32
|
+
# model.send(:class_eval, <<-eoruby, __FILE__, __LINE__ + 1)
|
33
|
+
# def #{local}
|
34
|
+
# eoruby
|
35
|
+
# end
|
36
|
+
end
|
46
37
|
|
47
|
-
|
48
|
-
|
49
|
-
end
|
38
|
+
def define_constructors
|
39
|
+
name = self.name
|
50
40
|
|
51
|
-
|
52
|
-
|
53
|
-
end
|
41
|
+
model.redefine_method("build_#{name}") do |*params, &block|
|
42
|
+
association(name).build(*params, &block)
|
54
43
|
end
|
44
|
+
|
45
|
+
model.redefine_method("create_#{name}") do |*params, &block|
|
46
|
+
association(name).create(*params, &block)
|
47
|
+
end
|
48
|
+
|
49
|
+
model.redefine_method("create_#{name}!") do |*params, &block|
|
50
|
+
association(name).create!(*params, &block)
|
51
|
+
end
|
52
|
+
end
|
55
53
|
end
|
56
|
-
end
|
54
|
+
end
|
@@ -17,14 +17,14 @@ module DatastaxRails
|
|
17
17
|
# +load_target+ and the +loaded+ flag are your friends.
|
18
18
|
class CollectionAssociation < Association #:nodoc:
|
19
19
|
attr_reader :proxy
|
20
|
-
|
21
|
-
delegate :first, :last, :
|
22
|
-
|
20
|
+
|
21
|
+
delegate :first, :last, to: :scoped
|
22
|
+
|
23
23
|
def initialize(owner, reflection)
|
24
24
|
super
|
25
25
|
@proxy = CollectionProxy.new(self)
|
26
26
|
end
|
27
|
-
|
27
|
+
|
28
28
|
def size
|
29
29
|
if !find_target? || loaded?
|
30
30
|
target.size
|
@@ -36,33 +36,30 @@ module DatastaxRails
|
|
36
36
|
end
|
37
37
|
end
|
38
38
|
alias_method :count, :size
|
39
|
-
|
39
|
+
|
40
40
|
def empty?
|
41
41
|
size == 0
|
42
42
|
end
|
43
|
-
|
43
|
+
|
44
44
|
def any?
|
45
45
|
size > 0
|
46
46
|
end
|
47
|
-
|
47
|
+
|
48
48
|
def many?
|
49
49
|
size > 1
|
50
50
|
end
|
51
|
-
|
51
|
+
|
52
52
|
# Implements the reader method, e.g. foo.items for Foo.has_many :items
|
53
53
|
def reader(force_reload = false)
|
54
|
-
if force_reload || stale_target?
|
55
|
-
reload
|
56
|
-
end
|
57
|
-
|
54
|
+
reload if force_reload || stale_target?
|
58
55
|
proxy
|
59
56
|
end
|
60
|
-
|
57
|
+
|
61
58
|
# Implements the writer method, e.g. foo.items= for Foo.has_many :items
|
62
59
|
def writer(records)
|
63
60
|
replace(records)
|
64
61
|
end
|
65
|
-
|
62
|
+
|
66
63
|
# Implements the ids reader method, e.g. foo.item_ids for Foo.has_many :items
|
67
64
|
def ids_reader
|
68
65
|
if loaded?
|
@@ -75,21 +72,21 @@ module DatastaxRails
|
|
75
72
|
end
|
76
73
|
end
|
77
74
|
end
|
78
|
-
|
75
|
+
|
79
76
|
# Implements the ids writer method, e.g. foo.item_ids= for Foo.has_many :items
|
80
77
|
def ids_writer(ids)
|
81
78
|
ids = Array.wrap(ids).reject { |id| id.blank? }
|
82
79
|
replace(klass.find(ids).index_by { |r| r.id }.values_at(*ids))
|
83
80
|
end
|
84
|
-
|
81
|
+
|
85
82
|
def reset
|
86
83
|
@loaded = false
|
87
84
|
@target = []
|
88
85
|
end
|
89
|
-
|
86
|
+
|
90
87
|
def build(attributes = {}, options = {}, &block)
|
91
88
|
if attributes.is_a?(Array)
|
92
|
-
attributes.
|
89
|
+
attributes.map { |attr| build(attr, options, &block) }
|
93
90
|
else
|
94
91
|
add_to_target(build_record(attributes, options)) do |record|
|
95
92
|
yield(record) if block_given?
|
@@ -104,7 +101,7 @@ module DatastaxRails
|
|
104
101
|
def create!(attributes = {}, options = {}, &block)
|
105
102
|
create_record(attributes, options, true, &block)
|
106
103
|
end
|
107
|
-
|
104
|
+
|
108
105
|
# Remove all records from this association
|
109
106
|
#
|
110
107
|
# See delete for more info.
|
@@ -124,7 +121,7 @@ module DatastaxRails
|
|
124
121
|
loaded!
|
125
122
|
end
|
126
123
|
end
|
127
|
-
|
124
|
+
|
128
125
|
# Removes +records+ from this association calling +before_remove+ and
|
129
126
|
# +after_remove+ callbacks.
|
130
127
|
#
|
@@ -142,31 +139,28 @@ module DatastaxRails
|
|
142
139
|
# Note that this method will _always_ remove records from the database
|
143
140
|
# ignoring the +:dependent+ option.
|
144
141
|
def destroy(*records)
|
145
|
-
records = find(records) if records.any? { |record| record.
|
142
|
+
records = find(records) if records.any? { |record| record.is_a?(Fixnum) || record.is_a?(String) }
|
146
143
|
delete_or_destroy(records, :destroy)
|
147
144
|
end
|
148
|
-
|
145
|
+
|
149
146
|
def uniq(collection = load_target)
|
150
147
|
seen = {}
|
151
|
-
collection.
|
148
|
+
collection.select do |record|
|
152
149
|
seen[record.id] = true unless seen.key?(record.id)
|
153
150
|
end
|
154
151
|
end
|
155
|
-
|
156
|
-
def load_target
|
157
|
-
if find_target?
|
158
|
-
@target = merge_target_lists(find_target, target)
|
159
|
-
end
|
160
152
|
|
153
|
+
def load_target
|
154
|
+
@target = merge_target_lists(find_target, target) if find_target?
|
161
155
|
loaded!
|
162
156
|
target
|
163
157
|
end
|
164
|
-
|
158
|
+
|
165
159
|
def add_to_target(record)
|
166
160
|
callback(:before_add, record)
|
167
161
|
yield(record) if block_given?
|
168
162
|
|
169
|
-
if options[:uniq] && index = @target.index(record)
|
163
|
+
if options[:uniq] && (index = @target.index(record))
|
170
164
|
@target[index] = record
|
171
165
|
else
|
172
166
|
@target << record
|
@@ -177,7 +171,7 @@ module DatastaxRails
|
|
177
171
|
|
178
172
|
record
|
179
173
|
end
|
180
|
-
|
174
|
+
|
181
175
|
# Replace this collection with +other_array+
|
182
176
|
# This will perform a diff and delete/add only records that have changed.
|
183
177
|
def replace(other_array)
|
@@ -186,13 +180,13 @@ module DatastaxRails
|
|
186
180
|
|
187
181
|
delete(target - other_array)
|
188
182
|
|
189
|
-
unless concat(other_array - target)
|
183
|
+
unless concat(other_array - target) # rubocop:disable Style/GuardClause
|
190
184
|
@target = original_target
|
191
|
-
|
192
|
-
|
185
|
+
fail RecordNotSaved, "Failed to replace #{reflection.name} because one or more of the " \
|
186
|
+
'new records could not be saved.'
|
193
187
|
end
|
194
188
|
end
|
195
|
-
|
189
|
+
|
196
190
|
# Add +records+ to this association. Returns +self+ so method calls may be chained.
|
197
191
|
# Since << flattens its argument list and inserts each record, +push+ and +concat+ behave identically.
|
198
192
|
def concat(*records)
|
@@ -201,129 +195,129 @@ module DatastaxRails
|
|
201
195
|
|
202
196
|
records.flatten.each do |record|
|
203
197
|
raise_on_type_mismatch(record)
|
204
|
-
add_to_target(record) do |
|
198
|
+
add_to_target(record) do |_r|
|
205
199
|
result &&= insert_record(record) unless owner.new_record?
|
206
200
|
end
|
207
201
|
end
|
208
202
|
|
209
203
|
result && records
|
210
204
|
end
|
211
|
-
|
205
|
+
|
212
206
|
private
|
213
|
-
|
214
|
-
# We have some records loaded from the database (persisted) and some that are
|
215
|
-
# in-memory (memory). The same record may be represented in the persisted array
|
216
|
-
# and in the memory array.
|
217
|
-
#
|
218
|
-
# So the task of this method is to merge them according to the following rules:
|
219
|
-
#
|
220
|
-
# * The final array must not have duplicates
|
221
|
-
# * The order of the persisted array is to be preserved
|
222
|
-
# * Any changes made to attributes on objects in the memory array are to be preserved
|
223
|
-
# * Otherwise, attributes should have the value found in the database
|
224
|
-
def merge_target_lists(persisted, memory)
|
225
|
-
return persisted if memory.empty?
|
226
|
-
return memory if persisted.empty?
|
227
|
-
|
228
|
-
persisted.map! do |record|
|
229
|
-
# Unfortunately we cannot simply do memory.delete(record) since on 1.8 this returns
|
230
|
-
# record rather than memory.at(memory.index(record)). The behavior is fixed in 1.9.
|
231
|
-
mem_index = memory.index(record)
|
232
|
-
|
233
|
-
if mem_index
|
234
|
-
mem_record = memory.delete_at(mem_index)
|
235
|
-
|
236
|
-
(record.attribute_names - mem_record.changes.keys).each do |name|
|
237
|
-
mem_record[name] = record[name]
|
238
|
-
end
|
239
|
-
|
240
|
-
mem_record
|
241
|
-
else
|
242
|
-
record
|
243
|
-
end
|
244
|
-
end
|
245
207
|
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
end
|
208
|
+
# We have some records loaded from the database (persisted) and some that are
|
209
|
+
# in-memory (memory). The same record may be represented in the persisted array
|
210
|
+
# and in the memory array.
|
211
|
+
#
|
212
|
+
# So the task of this method is to merge them according to the following rules:
|
213
|
+
#
|
214
|
+
# * The final array must not have duplicates
|
215
|
+
# * The order of the persisted array is to be preserved
|
216
|
+
# * Any changes made to attributes on objects in the memory array are to be preserved
|
217
|
+
# * Otherwise, attributes should have the value found in the database
|
218
|
+
def merge_target_lists(persisted, memory)
|
219
|
+
return persisted if memory.empty?
|
220
|
+
return memory if persisted.empty?
|
260
221
|
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
222
|
+
persisted.map! do |record|
|
223
|
+
# Unfortunately we cannot simply do memory.delete(record) since on 1.8 this returns
|
224
|
+
# record rather than memory.at(memory.index(record)). The behavior is fixed in 1.9.
|
225
|
+
mem_index = memory.index(record)
|
226
|
+
|
227
|
+
if mem_index
|
228
|
+
mem_record = memory.delete_at(mem_index)
|
229
|
+
|
230
|
+
(record.attribute_names - mem_record.changes.keys).each do |name|
|
231
|
+
mem_record[name] = record[name]
|
267
232
|
end
|
233
|
+
|
234
|
+
mem_record
|
235
|
+
else
|
236
|
+
record
|
268
237
|
end
|
269
238
|
end
|
270
239
|
|
271
|
-
|
272
|
-
|
273
|
-
|
240
|
+
persisted + memory
|
241
|
+
end
|
242
|
+
|
243
|
+
def find_target
|
244
|
+
records = scoped.all
|
245
|
+
records = options[:uniq] ? uniq(records) : records
|
246
|
+
records.each { |record| set_inverse_instance(record) }
|
247
|
+
records
|
248
|
+
end
|
249
|
+
|
250
|
+
def create_record(attributes, options, raise = false, &block)
|
251
|
+
unless owner.persisted?
|
252
|
+
fail DatastaxRails::RecordNotSaved, 'You cannot call create unless the parent is saved'
|
274
253
|
end
|
275
|
-
|
276
|
-
|
277
|
-
|
254
|
+
|
255
|
+
if attributes.is_a?(Array)
|
256
|
+
attributes.map { |attr| create_record(attr, options, raise, &block) }
|
257
|
+
else
|
258
|
+
add_to_target(build_record(attributes, options)) do |record|
|
259
|
+
yield(record) if block_given?
|
260
|
+
insert_record(record, true, raise)
|
261
|
+
end
|
278
262
|
end
|
263
|
+
end
|
279
264
|
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
265
|
+
# Do the relevant stuff to insert the given record into the association collection.
|
266
|
+
def insert_record(_record, _validate = true, _raise = false)
|
267
|
+
fail NotImplementedError
|
268
|
+
end
|
284
269
|
|
285
|
-
|
270
|
+
def create_scope
|
271
|
+
scoped.scope_for_create.stringify_keys
|
272
|
+
end
|
286
273
|
|
287
|
-
|
288
|
-
|
274
|
+
def delete_or_destroy(records, method)
|
275
|
+
records = records.flatten
|
276
|
+
records.each { |record| raise_on_type_mismatch(record) }
|
277
|
+
existing_records = records.reject { |r| r.new_record? }
|
289
278
|
|
290
|
-
|
291
|
-
end
|
292
|
-
|
293
|
-
# Delete the given records from the association, using one of the methods :destroy,
|
294
|
-
# :delete_all or :nullify (or nil, in which case a default is used).
|
295
|
-
def delete_records(records, method)
|
296
|
-
raise NotImplementedError
|
297
|
-
end
|
279
|
+
records.each { |record| callback(:before_remove, record) }
|
298
280
|
|
299
|
-
|
300
|
-
|
301
|
-
case callback
|
302
|
-
when Symbol
|
303
|
-
owner.send(callback, record)
|
304
|
-
when Proc
|
305
|
-
callback.call(owner, record)
|
306
|
-
else
|
307
|
-
callback.send(method, owner, record)
|
308
|
-
end
|
309
|
-
end
|
310
|
-
end
|
281
|
+
delete_records(existing_records, method) if existing_records.any?
|
282
|
+
records.each { |record| target.delete(record) }
|
311
283
|
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
284
|
+
records.each { |record| callback(:after_remove, record) }
|
285
|
+
end
|
286
|
+
|
287
|
+
# Delete the given records from the association, using one of the methods :destroy,
|
288
|
+
# :delete_all or :nullify (or nil, in which case a default is used).
|
289
|
+
def delete_records(_records, _method)
|
290
|
+
fail NotImplementedError
|
291
|
+
end
|
292
|
+
|
293
|
+
def callback(method, record)
|
294
|
+
callbacks_for(method).each do |callback|
|
295
|
+
case callback
|
296
|
+
when Symbol
|
297
|
+
owner.send(callback, record)
|
298
|
+
when Proc
|
299
|
+
callback.call(owner, record)
|
323
300
|
else
|
324
|
-
|
301
|
+
callback.send(method, owner, record)
|
325
302
|
end
|
326
303
|
end
|
304
|
+
end
|
305
|
+
|
306
|
+
def callbacks_for(callback_name)
|
307
|
+
full_callback_name = "#{callback_name}_for_#{reflection.name}"
|
308
|
+
owner.class.send(full_callback_name.to_sym) || []
|
309
|
+
end
|
310
|
+
|
311
|
+
def include_in_memory?(record)
|
312
|
+
if reflection.is_a?(DatastaxRails::Reflection::ThroughReflection)
|
313
|
+
owner.send(reflection.through_reflection.name).any? do |source|
|
314
|
+
target = source.send(reflection.source_reflection.name)
|
315
|
+
target.respond_to?(:include?) ? target.include?(record) : target == record
|
316
|
+
end || target.include?(record)
|
317
|
+
else
|
318
|
+
target.include?(record)
|
319
|
+
end
|
320
|
+
end
|
327
321
|
end
|
328
322
|
end
|
329
|
-
end
|
323
|
+
end
|