datamapper 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. data/CHANGELOG +20 -1
  2. data/environment.rb +5 -3
  3. data/lib/data_mapper.rb +42 -23
  4. data/lib/data_mapper/adapters/data_object_adapter.rb +76 -73
  5. data/lib/data_mapper/adapters/mysql_adapter.rb +15 -1
  6. data/lib/data_mapper/adapters/postgresql_adapter.rb +1 -1
  7. data/lib/data_mapper/adapters/sql/commands/load_command.rb +242 -28
  8. data/lib/data_mapper/adapters/sql/mappings/column.rb +18 -1
  9. data/lib/data_mapper/adapters/sql/mappings/table.rb +20 -32
  10. data/lib/data_mapper/adapters/sql/quoting.rb +40 -7
  11. data/lib/data_mapper/adapters/sqlite3_adapter.rb +7 -1
  12. data/lib/data_mapper/associations/has_and_belongs_to_many_association.rb +6 -1
  13. data/lib/data_mapper/associations/has_many_association.rb +1 -1
  14. data/lib/data_mapper/context.rb +4 -2
  15. data/lib/data_mapper/database.rb +2 -12
  16. data/lib/data_mapper/support/active_record_impersonation.rb +1 -1
  17. data/lib/data_mapper/support/blank.rb +2 -2
  18. data/lib/data_mapper/support/serialization.rb +60 -4
  19. data/lib/data_mapper/support/string.rb +24 -2
  20. data/lib/data_mapper/validations/validation_errors.rb +6 -3
  21. data/performance.rb +20 -5
  22. data/plugins/dataobjects/Rakefile +2 -0
  23. data/plugins/dataobjects/do.rb +18 -8
  24. data/plugins/dataobjects/do_mysql.rb +57 -24
  25. data/plugins/dataobjects/do_postgres.rb +3 -7
  26. data/plugins/dataobjects/do_sqlite3.rb +18 -17
  27. data/plugins/dataobjects/swig_mysql/Makefile +146 -0
  28. data/plugins/dataobjects/swig_mysql/extconf.rb +13 -1
  29. data/plugins/dataobjects/swig_mysql/mkmf.log +24 -0
  30. data/plugins/dataobjects/swig_mysql/mysql_c.bundle +0 -0
  31. data/plugins/dataobjects/swig_mysql/mysql_c.c +303 -2501
  32. data/plugins/dataobjects/swig_mysql/mysql_c.i +63 -4
  33. data/plugins/dataobjects/swig_mysql/mysql_c.o +0 -0
  34. data/profile_data_mapper.rb +4 -4
  35. data/rakefile.rb +13 -7
  36. data/spec/acts_as_tree_spec.rb +2 -0
  37. data/spec/associations_spec.rb +12 -0
  38. data/spec/attributes_spec.rb +2 -0
  39. data/spec/base_spec.rb +2 -0
  40. data/spec/callbacks_spec.rb +2 -0
  41. data/spec/can_has_sphinx.rb +0 -1
  42. data/spec/coersion_spec.rb +10 -3
  43. data/spec/column_spec.rb +23 -0
  44. data/spec/conditions_spec.rb +18 -18
  45. data/spec/count_command_spec.rb +2 -0
  46. data/spec/dataobjects_spec.rb +26 -0
  47. data/spec/delete_command_spec.rb +2 -0
  48. data/spec/embedded_value_spec.rb +2 -0
  49. data/spec/fixtures/people.yaml +1 -1
  50. data/spec/fixtures/posts.yaml +3 -0
  51. data/spec/legacy_spec.rb +2 -0
  52. data/spec/load_command_spec.rb +28 -2
  53. data/spec/magic_columns_spec.rb +2 -0
  54. data/spec/models/person.rb +1 -1
  55. data/spec/models/post.rb +8 -0
  56. data/spec/query_spec.rb +2 -0
  57. data/spec/save_command_spec.rb +2 -0
  58. data/spec/schema_spec.rb +2 -0
  59. data/spec/serialization_spec.rb +58 -0
  60. data/spec/single_table_inheritance_spec.rb +2 -0
  61. data/spec/symbolic_operators_spec.rb +2 -0
  62. data/spec/validates_confirmation_of_spec.rb +2 -0
  63. data/spec/validates_format_of_spec.rb +2 -0
  64. data/spec/validates_length_of_spec.rb +2 -0
  65. data/spec/validates_uniqueness_of_spec.rb +2 -0
  66. data/spec/validations_spec.rb +2 -0
  67. data/tasks/fixtures.rb +15 -10
  68. metadata +10 -13
  69. data/lib/data_mapper/adapters/sql/commands/conditions.rb +0 -130
  70. data/lib/data_mapper/adapters/sql/commands/loader.rb +0 -99
  71. data/plugins/dataobjects/swig_mysql/do_mysql.bundle +0 -0
  72. data/spec/conversions_to_yaml_spec.rb +0 -17
