activerecord 1.15.6 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (185) hide show
  1. data/CHANGELOG +2454 -34
  2. data/README +1 -1
  3. data/RUNNING_UNIT_TESTS +3 -34
  4. data/Rakefile +98 -77
  5. data/install.rb +1 -1
  6. data/lib/active_record.rb +13 -22
  7. data/lib/active_record/aggregations.rb +38 -49
  8. data/lib/active_record/associations.rb +452 -333
  9. data/lib/active_record/associations/association_collection.rb +66 -20
  10. data/lib/active_record/associations/association_proxy.rb +9 -8
  11. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +46 -51
  12. data/lib/active_record/associations/has_many_association.rb +21 -57
  13. data/lib/active_record/associations/has_many_through_association.rb +38 -18
  14. data/lib/active_record/associations/has_one_association.rb +30 -14
  15. data/lib/active_record/attribute_methods.rb +253 -0
  16. data/lib/active_record/base.rb +719 -494
  17. data/lib/active_record/calculations.rb +62 -63
  18. data/lib/active_record/callbacks.rb +57 -83
  19. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +38 -9
  20. data/lib/active_record/connection_adapters/abstract/database_statements.rb +56 -15
  21. data/lib/active_record/connection_adapters/abstract/query_cache.rb +87 -0
  22. data/lib/active_record/connection_adapters/abstract/quoting.rb +23 -12
  23. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +191 -62
  24. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +37 -34
  25. data/lib/active_record/connection_adapters/abstract_adapter.rb +28 -17
  26. data/lib/active_record/connection_adapters/mysql_adapter.rb +119 -37
  27. data/lib/active_record/connection_adapters/postgresql_adapter.rb +473 -210
  28. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +34 -0
  29. data/lib/active_record/connection_adapters/sqlite_adapter.rb +91 -107
  30. data/lib/active_record/fixtures.rb +503 -113
  31. data/lib/active_record/locking/optimistic.rb +72 -34
  32. data/lib/active_record/migration.rb +80 -57
  33. data/lib/active_record/observer.rb +13 -10
  34. data/lib/active_record/query_cache.rb +16 -57
  35. data/lib/active_record/reflection.rb +35 -38
  36. data/lib/active_record/schema.rb +5 -5
  37. data/lib/active_record/schema_dumper.rb +35 -13
  38. data/lib/active_record/serialization.rb +98 -0
  39. data/lib/active_record/serializers/json_serializer.rb +71 -0
  40. data/lib/active_record/{xml_serialization.rb → serializers/xml_serializer.rb} +90 -83
  41. data/lib/active_record/timestamp.rb +20 -21
  42. data/lib/active_record/transactions.rb +39 -43
  43. data/lib/active_record/validations.rb +256 -107
  44. data/lib/active_record/version.rb +3 -3
  45. data/lib/activerecord.rb +1 -0
  46. data/test/aaa_create_tables_test.rb +15 -2
  47. data/test/abstract_unit.rb +24 -17
  48. data/test/active_schema_test_mysql.rb +20 -8
  49. data/test/adapter_test.rb +23 -5
  50. data/test/adapter_test_sqlserver.rb +15 -1
  51. data/test/aggregations_test.rb +16 -1
  52. data/test/all.sh +2 -2
  53. data/test/associations/ar_joins_test.rb +0 -0
  54. data/test/associations/callbacks_test.rb +51 -30
  55. data/test/associations/cascaded_eager_loading_test.rb +1 -29
  56. data/test/associations/eager_singularization_test.rb +145 -0
  57. data/test/associations/eager_test.rb +42 -6
  58. data/test/associations/extension_test.rb +6 -1
  59. data/test/associations/inner_join_association_test.rb +88 -0
  60. data/test/associations/join_model_test.rb +47 -16
  61. data/test/associations_test.rb +449 -226
  62. data/test/attribute_methods_test.rb +97 -0
  63. data/test/base_test.rb +251 -105
  64. data/test/binary_test.rb +22 -27
  65. data/test/calculations_test.rb +37 -5
  66. data/test/callbacks_test.rb +23 -0
  67. data/test/connection_test_firebird.rb +2 -2
  68. data/test/connection_test_mysql.rb +30 -0
  69. data/test/connections/native_mysql/connection.rb +3 -0
  70. data/test/connections/native_sqlite/connection.rb +5 -14
  71. data/test/connections/native_sqlite3/connection.rb +5 -14
  72. data/test/connections/native_sqlite3/in_memory_connection.rb +1 -1
  73. data/test/{copy_table_sqlite.rb → copy_table_test_sqlite.rb} +8 -3
  74. data/test/datatype_test_postgresql.rb +178 -27
  75. data/test/{empty_date_time_test.rb → date_time_test.rb} +13 -1
  76. data/test/defaults_test.rb +8 -1
  77. data/test/deprecated_finder_test.rb +7 -128
  78. data/test/finder_test.rb +192 -54
  79. data/test/fixtures/all/developers.yml +0 -0
  80. data/test/fixtures/all/people.csv +0 -0
  81. data/test/fixtures/all/tasks.yml +0 -0
  82. data/test/fixtures/author.rb +12 -5
  83. data/test/fixtures/binaries.yml +130 -435
  84. data/test/fixtures/category.rb +6 -0
  85. data/test/fixtures/company.rb +8 -1
  86. data/test/fixtures/computer.rb +1 -0
  87. data/test/fixtures/contact.rb +16 -0
  88. data/test/fixtures/customer.rb +2 -2
  89. data/test/fixtures/db_definitions/db2.drop.sql +1 -0
  90. data/test/fixtures/db_definitions/db2.sql +4 -0
  91. data/test/fixtures/db_definitions/firebird.drop.sql +3 -1
  92. data/test/fixtures/db_definitions/firebird.sql +6 -0
  93. data/test/fixtures/db_definitions/frontbase.drop.sql +1 -0
  94. data/test/fixtures/db_definitions/frontbase.sql +5 -0
  95. data/test/fixtures/db_definitions/openbase.sql +41 -25
  96. data/test/fixtures/db_definitions/oracle.drop.sql +2 -0
  97. data/test/fixtures/db_definitions/oracle.sql +5 -0
  98. data/test/fixtures/db_definitions/postgresql.drop.sql +7 -0
  99. data/test/fixtures/db_definitions/postgresql.sql +87 -58
  100. data/test/fixtures/db_definitions/postgresql2.sql +1 -2
  101. data/test/fixtures/db_definitions/schema.rb +280 -0
  102. data/test/fixtures/db_definitions/schema2.rb +11 -0
  103. data/test/fixtures/db_definitions/sqlite.drop.sql +1 -0
  104. data/test/fixtures/db_definitions/sqlite.sql +4 -0
  105. data/test/fixtures/db_definitions/sybase.drop.sql +1 -0
  106. data/test/fixtures/db_definitions/sybase.sql +4 -0
  107. data/test/fixtures/developer.rb +10 -0
  108. data/test/fixtures/example.log +1 -0
  109. data/test/fixtures/flowers.jpg +0 -0
  110. data/test/fixtures/item.rb +7 -0
  111. data/test/fixtures/items.yml +4 -0
  112. data/test/fixtures/joke.rb +0 -3
  113. data/test/fixtures/matey.rb +4 -0
  114. data/test/fixtures/mateys.yml +4 -0
  115. data/test/fixtures/minimalistic.rb +2 -0
  116. data/test/fixtures/minimalistics.yml +2 -0
  117. data/test/fixtures/mixins.yml +2 -100
  118. data/test/fixtures/parrot.rb +13 -0
  119. data/test/fixtures/parrots.yml +27 -0
  120. data/test/fixtures/parrots_pirates.yml +7 -0
  121. data/test/fixtures/pirate.rb +5 -0
  122. data/test/fixtures/pirates.yml +9 -0
  123. data/test/fixtures/post.rb +1 -0
  124. data/test/fixtures/project.rb +3 -2
  125. data/test/fixtures/reserved_words/distinct.yml +5 -0
  126. data/test/fixtures/reserved_words/distincts_selects.yml +11 -0
  127. data/test/fixtures/reserved_words/group.yml +14 -0
  128. data/test/fixtures/reserved_words/select.yml +8 -0
  129. data/test/fixtures/reserved_words/values.yml +7 -0
  130. data/test/fixtures/ship.rb +3 -0
  131. data/test/fixtures/ships.yml +5 -0
  132. data/test/fixtures/tagging.rb +4 -0
  133. data/test/fixtures/taggings.yml +8 -1
  134. data/test/fixtures/topic.rb +13 -1
  135. data/test/fixtures/treasure.rb +4 -0
  136. data/test/fixtures/treasures.yml +10 -0
  137. data/test/fixtures_test.rb +205 -24
  138. data/test/inheritance_test.rb +7 -1
  139. data/test/json_serialization_test.rb +180 -0
  140. data/test/lifecycle_test.rb +1 -1
  141. data/test/locking_test.rb +85 -2
  142. data/test/migration_test.rb +206 -40
  143. data/test/mixin_test.rb +13 -515
  144. data/test/pk_test.rb +3 -6
  145. data/test/query_cache_test.rb +104 -0
  146. data/test/reflection_test.rb +16 -0
  147. data/test/reserved_word_test_mysql.rb +177 -0
  148. data/test/schema_dumper_test.rb +38 -3
  149. data/test/serialization_test.rb +47 -0
  150. data/test/transactions_test.rb +74 -23
  151. data/test/unconnected_test.rb +1 -1
  152. data/test/validations_test.rb +322 -32
  153. data/test/xml_serialization_test.rb +121 -44
  154. metadata +48 -41
  155. data/examples/associations.rb +0 -87
  156. data/examples/shared_setup.rb +0 -15
  157. data/examples/validation.rb +0 -85
  158. data/lib/active_record/acts/list.rb +0 -256
  159. data/lib/active_record/acts/nested_set.rb +0 -211
  160. data/lib/active_record/acts/tree.rb +0 -96
  161. data/lib/active_record/connection_adapters/db2_adapter.rb +0 -228
  162. data/lib/active_record/connection_adapters/firebird_adapter.rb +0 -728
  163. data/lib/active_record/connection_adapters/frontbase_adapter.rb +0 -861
  164. data/lib/active_record/connection_adapters/openbase_adapter.rb +0 -350
  165. data/lib/active_record/connection_adapters/oracle_adapter.rb +0 -690
  166. data/lib/active_record/connection_adapters/sqlserver_adapter.rb +0 -591
  167. data/lib/active_record/connection_adapters/sybase_adapter.rb +0 -662
  168. data/lib/active_record/deprecated_associations.rb +0 -104
  169. data/lib/active_record/deprecated_finders.rb +0 -44
  170. data/lib/active_record/vendor/simple.rb +0 -693
  171. data/lib/active_record/wrappers/yaml_wrapper.rb +0 -15
  172. data/lib/active_record/wrappings.rb +0 -58
  173. data/test/connections/native_sqlserver/connection.rb +0 -23
  174. data/test/connections/native_sqlserver_odbc/connection.rb +0 -25
  175. data/test/deprecated_associations_test.rb +0 -396
  176. data/test/fixtures/db_definitions/mysql.drop.sql +0 -32
  177. data/test/fixtures/db_definitions/mysql.sql +0 -234
  178. data/test/fixtures/db_definitions/mysql2.drop.sql +0 -2
  179. data/test/fixtures/db_definitions/mysql2.sql +0 -5
  180. data/test/fixtures/db_definitions/sqlserver.drop.sql +0 -34
  181. data/test/fixtures/db_definitions/sqlserver.sql +0 -243
  182. data/test/fixtures/db_definitions/sqlserver2.drop.sql +0 -2
  183. data/test/fixtures/db_definitions/sqlserver2.sql +0 -5
  184. data/test/fixtures/mixin.rb +0 -63
  185. data/test/mixin_nested_set_test.rb +0 -196
