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.
Files changed (135) hide show
  1. data/CHANGELOG.md +58 -2
  2. data/Gemfile.lock +17 -17
  3. data/README.md +98 -41
  4. data/lib/massive_record.rb +2 -1
  5. data/lib/massive_record/adapters/thrift/hbase/hbase.rb +2425 -2154
  6. data/lib/massive_record/adapters/thrift/hbase/hbase_constants.rb +3 -3
  7. data/lib/massive_record/adapters/thrift/hbase/hbase_types.rb +195 -195
  8. data/lib/massive_record/adapters/thrift/row.rb +35 -4
  9. data/lib/massive_record/adapters/thrift/table.rb +49 -12
  10. data/lib/massive_record/orm/attribute_methods.rb +77 -5
  11. data/lib/massive_record/orm/attribute_methods/cast_numbers_on_write.rb +24 -0
  12. data/lib/massive_record/orm/attribute_methods/dirty.rb +18 -0
  13. data/lib/massive_record/orm/attribute_methods/time_zone_conversion.rb +24 -3
  14. data/lib/massive_record/orm/attribute_methods/write.rb +8 -1
  15. data/lib/massive_record/orm/base.rb +62 -8
  16. data/lib/massive_record/orm/column.rb +7 -11
  17. data/lib/massive_record/orm/default_id.rb +1 -1
  18. data/lib/massive_record/orm/embedded.rb +66 -0
  19. data/lib/massive_record/orm/errors.rb +17 -0
  20. data/lib/massive_record/orm/finders.rb +124 -71
  21. data/lib/massive_record/orm/finders/rescue_missing_table_on_find.rb +1 -1
  22. data/lib/massive_record/orm/finders/scope.rb +58 -34
  23. data/lib/massive_record/orm/id_factory.rb +22 -105
  24. data/lib/massive_record/orm/id_factory/atomic_incrementation.rb +117 -0
  25. data/lib/massive_record/orm/id_factory/timestamp.rb +60 -0
  26. data/lib/massive_record/orm/identity_map.rb +256 -0
  27. data/lib/massive_record/orm/log_subscriber.rb +18 -0
  28. data/lib/massive_record/orm/observer.rb +69 -0
  29. data/lib/massive_record/orm/persistence.rb +47 -119
  30. data/lib/massive_record/orm/persistence/operations.rb +100 -0
  31. data/lib/massive_record/orm/persistence/operations/atomic_operation.rb +71 -0
  32. data/lib/massive_record/orm/persistence/operations/destroy.rb +17 -0
  33. data/lib/massive_record/orm/persistence/operations/embedded/destroy.rb +26 -0
  34. data/lib/massive_record/orm/persistence/operations/embedded/insert.rb +27 -0
  35. data/lib/massive_record/orm/persistence/operations/embedded/operation_helpers.rb +66 -0
  36. data/lib/massive_record/orm/persistence/operations/embedded/reload.rb +39 -0
  37. data/lib/massive_record/orm/persistence/operations/embedded/update.rb +29 -0
  38. data/lib/massive_record/orm/persistence/operations/insert.rb +19 -0
  39. data/lib/massive_record/orm/persistence/operations/reload.rb +26 -0
  40. data/lib/massive_record/orm/persistence/operations/suppress.rb +15 -0
  41. data/lib/massive_record/orm/persistence/operations/table_operation_helpers.rb +106 -0
  42. data/lib/massive_record/orm/persistence/operations/update.rb +25 -0
  43. data/lib/massive_record/orm/query_instrumentation.rb +26 -49
  44. data/lib/massive_record/orm/raw_data.rb +47 -0
  45. data/lib/massive_record/orm/relations.rb +4 -0
  46. data/lib/massive_record/orm/relations/interface.rb +134 -0
  47. data/lib/massive_record/orm/relations/metadata.rb +58 -12
  48. data/lib/massive_record/orm/relations/proxy.rb +17 -12
  49. data/lib/massive_record/orm/relations/proxy/embedded_in.rb +54 -0
  50. data/lib/massive_record/orm/relations/proxy/embedded_in_polymorphic.rb +15 -0
  51. data/lib/massive_record/orm/relations/proxy/embeds_many.rb +215 -0
  52. data/lib/massive_record/orm/relations/proxy/references_many.rb +112 -88
  53. data/lib/massive_record/orm/relations/proxy/references_one.rb +1 -1
  54. data/lib/massive_record/orm/relations/proxy/references_one_polymorphic.rb +1 -1
  55. data/lib/massive_record/orm/relations/proxy_collection.rb +84 -0
  56. data/lib/massive_record/orm/schema/column_family.rb +3 -2
  57. data/lib/massive_record/orm/schema/{column_interface.rb → embedded_interface.rb} +38 -4
  58. data/lib/massive_record/orm/schema/field.rb +2 -0
  59. data/lib/massive_record/orm/schema/table_interface.rb +19 -2
  60. data/lib/massive_record/orm/single_table_inheritance.rb +37 -2
  61. data/lib/massive_record/orm/timestamps.rb +17 -7
  62. data/lib/massive_record/orm/validations.rb +4 -0
  63. data/lib/massive_record/orm/validations/associated.rb +50 -0
  64. data/lib/massive_record/rails/railtie.rb +31 -0
  65. data/lib/massive_record/version.rb +1 -1
  66. data/lib/massive_record/wrapper/cell.rb +8 -1
  67. data/massive_record.gemspec +4 -4
  68. data/spec/adapter/thrift/atomic_increment_spec.rb +16 -0
  69. data/spec/adapter/thrift/table_find_spec.rb +14 -2
  70. data/spec/adapter/thrift/table_spec.rb +6 -6
  71. data/spec/adapter/thrift/utf8_encoding_of_id_spec.rb +71 -0
  72. data/spec/orm/cases/attribute_methods_spec.rb +215 -22
  73. data/spec/orm/cases/auto_generate_id_spec.rb +1 -1
  74. data/spec/orm/cases/change_id_spec.rb +62 -0
  75. data/spec/orm/cases/default_id_spec.rb +25 -6
  76. data/spec/orm/cases/default_values_spec.rb +6 -3
  77. data/spec/orm/cases/dirty_spec.rb +150 -102
  78. data/spec/orm/cases/embedded_spec.rb +250 -0
  79. data/spec/orm/cases/{finder_default_scope.rb → finder_default_scope_spec.rb} +4 -0
  80. data/spec/orm/cases/finder_scope_spec.rb +96 -29
  81. data/spec/orm/cases/finders_spec.rb +57 -10
  82. data/spec/orm/cases/id_factory/atomic_incrementation_spec.rb +72 -0
  83. data/spec/orm/cases/id_factory/timestamp_spec.rb +61 -0
  84. data/spec/orm/cases/identity_map/identity_map_spec.rb +357 -0
  85. data/spec/orm/cases/identity_map/middleware_spec.rb +74 -0
  86. data/spec/orm/cases/log_subscriber_spec.rb +15 -2
  87. data/spec/orm/cases/observing_spec.rb +61 -0
  88. data/spec/orm/cases/persistence_spec.rb +151 -60
  89. data/spec/orm/cases/raw_data_spec.rb +58 -0
  90. data/spec/orm/cases/single_table_inheritance_spec.rb +58 -2
  91. data/spec/orm/cases/table_spec.rb +3 -3
  92. data/spec/orm/cases/time_zone_awareness_spec.rb +27 -0
  93. data/spec/orm/cases/timestamps_spec.rb +23 -109
  94. data/spec/orm/cases/validation_spec.rb +9 -0
  95. data/spec/orm/models/address.rb +5 -1
  96. data/spec/orm/models/address_with_timestamp.rb +12 -0
  97. data/spec/orm/models/car.rb +5 -0
  98. data/spec/orm/models/person.rb +13 -1
  99. data/spec/orm/models/person_with_timestamp.rb +4 -2
  100. data/spec/orm/models/test_class.rb +1 -0
  101. data/spec/orm/persistence/operations/atomic_operation_spec.rb +58 -0
  102. data/spec/orm/persistence/operations/destroy_spec.rb +22 -0
  103. data/spec/orm/persistence/operations/embedded/destroy_spec.rb +71 -0
  104. data/spec/orm/persistence/operations/embedded/insert_spec.rb +59 -0
  105. data/spec/orm/persistence/operations/embedded/operation_helpers_spec.rb +92 -0
  106. data/spec/orm/persistence/operations/embedded/reload_spec.rb +67 -0
  107. data/spec/orm/persistence/operations/embedded/update_spec.rb +60 -0
  108. data/spec/orm/persistence/operations/insert_spec.rb +31 -0
  109. data/spec/orm/persistence/operations/reload_spec.rb +48 -0
  110. data/spec/orm/persistence/operations/suppress_spec.rb +17 -0
  111. data/spec/orm/persistence/operations/table_operation_helpers_spec.rb +98 -0
  112. data/spec/orm/persistence/operations/update_spec.rb +25 -0
  113. data/spec/orm/persistence/operations_spec.rb +58 -0
  114. data/spec/orm/relations/interface_spec.rb +188 -0
  115. data/spec/orm/relations/metadata_spec.rb +92 -15
  116. data/spec/orm/relations/proxy/embedded_in_polymorphic_spec.rb +37 -0
  117. data/spec/orm/relations/proxy/embedded_in_spec.rb +66 -0
  118. data/spec/orm/relations/proxy/embeds_many_spec.rb +651 -0
  119. data/spec/orm/relations/proxy/references_many_spec.rb +466 -2
  120. data/spec/orm/schema/column_family_spec.rb +21 -0
  121. data/spec/orm/schema/embedded_interface_spec.rb +181 -0
  122. data/spec/orm/schema/field_spec.rb +7 -0
  123. data/spec/orm/schema/table_interface_spec.rb +31 -1
  124. data/spec/shared/orm/id_factories.rb +44 -0
  125. data/spec/shared/orm/model_with_timestamps.rb +132 -0
  126. data/spec/shared/orm/persistence/a_persistence_embedded_operation_class.rb +3 -0
  127. data/spec/shared/orm/persistence/a_persistence_operation_class.rb +11 -0
  128. data/spec/shared/orm/persistence/a_persistence_table_operation_class.rb +11 -0
  129. data/spec/shared/orm/relations/proxy.rb +9 -2
  130. data/spec/spec_helper.rb +9 -0
  131. data/spec/support/mock_massive_record_connection.rb +2 -1
  132. metadata +106 -21
  133. data/spec/orm/cases/column_spec.rb +0 -49
  134. data/spec/orm/cases/id_factory_spec.rb +0 -92
  135. data/spec/orm/schema/column_interface_spec.rb +0 -136
