datamapper 0.2.3 → 0.2.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (121) hide show
  1. data/example.rb +5 -5
  2. data/lib/data_mapper/adapters/abstract_adapter.rb +2 -2
  3. data/lib/data_mapper/adapters/data_object_adapter.rb +141 -147
  4. data/lib/data_mapper/adapters/mysql_adapter.rb +14 -1
  5. data/lib/data_mapper/adapters/postgresql_adapter.rb +123 -18
  6. data/lib/data_mapper/adapters/sql/coersion.rb +21 -9
  7. data/lib/data_mapper/adapters/sql/commands/load_command.rb +36 -19
  8. data/lib/data_mapper/adapters/sql/mappings/column.rb +111 -17
  9. data/lib/data_mapper/adapters/sql/mappings/schema.rb +27 -0
  10. data/lib/data_mapper/adapters/sql/mappings/table.rb +256 -29
  11. data/lib/data_mapper/adapters/sqlite3_adapter.rb +93 -8
  12. data/lib/data_mapper/associations/belongs_to_association.rb +53 -54
  13. data/lib/data_mapper/associations/has_and_belongs_to_many_association.rb +157 -25
  14. data/lib/data_mapper/associations/has_many_association.rb +45 -15
  15. data/lib/data_mapper/associations/has_n_association.rb +79 -20
  16. data/lib/data_mapper/associations/has_one_association.rb +2 -2
  17. data/lib/data_mapper/associations/reference.rb +1 -1
  18. data/lib/data_mapper/auto_migrations.rb +40 -0
  19. data/lib/data_mapper/base.rb +201 -98
  20. data/lib/data_mapper/context.rb +16 -10
  21. data/lib/data_mapper/database.rb +22 -11
  22. data/lib/data_mapper/dependency_queue.rb +28 -0
  23. data/lib/data_mapper/embedded_value.rb +61 -17
  24. data/lib/data_mapper/property.rb +4 -0
  25. data/lib/data_mapper/support/active_record_impersonation.rb +13 -5
  26. data/lib/data_mapper/support/errors.rb +5 -0
  27. data/lib/data_mapper/support/serialization.rb +8 -4
  28. data/lib/data_mapper/validatable_extensions/errors.rb +12 -0
  29. data/lib/data_mapper/validatable_extensions/macros.rb +7 -0
  30. data/lib/data_mapper/validatable_extensions/validatable_instance_methods.rb +62 -0
  31. data/lib/data_mapper/validatable_extensions/validation_base.rb +18 -0
  32. data/lib/data_mapper/validatable_extensions/validations/formats/email.rb +43 -0
  33. data/lib/data_mapper/validatable_extensions/validations/validates_acceptance_of.rb +7 -0
  34. data/lib/data_mapper/validatable_extensions/validations/validates_confirmation_of.rb +7 -0
  35. data/lib/data_mapper/validatable_extensions/validations/validates_each.rb +7 -0
  36. data/lib/data_mapper/validatable_extensions/validations/validates_format_of.rb +28 -0
  37. data/lib/data_mapper/validatable_extensions/validations/validates_length_of.rb +15 -0
  38. data/lib/data_mapper/validatable_extensions/validations/validates_numericality_of.rb +7 -0
  39. data/lib/data_mapper/validatable_extensions/validations/validates_presence_of.rb +7 -0
  40. data/lib/data_mapper/validatable_extensions/validations/validates_true_for.rb +7 -0
  41. data/lib/data_mapper/validatable_extensions/validations/validates_uniqueness_of.rb +33 -0
  42. data/lib/data_mapper/validations.rb +20 -0
  43. data/lib/data_mapper.rb +39 -34
  44. data/performance.rb +24 -18
  45. data/plugins/dataobjects/do_rb +0 -0
  46. data/rakefile.rb +12 -2
  47. data/spec/active_record_impersonation_spec.rb +133 -0
  48. data/spec/acts_as_tree_spec.rb +25 -9
  49. data/spec/associations_spec.rb +124 -4
  50. data/spec/attributes_spec.rb +13 -0
  51. data/spec/auto_migrations_spec.rb +44 -0
  52. data/spec/base_spec.rb +189 -1
  53. data/spec/column_spec.rb +85 -7
  54. data/spec/conditions_spec.rb +2 -2
  55. data/spec/dependency_spec.rb +25 -0
  56. data/spec/embedded_value_spec.rb +123 -3
  57. data/spec/fixtures/animals.yaml +1 -0
  58. data/spec/fixtures/careers.yaml +5 -0
  59. data/spec/fixtures/comments.yaml +1 -0
  60. data/spec/fixtures/people.yaml +14 -9
  61. data/spec/fixtures/projects.yaml +4 -0
  62. data/spec/fixtures/sections.yaml +5 -0
  63. data/spec/fixtures/serializers.yaml +6 -0
  64. data/spec/fixtures/users.yaml +1 -0
  65. data/spec/load_command_spec.rb +5 -4
  66. data/spec/mock_adapter.rb +2 -2
  67. data/spec/models/animal.rb +2 -1
  68. data/spec/models/animals_exhibit.rb +2 -2
  69. data/spec/models/career.rb +6 -0
  70. data/spec/models/comment.rb +4 -0
  71. data/spec/models/exhibit.rb +4 -0
  72. data/spec/models/person.rb +3 -13
  73. data/spec/models/project.rb +1 -1
  74. data/spec/models/serializer.rb +3 -0
  75. data/spec/models/user.rb +4 -0
  76. data/spec/models/zoo.rb +8 -1
  77. data/spec/natural_key_spec.rb +36 -0
  78. data/spec/paranoia_spec.rb +36 -0
  79. data/spec/property_spec.rb +70 -0
  80. data/spec/schema_spec.rb +10 -2
  81. data/spec/serialization_spec.rb +6 -3
  82. data/spec/serialize_spec.rb +19 -0
  83. data/spec/single_table_inheritance_spec.rb +7 -1
  84. data/spec/spec_helper.rb +26 -8
  85. data/spec/table_spec.rb +33 -0
  86. data/spec/validates_confirmation_of_spec.rb +20 -4
  87. data/spec/validates_format_of_spec.rb +22 -8
  88. data/spec/validates_length_of_spec.rb +26 -13
  89. data/spec/validates_uniqueness_of_spec.rb +18 -5
  90. data/spec/validations_spec.rb +55 -10
  91. data/tasks/fixtures.rb +13 -7
  92. metadata +189 -153
  93. data/lib/data_mapper/validations/confirmation_validator.rb +0 -53
  94. data/lib/data_mapper/validations/contextual_validations.rb +0 -50
  95. data/lib/data_mapper/validations/format_validator.rb +0 -85
  96. data/lib/data_mapper/validations/formats/email.rb +0 -78
  97. data/lib/data_mapper/validations/generic_validator.rb +0 -22
  98. data/lib/data_mapper/validations/length_validator.rb +0 -76
  99. data/lib/data_mapper/validations/required_field_validator.rb +0 -41
  100. data/lib/data_mapper/validations/unique_validator.rb +0 -56
  101. data/lib/data_mapper/validations/validation_errors.rb +0 -37
  102. data/lib/data_mapper/validations/validation_helper.rb +0 -77
  103. data/plugins/dataobjects/REVISION +0 -1
  104. data/plugins/dataobjects/Rakefile +0 -9
  105. data/plugins/dataobjects/do.rb +0 -348
  106. data/plugins/dataobjects/do_mysql.rb +0 -212
  107. data/plugins/dataobjects/do_postgres.rb +0 -196
  108. data/plugins/dataobjects/do_sqlite3.rb +0 -157
  109. data/plugins/dataobjects/spec/do_spec.rb +0 -150
  110. data/plugins/dataobjects/spec/spec_helper.rb +0 -81
  111. data/plugins/dataobjects/swig_mysql/extconf.rb +0 -45
  112. data/plugins/dataobjects/swig_mysql/mysql_c.c +0 -16602
  113. data/plugins/dataobjects/swig_mysql/mysql_c.i +0 -67
  114. data/plugins/dataobjects/swig_mysql/mysql_supp.i +0 -46
  115. data/plugins/dataobjects/swig_postgres/extconf.rb +0 -29
  116. data/plugins/dataobjects/swig_postgres/postgres_c.c +0 -8185
  117. data/plugins/dataobjects/swig_postgres/postgres_c.i +0 -73
  118. data/plugins/dataobjects/swig_sqlite/extconf.rb +0 -9
  119. data/plugins/dataobjects/swig_sqlite/sqlite3_c.c +0 -4725
  120. data/plugins/dataobjects/swig_sqlite/sqlite_c.i +0 -168
  121. data/tasks/drivers.rb +0 -20
