massive_record 0.1.0

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 (81) hide show
  1. data/.autotest +15 -0
  2. data/.gitignore +6 -0
  3. data/.rspec +2 -0
  4. data/Gemfile +4 -0
  5. data/Gemfile.lock +38 -0
  6. data/Manifest +24 -0
  7. data/README.md +225 -0
  8. data/Rakefile +16 -0
  9. data/TODO.md +8 -0
  10. data/autotest/discover.rb +1 -0
  11. data/lib/massive_record.rb +18 -0
  12. data/lib/massive_record/exceptions.rb +11 -0
  13. data/lib/massive_record/orm/attribute_methods.rb +61 -0
  14. data/lib/massive_record/orm/attribute_methods/dirty.rb +80 -0
  15. data/lib/massive_record/orm/attribute_methods/read.rb +23 -0
  16. data/lib/massive_record/orm/attribute_methods/write.rb +24 -0
  17. data/lib/massive_record/orm/base.rb +176 -0
  18. data/lib/massive_record/orm/callbacks.rb +52 -0
  19. data/lib/massive_record/orm/column.rb +18 -0
  20. data/lib/massive_record/orm/config.rb +47 -0
  21. data/lib/massive_record/orm/errors.rb +47 -0
  22. data/lib/massive_record/orm/finders.rb +125 -0
  23. data/lib/massive_record/orm/id_factory.rb +133 -0
  24. data/lib/massive_record/orm/persistence.rb +199 -0
  25. data/lib/massive_record/orm/schema.rb +4 -0
  26. data/lib/massive_record/orm/schema/column_families.rb +48 -0
  27. data/lib/massive_record/orm/schema/column_family.rb +102 -0
  28. data/lib/massive_record/orm/schema/column_interface.rb +91 -0
  29. data/lib/massive_record/orm/schema/common_interface.rb +48 -0
  30. data/lib/massive_record/orm/schema/field.rb +128 -0
  31. data/lib/massive_record/orm/schema/fields.rb +37 -0
  32. data/lib/massive_record/orm/schema/table_interface.rb +96 -0
  33. data/lib/massive_record/orm/table.rb +9 -0
  34. data/lib/massive_record/orm/validations.rb +52 -0
  35. data/lib/massive_record/spec/support/simple_database_cleaner.rb +52 -0
  36. data/lib/massive_record/thrift/hbase.rb +2307 -0
  37. data/lib/massive_record/thrift/hbase_constants.rb +14 -0
  38. data/lib/massive_record/thrift/hbase_types.rb +225 -0
  39. data/lib/massive_record/version.rb +3 -0
  40. data/lib/massive_record/wrapper/base.rb +28 -0
  41. data/lib/massive_record/wrapper/cell.rb +45 -0
  42. data/lib/massive_record/wrapper/column_families_collection.rb +19 -0
  43. data/lib/massive_record/wrapper/column_family.rb +22 -0
  44. data/lib/massive_record/wrapper/connection.rb +71 -0
  45. data/lib/massive_record/wrapper/row.rb +170 -0
  46. data/lib/massive_record/wrapper/scanner.rb +50 -0
  47. data/lib/massive_record/wrapper/table.rb +148 -0
  48. data/lib/massive_record/wrapper/tables_collection.rb +13 -0
  49. data/massive_record.gemspec +28 -0
  50. data/spec/config.yml.example +4 -0
  51. data/spec/orm/cases/attribute_methods_spec.rb +47 -0
  52. data/spec/orm/cases/auto_generate_id_spec.rb +54 -0
  53. data/spec/orm/cases/base_spec.rb +176 -0
  54. data/spec/orm/cases/callbacks_spec.rb +309 -0
  55. data/spec/orm/cases/column_spec.rb +49 -0
  56. data/spec/orm/cases/config_spec.rb +103 -0
  57. data/spec/orm/cases/dirty_spec.rb +129 -0
  58. data/spec/orm/cases/encoding_spec.rb +49 -0
  59. data/spec/orm/cases/finders_spec.rb +208 -0
  60. data/spec/orm/cases/hbase/connection_spec.rb +13 -0
  61. data/spec/orm/cases/i18n_spec.rb +32 -0
  62. data/spec/orm/cases/id_factory_spec.rb +75 -0
  63. data/spec/orm/cases/persistence_spec.rb +479 -0
  64. data/spec/orm/cases/table_spec.rb +81 -0
  65. data/spec/orm/cases/validation_spec.rb +92 -0
  66. data/spec/orm/models/address.rb +7 -0
  67. data/spec/orm/models/person.rb +15 -0
  68. data/spec/orm/models/test_class.rb +5 -0
  69. data/spec/orm/schema/column_families_spec.rb +186 -0
  70. data/spec/orm/schema/column_family_spec.rb +131 -0
  71. data/spec/orm/schema/column_interface_spec.rb +115 -0
  72. data/spec/orm/schema/field_spec.rb +196 -0
  73. data/spec/orm/schema/fields_spec.rb +126 -0
  74. data/spec/orm/schema/table_interface_spec.rb +171 -0
  75. data/spec/spec_helper.rb +15 -0
  76. data/spec/support/connection_helpers.rb +76 -0
  77. data/spec/support/mock_massive_record_connection.rb +80 -0
  78. data/spec/thrift/cases/encoding_spec.rb +48 -0
  79. data/spec/wrapper/cases/connection_spec.rb +53 -0
  80. data/spec/wrapper/cases/table_spec.rb +231 -0
  81. metadata +228 -0