@@ -0,0 +1,58 @@
1
+ require 'spec_helper'
2
+
3
+ describe MassiveRecord::ORM::RawData do
4
+ let(:value) { "FooBar!" }
5
+ let(:created_at) { Time.now.to_s }
6
+
7
+ subject { MassiveRecord::ORM::RawData.new(value: value, created_at: created_at) }
8
+
9
+ describe "#initialize" do
10
+ it "assigns value" do
11
+ subject.value.should eq value
12
+ end
13
+
14
+ it "assigns created_at" do
15
+ subject.created_at.should eq created_at
16
+ end
17
+ end
18
+
19
+
20
+ describe ".new_with_data_from" do
21
+ describe "thrift cell" do
22
+ let(:cell) { MassiveRecord::Wrapper::Cell.new(value: value, created_at: created_at) }
23
+
24
+ subject { described_class.new_with_data_from(cell) }
25
+
26
+ it "assigns value" do
27
+ subject.value.should eq value
28
+ end
29
+
30
+ it "assigns created_at" do
31
+ subject.created_at.should eq created_at
32
+ end
33
+ end
34
+ end
35
+
36
+
37
+ describe "#to_s" do
38
+ it "represents itself with it's value" do
39
+ subject.to_s.should eq value
40
+ end
41
+ end
42
+
43
+ describe "#inspect" do
44
+ it "represents itself with it's value" do
45
+ subject.to_s.should eq value
46
+ end
47
+ end
48
+
49
+
50
+ describe "equality" do
51
+ it "considered equal if created at and value are the same" do
52
+ cell = described_class.new_with_data_from(
53
+ MassiveRecord::Wrapper::Cell.new(value: value, created_at: created_at)
54
+ )
55
+ cell.should eq subject
56
+ end
57
+ end
58
+ end
@@ -12,15 +12,71 @@ describe "Single table inheritance" do
12
12
 