data/spec/base_spec.rb CHANGED
@@ -25,6 +25,13 @@ describe DataMapper::Base do
25
25
  x.should be_dirty
26
26
  end
27
27
 
28
+ it "should be dirty when set to nil" do
29
+ x = Person.create(:name => 'a')
30
+ x.should_not be_dirty
31
+ x.name = "asdfasfd"
32
+ x.should be_dirty
33
+ end
34
+
28
35
  it "should return a diff" do
29
36
  x = Person.new(:name => 'Sam', :age => 30, :occupation => 'Programmer')
30
37
  y = Person.new(:name => 'Amy', :age => 21, :occupation => 'Programmer')
@@ -46,6 +53,30 @@ describe DataMapper::Base do
46
53
  x.should_not be_dirty
47
54
  end
48
55
 
56
+ it "should return the table for a given model" do
57
+ Person.table.should be_a_kind_of(DataMapper::Adapters::Sql::Mappings::Table)
58
+ end
59
+
60
+ it "should support boolean accessors" do
61
+ dolphin = Animal.first(:name => 'Dolphin')
62
+ dolphin.should be_nice
63
+ end
64
+
65
+ it "should be comparable" do
66
+ p1 = Person.create(:name => 'Sam')
67
+ p2 = Person[p1.id]
68
+
69
+ p1.should == p2
70
+ end
71
+
72
+ it "should not be equal if attributes have changed" do
73
+ p1 = Person.create(:name => 'Sam')
74
+ p2 = Person[p1.id]
75
+ p2.name = "Paul"
76
+
77
+ p1.should_not == p2
78
+ end
79
+
49
80
  end