@@ -1,8 +1,67 @@
1
1
  %module mysql_c
2
2
  %{
3
- #include <mysql.h>
4
- #include <errmsg.h>
5
- #include <mysqld_error.h>
3
+ #include <mysql.h>
4
+ #include <errmsg.h>
5
+ #include <mysqld_error.h>
6
+
7
+ VALUE mysql_c_fetch_field_names(MYSQL_RES *reader, int count) {
8
+ VALUE arr = rb_ary_new();
9
+ int i;
10
+ for(i = 0; i < count; i++) {
11
+ rb_ary_push(arr, rb_str_new2(mysql_fetch_field_direct(reader, i)->name));
12
+ }
13
+ return arr;
14
+ }
15
+
16
+ VALUE mysql_c_fetch_field_types(MYSQL_RES *reader, int count) {
17
+ VALUE arr = rb_ary_new();
18
+ int i;
19
+ for(i = 0; i < count; i++) {
20
+ rb_ary_push(arr, INT2NUM(mysql_fetch_field_direct(reader, i)->type));
21
+ }
22
+ return arr;
23
+ }
24
+
25
+ VALUE mysql_c_fetch_row(MYSQL_RES *reader) {
26
+ VALUE arr = rb_ary_new();
27
+ MYSQL_ROW result = (MYSQL_ROW)mysql_fetch_row(reader);
28
+ if(!result) return Qnil;
29
+ int i;
30
+
31
+ for(i = 0; i < reader->field_count; i++) {
32
+ if(result[i] == NULL) rb_ary_push(arr, Qnil);
33
+ else rb_ary_push(arr, rb_str_new2(result[i]));
34
+ }
35
+ return arr;
36
+ }
37
+
6
38
  %}
7
39
 
8
- %include "/opt/local/include/mysql5/mysql/mysql.h"
40
+ %ignore st_mysql_options;
41
+ %include "/usr/local/mysql-5.0.45-osx10.4-i686/include/mysql.h"
42
+
43
+ VALUE mysql_c_fetch_field_names(MYSQL_RES *reader, int count);
44
+ VALUE mysql_c_fetch_field_types(MYSQL_RES *reader, int count);
45
+ VALUE mysql_c_fetch_row(MYSQL_RES *reader);
46
+
47
+ enum enum_field_types { MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY,
48
+ MYSQL_TYPE_SHORT, MYSQL_TYPE_LONG,
49
+ MYSQL_TYPE_FLOAT, MYSQL_TYPE_DOUBLE,
50
+ MYSQL_TYPE_NULL, MYSQL_TYPE_TIMESTAMP,
51
+ MYSQL_TYPE_LONGLONG,MYSQL_TYPE_INT24,
52
+ MYSQL_TYPE_DATE, MYSQL_TYPE_TIME,
53
+ MYSQL_TYPE_DATETIME, MYSQL_TYPE_YEAR,
54
+ MYSQL_TYPE_NEWDATE, MYSQL_TYPE_VARCHAR,
55
+ MYSQL_TYPE_BIT,
56
+ MYSQL_TYPE_NEWDECIMAL=246,
57
+ MYSQL_TYPE_ENUM=247,
58
+ MYSQL_TYPE_SET=248,
59
+ MYSQL_TYPE_TINY_BLOB=249,
60
+ MYSQL_TYPE_MEDIUM_BLOB=250,
61
+ MYSQL_TYPE_LONG_BLOB=251,
62
+ MYSQL_TYPE_BLOB=252,
63
+ MYSQL_TYPE_VAR_STRING=253,
64
+ MYSQL_TYPE_STRING=254,
65
+ MYSQL_TYPE_GEOMETRY=255
66
+
67
+ };
@@ -1,8 +1,6 @@
1
1
  #!/opt/local/bin/ruby
2
2
 