13
13
  its(:type) { should == klass.to_s }
14
14
 
15
- it "should instantiate correct class when reading from database" do
15
+ it "instantiates correct class when reading from database via super class" do
16
16
  subject.save!
17
17
  Person.find(subject.id).should == subject
18
18
  end
19
19
  end
20
20
  end
21
21
 
22
- it "should not set type if record being saved is base class" do
22
+ it "sets no type when saving base class" do
23
23
  person = Person.new "ID1", :name => "Person1", :email => "one@person.com", :age => 11, :points => 111, :status => true
24
24
  person.type.should be_nil
25
25
  end
26
+
27
+ describe "fetching and restrictions" do
28
+ describe "#first" do
29
+ it "returns record if class found is the look-up class" do
30
+ person = Person.create!("ID1", :name => "Person1", :email => "one@person.com", :age => 11, :points => 111, :status => true)
31
+ Person.first.should eq person
32
+ end
33
+
34
+ it "returns record if class found is subclass of look up class" do
35
+ friend = Friend.create!("ID1", :name => "Person1", :email => "one@person.com", :age => 11, :points => 111, :status => true)
36
+ Person.first.should eq friend
37
+ end
38
+
39
+ it "raises an error if you call first on sub class" do
40
+ expect { Friend.first }.to raise_error MassiveRecord::ORM::SingleTableInheritance::FirstUnsupported
41
+ end
42
+
43
+ it "does not raise error if you call first on base class" do
44
+ Person.first.should eq nil
45
+ end
46
+ end
47
+
48
+ describe "#all" do
49
+ it "returns [] if class found is a super class of look-up class" do
50
+ Person.create!("ID1", :name => "Person1", :email => "one@person.com", :age => 11, :points => 111, :status => true)
51
+ Friend.all.should eq []
52
+ end
53
+
54
+ it "returns record if class found is the look-up class" do
55
+ person = Person.create!("ID1", :name => "Person1", :email => "one@person.com", :age => 11, :points => 111, :status => true)
56
+ Person.all.should eq [person]
57
+ end
58
+
59
+ it "returns record if class found is subclass of look up class" do
60
+ friend = Friend.create!("ID1", :name => "Person1", :email => "one@person.com", :age => 11, :points => 111, :status => true)
61
+ Person.all.should eq [friend]
62
+ end
63
+
64
+ it "returns record if class found is subclass of look up class, when class is not base class" do
65
+ person = Person.create!("ID1", :name => "Person1", :email => "one@person.com", :age => 11, :points => 111, :status => true)
66
+ friend = Friend.create!("ID2", :name => "Person1", :email => "one@person.com", :age => 11, :points => 111, :status => true)
67
+ best_friend = BestFriend.create!("ID3", :name => "Person1", :email => "one@person.com", :age => 11, :points => 111, :status => true)
68
+
69
+ Friend.all.tap do |result|
70
+ result.should include friend, best_friend
71
+ result.should_not include person
72
+ end
73
+ end
74
+ end
75
+
76
+ it "does not check kind of records if class is not STI enabled" do
77
+ record = TestClass.create! :foo => 'wee'
78
+ TestClass.should_not_receive(:ensure_only_class_or_subclass_of_self_are_returned)
79
+ TestClass.first
80
+ end
81
+ end
26
82
  end
