massive_record 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.autotest +15 -0
- data/.gitignore +6 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +38 -0
- data/Manifest +24 -0
- data/README.md +225 -0
- data/Rakefile +16 -0
- data/TODO.md +8 -0
- data/autotest/discover.rb +1 -0
- data/lib/massive_record.rb +18 -0
- data/lib/massive_record/exceptions.rb +11 -0
- data/lib/massive_record/orm/attribute_methods.rb +61 -0
- data/lib/massive_record/orm/attribute_methods/dirty.rb +80 -0
- data/lib/massive_record/orm/attribute_methods/read.rb +23 -0
- data/lib/massive_record/orm/attribute_methods/write.rb +24 -0
- data/lib/massive_record/orm/base.rb +176 -0
- data/lib/massive_record/orm/callbacks.rb +52 -0
- data/lib/massive_record/orm/column.rb +18 -0
- data/lib/massive_record/orm/config.rb +47 -0
- data/lib/massive_record/orm/errors.rb +47 -0
- data/lib/massive_record/orm/finders.rb +125 -0
- data/lib/massive_record/orm/id_factory.rb +133 -0
- data/lib/massive_record/orm/persistence.rb +199 -0
- data/lib/massive_record/orm/schema.rb +4 -0
- data/lib/massive_record/orm/schema/column_families.rb +48 -0
- data/lib/massive_record/orm/schema/column_family.rb +102 -0
- data/lib/massive_record/orm/schema/column_interface.rb +91 -0
- data/lib/massive_record/orm/schema/common_interface.rb +48 -0
- data/lib/massive_record/orm/schema/field.rb +128 -0
- data/lib/massive_record/orm/schema/fields.rb +37 -0
- data/lib/massive_record/orm/schema/table_interface.rb +96 -0
- data/lib/massive_record/orm/table.rb +9 -0
- data/lib/massive_record/orm/validations.rb +52 -0
- data/lib/massive_record/spec/support/simple_database_cleaner.rb +52 -0
- data/lib/massive_record/thrift/hbase.rb +2307 -0
- data/lib/massive_record/thrift/hbase_constants.rb +14 -0
- data/lib/massive_record/thrift/hbase_types.rb +225 -0
- data/lib/massive_record/version.rb +3 -0
- data/lib/massive_record/wrapper/base.rb +28 -0
- data/lib/massive_record/wrapper/cell.rb +45 -0
- data/lib/massive_record/wrapper/column_families_collection.rb +19 -0
- data/lib/massive_record/wrapper/column_family.rb +22 -0
- data/lib/massive_record/wrapper/connection.rb +71 -0
- data/lib/massive_record/wrapper/row.rb +170 -0
- data/lib/massive_record/wrapper/scanner.rb +50 -0
- data/lib/massive_record/wrapper/table.rb +148 -0
- data/lib/massive_record/wrapper/tables_collection.rb +13 -0
- data/massive_record.gemspec +28 -0
- data/spec/config.yml.example +4 -0
- data/spec/orm/cases/attribute_methods_spec.rb +47 -0
- data/spec/orm/cases/auto_generate_id_spec.rb +54 -0
- data/spec/orm/cases/base_spec.rb +176 -0
- data/spec/orm/cases/callbacks_spec.rb +309 -0
- data/spec/orm/cases/column_spec.rb +49 -0
- data/spec/orm/cases/config_spec.rb +103 -0
- data/spec/orm/cases/dirty_spec.rb +129 -0
- data/spec/orm/cases/encoding_spec.rb +49 -0
- data/spec/orm/cases/finders_spec.rb +208 -0
- data/spec/orm/cases/hbase/connection_spec.rb +13 -0
- data/spec/orm/cases/i18n_spec.rb +32 -0
- data/spec/orm/cases/id_factory_spec.rb +75 -0
- data/spec/orm/cases/persistence_spec.rb +479 -0
- data/spec/orm/cases/table_spec.rb +81 -0
- data/spec/orm/cases/validation_spec.rb +92 -0
- data/spec/orm/models/address.rb +7 -0
- data/spec/orm/models/person.rb +15 -0
- data/spec/orm/models/test_class.rb +5 -0
- data/spec/orm/schema/column_families_spec.rb +186 -0
- data/spec/orm/schema/column_family_spec.rb +131 -0
- data/spec/orm/schema/column_interface_spec.rb +115 -0
- data/spec/orm/schema/field_spec.rb +196 -0
- data/spec/orm/schema/fields_spec.rb +126 -0
- data/spec/orm/schema/table_interface_spec.rb +171 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/support/connection_helpers.rb +76 -0
- data/spec/support/mock_massive_record_connection.rb +80 -0
- data/spec/thrift/cases/encoding_spec.rb +48 -0
- data/spec/wrapper/cases/connection_spec.rb +53 -0
- data/spec/wrapper/cases/table_spec.rb +231 -0
- metadata +228 -0
@@ -0,0 +1,115 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class TestColumnInterface
|
4
|
+
include MassiveRecord::ORM::Schema::ColumnInterface
|
5
|
+
end
|
6
|
+
|
7
|
+
describe MassiveRecord::ORM::Schema::TableInterface do
|
8
|
+
after do
|
9
|
+
TestColumnInterface.fields = nil
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should respond_to default_attributes_from_schema" do
|
13
|
+
TestColumnInterface.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
|
+
TestColumnInterface.fields.should be_nil
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should have one field if one field is added" do
|
21
|
+
class TestColumnInterface
|
22
|
+
field :field_name, :string
|
23
|
+
end
|
24
|
+
|
25
|
+
TestColumnInterface.should have(1).fields
|
26
|
+
TestColumnInterface.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 TestColumnInterface
|
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 TestColumnInterface
|
40
|
+
field :name
|
41
|
+
field :age, :integer, :default => 1
|
42
|
+
end
|
43
|
+
|
44
|
+
TestColumnInterface.attributes_schema["name"].type.should == :string
|
45
|
+
TestColumnInterface.attributes_schema["age"].type.should == :integer
|
46
|
+
TestColumnInterface.attributes_schema["age"].default.should == 1
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should make attributes_schema readable from instances" do
|
50
|
+
class TestColumnInterface
|
51
|
+
field :name
|
52
|
+
end
|
53
|
+
|
54
|
+
TestColumnInterface.new.attributes_schema["name"].type.should == :string
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should have a list of known attribute names" do
|
58
|
+
class TestColumnInterface
|
59
|
+
field :name, :string
|
60
|
+
field :age, :integer
|
61
|
+
end
|
62
|
+
|
63
|
+
TestColumnInterface.should have(2).known_attribute_names
|
64
|
+
TestColumnInterface.known_attribute_names.should include("name", "age")
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should give us default attributes from schema" do
|
68
|
+
class TestColumnInterface
|
69
|
+
field :name
|
70
|
+
field :age, :integer, :default => 1
|
71
|
+
end
|
72
|
+
|
73
|
+
defaults = TestColumnInterface.default_attributes_from_schema
|
74
|
+
defaults["name"].should be_nil
|
75
|
+
defaults["age"].should == 1
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
describe "dynamically adding a field" do
|
80
|
+
it "should be possible to dynamically add a field" do
|
81
|
+
TestColumnInterface.add_field :name, :default => "NA"
|
82
|
+
|
83
|
+
TestColumnInterface.should have(1).fields
|
84
|
+
|
85
|
+
field = TestColumnInterface.fields.first
|
86
|
+
|
87
|
+
field.name.should == "name"
|
88
|
+
field.default.should == "NA"
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should be possible to set field's type just like the DSL" do
|
92
|
+
TestColumnInterface.add_field :age, :integer, :default => 0
|
93
|
+
|
94
|
+
TestColumnInterface.fields.first.name.should == "age"
|
95
|
+
TestColumnInterface.fields.first.type.should == :integer
|
96
|
+
TestColumnInterface.fields.first.default.should == 0
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should call class' undefine_attribute_methods to make sure it regenerates for newly added" do
|
100
|
+
TestColumnInterface.should_receive(:undefine_attribute_methods)
|
101
|
+
TestColumnInterface.add_field :name, :default => "NA"
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should return the new field" do
|
105
|
+
field = TestColumnInterface.add_field :age, :integer, :default => 0
|
106
|
+
field.should == TestColumnInterface.fields.first
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should insert the new field's default value right away" do
|
110
|
+
test_interface = TestColumnInterface.new
|
111
|
+
test_interface.should_receive("age=").with(1)
|
112
|
+
test_interface.add_field :age, :integer, :default => 1
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,196 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MassiveRecord::ORM::Schema::Field do
|
4
|
+
describe "initializer" do
|
5
|
+
%w(name column default).each do |attr_name|
|
6
|
+
it "should set #{attr_name}" do
|
7
|
+
field = MassiveRecord::ORM::Schema::Field.new attr_name => "a_value"
|
8
|
+
field.send(attr_name).should == "a_value"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should set type, cast it to a symbol" do
|
13
|
+
MassiveRecord::ORM::Schema::Field.new(:type => "a_value").type.should == :a_value
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should default to type string" do
|
17
|
+
MassiveRecord::ORM::Schema::Field.new(:name => "a_value").type.should == :string
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "new_with_arguments_from_dsl" do
|
22
|
+
it "should take the first argument as name" do
|
23
|
+
field = MassiveRecord::ORM::Schema::Field.new_with_arguments_from_dsl("info")
|
24
|
+
field.name.should == "info"
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should take the second argument as type" do
|
28
|
+
field = MassiveRecord::ORM::Schema::Field.new_with_arguments_from_dsl("info", "integer")
|
29
|
+
field.type.should == :integer
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should take the rest as options" do
|
33
|
+
field = MassiveRecord::ORM::Schema::Field.new_with_arguments_from_dsl("info", "integer", :default => 0)
|
34
|
+
field.default.should == 0
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "validations" do
|
39
|
+
before do
|
40
|
+
@fields = MassiveRecord::ORM::Schema::Fields.new
|
41
|
+
@field = MassiveRecord::ORM::Schema::Field.new :name => "field_name", :fields => @fields
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should be valid from before hook" do
|
45
|
+
@field.should be_valid
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should not be valid if name is blank" do
|
49
|
+
@field.send(:name=, nil)
|
50
|
+
@field.should_not be_valid
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should not be valid without fields to belong to" do
|
54
|
+
@field.fields = nil
|
55
|
+
@field.should_not be_valid
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should not be valid if it's parent some how knows that it's name has been taken" do
|
59
|
+
@fields.should_receive(:attribute_name_taken?).with("field_name").and_return true
|
60
|
+
@field.should_not be_valid
|
61
|
+
end
|
62
|
+
|
63
|
+
MassiveRecord::ORM::Schema::Field::TYPES.each do |type|
|
64
|
+
it "should be valid with type #{type}" do
|
65
|
+
@field.type = type
|
66
|
+
@field.should be_valid
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should not be valid with foo as type" do
|
71
|
+
@field.type = :foo
|
72
|
+
@field.should_not be_valid
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should cast name to string" do
|
77
|
+
field = MassiveRecord::ORM::Schema::Field.new(:name => :name)
|
78
|
+
field.name.should == "name"
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should compare two column families based on name" do
|
82
|
+
field_1 = MassiveRecord::ORM::Schema::Field.new(:name => :name)
|
83
|
+
field_2 = MassiveRecord::ORM::Schema::Field.new(:name => :name)
|
84
|
+
|
85
|
+
field_1.should == field_2
|
86
|
+
field_1.eql?(field_2).should be_true
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should have the same hash value for two families with the same name" do
|
90
|
+
field_1 = MassiveRecord::ORM::Schema::Field.new(:name => :name)
|
91
|
+
field_2 = MassiveRecord::ORM::Schema::Field.new(:name => :name)
|
92
|
+
|
93
|
+
field_1.hash.should == field_2.hash
|
94
|
+
end
|
95
|
+
|
96
|
+
describe "#decode" do
|
97
|
+
it "should return a value if value is of correct class" do
|
98
|
+
today = Date.today
|
99
|
+
@subject = MassiveRecord::ORM::Schema::Field.new(:name => :created_at, :type => :date)
|
100
|
+
@subject.decode(today) == today
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should decode a boolean value" do
|
104
|
+
@subject = MassiveRecord::ORM::Schema::Field.new(:name => :status, :type => :boolean)
|
105
|
+
@subject.decode("1").should be_true
|
106
|
+
@subject.decode("0").should be_false
|
107
|
+
@subject.decode("").should be_nil
|
108
|
+
@subject.decode(nil).should be_nil
|
109
|
+
end
|
110
|
+
|
111
|
+
it "should decode a string value" do
|
112
|
+
@subject = MassiveRecord::ORM::Schema::Field.new(:name => :status, :type => :string)
|
113
|
+
@subject.decode("value").should == "value"
|
114
|
+
@subject.decode("").should == ""
|
115
|
+
@subject.decode(nil).should be_nil
|
116
|
+
end
|
117
|
+
|
118
|
+
it "should decode an integer value" do
|
119
|
+
@subject = MassiveRecord::ORM::Schema::Field.new(:name => :status, :type => :integer)
|
120
|
+
@subject.decode("1").should == 1
|
121
|
+
@subject.decode("").should be_nil
|
122
|
+
@subject.decode(nil).should be_nil
|
123
|
+
end
|
124
|
+
|
125
|
+
it "should decode an float value" do
|
126
|
+
@subject = MassiveRecord::ORM::Schema::Field.new(:name => :code, :type => :float)
|
127
|
+
@subject.decode("12.345").should == 12.345
|
128
|
+
@subject.decode("").should be_nil
|
129
|
+
@subject.decode(nil).should be_nil
|
130
|
+
end
|
131
|
+
|
132
|
+
it "should decode a date type" do
|
133
|
+
today = Date.today
|
134
|
+
@subject = MassiveRecord::ORM::Schema::Field.new(:name => :created_at, :type => :date)
|
135
|
+
@subject.decode(today.to_s) == today
|
136
|
+
@subject.decode("").should be_nil
|
137
|
+
@subject.decode(nil).should be_nil
|
138
|
+
end
|
139
|
+
|
140
|
+
it "should decode a time type" do
|
141
|
+
today = Time.now
|
142
|
+
@subject = MassiveRecord::ORM::Schema::Field.new(:name => :created_at, :type => :time)
|
143
|
+
@subject.decode(today.to_s) == today
|
144
|
+
@subject.decode("").should be_nil
|
145
|
+
@subject.decode(nil).should be_nil
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
describe "#unique_name" do
|
150
|
+
before do
|
151
|
+
@family = MassiveRecord::ORM::Schema::ColumnFamily.new :name => :info
|
152
|
+
@field = MassiveRecord::ORM::Schema::Field.new :name => "field_name"
|
153
|
+
@field_with_column = MassiveRecord::ORM::Schema::Field.new :name => "field_name", :column => "fn"
|
154
|
+
end
|
155
|
+
|
156
|
+
it "should raise an error if it has no contained_in" do
|
157
|
+
lambda { @field.unique_name }.should raise_error "Can't generate a unique name as I don't have a column family!"
|
158
|
+
end
|
159
|
+
|
160
|
+
it "should return correct unique name" do
|
161
|
+
@family << @field
|
162
|
+
@field.unique_name.should == "info:field_name"
|
163
|
+
end
|
164
|
+
|
165
|
+
it "should return a correct unique name when using column" do
|
166
|
+
@family << @field_with_column
|
167
|
+
@field_with_column.unique_name.should == "info:fn"
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
describe "#column" do
|
172
|
+
before do
|
173
|
+
@field = MassiveRecord::ORM::Schema::Field.new :name => "field_name"
|
174
|
+
end
|
175
|
+
|
176
|
+
it "should default to name" do
|
177
|
+
@field.column.should == "field_name"
|
178
|
+
end
|
179
|
+
|
180
|
+
it "should be overridable" do
|
181
|
+
@field.column = "new"
|
182
|
+
@field.column.should == "new"
|
183
|
+
end
|
184
|
+
|
185
|
+
it "should be returned as a string" do
|
186
|
+
@field.column = :new
|
187
|
+
@field.column.should == "new"
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
it "should duplicate the default value" do
|
192
|
+
default_array = []
|
193
|
+
field = MassiveRecord::ORM::Schema::Field.new :name => "array", :type => :array, :default => default_array
|
194
|
+
field.default.object_id.should_not == default_array.object_id
|
195
|
+
end
|
196
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MassiveRecord::ORM::Schema::Fields do
|
4
|
+
before do
|
5
|
+
@fields = MassiveRecord::ORM::Schema::Fields.new
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should be a kind of set" do
|
9
|
+
@fields.should be_a_kind_of Set
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "add fields to the set" do
|
13
|
+
it "should be possible to add fields" do
|
14
|
+
@fields << MassiveRecord::ORM::Schema::Field.new(:name => "field")
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should add self to field's fields attribute" do
|
18
|
+
field = MassiveRecord::ORM::Schema::Field.new(:name => :field)
|
19
|
+
@fields << field
|
20
|
+
field.fields.should == @fields
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should not be possible to add two fields with the same name" do
|
24
|
+
@fields << MassiveRecord::ORM::Schema::Field.new(:name => "attr")
|
25
|
+
@fields.add?(MassiveRecord::ORM::Schema::Field.new(:name => "attr")).should be_nil
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should raise error if invalid column familiy is added" do
|
29
|
+
invalid_field = MassiveRecord::ORM::Schema::Field.new
|
30
|
+
lambda { @fields << invalid_field }.should raise_error MassiveRecord::ORM::Schema::InvalidField
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#to_hash" do
|
35
|
+
before do
|
36
|
+
@name_field = MassiveRecord::ORM::Schema::Field.new(:name => :name)
|
37
|
+
@phone_field = MassiveRecord::ORM::Schema::Field.new(:name => :phone)
|
38
|
+
@fields << @name_field << @phone_field
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should return nil if no fields are added" do
|
42
|
+
@fields.clear
|
43
|
+
@fields.to_hash.should == {}
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should contain added fields" do
|
47
|
+
@fields.to_hash.should include("name" => @name_field)
|
48
|
+
@fields.to_hash.should include("phone" => @phone_field)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "#attribute_names" do
|
53
|
+
before do
|
54
|
+
@name_field = MassiveRecord::ORM::Schema::Field.new(:name => :name)
|
55
|
+
@phone_field = MassiveRecord::ORM::Schema::Field.new(:name => :phone)
|
56
|
+
@fields << @name_field << @phone_field
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should return nil if no fields are added" do
|
60
|
+
@fields.clear
|
61
|
+
@fields.attribute_names.should == []
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should contain added fields" do
|
65
|
+
@fields.attribute_names.should include("name", "phone")
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe "#attribute_name_taken?" do
|
70
|
+
before do
|
71
|
+
@name_field = MassiveRecord::ORM::Schema::Field.new(:name => :name)
|
72
|
+
@phone_field = MassiveRecord::ORM::Schema::Field.new(:name => :phone)
|
73
|
+
@fields << @name_field << @phone_field
|
74
|
+
end
|
75
|
+
|
76
|
+
describe "with no contained_in" do
|
77
|
+
it "should return true if name is taken" do
|
78
|
+
@fields.attribute_name_taken?("phone").should be_true
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should accept and return true if name, given as a symbol, is taken" do
|
82
|
+
@fields.attribute_name_taken?(:phone).should be_true
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should return false if name is not taken" do
|
86
|
+
@fields.attribute_name_taken?("not_taken").should be_false
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe "with contained_in set" do
|
91
|
+
before do
|
92
|
+
@fields.contained_in = MassiveRecord::ORM::Schema::ColumnFamily.new :name => "Family"
|
93
|
+
end
|
94
|
+
|
95
|
+
it "should ask object it is contained in for the truth about if attribute name is taken" do
|
96
|
+
@fields.contained_in.should_receive(:attribute_name_taken?).and_return true
|
97
|
+
@fields.attribute_name_taken?(:foo).should be_true
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should not ask object it is contained in if asked not to" do
|
101
|
+
@fields.contained_in.should_not_receive(:attribute_name_taken?)
|
102
|
+
@fields.attribute_name_taken?(:foo, true).should be_false
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe "#field_by_name" do
|
108
|
+
before do
|
109
|
+
@name_field = MassiveRecord::ORM::Schema::Field.new(:name => :name)
|
110
|
+
@phone_field = MassiveRecord::ORM::Schema::Field.new(:name => :phone)
|
111
|
+
@fields << @name_field << @phone_field
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should return nil if nothing is found" do
|
115
|
+
@fields.field_by_name("unkown").should be_nil
|
116
|
+
end
|
117
|
+
|
118
|
+
it "should return found field" do
|
119
|
+
@fields.field_by_name("name").should == @name_field
|
120
|
+
end
|
121
|
+
|
122
|
+
it "should return found field given as symbol" do
|
123
|
+
@fields.field_by_name(:name).should == @name_field
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,171 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class TestInterface
|
4
|
+
include MassiveRecord::ORM::Schema::TableInterface
|
5
|
+
end
|
6
|
+
|
7
|
+
class TestInterfaceSubClass < TestInterface
|
8
|
+
end
|
9
|
+
|
10
|
+
describe MassiveRecord::ORM::Schema::TableInterface do
|
11
|
+
after do
|
12
|
+
TestInterface.column_families = nil
|
13
|
+
TestInterfaceSubClass.column_families = nil
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
it "should respond_to column_family" do
|
18
|
+
TestInterface.should respond_to :column_family
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should respond_to column_families" do
|
22
|
+
TestInterface.should respond_to :column_families
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should be possible to add column familiy through DSL" do
|
26
|
+
class TestInterface
|
27
|
+
column_family :misc do; end
|
28
|
+
end
|
29
|
+
|
30
|
+
TestInterface.column_families.collect(&:name).should include("misc")
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should be possible to add fields to a column families" do
|
34
|
+
class TestInterface
|
35
|
+
column_family :info do
|
36
|
+
field :name
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
TestInterface.known_attribute_names.should == ["name"]
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should return attributes schema based on DSL" do
|
44
|
+
class TestInterface
|
45
|
+
column_family :info do
|
46
|
+
field :name
|
47
|
+
field :age, :integer, :default => 1
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
TestInterface.attributes_schema["name"].type.should == :string
|
52
|
+
TestInterface.attributes_schema["age"].type.should == :integer
|
53
|
+
TestInterface.attributes_schema["age"].default.should == 1
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should raise an error if you try to add same field name twice" do
|
57
|
+
lambda {
|
58
|
+
class TestInterface
|
59
|
+
column_family :info do
|
60
|
+
field :name
|
61
|
+
field :name
|
62
|
+
end
|
63
|
+
end
|
64
|
+
}.should raise_error MassiveRecord::ORM::Schema::InvalidField
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should give us default attributes from schema" do
|
68
|
+
class TestInterface
|
69
|
+
column_family :info do
|
70
|
+
field :name
|
71
|
+
field :age, :integer, :default => 1
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
defaults = TestInterface.default_attributes_from_schema
|
76
|
+
defaults["name"].should be_nil
|
77
|
+
defaults["age"].should == 1
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should make attributes_schema readable from instances" do
|
81
|
+
class TestInterface
|
82
|
+
column_family :info do
|
83
|
+
field :name
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
TestInterface.new.attributes_schema["name"].type.should == :string
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should not be shared amonb subclasses" do
|
91
|
+
class TestInterface
|
92
|
+
column_family :info do
|
93
|
+
autoload_fields
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
TestInterface.column_families.should_not be_nil
|
98
|
+
TestInterfaceSubClass.column_families.should be_nil
|
99
|
+
end
|
100
|
+
|
101
|
+
|
102
|
+
describe "dynamically adding a field" do
|
103
|
+
it "should be possible to dynamically add a field" do
|
104
|
+
TestInterface.add_field_to_column_family :info, :name, :default => "NA"
|
105
|
+
|
106
|
+
TestInterface.should have(1).column_families
|
107
|
+
|
108
|
+
family = TestInterface.column_families.first
|
109
|
+
family.name.should == "info"
|
110
|
+
|
111
|
+
family.fields.first.name.should == "name"
|
112
|
+
family.fields.first.default.should == "NA"
|
113
|
+
end
|
114
|
+
|
115
|
+
it "should be possible to set field's type just like the DSL" do
|
116
|
+
TestInterface.add_field_to_column_family :info, :age, :integer, :default => 0
|
117
|
+
|
118
|
+
TestInterface.column_families.first.fields.first.name.should == "age"
|
119
|
+
TestInterface.column_families.first.fields.first.type.should == :integer
|
120
|
+
TestInterface.column_families.first.fields.first.default.should == 0
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should call class' undefine_attribute_methods to make sure it regenerates for newly added" do
|
124
|
+
TestInterface.should_receive(:undefine_attribute_methods)
|
125
|
+
TestInterface.add_field_to_column_family :info, :name, :default => "NA"
|
126
|
+
end
|
127
|
+
|
128
|
+
it "should return the new field" do
|
129
|
+
field = TestInterface.add_field_to_column_family :info, :age, :integer, :default => 0
|
130
|
+
field.should == TestInterface.column_families.first.fields.first
|
131
|
+
end
|
132
|
+
|
133
|
+
it "should insert the new field's default value right away" do
|
134
|
+
test_interface = TestInterface.new
|
135
|
+
test_interface.should_receive("age=").with(1)
|
136
|
+
test_interface.add_field_to_column_family :info, :age, :integer, :default => 1
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
|
141
|
+
|
142
|
+
describe "autoload_column_families_and_fields_with" do
|
143
|
+
before do
|
144
|
+
class TestInterface
|
145
|
+
column_family :info do
|
146
|
+
autoload_fields
|
147
|
+
end
|
148
|
+
|
149
|
+
column_family :misc do
|
150
|
+
field :text
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
@column_names = %w(info:name misc:other)
|
155
|
+
end
|
156
|
+
|
157
|
+
it "should not add fields to misc" do
|
158
|
+
TestInterface.column_families.family_by_name("misc").should_not_receive(:add?)
|
159
|
+
TestInterface.autoload_column_families_and_fields_with(@column_names)
|
160
|
+
end
|
161
|
+
|
162
|
+
it "should add fields to info" do
|
163
|
+
TestInterface.column_families.family_by_name("info").should_receive(:add?)
|
164
|
+
TestInterface.autoload_column_families_and_fields_with(@column_names)
|
165
|
+
end
|
166
|
+
|
167
|
+
it "should be possible to run twice" do
|
168
|
+
2.times { TestInterface.autoload_column_families_and_fields_with(@column_names) }
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|