activerecord 1.6.0 → 1.7.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 (96) hide show
  1. data/CHANGELOG +78 -0
  2. data/README +20 -29
  3. data/RUNNING_UNIT_TESTS +1 -2
  4. data/examples/validation.rb +0 -3
  5. data/install.rb +3 -16
  6. data/lib/active_record.rb +11 -4
  7. data/lib/active_record/aggregations.rb +2 -2
  8. data/lib/active_record/associations.rb +8 -8
  9. data/lib/active_record/associations/association_collection.rb +1 -1
  10. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +1 -1
  11. data/lib/active_record/base.rb +117 -43
  12. data/lib/active_record/callbacks.rb +2 -2
  13. data/lib/active_record/connection_adapters/abstract_adapter.rb +7 -14
  14. data/lib/active_record/connection_adapters/db2_adapter.rb +33 -22
  15. data/lib/active_record/connection_adapters/mysql_adapter.rb +74 -33
  16. data/lib/active_record/connection_adapters/oci_adapter.rb +265 -0
  17. data/lib/active_record/connection_adapters/postgresql_adapter.rb +23 -3
  18. data/lib/active_record/connection_adapters/sqlite_adapter.rb +13 -4
  19. data/lib/active_record/connection_adapters/sqlserver_adapter.rb +158 -67
  20. data/lib/active_record/deprecated_associations.rb +4 -4
  21. data/lib/active_record/fixtures.rb +12 -5
  22. data/lib/active_record/locking.rb +22 -22
  23. data/lib/active_record/observer.rb +6 -3
  24. data/lib/active_record/timestamp.rb +15 -5
  25. data/lib/active_record/transactions.rb +4 -4
  26. data/lib/active_record/validations.rb +272 -189
  27. data/lib/active_record/wrappings.rb +2 -2
  28. data/rakefile +17 -2
  29. data/test/aaa_create_tables_test.rb +58 -0
  30. data/test/abstract_unit.rb +3 -2
  31. data/test/aggregations_test.rb +0 -1
  32. data/test/associations_test.rb +27 -28
  33. data/test/base_test.rb +74 -2
  34. data/test/binary_test.rb +6 -2
  35. data/test/class_inheritable_attributes_test.rb +1 -1
  36. data/test/column_alias_test.rb +9 -2
  37. data/test/connections/native_oci/connection.rb +25 -0
  38. data/test/connections/native_sqlite/connection.rb +4 -1
  39. data/test/connections/native_sqlite3/connection.rb +4 -2
  40. data/test/deprecated_associations_test.rb +4 -5
  41. data/test/finder_test.rb +20 -4
  42. data/test/fixtures/db_definitions/create_oracle_db.bat +5 -0
  43. data/test/fixtures/db_definitions/create_oracle_db.sh +5 -0
  44. data/test/fixtures/db_definitions/db2.drop.sql +18 -0
  45. data/test/fixtures/db_definitions/db2.sql +1 -0
  46. data/test/fixtures/db_definitions/db22.drop.sql +2 -0
  47. data/test/fixtures/db_definitions/db22.sql +1 -0
  48. data/test/fixtures/db_definitions/drop_oracle_tables.sql +35 -0
  49. data/test/fixtures/db_definitions/drop_oracle_tables2.sql +3 -0
  50. data/test/fixtures/db_definitions/mysql.drop.sql +18 -0
  51. data/test/fixtures/db_definitions/mysql.sql +2 -1
  52. data/test/fixtures/db_definitions/mysql2.drop.sql +2 -0
  53. data/test/fixtures/db_definitions/mysql2.sql +1 -0
  54. data/test/fixtures/db_definitions/oci.drop.sql +18 -0
  55. data/test/fixtures/db_definitions/oci.sql +167 -0
  56. data/test/fixtures/db_definitions/oci2.drop.sql +2 -0
  57. data/test/fixtures/db_definitions/oci2.sql +6 -0
  58. data/test/fixtures/db_definitions/postgresql.drop.sql +18 -0
  59. data/test/fixtures/db_definitions/postgresql.sql +2 -1
  60. data/test/fixtures/db_definitions/postgresql2.drop.sql +2 -0
  61. data/test/fixtures/db_definitions/postgresql2.sql +2 -1
  62. data/test/fixtures/db_definitions/sqlite.drop.sql +18 -0
  63. data/test/fixtures/db_definitions/sqlite.sql +2 -1
  64. data/test/fixtures/db_definitions/sqlite2.drop.sql +2 -0
  65. data/test/fixtures/db_definitions/sqlite2.sql +1 -0
  66. data/test/fixtures/db_definitions/sqlserver.drop.sql +18 -0
  67. data/test/fixtures/db_definitions/sqlserver.sql +1 -0
  68. data/test/fixtures/db_definitions/sqlserver2.drop.sql +2 -0
  69. data/test/fixtures/db_definitions/sqlserver2.sql +1 -0
  70. data/test/fixtures/fixture_database.sqlite +0 -0
  71. data/test/fixtures/fixture_database_2.sqlite +0 -0
  72. data/test/fixtures/topics.yml +3 -3
  73. data/test/lifecycle_test.rb +0 -1
  74. data/test/modules_test.rb +0 -1
  75. data/test/reflection_test.rb +0 -1
  76. data/test/validations_test.rb +229 -41
  77. metadata +36 -28
  78. data/dev-utils/eval_debugger.rb +0 -14
  79. data/lib/active_record/support/binding_of_caller.rb +0 -83
  80. data/lib/active_record/support/breakpoint.rb +0 -518
  81. data/lib/active_record/support/class_attribute_accessors.rb +0 -57
  82. data/lib/active_record/support/class_inheritable_attributes.rb +0 -117
  83. data/lib/active_record/support/clean_logger.rb +0 -10
  84. data/lib/active_record/support/core_ext.rb +0 -1
  85. data/lib/active_record/support/core_ext/hash.rb +0 -5
  86. data/lib/active_record/support/core_ext/hash/keys.rb +0 -35
  87. data/lib/active_record/support/core_ext/numeric.rb +0 -7
  88. data/lib/active_record/support/core_ext/numeric/bytes.rb +0 -33
  89. data/lib/active_record/support/core_ext/numeric/time.rb +0 -59
  90. data/lib/active_record/support/core_ext/object_and_class.rb +0 -24
  91. data/lib/active_record/support/core_ext/string.rb +0 -5
  92. data/lib/active_record/support/core_ext/string/inflections.rb +0 -45
  93. data/lib/active_record/support/dependencies.rb +0 -63
  94. data/lib/active_record/support/inflector.rb +0 -84
  95. data/lib/active_record/support/misc.rb +0 -8
  96. data/lib/active_record/support/module_attribute_accessors.rb +0 -57
