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,58 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MassiveRecord::ORM::Persistence::Operations::AtomicOperation do
|
4
|
+
include MockMassiveRecordConnection
|
5
|
+
|
6
|
+
let(:record) { Person.new("id-1") }
|
7
|
+
let(:options) { {:operation => :increment, :attr_name => 'age', :by => 1} }
|
8
|
+
|
9
|
+
subject { described_class.new(record, options) }
|
10
|
+
|
11
|
+
it_should_behave_like "a persistence table operation class"
|
12
|
+
|
13
|
+
|
14
|
+
describe "#execute" do
|
15
|
+
it "raises NotNumericalFieldError if field is not numerical" do
|
16
|
+
options[:attr_name] = :name
|
17
|
+
expect { subject.execute }.to raise_error MassiveRecord::ORM::NotNumericalFieldError
|
18
|
+
end
|
19
|
+
|
20
|
+
it "ensures that we have table and column families" do
|
21
|
+
subject.should_receive(:ensure_that_we_have_table_and_column_families!)
|
22
|
+
subject.execute
|
23
|
+
end
|
24
|
+
|
25
|
+
it "ensures that we have binary representation of integer value" do
|
26
|
+
subject.should_receive(:ensure_proper_binary_integer_representation)
|
27
|
+
subject.execute
|
28
|
+
end
|
29
|
+
|
30
|
+
it "asks adapter's row to do the atomic operation" do
|
31
|
+
row = mock(Object)
|
32
|
+
row.should_receive(:atomic_increment).and_return(1)
|
33
|
+
subject.should_receive(:row_for_record).and_return row
|
34
|
+
subject.execute
|
35
|
+
end
|
36
|
+
|
37
|
+
it "assigns the attribute in record with whatever row for record atomic operation returns" do
|
38
|
+
row = mock(Object)
|
39
|
+
row.should_receive(:atomic_increment).and_return(111)
|
40
|
+
subject.should_receive(:row_for_record).and_return row
|
41
|
+
subject.execute
|
42
|
+
record.age.should eq 111
|
43
|
+
end
|
44
|
+
|
45
|
+
it "sets record's @new_record flag to false" do
|
46
|
+
record.instance_variable_set(:@new_record, true)
|
47
|
+
subject.execute
|
48
|
+
record.instance_variable_get(:@new_record).should be_false
|
49
|
+
end
|
50
|
+
|
51
|
+
it "returns the new state of attribute updated" do
|
52
|
+
row = mock(Object)
|
53
|
+
row.should_receive(:atomic_increment).and_return(123)
|
54
|
+
subject.should_receive(:row_for_record).and_return row
|
55
|
+
subject.execute.should eq 123
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MassiveRecord::ORM::Persistence::Operations::Destroy do
|
4
|
+
include MockMassiveRecordConnection
|
5
|
+
|
6
|
+
let(:record) { TestClass.new("id-1") }
|
7
|
+
let(:options) { {:this => 'hash', :has => 'options'} }
|
8
|
+
|
9
|
+
subject { described_class.new(record, options) }
|
10
|
+
|
11
|
+
it_should_behave_like "a persistence table operation class"
|
12
|
+
|
13
|
+
|
14
|
+
describe "#execute" do
|
15
|
+
it "asks row_for_record to destroy itself" do
|
16
|
+
row = mock(Object)
|
17
|
+
row.should_receive(:destroy).and_return true
|
18
|
+
subject.should_receive(:row_for_record).and_return(row)
|
19
|
+
subject.execute
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MassiveRecord::ORM::Persistence::Operations::Embedded::Destroy do
|
4
|
+
include SetUpHbaseConnectionBeforeAll
|
5
|
+
include SetTableNamesToTestTable
|
6
|
+
|
7
|
+
let(:another_address) { Address.new("addresss-id-2", :street => "Asker too", :number => 5) }
|
8
|
+
let(:record) { Address.new("addresss-id", :street => "Asker", :number => 5) }
|
9
|
+
let(:person) { Person.new "person-id", :name => "Thorbjorn", :age => "22" }
|
10
|
+
let(:options) { {:this => 'hash', :has => 'options'} }
|
11
|
+
|
12
|
+
subject { described_class.new(record, options) }
|
13
|
+
|
14
|
+
describe "generic behaviour" do
|
15
|
+
before { record.person = person }
|
16
|
+
it_should_behave_like "a persistence embedded operation class"
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
describe "#execute" do
|
21
|
+
before do
|
22
|
+
record.person = person
|
23
|
+
person.save
|
24
|
+
end
|
25
|
+
|
26
|
+
context "not embedded" do
|
27
|
+
before { record.person = nil }
|
28
|
+
|
29
|
+
it "returns true" do
|
30
|
+
subject.execute.should eq true
|
31
|
+
end
|
32
|
+
|
33
|
+
it "does not call destroy" do
|
34
|
+
subject.execute
|
35
|
+
subject.should_not_receive(:update_embedded)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context "embedded" do
|
40
|
+
context "collection owner new record" do
|
41
|
+
before { record.person = person }
|
42
|
+
|
43
|
+
it "returns true" do
|
44
|
+
subject.execute.should eq true
|
45
|
+
end
|
46
|
+
|
47
|
+
it "does not call destroy" do
|
48
|
+
subject.execute
|
49
|
+
subject.should_not_receive(:update_embedded)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context "collection owner persisted" do
|
54
|
+
before do
|
55
|
+
record.person = person
|
56
|
+
person.save!
|
57
|
+
end
|
58
|
+
|
59
|
+
it "removes record from collection owher" do
|
60
|
+
subject.execute
|
61
|
+
person.addresses.should be_empty
|
62
|
+
end
|
63
|
+
|
64
|
+
it "persists the removal of record from collection owner" do
|
65
|
+
subject.execute
|
66
|
+
person.reload.addresses.should be_empty
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MassiveRecord::ORM::Persistence::Operations::Embedded::Insert do
|
4
|
+
include SetUpHbaseConnectionBeforeAll
|
5
|
+
include SetTableNamesToTestTable
|
6
|
+
|
7
|
+
let(:record) { Address.new("addresss-id", :street => "Asker", :number => 5) }
|
8
|
+
let(:person) { Person.new "person-id", :name => "Thorbjorn", :age => "22" }
|
9
|
+
let(:options) { {:this => 'hash', :has => 'options'} }
|
10
|
+
|
11
|
+
subject { described_class.new(record, options) }
|
12
|
+
|
13
|
+
describe "generic behaviour" do
|
14
|
+
before { record.person = person }
|
15
|
+
it_should_behave_like "a persistence embedded operation class"
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
describe "#execute" do
|
20
|
+
before { record.person = nil }
|
21
|
+
|
22
|
+
context "not embedded" do
|
23
|
+
it "raises an error" do
|
24
|
+
expect { subject.execute }.to raise_error MassiveRecord::ORM::NotAssignedToEmbeddedCollection
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context "embedded" do
|
29
|
+
context "but embedded in is not saved" do
|
30
|
+
before { record.person = person }
|
31
|
+
|
32
|
+
it "calls save on embedded owner when it is a new record" do
|
33
|
+
person.should_receive(:save).and_return true
|
34
|
+
subject.execute
|
35
|
+
end
|
36
|
+
|
37
|
+
it "returns false if none of the embedded_in_proxy_targets returned true" do
|
38
|
+
person.should_receive(:save).and_return false
|
39
|
+
subject.execute.should be_false
|
40
|
+
end
|
41
|
+
|
42
|
+
it "is changed when reloading" do
|
43
|
+
subject.execute
|
44
|
+
Person.find(person.id).addresses.first.should eq record
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context "and embedded in is already saved and now needs to be updated" do
|
49
|
+
# Not gonna get into this situation as far as I can see now.
|
50
|
+
# Reason for it is we are auto-saving when pushing new records
|
51
|
+
# on to an embeds many collection where it's owner has been persisted.
|
52
|
+
# But, it might be something we want to handle in the future if we have
|
53
|
+
# an auto_save option on the relation. In which case I think we should
|
54
|
+
# ensure that only the one embedded record which receives save are actually
|
55
|
+
# updated in the embeds many collection owner's record.
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module MassiveRecord
|
4
|
+
module ORM
|
5
|
+
module Persistence
|
6
|
+
module Operations
|
7
|
+
module Embedded
|
8
|
+
class TestEmbeddedOperationHelpers
|
9
|
+
include Operations, OperationHelpers
|
10
|
+
end
|
11
|
+
|
12
|
+
describe TestEmbeddedOperationHelpers do
|
13
|
+
include SetUpHbaseConnectionBeforeAll
|
14
|
+
include SetTableNamesToTestTable
|
15
|
+
|
16
|
+
let(:address) { Address.new("addresss-id", :street => "Asker", :number => 5) }
|
17
|
+
let(:person) { Person.new "person-id", :name => "Thorbjorn", :age => "22" }
|
18
|
+
let(:options) { {:this => 'hash', :has => 'options'} }
|
19
|
+
|
20
|
+
|
21
|
+
let(:proxy_for_person) { address.send(:relation_proxy, :person) }
|
22
|
+
|
23
|
+
let(:row) do
|
24
|
+
MassiveRecord::Wrapper::Row.new({
|
25
|
+
:id => person.id,
|
26
|
+
:table => person.class.table
|
27
|
+
})
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
subject { TestEmbeddedOperationHelpers.new(address, options) }
|
32
|
+
|
33
|
+
before { address.person = person }
|
34
|
+
|
35
|
+
|
36
|
+
describe "#embedded_in_proxies" do
|
37
|
+
it "returns some proxies" do
|
38
|
+
subject.embedded_in_proxies.should_not be_empty
|
39
|
+
end
|
40
|
+
|
41
|
+
it "returns proxies which represents embedded in relations" do
|
42
|
+
subject.embedded_in_proxies.all? { |p| p.metadata.embedded_in? }.should be_true
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "#embedded_in_proxy_targets" do
|
47
|
+
its(:embedded_in_proxy_targets) { should include person }
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "#row_for_record" do
|
51
|
+
it "returns row for given record" do
|
52
|
+
row = subject.row_for_record(person)
|
53
|
+
row.id.should eq person.id
|
54
|
+
row.table.should eq person.class.table
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
|
60
|
+
describe "update_embedded" do
|
61
|
+
before { subject.stub(:row_for_record).and_return(row) }
|
62
|
+
|
63
|
+
it "ask for record's row" do
|
64
|
+
subject.should_receive(:row_for_record).with(person).and_return(row)
|
65
|
+
subject.update_embedded(proxy_for_person, "new_value")
|
66
|
+
end
|
67
|
+
|
68
|
+
it "sets value on row" do
|
69
|
+
row.should_receive(:values=).with(
|
70
|
+
'addresses' => {
|
71
|
+
address.database_id => "new_value"
|
72
|
+
}
|
73
|
+
)
|
74
|
+
subject.update_embedded(proxy_for_person, "new_value")
|
75
|
+
end
|
76
|
+
|
77
|
+
it "asks row to be saved" do
|
78
|
+
row.should_receive(:save)
|
79
|
+
subject.update_embedded(proxy_for_person, "new_value")
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
|
@@ -0,0 +1,67 @@
|
|
1
|
+
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe MassiveRecord::ORM::Persistence::Operations::Embedded::Reload do
|
5
|
+
include SetUpHbaseConnectionBeforeAll
|
6
|
+
include SetTableNamesToTestTable
|
7
|
+
|
8
|
+
let(:record) { Address.new("addresss-id", :street => "Asker", :number => 5) }
|
9
|
+
let(:person) { Person.new "person-id", :name => "Thorbjorn", :age => "22" }
|
10
|
+
let(:options) { {:this => 'hash', :has => 'options'} }
|
11
|
+
|
12
|
+
subject { described_class.new(record, options) }
|
13
|
+
|
14
|
+
before { record.person = person; record.save! }
|
15
|
+
|
16
|
+
describe "generic behaviour" do
|
17
|
+
it_should_behave_like "a persistence embedded operation class"
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
describe "#execute" do
|
22
|
+
context "new record" do
|
23
|
+
before { record.stub(:persisted?).and_return false }
|
24
|
+
|
25
|
+
its(:execute) { should be_false }
|
26
|
+
end
|
27
|
+
|
28
|
+
context "persisted" do
|
29
|
+
let(:inverse_proxy) { mock(Object, :reload => true, :find => record) }
|
30
|
+
let(:embedded_in_proxy) { subject.embedded_in_proxies.first }
|
31
|
+
|
32
|
+
before do
|
33
|
+
subject.stub(:inverse_proxy_for).and_return(inverse_proxy)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "just returns false if no not embedded in any proxies" do
|
37
|
+
subject.should_receive(:embedded_in_proxies).any_number_of_times.and_return []
|
38
|
+
subject.execute.should be_false
|
39
|
+
end
|
40
|
+
|
41
|
+
it "asks for inverse proxy" do
|
42
|
+
subject.should_receive(:inverse_proxy_for).with(embedded_in_proxy).and_return(inverse_proxy)
|
43
|
+
subject.execute
|
44
|
+
end
|
45
|
+
|
46
|
+
it "reloads inverse proxy" do
|
47
|
+
inverse_proxy.should_receive :reload
|
48
|
+
subject.execute
|
49
|
+
end
|
50
|
+
|
51
|
+
it "finds the record asked to be reloaded" do
|
52
|
+
inverse_proxy.should_receive(:find).with(record.id).and_return record
|
53
|
+
subject.execute
|
54
|
+
end
|
55
|
+
|
56
|
+
it "reinit record with found record's attributes and raw_data" do
|
57
|
+
record.should_receive(:attributes).and_return('attributes' => {})
|
58
|
+
record.should_receive(:raw_data).and_return('raw_data' => {})
|
59
|
+
record.should_receive(:reinit_with).with({
|
60
|
+
'attributes' => {'attributes' => {}},
|
61
|
+
'raw_data' => {'raw_data' => {}}
|
62
|
+
})
|
63
|
+
subject.execute
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MassiveRecord::ORM::Persistence::Operations::Embedded::Update do
|
4
|
+
include SetUpHbaseConnectionBeforeAll
|
5
|
+
include SetTableNamesToTestTable
|
6
|
+
|
7
|
+
let(:another_address) { Address.new("addresss-id-2", :street => "Asker too", :number => 5) }
|
8
|
+
let(:record) { Address.new("addresss-id", :street => "Asker", :number => 5) }
|
9
|
+
let(:person) { Person.new "person-id", :name => "Thorbjorn", :age => "22" }
|
10
|
+
let(:options) { {:this => 'hash', :has => 'options'} }
|
11
|
+
|
12
|
+
subject { described_class.new(record, options) }
|
13
|
+
|
14
|
+
describe "generic behaviour" do
|
15
|
+
before { record.person = person }
|
16
|
+
it_should_behave_like "a persistence embedded operation class"
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
describe "#execute" do
|
21
|
+
before do
|
22
|
+
record.person = person
|
23
|
+
person.save
|
24
|
+
end
|
25
|
+
|
26
|
+
context "not embedded" do
|
27
|
+
it "raises an error" do
|
28
|
+
record.person = nil
|
29
|
+
expect { subject.execute }.to raise_error MassiveRecord::ORM::NotAssignedToEmbeddedCollection
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context "embedded" do
|
34
|
+
it "do persist the changes" do
|
35
|
+
record.street = "Oslogata"
|
36
|
+
subject.execute
|
37
|
+
person.reload.addresses.first.street.should eq "Oslogata"
|
38
|
+
end
|
39
|
+
|
40
|
+
it "does not update other embedded records" do
|
41
|
+
person.addresses << another_address
|
42
|
+
record.street = "Oslogata"
|
43
|
+
another_address.street = "FooBar"
|
44
|
+
|
45
|
+
subject.execute
|
46
|
+
|
47
|
+
person.reload.addresses.find(another_address.id).street.should eq "Asker too"
|
48
|
+
end
|
49
|
+
|
50
|
+
it "does not update attributes on the record it is embedded in" do
|
51
|
+
person.name += "_NEW"
|
52
|
+
record.street = "Oslogata"
|
53
|
+
|
54
|
+
subject.execute
|
55
|
+
|
56
|
+
person.reload.name.should eq "Thorbjorn"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MassiveRecord::ORM::Persistence::Operations::Insert do
|
4
|
+
include MockMassiveRecordConnection
|
5
|
+
|
6
|
+
let(:record) { TestClass.new("id-1") }
|
7
|
+
let(:options) { {:this => 'hash', :has => 'options'} }
|
8
|
+
|
9
|
+
subject { described_class.new(record, options) }
|
10
|
+
|
11
|
+
it_should_behave_like "a persistence table operation class"
|
12
|
+
|
13
|
+
|
14
|
+
describe "#execute" do
|
15
|
+
it "ensures that we have table and column families" do
|
16
|
+
subject.should_receive(:ensure_that_we_have_table_and_column_families!)
|
17
|
+
subject.execute
|
18
|
+
end
|
19
|
+
|
20
|
+
it "raises a RecordNotUnique error if we should check it" do
|
21
|
+
record.class.should_receive(:check_record_uniqueness_on_create).and_return true
|
22
|
+
record.class.should_receive(:exists?).with(record.id).and_return true
|
23
|
+
expect { subject.execute }.to raise_error MassiveRecord::ORM::RecordNotUnique
|
24
|
+
end
|
25
|
+
|
26
|
+
it "calls upon store_record_to_database for help with actually insert job" do
|
27
|
+
subject.should_receive(:store_record_to_database).with('create')
|
28
|
+
subject.execute
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|