50
81
 
51
82
  describe 'A new record' do
@@ -71,4 +102,161 @@ describe 'A new record' do
71
102
  @bob.id.should == nil
72
103
  end
73
104
 
74
- end
105
+ it "should not have dirty attributes when not dirty" do
106
+ x = Person.create(:name => 'a')
107
+ x.should_not be_dirty
108
+ x.dirty_attributes.should be_empty
109
+ end
110
+
111
+ it "should only list attributes that have changed in the dirty attributes hash" do
112
+ x = Person.create(:name => 'a')
113
+ x.name = "asdfr"
114
+ x.should be_dirty
115
+ x.dirty_attributes.keys.should == [:name]
116
+ end
117
+
118
+ it "should not have original_values when a new record" do
119
+ x = Person.new(:name => 'a')
120
+ x.original_values.should be_empty
121
+ end
122
+
123
+ it "should have original_values after saved" do
124
+ x = Person.new(:name => 'a')
125
+ x.save
126
+ x.original_values.should_not be_empty
127
+ x.original_values.keys.should include(:name)
128
+ x.original_values[:name].should == 'a'
129
+ end
130
+
131
+ it "should have original values when created" do
132
+ x = Person.create(:name => 'a')
133
+ x.original_values.should_not be_empty
134
+ x.original_values.keys.should include(:name)
135
+ x.original_values[:name].should == "a"
136
+ end
137
+
138
+ it "should have original values when loaded from the database" do
139
+ Person.create(:name => 'a')
140
+ x = Person[:name => 'a']
141
+ x.original_values.should_not be_empty
142
+ x.original_values.keys.should include(:name)
143
+ x.original_values[:name].should == "a"
144
+ end
145
+
146
+ it "should reset the original values when not new, changed then saved" do
147
+ x = Person.create(:name => 'a')
148
+ x.should_not be_new_record
149
+ x.original_values[:name].should == "a"
150
+ x.name = "b"
151
+ x.save
152
+ x.original_values[:name].should == "b"
153
+ end
154
+
155
+ it "should allow a value to be set to nil" do
156
+ x = Person.create(:name => 'a')
157
+ x.name = nil
158
+ x.save
159
+ x.reload!
160
+ x.name.should be_nil
161
+ end
162
+
163
+ end
164
+
165
+ describe 'Properties' do
166
+
167
+ it 'should default to public method visibility' do
168
+ class SoftwareEngineer < DataMapper::Base
169
+ set_table_name 'people'
170
+ property :name, :string
171
+ end
172
+
173
+ public_properties = SoftwareEngineer.public_instance_methods.select { |m| ["name", "name="].include?(m) }
174
+ public_properties.length.should == 2
175
+ end
176
+
177
+ it 'should respect protected property options' do
178
+ class SanitationEngineer < DataMapper::Base
179
+ set_table_name 'people'
180
+ property :name, :string, :reader => :protected
181
+ property :age, :integer, :writer => :protected
182
+ end
183
+
184
+ protected_properties = SanitationEngineer.protected_instance_methods.select { |m| ["name", "age="].include?(m) }
185
+ protected_properties.length.should == 2
186
+ end
187
+
188
+ it 'should respect private property options' do
189
+ class ElectricalEngineer < DataMapper::Base
190
+ set_table_name 'people'
191
+ property :name, :string, :reader => :private
192
+ property :age, :integer, :writer => :private
193
+ end
194
+
195
+ private_properties = ElectricalEngineer.private_instance_methods.select { |m| ["name", "age="].include?(m) }
196
+ private_properties.length.should == 2
197
+ end
198
+
199
+ it 'should set both reader and writer visibiliy when accessor option is passed' do
200
+ class TrainEngineer < DataMapper::Base
201
+ property :name, :string, :accessor => :private
202
+ end
203
+
204
+ private_properties = TrainEngineer.private_instance_methods.select { |m| ["name", "name="].include?(m) }
205
+ private_properties.length.should == 2
206
+ end
207
+
208
+ it 'should only be listed in attributes if they have public getters' do
209
+ class SalesEngineer < DataMapper::Base
210
+ set_table_name 'people'
211
+ property :name, :string
212
+ property :age, :integer, :reader => :private
213
+ end
214
+
215
+ @sam = SalesEngineer[:name => 'Sam']
216
+ # note: id default key gets a public reader by default (but writer is protected)
217
+ @sam.attributes.should == {:id => @sam.id, :name => @sam.name}
218
+ end
219
+
220
+ it 'should not allow mass assignment if private or protected' do
221
+ class ChemicalEngineer < DataMapper::Base
222
+ set_table_name 'people'
223
+ property :name, :string, :writer => :private
224
+ property :age, :integer
225
+ end
226
+
227
+ @sam = ChemicalEngineer[:name => 'Sam']
228
+ @sam.attributes = {:name => 'frank', :age => 101}
229
+ @sam.age.should == 101
230
+ @sam.name.should == 'Sam'
231
+ end
232
+
233
+ it 'should allow :protected to be passed as an alias for a public reader, protected writer' do
234
+ class CivilEngineer < DataMapper::Base
235
+ set_table_name 'people'
236
+ property :name, :string, :protected => true
237
+ end
238
+
239
+ CivilEngineer.public_instance_methods.should include("name")
240
+ CivilEngineer.protected_instance_methods.should include("name=")
241
+ end
242
+
243
+ it 'should allow :private to be passed as an alias for a public reader, private writer' do
244
+ class AudioEngineer < DataMapper::Base
245
+ set_table_name 'people'
246
+ property :name, :string, :private => true
247
+ end
248
+
249
+ AudioEngineer.public_instance_methods.should include("name")
250
+ AudioEngineer.private_instance_methods.should include("name=")
251
+ end
252
+
253
+ it 'should raise an error when invalid options are passsed' do
254
+ lambda do
255
+ class JumpyCow < DataMapper::Base
256
+ set_table_name 'animals'
257
+ property :name, :string, :laze => true
258
+ end
259
+ end.should raise_error(ArgumentError)
260
+ end
261
+
262
+ end
data/spec/column_spec.rb CHANGED
@@ -2,22 +2,100 @@ require File.dirname(__FILE__) + "/spec_helper"
2
2
 
