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.
- data/CHANGELOG +2454 -34
- data/README +1 -1
- data/RUNNING_UNIT_TESTS +3 -34
- data/Rakefile +98 -77
- data/install.rb +1 -1
- data/lib/active_record.rb +13 -22
- data/lib/active_record/aggregations.rb +38 -49
- data/lib/active_record/associations.rb +452 -333
- data/lib/active_record/associations/association_collection.rb +66 -20
- data/lib/active_record/associations/association_proxy.rb +9 -8
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +46 -51
- data/lib/active_record/associations/has_many_association.rb +21 -57
- data/lib/active_record/associations/has_many_through_association.rb +38 -18
- data/lib/active_record/associations/has_one_association.rb +30 -14
- data/lib/active_record/attribute_methods.rb +253 -0
- data/lib/active_record/base.rb +719 -494
- data/lib/active_record/calculations.rb +62 -63
- data/lib/active_record/callbacks.rb +57 -83
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +38 -9
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +56 -15
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +87 -0
- data/lib/active_record/connection_adapters/abstract/quoting.rb +23 -12
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +191 -62
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +37 -34
- data/lib/active_record/connection_adapters/abstract_adapter.rb +28 -17
- data/lib/active_record/connection_adapters/mysql_adapter.rb +119 -37
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +473 -210
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +34 -0
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +91 -107
- data/lib/active_record/fixtures.rb +503 -113
- data/lib/active_record/locking/optimistic.rb +72 -34
- data/lib/active_record/migration.rb +80 -57
- data/lib/active_record/observer.rb +13 -10
- data/lib/active_record/query_cache.rb +16 -57
- data/lib/active_record/reflection.rb +35 -38
- data/lib/active_record/schema.rb +5 -5
- data/lib/active_record/schema_dumper.rb +35 -13
- data/lib/active_record/serialization.rb +98 -0
- data/lib/active_record/serializers/json_serializer.rb +71 -0
- data/lib/active_record/{xml_serialization.rb → serializers/xml_serializer.rb} +90 -83
- data/lib/active_record/timestamp.rb +20 -21
- data/lib/active_record/transactions.rb +39 -43
- data/lib/active_record/validations.rb +256 -107
- data/lib/active_record/version.rb +3 -3
- data/lib/activerecord.rb +1 -0
- data/test/aaa_create_tables_test.rb +15 -2
- data/test/abstract_unit.rb +24 -17
- data/test/active_schema_test_mysql.rb +20 -8
- data/test/adapter_test.rb +23 -5
- data/test/adapter_test_sqlserver.rb +15 -1
- data/test/aggregations_test.rb +16 -1
- data/test/all.sh +2 -2
- data/test/associations/ar_joins_test.rb +0 -0
- data/test/associations/callbacks_test.rb +51 -30
- data/test/associations/cascaded_eager_loading_test.rb +1 -29
- data/test/associations/eager_singularization_test.rb +145 -0
- data/test/associations/eager_test.rb +42 -6
- data/test/associations/extension_test.rb +6 -1
- data/test/associations/inner_join_association_test.rb +88 -0
- data/test/associations/join_model_test.rb +47 -16
- data/test/associations_test.rb +449 -226
- data/test/attribute_methods_test.rb +97 -0
- data/test/base_test.rb +251 -105
- data/test/binary_test.rb +22 -27
- data/test/calculations_test.rb +37 -5
- data/test/callbacks_test.rb +23 -0
- data/test/connection_test_firebird.rb +2 -2
- data/test/connection_test_mysql.rb +30 -0
- data/test/connections/native_mysql/connection.rb +3 -0
- data/test/connections/native_sqlite/connection.rb +5 -14
- data/test/connections/native_sqlite3/connection.rb +5 -14
- data/test/connections/native_sqlite3/in_memory_connection.rb +1 -1
- data/test/{copy_table_sqlite.rb → copy_table_test_sqlite.rb} +8 -3
- data/test/datatype_test_postgresql.rb +178 -27
- data/test/{empty_date_time_test.rb → date_time_test.rb} +13 -1
- data/test/defaults_test.rb +8 -1
- data/test/deprecated_finder_test.rb +7 -128
- data/test/finder_test.rb +192 -54
- data/test/fixtures/all/developers.yml +0 -0
- data/test/fixtures/all/people.csv +0 -0
- data/test/fixtures/all/tasks.yml +0 -0
- data/test/fixtures/author.rb +12 -5
- data/test/fixtures/binaries.yml +130 -435
- data/test/fixtures/category.rb +6 -0
- data/test/fixtures/company.rb +8 -1
- data/test/fixtures/computer.rb +1 -0
- data/test/fixtures/contact.rb +16 -0
- data/test/fixtures/customer.rb +2 -2
- data/test/fixtures/db_definitions/db2.drop.sql +1 -0
- data/test/fixtures/db_definitions/db2.sql +4 -0
- data/test/fixtures/db_definitions/firebird.drop.sql +3 -1
- data/test/fixtures/db_definitions/firebird.sql +6 -0
- data/test/fixtures/db_definitions/frontbase.drop.sql +1 -0
- data/test/fixtures/db_definitions/frontbase.sql +5 -0
- data/test/fixtures/db_definitions/openbase.sql +41 -25
- data/test/fixtures/db_definitions/oracle.drop.sql +2 -0
- data/test/fixtures/db_definitions/oracle.sql +5 -0
- data/test/fixtures/db_definitions/postgresql.drop.sql +7 -0
- data/test/fixtures/db_definitions/postgresql.sql +87 -58
- data/test/fixtures/db_definitions/postgresql2.sql +1 -2
- data/test/fixtures/db_definitions/schema.rb +280 -0
- data/test/fixtures/db_definitions/schema2.rb +11 -0
- data/test/fixtures/db_definitions/sqlite.drop.sql +1 -0
- data/test/fixtures/db_definitions/sqlite.sql +4 -0
- data/test/fixtures/db_definitions/sybase.drop.sql +1 -0
- data/test/fixtures/db_definitions/sybase.sql +4 -0
- data/test/fixtures/developer.rb +10 -0
- data/test/fixtures/example.log +1 -0
- data/test/fixtures/flowers.jpg +0 -0
- data/test/fixtures/item.rb +7 -0
- data/test/fixtures/items.yml +4 -0
- data/test/fixtures/joke.rb +0 -3
- data/test/fixtures/matey.rb +4 -0
- data/test/fixtures/mateys.yml +4 -0
- data/test/fixtures/minimalistic.rb +2 -0
- data/test/fixtures/minimalistics.yml +2 -0
- data/test/fixtures/mixins.yml +2 -100
- data/test/fixtures/parrot.rb +13 -0
- data/test/fixtures/parrots.yml +27 -0
- data/test/fixtures/parrots_pirates.yml +7 -0
- data/test/fixtures/pirate.rb +5 -0
- data/test/fixtures/pirates.yml +9 -0
- data/test/fixtures/post.rb +1 -0
- data/test/fixtures/project.rb +3 -2
- data/test/fixtures/reserved_words/distinct.yml +5 -0
- data/test/fixtures/reserved_words/distincts_selects.yml +11 -0
- data/test/fixtures/reserved_words/group.yml +14 -0
- data/test/fixtures/reserved_words/select.yml +8 -0
- data/test/fixtures/reserved_words/values.yml +7 -0
- data/test/fixtures/ship.rb +3 -0
- data/test/fixtures/ships.yml +5 -0
- data/test/fixtures/tagging.rb +4 -0
- data/test/fixtures/taggings.yml +8 -1
- data/test/fixtures/topic.rb +13 -1
- data/test/fixtures/treasure.rb +4 -0
- data/test/fixtures/treasures.yml +10 -0
- data/test/fixtures_test.rb +205 -24
- data/test/inheritance_test.rb +7 -1
- data/test/json_serialization_test.rb +180 -0
- data/test/lifecycle_test.rb +1 -1
- data/test/locking_test.rb +85 -2
- data/test/migration_test.rb +206 -40
- data/test/mixin_test.rb +13 -515
- data/test/pk_test.rb +3 -6
- data/test/query_cache_test.rb +104 -0
- data/test/reflection_test.rb +16 -0
- data/test/reserved_word_test_mysql.rb +177 -0
- data/test/schema_dumper_test.rb +38 -3
- data/test/serialization_test.rb +47 -0
- data/test/transactions_test.rb +74 -23
- data/test/unconnected_test.rb +1 -1
- data/test/validations_test.rb +322 -32
- data/test/xml_serialization_test.rb +121 -44
- metadata +48 -41
- data/examples/associations.rb +0 -87
- data/examples/shared_setup.rb +0 -15
- data/examples/validation.rb +0 -85
- data/lib/active_record/acts/list.rb +0 -256
- data/lib/active_record/acts/nested_set.rb +0 -211
- data/lib/active_record/acts/tree.rb +0 -96
- data/lib/active_record/connection_adapters/db2_adapter.rb +0 -228
- data/lib/active_record/connection_adapters/firebird_adapter.rb +0 -728
- data/lib/active_record/connection_adapters/frontbase_adapter.rb +0 -861
- data/lib/active_record/connection_adapters/openbase_adapter.rb +0 -350
- data/lib/active_record/connection_adapters/oracle_adapter.rb +0 -690
- data/lib/active_record/connection_adapters/sqlserver_adapter.rb +0 -591
- data/lib/active_record/connection_adapters/sybase_adapter.rb +0 -662
- data/lib/active_record/deprecated_associations.rb +0 -104
- data/lib/active_record/deprecated_finders.rb +0 -44
- data/lib/active_record/vendor/simple.rb +0 -693
- data/lib/active_record/wrappers/yaml_wrapper.rb +0 -15
- data/lib/active_record/wrappings.rb +0 -58
- data/test/connections/native_sqlserver/connection.rb +0 -23
- data/test/connections/native_sqlserver_odbc/connection.rb +0 -25
- data/test/deprecated_associations_test.rb +0 -396
- data/test/fixtures/db_definitions/mysql.drop.sql +0 -32
- data/test/fixtures/db_definitions/mysql.sql +0 -234
- data/test/fixtures/db_definitions/mysql2.drop.sql +0 -2
- data/test/fixtures/db_definitions/mysql2.sql +0 -5
- data/test/fixtures/db_definitions/sqlserver.drop.sql +0 -34
- data/test/fixtures/db_definitions/sqlserver.sql +0 -243
- data/test/fixtures/db_definitions/sqlserver2.drop.sql +0 -2
- data/test/fixtures/db_definitions/sqlserver2.sql +0 -5
- data/test/fixtures/mixin.rb +0 -63
- 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/
|
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]
|
data/RUNNING_UNIT_TESTS
CHANGED
@@ -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
|
-
|
26
|
+
you can do so with:
|
27
27
|
|
28
|
-
|
28
|
+
rake test_mysql TEST=base_test.rb
|
29
29
|
|
30
|
-
That'll run the base suite using the MySQL-Ruby 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
|
26
|
-
task :default =>
|
25
|
+
desc 'Run mysql, sqlite, and postgresql tests by default'
|
26
|
+
task :default => :test
|
27
27
|
|
28
|
-
|
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
|
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
|
-
|
34
|
-
|
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
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
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 '
|
55
|
-
task :
|
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
|
-
|
61
|
-
task :
|
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
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
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
|
-
|
78
|
-
task :
|
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
|
-
|
84
|
-
|
85
|
-
|
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
|
-
|
92
|
-
|
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
|
-
|
95
|
-
|
96
|
-
COMMIT;
|
106
|
+
CONNECT TO #{db_name} AS SESSION_NAME USER _SYSTEM;
|
107
|
+
SET COMMIT FALSE;
|
97
108
|
|
98
|
-
|
99
|
-
|
109
|
+
CREATE USER RAILS;
|
110
|
+
CREATE SCHEMA RAILS AUTHORIZATION RAILS;
|
111
|
+
COMMIT;
|
100
112
|
|
101
|
-
|
113
|
+
SET SESSION AUTHORIZATION RAILS;
|
114
|
+
SCRIPT '#{sql_definition_file}';
|
102
115
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
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"
|
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', '=
|
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
data/lib/active_record.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright (c) 2004-
|
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?
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
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/
|
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::
|
70
|
+
include ActiveRecord::Serialization
|
73
71
|
include ActiveRecord::AttributeMethods
|
74
72
|
end
|
75
73
|
|
76
|
-
|
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
|
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
|
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
|
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
|
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
|
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
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
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
|
-
|
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
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
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
|
-
|
175
|
+
end
|
187
176
|
end
|
188
177
|
end
|
189
178
|
end
|