3
- ENV['LOGGER'] = 'false'
4
-
5
- require 'example'
3
+ require 'environment'
6
4
  require 'ruby-prof'
7
5
 
8
6
  # RubyProf, making profiling Ruby pretty since 1899!
@@ -17,10 +15,12 @@ end
17
15
 
18
16
  profile do
19
17
  1000.times do
20
- Zoo.all
18
+ database.query("SELECT * FROM zoos")
21
19
  end
22
20
  end
23
21
 
22
+ puts "Done!"
23
+
24
24
  # require 'benchmark'
25
25
  #
26
26
  # N = 100_000
@@ -10,6 +10,8 @@ Dir[File.dirname(__FILE__) + '/tasks/*'].each { |t| require(t) }
10
10
 
11
11
  task :default => 'dm:spec'
12
12
 
13
+ task :environment => 'dm:environment'
14
+
13
15
  namespace :dm do
14
16
 
15
17
  desc "Setup Environment"
@@ -19,10 +21,10 @@ namespace :dm do
19
21
 
20
22
  desc "Run specifications"
21
23
  Spec::Rake::SpecTask.new('spec') do |t|
22
- t.spec_opts = [ '-rspec/spec_helper' ]
24
+ t.spec_opts = ["--format", "specdoc", "--colour"]
23
25
  t.spec_files = FileList[(ENV['FILES'] || 'spec/**/*_spec.rb')]
24
26
  end
25
-
27
+
26
28
  desc "Run comparison with ActiveRecord"
27
29
  task :perf do
28
30
  load 'performance.rb'
@@ -35,7 +37,7 @@ namespace :dm do
35
37
 
36
38
  end
37
39
 
38
- PACKAGE_VERSION = '0.2.0'
40
+ PACKAGE_VERSION = '0.2.1'
39
41
 