@@ -53,7 +53,7 @@ describe "Person which is a table" do
53
53
 
54
54
  it "should keep different column families per sub class" do
55
55
  Person.column_families.collect(&:name).should include "info", "base"
56
- TestClass.column_families.collect(&:name).should == ["test_family"]
56
+ TestClass.column_families.collect(&:name).should include "test_family", "addresses"
57
57
  end
58
58
 
59
59
  it "should have a list of attributes created from the column family 'info'" do
@@ -73,9 +73,9 @@ describe "Person which is a table" do
73
73
  end
74
74
 
75
75
  it "should decode/encode empty hashes correctly" do
76
- @person.addresses = {}
76
+ @person.dictionary = {}
77
77
  @person.save! :validate => false
78
78
  @person.reload
79
- @person.addresses.should be_instance_of Hash
79
+ @person.dictionary.should be_instance_of Hash
80
80
  end
81
81
  end
@@ -153,5 +153,32 @@ describe "Time zone awareness" do
153
153
  cell.value.should eq MassiveRecord::ORM::Base.coder.dump(Time.zone.parse(time_as_string).utc)
154
154
  end
155
155
  end
156
+
157
+ describe "write string representation pf time" do
158
+ it "it writes string in current time zone" do
159
+ in_time_zone tz_us do
160
+ subject.tested_at = time_as_string
161
+ subject.save!
162
+
163
+ subject.reload.tested_at.to_s.should eq Time.zone.parse(time_as_string).to_s
164
+ end
165
+ end
166
+
167
+ it "handles crappy strings" do
168
+ in_time_zone tz_us do
169
+ subject.tested_at = "rubbish"
170
+ subject.tested_at.should be_nil
171
+ end
172
+ end
173
+
174
+ it "write_attribute writes in current time zone" do
175
+ in_time_zone tz_us do
176
+ subject.write_attribute :tested_at, time_as_string
177
+ subject.save!
178
+
179
+ subject.reload.tested_at.to_s.should eq Time.zone.parse(time_as_string).to_s
180
+ end
181
+ end
182
+ end
156
183
  end