3
3
  describe DataMapper::Adapters::Sql::Mappings::Column do
4
4
 
5
+ before(:all) do
6
+ fixtures(:zoos)
7
+ end
8
+
9
+ it "should only lazy loading text columns by default" do
10
+ table = database.table(Zoo)
11
+ table.columns.each do |column|
12
+ if column.type == :text
13
+ column.should be_lazy
14
+ else
15
+ column.should_not be_lazy
16
+ end
17
+ end
18
+ end
19
+
5
20
  it "should be unique within a set" do
6
21
 
7
22
  mappings = DataMapper::Adapters::Sql::Mappings
8
23
 
9
24
  columns = SortedSet.new
10
-
11
- columns << mappings::Column.new(database(:mock).adapter, nil, :one, :string, 1)
12
- columns << mappings::Column.new(database(:mock).adapter, nil, :two, :string, 2)
13
- columns << mappings::Column.new(database(:mock).adapter, nil, :three, :string, 3)
25
+
26
+ table = mappings::Table.new(database(:mock).adapter, "Cow")
27
+ columns << mappings::Column.new(database(:mock).adapter, table, :one, :string, 1)
28
+ columns << mappings::Column.new(database(:mock).adapter, table, :two, :string, 2)
29
+ columns << mappings::Column.new(database(:mock).adapter, table, :three, :string, 3)
14
30
  columns.should have(3).entries
