datamapper 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (131) hide show
  1. data/CHANGELOG +65 -0
  2. data/README +193 -1
  3. data/do_performance.rb +153 -0
  4. data/environment.rb +45 -0
  5. data/example.rb +119 -22
  6. data/lib/data_mapper.rb +36 -16
  7. data/lib/data_mapper/adapters/abstract_adapter.rb +8 -0
  8. data/lib/data_mapper/adapters/data_object_adapter.rb +360 -0
  9. data/lib/data_mapper/adapters/mysql_adapter.rb +30 -179
  10. data/lib/data_mapper/adapters/postgresql_adapter.rb +90 -199
  11. data/lib/data_mapper/adapters/sql/coersion.rb +32 -3
  12. data/lib/data_mapper/adapters/sql/commands/conditions.rb +97 -128
  13. data/lib/data_mapper/adapters/sql/commands/load_command.rb +234 -231
  14. data/lib/data_mapper/adapters/sql/commands/loader.rb +99 -0
  15. data/lib/data_mapper/adapters/sql/mappings/associations_set.rb +30 -0
  16. data/lib/data_mapper/adapters/sql/mappings/column.rb +68 -6
  17. data/lib/data_mapper/adapters/sql/mappings/schema.rb +6 -3
  18. data/lib/data_mapper/adapters/sql/mappings/table.rb +71 -42
  19. data/lib/data_mapper/adapters/sql/quoting.rb +8 -2
  20. data/lib/data_mapper/adapters/sqlite3_adapter.rb +32 -201
  21. data/lib/data_mapper/associations.rb +21 -7
  22. data/lib/data_mapper/associations/belongs_to_association.rb +96 -80
  23. data/lib/data_mapper/associations/has_and_belongs_to_many_association.rb +158 -67
  24. data/lib/data_mapper/associations/has_many_association.rb +96 -78
  25. data/lib/data_mapper/associations/has_n_association.rb +64 -0
  26. data/lib/data_mapper/associations/has_one_association.rb +49 -79
  27. data/lib/data_mapper/associations/reference.rb +47 -0
  28. data/lib/data_mapper/base.rb +216 -50
  29. data/lib/data_mapper/callbacks.rb +71 -24
  30. data/lib/data_mapper/{session.rb → context.rb} +20 -8
  31. data/lib/data_mapper/database.rb +176 -45
  32. data/lib/data_mapper/embedded_value.rb +65 -0
  33. data/lib/data_mapper/identity_map.rb +12 -4
  34. data/lib/data_mapper/support/active_record_impersonation.rb +12 -8
  35. data/lib/data_mapper/support/enumerable.rb +8 -0
  36. data/lib/data_mapper/support/serialization.rb +13 -0
  37. data/lib/data_mapper/support/string.rb +1 -12
  38. data/lib/data_mapper/support/symbol.rb +3 -0
  39. data/lib/data_mapper/validations/unique_validator.rb +1 -2
  40. data/lib/data_mapper/validations/validation_helper.rb +18 -1
  41. data/performance.rb +109 -34
  42. data/plugins/can_has_sphinx/LICENSE +23 -0
  43. data/plugins/can_has_sphinx/README +4 -0
  44. data/plugins/can_has_sphinx/REVISION +1 -0
  45. data/plugins/can_has_sphinx/Rakefile +22 -0
  46. data/plugins/can_has_sphinx/init.rb +1 -0
  47. data/plugins/can_has_sphinx/install.rb +1 -0
  48. data/plugins/can_has_sphinx/lib/acts_as_sphinx.rb +123 -0
  49. data/plugins/can_has_sphinx/lib/sphinx.rb +460 -0
  50. data/plugins/can_has_sphinx/scripts/sphinx.sh +47 -0
  51. data/plugins/can_has_sphinx/tasks/acts_as_sphinx_tasks.rake +41 -0
  52. data/plugins/dataobjects/REVISION +1 -0
  53. data/plugins/dataobjects/Rakefile +7 -0
  54. data/plugins/dataobjects/do.rb +246 -0
  55. data/plugins/dataobjects/do_mysql.rb +179 -0
  56. data/plugins/dataobjects/do_postgres.rb +181 -0
  57. data/plugins/dataobjects/do_sqlite3.rb +153 -0
  58. data/plugins/dataobjects/spec/do_spec.rb +150 -0
  59. data/plugins/dataobjects/spec/spec_helper.rb +81 -0
  60. data/plugins/dataobjects/swig_mysql/do_mysql.bundle +0 -0
  61. data/plugins/dataobjects/swig_mysql/extconf.rb +33 -0
  62. data/plugins/dataobjects/swig_mysql/mysql_c.c +18800 -0
  63. data/plugins/dataobjects/swig_mysql/mysql_c.i +8 -0
  64. data/plugins/dataobjects/swig_mysql/mysql_supp.i +46 -0
  65. data/plugins/dataobjects/swig_postgres/Makefile +146 -0
  66. data/plugins/dataobjects/swig_postgres/extconf.rb +29 -0
  67. data/plugins/dataobjects/swig_postgres/postgres_c.bundle +0 -0
  68. data/plugins/dataobjects/swig_postgres/postgres_c.c +8185 -0
  69. data/plugins/dataobjects/swig_postgres/postgres_c.i +73 -0
  70. data/plugins/dataobjects/swig_sqlite/db +0 -0
  71. data/plugins/dataobjects/swig_sqlite/extconf.rb +9 -0
  72. data/plugins/dataobjects/swig_sqlite/sqlite3_c.c +4725 -0
  73. data/plugins/dataobjects/swig_sqlite/sqlite_c.i +168 -0
  74. data/rakefile.rb +45 -23
  75. data/spec/acts_as_tree_spec.rb +39 -0
  76. data/spec/associations_spec.rb +220 -0
  77. data/spec/attributes_spec.rb +15 -0
  78. data/spec/base_spec.rb +44 -0
  79. data/spec/callbacks_spec.rb +45 -0
  80. data/spec/can_has_sphinx.rb +6 -0
  81. data/spec/coersion_spec.rb +34 -0
  82. data/spec/conditions_spec.rb +49 -0
  83. data/spec/conversions_to_yaml_spec.rb +17 -0
  84. data/spec/count_command_spec.rb +11 -0
  85. data/spec/delete_command_spec.rb +1 -1
  86. data/spec/embedded_value_spec.rb +23 -0
  87. data/spec/fixtures/animals_exhibits.yaml +2 -0
  88. data/spec/fixtures/people.yaml +18 -1
  89. data/spec/{legacy.rb → legacy_spec.rb} +3 -3
  90. data/spec/load_command_spec.rb +157 -20
  91. data/spec/magic_columns_spec.rb +9 -0
  92. data/spec/mock_adapter.rb +20 -0
  93. data/spec/models/animal.rb +1 -1
  94. data/spec/models/animals_exhibit.rb +6 -0
  95. data/spec/models/exhibit.rb +2 -0
  96. data/spec/models/person.rb +26 -1
  97. data/spec/models/project.rb +19 -0
  98. data/spec/models/sales_person.rb +1 -0
  99. data/spec/models/section.rb +6 -0
  100. data/spec/models/zoo.rb +3 -1
  101. data/spec/query_spec.rb +9 -0
  102. data/spec/save_command_spec.rb +65 -1
  103. data/spec/schema_spec.rb +89 -0
  104. data/spec/single_table_inheritance_spec.rb +27 -0
  105. data/spec/spec_helper.rb +9 -55
  106. data/spec/{symbolic_operators.rb → symbolic_operators_spec.rb} +9 -5
  107. data/spec/{validates_confirmation_of.rb → validates_confirmation_of_spec.rb} +4 -3
  108. data/spec/{validates_format_of.rb → validates_format_of_spec.rb} +5 -4
  109. data/spec/{validates_length_of.rb → validates_length_of_spec.rb} +8 -7
  110. data/spec/{validates_uniqueness_of.rb → validates_uniqueness_of_spec.rb} +7 -10
  111. data/spec/{validations.rb → validations_spec.rb} +24 -6
  112. data/tasks/drivers.rb +20 -0
  113. data/tasks/fixtures.rb +42 -0
  114. metadata +181 -42
  115. data/lib/data_mapper/adapters/sql/commands/advanced_load_command.rb +0 -140
  116. data/lib/data_mapper/adapters/sql/commands/delete_command.rb +0 -113
  117. data/lib/data_mapper/adapters/sql/commands/save_command.rb +0 -141
  118. data/lib/data_mapper/adapters/sql/commands/table_exists_command.rb +0 -33
  119. data/lib/data_mapper/adapters/sql_adapter.rb +0 -163
  120. data/lib/data_mapper/associations/advanced_has_many_association.rb +0 -55
  121. data/lib/data_mapper/support/blank_slate.rb +0 -3
  122. data/lib/data_mapper/support/proc.rb +0 -69
  123. data/lib/data_mapper/support/struct.rb +0 -26
  124. data/lib/data_mapper/unit_of_work.rb +0 -38
  125. data/spec/basic_finder.rb +0 -67
  126. data/spec/belongs_to.rb +0 -47
  127. data/spec/has_and_belongs_to_many.rb +0 -25
  128. data/spec/has_many.rb +0 -34
  129. data/spec/new_record.rb +0 -24
  130. data/spec/sub_select.rb +0 -16
  131. 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
- task :default => 'test'
9
+ Dir[File.dirname(__FILE__) + '/tasks/*'].each { |t| require(t) }
10
10
 
11
- desc "Run specifications"
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
- desc "Run comparison with ActiveRecord"
18
- task :perf do
19
- load 'performance.rb'
20
- end
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.1.1'
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 =~ /^(spec|\w+\.rb)/ })
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 = "It's ActiveRecord, but Faster, Better, Simpler."
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 = rd.rdoc_files.reject { |path| path =~ /\.rb$/ }.to_a
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