157
184
  end
@@ -1,132 +1,46 @@
1
1
  require 'spec_helper'
2
2
  require 'orm/models/person'
3
3
  require 'orm/models/person_with_timestamp'
4
+ require 'orm/models/address'
5
+ require 'orm/models/address_with_timestamp'
4
6
 
5
7
  describe "timestamps" do
6
- include TimeZoneHelper
7
- include CreatePersonBeforeEach
8
+ include SetUpHbaseConnectionBeforeAll
9
+ include SetTableNamesToTestTable
8
10
 
9
- before do
10
- @person = Person.first
11
- end
12
-
13
-
14
- describe "#updated_at" do
15
- it "should have updated at equal to nil on new records" do
16
- Person.new.updated_at.should be_nil
17
- end
18
-
19
- it "should not be possible to set updated at" do
20
- lambda { @person.updated_at = Time.now }.should raise_error MassiveRecord::ORM::CantBeManuallyAssigned
21
- lambda { @person['updated_at'] = Time.now }.should raise_error MassiveRecord::ORM::CantBeManuallyAssigned
22
- lambda { @person.write_attribute(:updated_at, Time.now) }.should raise_error MassiveRecord::ORM::CantBeManuallyAssigned
23
- end
11
+ describe "on table classes" do
12
+ let(:attribute_to_be_changed) { 'name' }
24
13
 
25
- it "should have updated at on a persisted record" do
26
- @person.updated_at.should be_a_kind_of Time
27
- end
14
+ describe PersonWithTimestamp do
15
+ subject { PersonWithTimestamp.create!(:name => "John Doe", :email => "john@base.com", :age => "20") }
28
16
 
29
- it "should be included in the list of known_attribute_names_for_inspect" do
30
- @person.send(:known_attribute_names_for_inspect).should include 'updated_at'
17
+ it_should_behave_like "a model with timestamps"
31
18
  end
32
19
 
33
- it "should include updated_at in inspect" do
34
- @person.inspect.should include(%q{updated_at:})
35
- end
36
-
37
- it "should be updated after a save" do
38
- sleep(1)
39
-
40
- updated_at_was = @person.updated_at
41
- @person.update_attribute :name, "Should Give Me New Updated At"
20
+ describe Person do
21
+ subject { Person.create!(:name => "John Doe", :email => "john@base.com", :age => "20") }
42
22
 