15
31
 
16
- columns << mappings::Column.new(database(:mock).adapter, nil, :two, :integer, 3)
32
+ columns << mappings::Column.new(database(:mock).adapter, table, :two, :integer, 3)
17
33
  columns.should have(3).entries
18
34
 
19
- columns << mappings::Column.new(database(:mock).adapter, nil, :id, :integer, -1)
35
+ columns << mappings::Column.new(database(:mock).adapter, table, :id, :integer, -1)
20
36
  columns.should have(4).entries
21
37
  end
22
38
 
23
- end
39
+ it "should get its meta data from the database"
40
+
41
+ it "should be able to rename" do
42
+ table = database.table(Zoo)
43
+ name_column = table[:name]
44
+
45
+ lambda { database.query("SELECT name FROM zoos") }.should_not raise_error
46
+ lambda { database.query("SELECT moo FROM zoos") }.should raise_error
47
+
48
+ name_column.rename!(:moo).should eql(true)
49
+ name_column.name.should eql(:moo)
50
+
51
+ lambda { database.query("SELECT name FROM zoos") }.should raise_error
52
+ lambda { database.query("SELECT moo FROM zoos") }.should_not raise_error
53
+
54
+ name_column.rename!(:name)
55
+ name_column.name.should eql(:name)
56
+
57
+ lambda { database.query("SELECT name FROM zoos") }.should_not raise_error
58
+ lambda { database.query("SELECT moo FROM zoos") }.should raise_error
59
+ end
60
+
61
+ it "should create, alter and drop a column" do
62
+ lambda { database.query("SELECT moo FROM zoos") }.should raise_error
63
+
64
+ database.logger.debug { 'MOO' * 10 }
65
+
66
+ table = database.table(Zoo)
67
+ Zoo.property(:moo, :string)
68
+ moo = table[:moo]
69
+ moo.create!
70
+
71
+ lambda { database.query("SELECT moo FROM zoos") }.should_not raise_error
72
+
73
+ zoo = Zoo.create(:name => 'columns', :moo => 'AAA')
74
+ zoo.moo.should eql('AAA')
75
+
76
+ zoo.moo = 4
77
+ zoo.save
78
+ zoo.reload!
79
+ zoo.moo.should eql('4')
80
+
81
+ moo.type = :integer
82
+ moo.alter!
83
+ zoo.reload!
84
+ zoo.moo.should eql(4)
85
+
86
+ moo.drop!
87
+
88
+ Zoo.send(:undef_method, :moo)
89
+ Zoo.send(:undef_method, :moo=)
90
+
91
+ lambda { database.query("SELECT moo FROM zoos") }.should raise_error
92
+ end
93
+
94
+ it "should default the size of an integer column to 11" do
95
+ mappings = DataMapper::Adapters::Sql::Mappings
96
+ table = mappings::Table.new(database(:mock).adapter, "Zebu")
97
+ integer = mappings::Column.new(database(:mock).adapter, table, :age, :integer, 1)
98
+ integer.size.should == 11
99
+ end
100
+
101
+ end
@@ -3,9 +3,9 @@ require File.dirname(__FILE__) + "/spec_helper"
3
3
  describe DataMapper::Adapters::Sql::Commands::LoadCommand do
4
4
 
5
5
  def conditions_for(klass, options = {})
6
- session = database(:mock)
6
+ database_context = database(:mock)
7
7
  DataMapper::Adapters::Sql::Commands::LoadCommand.new(
8
- session.adapter, session, klass, options
8
+ database_context.adapter, database_context, klass, options
9
9
  ).conditions