data/CHANGELOG CHANGED
@@ -1,3 +1,81 @@
1
+ *1.7.0* (24th February, 2005)
2
+
3
+ * Changed the auto-timestamping feature to use ActiveRecord::Base.default_timezone instead of entertaining the parallel ActiveRecord::Base.timestamps_gmt method. The latter is now deprecated and will throw a warning on use (but still work) #710 [Jamis Buck]
4
+
5
+ * Added a OCI8-based Oracle adapter that has been verified to work with Oracle 8 and 9 #629 [Graham Jenkins]. Usage notes:
6
+
7
+ 1. Key generation uses a sequence "rails_sequence" for all tables. (I couldn't find a simple
8
+ and safe way of passing table-specific sequence information to the adapter.)
9
+ 2. Oracle uses DATE or TIMESTAMP datatypes for both dates and times. Consequently I have had to
10
+ resort to some hacks to get data converted to Date or Time in Ruby.
11
+ If the column_name ends in _at (like created_at, updated_at) it's created as a Ruby Time. Else if the
12
+ hours/minutes/seconds are 0, I make it a Ruby Date. Else it's a Ruby Time.
13
+ This is nasty - but if you use Duck Typing you'll probably not care very much.
14
+ In 9i it's tempting to map DATE to Date and TIMESTAMP to Time but I don't think that is
15
+ valid - too many databases use DATE for both.
16
+ Timezones and sub-second precision on timestamps are not supported.
17
+ 3. Default values that are functions (such as "SYSDATE") are not supported. This is a
18
+ restriction of the way active record supports default values.
19
+ 4. Referential integrity constraints are not fully supported. Under at least
20
+ some circumstances, active record appears to delete parent and child records out of
21
+ sequence and out of transaction scope. (Or this may just be a problem of test setup.)
22
+
23
+ The OCI8 driver can be retrieved from http://rubyforge.org/projects/ruby-oci8/
24
+
25
+ * Added option :schema_order to the PostgreSQL adapter to support the use of multiple schemas per database #697 [YuriSchimke]
26
+
27
+ * Optimized the SQL used to generate has_and_belongs_to_many queries by listing the join table first #693 [yerejm]
28
+
29
+ * Fixed that when using validation macros with a custom message, if you happened to use single quotes in the message string you would get a parsing error #657 [tonka]
30
+
31
+ * Fixed that Active Record would throw Broken Pipe errors with FCGI when the MySQL connection timed out instead of reconnecting #428 [Nicholas Seckar]
32
+
33
+ * Added options to specify an SSL connection for MySQL. Define the following attributes in the connection config (config/database.yml in Rails) to use it: sslkey, sslcert, sslca, sslcapath, sslcipher. To use SSL with no client certs, just set :sslca = '/dev/null'. http://dev.mysql.com/doc/mysql/en/secure-connections.html #604 [daniel@nightrunner.com]
34
+
35
+ * Added automatic dropping/creating of test tables for running the unit tests on all databases #587 [adelle@bullet.net.au]
36
+
37
+ * Fixed that find_by_* would fail when column names had numbers #670 [demetrius]
38
+
39
+ * Fixed the SQL Server adapter on a bunch of issues #667 [DeLynn]
40
+
41
+ 1. Created a new columns method that is much cleaner.
42
+ 2. Corrected a problem with the select and select_all methods
43
+ that didn't account for the LIMIT clause being passed into raw SQL statements.
44
+ 3. Implemented the string_to_time method in order to create proper instances of the time class.
45
+ 4. Added logic to the simplified_type method that allows the database to specify the scale of float data.
46
+ 5. Adjusted the quote_column_name to account for the fact that MS SQL is bothered by a forward slash in the data string.
47
+
48
+ * Fixed that the dynamic finder like find_all_by_something_boolean(false) didn't work #649 [lmarlow@yahoo.com]
49
+
50
+ * Added validates_each that validates each specified attribute against a block #610 [bitsweat]. Example:
51
+
52
+ class Person < ActiveRecord::Base
53
+ validates_each :first_name, :last_name do |record, attr|
54
+ record.errors.add attr, 'starts with z.' if attr[0] == ?z
55
+ end
56
+ end
57
+
58
+ * Added :allow_nil as an explicit option for validates_length_of, so unless that's set to true having the attribute as nil will also return an error if a range is specified as :within #610 [bitsweat]
59
+
60
+ * Added that validates_* now accept blocks to perform validations #618 [Tim Bates]. Example:
61
+
62
+ class Person < ActiveRecord::Base
63
+ validate { |person| person.errors.add("title", "will never be valid") if SHOULD_NEVER_BE_VALID }
64
+ end
65
+
66
+ * Addded validation for validate all the associated objects before declaring failure with validates_associated #618 [Tim Bates]
67
+
68
+ * Added keyword-style approach to defining the custom relational bindings #545 [Jamis Buck]. Example:
69
+
70
+ class Project < ActiveRecord::Base
71
+ primary_key "sysid"
72
+ table_name "XYZ_PROJECT"
73
+ inheritance_column { original_inheritance_column + "_id" }
74
+ end
75
+
76
+ * Fixed Base#clone for use with PostgreSQL #565 [hanson@surgery.wisc.edu]
77
+
78
+
1
79
  *1.6.0* (January 25th, 2005)
2
80
 
3
81
  * Added that has_many association build and create methods can take arrays of record data like Base#create and Base#build to build/create multiple records at once.
data/README CHANGED
@@ -29,7 +29,7 @@ A short rundown of the major features:
29
29
 
30
30
  ...which again gives Product#name and Product#name=(new_name)
31
31
 
32
- Learn more in link:classes/ActiveRecord/Base.html
32
+ {Learn more}[link:classes/ActiveRecord/Base.html]
33
33
 
34
34
 
35
35
  * Associations between objects controlled by simple meta-programming macros.
@@ -40,7 +40,7 @@ A short rundown of the major features:
40
40
  belongs_to :conglomorate
41
41
  end
42
42
 
43
- Learn more in link:classes/ActiveRecord/Associations/ClassMethods.html
43
+ {Learn more}[link:classes/ActiveRecord/Associations/ClassMethods.html]
44
44
 
45
45
 
46
46
  * Aggregations of value objects controlled by simple meta-programming macros.