43
- @person.updated_at.should_not == updated_at_was
44
- end
45
-
46
- it "should not be updated after a save which failed" do
47
- sleep(1)
48
-
49
- updated_at_was = @person.updated_at
50
- @person.name = nil
51
-
52
- @person.should_not be_valid
53
-
54
- @person.updated_at.should == updated_at_was
55
- end
56
-
57
- context "with time zone awarenesswith zone enabled" do
58
- it "should return time with zone" do
59
- in_time_zone "Europe/Stockholm" do
60
- @person.updated_at.should be_instance_of ActiveSupport::TimeWithZone
61
- end
62
- end
63
-
64
- it "should be nil on new records" do
65
- in_time_zone "Europe/Stockholm" do
66
- Person.new.updated_at.should be_nil
67
- end
68
- end
23
+ it_should_behave_like "a model without timestamps"
69
24
  end
70
25
  end
71
26
 
72
- describe "#created_at" do
73
- before do
74
- @person_with_timestamp = PersonWithTimestamp.create! :name => "John Doe", :email => "john@base.com", :age => "20"
75
- end
76
-
77
- it "should have created at" do
78
- @person_with_timestamp.should be_set_created_at_on_create
79
- end
80
-
81
- it "should not have created at on create if model does not have created at" do
82
- @person.should_not be_set_created_at_on_create
83
- end
84
-
85
- it "should have updated at equal to nil on new records" do
86
- PersonWithTimestamp.new.created_at.should be_nil
87
- end
88
27
 
89
- it "should not be possible to set updated at" do
90
- lambda { @person_with_timestamp.created_at = Time.now }.should raise_error MassiveRecord::ORM::CantBeManuallyAssigned
91
- lambda { @person_with_timestamp['created_at'] = Time.now }.should raise_error MassiveRecord::ORM::CantBeManuallyAssigned
92
- lambda { @person_with_timestamp.write_attribute(:created_at, Time.now) }.should raise_error MassiveRecord::ORM::CantBeManuallyAssigned
93
- end
28
+ describe "on embedded classes" do
29
+ let(:attribute_to_be_changed) { 'street' }
30
+ let(:person) { Person.create!(:name => "John Doe", :email => "john@base.com", :age => "20") }
94
31
 
95
- it "should not raise cant-set-error if object has no timestamps" do
96
- lambda { @person.created_at = Time.now }.should_not raise_error MassiveRecord::ORM::CantBeManuallyAssigned
97
- end
32
+ describe AddressWithTimestamp do
33
+ subject { AddressWithTimestamp.new "id1", :street => "Karl Johans gate 13" }
34
+ before { person.addresses_with_timestamp << subject; subject }
98
35
 
99
- it "should have created_at on a persisted record" do
100
- @person_with_timestamp.created_at.should be_a_kind_of Time
36
+ it_should_behave_like "a model with timestamps"
101
37
  end
102
38
 
103
- it "should not alter created at on update" do
104
- created_at_was = @person_with_timestamp.created_at
105
-
106
- sleep(1)
107
-
108
- @person_with_timestamp.update_attribute :name, @person_with_timestamp.name + "NEW"
109
- @person_with_timestamp.created_at.should == created_at_was
110
- end
111
-
112
- it "should be included in the list of known_attribute_names_for_inspect" do
113
- @person_with_timestamp.send(:known_attribute_names_for_inspect).should include 'created_at'
114
- end
115
-
116
- it "should include created_at in inspect" do
117
- @person_with_timestamp.inspect.should include(%q{created_at:})
118
- end
119
-
120
- it "should not include created_at if object does not have it" do
121
- @person.send(:known_attribute_names_for_inspect).should_not include 'created_at'
122
- end
123
-
124
- it "should raise error if created_at is not time" do
125
- PersonWithTimestamp.attributes_schema['created_at'].type = :string
126
-
127
- lambda { PersonWithTimestamp.create! }.should raise_error "created_at must be of type time"
39
+ describe Address do
40
+ subject { Address.new "id1", :street => "Karl Johans gate 13" }
41
+ before { person.addresses << subject; subject }
128
42
 
129
- PersonWithTimestamp.attributes_schema['created_at'].type = :time
43
+ it_should_behave_like "a model without timestamps"
130
44
  end
131
45
  end
