massive_record 0.2.1 → 0.2.2.rc1
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.
- data/CHANGELOG.md +58 -2
- data/Gemfile.lock +17 -17
- data/README.md +98 -41
- data/lib/massive_record.rb +2 -1
- data/lib/massive_record/adapters/thrift/hbase/hbase.rb +2425 -2154
- data/lib/massive_record/adapters/thrift/hbase/hbase_constants.rb +3 -3
- data/lib/massive_record/adapters/thrift/hbase/hbase_types.rb +195 -195
- data/lib/massive_record/adapters/thrift/row.rb +35 -4
- data/lib/massive_record/adapters/thrift/table.rb +49 -12
- data/lib/massive_record/orm/attribute_methods.rb +77 -5
- data/lib/massive_record/orm/attribute_methods/cast_numbers_on_write.rb +24 -0
- data/lib/massive_record/orm/attribute_methods/dirty.rb +18 -0
- data/lib/massive_record/orm/attribute_methods/time_zone_conversion.rb +24 -3
- data/lib/massive_record/orm/attribute_methods/write.rb +8 -1
- data/lib/massive_record/orm/base.rb +62 -8
- data/lib/massive_record/orm/column.rb +7 -11
- data/lib/massive_record/orm/default_id.rb +1 -1
- data/lib/massive_record/orm/embedded.rb +66 -0
- data/lib/massive_record/orm/errors.rb +17 -0
- data/lib/massive_record/orm/finders.rb +124 -71
- data/lib/massive_record/orm/finders/rescue_missing_table_on_find.rb +1 -1
- data/lib/massive_record/orm/finders/scope.rb +58 -34
- data/lib/massive_record/orm/id_factory.rb +22 -105
- data/lib/massive_record/orm/id_factory/atomic_incrementation.rb +117 -0
- data/lib/massive_record/orm/id_factory/timestamp.rb +60 -0
- data/lib/massive_record/orm/identity_map.rb +256 -0
- data/lib/massive_record/orm/log_subscriber.rb +18 -0
- data/lib/massive_record/orm/observer.rb +69 -0
- data/lib/massive_record/orm/persistence.rb +47 -119
- data/lib/massive_record/orm/persistence/operations.rb +100 -0
- data/lib/massive_record/orm/persistence/operations/atomic_operation.rb +71 -0
- data/lib/massive_record/orm/persistence/operations/destroy.rb +17 -0
- data/lib/massive_record/orm/persistence/operations/embedded/destroy.rb +26 -0
- data/lib/massive_record/orm/persistence/operations/embedded/insert.rb +27 -0
- data/lib/massive_record/orm/persistence/operations/embedded/operation_helpers.rb +66 -0
- data/lib/massive_record/orm/persistence/operations/embedded/reload.rb +39 -0
- data/lib/massive_record/orm/persistence/operations/embedded/update.rb +29 -0
- data/lib/massive_record/orm/persistence/operations/insert.rb +19 -0
- data/lib/massive_record/orm/persistence/operations/reload.rb +26 -0
- data/lib/massive_record/orm/persistence/operations/suppress.rb +15 -0
- data/lib/massive_record/orm/persistence/operations/table_operation_helpers.rb +106 -0
- data/lib/massive_record/orm/persistence/operations/update.rb +25 -0
- data/lib/massive_record/orm/query_instrumentation.rb +26 -49
- data/lib/massive_record/orm/raw_data.rb +47 -0
- data/lib/massive_record/orm/relations.rb +4 -0
- data/lib/massive_record/orm/relations/interface.rb +134 -0
- data/lib/massive_record/orm/relations/metadata.rb +58 -12
- data/lib/massive_record/orm/relations/proxy.rb +17 -12
- data/lib/massive_record/orm/relations/proxy/embedded_in.rb +54 -0
- data/lib/massive_record/orm/relations/proxy/embedded_in_polymorphic.rb +15 -0
- data/lib/massive_record/orm/relations/proxy/embeds_many.rb +215 -0
- data/lib/massive_record/orm/relations/proxy/references_many.rb +112 -88
- data/lib/massive_record/orm/relations/proxy/references_one.rb +1 -1
- data/lib/massive_record/orm/relations/proxy/references_one_polymorphic.rb +1 -1
- data/lib/massive_record/orm/relations/proxy_collection.rb +84 -0
- data/lib/massive_record/orm/schema/column_family.rb +3 -2
- data/lib/massive_record/orm/schema/{column_interface.rb → embedded_interface.rb} +38 -4
- data/lib/massive_record/orm/schema/field.rb +2 -0
- data/lib/massive_record/orm/schema/table_interface.rb +19 -2
- data/lib/massive_record/orm/single_table_inheritance.rb +37 -2
- data/lib/massive_record/orm/timestamps.rb +17 -7
- data/lib/massive_record/orm/validations.rb +4 -0
- data/lib/massive_record/orm/validations/associated.rb +50 -0
- data/lib/massive_record/rails/railtie.rb +31 -0
- data/lib/massive_record/version.rb +1 -1
- data/lib/massive_record/wrapper/cell.rb +8 -1
- data/massive_record.gemspec +4 -4
- data/spec/adapter/thrift/atomic_increment_spec.rb +16 -0
- data/spec/adapter/thrift/table_find_spec.rb +14 -2
- data/spec/adapter/thrift/table_spec.rb +6 -6
- data/spec/adapter/thrift/utf8_encoding_of_id_spec.rb +71 -0
- data/spec/orm/cases/attribute_methods_spec.rb +215 -22
- data/spec/orm/cases/auto_generate_id_spec.rb +1 -1
- data/spec/orm/cases/change_id_spec.rb +62 -0
- data/spec/orm/cases/default_id_spec.rb +25 -6
- data/spec/orm/cases/default_values_spec.rb +6 -3
- data/spec/orm/cases/dirty_spec.rb +150 -102
- data/spec/orm/cases/embedded_spec.rb +250 -0
- data/spec/orm/cases/{finder_default_scope.rb → finder_default_scope_spec.rb} +4 -0
- data/spec/orm/cases/finder_scope_spec.rb +96 -29
- data/spec/orm/cases/finders_spec.rb +57 -10
- data/spec/orm/cases/id_factory/atomic_incrementation_spec.rb +72 -0
- data/spec/orm/cases/id_factory/timestamp_spec.rb +61 -0
- data/spec/orm/cases/identity_map/identity_map_spec.rb +357 -0
- data/spec/orm/cases/identity_map/middleware_spec.rb +74 -0
- data/spec/orm/cases/log_subscriber_spec.rb +15 -2
- data/spec/orm/cases/observing_spec.rb +61 -0
- data/spec/orm/cases/persistence_spec.rb +151 -60
- data/spec/orm/cases/raw_data_spec.rb +58 -0
- data/spec/orm/cases/single_table_inheritance_spec.rb +58 -2
- data/spec/orm/cases/table_spec.rb +3 -3
- data/spec/orm/cases/time_zone_awareness_spec.rb +27 -0
- data/spec/orm/cases/timestamps_spec.rb +23 -109
- data/spec/orm/cases/validation_spec.rb +9 -0
- data/spec/orm/models/address.rb +5 -1
- data/spec/orm/models/address_with_timestamp.rb +12 -0
- data/spec/orm/models/car.rb +5 -0
- data/spec/orm/models/person.rb +13 -1
- data/spec/orm/models/person_with_timestamp.rb +4 -2
- data/spec/orm/models/test_class.rb +1 -0
- data/spec/orm/persistence/operations/atomic_operation_spec.rb +58 -0
- data/spec/orm/persistence/operations/destroy_spec.rb +22 -0
- data/spec/orm/persistence/operations/embedded/destroy_spec.rb +71 -0
- data/spec/orm/persistence/operations/embedded/insert_spec.rb +59 -0
- data/spec/orm/persistence/operations/embedded/operation_helpers_spec.rb +92 -0
- data/spec/orm/persistence/operations/embedded/reload_spec.rb +67 -0
- data/spec/orm/persistence/operations/embedded/update_spec.rb +60 -0
- data/spec/orm/persistence/operations/insert_spec.rb +31 -0
- data/spec/orm/persistence/operations/reload_spec.rb +48 -0
- data/spec/orm/persistence/operations/suppress_spec.rb +17 -0
- data/spec/orm/persistence/operations/table_operation_helpers_spec.rb +98 -0
- data/spec/orm/persistence/operations/update_spec.rb +25 -0
- data/spec/orm/persistence/operations_spec.rb +58 -0
- data/spec/orm/relations/interface_spec.rb +188 -0
- data/spec/orm/relations/metadata_spec.rb +92 -15
- data/spec/orm/relations/proxy/embedded_in_polymorphic_spec.rb +37 -0
- data/spec/orm/relations/proxy/embedded_in_spec.rb +66 -0
- data/spec/orm/relations/proxy/embeds_many_spec.rb +651 -0
- data/spec/orm/relations/proxy/references_many_spec.rb +466 -2
- data/spec/orm/schema/column_family_spec.rb +21 -0
- data/spec/orm/schema/embedded_interface_spec.rb +181 -0
- data/spec/orm/schema/field_spec.rb +7 -0
- data/spec/orm/schema/table_interface_spec.rb +31 -1
- data/spec/shared/orm/id_factories.rb +44 -0
- data/spec/shared/orm/model_with_timestamps.rb +132 -0
- data/spec/shared/orm/persistence/a_persistence_embedded_operation_class.rb +3 -0
- data/spec/shared/orm/persistence/a_persistence_operation_class.rb +11 -0
- data/spec/shared/orm/persistence/a_persistence_table_operation_class.rb +11 -0
- data/spec/shared/orm/relations/proxy.rb +9 -2
- data/spec/spec_helper.rb +9 -0
- data/spec/support/mock_massive_record_connection.rb +2 -1
- metadata +106 -21
- data/spec/orm/cases/column_spec.rb +0 -49
- data/spec/orm/cases/id_factory_spec.rb +0 -92
- data/spec/orm/schema/column_interface_spec.rb +0 -136
@@ -0,0 +1,215 @@
|
|
1
|
+
module MassiveRecord
|
2
|
+
module ORM
|
3
|
+
module Relations
|
4
|
+
class Proxy
|
5
|
+
class EmbedsMany < ProxyCollection
|
6
|
+
def find(id)
|
7
|
+
record = if loaded? || proxy_owner.new_record?
|
8
|
+
proxy_target.detect { |record| record.id == id }
|
9
|
+
else
|
10
|
+
find_one_embedded_record_from_raw_data(id)
|
11
|
+
end
|
12
|
+
|
13
|
+
record or raise RecordNotFound.new("Could not find #{proxy_target_class.model_name} with id=#{id}")
|
14
|
+
end
|
15
|
+
|
16
|
+
def limit(limit)
|
17
|
+
load_proxy_target.slice(0, limit)
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
#
|
22
|
+
# Adding record(s) to the collection.
|
23
|
+
#
|
24
|
+
def <<(*records)
|
25
|
+
records.flatten.each do |record|
|
26
|
+
unless include? record
|
27
|
+
raise_if_type_mismatch(record)
|
28
|
+
proxy_target << record
|
29
|
+
record.send(metadata.inverse_of).replace(proxy_owner, false)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
if proxy_owner.persisted?
|
34
|
+
proxy_owner.save
|
35
|
+
else
|
36
|
+
proxy_target.sort_by! &:id
|
37
|
+
end
|
38
|
+
|
39
|
+
self
|
40
|
+
end
|
41
|
+
alias_method :push, :<<
|
42
|
+
alias_method :concat, :<<
|
43
|
+
|
44
|
+
|
45
|
+
#
|
46
|
+
# Checks if record is included in collection
|
47
|
+
#
|
48
|
+
def include?(record)
|
49
|
+
load_proxy_target.include? record
|
50
|
+
end
|
51
|
+
|
52
|
+
def length
|
53
|
+
load_proxy_target.length
|
54
|
+
end
|
55
|
+
alias_method :count, :length
|
56
|
+
alias_method :size, :length
|
57
|
+
|
58
|
+
|
59
|
+
|
60
|
+
|
61
|
+
|
62
|
+
#
|
63
|
+
# Returns the raw hash of attributes for embedded objects
|
64
|
+
# It filters away database_ids (keys in a column family)
|
65
|
+
# which it does not recognize.
|
66
|
+
#
|
67
|
+
def proxy_targets_raw # :nodoc:
|
68
|
+
Hash[proxy_owner.raw_data[metadata.store_in].collect do |database_id, value|
|
69
|
+
begin
|
70
|
+
base_class, id = Embedded.parse_database_id(database_id)
|
71
|
+
[id, value] if base_class == proxy_target_class.base_class.to_s.underscore
|
72
|
+
rescue InvalidEmbeddedDatabaseId
|
73
|
+
end
|
74
|
+
end.compact]
|
75
|
+
end
|
76
|
+
|
77
|
+
|
78
|
+
|
79
|
+
|
80
|
+
#
|
81
|
+
# Hook which are called just before save.
|
82
|
+
# It iterates over new or changed records, asking them to "save" themself.
|
83
|
+
# This will result in created_at / updated_at and persistence state being set.
|
84
|
+
# It will also build the proxy_targets_update_hash with these
|
85
|
+
# changes, which will be used at the proxy owner's save for actually updating
|
86
|
+
# these records.
|
87
|
+
#
|
88
|
+
def parent_will_be_saved! # :nodoc:
|
89
|
+
proxy_targets_update_hash.clear
|
90
|
+
|
91
|
+
MassiveRecord::ORM::Persistence::Operations.suppress do
|
92
|
+
proxy_target.each do |record|
|
93
|
+
if record.destroyed?
|
94
|
+
proxy_targets_update_hash[record.database_id] = nil
|
95
|
+
elsif record.new_record? || record.changed?
|
96
|
+
record.save
|
97
|
+
proxy_targets_update_hash[record.database_id] = Base.coder.dump(record.attributes_db_raw_data_hash)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
to_be_destroyed.each do |record|
|
102
|
+
targets_current_owner = record.send(metadata.inverse_of).proxy_target
|
103
|
+
if targets_current_owner.nil? || targets_current_owner == proxy_owner
|
104
|
+
record.destroy
|
105
|
+
proxy_targets_update_hash[record.database_id] = nil
|
106
|
+
end
|
107
|
+
end
|
108
|
+
to_be_destroyed.clear
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# Hook to call when save is done through parent
|
113
|
+
def parent_has_been_saved!
|
114
|
+
reload_raw_data
|
115
|
+
proxy_targets_update_hash.clear
|
116
|
+
end
|
117
|
+
|
118
|
+
def proxy_targets_update_hash
|
119
|
+
@proxy_targets_update_hash ||= {}
|
120
|
+
end
|
121
|
+
|
122
|
+
|
123
|
+
|
124
|
+
|
125
|
+
|
126
|
+
|
127
|
+
|
128
|
+
|
129
|
+
def changed?
|
130
|
+
to_be_destroyed.any? || proxy_target.any? do |record|
|
131
|
+
record.new_record? || record.destroyed? || record.changed?
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def changes
|
136
|
+
Hash[proxy_target.collect do |record|
|
137
|
+
if record.changed?
|
138
|
+
[record.id, record.changes]
|
139
|
+
end
|
140
|
+
end.compact]
|
141
|
+
end
|
142
|
+
|
143
|
+
|
144
|
+
|
145
|
+
|
146
|
+
private
|
147
|
+
|
148
|
+
def find_proxy_target(options = {})
|
149
|
+
reload_raw_data if proxy_targets_raw.empty?
|
150
|
+
|
151
|
+
proxy_targets_raw.inject([]) do |records, (id, raw_data)|
|
152
|
+
records << instantiate_target_class(id, raw_data)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
#
|
157
|
+
# Replaces the raw_data hash in parent with reloaded data from database
|
158
|
+
#
|
159
|
+
def reload_raw_data
|
160
|
+
if proxy_owner.persisted?
|
161
|
+
reloaded_data = proxy_owner.class.select(metadata.store_in).find(proxy_owner.id).raw_data[metadata.store_in]
|
162
|
+
proxy_owner.update_raw_data_for_column_family(metadata.store_in, reloaded_data)
|
163
|
+
end
|
164
|
+
rescue MassiveRecord::ORM::RecordNotFound
|
165
|
+
# When we try to load raw data we might end up getting nil back, even though
|
166
|
+
# a row exists with given id. The reason for this is that when only selecting
|
167
|
+
# one column family (family for embedded records) and that family is empty for
|
168
|
+
# a given row we'll end up getting nil back, resulting in a record not found error.
|
169
|
+
end
|
170
|
+
|
171
|
+
|
172
|
+
def find_one_embedded_record_from_raw_data(id)
|
173
|
+
raw_data = proxy_targets_raw[id] || load_raw_data_for_id(id)
|
174
|
+
instantiate_target_class(id, raw_data) if raw_data
|
175
|
+
end
|
176
|
+
|
177
|
+
def load_raw_data_for_id(id)
|
178
|
+
database_id = Embedded.database_id(proxy_target_class, id)
|
179
|
+
if cell = proxy_owner.class.table.get_cell(proxy_owner.id, metadata.store_in, database_id)
|
180
|
+
RawData.new_with_data_from cell
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
# FIXME Common to all proxies representing multiple values
|
185
|
+
def find_proxy_target_with_proc(options = {}, &block)
|
186
|
+
Array(super).compact
|
187
|
+
end
|
188
|
+
|
189
|
+
def delete_or_destroy(*records, method)
|
190
|
+
records.flatten!
|
191
|
+
self.proxy_target -= records
|
192
|
+
to_be_destroyed.concat(records).uniq!
|
193
|
+
proxy_owner.save if proxy_owner.persisted? && method == :destroy
|
194
|
+
records
|
195
|
+
end
|
196
|
+
|
197
|
+
def can_find_proxy_target?
|
198
|
+
true
|
199
|
+
end
|
200
|
+
|
201
|
+
|
202
|
+
def to_be_destroyed
|
203
|
+
@to_be_destroyed ||= []
|
204
|
+
end
|
205
|
+
|
206
|
+
def instantiate_target_class(id, raw_data)
|
207
|
+
proxy_target_class.send(:instantiate, *proxy_target_class.transpose_raw_data_to_record_attributes_and_raw_data(id, raw_data)).tap do |record|
|
208
|
+
record.send(metadata.inverse_of).replace(proxy_owner, false)
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
@@ -2,41 +2,21 @@ module MassiveRecord
|
|
2
2
|
module ORM
|
3
3
|
module Relations
|
4
4
|
class Proxy
|
5
|
-
class ReferencesMany <
|
6
|
-
|
7
|
-
# Loading proxy_targets will merge it with records found currently in proxy,
|
8
|
-
# to make sure we don't remove any pushed proxy_targets only cause we load the
|
9
|
-
# proxy_targets.
|
10
|
-
#
|
11
|
-
# TODO - Implement methods like:
|
12
|
-
# * find_in_batches
|
13
|
-
# * find_each
|
14
|
-
# * etc :-)
|
5
|
+
class ReferencesMany < ProxyCollection
|
6
|
+
|
15
7
|
#
|
16
|
-
#
|
8
|
+
# Raised when we are in a references many relationship where the
|
9
|
+
# target's foreign keys are persisted in the owner and you try to
|
10
|
+
# do a person.cars.all(:limit => 1, :offset => "something") and
|
11
|
+
# some of these options are unsupported. The reason for these being
|
12
|
+
# unsupported is that we have to implement offset and limitiation
|
13
|
+
# in pure Ruby working on that car_ids array in the person. Its
|
14
|
+
# nothing close to impossible; it just has not been done yet.
|
17
15
|
#
|
18
|
-
|
19
|
-
|
20
|
-
proxy_target_after_load = super
|
21
|
-
|
22
|
-
self.proxy_target = (proxy_target_before_load + proxy_target_after_load).uniq
|
16
|
+
class UnsupportedFinderOption < MassiveRecordError
|
17
|
+
OPTIONS = %w(limit offset starts_with)
|
23
18
|
end
|
24
19
|
|
25
|
-
def reset
|
26
|
-
super
|
27
|
-
@proxy_target = []
|
28
|
-
end
|
29
|
-
|
30
|
-
def replace(*records)
|
31
|
-
records.flatten!
|
32
|
-
|
33
|
-
if records.length == 1 and records.first.nil?
|
34
|
-
reset
|
35
|
-
else
|
36
|
-
delete_all
|
37
|
-
concat(records)
|
38
|
-
end
|
39
|
-
end
|
40
20
|
|
41
21
|
|
42
22
|
#
|
@@ -63,74 +43,49 @@ module MassiveRecord
|
|
63
43
|
alias_method :push, :<<
|
64
44
|
alias_method :concat, :<<
|
65
45
|
|
66
|
-
#
|
67
|
-
# Destroy record(s) from the collection
|
68
|
-
# Each record will be asked to destroy itself as well
|
69
|
-
#
|
70
|
-
def destroy(*records)
|
71
|
-
delete_or_destroy *records, :destroy
|
72
|
-
end
|
73
|
-
|
74
|
-
#
|
75
|
-
# Deletes record(s) from the collection
|
76
|
-
#
|
77
|
-
def delete(*records)
|
78
|
-
delete_or_destroy *records, :delete
|
79
|
-
end
|
80
|
-
|
81
|
-
#
|
82
|
-
# Destroys all records
|
83
|
-
#
|
84
|
-
def destroy_all
|
85
|
-
destroy(load_proxy_target)
|
86
|
-
reset
|
87
|
-
loaded!
|
88
|
-
end
|
89
|
-
|
90
|
-
#
|
91
|
-
# Deletes all records from the relationship.
|
92
|
-
# Does not destroy the records
|
93
|
-
#
|
94
|
-
def delete_all
|
95
|
-
delete(load_proxy_target)
|
96
|
-
reset
|
97
|
-
loaded!
|
98
|
-
end
|
99
46
|
|
100
47
|
#
|
101
48
|
# Checks if record is included in collection
|
102
49
|
#
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
50
|
+
def include?(record_or_id)
|
51
|
+
id = record_or_id.respond_to?(:id) ? record_or_id.id : record_or_id
|
52
|
+
|
53
|
+
if loaded? || find_with_proc?
|
54
|
+
!!find(id)
|
55
|
+
else
|
56
|
+
foreign_key_in_proxy_owner_exists? id
|
57
|
+
end
|
58
|
+
rescue RecordNotFound
|
59
|
+
false
|
109
60
|
end
|
110
61
|
|
111
62
|
#
|
112
63
|
# Returns the length of targes
|
113
64
|
#
|
114
|
-
# TODO This can be smarter as well. For instance; if we have not
|
115
|
-
# loaded targets, and we have foreign keys in the owner we
|
116
|
-
# can simply do a owner's foreign keys and ask for it's length.
|
117
|
-
#
|
118
65
|
def length
|
119
|
-
|
66
|
+
if loaded?
|
67
|
+
proxy_target.length
|
68
|
+
elsif find_with_proc?
|
69
|
+
load_proxy_target.length
|
70
|
+
else
|
71
|
+
foreign_keys_in_proxy_owner.length
|
72
|
+
end
|
120
73
|
end
|
121
74
|
alias_method :count, :length
|
122
75
|
alias_method :size, :length
|
123
76
|
|
124
|
-
def
|
125
|
-
|
77
|
+
def any?
|
78
|
+
if !loaded? && find_with_proc?
|
79
|
+
!!first
|
80
|
+
else
|
81
|
+
!empty?
|
82
|
+
end
|
126
83
|
end
|
84
|
+
alias_method :present?, :any?
|
127
85
|
|
128
|
-
def first
|
129
|
-
limit(1).first
|
130
|
-
end
|
131
86
|
|
132
87
|
def find(id)
|
133
|
-
if loaded?
|
88
|
+
if loaded? || proxy_owner.new_record?
|
134
89
|
record = proxy_target.find { |record| record.id == id }
|
135
90
|
elsif find_with_proc?
|
136
91
|
if id.starts_with? proxy_owner.send(metadata.records_starts_from)
|
@@ -145,6 +100,53 @@ module MassiveRecord
|
|
145
100
|
record
|
146
101
|
end
|
147
102
|
|
103
|
+
def all(options = {})
|
104
|
+
options = MassiveRecord::Adapters::Thrift::Table.warn_and_change_deprecated_finder_options(options)
|
105
|
+
|
106
|
+
load_proxy_target(options)
|
107
|
+
end
|
108
|
+
|
109
|
+
#
|
110
|
+
# Find records in batches, yields batch into your block
|
111
|
+
#
|
112
|
+
# Options:
|
113
|
+
# <tt>:batch_size</tt> The number of records you want per batch. Defaults to 1000
|
114
|
+
# <tt>:starts_with</tt> The ids starts with this
|
115
|
+
#
|
116
|
+
def find_in_batches(options = {}, &block)
|
117
|
+
options = MassiveRecord::Adapters::Thrift::Table.warn_and_change_deprecated_finder_options(options)
|
118
|
+
|
119
|
+
options[:batch_size] ||= 1000
|
120
|
+
|
121
|
+
if loaded?
|
122
|
+
collection = if options[:starts_with]
|
123
|
+
proxy_target.select { |r| r.id.starts_with? options[:starts_with] }
|
124
|
+
else
|
125
|
+
proxy_target
|
126
|
+
end
|
127
|
+
collection.in_groups_of(options[:batch_size], false, &block)
|
128
|
+
elsif find_with_proc?
|
129
|
+
find_proxy_target_with_proc(options.merge(:finder_method => :find_in_batches), &block)
|
130
|
+
else
|
131
|
+
all_ids = proxy_owner.send(metadata.foreign_key)
|
132
|
+
all_ids = all_ids.select { |id| id.starts_with? options[:starts_with] } if options[:starts_with]
|
133
|
+
all_ids.in_groups_of(options[:batch_size]).each do |ids_in_batch|
|
134
|
+
yield Array(find_proxy_target(:ids => ids_in_batch))
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
#
|
140
|
+
# Fetches records in batches of 1000 (by default), iterates over each batch
|
141
|
+
# and yields one and one record in to given block. See find_in_batches for
|
142
|
+
# options.
|
143
|
+
#
|
144
|
+
def find_each(options = {})
|
145
|
+
find_in_batches(options) do |batch|
|
146
|
+
batch.each { |record| yield record }
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
148
150
|
#
|
149
151
|
# Returns a limited result set of target records.
|
150
152
|
#
|
@@ -153,25 +155,31 @@ module MassiveRecord
|
|
153
155
|
# than foreign keys length.
|
154
156
|
#
|
155
157
|
def limit(limit)
|
156
|
-
if loaded?
|
158
|
+
if loaded? || proxy_owner.new_record?
|
157
159
|
proxy_target.slice(0, limit)
|
158
160
|
elsif find_with_proc?
|
159
161
|
find_proxy_target_with_proc(:limit => limit)
|
160
162
|
else
|
161
163
|
ids = proxy_owner.send(metadata.foreign_key).slice(0, limit)
|
162
164
|
ids = ids.first if ids.length == 1
|
163
|
-
|
165
|
+
Array(find_proxy_target(:ids => ids))
|
164
166
|
end
|
165
167
|
end
|
166
168
|
|
167
169
|
|
170
|
+
def is_a?(klass)
|
171
|
+
klass == Array
|
172
|
+
end
|
168
173
|
|
169
174
|
private
|
170
175
|
|
171
176
|
|
172
177
|
def delete_or_destroy(*records, method)
|
178
|
+
removed = []
|
179
|
+
|
173
180
|
records.flatten.each do |record|
|
174
181
|
if include? record
|
182
|
+
removed << record
|
175
183
|
remove_foreign_key_in_proxy_owner(record.id)
|
176
184
|
proxy_target.delete(record)
|
177
185
|
record.destroy if method.to_sym == :destroy
|
@@ -179,17 +187,29 @@ module MassiveRecord
|
|
179
187
|
end
|
180
188
|
|
181
189
|
proxy_owner.save if proxy_owner.persisted?
|
190
|
+
removed
|
182
191
|
end
|
183
192
|
|
184
193
|
|
185
194
|
|
186
|
-
def find_proxy_target(
|
187
|
-
ids = proxy_owner.send(metadata.foreign_key)
|
195
|
+
def find_proxy_target(options = {})
|
196
|
+
ids = options.delete(:ids) || proxy_owner.send(metadata.foreign_key)
|
197
|
+
unsupported_finder_options = UnsupportedFinderOption::OPTIONS & options.keys.collect(&:to_s)
|
198
|
+
|
199
|
+
if unsupported_finder_options.any?
|
200
|
+
raise UnsupportedFinderOption.new(
|
201
|
+
<<-TXT
|
202
|
+
Sorry, option(s): #{unsupported_finder_options.join(', ')} are not supported when foreign
|
203
|
+
keys are persisted in proxy owner #{proxy_owner.class}
|
204
|
+
TXT
|
205
|
+
)
|
206
|
+
end
|
207
|
+
|
188
208
|
proxy_target_class.find(ids, :skip_expected_result_check => true)
|
189
209
|
end
|
190
210
|
|
191
|
-
def find_proxy_target_with_proc(options = {})
|
192
|
-
|
211
|
+
def find_proxy_target_with_proc(options = {}, &block)
|
212
|
+
Array(super).compact
|
193
213
|
end
|
194
214
|
|
195
215
|
def can_find_proxy_target?
|
@@ -215,7 +235,11 @@ module MassiveRecord
|
|
215
235
|
end
|
216
236
|
|
217
237
|
def foreign_key_in_proxy_owner_exists?(id)
|
218
|
-
|
238
|
+
foreign_keys_in_proxy_owner.include? id
|
239
|
+
end
|
240
|
+
|
241
|
+
def foreign_keys_in_proxy_owner
|
242
|
+
proxy_owner.send(metadata.foreign_key)
|
219
243
|
end
|
220
244
|
|
221
245
|
def notify_of_change_in_proxy_owner_foreign_key
|