data/README CHANGED
@@ -176,7 +176,7 @@ A short rundown of the major features:
176
176
  )
177
177
 
178
178
  {Learn more}[link:classes/ActiveRecord/Base.html#M000081] and read about the built-in support for
179
- MySQL[link:classes/ActiveRecord/ConnectionAdapters/MysqlAdapter.html], PostgreSQL[link:classes/ActiveRecord/ConnectionAdapters/PostgreSQLAdapter.html], SQLite[link:classes/ActiveRecord/ConnectionAdapters/SQLiteAdapter.html], Oracle[link:classes/ActiveRecord/ConnectionAdapters/OCIAdapter.html], SQLServer[link:classes/ActiveRecord/ConnectionAdapters/SQLServerAdapter.html], and DB2[link:classes/ActiveRecord/ConnectionAdapters/DB2Adapter.html].
179
+ MySQL[link:classes/ActiveRecord/ConnectionAdapters/MysqlAdapter.html], PostgreSQL[link:classes/ActiveRecord/ConnectionAdapters/PostgreSQLAdapter.html], SQLite[link:classes/ActiveRecord/ConnectionAdapters/SQLiteAdapter.html], Oracle[link:classes/ActiveRecord/ConnectionAdapters/OracleAdapter.html], SQLServer[link:classes/ActiveRecord/ConnectionAdapters/SQLServerAdapter.html], and DB2[link:classes/ActiveRecord/ConnectionAdapters/DB2Adapter.html].
180
180
 
181
181
 
182
182
  * Logging support for Log4r[http://log4r.sourceforge.net] and Logger[http://www.ruby-doc.org/stdlib/libdoc/logger/rdoc]
@@ -23,42 +23,11 @@ Rake can be found at http://rake.rubyforge.org
23
23
  == Running by hand
24
24
 
25
25
  Unit tests are located in test directory. If you only want to run a single test suite,
26
- or don't want to bother with Rake, you can do so with something like:
26
+ you can do so with:
27
27
 
28
- cd test; ruby -I "connections/native_mysql" base_test.rb
28
+ rake test_mysql TEST=base_test.rb
29
29
 
30
- That'll run the base suite using the MySQL-Ruby adapter. Change the adapter
31
- and test suite name as needed.
30
+ That'll run the base suite using the MySQL-Ruby adapter.
32
31
 
33
- You can also run all the suites on a specific adapter with:
34
32
 
35
- cd test; all.sh "connections/native_mysql"
36
-
37
- == Faster tests
38
-
39
- If you are using a database that supports transactions, you can set the
40
- "AR_TX_FIXTURES" environment variable to "yes" to use transactional fixtures.
41
- This gives a very large speed boost. With rake:
42
-
43
- rake AR_TX_FIXTURES=yes
44
-
45
- Or, by hand:
46
-
47
- AR_TX_FIXTURES=yes ruby -I connections/native_sqlite3 base_test.rb
48
-
49
- == Testing with Oracle
50
-
51
- In order to allow for testing against Oracle using an "arunit" schema within an existing
52
- Oracle database, the database name and tns connection string must be set in environment
53
- variables prior to running the unit tests.
54
-
55
- $ export ARUNIT_DB_NAME=MYDB
56
- $ export ARUNIT_DB=MYDB
57
-
58
- The ARUNIT_DB_NAME variable should be set to the name by which the database knows
59
- itself, ie., what will be returned by the query:
60
-
61
- select sys_context('userenv','db_name') db from dual
62
-
63
- And the ARUNIT_DB variable should be set to the tns connection string.
64
33
 
data/Rakefile CHANGED
@@ -22,106 +22,127 @@ PKG_FILES = FileList[
22
22
  ].exclude(/\bCVS\b|~$/)
23
23
 
24
24
 
25
- desc "Default Task"
26
- task :default => [ :test_mysql, :test_sqlite, :test_postgresql ]
25
+ desc 'Run mysql, sqlite, and postgresql tests by default'
26
+ task :default => :test
27
27
 
28
- # Run the unit tests
28
+ desc 'Run mysql, sqlite, and postgresql tests'
29
+ task :test => %w(test_mysql test_sqlite test_sqlite3 test_postgresql)
29
30
 
30
- for adapter in %w( mysql postgresql sqlite sqlite3 firebird sqlserver sqlserver_odbc db2 oracle sybase openbase frontbase )
31
+ for adapter in %w( mysql postgresql sqlite sqlite3 firebird db2 oracle sybase openbase frontbase )
31
32
  Rake::TestTask.new("test_#{adapter}") { |t|
32
33
  t.libs << "test" << "test/connections/native_#{adapter}"
33
- if adapter =~ /^sqlserver/
34
- t.pattern = "test/**/*_test{,_sqlserver}.rb"
35
- else
36
- t.pattern = "test/**/*_test{,_#{adapter}}.rb"
37
- end
34
+ adapter_short = adapter == 'db2' ? adapter : adapter[/^[a-z]+/]
35
+ t.pattern = "test/**/*_test{,_#{adapter_short}}.rb"
38
36
  t.verbose = true
39
37
  }
38
+
39
+ namespace adapter do
40
+ task :test => "test_#{adapter}"
41
+ end
40
42
  end
41
43
 
42
44
  SCHEMA_PATH = File.join(File.dirname(__FILE__), *%w(test fixtures db_definitions))
43
45
 
44
- desc 'Build the MySQL test databases'
45
- task :build_mysql_databases do
46
- %x( mysqladmin create activerecord_unittest )
47
- %x( mysqladmin create activerecord_unittest2 )
48
- %x( mysql -e "grant all on activerecord_unittest.* to rails@localhost" )
49
- %x( mysql -e "grant all on activerecord_unittest2.* to rails@localhost" )
50
- %x( mysql activerecord_unittest < #{File.join(SCHEMA_PATH, 'mysql.sql')} )
51
- %x( mysql activerecord_unittest < #{File.join(SCHEMA_PATH, 'mysql2.sql')} )
52
- end
46
+ namespace :mysql do
47
+ desc 'Build the MySQL test databases'
48
+ task :build_databases do
49
+ %x( mysqladmin create activerecord_unittest )
50
+ %x( mysqladmin create activerecord_unittest2 )
51
+ %x( mysql -e "grant all on activerecord_unittest.* to rails@localhost" )
52
+ %x( mysql -e "grant all on activerecord_unittest2.* to rails@localhost" )
53
+ end
54
+
55
+ desc 'Drop the MySQL test databases'
56
+ task :drop_databases do
57
+ %x( mysqladmin -f drop activerecord_unittest )
58
+ %x( mysqladmin -f drop activerecord_unittest2 )
59
+ end
53
60
 
54
- desc 'Drop the MySQL test databases'
55
- task :drop_mysql_databases do
56
- %x( mysqladmin -f drop activerecord_unittest )
57
- %x( mysqladmin -f drop activerecord_unittest2 )
61
+ desc 'Rebuild the MySQL test databases'
62
+ task :rebuild_databases => [:drop_databases, :build_databases]
58
63
  end
59
64
 
60
- desc 'Rebuild the MySQL test databases'
61
- task :rebuild_mysql_databases => [:drop_mysql_databases, :build_mysql_databases]
65
+ task :build_mysql_databases => 'mysql:build_databases'
66
+ task :drop_mysql_databases => 'mysql:drop_databases'
67
+ task :rebuild_mysql_databases => 'mysql:rebuild_databases'
62
68
 
63
- desc 'Build the PostgreSQL test databases'
64
- task :build_postgresql_databases do
65
- %x( createdb -U postgres activerecord_unittest )
66
- %x( createdb -U postgres activerecord_unittest2 )
67
- %x( psql activerecord_unittest -f #{File.join(SCHEMA_PATH, 'postgresql.sql')} postgres )
68
- %x( psql activerecord_unittest2 -f #{File.join(SCHEMA_PATH, 'postgresql2.sql')} postgres )
69
- end
70
69
 
71
- desc 'Drop the PostgreSQL test databases'
72
- task :drop_postgresql_databases do
73
- %x( dropdb -U postgres activerecord_unittest )
74
- %x( dropdb -U postgres activerecord_unittest2 )
70
+ namespace :postgresql do
71
+ desc 'Build the PostgreSQL test databases'
72
+ task :build_databases do
73
+ %x( createdb -U postgres activerecord_unittest )
74
+ %x( createdb -U postgres activerecord_unittest2 )
75
+ %x( psql activerecord_unittest -f #{File.join(SCHEMA_PATH, 'postgresql.sql')} postgres )
76
+ %x( psql activerecord_unittest2 -f #{File.join(SCHEMA_PATH, 'postgresql2.sql')} postgres )
77
+ end
78
+
79
+ desc 'Drop the PostgreSQL test databases'
80
+ task :drop_databases do
81
+ %x( dropdb -U postgres activerecord_unittest )
82
+ %x( dropdb -U postgres activerecord_unittest2 )
83
+ end
84
+
85
+ desc 'Rebuild the PostgreSQL test databases'
86
+ task :rebuild_databases => [:drop_databases, :build_databases]
75
87
  end
76
88
 
77
- desc 'Rebuild the PostgreSQL test databases'
78
- task :rebuild_postgresql_databases => [:drop_postgresql_databases, :build_postgresql_databases]
89
+ task :build_postgresql_databases => 'postgresql:build_databases'
90
+ task :drop_postgresql_databases => 'postgresql:drop_databases'
91
+ task :rebuild_postgresql_databases => 'postgresql:rebuild_databases'
79
92
 
80
- desc 'Build the FrontBase test databases'
81
- task :build_frontbase_databases => :rebuild_frontbase_databases
82
93
 
83
- desc 'Rebuild the FrontBase test databases'
84
- task :rebuild_frontbase_databases do
85
- build_frontbase_database = Proc.new do |db_name, sql_definition_file|
86
- %(
87
- STOP DATABASE #{db_name};
88
- DELETE DATABASE #{db_name};
89
- CREATE DATABASE #{db_name};
94
+ namespace :frontbase do
95
+ desc 'Build the FrontBase test databases'
96
+ task :build_databases => :rebuild_frontbase_databases
90
97
 
91
- CONNECT TO #{db_name} AS SESSION_NAME USER _SYSTEM;
92
- SET COMMIT FALSE;
98
+ desc 'Rebuild the FrontBase test databases'
99
+ task :rebuild_databases do
100
+ build_frontbase_database = Proc.new do |db_name, sql_definition_file|
101
+ %(
102
+ STOP DATABASE #{db_name};
103
+ DELETE DATABASE #{db_name};
104
+ CREATE DATABASE #{db_name};
93
105
 
94
- CREATE USER RAILS;
95
- CREATE SCHEMA RAILS AUTHORIZATION RAILS;
96
- COMMIT;
106
+ CONNECT TO #{db_name} AS SESSION_NAME USER _SYSTEM;
107
+ SET COMMIT FALSE;
97
108
 
98
- SET SESSION AUTHORIZATION RAILS;
99
- SCRIPT '#{sql_definition_file}';
109
+ CREATE USER RAILS;
110
+ CREATE SCHEMA RAILS AUTHORIZATION RAILS;
111
+ COMMIT;
100
112
 
101
- COMMIT;
113
+ SET SESSION AUTHORIZATION RAILS;
114
+ SCRIPT '#{sql_definition_file}';
102
115
 
103
- DISCONNECT ALL;
104
- )
105
- end
106
- create_activerecord_unittest = build_frontbase_database['activerecord_unittest', File.join(SCHEMA_PATH, 'frontbase.sql')]
107
- create_activerecord_unittest2 = build_frontbase_database['activerecord_unittest2', File.join(SCHEMA_PATH, 'frontbase2.sql')]
108
- execute_frontbase_sql = Proc.new do |sql|
109
- system(<<-SHELL)
110
- /Library/FrontBase/bin/sql92 <<-SQL
111
- #{sql}
112
- SQL
113
- SHELL
116
+ COMMIT;
117
+
118
+ DISCONNECT ALL;
119
+ )
120
+ end
121
+ create_activerecord_unittest = build_frontbase_database['activerecord_unittest', File.join(SCHEMA_PATH, 'frontbase.sql')]
122
+ create_activerecord_unittest2 = build_frontbase_database['activerecord_unittest2', File.join(SCHEMA_PATH, 'frontbase2.sql')]
123
+ execute_frontbase_sql = Proc.new do |sql|
124
+ system(<<-SHELL)
125
+ /Library/FrontBase/bin/sql92 <<-SQL
126
+ #{sql}
127
+ SQL
128
+ SHELL
129
+ end
130
+ execute_frontbase_sql[create_activerecord_unittest]
131
+ execute_frontbase_sql[create_activerecord_unittest2]
114
132
  end
115
- execute_frontbase_sql[create_activerecord_unittest]
116
- execute_frontbase_sql[create_activerecord_unittest2]
117
133
  end
118
134
 
135
+ task :build_frontbase_databases => 'frontbase:build_databases'
136
+ task :rebuild_frontbase_databases => 'frontbase:rebuild_databases'
137
+
138
+
119
139
  # Generate the RDoc documentation
120
140
 
121
141
  Rake::RDocTask.new { |rdoc|
122
142
  rdoc.rdoc_dir = 'doc'
123
143
  rdoc.title = "Active Record -- Object-relation mapping put on rails"
124
144
  rdoc.options << '--line-numbers' << '--inline-source' << '-A cattr_accessor=object'
145
+ rdoc.options << '--charset' << 'utf-8'
125
146
  rdoc.template = "#{ENV['template']}.rb" if ENV['template']
126
147
  rdoc.rdoc_files.include('README', 'RUNNING_UNIT_TESTS', 'CHANGELOG')
127
148
  rdoc.rdoc_files.include('lib/**/*.rb')
@@ -138,7 +159,7 @@ end
138
159
 
139
160
  # Create compressed packages
140
161
 
141
- dist_dirs = [ "lib", "test", "examples", "dev-utils" ]
162
+ dist_dirs = [ "lib", "test", "examples" ]
142
163
 
143
164
  spec = Gem::Specification.new do |s|
144
165
  s.name = PKG_NAME
@@ -150,8 +171,8 @@ spec = Gem::Specification.new do |s|
150
171
  dist_dirs.each do |dir|
151
172
  s.files = s.files + Dir.glob( "#{dir}/**/*" ).delete_if { |item| item.include?( "\.svn" ) }
152
173
  end
153
-
154
- s.add_dependency('activesupport', '= 1.4.4' + PKG_BUILD)
174
+
175
+ s.add_dependency('activesupport', '= 2.0.0' + PKG_BUILD)
155
176
 
156
177
  s.files.delete "test/fixtures/fixture_database.sqlite"
157
178
  s.files.delete "test/fixtures/fixture_database_2.sqlite"
@@ -163,13 +184,13 @@ spec = Gem::Specification.new do |s|
163
184
  s.has_rdoc = true
164
185
  s.extra_rdoc_files = %w( README )
165
186
  s.rdoc_options.concat ['--main', 'README']
166
-
187
+
167
188
  s.author = "David Heinemeier Hansson"
168
189
  s.email = "david@loudthinking.com"
169
190
  s.homepage = "http://www.rubyonrails.org"
170
191
  s.rubyforge_project = "activerecord"
171
192
  end
172
-
193
+
173
194
  Rake::GemPackageTask.new(spec) do |p|
174
195
  p.gem_spec = spec
175
196
  p.need_tar = true
@@ -190,10 +211,10 @@ task :lines do
190
211
  codelines += 1
191
212
  end
192
213
  puts "L: #{sprintf("%4d", lines)}, LOC #{sprintf("%4d", codelines)} | #{file_name}"
193
-
214
+
194
215
  total_lines += lines
195
216
  total_codelines += codelines
196
-
217
+
197
218
  lines, codelines = 0, 0
198
219
  end
199
220
 
@@ -204,13 +225,13 @@ end
204
225
  # Publishing ------------------------------------------------------
205
226
 
206
227
  desc "Publish the beta gem"
207
- task :pgem => [:package] do
228
+ task :pgem => [:package] do
208
229
  Rake::SshFilePublisher.new("davidhh@wrath.rubyonrails.org", "public_html/gems/gems", "pkg", "#{PKG_FILE_NAME}.gem").upload
209
230
  `ssh davidhh@wrath.rubyonrails.org './gemupdate.sh'`
210
231
  end
211
232
 
212
233
  desc "Publish the API documentation"
213
- task :pdoc => [:rdoc] do
234
+ task :pdoc => [:rdoc] do
214
235
  Rake::SshDirPublisher.new("davidhh@wrath.rubyonrails.org", "public_html/ar", "doc").upload
215
236
  end
216
237
 
@@ -223,4 +244,4 @@ task :release => [ :package ] do
223
244
  rubyforge = RubyForge.new
224
245
  rubyforge.login
225
246
  rubyforge.add_release(PKG_NAME, PKG_NAME, "REL #{PKG_VERSION}", *packages)
226
- end
247
+ end
data/install.rb CHANGED
@@ -18,7 +18,7 @@ unless $sitedir
18
18
  end
19
19
  end
20
20
 
21
- # the acual gruntwork
21
+ # the actual gruntwork
22
22
  Dir.chdir("lib")
23
23
 
24
24
  Find.find("active_record", "active_record.rb") { |f|
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2004-2006 David Heinemeier Hansson
2
+ # Copyright (c) 2004-2007 David Heinemeier Hansson
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining
5
5
  # a copy of this software and associated documentation files (the
@@ -24,18 +24,21 @@
24
24
  $:.unshift(File.dirname(__FILE__)) unless
25
25
  $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
26
26
 
27
- unless defined?(ActiveSupport)
28
- begin
29
- $:.unshift(File.dirname(__FILE__) + "/../../activesupport/lib")
30
- require 'active_support'
31
- rescue LoadError
27
+ unless defined? ActiveSupport
28
+ active_support_path = File.dirname(__FILE__) + "/../../activesupport/lib"
29
+ if File.exist?(active_support_path)
30
+ $:.unshift active_support_path
31
+ require 'active_support'
32
+ else
32
33
  require 'rubygems'
33
34
  gem 'activesupport'
35
+ require 'active_support'
34
36
  end
35
37
  end
36
38
 
37
39
  require 'active_record/base'
38
40
  require 'active_record/observer'
41
+ require 'active_record/query_cache'
39
42
  require 'active_record/validations'
40
43
  require 'active_record/callbacks'
41
44
  require 'active_record/reflection'
@@ -43,18 +46,16 @@ require 'active_record/associations'
43
46
  require 'active_record/aggregations'
44
47
  require 'active_record/transactions'
45
48
  require 'active_record/timestamp'
46
- require 'active_record/acts/list'
47
- require 'active_record/acts/tree'
48
- require 'active_record/acts/nested_set'
49
49
  require 'active_record/locking/optimistic'
50
50
  require 'active_record/locking/pessimistic'
51
51
  require 'active_record/migration'
52
52
  require 'active_record/schema'
53
53
  require 'active_record/calculations'
54
- require 'active_record/xml_serialization'
54
+ require 'active_record/serialization'
55
55
  require 'active_record/attribute_methods'
56
56
 
57
57
  ActiveRecord::Base.class_eval do
58
+ extend ActiveRecord::QueryCache
58
59
  include ActiveRecord::Validations
59
60
  include ActiveRecord::Locking::Optimistic
60
61
  include ActiveRecord::Locking::Pessimistic
@@ -65,21 +66,11 @@ ActiveRecord::Base.class_eval do
65
66
  include ActiveRecord::Aggregations
66
67
  include ActiveRecord::Transactions
67
68
  include ActiveRecord::Reflection
68
- include ActiveRecord::Acts::Tree
69
- include ActiveRecord::Acts::List
70
- include ActiveRecord::Acts::NestedSet
71
69
  include ActiveRecord::Calculations
72
- include ActiveRecord::XmlSerialization
70
+ include ActiveRecord::Serialization
73
71
  include ActiveRecord::AttributeMethods
74
72
  end
75
73
 
76
- unless defined?(RAILS_CONNECTION_ADAPTERS)
77
- RAILS_CONNECTION_ADAPTERS = %w( mysql postgresql sqlite firebird sqlserver db2 oracle sybase openbase frontbase )
78
- end
74
+ require 'active_record/connection_adapters/abstract_adapter'
79
75
 
80
- RAILS_CONNECTION_ADAPTERS.each do |adapter|
81
- require "active_record/connection_adapters/" + adapter + "_adapter"
82
- end
83
-
84
- require 'active_record/query_cache'
85
76
  require 'active_record/schema_dumper'
@@ -70,7 +70,7 @@ module ActiveRecord
70
70
  # end
71
71
  #
72
72
  # Now it's possible to access attributes from the database through the value objects instead. If you choose to name the
73
- # composition the same as the attributes name, it will be the only way to access that attribute. That's the case with our
73
+ # composition the same as the attribute's name, it will be the only way to access that attribute. That's the case with our
74
74
  # +balance+ attribute. You interact with the value objects just like you would any other attribute, though:
75
75
  #
76
76
  # customer.balance = Money.new(20) # sets the Money value object and the attribute
@@ -92,19 +92,19 @@ module ActiveRecord
92
92
  #
93
93
  # == Writing value objects
94
94
  #
95
- # Value objects are immutable and interchangeable objects that represent a given value, such as a Money object representing
96
- # $5. Two Money objects both representing $5 should be equal (through methods such as == and <=> from Comparable if ranking
97
- # makes sense). This is unlike entity objects where equality is determined by identity. An entity class such as Customer can
95
+ # Value objects are immutable and interchangeable objects that represent a given value, such as a +Money+ object representing
96
+ # $5. Two +Money+ objects both representing $5 should be equal (through methods such as == and <=> from +Comparable+ if ranking
97
+ # makes sense). This is unlike entity objects where equality is determined by identity. An entity class such as +Customer+ can
98
98
  # easily have two different objects that both have an address on Hyancintvej. Entity identity is determined by object or
99
- # relational unique identifiers (such as primary keys). Normal ActiveRecord::Base classes are entity objects.
99
+ # relational unique identifiers (such as primary keys). Normal <tt>ActiveRecord::Base</tt> classes are entity objects.
100
100
  #
101
- # It's also important to treat the value objects as immutable. Don't allow the Money object to have its amount changed after
102
- # creation. Create a new money object with the new value instead. This is exemplified by the Money#exchanged_to method that
101
+ # It's also important to treat the value objects as immutable. Don't allow the +Money+ object to have its amount changed after
102
+ # creation. Create a new +Money+ object with the new value instead. This is exemplified by the <tt>Money#exchanged_to</tt> method that
103
103
  # returns a new value object instead of changing its own values. Active Record won't persist value objects that have been
104
- # changed through other means than the writer method.
104
+ # changed through means other than the writer method.
105
105
  #
106
106
  # The immutable requirement is enforced by Active Record by freezing any object assigned as a value object. Attempting to
107
- # change it afterwards will result in a TypeError.
107
+ # change it afterwards will result in a <tt>TypeError</tt>.
108
108
  #
109
109
  # Read more about value objects on http://c2.com/cgi/wiki?ValueObject and on the dangers of not keeping value objects
110
110
  # immutable on http://c2.com/cgi/wiki?ValueObjectsShouldBeImmutable
@@ -119,71 +119,60 @@ module ActiveRecord
119
119
  # * <tt>:mapping</tt> - specifies a number of mapping arrays (attribute, parameter) that bind an attribute name
120
120
  # to a constructor parameter on the value class.
121
121
  # * <tt>:allow_nil</tt> - specifies that the aggregate object will not be instantiated when all mapped
122
- # attributes are nil. Setting the aggregate class to nil has the effect of writing nil to all mapped attributes.
123
- # This defaults to false.
122
+ # attributes are +nil+. Setting the aggregate class to +nil+ has the effect of writing +nil+ to all mapped attributes.
123
+ # This defaults to +false+.
124
+ #
125
+ # An optional block can be passed to convert the argument that is passed to the writer method into an instance of
126
+ # <tt>:class_name</tt>. The block will only be called if the argument is not already an instance of <tt>:class_name</tt>.
124
127
  #
125
128
  # Option examples:
126
129
  # composed_of :temperature, :mapping => %w(reading celsius)
127
- # composed_of :balance, :class_name => "Money", :mapping => %w(balance amount)
130
+ # composed_of(:balance, :class_name => "Money", :mapping => %w(balance amount)) {|balance| balance.to_money }
128
131
  # composed_of :address, :mapping => [ %w(address_street street), %w(address_city city) ]
129
132
  # composed_of :gps_location
130
133
  # composed_of :gps_location, :allow_nil => true
131
134
  #
132
- def composed_of(part_id, options = {})
135
+ def composed_of(part_id, options = {}, &block)
133
136
  options.assert_valid_keys(:class_name, :mapping, :allow_nil)
134
137
 
135
138
  name = part_id.id2name
136
139
  class_name = options[:class_name] || name.camelize
137
140
  mapping = options[:mapping] || [ name, name ]
141
+ mapping = [ mapping ] unless mapping.first.is_a?(Array)
138
142
  allow_nil = options[:allow_nil] || false
139
143
 
140
144
  reader_method(name, class_name, mapping, allow_nil)
141
- writer_method(name, class_name, mapping, allow_nil)
145
+ writer_method(name, class_name, mapping, allow_nil, block)
142
146
 
143
147
  create_reflection(:composed_of, part_id, options, self)
144
148
  end
145
149
 
146
150
  private
147
151
  def reader_method(name, class_name, mapping, allow_nil)
148
- mapping = (Array === mapping.first ? mapping : [ mapping ])
149
-
150
- allow_nil_condition = if allow_nil
151
- mapping.collect { |pair| "!read_attribute(\"#{pair.first}\").nil?"}.join(" && ")
152
- else
153
- "true"
154
- end
155
-
156
- module_eval <<-end_eval
157
- def #{name}(force_reload = false)
158
- if (@#{name}.nil? || force_reload) && #{allow_nil_condition}
159
- @#{name} = #{class_name}.new(#{mapping.collect { |pair| "read_attribute(\"#{pair.first}\")"}.join(", ")})
152
+ module_eval do
153
+ define_method(name) do |*args|
154
+ force_reload = args.first || false
155
+ if (instance_variable_get("@#{name}").nil? || force_reload) && (!allow_nil || mapping.any? {|pair| !read_attribute(pair.first).nil? })
156
+ instance_variable_set("@#{name}", class_name.constantize.new(*mapping.collect {|pair| read_attribute(pair.first)}))
160
157
  end
161
- return @#{name}
158
+ return instance_variable_get("@#{name}")
162
159
  end
163
- end_eval
164
- end
165
-
166
- def writer_method(name, class_name, mapping, allow_nil)
167
- mapping = (Array === mapping.first ? mapping : [ mapping ])
160
+ end
168
161
 
169
- if allow_nil
170
- module_eval <<-end_eval
171
- def #{name}=(part)
172
- if part.nil?
173
- #{mapping.collect { |pair| "@attributes[\"#{pair.first}\"] = nil" }.join("\n")}
174
- else
175
- @#{name} = part.freeze
176
- #{mapping.collect { |pair| "@attributes[\"#{pair.first}\"] = part.#{pair.last}" }.join("\n")}
177
- end
178
- end
179
- end_eval
180
- else
181
- module_eval <<-end_eval
182
- def #{name}=(part)
183
- @#{name} = part.freeze
184
- #{mapping.collect{ |pair| "@attributes[\"#{pair.first}\"] = part.#{pair.last}" }.join("\n")}
162
+ end
163
+
164
+ def writer_method(name, class_name, mapping, allow_nil, conversion)
165
+ module_eval do
166
+ define_method("#{name}=") do |part|
167
+ if part.nil? && allow_nil
168
+ mapping.each { |pair| @attributes[pair.first] = nil }
169
+ instance_variable_set("@#{name}", nil)
170
+ else
171
+ part = conversion.call(part) unless part.is_a?(class_name.constantize) || conversion.nil?
172
+ mapping.each { |pair| @attributes[pair.first] = part.send(pair.last) }
173
+ instance_variable_set("@#{name}", part.freeze)
185
174
  end
186
- end_eval
175
+ end
187
176
  end
188
177
  end
189
178
  end