132
46
  end
@@ -58,6 +58,15 @@ shared_examples_for "validateable massive record model" do
58
58
  @model.class.stub(:new).and_return(@model)
59
59
  lambda { @model.class.create! }.should raise_error MassiveRecord::ORM::RecordInvalid
60
60
  end
61
+
62
+ describe ":on option" do
63
+ before { @model.consider_carma = true }
64
+
65
+ it "takes :on => create into consideration" do
66
+ @model.should_not be_valid
67
+ @model.errors[:carma].length.should eq 1
68
+ end
69
+ end
61
70
  end
62
71
  end
63
72
 
@@ -1,7 +1,11 @@
1
- class Address < MassiveRecord::ORM::Column
1
+ class Address < MassiveRecord::ORM::Embedded
2
+ embedded_in :person
3
+ embedded_in :addressable, :inverse_of => :addresses, :polymorphic => true
4
+
2
5
  field :street
3
6
  field :number, :integer
4
7
  field :nice_place, :boolean, :default => true
8
+ field :zip, :column => :postal_code
5
9
 
6
10
  validates_presence_of :street
7
11
  end
@@ -0,0 +1,12 @@
1
+ class AddressWithTimestamp < MassiveRecord::ORM::Embedded
2
+ embedded_in :person, :inverse_of => :addresses_with_timestamp
3
+ embedded_in :addressable, :inverse_of => :addresses, :polymorphic => true
4
+
5
+ field :street
6
+ field :number, :integer
7
+ field :nice_place, :boolean, :default => true
8
+ field :zip, :column => :postal_code
9
+ timestamps
10
+
11
+ validates_presence_of :street
12
+ end
@@ -0,0 +1,5 @@
1
+ class Car < MassiveRecord::ORM::Embedded
2
+ embedded_in :person
3
+
4
+ field :color
5
+ end
@@ -3,14 +3,17 @@ class Person < MassiveRecord::ORM::Table
3
3
  field :name
4
4
  field :email
5
5
  field :age, :integer
6
+ field :carma, :float
6
7
  field :date_of_birth, :date
7
- field :addresses, :hash, :default => {}
8
+ field :last_signed_in_at, :time
9
+ field :dictionary, :hash, :default => {}
8
10
  field :type
9
11
  end
10
12
 
11
13
  column_family :base do
12
14
  field :points, :integer, :default => 1, :column => :pts
13
15
  field :status, :boolean, :default => false
16
+ field :positive_as_default, :boolean, :default => true, :allow_nil => false
14
17
  field :phone_numbers, :array, :allow_nil => false
15
18
  end
16
19
 
@@ -19,10 +22,19 @@ class Person < MassiveRecord::ORM::Table
19
22
  references_many :test_classes, :store_in => :info
20
23
  references_many :friends, :class_name => "Person", :records_starts_from => :friends_records_starts_from_id
21
24
 
25
+ embeds_many :addresses
26
+ embeds_many :addresses_with_timestamp, :class_name => "AddressWithTimestamp"
27
+ embeds_many :cars, :store_in => :info
28
+
22
29
  validates_presence_of :name, :age
23
30
  validates_numericality_of :age, :greater_than_or_equal_to => 0
24
31
  validates_format_of :email, :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i, :allow_blank => true
25
32
 
33
+ validates :carma, :presence => true, :if => :consider_carma?, :on => :create
34
+
35
+ attr_accessor :consider_carma
36
+ alias :consider_carma? :consider_carma
37
+
26
38
 
27
39
  def friends_records_starts_from_id
28
40
  id+'-'
@@ -6,11 +6,13 @@ class PersonWithTimestamp < MassiveRecord::ORM::Table
6
6
  field :points, :integer, :default => 1, :column => :pts
7
7
  field :date_of_birth, :date
8
8
  field :status, :boolean, :default => false
9
- field :addresses, :hash, :default => {}
9
+ field :dictionary, :hash, :default => {}
10
10
 
11
- field :created_at, :time
11
+ timestamps
12
12
  end
13
13
 
14
+ validates_presence_of :name
15
+
14
16
  private
15
17
 
16
18
  def default_id