datamapper 0.2.0 → 0.2.1

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