massive_record 0.2.1 → 0.2.2.rc1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|