datamapper 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +65 -0
- data/README +193 -1
- data/do_performance.rb +153 -0
- data/environment.rb +45 -0
- data/example.rb +119 -22
- data/lib/data_mapper.rb +36 -16
- data/lib/data_mapper/adapters/abstract_adapter.rb +8 -0
- data/lib/data_mapper/adapters/data_object_adapter.rb +360 -0
- data/lib/data_mapper/adapters/mysql_adapter.rb +30 -179
- data/lib/data_mapper/adapters/postgresql_adapter.rb +90 -199
- data/lib/data_mapper/adapters/sql/coersion.rb +32 -3
- data/lib/data_mapper/adapters/sql/commands/conditions.rb +97 -128
- data/lib/data_mapper/adapters/sql/commands/load_command.rb +234 -231
- data/lib/data_mapper/adapters/sql/commands/loader.rb +99 -0
- data/lib/data_mapper/adapters/sql/mappings/associations_set.rb +30 -0
- data/lib/data_mapper/adapters/sql/mappings/column.rb +68 -6
- data/lib/data_mapper/adapters/sql/mappings/schema.rb +6 -3
- data/lib/data_mapper/adapters/sql/mappings/table.rb +71 -42
- data/lib/data_mapper/adapters/sql/quoting.rb +8 -2
- data/lib/data_mapper/adapters/sqlite3_adapter.rb +32 -201
- data/lib/data_mapper/associations.rb +21 -7
- data/lib/data_mapper/associations/belongs_to_association.rb +96 -80
- data/lib/data_mapper/associations/has_and_belongs_to_many_association.rb +158 -67
- data/lib/data_mapper/associations/has_many_association.rb +96 -78
- data/lib/data_mapper/associations/has_n_association.rb +64 -0
- data/lib/data_mapper/associations/has_one_association.rb +49 -79
- data/lib/data_mapper/associations/reference.rb +47 -0
- data/lib/data_mapper/base.rb +216 -50
- data/lib/data_mapper/callbacks.rb +71 -24
- data/lib/data_mapper/{session.rb → context.rb} +20 -8
- data/lib/data_mapper/database.rb +176 -45
- data/lib/data_mapper/embedded_value.rb +65 -0
- data/lib/data_mapper/identity_map.rb +12 -4
- data/lib/data_mapper/support/active_record_impersonation.rb +12 -8
- data/lib/data_mapper/support/enumerable.rb +8 -0
- data/lib/data_mapper/support/serialization.rb +13 -0
- data/lib/data_mapper/support/string.rb +1 -12
- data/lib/data_mapper/support/symbol.rb +3 -0
- data/lib/data_mapper/validations/unique_validator.rb +1 -2
- data/lib/data_mapper/validations/validation_helper.rb +18 -1
- data/performance.rb +109 -34
- data/plugins/can_has_sphinx/LICENSE +23 -0
- data/plugins/can_has_sphinx/README +4 -0
- data/plugins/can_has_sphinx/REVISION +1 -0
- data/plugins/can_has_sphinx/Rakefile +22 -0
- data/plugins/can_has_sphinx/init.rb +1 -0
- data/plugins/can_has_sphinx/install.rb +1 -0
- data/plugins/can_has_sphinx/lib/acts_as_sphinx.rb +123 -0
- data/plugins/can_has_sphinx/lib/sphinx.rb +460 -0
- data/plugins/can_has_sphinx/scripts/sphinx.sh +47 -0
- data/plugins/can_has_sphinx/tasks/acts_as_sphinx_tasks.rake +41 -0
- data/plugins/dataobjects/REVISION +1 -0
- data/plugins/dataobjects/Rakefile +7 -0
- data/plugins/dataobjects/do.rb +246 -0
- data/plugins/dataobjects/do_mysql.rb +179 -0
- data/plugins/dataobjects/do_postgres.rb +181 -0
- data/plugins/dataobjects/do_sqlite3.rb +153 -0
- data/plugins/dataobjects/spec/do_spec.rb +150 -0
- data/plugins/dataobjects/spec/spec_helper.rb +81 -0
- data/plugins/dataobjects/swig_mysql/do_mysql.bundle +0 -0
- data/plugins/dataobjects/swig_mysql/extconf.rb +33 -0
- data/plugins/dataobjects/swig_mysql/mysql_c.c +18800 -0
- data/plugins/dataobjects/swig_mysql/mysql_c.i +8 -0
- data/plugins/dataobjects/swig_mysql/mysql_supp.i +46 -0
- data/plugins/dataobjects/swig_postgres/Makefile +146 -0
- data/plugins/dataobjects/swig_postgres/extconf.rb +29 -0
- data/plugins/dataobjects/swig_postgres/postgres_c.bundle +0 -0
- data/plugins/dataobjects/swig_postgres/postgres_c.c +8185 -0
- data/plugins/dataobjects/swig_postgres/postgres_c.i +73 -0
- data/plugins/dataobjects/swig_sqlite/db +0 -0
- data/plugins/dataobjects/swig_sqlite/extconf.rb +9 -0
- data/plugins/dataobjects/swig_sqlite/sqlite3_c.c +4725 -0
- data/plugins/dataobjects/swig_sqlite/sqlite_c.i +168 -0
- data/rakefile.rb +45 -23
- data/spec/acts_as_tree_spec.rb +39 -0
- data/spec/associations_spec.rb +220 -0
- data/spec/attributes_spec.rb +15 -0
- data/spec/base_spec.rb +44 -0
- data/spec/callbacks_spec.rb +45 -0
- data/spec/can_has_sphinx.rb +6 -0
- data/spec/coersion_spec.rb +34 -0
- data/spec/conditions_spec.rb +49 -0
- data/spec/conversions_to_yaml_spec.rb +17 -0
- data/spec/count_command_spec.rb +11 -0
- data/spec/delete_command_spec.rb +1 -1
- data/spec/embedded_value_spec.rb +23 -0
- data/spec/fixtures/animals_exhibits.yaml +2 -0
- data/spec/fixtures/people.yaml +18 -1
- data/spec/{legacy.rb → legacy_spec.rb} +3 -3
- data/spec/load_command_spec.rb +157 -20
- data/spec/magic_columns_spec.rb +9 -0
- data/spec/mock_adapter.rb +20 -0
- data/spec/models/animal.rb +1 -1
- data/spec/models/animals_exhibit.rb +6 -0
- data/spec/models/exhibit.rb +2 -0
- data/spec/models/person.rb +26 -1
- data/spec/models/project.rb +19 -0
- data/spec/models/sales_person.rb +1 -0
- data/spec/models/section.rb +6 -0
- data/spec/models/zoo.rb +3 -1
- data/spec/query_spec.rb +9 -0
- data/spec/save_command_spec.rb +65 -1
- data/spec/schema_spec.rb +89 -0
- data/spec/single_table_inheritance_spec.rb +27 -0
- data/spec/spec_helper.rb +9 -55
- data/spec/{symbolic_operators.rb → symbolic_operators_spec.rb} +9 -5
- data/spec/{validates_confirmation_of.rb → validates_confirmation_of_spec.rb} +4 -3
- data/spec/{validates_format_of.rb → validates_format_of_spec.rb} +5 -4
- data/spec/{validates_length_of.rb → validates_length_of_spec.rb} +8 -7
- data/spec/{validates_uniqueness_of.rb → validates_uniqueness_of_spec.rb} +7 -10
- data/spec/{validations.rb → validations_spec.rb} +24 -6
- data/tasks/drivers.rb +20 -0
- data/tasks/fixtures.rb +42 -0
- metadata +181 -42
- data/lib/data_mapper/adapters/sql/commands/advanced_load_command.rb +0 -140
- data/lib/data_mapper/adapters/sql/commands/delete_command.rb +0 -113
- data/lib/data_mapper/adapters/sql/commands/save_command.rb +0 -141
- data/lib/data_mapper/adapters/sql/commands/table_exists_command.rb +0 -33
- data/lib/data_mapper/adapters/sql_adapter.rb +0 -163
- data/lib/data_mapper/associations/advanced_has_many_association.rb +0 -55
- data/lib/data_mapper/support/blank_slate.rb +0 -3
- data/lib/data_mapper/support/proc.rb +0 -69
- data/lib/data_mapper/support/struct.rb +0 -26
- data/lib/data_mapper/unit_of_work.rb +0 -38
- data/spec/basic_finder.rb +0 -67
- data/spec/belongs_to.rb +0 -47
- data/spec/has_and_belongs_to_many.rb +0 -25
- data/spec/has_many.rb +0 -34
- data/spec/new_record.rb +0 -24
- data/spec/sub_select.rb +0 -16
- data/spec/support/string_spec.rb +0 -7
@@ -0,0 +1,168 @@
|
|
1
|
+
%module sqlite3_c
|
2
|
+
%include "typemaps.i"
|
3
|
+
%{
|
4
|
+
#include <sqlite3.h>
|
5
|
+
typedef void BLOB;
|
6
|
+
typedef void VALBLOB;
|
7
|
+
%}
|
8
|
+
|
9
|
+
%typemap(in,numinputs=0) sqlite3 **OUTPUT(sqlite3 *) {
|
10
|
+
$1 = (sqlite3**)malloc( sizeof( sqlite3* ) );
|
11
|
+
};
|
12
|
+
%typemap(argout,fragment="output_helper") sqlite3 **OUTPUT (sqlite3 *) {
|
13
|
+
$result = output_helper($result, SWIG_NewPointerObj( *$1, SWIGTYPE_p_sqlite3, 0 ));
|
14
|
+
}
|
15
|
+
%typemap(freearg) sqlite3 ** {
|
16
|
+
free((sqlite3 *)$1);
|
17
|
+
}
|
18
|
+
|
19
|
+
%typemap(in,numinputs=0) sqlite3_stmt **OUTPUT(sqlite3_stmt *) {
|
20
|
+
$1 = (sqlite3_stmt**)malloc( sizeof( sqlite3_stmt* ) );
|
21
|
+
};
|
22
|
+
%typemap(argout,fragment="output_helper") sqlite3_stmt **OUTPUT (sqlite3_stmt *) {
|
23
|
+
$result = output_helper($result, SWIG_NewPointerObj( *$1, SWIGTYPE_p_sqlite3_stmt, 0 ));
|
24
|
+
}
|
25
|
+
%typemap(freearg) sqlite3_stmt ** {
|
26
|
+
free((sqlite3_stmt *)$1);
|
27
|
+
}
|
28
|
+
|
29
|
+
%typemap(in,numinputs=0) char **OUTPUT(char *) {
|
30
|
+
$1 = (char**)malloc( sizeof( char* ) );
|
31
|
+
};
|
32
|
+
%typemap(argout,fragment="output_helper") char **OUTPUT (char *) {
|
33
|
+
$result = output_helper($result, rb_str_new2(*$1));
|
34
|
+
}
|
35
|
+
%typemap(freearg) char ** {
|
36
|
+
free((char *)$1);
|
37
|
+
}
|
38
|
+
|
39
|
+
%typemap(out) sqlite_int64 {
|
40
|
+
$result = LONG2NUM(result);
|
41
|
+
}
|
42
|
+
|
43
|
+
const char *sqlite3_libversion(void);
|
44
|
+
int sqlite3_close(sqlite3*);
|
45
|
+
|
46
|
+
sqlite_int64 sqlite3_last_insert_rowid(sqlite3*);
|
47
|
+
|
48
|
+
int sqlite3_changes(sqlite3*);
|
49
|
+
int sqlite3_total_changes(sqlite3*);
|
50
|
+
void sqlite3_interrupt(sqlite3*);
|
51
|
+
|
52
|
+
int sqlite3_complete(const char*);
|
53
|
+
int sqlite3_complete16(const void *str);
|
54
|
+
|
55
|
+
int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*);
|
56
|
+
int sqlite3_busy_timeout(sqlite3*,int);
|
57
|
+
int sqlite3_set_authorizer(sqlite3*, int(*)(void*,int,const char*,const char*,const char*,const char*), void*);
|
58
|
+
int sqlite3_trace(sqlite3*, void(*)(void*,const char*), void*);
|
59
|
+
|
60
|
+
int sqlite3_open(const char *filename, sqlite3 **OUTPUT);
|
61
|
+
int sqlite3_open16(const void *filename, sqlite3 **);
|
62
|
+
|
63
|
+
int sqlite3_errcode(sqlite3*);
|
64
|
+
const char *sqlite3_errmsg(sqlite3*);
|
65
|
+
const void *sqlite3_errmsg16(sqlite3*);
|
66
|
+
|
67
|
+
int sqlite3_prepare(sqlite3*,const char* sql,int,sqlite3_stmt**OUTPUT,const char**OUTPUT);
|
68
|
+
int sqlite3_prepare_v2(sqlite3*,const char* sql,int,sqlite3_stmt**OUTPUT,const char**OUTPUT);
|
69
|
+
int sqlite3_prepare16(sqlite3*,const void* sql,int,sqlite3_stmt**,const void**);
|
70
|
+
|
71
|
+
int sqlite3_bind_blob(sqlite3_stmt*,int,const void *blob,int,void(*free)(void*));
|
72
|
+
int sqlite3_bind_double(sqlite3_stmt*,int,double);
|
73
|
+
int sqlite3_bind_int(sqlite3_stmt*,int,int);
|
74
|
+
int sqlite3_bind_int64(sqlite3_stmt*,int,sqlite_int64);
|
75
|
+
int sqlite3_bind_null(sqlite3_stmt*,int);
|
76
|
+
int sqlite3_bind_text(sqlite3_stmt*,int,const char*text,int,void(*free)(void*));
|
77
|
+
int sqlite3_bind_text16(sqlite3_stmt*,int,const void*utf16,int,void(*free)(void*));
|
78
|
+
|
79
|
+
int sqlite3_bind_parameter_count(sqlite3_stmt*);
|
80
|
+
const char *sqlite3_bind_parameter_name(sqlite3_stmt*,int);
|
81
|
+
int sqlite3_bind_parameter_index(sqlite3_stmt*,const char*);
|
82
|
+
|
83
|
+
int sqlite3_column_count(sqlite3_stmt*);
|
84
|
+
const char *sqlite3_column_name(sqlite3_stmt*,int);
|
85
|
+
const void *sqlite3_column_name16(sqlite3_stmt*,int);
|
86
|
+
const char *sqlite3_column_decltype(sqlite3_stmt*,int);
|
87
|
+
const void *sqlite3_column_decltype16(sqlite3_stmt*,int);
|
88
|
+
|
89
|
+
int sqlite3_step(sqlite3_stmt*);
|
90
|
+
|
91
|
+
int sqlite3_data_count(sqlite3_stmt*);
|
92
|
+
|
93
|
+
const BLOB *sqlite3_column_blob(sqlite3_stmt*,int);
|
94
|
+
int sqlite3_column_bytes(sqlite3_stmt*,int);
|
95
|
+
int sqlite3_column_bytes16(sqlite3_stmt*,int);
|
96
|
+
double sqlite3_column_double(sqlite3_stmt*,int);
|
97
|
+
double sqlite3_column_int(sqlite3_stmt*,int);
|
98
|
+
sqlite_int64 sqlite3_column_int64(sqlite3_stmt*,int);
|
99
|
+
const char *sqlite3_column_text(sqlite3_stmt*,int);
|
100
|
+
const void *sqlite3_column_text16(sqlite3_stmt*,int);
|
101
|
+
int sqlite3_column_type(sqlite3_stmt*,int);
|
102
|
+
|
103
|
+
int sqlite3_finalize(sqlite3_stmt*);
|
104
|
+
int sqlite3_reset(sqlite3_stmt*);
|
105
|
+
|
106
|
+
int sqlite3_create_function(sqlite3*,const char*str,int,int,void*,void(*func)(sqlite3_context*,int,sqlite3_value**),void(*step)(sqlite3_context*,int,sqlite3_value**),void(*final)(sqlite3_context*));
|
107
|
+
|
108
|
+
int sqlite3_create_function16(sqlite3*,const void*str,int,int,void*,void(*func)(sqlite3_context*,int,sqlite3_value**),void(*step)(sqlite3_context*,int,sqlite3_value**),void(*final)(sqlite3_context*));
|
109
|
+
|
110
|
+
int sqlite3_aggregate_count(sqlite3_context*);
|
111
|
+
|
112
|
+
const VALBLOB *sqlite3_value_blob(sqlite3_value*);
|
113
|
+
int sqlite3_value_bytes(sqlite3_value*);
|
114
|
+
int sqlite3_value_bytes16(sqlite3_value*);
|
115
|
+
double sqlite3_value_double(sqlite3_value*);
|
116
|
+
int sqlite3_value_int(sqlite3_value*);
|
117
|
+
sqlite_int64 sqlite3_value_int64(sqlite3_value*);
|
118
|
+
const char *sqlite3_value_text(sqlite3_value*);
|
119
|
+
const void *sqlite3_value_text16(sqlite3_value*);
|
120
|
+
const void *sqlite3_value_text16le(sqlite3_value*);
|
121
|
+
const void *sqlite3_value_text16be(sqlite3_value*);
|
122
|
+
int sqlite3_value_type(sqlite3_value*);
|
123
|
+
|
124
|
+
void sqlite3_result_blob(sqlite3_context*,const void *blob,int,void(*free)(void*));
|
125
|
+
void sqlite3_result_double(sqlite3_context*,double);
|
126
|
+
void sqlite3_result_error(sqlite3_context*,const char *text,int);
|
127
|
+
void sqlite3_result_error16(sqlite3_context*,const void *blob,int);
|
128
|
+
void sqlite3_result_int(sqlite3_context*,int);
|
129
|
+
void sqlite3_result_int64(sqlite3_context*,sqlite_int64);
|
130
|
+
void sqlite3_result_text(sqlite3_context*,const char* text,int,void(*free)(void*));
|
131
|
+
void sqlite3_result_text16(sqlite3_context*,const void* utf16,int,void(*free)(void*));
|
132
|
+
void sqlite3_result_text16le(sqlite3_context*,const void* utf16,int,void(*free)(void*));
|
133
|
+
void sqlite3_result_text16be(sqlite3_context*,const void* utf16,int,void(*free)(void*));
|
134
|
+
void sqlite3_result_value(sqlite3_context*,sqlite3_value*);
|
135
|
+
|
136
|
+
VALUE *sqlite3_aggregate_context(sqlite3_context*,int data_size);
|
137
|
+
|
138
|
+
#define SQLITE_OK 0 /* Successful result */
|
139
|
+
/* beginning-of-error-codes */
|
140
|
+
#define SQLITE_ERROR 1 /* SQL error or missing database */
|
141
|
+
#define SQLITE_INTERNAL 2 /* NOT USED. Internal logic error in SQLite */
|
142
|
+
#define SQLITE_PERM 3 /* Access permission denied */
|
143
|
+
#define SQLITE_ABORT 4 /* Callback routine requested an abort */
|
144
|
+
#define SQLITE_BUSY 5 /* The database file is locked */
|
145
|
+
#define SQLITE_LOCKED 6 /* A table in the database is locked */
|
146
|
+
#define SQLITE_NOMEM 7 /* A malloc() failed */
|
147
|
+
#define SQLITE_READONLY 8 /* Attempt to write a readonly database */
|
148
|
+
#define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite3_interrupt()*/
|
149
|
+
#define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */
|
150
|
+
#define SQLITE_CORRUPT 11 /* The database disk image is malformed */
|
151
|
+
#define SQLITE_NOTFOUND 12 /* NOT USED. Table or record not found */
|
152
|
+
#define SQLITE_FULL 13 /* Insertion failed because database is full */
|
153
|
+
#define SQLITE_CANTOPEN 14 /* Unable to open the database file */
|
154
|
+
#define SQLITE_PROTOCOL 15 /* NOT USED. Database lock protocol error */
|
155
|
+
#define SQLITE_EMPTY 16 /* Database is empty */
|
156
|
+
#define SQLITE_SCHEMA 17 /* The database schema changed */
|
157
|
+
#define SQLITE_TOOBIG 18 /* String or BLOB exceeds size limit */
|
158
|
+
#define SQLITE_CONSTRAINT 19 /* Abort due to constraint violation */
|
159
|
+
#define SQLITE_MISMATCH 20 /* Data type mismatch */
|
160
|
+
#define SQLITE_MISUSE 21 /* Library used incorrectly */
|
161
|
+
#define SQLITE_NOLFS 22 /* Uses OS features not supported on host */
|
162
|
+
#define SQLITE_AUTH 23 /* Authorization denied */
|
163
|
+
#define SQLITE_FORMAT 24 /* Auxiliary database format error */
|
164
|
+
#define SQLITE_RANGE 25 /* 2nd parameter to sqlite3_bind out of range */
|
165
|
+
#define SQLITE_NOTADB 26 /* File opened that is not a database file */
|
166
|
+
#define SQLITE_ROW 100 /* sqlite3_step() has another row ready */
|
167
|
+
#define SQLITE_DONE 101 /* sqlite3_step() has finished executing */
|
168
|
+
/* end-of-error-codes */
|
data/rakefile.rb
CHANGED
@@ -6,25 +6,36 @@ require 'rake/rdoctask'
|
|
6
6
|
require 'rake/gempackagetask'
|
7
7
|
require 'rake/contrib/rubyforgepublisher'
|
8
8
|
|
9
|
-
|
9
|
+
Dir[File.dirname(__FILE__) + '/tasks/*'].each { |t| require(t) }
|
10
10
|
|
11
|
-
|
12
|
-
Spec::Rake::SpecTask.new('test') do |t|
|
13
|
-
t.spec_opts = [ '-rspec/spec_helper' ]
|
14
|
-
t.spec_files = FileList['spec/*.rb', (ENV['FILES'] || 'spec/**/*_spec.rb')]
|
15
|
-
end
|
11
|
+
task :default => 'dm:spec'
|
16
12
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
13
|
+
namespace :dm do
|
14
|
+
|
15
|
+
desc "Setup Environment"
|
16
|
+
task :environment do
|
17
|
+
require 'environment'
|
18
|
+
end
|
19
|
+
|
20
|
+
desc "Run specifications"
|
21
|
+
Spec::Rake::SpecTask.new('spec') do |t|
|
22
|
+
t.spec_opts = [ '-rspec/spec_helper' ]
|
23
|
+
t.spec_files = FileList[(ENV['FILES'] || 'spec/**/*_spec.rb')]
|
24
|
+
end
|
25
|
+
|
26
|
+
desc "Run comparison with ActiveRecord"
|
27
|
+
task :perf do
|
28
|
+
load 'performance.rb'
|
29
|
+
end
|
30
|
+
|
31
|
+
desc "Profile DataMapper"
|
32
|
+
task :profile do
|
33
|
+
load 'profile_data_mapper.rb'
|
34
|
+
end
|
21
35
|
|
22
|
-
desc "Profile DataMapper"
|
23
|
-
task :profile do
|
24
|
-
load 'profile_data_mapper.rb'
|
25
36
|
end
|
26
37
|
|
27
|
-
PACKAGE_VERSION = '0.
|
38
|
+
PACKAGE_VERSION = '0.2.0'
|
28
39
|
|
29
40
|
PACKAGE_FILES = FileList[
|
30
41
|
'README',
|
@@ -32,40 +43,47 @@ PACKAGE_FILES = FileList[
|
|
32
43
|
'MIT-LICENSE',
|
33
44
|
'*.rb',
|
34
45
|
'lib/**/*.rb',
|
35
|
-
'spec/**/*.{rb,yaml}'
|
46
|
+
'spec/**/*.{rb,yaml}',
|
47
|
+
'tasks/**/*',
|
48
|
+
'plugins/**/*'
|
36
49
|
].to_a
|
37
50
|
|
38
51
|
PROJECT = 'datamapper'
|
39
52
|
|
53
|
+
task :ls do
|
54
|
+
p PACKAGE_FILES.reject { |path| path =~ /(^spec|\/spec|\/swig\_)/ }.sort
|
55
|
+
end
|
56
|
+
|
40
57
|
desc "Generate Documentation"
|
41
58
|
rd = Rake::RDocTask.new do |rdoc|
|
42
59
|
rdoc.rdoc_dir = 'doc'
|
43
60
|
rdoc.title = "DataMapper -- An Object/Relational Mapper for Ruby"
|
44
61
|
rdoc.options << '--line-numbers' << '--inline-source' << '--main' << 'README'
|
45
|
-
rdoc.rdoc_files.include(PACKAGE_FILES.reject { |path| path =~
|
62
|
+
rdoc.rdoc_files.include(PACKAGE_FILES.reject { |path| path =~ /(^spec|\/spec|\/swig\_)/ })
|
46
63
|
end
|
47
64
|
|
48
|
-
gem_spec = Gem::Specification.new do |s|
|
65
|
+
gem_spec = Gem::Specification.new do |s|
|
49
66
|
s.platform = Gem::Platform::RUBY
|
50
67
|
s.name = PROJECT
|
51
68
|
s.summary = "An Object/Relational Mapper for Ruby"
|
52
|
-
s.description = "
|
69
|
+
s.description = "Faster, Better, Simpler."
|
53
70
|
s.version = PACKAGE_VERSION
|
54
|
-
|
71
|
+
|
55
72
|
s.authors = 'Sam Smoot'
|
56
73
|
s.email = 'ssmoot@gmail.com'
|
57
74
|
s.rubyforge_project = PROJECT
|
58
75
|
s.homepage = 'http://datamapper.org'
|
59
|
-
|
76
|
+
|
60
77
|
s.files = PACKAGE_FILES
|
61
|
-
|
78
|
+
|
62
79
|
s.require_path = 'lib'
|
63
80
|
s.requirements << 'none'
|
64
81
|
s.autorequire = 'data_mapper'
|
82
|
+
s.add_dependency('fastthread')
|
65
83
|
|
66
84
|
s.has_rdoc = true
|
67
85
|
s.rdoc_options << '--line-numbers' << '--inline-source' << '--main' << 'README'
|
68
|
-
s.extra_rdoc_files =
|
86
|
+
s.extra_rdoc_files = PACKAGE_FILES.reject { |path| path =~ /(^spec|\/spec|\/swig\_)/ }.to_a
|
69
87
|
end
|
70
88
|
|
71
89
|
Rake::GemPackageTask.new(gem_spec) do |p|
|
@@ -76,5 +94,9 @@ end
|
|
76
94
|
|
77
95
|
desc "Publish to RubyForge"
|
78
96
|
task :rubyforge => [ :rdoc, :gem ] do
|
79
|
-
Rake::SshDirPublisher.new(ENV['RUBYFORGE_USER'], "/var/www/gforge-projects/#{PROJECT}", 'doc').upload
|
97
|
+
Rake::SshDirPublisher.new("#{ENV['RUBYFORGE_USER']}@rubyforge.org", "/var/www/gforge-projects/#{PROJECT}", 'doc').upload
|
98
|
+
end
|
99
|
+
|
100
|
+
task :install => :package do
|
101
|
+
sh %{sudo gem install pkg/#{PROJECT}-#{PACKAGE_VERSION}}
|
80
102
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
describe('A tree') do
|
2
|
+
|
3
|
+
before(:all) do
|
4
|
+
class Node < DataMapper::Base
|
5
|
+
property :name, :string
|
6
|
+
|
7
|
+
belongs_to :parent, :class => 'Node'
|
8
|
+
has_many :children, :class => 'Node', :foreign_key => 'parent_id'
|
9
|
+
end
|
10
|
+
|
11
|
+
database.schema[Node].drop!
|
12
|
+
database.save(Node)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should work' do
|
16
|
+
root = Node.new(:name => 'root')
|
17
|
+
|
18
|
+
one = Node.new(:name => 'one')
|
19
|
+
two = Node.new(:name => 'two')
|
20
|
+
|
21
|
+
root.children << one << two
|
22
|
+
|
23
|
+
one_one = Node.new(:name => 'one_one')
|
24
|
+
one_two = Node.new(:name => 'one_two')
|
25
|
+
one.children << one_one << one_two
|
26
|
+
|
27
|
+
two_one = Node.new(:name => 'two_one')
|
28
|
+
two_two = Node.new(:name => 'two_two')
|
29
|
+
two.children << two_one << two_two
|
30
|
+
|
31
|
+
root.save
|
32
|
+
|
33
|
+
grand = Node[:name => 'root']
|
34
|
+
root.should_not == grand # false since +root+ and +grand+ are in different sessions.
|
35
|
+
|
36
|
+
grand.children[0].children[0].name.should == 'one_one'
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
@@ -0,0 +1,220 @@
|
|
1
|
+
describe DataMapper::Associations::BelongsToAssociation do
|
2
|
+
before(:each) do
|
3
|
+
@aviary = Exhibit[:name => 'Monkey Mayhem']
|
4
|
+
end
|
5
|
+
|
6
|
+
it 'has a zoo association' do
|
7
|
+
@aviary.zoo.class.should == Zoo
|
8
|
+
Exhibit.new.zoo.should == nil
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'belongs to a zoo' do
|
12
|
+
@aviary.zoo.should == @aviary.session.first(Zoo, :name => 'San Diego')
|
13
|
+
end
|
14
|
+
|
15
|
+
it "is assigned a zoo_id" do
|
16
|
+
zoo = Zoo.first
|
17
|
+
exhibit = Exhibit.new(:name => 'bob')
|
18
|
+
exhibit.zoo = zoo
|
19
|
+
exhibit.instance_variable_get("@zoo_id").should == zoo.id
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'can build its zoo' do
|
23
|
+
database do |db|
|
24
|
+
e = Exhibit.new({:name => 'Super Extra Crazy Monkey Cage'})
|
25
|
+
e.zoo.should == nil
|
26
|
+
e.build_zoo({:name => 'Monkey Zoo'})
|
27
|
+
e.zoo.class == Zoo
|
28
|
+
e.zoo.new_record?.should == true
|
29
|
+
|
30
|
+
e.save
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'can build its zoo' do
|
35
|
+
database do |db|
|
36
|
+
e = Exhibit.new({:name => 'Super Extra Crazy Monkey Cage'})
|
37
|
+
e.zoo.should == nil
|
38
|
+
e.create_zoo({:name => 'Monkey Zoo'})
|
39
|
+
e.zoo.class == Zoo
|
40
|
+
e.zoo.new_record?.should == false
|
41
|
+
e.save
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
after(:all) do
|
46
|
+
fixtures('zoos')
|
47
|
+
fixtures('exhibits')
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe DataMapper::Associations::HasManyAssociation do
|
52
|
+
|
53
|
+
before(:all) do
|
54
|
+
fixtures(:zoos)
|
55
|
+
fixtures(:exhibits)
|
56
|
+
end
|
57
|
+
|
58
|
+
before(:each) do
|
59
|
+
@zoo = Zoo.new(:name => "ZOO")
|
60
|
+
@zoo.save
|
61
|
+
end
|
62
|
+
|
63
|
+
after(:each) do
|
64
|
+
@zoo.destroy!
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'should lazily-load the association when Enumerable methods are called' do
|
68
|
+
database do |db|
|
69
|
+
san_diego = Zoo[:name => 'San Diego']
|
70
|
+
san_diego.exhibits.size.should == 2
|
71
|
+
san_diego.exhibits.should include(Exhibit[:name => 'Monkey Mayhem'])
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'should eager-load associations for an entire set' do
|
76
|
+
database do
|
77
|
+
zoos = Zoo.all
|
78
|
+
zoos.each do |zoo|
|
79
|
+
zoo.exhibits.each do |exhibit|
|
80
|
+
exhibit.zoo.should == zoo
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should be dirty even when clean objects are associated" do
|
87
|
+
zoo = Zoo[:name => 'New York']
|
88
|
+
zoo.exhibits << Exhibit.first
|
89
|
+
zoo.should be_dirty
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should proxy associations on the associated type" do
|
93
|
+
Zoo[:name => 'Miami'].exhibits.animals.size.should == 1
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should have a valid zoo setup for testing" do
|
97
|
+
@zoo.should be_valid
|
98
|
+
@zoo.should_not be_a_new_record
|
99
|
+
@zoo.id.should_not be_nil
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should generate the SQL for a join statement" do
|
103
|
+
exhibits_association = database(:mock).schema[Zoo].associations.find { |a| a.name == :exhibits }
|
104
|
+
|
105
|
+
exhibits_association.to_sql.should == <<-EOS.compress_lines
|
106
|
+
JOIN `exhibits` ON `exhibits`.`zoo_id` = `zoos`.`id`
|
107
|
+
EOS
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should add an item to an association" do
|
111
|
+
bear = Exhibit.new( :name => "Bear")
|
112
|
+
@zoo.exhibits << bear
|
113
|
+
@zoo.exhibits.should include(bear)
|
114
|
+
end
|
115
|
+
|
116
|
+
|
117
|
+
it "should set the association to a saved target when added with <<" do
|
118
|
+
pirahna = Exhibit.new(:name => "Pirahna")
|
119
|
+
pirahna.zoo_id.should be_nil
|
120
|
+
|
121
|
+
@zoo.exhibits << pirahna
|
122
|
+
pirahna.zoo.should == @zoo
|
123
|
+
end
|
124
|
+
|
125
|
+
it "should set the association to a non-saved target when added with <<" do
|
126
|
+
zoo = Zoo.new(:name => "My Zoo")
|
127
|
+
kangaroo = Exhibit.new(:name => "Kangaroo")
|
128
|
+
zoo.exhibits << kangaroo
|
129
|
+
kangaroo.zoo.should == zoo
|
130
|
+
end
|
131
|
+
|
132
|
+
it "should set the id of the exhibit when the associated zoo is saved" do
|
133
|
+
snake = Exhibit.new(:name => "Snake")
|
134
|
+
@zoo.exhibits << snake
|
135
|
+
@zoo.save
|
136
|
+
@zoo.id.should == snake.zoo_id
|
137
|
+
end
|
138
|
+
|
139
|
+
it "should set the id of an already saved exibit if it's added to a different zoo" do
|
140
|
+
beaver = Exhibit.new(:name => "Beaver")
|
141
|
+
beaver.save
|
142
|
+
beaver.should_not be_a_new_record
|
143
|
+
@zoo.exhibits << beaver
|
144
|
+
@zoo.save
|
145
|
+
beaver.zoo.should == @zoo
|
146
|
+
beaver.zoo_id.should == @zoo.id
|
147
|
+
end
|
148
|
+
|
149
|
+
it "should set the size of the assocation" do
|
150
|
+
@zoo.exhibits << Exhibit.new(:name => "anonymous")
|
151
|
+
@zoo.exhibits.size.should == 1
|
152
|
+
end
|
153
|
+
|
154
|
+
it "should give the association when an inspect is done on it" do
|
155
|
+
whale = Exhibit.new(:name => "Whale")
|
156
|
+
@zoo.exhibits << whale
|
157
|
+
@zoo.exhibits.should_not == "nil"
|
158
|
+
@zoo.exhibits.inspect.should_not be_nil
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
describe DataMapper::Associations::HasOneAssociation do
|
163
|
+
|
164
|
+
it "should generate the SQL for a join statement" do
|
165
|
+
fruit_association = database(:mock).schema[Animal].associations.find { |a| a.name == :favourite_fruit }
|
166
|
+
|
167
|
+
fruit_association.to_sql.should == <<-EOS.compress_lines
|
168
|
+
JOIN `fruit` ON `fruit`.`devourer_id` = `animals`.`id`
|
169
|
+
EOS
|
170
|
+
end
|
171
|
+
|
172
|
+
end
|
173
|
+
|
174
|
+
describe DataMapper::Associations::HasAndBelongsToManyAssociation do
|
175
|
+
|
176
|
+
before(:all) do
|
177
|
+
fixtures(:animals)
|
178
|
+
fixtures(:exhibits)
|
179
|
+
end
|
180
|
+
|
181
|
+
before(:each) do
|
182
|
+
@amazonia = Exhibit[:name => 'Amazonia']
|
183
|
+
end
|
184
|
+
|
185
|
+
it "should generate the SQL for a join statement" do
|
186
|
+
animals_association = database(:mock).schema[Exhibit].associations.find { |a| a.name == :animals }
|
187
|
+
|
188
|
+
animals_association.to_sql.should == <<-EOS.compress_lines
|
189
|
+
JOIN `animals_exhibits` ON `animals_exhibits`.`exhibit_id` = `exhibits`.`id`
|
190
|
+
JOIN `animals` ON `animals`.`id` = `animals_exhibits`.`animal_id`
|
191
|
+
EOS
|
192
|
+
end
|
193
|
+
|
194
|
+
it "should load associations" do
|
195
|
+
database do
|
196
|
+
froggy = Animal[:name => 'Frog']
|
197
|
+
froggy.exhibits.size.should == 1
|
198
|
+
froggy.exhibits.entries.first.should == Exhibit[:name => 'Amazonia']
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
it 'has an animals association' do
|
203
|
+
[@amazonia, Exhibit.new].each do |exhibit|
|
204
|
+
exhibit.animals.class.should == DataMapper::Associations::HasAndBelongsToManyAssociation::Set
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
it 'has many animals' do
|
209
|
+
@amazonia.animals.size.should == 1
|
210
|
+
end
|
211
|
+
|
212
|
+
it 'should load associations magically' do
|
213
|
+
Exhibit.all.each do |exhibit|
|
214
|
+
exhibit.animals.each do |animal|
|
215
|
+
animal.exhibits.should include(exhibit)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
end
|