datamapper 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +20 -1
- data/environment.rb +5 -3
- data/lib/data_mapper.rb +42 -23
- data/lib/data_mapper/adapters/data_object_adapter.rb +76 -73
- data/lib/data_mapper/adapters/mysql_adapter.rb +15 -1
- data/lib/data_mapper/adapters/postgresql_adapter.rb +1 -1
- data/lib/data_mapper/adapters/sql/commands/load_command.rb +242 -28
- data/lib/data_mapper/adapters/sql/mappings/column.rb +18 -1
- data/lib/data_mapper/adapters/sql/mappings/table.rb +20 -32
- data/lib/data_mapper/adapters/sql/quoting.rb +40 -7
- data/lib/data_mapper/adapters/sqlite3_adapter.rb +7 -1
- data/lib/data_mapper/associations/has_and_belongs_to_many_association.rb +6 -1
- data/lib/data_mapper/associations/has_many_association.rb +1 -1
- data/lib/data_mapper/context.rb +4 -2
- data/lib/data_mapper/database.rb +2 -12
- data/lib/data_mapper/support/active_record_impersonation.rb +1 -1
- data/lib/data_mapper/support/blank.rb +2 -2
- data/lib/data_mapper/support/serialization.rb +60 -4
- data/lib/data_mapper/support/string.rb +24 -2
- data/lib/data_mapper/validations/validation_errors.rb +6 -3
- data/performance.rb +20 -5
- data/plugins/dataobjects/Rakefile +2 -0
- data/plugins/dataobjects/do.rb +18 -8
- data/plugins/dataobjects/do_mysql.rb +57 -24
- data/plugins/dataobjects/do_postgres.rb +3 -7
- data/plugins/dataobjects/do_sqlite3.rb +18 -17
- data/plugins/dataobjects/swig_mysql/Makefile +146 -0
- data/plugins/dataobjects/swig_mysql/extconf.rb +13 -1
- data/plugins/dataobjects/swig_mysql/mkmf.log +24 -0
- data/plugins/dataobjects/swig_mysql/mysql_c.bundle +0 -0
- data/plugins/dataobjects/swig_mysql/mysql_c.c +303 -2501
- data/plugins/dataobjects/swig_mysql/mysql_c.i +63 -4
- data/plugins/dataobjects/swig_mysql/mysql_c.o +0 -0
- data/profile_data_mapper.rb +4 -4
- data/rakefile.rb +13 -7
- data/spec/acts_as_tree_spec.rb +2 -0
- data/spec/associations_spec.rb +12 -0
- data/spec/attributes_spec.rb +2 -0
- data/spec/base_spec.rb +2 -0
- data/spec/callbacks_spec.rb +2 -0
- data/spec/can_has_sphinx.rb +0 -1
- data/spec/coersion_spec.rb +10 -3
- data/spec/column_spec.rb +23 -0
- data/spec/conditions_spec.rb +18 -18
- data/spec/count_command_spec.rb +2 -0
- data/spec/dataobjects_spec.rb +26 -0
- data/spec/delete_command_spec.rb +2 -0
- data/spec/embedded_value_spec.rb +2 -0
- data/spec/fixtures/people.yaml +1 -1
- data/spec/fixtures/posts.yaml +3 -0
- data/spec/legacy_spec.rb +2 -0
- data/spec/load_command_spec.rb +28 -2
- data/spec/magic_columns_spec.rb +2 -0
- data/spec/models/person.rb +1 -1
- data/spec/models/post.rb +8 -0
- data/spec/query_spec.rb +2 -0
- data/spec/save_command_spec.rb +2 -0
- data/spec/schema_spec.rb +2 -0
- data/spec/serialization_spec.rb +58 -0
- data/spec/single_table_inheritance_spec.rb +2 -0
- data/spec/symbolic_operators_spec.rb +2 -0
- data/spec/validates_confirmation_of_spec.rb +2 -0
- data/spec/validates_format_of_spec.rb +2 -0
- data/spec/validates_length_of_spec.rb +2 -0
- data/spec/validates_uniqueness_of_spec.rb +2 -0
- data/spec/validations_spec.rb +2 -0
- data/tasks/fixtures.rb +15 -10
- metadata +10 -13
- data/lib/data_mapper/adapters/sql/commands/conditions.rb +0 -130
- data/lib/data_mapper/adapters/sql/commands/loader.rb +0 -99
- data/plugins/dataobjects/swig_mysql/do_mysql.bundle +0 -0
- 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
|
-
%
|
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
|
+
};
|
Binary file
|
data/profile_data_mapper.rb
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
#!/opt/local/bin/ruby
|
2
2
|
|
3
|
-
|
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
|
-
|
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
|
data/rakefile.rb
CHANGED
@@ -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 = [
|
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.
|
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
|
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(
|
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 =
|
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|
|
data/spec/acts_as_tree_spec.rb
CHANGED
data/spec/associations_spec.rb
CHANGED
@@ -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']
|
data/spec/attributes_spec.rb
CHANGED
data/spec/base_spec.rb
CHANGED
data/spec/callbacks_spec.rb
CHANGED
data/spec/can_has_sphinx.rb
CHANGED
data/spec/coersion_spec.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
data/spec/column_spec.rb
ADDED
@@ -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
|
data/spec/conditions_spec.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
|
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').
|
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').
|
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
|
-
|
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).
|
25
|
-
conditions_for(Person, :age.gte => 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).
|
28
|
-
conditions_for(Person, :age.lte => 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).
|
31
|
-
conditions_for(Person, :age.eql => 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%').
|
34
|
+
conditions_for(Person, :name.like => 'S%').should eql([["`name` LIKE ?", 'S%']])
|
34
35
|
|
35
|
-
conditions_for(Person, :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
|
-
|
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').
|
45
|
-
conditions_for(Person, :name.not => nil).
|
46
|
-
conditions_for(Person, :name.not => ['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
|
data/spec/count_command_spec.rb
CHANGED
@@ -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
|
data/spec/delete_command_spec.rb
CHANGED
data/spec/embedded_value_spec.rb
CHANGED
data/spec/fixtures/people.yaml
CHANGED
data/spec/legacy_spec.rb
CHANGED
data/spec/load_command_spec.rb
CHANGED
@@ -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:
|
162
|
-
Zoo.first(:name.like => '%
|
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
|
|