10
10
  end
11
11
 
@@ -0,0 +1,25 @@
1
+ require File.dirname(__FILE__) + "/spec_helper"
2
+
3
+ describe DataMapper::Base do
4
+
5
+ it "should be able to add a dependency for a class not yet defined" do
6
+
7
+ $happy_cow_defined = false
8
+
9
+ DataMapper::Base.dependencies.add('HappyCow') do |klass|
10
+ klass.should eql(Object.const_get('HappyCow'))
11
+ database.table(klass).key.name.should eql(:name)
12
+ $happy_cow_defined = true
13
+ end
14
+
15
+ class HappyCow < DataMapper::Base
16
+ property :name, :string, :key => true
17
+ end
18
+
19
+ # Dependencies are not resolved until you try to access the key for a table...
20
+ database.table(HappyCow).key
21
+
22
+ raise 'Dependency not called for HappyCow :-(' unless $happy_cow_defined
23
+ end
24
+
25
+ end
@@ -18,8 +18,128 @@ describe DataMapper::EmbeddedValue do
18
18
  @bob.address.city_state_zip_code.should == 'Dallas, TX 75000'
19
19
  end
20
20
 
21
- it 'should allow you to use your own classes as well as long as they inherit from EmbeddedValue' do
22
- @bob.location.to_s.should == 'Dallas, TX'
21
+ it 'should not require prefix' do
22
+ class PointyHeadedBoss < DataMapper::Base
23
+ set_table_name 'people'
24
+ property :name, :string
25
+
26
+ embed :address do
27
+ # don't provide a prefix option to embed
28
+ # so the column names of these properties gets nothing auto-prepended
29
+ property :address_street, :string
30
+ property :address_city, :string
31
+ end
32
+ end
33
+
34
+ @sam = PointyHeadedBoss[:name => 'Sam']
35
+ @sam.address.address_street.should == '1337 Duck Way'
36
+ end
37
+
38
+ it 'should add convenience methods to the non-embedded base' do
39
+ class Employee < DataMapper::Base
40
+ set_table_name 'people'
41
+ property :name, :string
42
+
43
+ embed :address, :prefix => true do
44
+ property :street, :string
45
+ property :city, :string
46
+ end
47
+ end
48
+
49
+ @sam = Employee[:name => 'Sam']
50
+ @sam.address_street.should == '1337 Duck Way'
23
51
  end
52
+
53
+ it 'should support lazy loading of embedded properties' do
54
+ class Human < DataMapper::Base
55
+ set_table_name 'people'
56
+ property :name, :string
57
+
58
+ embed :address, :lazy => true, :prefix => true do
59
+ property :street, :string
60
+ property :city, :string
61
+ end
62
+ end
63
+
64
+ @sam = Human[:name => 'Sam']
65
+ @sam.address.street.should == '1337 Duck Way'
66
+ end
67
+
68
+ it 'should default to public method visibility for all' do
69
+ class SoftwareEngineer < DataMapper::Base
70
+ set_table_name 'people'
71
+ property :name, :string
72
+
73
+ embed :address, :prefix => true do
74
+ property :city, :string
75
+ end
76
+ end
77
+
78
+ @sam = SoftwareEngineer[:name => 'Sam']
79
+ public_properties = @sam.address.class.public_instance_methods.select { |m| ["city", "city="].include?(m) }
80
+ public_properties.length.should == 2
81
+ end
82
+
83
+ it 'should respect protected property options for all' do
84
+ class SanitationEngineer < DataMapper::Base
85
+ set_table_name 'people'
86
+ property :name, :string
87
+
88
+ embed :address, :reader => :protected, :prefix => true do
89
+ property :city, :string
90
+ property :street, :string
91
+ end
92
+ end
93
+
94
+ @sam = SanitationEngineer[:name => 'Sam']
95
+ protected_properties = @sam.address.class.protected_instance_methods.select { |m| ["city", "street"].include?(m) }
96
+ protected_properties.length.should == 2
97
+ end
98
+
99
+ it 'should respect private property options for all' do
100
+ class ElectricalEngineer < DataMapper::Base
101
+ set_table_name 'people'
102
+ property :name, :string, :reader => :private
103
+
104
+ embed :address, :writer => :private, :prefix => true do
105
+ property :city, :string
106
+ property :street, :string
107
+ end
108
+ end
109
+
110
+ @sam = ElectricalEngineer[:name => 'Sam']
111
+ private_properties = @sam.address.class.private_instance_methods.select { |m| ["city=", "street="].include?(m) }
112
+ private_properties.length.should == 2
113
+ end
114
+
115
+ it 'should set both reader and writer visibiliy for all when accessor option is passed' do
116
+ class TrainEngineer < DataMapper::Base
117
+ set_table_name 'people'
118
+ property :name, :string, :reader => :private
24
119
 