@@ -0,0 +1,309 @@
1
+ require 'spec_helper'
2
+ require 'orm/models/person'
3
+ require 'orm/models/address'
4
+
5
+ #
6
+ # Some basic tests
7
+ #
8
+ shared_examples_for "Massive Record with callbacks" do
9
+ it "should include ActiveModel::Callbacks" do
10
+ @model.class.should respond_to :define_model_callbacks
11
+ end
12
+
13
+ it "should include ActiveModell::Validations::Callback" do
14
+ @model.class.included_modules.should include(ActiveModel::Validations::Callbacks)
15
+ end
16
+ end
17
+
18
+ {
19
+ "MassiveRecord::Base::Table" => Person,
20
+ "MassiveRecord::Base::Column" => Address
21
+ }.each do |orm_class, inherited_by_test_class|
22
+ describe orm_class do
23
+ before do
24
+ @model = inherited_by_test_class.new
25
+ end
26
+
27
+ it_should_behave_like "Massive Record with callbacks"
28
+ end
29
+ end
30
+
31
+
32
+ #
33
+ # Some real life object tests
34
+ #
35
+ class CallbackDeveloper < MassiveRecord::ORM::Table
36
+ class << self
37
+ def callback_string(callback_method)
38
+ "history << [#{callback_method.to_sym.inspect}, :string]"
39
+ end
40
+
41
+ def callback_proc(callback_method)
42
+ Proc.new { |model| model.history << [callback_method, :proc] }
43
+ end
44
+
45
+ def define_callback_method(callback_method)
46
+ define_method(callback_method) do
47
+ self.history << [callback_method, :method]
48
+ end
49
+ send(callback_method, :"#{callback_method}")
50
+ end
51
+
52
+ def callback_object(callback_method)
53
+ klass = Class.new
54
+ klass.send(:define_method, callback_method) do |model|
55
+ model.history << [callback_method, :object]
56
+ end
57
+ klass.new
58
+ end
59
+ end
60
+
61
+ MassiveRecord::ORM::Callbacks::CALLBACKS.each do |callback_method|
62
+ next if callback_method.to_s =~ /^around_/
63
+ define_callback_method(callback_method)
64
+ send(callback_method, callback_string(callback_method))
65
+ send(callback_method, callback_proc(callback_method))
66
+ send(callback_method, callback_object(callback_method))
67
+ send(callback_method) { |model| model.history << [callback_method, :block] }
68
+ end
69
+
70
+ def history
71
+ @history ||= []
72
+ end
73
+ end
74
+
75
+
76
+ describe "callbacks for" do
77
+ include MockMassiveRecordConnection
78
+
79
+ it "initialize should run in correct order" do
80
+ thorbjorn = CallbackDeveloper.new
81
+ thorbjorn.history.should == [
82
+ [:after_initialize, :method],
83
+ [:after_initialize, :string],
84
+ [:after_initialize, :proc],
85
+ [:after_initialize, :object],
86
+ [:after_initialize, :block]
87
+ ]
88
+ end
89
+
90
+ it "find should run in correct order" do
91
+ thorbjorn = CallbackDeveloper.find(1)
92
+ thorbjorn.history.should == [
93
+ [:after_find, :method],
94
+ [:after_find, :string],
95
+ [:after_find, :proc],
96
+ [:after_find, :object],
97
+ [:after_find, :block],
98
+ [:after_initialize, :method],
99
+ [:after_initialize, :string],
100
+ [:after_initialize, :proc],
101
+ [:after_initialize, :object],
102
+ [:after_initialize, :block]
103
+ ]
104
+ end
105
+
106
+ it "touch should run in correct order" do
107
+ thorbjorn = CallbackDeveloper.find(1)
108
+ thorbjorn.touch
109
+ thorbjorn.history.should == [
110
+ [:after_find, :method],
111
+ [:after_find, :string],
112
+ [:after_find, :proc],
113
+ [:after_find, :object],
114
+ [:after_find, :block],
115
+ [:after_initialize, :method],
116
+ [:after_initialize, :string],
117
+ [:after_initialize, :proc],
118
+ [:after_initialize, :object],
119
+ [:after_initialize, :block],
120
+ [:after_touch, :method],
121
+ [:after_touch, :string],
122
+ [:after_touch, :proc],
123
+ [:after_touch, :object],
124
+ [:after_touch, :block]
125
+ ]
126
+ end
127
+
128
+ it "valid for new record should run in correct order" do
129
+ thorbjorn = CallbackDeveloper.new
130
+ thorbjorn.valid?
131
+ thorbjorn.history.should == [
132
+ [:after_initialize, :method],
133
+ [:after_initialize, :string],
134
+ [:after_initialize, :proc],
135
+ [:after_initialize, :object],
136
+ [:after_initialize, :block],
137
+ [:before_validation, :method],
138
+ [:before_validation, :string],
139
+ [:before_validation, :proc],
140
+ [:before_validation, :object],
141
+ [:before_validation, :block],
142
+ [:after_validation, :method],
143
+ [:after_validation, :string],
144
+ [:after_validation, :proc],
145
+ [:after_validation, :object],
146
+ [:after_validation, :block]
147
+ ]
148
+ end
149
+
150
+ it "valid for exiting record should run in correct order" do
151
+ thorbjorn = CallbackDeveloper.find(1)
152
+ thorbjorn.valid?
153
+ thorbjorn.history.should == [
154
+ [:after_find, :method],
155
+ [:after_find, :string],
156
+ [:after_find, :proc],
157
+ [:after_find, :object],
158
+ [:after_find, :block],
159
+ [:after_initialize, :method],
160
+ [:after_initialize, :string],
161
+ [:after_initialize, :proc],
162
+ [:after_initialize, :object],
163
+ [:after_initialize, :block],
164
+ [:before_validation, :method],
165
+ [:before_validation, :string],
166
+ [:before_validation, :proc],
167
+ [:before_validation, :object],
168
+ [:before_validation, :block],
169
+ [:after_validation, :method],
170
+ [:after_validation, :string],
171
+ [:after_validation, :proc],
172
+ [:after_validation, :object],
173
+ [:after_validation, :block]
174
+ ]
175
+ end
176
+
177
+ it "create should run in correct order" do
178
+ thorbjorn = CallbackDeveloper.create :id => "dummy"
179
+ thorbjorn.history.should == [
180
+ [:after_initialize, :method],
181
+ [:after_initialize, :string],
182
+ [:after_initialize, :proc ],
183
+ [:after_initialize, :object],
184
+ [:after_initialize, :block ],
185
+ [:before_validation, :method],
186
+ [:before_validation, :string],
187
+ [:before_validation, :proc ],
188
+ [:before_validation, :object],
189
+ [:before_validation, :block ],
190
+ [:after_validation, :method],
191
+ [:after_validation, :string],
192
+ [:after_validation, :proc ],
193
+ [:after_validation, :object],
194
+ [:after_validation, :block ],
195
+ [:before_save, :method],
196
+ [:before_save, :string],
197
+ [:before_save, :proc ],
198
+ [:before_save, :object],
199
+ [:before_save, :block ],
200
+ [:before_create, :method],
201
+ [:before_create, :string],
202
+ [:before_create, :proc ],
203
+ [:before_create, :object],
204
+ [:before_create, :block ],
205
+ [:after_create, :method],
206
+ [:after_create, :string],
207
+ [:after_create, :proc ],
208
+ [:after_create, :object],
209
+ [:after_create, :block ],
210
+ [:after_save, :method],
211
+ [:after_save, :string],
212
+ [:after_save, :proc ],
213
+ [:after_save, :object],
214
+ [:after_save, :block ]
215
+ ]
216
+ end
217
+
218
+ it "update should run in correct order" do
219
+ thorbjorn = CallbackDeveloper.find(1)
220
+ thorbjorn.save
221
+ thorbjorn.history.should == [
222
+ [:after_find, :method],
223
+ [:after_find, :string],
224
+ [:after_find, :proc],
225
+ [:after_find, :object],
226
+ [:after_find, :block],
227
+ [:after_initialize, :method],
228
+ [:after_initialize, :string],
229
+ [:after_initialize, :proc ],
230
+ [:after_initialize, :object],
231
+ [:after_initialize, :block ],
232
+ [:before_validation, :method],
233
+ [:before_validation, :string],
234
+ [:before_validation, :proc ],
235
+ [:before_validation, :object],
236
+ [:before_validation, :block ],
237
+ [:after_validation, :method],
238
+ [:after_validation, :string],
239
+ [:after_validation, :proc ],
240
+ [:after_validation, :object],
241
+ [:after_validation, :block ],
242
+ [:before_save, :method],
243
+ [:before_save, :string],
244
+ [:before_save, :proc ],
245
+ [:before_save, :object],
246
+ [:before_save, :block ],
247
+ [:before_update, :method],
248
+ [:before_update, :string],
249
+ [:before_update, :proc ],
250
+ [:before_update, :object],
251
+ [:before_update, :block ],
252
+ [:after_update, :method],
253
+ [:after_update, :string],
254
+ [:after_update, :proc ],
255
+ [:after_update, :object],
256
+ [:after_update, :block ],
257
+ [:after_save, :method],
258
+ [:after_save, :string],
259
+ [:after_save, :proc ],
260
+ [:after_save, :object],
261
+ [:after_save, :block ]
262
+ ]
263
+ end
264
+
265
+ it "destroy should run in correct order" do
266
+ thorbjorn = CallbackDeveloper.find(1)
267
+ thorbjorn.destroy
268
+ thorbjorn.history.should == [
269
+ [:after_find, :method],
270
+ [:after_find, :string],
271
+ [:after_find, :proc],
272
+ [:after_find, :object],
273
+ [:after_find, :block],
274
+ [:after_initialize, :method],
275
+ [:after_initialize, :string],
276
+ [:after_initialize, :proc ],
277
+ [:after_initialize, :object],
278
+ [:after_initialize, :block ],
279
+ [:before_destroy, :method],
280
+ [:before_destroy, :string],
281
+ [:before_destroy, :proc ],
282
+ [:before_destroy, :object],
283
+ [:before_destroy, :block ],
284
+ [:after_destroy, :method],
285
+ [:after_destroy, :string],
286
+ [:after_destroy, :proc ],
287
+ [:after_destroy, :object],
288
+ [:after_destroy, :block ]
289
+ ]
290
+ end
291
+
292
+ it "should not run callbacks for destroy on delete" do
293
+ thorbjorn = CallbackDeveloper.find(1)
294
+ thorbjorn.delete
295
+ thorbjorn.should be_destroyed
296
+ thorbjorn.history.should == [
297
+ [:after_find, :method],
298
+ [:after_find, :string],
299
+ [:after_find, :proc],
300
+ [:after_find, :object],
301
+ [:after_find, :block],
302
+ [:after_initialize, :method],
303
+ [:after_initialize, :string],
304
+ [:after_initialize, :proc ],
305
+ [:after_initialize, :object],
306
+ [:after_initialize, :block ]
307
+ ]
308
+ end
309
+ end
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+ require 'orm/models/address'
3
+
4
+ describe "column classes" do
5
+ before do
6
+ @address = Address.new(:street => "Asker", :number => 5)
7
+ end
8
+
9
+ it "should have known_attribute_names" do
10
+ Address.should have(3).known_attribute_names
11
+ Address.known_attribute_names.should include("street", "number", "nice_place")
12
+ end
13
+
14
+ it "should have default_attributes_from_schema" do
15
+ Address.default_attributes_from_schema["street"].should be_nil
16
+ Address.default_attributes_from_schema["number"].should be_nil
17
+ Address.default_attributes_from_schema["nice_place"].should be_true
18
+ end
19
+
20
+ it "should have attributes_schema" do
21
+ Address.attributes_schema["street"].should be_instance_of MassiveRecord::ORM::Schema::Field
22
+ end
23
+
24
+ it "should have a default value set" do
25
+ @address.nice_place.should be_true
26
+ end
27
+
28
+
29
+ # TODO We might want to remove this when we have implemented
30
+ # associations correctly. Since Columns are contained within
31
+ # tables, calling save should do something on it's owner object.
32
+ describe "not be possible to persist (at least for now...)" do
33
+ %w(first last all exists? destroy_all).each do |method|
34
+ it "should not respond to class method #{method}" do
35
+ Address.should_not respond_to method
36
+ end
37
+ end
38
+
39
+ %w(
40
+ create! create reload save save!
41
+ update_attribute update_attributes update_attributes! touch destroy
42
+ delete increment! atomic_increment! decrement!
43
+ ).each do |method|
44
+ it "should not respond to instance method #{method}" do
45
+ @address.should_not respond_to method
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,103 @@
1
+ require 'spec_helper'
2
+ require 'orm/models/test_class'
3
+ require 'orm/models/person'
4
+
5
+ describe "configuration" do
6
+ include MockMassiveRecordConnection
7
+
8
+ before do
9
+ @mock_connection = mock(MassiveRecord::Wrapper::Connection, :open => true)
10
+ MassiveRecord::Wrapper::Connection.stub(:new).and_return(@mock_connection)
11
+ end
12
+
13
+ describe "connection" do
14
+ it "should use connection_configuration if present" do
15
+ TestClass.reset_connection!
16
+ MassiveRecord::Wrapper::Connection.should_receive(:new).with(TestClass.connection_configuration)
17
+ TestClass.connection
18
+ end
19
+
20
+ it "should not ask Wrapper::Base for a connection when Rails is not defined" do
21
+ MassiveRecord::Wrapper::Base.should_not_receive(:connection)
22
+ TestClass.connection
23
+ end
24
+
25
+ it "should use the same connection if asked twice" do
26
+ TestClass.connection_configuration = {:host => "foo", :port => 9001}
27
+ MassiveRecord::Wrapper::Connection.should_receive(:new).once.and_return(@mock_connection)
28
+ 2.times { TestClass.connection }
29
+ end
30
+
31
+ it "should use the same connection for different sub classes" do
32
+ TestClass.connection_configuration = {:host => "foo", :port => 9001}
33
+ MassiveRecord::Wrapper::Connection.should_receive(:new).and_return(@mock_connection)
34
+ TestClass.connection.should == Person.connection
35
+ end
36
+
37
+ it "should raise an error if connection configuration is missing" do
38
+ TestClass.connection_configuration = {}
39
+ lambda { TestClass.connection }.should raise_error MassiveRecord::ORM::ConnectionConfigurationMissing
40
+ end
41
+
42
+ it "should return an opened connection" do
43
+ @mock_connection = mock(MassiveRecord::Wrapper::Connection)
44
+ @mock_connection.should_receive(:open)
45
+ MassiveRecord::Wrapper::Connection.should_receive(:new).and_return(@mock_connection)
46
+
47
+ TestClass.connection
48
+ end
49
+
50
+
51
+ describe "under Rails" do
52
+ before do
53
+ TestClass.connection_configuration = {}
54
+ module Rails; end
55
+ MassiveRecord::Wrapper::Base.stub!(:connection).and_return(@mock_connection)
56
+ end
57
+
58
+ after do
59
+ Object.send(:remove_const, :Rails)
60
+ end
61
+
62
+ it "should simply call Wrapper::Base" do
63
+ MassiveRecord::Wrapper::Base.should_receive(:connection).and_return(@mock_connection)
64
+ TestClass.connection.should == @mock_connection
65
+ end
66
+
67
+ it "should use connection_configuration if defined" do
68
+ TestClass.connection_configuration = {:host => "foo", :port => 9001}
69
+ MassiveRecord::Wrapper::Connection.should_receive(:new).with(TestClass.connection_configuration)
70
+ TestClass.connection
71
+ end
72
+ end
73
+ end
74
+
75
+
76
+
77
+ describe "table" do
78
+ it "should create a new wrapper table instance" do
79
+ table_name = "TestClasss"
80
+ connection = "dummy_connection"
81
+
82
+ TestClass.should_receive(:table_name).and_return(table_name)
83
+ TestClass.should_receive(:connection).and_return(connection)
84
+ MassiveRecord::Wrapper::Table.should_receive(:new).with(connection, table_name)
85
+
86
+ TestClass.table
87
+ end
88
+
89
+ it "should not reinitialize the same table twice" do
90
+ MassiveRecord::Wrapper::Table.should_receive(:new).twice
91
+ 2.times { TestClass.table }
92
+ 2.times { Person.table }
93
+ end
94
+
95
+ it "should not return the same table for two different sub classes" do
96
+ TestClass.table.should_not == Person.table
97
+ end
98
+
99
+ it "should use the same conncetion for two tables" do
100
+ TestClass.table.connection.should == Person.table.connection
101
+ end
102
+ end
103
+ end