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
@@ -1,6 +1,10 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe MassiveRecord::ORM::Schema::ColumnFamily do
|
4
|
+
|
5
|
+
let(:families) { MassiveRecord::ORM::Schema::ColumnFamilies.new }
|
6
|
+
subject { MassiveRecord::ORM::Schema::ColumnFamily.new :name => "family_name", :column_families => families }
|
7
|
+
|
4
8
|
describe "initializer" do
|
5
9
|
it "should take a name" do
|
6
10
|
column_family = MassiveRecord::ORM::Schema::ColumnFamily.new :name => "family_name"
|
@@ -128,4 +132,21 @@ describe MassiveRecord::ORM::Schema::ColumnFamily do
|
|
128
132
|
end
|
129
133
|
end
|
130
134
|
end
|
135
|
+
|
136
|
+
describe "#autoload_fields" do
|
137
|
+
it "sets self to be autoloaded" do
|
138
|
+
subject.instance_eval do
|
139
|
+
autoload_fields
|
140
|
+
end
|
141
|
+
subject.should be_autoload_fields
|
142
|
+
end
|
143
|
+
|
144
|
+
it "takes options for created fields when autoloading" do
|
145
|
+
options = {:type => :integer}
|
146
|
+
subject.instance_eval do
|
147
|
+
autoload_fields options
|
148
|
+
end
|
149
|
+
subject.options_for_autoload_created_fields.should eq options
|
150
|
+
end
|
151
|
+
end
|
131
152
|
end
|
@@ -0,0 +1,181 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class TestEmbeddedInterface
|
4
|
+
include MassiveRecord::ORM::Schema::EmbeddedInterface
|
5
|
+
end
|
6
|
+
|
7
|
+
describe MassiveRecord::ORM::Schema::EmbeddedInterface do
|
8
|
+
after do
|
9
|
+
TestEmbeddedInterface.fields = nil
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should respond_to default_attributes_from_schema" do
|
13
|
+
TestEmbeddedInterface.should respond_to :default_attributes_from_schema
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should have fields set to nil if no fields are defined" do
|
17
|
+
TestEmbeddedInterface.fields.should be_nil
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should have one field if one field is added" do
|
21
|
+
class TestEmbeddedInterface
|
22
|
+
field :field_name, :string
|
23
|
+
end
|
24
|
+
|
25
|
+
TestEmbeddedInterface.should have(1).fields
|
26
|
+
TestEmbeddedInterface.fields.first.name.should == "field_name"
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should not be possible to have to fields with the same name" do
|
30
|
+
lambda {
|
31
|
+
class TestEmbeddedInterface
|
32
|
+
field :will_raise_error
|
33
|
+
field :will_raise_error
|
34
|
+
end
|
35
|
+
}.should raise_error MassiveRecord::ORM::Schema::InvalidField
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should return attributes schema based on DSL" do
|
39
|
+
class TestEmbeddedInterface
|
40
|
+
field :name
|
41
|
+
field :age, :integer, :default => 1
|
42
|
+
end
|
43
|
+
|
44
|
+
TestEmbeddedInterface.attributes_schema["name"].type.should == :string
|
45
|
+
TestEmbeddedInterface.attributes_schema["age"].type.should == :integer
|
46
|
+
TestEmbeddedInterface.attributes_schema["age"].default.should == 1
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should make attributes_schema readable from instances" do
|
50
|
+
class TestEmbeddedInterface
|
51
|
+
field :name
|
52
|
+
end
|
53
|
+
|
54
|
+
TestEmbeddedInterface.new.attributes_schema["name"].type.should == :string
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should have a list of known attribute names" do
|
58
|
+
class TestEmbeddedInterface
|
59
|
+
field :name, :string
|
60
|
+
field :age, :integer
|
61
|
+
end
|
62
|
+
|
63
|
+
TestEmbeddedInterface.should have(2).known_attribute_names
|
64
|
+
TestEmbeddedInterface.known_attribute_names.should include("name", "age")
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should make known_attribute_names readable for instances" do
|
68
|
+
class TestEmbeddedInterface
|
69
|
+
field :name, :string
|
70
|
+
end
|
71
|
+
|
72
|
+
TestEmbeddedInterface.new.known_attribute_names.should include('name')
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
it "should give us default attributes from schema" do
|
77
|
+
class TestEmbeddedInterface
|
78
|
+
field :name
|
79
|
+
field :age, :integer, :default => 1
|
80
|
+
end
|
81
|
+
|
82
|
+
defaults = TestEmbeddedInterface.default_attributes_from_schema
|
83
|
+
defaults["name"].should be_nil
|
84
|
+
defaults["age"].should == 1
|
85
|
+
end
|
86
|
+
|
87
|
+
describe "timestamps" do
|
88
|
+
before do
|
89
|
+
class TestEmbeddedInterface
|
90
|
+
timestamps
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should have a created_at time field" do
|
95
|
+
TestEmbeddedInterface.attributes_schema['created_at'].type.should == :time
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
describe "dynamically adding a field" do
|
101
|
+
it "should be possible to dynamically add a field" do
|
102
|
+
TestEmbeddedInterface.add_field :name, :default => "NA"
|
103
|
+
|
104
|
+
TestEmbeddedInterface.should have(1).fields
|
105
|
+
|
106
|
+
field = TestEmbeddedInterface.fields.first
|
107
|
+
|
108
|
+
field.name.should == "name"
|
109
|
+
field.default.should == "NA"
|
110
|
+
end
|
111
|
+
|
112
|
+
it "should be possible to set field's type just like the DSL" do
|
113
|
+
TestEmbeddedInterface.add_field :age, :integer, :default => 0
|
114
|
+
|
115
|
+
TestEmbeddedInterface.fields.first.name.should == "age"
|
116
|
+
TestEmbeddedInterface.fields.first.type.should == :integer
|
117
|
+
TestEmbeddedInterface.fields.first.default.should == 0
|
118
|
+
end
|
119
|
+
|
120
|
+
it "should call class' undefine_attribute_methods to make sure it regenerates for newly added" do
|
121
|
+
TestEmbeddedInterface.should_receive(:undefine_attribute_methods)
|
122
|
+
TestEmbeddedInterface.add_field :name, :default => "NA"
|
123
|
+
end
|
124
|
+
|
125
|
+
it "should return the new field" do
|
126
|
+
field = TestEmbeddedInterface.add_field :age, :integer, :default => 0
|
127
|
+
field.should == TestEmbeddedInterface.fields.first
|
128
|
+
end
|
129
|
+
|
130
|
+
it "should insert the new field's default value right away" do
|
131
|
+
test_interface = TestEmbeddedInterface.new
|
132
|
+
test_interface.should_receive("age=").with(1)
|
133
|
+
test_interface.add_field :age, :integer, :default => 1
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
describe "#attributes_db_raw_data_hash" do
|
138
|
+
subject { Address.new("id", :street => "Asker", :number => 2, :nice_place => true, :zip => '1384') }
|
139
|
+
|
140
|
+
it "returns hash with correct key-value pairs" do
|
141
|
+
subject.attributes_db_raw_data_hash.should eq({
|
142
|
+
"street" => "Asker",
|
143
|
+
"number" => 2,
|
144
|
+
"nice_place" => "true",
|
145
|
+
"postal_code" => "1384"
|
146
|
+
})
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
describe ".transpose_raw_data_to_record_attributes_and_raw_data" do
|
151
|
+
let(:id) { "id" }
|
152
|
+
let(:raw_data) do
|
153
|
+
MassiveRecord::ORM::RawData.new(value: {
|
154
|
+
"street" => "Oslo",
|
155
|
+
"number" => 3,
|
156
|
+
"nice_place" => "false",
|
157
|
+
"postal_code" => "1111"
|
158
|
+
})
|
159
|
+
end
|
160
|
+
|
161
|
+
it "returns attributes" do
|
162
|
+
attributes, raw = Address.transpose_raw_data_to_record_attributes_and_raw_data id, raw_data
|
163
|
+
attributes.should eq({:id=>"id", "street"=>"Oslo", "number"=>3, "nice_place"=>false, "zip"=>"1111", "updated_at" => nil})
|
164
|
+
end
|
165
|
+
|
166
|
+
it "returns raw data" do
|
167
|
+
attributes, raw = Address.transpose_raw_data_to_record_attributes_and_raw_data id, raw_data
|
168
|
+
raw.should eq Hash[raw_data.value.collect do |attr, value|
|
169
|
+
[attr, MassiveRecord::ORM::RawData.new(value: value, created_at: raw_data.created_at)]
|
170
|
+
end]
|
171
|
+
end
|
172
|
+
|
173
|
+
it "returns correct attributes from serialized db values hash" do
|
174
|
+
attributes, raw = Address.transpose_raw_data_to_record_attributes_and_raw_data(
|
175
|
+
id,
|
176
|
+
MassiveRecord::ORM::RawData.new(value: MassiveRecord::ORM::Base.coder.dump(raw_data.value))
|
177
|
+
)
|
178
|
+
attributes.should eq({:id=>"id", "street"=>"Oslo", "number"=>3, "nice_place"=>false, "zip"=>"1111", "updated_at" => nil})
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
@@ -162,6 +162,13 @@ describe MassiveRecord::ORM::Schema::Field do
|
|
162
162
|
@subject.decode("\x00\x00\x00\x00\x00\x00\x00\x1E").should eq 30
|
163
163
|
end
|
164
164
|
|
165
|
+
it "it forces encoding on the value to be BINARY if value is integer" do
|
166
|
+
value = "\x00\x00\x00\x00\x00\x00\x00\x01"
|
167
|
+
value.should_receive(:force_encoding).and_return(value)
|
168
|
+
@subject = MassiveRecord::ORM::Schema::Field.new(:name => :status, :type => :integer)
|
169
|
+
@subject.decode(value)
|
170
|
+
end
|
171
|
+
|
165
172
|
it "should decode an float value" do
|
166
173
|
@subject = MassiveRecord::ORM::Schema::Field.new(:name => :code, :type => :float)
|
167
174
|
@subject.decode("12.345").should == 12.345
|
@@ -30,6 +30,11 @@ describe MassiveRecord::ORM::Schema::TableInterface do
|
|
30
30
|
TestInterface.column_families.collect(&:name).should include("misc")
|
31
31
|
end
|
32
32
|
|
33
|
+
it "adds a column family" do
|
34
|
+
TestInterface.add_column_family(:foo)
|
35
|
+
TestInterface.column_families.collect(&:name).should include("foo")
|
36
|
+
end
|
37
|
+
|
33
38
|
it "should be possible to add fields to a column families" do
|
34
39
|
class TestInterface
|
35
40
|
column_family :info do
|
@@ -40,6 +45,20 @@ describe MassiveRecord::ORM::Schema::TableInterface do
|
|
40
45
|
TestInterface.known_attribute_names.should == ["name"]
|
41
46
|
end
|
42
47
|
|
48
|
+
it "should return a list of known collum families" do
|
49
|
+
class TestInterface
|
50
|
+
column_family :info do
|
51
|
+
field :name
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
TestInterface.known_column_family_names.should == ["info"]
|
56
|
+
end
|
57
|
+
|
58
|
+
it "returns no known column family names if no one are defined" do
|
59
|
+
TestInterface.known_column_family_names.should == []
|
60
|
+
end
|
61
|
+
|
43
62
|
it "should return attributes schema based on DSL" do
|
44
63
|
class TestInterface
|
45
64
|
column_family :info do
|
@@ -170,12 +189,16 @@ describe MassiveRecord::ORM::Schema::TableInterface do
|
|
170
189
|
autoload_fields
|
171
190
|
end
|
172
191
|
|
192
|
+
column_family :integers_only do
|
193
|
+
autoload_fields :type => :integer
|
194
|
+
end
|
195
|
+
|
173
196
|
column_family :misc do
|
174
197
|
field :text
|
175
198
|
end
|
176
199
|
end
|
177
200
|
|
178
|
-
@column_names = %w(info:name misc:other)
|
201
|
+
@column_names = %w(info:name misc:other integers_only:number)
|
179
202
|
end
|
180
203
|
|
181
204
|
it "should not add fields to misc" do
|
@@ -188,6 +211,13 @@ describe MassiveRecord::ORM::Schema::TableInterface do
|
|
188
211
|
TestInterface.autoload_column_families_and_fields_with(@column_names)
|
189
212
|
end
|
190
213
|
|
214
|
+
it "creates fields with same options as you give to autoload fields" do
|
215
|
+
TestInterface.autoload_column_families_and_fields_with(@column_names)
|
216
|
+
family = TestInterface.column_families.family_by_name("integers_only")
|
217
|
+
autoloaded_field = family.field_by_name(:number)
|
218
|
+
autoloaded_field.type.should eq :integer
|
219
|
+
end
|
220
|
+
|
191
221
|
it "should be possible to run twice" do
|
192
222
|
2.times { TestInterface.autoload_column_families_and_fields_with(@column_names) }
|
193
223
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
shared_examples_for 'an id factory' do
|
4
|
+
it "is a singleton" do
|
5
|
+
MassiveRecord::ORM::IdFactory::AtomicIncrementation.included_modules.should include(Singleton)
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "#next_for" do
|
9
|
+
it "responds_to next_for" do
|
10
|
+
subject.should respond_to :next_for
|
11
|
+
end
|
12
|
+
|
13
|
+
it "uses incomming table name if it's a string" do
|
14
|
+
subject.should_receive(:next_id).with(hash_including(:table => "test_table"))
|
15
|
+
subject.next_for "test_table"
|
16
|
+
end
|
17
|
+
|
18
|
+
it "usees incomming table name if it's a symbol" do
|
19
|
+
subject.should_receive(:next_id).with(hash_including(:table => "test_table"))
|
20
|
+
subject.next_for :test_table
|
21
|
+
end
|
22
|
+
|
23
|
+
it "asks object for it's table name if it responds to that" do
|
24
|
+
Person.should_receive(:table_name).any_number_of_times.and_return("people")
|
25
|
+
subject.should_receive(:next_id).with(hash_including(:table => "people"))
|
26
|
+
subject.next_for(Person)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "returns uniq ids" do
|
30
|
+
ids = 10.times.inject([]) do |ids|
|
31
|
+
ids << subject.next_for(Person)
|
32
|
+
end
|
33
|
+
|
34
|
+
ids.should eq ids.uniq
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe ".next_for" do
|
39
|
+
it "delegates to it's instance" do
|
40
|
+
subject.should_receive(:next_for).with("cars")
|
41
|
+
described_class.next_for("cars")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
shared_examples_for "a model with timestamps" do
|
4
|
+
include TimeZoneHelper
|
5
|
+
|
6
|
+
describe "#created_at" do
|
7
|
+
it "is instructed to create it on create :-)" do
|
8
|
+
subject.should be_set_created_at_on_create
|
9
|
+
end
|
10
|
+
|
11
|
+
it "is nil on new records" do
|
12
|
+
described_class.new.created_at.should be_nil
|
13
|
+
end
|
14
|
+
|
15
|
+
it "is not possible to set" do
|
16
|
+
expect { subject.created_at = Time.now }.to raise_error MassiveRecord::ORM::CantBeManuallyAssigned
|
17
|
+
expect { subject['created_at'] = Time.now }.to raise_error MassiveRecord::ORM::CantBeManuallyAssigned
|
18
|
+
expect { subject.write_attribute(:created_at, Time.now) }.to raise_error MassiveRecord::ORM::CantBeManuallyAssigned
|
19
|
+
end
|
20
|
+
|
21
|
+
it "is set on persisted records" do
|
22
|
+
subject.created_at.should be_a_kind_of Time
|
23
|
+
end
|
24
|
+
|
25
|
+
it "is not changed on update" do
|
26
|
+
created_at_was = subject.created_at
|
27
|
+
|
28
|
+
sleep(1)
|
29
|
+
|
30
|
+
subject.update_attribute attribute_to_be_changed, subject[attribute_to_be_changed] + "NEW"
|
31
|
+
subject.created_at.should == created_at_was
|
32
|
+
end
|
33
|
+
|
34
|
+
it "is included in list of #known_attribute_names_for_inspect" do
|
35
|
+
subject.send(:known_attribute_names_for_inspect).should include 'created_at'
|
36
|
+
end
|
37
|
+
|
38
|
+
it "is included in inspect" do
|
39
|
+
subject.inspect.should include(%q{created_at:})
|
40
|
+
end
|
41
|
+
|
42
|
+
it "raises error if created_at is not time" do
|
43
|
+
described_class.attributes_schema['created_at'].type = :string
|
44
|
+
expect { described_class.new.save(:validate => false) }.to raise_error "created_at must be of type time"
|
45
|
+
described_class.attributes_schema['created_at'].type = :time
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
|
52
|
+
|
53
|
+
|
54
|
+
shared_examples_for "a model without timestamps" do
|
55
|
+
include TimeZoneHelper
|
56
|
+
|
57
|
+
describe "#created_at" do
|
58
|
+
it "is instructed not to create it on create :-)" do
|
59
|
+
subject.should_not be_set_created_at_on_create
|
60
|
+
end
|
61
|
+
|
62
|
+
it "does not raise cant-set-error" do
|
63
|
+
expect { subject.created_at = Time.now }.to_not raise_error MassiveRecord::ORM::CantBeManuallyAssigned
|
64
|
+
end
|
65
|
+
|
66
|
+
it "does not include created_at in the list of known attributes" do
|
67
|
+
subject.send(:known_attribute_names_for_inspect).should_not include 'created_at'
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Might be a bit strange, but HBase gives you time stamps on cells
|
72
|
+
# regardless, so we'll always make it available to the client
|
73
|
+
describe "#updated_at" do
|
74
|
+
it "is nil on new records" do
|
75
|
+
described_class.new.updated_at.should be_nil
|
76
|
+
end
|
77
|
+
|
78
|
+
it "is not possible to set" do
|
79
|
+
expect { subject.updated_at = Time.now }.to raise_error MassiveRecord::ORM::CantBeManuallyAssigned
|
80
|
+
expect { subject['updated_at'] = Time.now }.to raise_error MassiveRecord::ORM::CantBeManuallyAssigned
|
81
|
+
expect { subject.write_attribute(:updated_at, Time.now) }.to raise_error MassiveRecord::ORM::CantBeManuallyAssigned
|
82
|
+
end
|
83
|
+
|
84
|
+
it "is set on persisted records" do
|
85
|
+
subject.updated_at.should be_a_kind_of Time
|
86
|
+
end
|
87
|
+
|
88
|
+
it "is included in list of #known_attribute_names_for_inspect" do
|
89
|
+
subject.send(:known_attribute_names_for_inspect).should include 'updated_at'
|
90
|
+
end
|
91
|
+
|
92
|
+
it "includes updated_at in inspect" do
|
93
|
+
subject.inspect.should include(%q{updated_at:})
|
94
|
+
end
|
95
|
+
|
96
|
+
it "is updated after save" do
|
97
|
+
sleep(1)
|
98
|
+
|
99
|
+
updated_at_was = subject.updated_at
|
100
|
+
subject.update_attribute attribute_to_be_changed, "Should Give Me New Updated At"
|
101
|
+
|
102
|
+
subject.updated_at.should_not eq updated_at_was
|
103
|
+
end
|
104
|
+
|
105
|
+
it "is not updated when save fails" do
|
106
|
+
sleep(1)
|
107
|
+
|
108
|
+
updated_at_was = subject.updated_at
|
109
|
+
subject[attribute_to_be_changed] = nil
|
110
|
+
|
111
|
+
subject.should_not be_valid
|
112
|
+
|
113
|
+
subject.updated_at.should eq updated_at_was
|
114
|
+
end
|
115
|
+
|
116
|
+
context "with time zone awarenesswith zone enabled" do
|
117
|
+
it "should return time with zone" do
|
118
|
+
in_time_zone "Europe/Stockholm" do
|
119
|
+
subject.updated_at.should be_instance_of ActiveSupport::TimeWithZone
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should be nil on new records" do
|
124
|
+
in_time_zone "Europe/Stockholm" do
|
125
|
+
Person.new.updated_at.should be_nil
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
|