datamapper 0.1.1 → 0.2.0

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