datamapper 0.2.3 → 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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