25
- end
120
+ embed :address, :accessor => :private, :prefix => true do
121
+ property :city, :string
122
+ end
123
+ end
124
+
125
+ @sam = TrainEngineer[:name => 'Sam']
126
+ private_properties = @sam.address.class.private_instance_methods.select { |m| ["city", "city="].include?(m) }
127
+ private_properties.length.should == 2
128
+ end
129
+
130
+ it 'should allow individual properties to override method visibility options passed on the block' do
131
+ class ChemicalEngineer < DataMapper::Base
132
+ set_table_name 'people'
133
+ property :name, :string
134
+
135
+ embed :address, :accessor => :private, :prefix => true do
136
+ property :city, :string
137
+ property :street, :string, :accessor => :public
138
+ end
139
+ end
140
+
141
+ @sam = ChemicalEngineer[:name => 'Sam']
142
+ public_properties = @sam.address.class.public_instance_methods.select { |m| ["street", "street="].include?(m) }
143
+ public_properties.length.should == 2
144
+ end
145
+ end
@@ -22,6 +22,7 @@
22
22
  notes: I am a Whale!
23
23
  - name: Dolphin
24
24
  notes: I am a Dolphin!
25
+ nice: true
25
26
  - name: Mouse
26
27
  notes: I am a Mouse!
27
28
  - name: Rat
@@ -0,0 +1,5 @@
1
+ ---
2
+ - name: Programmer
3
+ - name: Business Analyst Manager
4
+ - name: Peon
5
+ - name: Supervisor
@@ -0,0 +1 @@
1
+ --- []
@@ -2,31 +2,36 @@
2
2
  age: 29
3
3
  occupation: Programmer
4
4
  type: Person
5
- street: 1337 Duck Way
6
- city: Galveston
7
- state: TX
8
- zip_code: "75000"
5
+ address_street: 1337 Duck Way
6
+ address_city: Galveston
7
+ adresss_state: TX
8
+ address_zip_code: "75000"
9
9
  notes:
10
10
  date_of_birth: 2007-10-24
11
+ career_name: Programmer
11
12
  - name: Amy
12
13
  age: 28
13
14
  occupation: Business Analyst Manager
14
15
  type: Person
16
+ career_name: Business Analyst Manager
15
17
  - name: Scott
16
18
  age: 25
17
19
  occupation: Programmer
18
20
  type: SalesPerson
19
21
  commission: 172
22
+ career_name: Programmer
20
23
  - name: Josh
21
24
  age: 23
22
25
  occupation: Supervisor
23
26
  type:
27
+ career_name: Supervisor
24
28
  - name: Bob
25
29
  age: 29
26
30
  occupation: Peon
27
- street: 123 Happy Ln.
28
- city: Dallas
29
- state: TX
30
- zip_code: 75000
31
+ address_street: 123 Happy Ln.
32
+ address_city: Dallas
33
+ address_state: TX
34
+ address_zip_code: 75000
31
35
  type: SalesPerson
32
- commission: 40
36
+ commission: 40
37
+ career_name: Peon
@@ -0,0 +1,4 @@
1
+ ---
2
+ - id: 1
3
+ title: Test
4
+ description:
@@ -0,0 +1,5 @@
1
+ ---
2
+ - id: 1
3
+ title: Main
4
+ created_at: 2007-12-08T11:31:08-06:00
5
+ project_id: 1
@@ -0,0 +1,6 @@
1
+ ---
2
+ - id: 1
3
+ content:
4
+ :second: dos
5
+ :first: 1
6
+ :third: 3.0
@@ -0,0 +1 @@
1
+ --- []
@@ -4,11 +4,12 @@ describe DataMapper::Adapters::Sql::Commands::LoadCommand do
4
4
 