40
42
  PACKAGE_FILES = FileList[
41
43
  'README',
@@ -48,10 +50,14 @@ PACKAGE_FILES = FileList[
48
50
  'plugins/**/*'
49
51
  ].to_a
50
52
 
53
+ DOCUMENTED_FILES = PACKAGE_FILES.reject do |path|
54
+ FileTest.directory?(path) || path =~ /(^spec|\/spec|\/swig\_)/
55
+ end
56
+
51
57
  PROJECT = 'datamapper'
52
58
 
53
59
  task :ls do
54
- p PACKAGE_FILES.reject { |path| path =~ /(^spec|\/spec|\/swig\_)/ }.sort
60
+ p DOCUMENTED_FILES
55
61
  end
56
62
 
57
63
  desc "Generate Documentation"
@@ -59,7 +65,7 @@ rd = Rake::RDocTask.new do |rdoc|
59
65
  rdoc.rdoc_dir = 'doc'
60
66
  rdoc.title = "DataMapper -- An Object/Relational Mapper for Ruby"
61
67
  rdoc.options << '--line-numbers' << '--inline-source' << '--main' << 'README'
62
- rdoc.rdoc_files.include(PACKAGE_FILES.reject { |path| path =~ /(^spec|\/spec|\/swig\_)/ })
68
+ rdoc.rdoc_files.include(*DOCUMENTED_FILES)
63
69
  end
64
70
 
65
71
  gem_spec = Gem::Specification.new do |s|
@@ -82,8 +88,8 @@ gem_spec = Gem::Specification.new do |s|
82
88
  s.add_dependency('fastthread')
83
89
 
84
90
  s.has_rdoc = true
85
- s.rdoc_options << '--line-numbers' << '--inline-source' << '--main' << 'README'
86
- s.extra_rdoc_files = PACKAGE_FILES.reject { |path| path =~ /(^spec|\/spec|\/swig\_)/ }.to_a
91
+ s.rdoc_options << '--line-numbers' << '--inline-source' << '--main' << 'README'
92
+ s.extra_rdoc_files = DOCUMENTED_FILES
87
93
  end
88
94
 
89
95
  Rake::GemPackageTask.new(gem_spec) do |p|
@@ -1,3 +1,5 @@
1
+ require File.dirname(__FILE__) + "/spec_helper"
2
+
1
3
  describe('A tree') do
2
4
 
3
5
  before(:all) do
@@ -1,3 +1,5 @@
1
+ require File.dirname(__FILE__) + "/spec_helper"
2
+
1
3
  describe DataMapper::Associations::BelongsToAssociation do
2
4
  before(:each) do
3
5
  @aviary = Exhibit[:name => 'Monkey Mayhem']
@@ -64,6 +66,16 @@ describe DataMapper::Associations::HasManyAssociation do
64
66
  @zoo.destroy!
65
67
  end
66
68
 
69
+ it "should return an empty Enumerable for new objects" do
70
+ project = Project.new
71
+ project.sections.should be_a_kind_of(Enumerable)
72
+ project.sections.should be_empty
73
+ end
74
+
75
+ it "should display correctly when inspected" do
76
+ Zoo.first(:name => 'Dallas').exhibits.inspect.should match(/\#\<Exhibit\:0x.{7}/)
77
+ end
78
+
67
79
  it 'should lazily-load the association when Enumerable methods are called' do
68
80
  database do |db|
69
81
  san_diego = Zoo[:name => 'San Diego']
@@ -1,3 +1,5 @@
1
+ require File.dirname(__FILE__) + "/spec_helper"
2
+
1
3
  describe DataMapper::Base do
2
4
 
3
5
  it 'should allow mass-assignment of attributes' do
@@ -1,3 +1,5 @@
1
+ require File.dirname(__FILE__) + "/spec_helper"
2
+
1
3
  describe DataMapper::Base do
2
4
 
3
5
  it "attributes method should load all lazy-loaded values" do
@@ -1,3 +1,5 @@
1
+ require File.dirname(__FILE__) + "/spec_helper"
2
+
1
3
  describe DataMapper::Callbacks do
2
4
 
3
5
  it "should allow for a callback to be set, then called" do
@@ -1,6 +1,5 @@
1
1
  require File.dirname(__FILE__) + '/spec_helper'
2
2
 
3
-
4
3
  describe DataMapper::Plugins::CanHasSphinx do
5
4
 
6
5
  end
@@ -1,3 +1,5 @@
1
+ require File.dirname(__FILE__) + "/spec_helper"
2
+
1
3
  describe DataMapper::Adapters::Sql::Coersion do
2
4
 
3
5
  before(:all) do
@@ -19,7 +21,7 @@ describe DataMapper::Adapters::Sql::Coersion do
19
21
  bob2 = Person[:name => 'DateCoersionTest']
20
22
 
21
23
  bob.date_of_birth.should eql(dob)
22
- bob.date_of_birth.should eql(bob2.date_of_birth)
24
+ bob2.date_of_birth.should eql(dob)
23
25
  end
24
26
 
25
27
  it 'should cast to a Date' do
@@ -30,5 +32,10 @@ describe DataMapper::Adapters::Sql::Coersion do
30
32
  @coersive.type_cast_date(DateTime::parse('2001-1-1')).should eql(target)
31
33
  @coersive.type_cast_date(Time::parse('2001-1-1')).should eql(target)
32
34
  end
33
-
34
- end
35
+
36
+ it 'should cast to a String' do
37
+ target = "\n\ttest\n\n\ntest\n\n"
38
+
39
+ @coersive.type_cast_text(target).should == target
40
+ end
41
+ end
@@ -0,0 +1,23 @@
1
+ require File.dirname(__FILE__) + "/spec_helper"
2
+
3
+ describe DataMapper::Adapters::Sql::Mappings::Column do
4
+
5
+ it "should be unique within a set" do
6
+
7
+ mappings = DataMapper::Adapters::Sql::Mappings
8
+
9
+ 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)
14
+ columns.should have(3).entries
15
+
16
+ columns << mappings::Column.new(database(:mock).adapter, nil, :two, :integer, 3)
17
+ columns.should have(3).entries
18
+
19
+ columns << mappings::Column.new(database(:mock).adapter, nil, :id, :integer, -1)
20
+ columns.should have(4).entries
21
+ end
22
+
23
+ end
@@ -1,4 +1,6 @@
1
- describe DataMapper::Adapters::Sql::Commands::Conditions do
1
+ require File.dirname(__FILE__) + "/spec_helper"
2
+
3
+ describe DataMapper::Adapters::Sql::Commands::LoadCommand do
2
4
 
3
5
  def conditions_for(klass, options = {})
4
6
  session = database(:mock)
@@ -8,42 +10,40 @@ describe DataMapper::Adapters::Sql::Commands::Conditions do
8
10
  end
9
11
 
10
12
  it 'empty? should be false if conditions are present' do
11
- conditions_for(Zoo, :name => 'Galveston').empty?.should == false
13
+ conditions_for(Zoo, :name => 'Galveston').should_not be_empty
12
14
  end
13
15
 
14
16
  it 'should map implicit option names to field names' do
15
- conditions_for(Zoo, :name => 'Galveston').to_parameterized_sql.should == ["(`name` = ?)", 'Galveston']
17
+ conditions_for(Zoo, :name => 'Galveston').should eql([["`name` = ?", 'Galveston']])
16
18
  end
17
19
 
18
20
  it 'should qualify with table name when using a join' do
19
- conditions = conditions_for(Zoo, :name => 'Galveston', :include => :exhibits)
20
- conditions.to_parameterized_sql.should == ["(`zoos`.`name` = ?)", 'Galveston']
21
+ conditions_for(Zoo, :name => 'Galveston', :include => :exhibits).should eql([["`zoos`.`name` = ?", 'Galveston']])
21
22
  end
22
23
 
23
24
  it 'should use Symbol::Operator to determine operator' do
24
- conditions_for(Person, :age.gt => 28).to_parameterized_sql.should == ["(`age` > ?)", 28]
25
- conditions_for(Person, :age.gte => 28).to_parameterized_sql.should == ["(`age` >= ?)", 28]
25
+ conditions_for(Person, :age.gt => 28).should eql([["`age` > ?", 28]])
26
+ conditions_for(Person, :age.gte => 28).should eql([["`age` >= ?", 28]])
26
27
 
27
- conditions_for(Person, :age.lt => 28).to_parameterized_sql.should == ["(`age` < ?)", 28]
28
- conditions_for(Person, :age.lte => 28).to_parameterized_sql.should == ["(`age` <= ?)", 28]
28
+ conditions_for(Person, :age.lt => 28).should eql([["`age` < ?", 28]])
29
+ conditions_for(Person, :age.lte => 28).should eql([["`age` <= ?", 28]])
29
30
 
30
- conditions_for(Person, :age.not => 28).to_parameterized_sql.should == ["(`age` <> ?)", 28]
31
- conditions_for(Person, :age.eql => 28).to_parameterized_sql.should == ["(`age` = ?)", 28]
31
+ conditions_for(Person, :age.not => 28).should eql([["`age` <> ?", 28]])
32
+ conditions_for(Person, :age.eql => 28).should eql([["`age` = ?", 28]])
32
33
 
33
- conditions_for(Person, :name.like => 'S%').to_parameterized_sql.should == ["(`name` LIKE ?)", 'S%']
34
+ conditions_for(Person, :name.like => 'S%').should eql([["`name` LIKE ?", 'S%']])
34
35
 
35
- conditions_for(Person, :age.in => [ 28, 29 ]).to_parameterized_sql.should == ["(`age` IN ?)", [ 28, 29 ]]
36
+ conditions_for(Person, :age.in => [ 28, 29 ]).should eql([["`age` IN ?", [ 28, 29 ]]])
36
37
  end
37
38
 
38
39
  it 'should use an IN clause for an Array' do
39
- conditions = conditions_for(Person, :age => [ 28, 29 ])
40
- conditions.to_parameterized_sql.should == ["(`age` IN ?)", [ 28, 29 ]]
40
+ conditions_for(Person, :age => [ 28, 29 ]).should eql([["`age` IN ?", [ 28, 29 ]]])
41
41
  end
42
42
 
43
43
  it 'should use "not" for not-equal operations' do
44
- conditions_for(Person, :name.not => 'Bob').to_parameterized_sql.should == ["(`name` <> ?)", 'Bob']
45
- conditions_for(Person, :name.not => nil).to_parameterized_sql.should == ["(`name` IS NOT ?)", nil]
46
- conditions_for(Person, :name.not => ['Sam', 'Bob']).to_parameterized_sql.should == ["(`name` NOT IN ?)", ['Sam', 'Bob']]
44
+ conditions_for(Person, :name.not => 'Bob').should eql([["`name` <> ?", 'Bob']])
45
+ conditions_for(Person, :name.not => nil).should eql([["`name` IS NOT ?", nil]])
46
+ conditions_for(Person, :name.not => ['Sam', 'Bob']).should eql([["`name` NOT IN ?", ['Sam', 'Bob']]])
47
47
  end
48
48
 
49
49
  end
@@ -1,3 +1,5 @@
1
+ require File.dirname(__FILE__) + "/spec_helper"
2
+
1
3
  describe DataMapper::Adapters::AbstractAdapter do
2
4
 
3
5
  before(:all) do
@@ -0,0 +1,26 @@
1
+ require File.dirname(__FILE__) + "/spec_helper"
2
+
3
+ describe DataObject do
4
+
5
+ # These specs only fail in MySQL because:
6
+ # 1) An insert happened in the previous connection
7
+ # 2) We are searching for NULL
8
+ #
9
+ # It turns out that this is actually by design o.O:
10
+ # http://dev.mysql.com/doc/refman/5.0/en/myodbc-usagenotes-functionality.html
11
+ #
12
+ # Certain ODBC applications (including Delphi and Access) may have trouble
13
+ # obtaining the auto-increment value using the previous examples. In this case,
14
+ # try the following statement as an alternative:
15
+ # SELECT * FROM tbl WHERE auto IS NULL;
16
+ it "should return an empty reader" do
17
+ database.adapter.connection do |connection|
18
+ command = connection.create_command('SELECT `id`, `name` FROM `zoos` WHERE (`id` IS NULL)')
19
+
20
+ command.execute_reader do |reader|
21
+ reader.has_rows?.should eql(ENV['ADAPTER'] == 'mysql')
22
+ end
23
+ end
24
+ end
25
+
26
+ end
@@ -1,3 +1,5 @@
1
+ require File.dirname(__FILE__) + "/spec_helper"
2
+
1
3
  describe "Delete Command" do
2
4
 
3
5
  it "should drop and create the table" do
@@ -1,3 +1,5 @@
1
+ require File.dirname(__FILE__) + "/spec_helper"
2
+
1
3
  describe DataMapper::EmbeddedValue do
2
4
 
3
5
  before(:all) do
@@ -7,7 +7,7 @@
7
7
  state: TX
8
8
  zip_code: "75000"
9
9
  notes:
10
- date_of_birth: 2007-10-24T22:48:51-05:00
10
+ date_of_birth: 2007-10-24
11
11
  - name: Amy
12
12
  age: 28
13
13
  occupation: Business Analyst Manager
@@ -0,0 +1,3 @@
1
+ - title: One
2
+ - title: Two
3
+ - title: Three
@@ -1,3 +1,5 @@
1
+ require File.dirname(__FILE__) + "/spec_helper"
2
+
1
3
  describe 'Legacy mappings' do
2
4
 
3
5
  it('should allow models to map with custom attribute names') do
@@ -1,3 +1,5 @@
1
+ require File.dirname(__FILE__) + "/spec_helper"
2
+
1
3
  describe DataMapper::Adapters::Sql::Commands::LoadCommand do
2
4
 
3
5
  before(:all) do
@@ -158,8 +160,32 @@ describe DataMapper::Adapters::Sql::Commands::LoadCommand do
158
160
  end
159
161
 
160
162
  it "should be able to search on UTF-8 strings" do
161
- Zoo.create(:name => 'Danish Vowels: Smøøt!')
162
- Zoo.first(:name.like => '%Smøøt%').should be_a_kind_of(Zoo)
163
+ Zoo.create(:name => 'Danish Vowels: Smoot!') # øø
164
+ Zoo.first(:name.like => '%Smoot%').should be_a_kind_of(Zoo)
165
+ end
166
+
167
+ it "should destructively reload the loaded attributes of an object" do
168
+ zoo = Zoo.first(:name => 'Dallas')
169
+ zoo.name.should eql('Dallas')
170
+ zoo.name = 'bob'
171
+ zoo.name.should eql('bob')
172
+ zoo.reload!
173
+ zoo.name.should eql('Dallas')
174
+ end
175
+
176
+ # See the comment in dataobjects_spec for why this is failing
177
+ it "should return nil when finding by id, and the id is not present and/or invalid" do
178
+ Zoo.find(nil).should be_nil
179
+ end
180
+
181
+ it "should return in order" do
182
+ fixtures(:posts)
183
+
184
+ one = Post.first
185
+ one.title.should eql('One')
186
+ two = one.next
187
+ two.title.should eql('Two')
188
+ one.next.next.previous.previous.next.previous.next.next.title.should eql('Three')
163
189
  end
164
190
  end
165
191