@@ -52,7 +52,7 @@ A short rundown of the major features:
52
52
  :mapping => [%w(address_street street), %w(address_city city)]
53
53
  end
54
54
 
55
- Learn more in link:classes/ActiveRecord/Aggregations/ClassMethods.html
55
+ {Learn more}[link:classes/ActiveRecord/Aggregations/ClassMethods.html]
56
56
 
57
57
 
58
58
  * Validation rules that can differ for new or existing objects.
@@ -64,7 +64,7 @@ A short rundown of the major features:
64
64
  validates_confirmation_of :password, :email_address, :on => :create
65
65
  end
66
66
 
67
- Learn more in link:classes/ActiveRecord/Validations.html
67
+ {Learn more}[link:classes/ActiveRecord/Validations.html]
68
68
 
69
69
 
70
70
  * Acts that can make records work as lists or trees:
@@ -77,6 +77,8 @@ A short rundown of the major features:
77
77
  item.move_higher
78
78
  item.move_to_bottom
79
79
 
80
+ Learn about {acts_as_list}[link:classes/ActiveRecord/Acts/List/ClassMethods.html], {the instance methods acts_as_list provides}[link:classes/ActiveRecord/Acts/List/InstanceMethods.html], and
81
+ {acts_as_tree}[link:classes/ActiveRecord/Acts/Tree/ClassMethods.html]
80
82
 
81
83
  * Callbacks as methods or queues on the entire lifecycle (instantiation, saving, destroying, validating, etc).
82
84
 
@@ -90,18 +92,18 @@ A short rundown of the major features:
90
92
  after_find :eager_load, 'self.class.announce(#{id})'
91
93
  end
92
94
 
93
- Learn more in link:classes/ActiveRecord/Callbacks.html
95
+ {Learn more}[link:classes/ActiveRecord/Callbacks.html]
94
96
 
95
97
 
96
98
  * Observers for the entire lifecycle
97
99
 
98
100
  class CommentObserver < ActiveRecord::Observer
99
101
  def after_create(comment) # is called just after Comment#save
100
- NotificationService.send_email("david@loudthinking.com", comment)
102
+ Notifications.deliver_new_comment("david@loudthinking.com", comment)
101
103
  end
102
104
  end
103
105
 
104
- Learn more in link:classes/ActiveRecord/Observer.html
106
+ {Learn more}[link:classes/ActiveRecord/Observer.html]
105
107
 
106
108
 
107
109
  * Inheritance hierarchies
@@ -111,7 +113,7 @@ A short rundown of the major features:
111
113
  class Client < Company; end
112
114
  class PriorityClient < Client; end
113
115
 
114
- Learn more in link:classes/ActiveRecord/Base.html
116
+ {Learn more}[link:classes/ActiveRecord/Base.html]
115
117
 
116
118
 
117
119
  * Transaction support on both a database and object level. The latter is implemented
@@ -129,7 +131,7 @@ A short rundown of the major features:
129
131
  mary.deposit(100)
130
132
  end
131
133
 
132
- Learn more in link:classes/ActiveRecord/Transactions/ClassMethods.html
134
+ {Learn more}[link:classes/ActiveRecord/Transactions/ClassMethods.html]
133
135
 
134
136
 
135
137
  * Reflections on columns, associations, and aggregations
@@ -138,7 +140,7 @@ A short rundown of the major features:
138
140
  reflection.klass # => Client (class)
139
141
  Firm.columns # Returns an array of column descriptors for the firms table
140
142
 
141
- Learn more in link:classes/ActiveRecord/Reflection/ClassMethods.html
143
+ {Learn more}[link:classes/ActiveRecord/Reflection/ClassMethods.html]
142
144
 
143
145
 
144
146
  * Direct manipulation (instead of service invocation)
@@ -158,7 +160,7 @@ A short rundown of the major features:
158
160
  # something even more interesting involving a the same cat...
159
161
  cat.save
160
162
 
161
- Learn more in link:classes/ActiveRecord/Base.html
163
+ {Learn more}[link:classes/ActiveRecord/Base.html]
162
164
 
163
165
 
164
166
  * Database abstraction through simple adapters (~100 lines) with a shared connector
@@ -173,7 +175,8 @@ A short rundown of the major features:
173
175
  :database => "activerecord"
174
176
  )
175
177
 
176
- Learn more in link:classes/ActiveRecord/Base.html#M000081
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].
177
180
 
178
181
 