5
5
  before(:all) do
6
6
  fixtures(:zoos)
7
+ fixtures(:animals)
7
8
  end
8
9
 
9
10
  def loader_for(klass, options = {})
10
- session = database(:mock)
11
- DataMapper::Adapters::Sql::Commands::LoadCommand.new(session.adapter, session, klass, options)
11
+ database_context = database(:mock)
12
+ DataMapper::Adapters::Sql::Commands::LoadCommand.new(database_context.adapter, database_context, klass, options)
12
13
  end
13
14
 
14
15
  it "should return a Struct for custom queries" do
@@ -41,7 +42,7 @@ describe DataMapper::Adapters::Sql::Commands::LoadCommand do
41
42
 
42
43
  it "should join has and belongs to many associtions in the statement" do
43
44
  loader_for(Animal, :include => :exhibits).to_parameterized_sql.first.should == <<-EOS.compress_lines
44
- SELECT `animals`.`id`, `animals`.`name`,
45
+ SELECT `animals`.`id`, `animals`.`name`, `animals`.`nice`,
45
46
  `exhibits`.`id`, `exhibits`.`name`, `exhibits`.`zoo_id`,
46
47
  `animals_exhibits`.`animal_id`, `animals_exhibits`.`exhibit_id`
47
48
  FROM `animals`
@@ -52,7 +53,7 @@ describe DataMapper::Adapters::Sql::Commands::LoadCommand do
52
53
 
53
54
  it "should shallow-join unmapped tables for has-and-belongs-to-many in the statement" do
54
55
  loader_for(Animal, :shallow_include => :exhibits).to_parameterized_sql.first.should == <<-EOS.compress_lines
55
- SELECT `animals`.`id`, `animals`.`name`,
56
+ SELECT `animals`.`id`, `animals`.`name`, `animals`.`nice`,
56
57
  `animals_exhibits`.`animal_id`, `animals_exhibits`.`exhibit_id`
57
58
  FROM `animals`
58
59
  JOIN `animals_exhibits` ON `animals_exhibits`.`animal_id` = `animals`.`id`
data/spec/mock_adapter.rb CHANGED
@@ -7,10 +7,10 @@ class MockAdapter < DataMapper::Adapters::DataObjectAdapter
7
7
  def delete(instance_or_klass, options = nil)
8
8
  end
9
9
 
10
- def save(session, instance)
10
+ def save(database_context, instance)
11
11
  end
12
12
 
13
- def load(session, klass, options)
13
+ def load(database_context, klass, options)
14
14
  end
15
15
 
16
16
  def table_exists?(name)
@@ -1,6 +1,7 @@
1
1
  class Animal < DataMapper::Base
2
- property :name, :string
2
+ property :name, :string, :default => "No Name"
3
3
  property :notes, :text
4
+ property :nice, :boolean
4
5
 
5
6
  has_one :favourite_fruit, :class => 'Fruit', :foreign_key => 'devourer_id'
6
7
  has_and_belongs_to_many :exhibits
@@ -1,6 +1,6 @@
1
1
  # This is just here to get around the fact I use a Class to load
2
2
  # fixtures right now.
3
3
  class AnimalsExhibit < DataMapper::Base
4
- property :animal_id, :integer, :key => true, :serial => false
5
- property :exhibit_id, :integer
4
+ property :animal_id, :integer, :key => true
5
+ property :exhibit_id, :integer, :key => true
6
6
  end
@@ -0,0 +1,6 @@
1
+ class Career < DataMapper::Base
2
+
3
+ property :name, :string, :key => true
4
+
5
+ has_many :followers, :class => 'Person'
6
+ end
@@ -0,0 +1,4 @@
1
+ class Comment < DataMapper::Base
2
+ property :comment, :text, :lazy => false
3
+ belongs_to :author, :class => 'User', :foreign_key => 'user_id'
4
+ end
@@ -1,7 +1,11 @@
1
1
  class Exhibit < DataMapper::Base
2
2
  property :name, :string
3
3
 
4
+ begin
4
5
  validates_presence_of :name
6
+ rescue ArgumentError => e
7
+ throw e unless e.message =~ /specify a unique key/
8
+ end
5
9
 
6
10
  belongs_to :zoo
7
11
  has_and_belongs_to_many :animals