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.
- 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
|