179
182
  * Logging support for Log4r[http://log4r.sourceforge.net] and Logger[http://www.ruby-doc.org/stdlib/libdoc/logger/rdoc]
@@ -295,17 +298,6 @@ the examples themselves.
295
298
  It's also highly recommended to have a look at the unit tests. Read more in link:files/RUNNING_UNIT_TESTS.html
296
299
 
297
300
 
298
- == Database support
299
-
300
- Active Record ships with adapters for MySQL/Ruby[http://www.tmtm.org/en/mysql/ruby/]
301
- (compatible with Ruby/MySQL[http://www.tmtm.org/ruby/mysql/README_en.html]),
302
- PostgreSQL[http://www.postgresql.jp/interfaces/ruby/], and
303
- SQLite[http://rubyforge.org/projects/sqlite-ruby/] (needs SQLite 2.8.13+ and SQLite-Ruby 1.1.2+).
304
- The adapters are around 100 lines of code fulfilling the interface specified by
305
- ActiveRecord::ConnectionAdapters::AbstractAdapter. Writing a new adapter should be a small task --
306
- especially considering the extensive test suite that'll make sure you're fulfilling the contract.
307
-
308
-
309
301
  == Philosophy
310
302
 
311
303
  Active Record attempts to provide a coherent wrapping for the inconvenience that is
@@ -332,7 +324,7 @@ The latest version of Active Record can be found at
332
324
 
333
325
  Documentation can be found at
334
326
 
335
- * http://ar.rubyonrails.org
327
+ * http://ar.rubyonrails.com
336
328
 
337
329
 
338
330
  == Installation
@@ -341,7 +333,7 @@ The prefered method of installing Active Record is through its GEM file. You'll
341
333
  RubyGems[http://rubygems.rubyforge.org/wiki/wiki.pl] installed for that, though. If you have,
342
334
  then use:
343
335
 
344
- % [sudo] gem install activerecord-0.9.0.gem
336
+ % [sudo] gem install activerecord-1.7.0.gem
345
337
 
346
338
  You can also install Active Record the old-fashion way with the following command:
347
339
 
@@ -352,12 +344,12 @@ from its distribution directory.
352
344
 
353
345
  == License
354
346
 
355
- Active Record is released under the same license as Ruby.
347
+ Active Record is released under the MIT license.
356
348
 
357
349
 
358
350
  == Support
359
351
 
360
- The Active Record homepage is http://activerecord.rubyonrails.org. You can find the Active Record
352
+ The Active Record homepage is http://www.rubyonrails.com. You can find the Active Record
361
353
  RubyForge page at http://rubyforge.org/projects/activerecord. And as Jim from Rake says:
362
354
 
363
355
  Feel free to submit commits or feature requests. If you send a patch,
@@ -365,5 +357,4 @@ RubyForge page at http://rubyforge.org/projects/activerecord. And as Jim from Ra
365
357
  new feature to be submitted in the form of new unit tests.
366
358
 
367
359
  For other information, feel free to ask on the ruby-talk mailing list
368
- (which is mirrored to comp.lang.ruby) or contact mailto:david@loudthinking.com.
369
-
360
+ (which is mirrored to comp.lang.ruby) or contact mailto:david@loudthinking.com.
@@ -8,8 +8,7 @@ When you have the database online, you can import the fixture tables with
8
8
  the test/fixtures/db_definitions/*.sql files.
9
9
 
10
10
  Make sure that you create database objects with the same user that you specified in i
11
- connection.rb otherwise (on Postgres, at least) tests for default values will fail
12
- (see http://dev.rubyonrails.org/trac.cgi/ticket/118)
11
+ connection.rb otherwise (on Postgres, at least) tests for default values will fail.
13
12
 
14
13
  == Running with Rake
15
14
 
@@ -16,9 +16,6 @@ logger.info "\nCreate tables"
16
16
  # Class setup ---------------
17
17
 
18
18
  class Person < ActiveRecord::Base
19
- # Active Record can only guess simple table names like Card/cards, Company/companies
20
- def self.table_name() "people" end
21
-
22
19
  # Using
23
20
  def self.authenticate(name, pass)
24
21
  # find_first "name = '#{name}' AND pass = '#{pass}'" would be open to sql-injection (in a web-app scenario)
data/install.rb CHANGED
@@ -18,7 +18,7 @@ unless $sitedir
18
18
  end
19
19
  end
20
20
 
21
- makedirs = %w{ active_record/associations active_record/connection_adapters active_record/support active_record/vendor active_record/acts active_record/support/core_ext active_record/support/core_ext/hash active_record/support/core_ext/numeric active_record/support/core_ext/string }
21
+ makedirs = %w{ active_record/associations active_record/connection_adapters active_record/support active_record/vendor active_record/acts }
22
22
  makedirs.each {|f| File::makedirs(File.join($sitedir, *f.split(/\//)))}
23
23
 
24
24
  # deprecated files that should be removed
@@ -37,6 +37,7 @@ files = %w-
37
37
  active_record/connection_adapters/abstract_adapter.rb
38
38
  active_record/connection_adapters/db2_adapter.rb
39
39
  active_record/connection_adapters/mysql_adapter.rb
40
+ active_record/connection_adapters/oracle_adapter.rb
40
41
  active_record/connection_adapters/postgresql_adapter.rb
41
42
  active_record/connection_adapters/sqlite_adapter.rb
42
43
  active_record/connection_adapters/sqlserver_adapter.rb
@@ -47,24 +48,10 @@ files = %w-
47
48
  active_record/reflection.rb
48
49
  active_record/acts/list.rb
49
50
  active_record/acts/tree.rb
50
- active_record/support/class_attribute_accessors.rb
51
- active_record/support/class_inheritable_attributes.rb
52
- active_record/support/clean_logger.rb
53
- active_record/support/core_ext/hash/keys.rb
54
- active_record/support/core_ext/hash.rb
55
- active_record/support/core_ext/object_and_class.rb
56
- active_record/support/core_ext/numeric/bytes.rb
57
- active_record/support/core_ext/numeric/time.rb
58
- active_record/support/core_ext/numeric.rb
59
- active_record/support/core_ext/string/inflections.rb
60
- active_record/support/core_ext/string.rb
61
- active_record/support/core_ext.rb
62
- active_record/support/inflector.rb
63
- active_record/support/misc.rb
64
- active_record/support/module_attribute_accessors.rb
65
51
  active_record/timestamp.rb
66
52
  active_record/transactions.rb
67
53
  active_record/validations.rb
54
+ active_record/vendor/db2.rb
68
55
  active_record/vendor/mysql.rb
69
56
  active_record/vendor/mysql411.rb
70
57
  active_record/vendor/simple.rb
@@ -24,10 +24,16 @@
24
24
 
25
25
  $:.unshift(File.dirname(__FILE__))
26
26
 
27
- require 'active_record/support/core_ext'
28
- require 'active_record/support/clean_logger'
29
- require 'active_record/support/misc'
30
- require 'active_record/support/dependencies'
27
+ begin
28
+ require 'active_support'
29
+ rescue LoadError
30
+ begin
31
+ require File.dirname(__FILE__) + '/../../activesupport/lib/active_support'
32
+ rescue LoadError
33
+ require 'rubygems'
34
+ require_gem 'activesupport'
35
+ end
36
+ end
31
37
 
32
38
  require 'active_record/base'
33
39
  require 'active_record/observer'
@@ -60,3 +66,4 @@ require 'active_record/connection_adapters/postgresql_adapter'
60
66
  require 'active_record/connection_adapters/sqlite_adapter'
61
67
  require 'active_record/connection_adapters/sqlserver_adapter'
62
68
  require 'active_record/connection_adapters/db2_adapter'
69
+ require 'active_record/connection_adapters/oci_adapter'
@@ -94,7 +94,7 @@ module ActiveRecord
94
94
  # relational unique identifiers (such as primary keys). Normal ActiveRecord::Base classes are entity objects.
95
95
  #
96
96
  # It's also important to treat the value objects as immutable. Don't allow the Money object to have its amount changed after
97
- # creation. Create a new money object with the new value instead. This is examplified by the Money#exchanged_to method that
97
+ # creation. Create a new money object with the new value instead. This is exemplified by the Money#exchanged_to method that
98
98
  # returns a new value object instead of changing its own values. Active Record won't persist value objects that have been
99
99
  # changed through other means than the writer method.
100
100
  #
@@ -108,7 +108,7 @@ module ActiveRecord
108
108
  # <tt>composed_of :address</tt> would add <tt>address</tt> and <tt>address=(new_address)</tt>.
109
109
  #
110
110
  # Options are:
111
- # * <tt>:class_name</tt> - specify the class name of the association. Use it only if that name can't be infered
111
+ # * <tt>:class_name</tt> - specify the class name of the association. Use it only if that name can't be inferred
112
112
  # from the part id. So <tt>composed_of :address</tt> will by default be linked to the +Address+ class, but
113
113
  # if the real class name is +CompanyAddress+, you'll have to specify it with this option.
114
114
  # * <tt>:mapping</tt> - specifies a number of mapping arrays (attribute, parameter) that bind an attribute name
@@ -43,7 +43,7 @@ module ActiveRecord
43
43
  #
44
44
  # == Example
45
45
  #
46
- # link:../examples/associations.png
46
+ # link:../../examples/associations.png
47
47
  #
48
48
  # == Is it belongs_to or has_one?
49
49
  #
@@ -160,7 +160,7 @@ module ActiveRecord
160
160
  # * <tt>collection.find(id)</tt> - finds an associated object responding to the +id+ and that
161
161
  # meets the condition that it has to be associated with this object.
162
162
  # * <tt>collection.find_all(conditions = nil, orderings = nil, limit = nil, joins = nil)</tt> - finds all associated objects responding
163
- # criterias mentioned (like in the standard find_all) and that meets the condition that it has to be associated with this object.
163
+ # criteria mentioned (like in the standard find_all) and that meets the condition that it has to be associated with this object.
164
164
  # * <tt>collection.build(attributes = {})</tt> - returns a new object of the collection type that has been instantiated
165
165
  # with +attributes+ and linked to this object through a foreign key but has not yet been saved.
166
166
  # * <tt>collection.create(attributes = {})</tt> - returns a new object of the collection type that has been instantiated
@@ -180,7 +180,7 @@ module ActiveRecord
180
180
  # The declaration can also include an options hash to specialize the behavior of the association.
181
181
  #
182
182
  # Options are:
183
- # * <tt>:class_name</tt> - specify the class name of the association. Use it only if that name can't be infered
183
+ # * <tt>:class_name</tt> - specify the class name of the association. Use it only if that name can't be inferred
184
184
  # from the association name. So <tt>has_many :products</tt> will by default be linked to the +Product+ class, but
185
185
  # if the real class name is +SpecialProduct+, you'll have to specify it with this option.
186
186
  # * <tt>:conditions</tt> - specify the conditions that the associated objects must meet in order to be included as a "WHERE"
@@ -263,7 +263,7 @@ module ActiveRecord
263
263
  # The declaration can also include an options hash to specialize the behavior of the association.
264
264
  #
265
265
  # Options are:
266
- # * <tt>:class_name</tt> - specify the class name of the association. Use it only if that name can't be infered
266
+ # * <tt>:class_name</tt> - specify the class name of the association. Use it only if that name can't be inferred
267
267
  # from the association name. So <tt>has_one :manager</tt> will by default be linked to the +Manager+ class, but
268
268
  # if the real class name is +Person+, you'll have to specify it with this option.
269
269
  # * <tt>:conditions</tt> - specify the conditions that the associated object must meet in order to be included as a "WHERE"
@@ -320,7 +320,7 @@ module ActiveRecord
320
320
  # * <tt>association.create(attributes = {})</tt> - returns a new object of the associated type that has been instantiated
321
321
  # with +attributes+ and linked to this object through a foreign key and that has already been saved (if it passed the validation).
322
322
  #
323
- # Example: A Post class declares <tt>has_one :author</tt>, which will add:
323
+ # Example: A Post class declares <tt>belongs_to :author</tt>, which will add:
324
324
  # * <tt>Post#author</tt> (similar to <tt>Author.find(author_id)</tt>)
325
325
  # * <tt>Post#author=(author)</tt> (similar to <tt>post.author_id = author.id</tt>)
326
326
  # * <tt>Post#author?</tt> (similar to <tt>post.author == some_author</tt>)
@@ -330,7 +330,7 @@ module ActiveRecord
330
330
  # The declaration can also include an options hash to specialize the behavior of the association.
331
331
  #
332
332
  # Options are:
333
- # * <tt>:class_name</tt> - specify the class name of the association. Use it only if that name can't be infered
333
+ # * <tt>:class_name</tt> - specify the class name of the association. Use it only if that name can't be inferred
334
334
  # from the association name. So <tt>has_one :author</tt> will by default be linked to the +Author+ class, but
335
335
  # if the real class name is +Person+, you'll have to specify it with this option.
336
336
  # * <tt>:conditions</tt> - specify the conditions that the associated object must meet in order to be included as a "WHERE"
@@ -403,7 +403,7 @@ module ActiveRecord
403
403
  #
404
404
  # Adds the following methods for retrieval and query.
405
405
  # +collection+ is replaced with the symbol passed as the first argument, so
406
- # <tt>has_and_belongs_to_many :categories</tt> would add among others +categories.empty?+.
406
+ # <tt>has_and_belongs_to_many :categories</tt> would add among others <tt>categories.empty?</tt>.
407
407
  # * <tt>collection(force_reload = false)</tt> - returns an array of all the associated objects.
408
408
  # An empty array is returned if none is found.
409
409
  # * <tt>collection<<(object, ...)</tt> - adds one or more objects to the collection by creating associations in the join table
@@ -432,7 +432,7 @@ module ActiveRecord
432
432
  # The declaration may include an options hash to specialize the behavior of the association.
433
433
  #
434
434
  # Options are:
435
- # * <tt>:class_name</tt> - specify the class name of the association. Use it only if that name can't be infered
435
+ # * <tt>:class_name</tt> - specify the class name of the association. Use it only if that name can't be inferred
436
436
  # from the association name. So <tt>has_and_belongs_to_many :projects</tt> will by default be linked to the
437
437
  # +Project+ class, but if the real class name is +SuperProject+, you'll have to specify it with this option.
438
438
  # * <tt>:join_table</tt> - specify the name of the join table if the default based on lexical order isn't what you want.
@@ -99,7 +99,7 @@ module ActiveRecord
99
99
  false
100
100
  end
101
101
 
102
- # Array#flatten has problems with rescursive arrays. Going one level deeper solves the majority of the problems.
102
+ # Array#flatten has problems with recursive arrays. Going one level deeper solves the majority of the problems.
103
103
  def flatten_deeper(array)
104
104
  array.collect { |element| element.respond_to?(:flatten) ? element.flatten : element }.flatten
105
105
  end
@@ -147,7 +147,7 @@ module ActiveRecord
147
147
  def construct_sql
148
148
  interpolate_sql_options!(@options, :finder_sql, :delete_sql)
149
149
  @finder_sql = @options[:finder_sql] ||
150
- "SELECT t.*, j.* FROM #{@association_table_name} t, #{@join_table} j " +
150
+ "SELECT t.*, j.* FROM #{@join_table} j, #{@association_table_name} t " +
151
151
  "WHERE t.#{@association_class.primary_key} = j.#{@association_foreign_key} AND " +
152
152
  "j.#{@association_class_primary_key_name} = #{@owner.quoted_id} " +
153
153
  (@options[:conditions] ? " AND " + interpolate_sql(@options[:conditions]) : "") + " " +
@@ -1,6 +1,6 @@
1
- require 'active_record/support/class_attribute_accessors'
2
- require 'active_record/support/class_inheritable_attributes'
3
- require 'active_record/support/inflector'
1
+ require 'active_support/class_attribute_accessors'
2
+ require 'active_support/class_inheritable_attributes'
3
+ require 'active_support/inflector'
4
4
  require 'yaml'
5
5
 
6
6
  module ActiveRecord #:nodoc:
@@ -97,6 +97,16 @@ module ActiveRecord #:nodoc:
97
97
  # end
98
98
  # end
99
99
  #
100
+ # == Accessing attributes before they have been type casted
101
+ #
102
+ # Some times you want to be able to read the raw attribute data without having the column-determined type cast run its course first.
103
+ # That can be done by using the <attribute>_before_type_cast accessors that all attributes have. For example, if your Account model
104
+ # has a balance attribute, you can call account.balance_before_type_cast or account.id_before_type_cast.
105
+ #
106
+ # This is especially useful in validation situations where the user might supply a string for an integer field and you want to display
107
+ # the original string back in an error message. Accessing the attribute normally would type cast the string to 0, which isn't what you
108
+ # want.
109
+ #
100
110
  # == Dynamic attribute-based finders
101
111
  #
102
112
  # Dynamic attribute-based finders are a cleaner way of getting objects by simple queries without turning to SQL. They work by
@@ -112,7 +122,7 @@ module ActiveRecord #:nodoc:
112
122
  # is actually Payment.find_all_by_amount(amount, orderings = nil, limit = nil, joins = nil). And the full interface to Person.find_by_user_name is
113
123
  # actually Person.find_by_user_name(user_name, orderings = nil)
114
124
  #
115
- # == Saving arrays, hashes, and other non-mappeable objects in text columns
125
+ # == Saving arrays, hashes, and other non-mappable objects in text columns
116
126
  #
117
127
  # Active Record can serialize any object in text columns using YAML. To do so, you must specify this with a call to the class method +serialize+.
118
128
  # This makes it possible to store arrays, hashes, and other non-mappeable objects without doing any additional work. Example:
@@ -144,7 +154,7 @@ module ActiveRecord #:nodoc:
144
154
  # class Client < Company; end
145
155
  # class PriorityClient < Client; end
146
156
  #
147
- # When you do Firm.create("name" => "37signals"), this record with be saved in the companies table with type = "Firm". You can then
157
+ # When you do Firm.create("name" => "37signals"), this record will be saved in the companies table with type = "Firm". You can then
148
158
  # fetch this row again using Company.find_first "name = '37signals'" and it will return a Firm object.
149
159
  #
150
160
  # If you don't have a type column defined in your table, single-table inheritance won't be triggered. In that case, it'll work just
@@ -168,7 +178,7 @@ module ActiveRecord #:nodoc:
168
178
  # * +ActiveRecordError+ -- generic error class and superclass of all other errors raised by Active Record
169
179
  # * +AdapterNotSpecified+ -- the configuration hash used in <tt>establish_connection</tt> didn't include a
170
180
  # <tt>:adapter</tt> key.
171
- # * +AdapterNotSpecified+ -- the <tt>:adapter</tt> key used in <tt>establish_connection</tt> specified an unexisting adapter
181
+ # * +AdapterNotSpecified+ -- the <tt>:adapter</tt> key used in <tt>establish_connection</tt> specified an non-existent adapter
172
182
  # (or a bad spelling of an existing one).
173
183
  # * +AssociationTypeMismatch+ -- the object assigned to the association wasn't of the type specified in the association definition.
174
184
  # * +SerializationTypeMismatch+ -- the object serialized wasn't of the class specified as the second parameter.
@@ -221,7 +231,7 @@ module ActiveRecord #:nodoc:
221
231
  @@primary_key_prefix_type = nil
222
232
 
223
233
  # Accessor for the name of the prefix string to prepend to every table name. So if set to "basecamp_", all
224
- # table names will be named like "basecamp_projects", "basecamp_people", etc. This is a convinient way of creating a namespace
234
+ # table names will be named like "basecamp_projects", "basecamp_people", etc. This is a convenient way of creating a namespace
225
235
  # for tables in a shared database. By default, the prefix is the empty string.
226
236
  cattr_accessor :table_name_prefix
227
237
  @@table_name_prefix = ""
@@ -447,7 +457,7 @@ module ActiveRecord #:nodoc:
447
457
  write_inheritable_array("attr_protected", attributes)
448
458
  end
449
459
 
450
- # Returns an array of all the attributes that have been protected from mass-assigment.
460
+ # Returns an array of all the attributes that have been protected from mass-assignment.
451
461
  def protected_attributes # :nodoc:
452
462
  read_inheritable_attribute("attr_protected")
453
463
  end
@@ -460,14 +470,14 @@ module ActiveRecord #:nodoc:
460
470
  write_inheritable_array("attr_accessible", attributes)
461
471
  end
462
472
 
463
- # Returns an array of all the attributes that have been made accessible to mass-assigment.
473
+ # Returns an array of all the attributes that have been made accessible to mass-assignment.
464
474
  def accessible_attributes # :nodoc:
465
475
  read_inheritable_attribute("attr_accessible")
466
476
  end
467
477
 
468
478
  # Specifies that the attribute by the name of +attr_name+ should be serialized before saving to the database and unserialized
469
479
  # after loading from the database. The serialization is done through YAML. If +class_name+ is specified, the serialized
470
- # object must be of that class on retrival or +SerializationTypeMismatch+ will be raised.
480
+ # object must be of that class on retrieval or +SerializationTypeMismatch+ will be raised.
471
481
  def serialize(attr_name, class_name = Object)
472
482
  write_inheritable_attribute("attr_serialized", serialized_attributes.update(attr_name.to_s => class_name))
473
483
  end
@@ -479,20 +489,8 @@ module ActiveRecord #:nodoc:
479
489
 
480
490
  # Guesses the table name (in forced lower-case) based on the name of the class in the inheritance hierarchy descending
481
491
  # directly from ActiveRecord. So if the hierarchy looks like: Reply < Message < ActiveRecord, then Message is used
482
- # to guess the table name from even when called on Reply. The guessing rules are as follows:
483
- #
484
- # * Class name ends in "x", "ch" or "ss": "es" is appended, so a Search class becomes a searches table.
485
- # * Class name ends in "y" preceded by a consonant or "qu": The "y" is replaced with "ies", so a Category class becomes a categories table.
486
- # * Class name ends in "fe": The "fe" is replaced with "ves", so a Wife class becomes a wives table.
487
- # * Class name ends in "lf" or "rf": The "f" is replaced with "ves", so a Half class becomes a halves table.
488
- # * Class name ends in "person": The "person" is replaced with "people", so a Salesperson class becomes a salespeople table.
489
- # * Class name ends in "man": The "man" is replaced with "men", so a Spokesman class becomes a spokesmen table.
490
- # * Class name ends in "sis": The "i" is replaced with an "e", so a Basis class becomes a bases table.
491
- # * Class name ends in "tum" or "ium": The "um" is replaced with an "a", so a Datum class becomes a data table.
492
- # * Class name ends in "child": The "child" is replaced with "children", so a NodeChild class becomes a node_children table.
493
- # * Class name ends in an "s": No additional characters are added or removed.
494
- # * Class name doesn't end in "s": An "s" is appended, so a Comment class becomes a comments table.
495
- # * Class name with word compositions: Compositions are underscored, so CreditCard class becomes a credit_cards table.
492
+ # to guess the table name from even when called on Reply. The rules used to do the guess are handled by the Inflector class
493
+ # in Active Support, which knows almost all common English inflections (report a bug if your inflection isn't covered).
496
494
  #
497
495
  # Additionally, the class-level table_name_prefix is prepended to the table_name and the table_name_suffix is appended.
498
496
  # So if you have "myapp_" as a prefix, the table name guess for an Account class becomes "myapp_accounts".
@@ -501,13 +499,13 @@ module ActiveRecord #:nodoc:
501
499
  # "mice" table. Example:
502
500
  #
503
501
  # class Mouse < ActiveRecord::Base
504
- # def self.table_name() "mice" end
502
+ # table_name "mice"
505
503
  # end
506
504
  def table_name
507
505
  table_name_prefix + undecorated_table_name(class_name_of_active_record_descendant(self)) + table_name_suffix
508
506
  end
509
507
 
510
- # Defines the primary key field -- can be overridden in subclasses. Overwritting will negate any effect of the
508
+ # Defines the primary key field -- can be overridden in subclasses. Overwriting will negate any effect of the
511
509
  # primary_key_prefix_type setting, though.
512
510
  def primary_key
513
511
  case primary_key_prefix_type
@@ -525,6 +523,49 @@ module ActiveRecord #:nodoc:
525
523
  "type"
526
524
  end
527
525
 
526
+ # Sets the table name to use to the given value, or (if the value
527
+ # is nil or false) to the value returned by the given block.
528
+ #
529
+ # Example:
530
+ #
531
+ # class Project < ActiveRecord::Base
532
+ # set_table_name "project"
533
+ # end
534
+ def set_table_name( value=nil, &block )
535
+ define_attr_method :table_name, value, &block
536
+ end
537
+ alias :table_name= :set_table_name
538
+
539
+ # Sets the name of the primary key column to use to the given value,
540
+ # or (if the value is nil or false) to the value returned by the given
541
+ # block.
542
+ #
543
+ # Example:
544
+ #
545
+ # class Project < ActiveRecord::Base
546
+ # set_primary_key "sysid"
547
+ # end
548
+ def set_primary_key( value=nil, &block )
549
+ define_attr_method :primary_key, value, &block
550
+ end
551
+ alias :primary_key= :set_primary_key
552
+
553
+ # Sets the name of the inheritance column to use to the given value,
554
+ # or (if the value # is nil or false) to the value returned by the
555
+ # given block.
556
+ #
557
+ # Example:
558
+ #
559
+ # class Project < ActiveRecord::Base
560
+ # set_inheritance_column do
561
+ # original_inheritance_column + "_id"
562
+ # end
563
+ # end
564
+ def set_inheritance_column( value=nil, &block )
565
+ define_attr_method :inheritance_column, value, &block
566
+ end
567
+ alias :inheritance_column= :set_inheritance_column
568
+
528
569
  # Turns the +table_name+ back into a class name following the reverse rules of +table_name+.
529
570
  def class_name(table_name = table_name) # :nodoc:
530
571
  # remove any prefix and/or suffix from the table name
@@ -567,13 +608,14 @@ module ActiveRecord #:nodoc:
567
608
  @columns = @columns_hash = @content_columns = @dynamic_methods_hash = nil
568
609
  end
569
610
 
570
- def reset_column_information_and_inheritable_attributes_for_all_subclasses
611
+ def reset_column_information_and_inheritable_attributes_for_all_subclasses#:nodoc:
571
612
  subclasses.each { |klass| klass.reset_inheritable_attributes; klass.reset_column_information }
572
613
  end
573
614
 
574
615
  # Transforms attribute key names into a more humane format, such as "First name" instead of "first_name". Example:
575
616
  # Person.human_attribute_name("first_name") # => "First name"
576
- def human_attribute_name(attribute_key_name)
617
+ # Deprecated in favor of just calling "first_name".humanize
618
+ def human_attribute_name(attribute_key_name) #:nodoc:
577
619
  attribute_key_name.humanize
578
620
  end
579
621
 
@@ -581,12 +623,12 @@ module ActiveRecord #:nodoc:
581
623
  superclass == Base || !columns_hash.has_key?(inheritance_column)
582
624
  end
583
625
 
584
- def quote(object)
626
+ def quote(object) #:nodoc:
585
627
  connection.quote(object)
586
628
  end
587
629
 
588
630
  # Used to sanitize objects before they're used in an SELECT SQL-statement. Delegates to <tt>connection.quote</tt>.
589
- def sanitize(object) # :nodoc:
631
+ def sanitize(object) #:nodoc:
590
632
  connection.quote(object)
591
633
  end
592
634
 
@@ -599,11 +641,18 @@ module ActiveRecord #:nodoc:
599
641
  # project.milestones << Milestone.find_all
600
642
  # end
601
643
  def benchmark(title)
644
+ result = nil
645
+ bm = Benchmark.measure { result = silence { yield } }
646
+ logger.info "#{title} (#{sprintf("%f", bm.real)})"
647
+ return result
648
+ end
649
+
650
+ # Silences the logger for the duration of the block.
651
+ def silence
602
652
  result = nil
603
653
  logger.level = Logger::ERROR
604
- bm = Benchmark.measure { result = yield }
654
+ result = yield
605
655
  logger.level = Logger::DEBUG
606
- logger.info "#{title} (#{sprintf("%f", bm.real)})"
607
656
  return result
608
657
  end
609
658
 
@@ -674,18 +723,43 @@ module ActiveRecord #:nodoc:
674
723
  def method_missing(method_id, *arguments)
675
724
  method_name = method_id.id2name
676
725
 
677
- if method_name =~ /find_(all_by|by)_([_a-z]+)/
726
+ if method_name =~ /find_(all_by|by)_([_a-z][_a-z\d]*)/
678
727
  finder, attributes = ($1 == "all_by" ? :find_all : :find_first), $2.split("_and_")
679
728
  attributes.each { |attr_name| super unless column_methods_hash[attr_name.intern] }
680
729
 
681
730
  attr_index = -1
682
- conditions = attributes.collect { |attr_name| attr_index += 1; "#{attr_name} #{arguments[attr_index] ? "=" : "IS"} ? " }.join(" AND ")
731
+ conditions = attributes.collect { |attr_name| attr_index += 1; "#{attr_name} #{arguments[attr_index].nil? ? "IS" : "="} ? " }.join(" AND ")
683
732
  send(finder, [conditions, *arguments[0...attributes.length]], *arguments[attributes.length..-1])
684
733
  else
685
734
  super
686
735
  end
687
736
  end
688
737
 
738
+ # Defines an "attribute" method (like #inheritance_column or
739
+ # #table_name). A new (class) method will be created with the
740
+ # given name. If a value is specified, the new method will
741
+ # return that value (as a string). Otherwise, the given block
742
+ # will be used to compute the value of the method.
743
+ #
744
+ # The original method will be aliased, with the new name being
745
+ # prefixed with "original_". This allows the new method to
746
+ # access the original value.
747
+ #
748
+ # Example:
749
+ #
750
+ # class A < ActiveRecord::Base
751
+ # define_attr_method :primary_key, "sysid"
752
+ # define_attr_method( :inheritance_column ) do
753
+ # original_inheritance_column + "_id"
754
+ # end
755
+ # end
756
+ def define_attr_method(name, value=nil, &block)
757
+ sing = class << self; self; end
758
+ block = proc { value.to_s } if value
759
+ sing.send( :alias_method, "original_#{name}", name )
760
+ sing.send( :define_method, name, &block )
761
+ end
762
+
689
763
  protected
690
764
  def subclasses
691
765
  @@subclasses[self] ||= []
@@ -792,11 +866,11 @@ module ActiveRecord #:nodoc:
792
866
  read_attribute(self.class.primary_key)
793
867
  end
794
868
 
795
- def id_before_type_cast
869
+ def id_before_type_cast #:nodoc:
796
870
  read_attribute_before_type_cast(self.class.primary_key)
797
871
  end
798
872
 
799
- def quoted_id
873
+ def quoted_id #:nodoc:
800
874
  quote(id, self.class.columns_hash[self.class.primary_key])
801
875
  end
802
876
 
@@ -832,9 +906,9 @@ module ActiveRecord #:nodoc:
832
906
 
833
907
  # Returns a clone of the record that hasn't been assigned an id yet and is treated as a new record.
834
908
  def clone
835
- cloned_record = self.class.new(self.attributes)
836
- cloned_record.instance_variable_set "@new_record", true
837
- cloned_record.id = nil
909
+ attrs = self.attributes
910
+ attrs.delete(self.class.primary_key)
911
+ cloned_record = self.class.new(attrs)
838
912
  cloned_record
839
913
  end
840
914
 
@@ -1047,7 +1121,7 @@ module ActiveRecord #:nodoc:
1047
1121
 
1048
1122
  # Returns the value of attribute identified by <tt>attr_name</tt> after it has been type cast (for example,
1049
1123
  # "2004-12-12" in a data column is cast to a date object, like Date.new(2004, 12, 12)).
1050
- def read_attribute(attr_name) #:doc:
1124
+ def read_attribute(attr_name)
1051
1125
  if @attributes.keys.include? attr_name
1052
1126
  if column = column_for_attribute(attr_name)
1053
1127
  unserializable_attribute?(attr_name, column) ?
@@ -1086,7 +1160,7 @@ module ActiveRecord #:nodoc:
1086
1160
 
1087
1161
  # Updates the attribute identified by <tt>attr_name</tt> with the specified +value+. Empty strings for fixnum and float
1088
1162
  # columns are turned into nil.
1089
- def write_attribute(attr_name, value) #:doc:
1163
+ def write_attribute(attr_name, value)
1090
1164
  @attributes[attr_name] = empty_string_for_number_column?(attr_name, value) ? nil : value
1091
1165
  end
1092
1166
 
@@ -1170,7 +1244,7 @@ module ActiveRecord #:nodoc:
1170
1244
  # by calling new on the column type or aggregation type (through composed_of) object with these parameters.
1171
1245
  # So having the pairs written_on(1) = "2004", written_on(2) = "6", written_on(3) = "24", will instantiate
1172
1246
  # written_on (a date type) with Date.new("2004", "6", "24"). You can also specify a typecast character in the
1173
- # parenteses to have the parameters typecasted before they're used in the constructor. Use i for Fixnum, f for Float,
1247
+ # parentheses to have the parameters typecasted before they're used in the constructor. Use i for Fixnum, f for Float,
1174
1248
  # s for String, and a for Array. If all the values for a given attribute is empty, the attribute will be set to nil.
1175
1249
  def assign_multiparameter_attributes(pairs)
1176
1250
  execute_callstack_for_multiparameter_attributes(
@@ -1253,4 +1327,4 @@ module ActiveRecord #:nodoc:
1253
1327
  string[0..3] == "--- "
1254
1328
  end
1255
1329
  end
1256
- end
1330
+ end