activerecord 3.2.22.5 → 4.0.0.beta1

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 (162) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1024 -543
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +20 -29
  5. data/examples/performance.rb +1 -1
  6. data/lib/active_record.rb +55 -44
  7. data/lib/active_record/aggregations.rb +40 -34
  8. data/lib/active_record/associations.rb +204 -276
  9. data/lib/active_record/associations/alias_tracker.rb +1 -1
  10. data/lib/active_record/associations/association.rb +30 -35
  11. data/lib/active_record/associations/association_scope.rb +40 -40
  12. data/lib/active_record/associations/belongs_to_association.rb +15 -2
  13. data/lib/active_record/associations/builder/association.rb +81 -28
  14. data/lib/active_record/associations/builder/belongs_to.rb +35 -57
  15. data/lib/active_record/associations/builder/collection_association.rb +54 -40
  16. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +23 -41
  17. data/lib/active_record/associations/builder/has_many.rb +8 -64
  18. data/lib/active_record/associations/builder/has_one.rb +13 -50
  19. data/lib/active_record/associations/builder/singular_association.rb +13 -13
  20. data/lib/active_record/associations/collection_association.rb +92 -88
  21. data/lib/active_record/associations/collection_proxy.rb +913 -63
  22. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +12 -10
  23. data/lib/active_record/associations/has_many_association.rb +35 -9
  24. data/lib/active_record/associations/has_many_through_association.rb +24 -14
  25. data/lib/active_record/associations/has_one_association.rb +33 -13
  26. data/lib/active_record/associations/has_one_through_association.rb +1 -1
  27. data/lib/active_record/associations/join_dependency.rb +2 -2
  28. data/lib/active_record/associations/join_dependency/join_association.rb +17 -22
  29. data/lib/active_record/associations/join_dependency/join_part.rb +1 -1
  30. data/lib/active_record/associations/join_helper.rb +1 -11
  31. data/lib/active_record/associations/preloader.rb +14 -17
  32. data/lib/active_record/associations/preloader/association.rb +29 -33
  33. data/lib/active_record/associations/preloader/collection_association.rb +1 -1
  34. data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +1 -1
  35. data/lib/active_record/associations/preloader/has_many_through.rb +1 -1
  36. data/lib/active_record/associations/preloader/has_one.rb +1 -1
  37. data/lib/active_record/associations/preloader/through_association.rb +13 -17
  38. data/lib/active_record/associations/singular_association.rb +11 -11
  39. data/lib/active_record/associations/through_association.rb +2 -2
  40. data/lib/active_record/attribute_assignment.rb +133 -153
  41. data/lib/active_record/attribute_methods.rb +196 -93
  42. data/lib/active_record/attribute_methods/before_type_cast.rb +44 -5
  43. data/lib/active_record/attribute_methods/dirty.rb +31 -28
  44. data/lib/active_record/attribute_methods/primary_key.rb +38 -30
  45. data/lib/active_record/attribute_methods/query.rb +5 -4
  46. data/lib/active_record/attribute_methods/read.rb +62 -91
  47. data/lib/active_record/attribute_methods/serialization.rb +97 -66
  48. data/lib/active_record/attribute_methods/time_zone_conversion.rb +39 -45
  49. data/lib/active_record/attribute_methods/write.rb +32 -39
  50. data/lib/active_record/autosave_association.rb +56 -70
  51. data/lib/active_record/base.rb +53 -450
  52. data/lib/active_record/callbacks.rb +53 -18
  53. data/lib/active_record/coders/yaml_column.rb +11 -9
  54. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +353 -197
  55. data/lib/active_record/connection_adapters/abstract/database_limits.rb +9 -0
  56. data/lib/active_record/connection_adapters/abstract/database_statements.rb +130 -131
  57. data/lib/active_record/connection_adapters/abstract/query_cache.rb +24 -19
  58. data/lib/active_record/connection_adapters/abstract/quoting.rb +23 -3
  59. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +101 -91
  60. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +59 -0
  61. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +225 -96
  62. data/lib/active_record/connection_adapters/abstract/transaction.rb +203 -0
  63. data/lib/active_record/connection_adapters/abstract_adapter.rb +99 -46
  64. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +114 -36
  65. data/lib/active_record/connection_adapters/column.rb +46 -24
  66. data/lib/active_record/connection_adapters/connection_specification.rb +96 -0
  67. data/lib/active_record/connection_adapters/mysql2_adapter.rb +16 -32
  68. data/lib/active_record/connection_adapters/mysql_adapter.rb +181 -64
  69. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +97 -0
  70. data/lib/active_record/connection_adapters/postgresql/cast.rb +132 -0
  71. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +242 -0
  72. data/lib/active_record/connection_adapters/postgresql/oid.rb +347 -0
  73. data/lib/active_record/connection_adapters/postgresql/quoting.rb +158 -0
  74. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +30 -0
  75. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +448 -0
  76. data/lib/active_record/connection_adapters/postgresql_adapter.rb +454 -885
  77. data/lib/active_record/connection_adapters/schema_cache.rb +48 -16
  78. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +574 -13
  79. data/lib/active_record/connection_handling.rb +98 -0
  80. data/lib/active_record/core.rb +428 -0
  81. data/lib/active_record/counter_cache.rb +106 -108
  82. data/lib/active_record/dynamic_matchers.rb +110 -63
  83. data/lib/active_record/errors.rb +25 -8
  84. data/lib/active_record/explain.rb +8 -58
  85. data/lib/active_record/explain_subscriber.rb +6 -3
  86. data/lib/active_record/fixture_set/file.rb +56 -0
  87. data/lib/active_record/fixtures.rb +146 -148
  88. data/lib/active_record/inheritance.rb +77 -59
  89. data/lib/active_record/integration.rb +5 -5
  90. data/lib/active_record/locale/en.yml +8 -1
  91. data/lib/active_record/locking/optimistic.rb +38 -42
  92. data/lib/active_record/locking/pessimistic.rb +4 -4
  93. data/lib/active_record/log_subscriber.rb +19 -9
  94. data/lib/active_record/migration.rb +318 -153
  95. data/lib/active_record/migration/command_recorder.rb +90 -31
  96. data/lib/active_record/migration/join_table.rb +15 -0
  97. data/lib/active_record/model_schema.rb +69 -92
  98. data/lib/active_record/nested_attributes.rb +113 -148
  99. data/lib/active_record/null_relation.rb +65 -0
  100. data/lib/active_record/persistence.rb +188 -97
  101. data/lib/active_record/query_cache.rb +18 -36
  102. data/lib/active_record/querying.rb +19 -15
  103. data/lib/active_record/railtie.rb +91 -36
  104. data/lib/active_record/railties/console_sandbox.rb +0 -2
  105. data/lib/active_record/railties/controller_runtime.rb +2 -2
  106. data/lib/active_record/railties/databases.rake +90 -309
  107. data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
  108. data/lib/active_record/readonly_attributes.rb +7 -3
  109. data/lib/active_record/reflection.rb +72 -56
  110. data/lib/active_record/relation.rb +241 -157
  111. data/lib/active_record/relation/batches.rb +25 -22
  112. data/lib/active_record/relation/calculations.rb +143 -121
  113. data/lib/active_record/relation/delegation.rb +96 -18
  114. data/lib/active_record/relation/finder_methods.rb +117 -183
  115. data/lib/active_record/relation/merger.rb +133 -0
  116. data/lib/active_record/relation/predicate_builder.rb +90 -42
  117. data/lib/active_record/relation/query_methods.rb +666 -136
  118. data/lib/active_record/relation/spawn_methods.rb +43 -150
  119. data/lib/active_record/result.rb +33 -6
  120. data/lib/active_record/sanitization.rb +24 -50
  121. data/lib/active_record/schema.rb +19 -12
  122. data/lib/active_record/schema_dumper.rb +31 -39
  123. data/lib/active_record/schema_migration.rb +36 -0
  124. data/lib/active_record/scoping.rb +0 -124
  125. data/lib/active_record/scoping/default.rb +48 -45
  126. data/lib/active_record/scoping/named.rb +74 -103
  127. data/lib/active_record/serialization.rb +6 -2
  128. data/lib/active_record/serializers/xml_serializer.rb +9 -15
  129. data/lib/active_record/store.rb +119 -15
  130. data/lib/active_record/tasks/database_tasks.rb +158 -0
  131. data/lib/active_record/tasks/mysql_database_tasks.rb +138 -0
  132. data/lib/active_record/tasks/postgresql_database_tasks.rb +90 -0
  133. data/lib/active_record/tasks/sqlite_database_tasks.rb +51 -0
  134. data/lib/active_record/test_case.rb +61 -38
  135. data/lib/active_record/timestamp.rb +8 -9
  136. data/lib/active_record/transactions.rb +65 -51
  137. data/lib/active_record/validations.rb +17 -15
  138. data/lib/active_record/validations/associated.rb +20 -14
  139. data/lib/active_record/validations/presence.rb +65 -0
  140. data/lib/active_record/validations/uniqueness.rb +93 -52
  141. data/lib/active_record/version.rb +4 -4
  142. data/lib/rails/generators/active_record.rb +3 -5
  143. data/lib/rails/generators/active_record/migration/migration_generator.rb +37 -7
  144. data/lib/rails/generators/active_record/migration/templates/migration.rb +20 -15
  145. data/lib/rails/generators/active_record/model/model_generator.rb +4 -3
  146. data/lib/rails/generators/active_record/model/templates/model.rb +1 -6
  147. data/lib/rails/generators/active_record/model/templates/module.rb +1 -1
  148. metadata +53 -46
  149. data/lib/active_record/attribute_methods/deprecated_underscore_read.rb +0 -32
  150. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +0 -191
  151. data/lib/active_record/connection_adapters/sqlite_adapter.rb +0 -583
  152. data/lib/active_record/dynamic_finder_match.rb +0 -68
  153. data/lib/active_record/dynamic_scope_match.rb +0 -23
  154. data/lib/active_record/fixtures/file.rb +0 -65
  155. data/lib/active_record/identity_map.rb +0 -162
  156. data/lib/active_record/observer.rb +0 -121
  157. data/lib/active_record/session_store.rb +0 -360
  158. data/lib/rails/generators/active_record/migration.rb +0 -15
  159. data/lib/rails/generators/active_record/observer/observer_generator.rb +0 -15
  160. data/lib/rails/generators/active_record/observer/templates/observer.rb +0 -4
  161. data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +0 -25
  162. data/lib/rails/generators/active_record/session_migration/templates/migration.rb +0 -12
@@ -1,4 +1,4 @@
1
- Copyright (c) 2004-2011 David Heinemeier Hansson
1
+ Copyright (c) 2004-2013 David Heinemeier Hansson
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
@@ -49,10 +49,10 @@ A short rundown of some of the major features:
49
49
  * Aggregations of value objects.
50
50
 
51
51
  class Account < ActiveRecord::Base
52
- composed_of :balance, :class_name => "Money",
53
- :mapping => %w(balance amount)
52
+ composed_of :balance, class_name: 'Money',
53
+ mapping: %w(balance amount)
54
54
  composed_of :address,
55
- :mapping => [%w(address_street street), %w(address_city city)]
55
+ mapping: [%w(address_street street), %w(address_city city)]
56
56
  end
57
57
 
58
58
  {Learn more}[link:classes/ActiveRecord/Aggregations/ClassMethods.html]
@@ -61,10 +61,10 @@ A short rundown of some of the major features:
61
61
  * Validation rules that can differ for new or existing objects.
62
62
 
63
63
  class Account < ActiveRecord::Base
64
- validates_presence_of :subdomain, :name, :email_address, :password
65
- validates_uniqueness_of :subdomain
66
- validates_acceptance_of :terms_of_service, :on => :create
67
- validates_confirmation_of :password, :email_address, :on => :create
64
+ validates :subdomain, :name, :email_address, :password, presence: true
65
+ validates :subdomain, uniqueness: true
66
+ validates :terms_of_service, acceptance: true, on: :create
67
+ validates :password, :email_address, confirmation: true, on: :create
68
68
  end
69
69
 
70
70
  {Learn more}[link:classes/ActiveRecord/Validations.html]
@@ -80,17 +80,6 @@ A short rundown of some of the major features:
80
80
  {Learn more}[link:classes/ActiveRecord/Callbacks.html]
81
81
 
82
82
 
83
- * Observers that react to changes in a model.
84
-
85
- class CommentObserver < ActiveRecord::Observer
86
- def after_create(comment) # is called just after Comment#save
87
- CommentMailer.new_comment_email("david@loudthinking.com", comment).deliver
88
- end
89
- end
90
-
91
- {Learn more}[link:classes/ActiveRecord/Observer.html]
92
-
93
-
94
83
  * Inheritance hierarchies.
95
84
 
96
85
  class Company < ActiveRecord::Base; end
@@ -124,15 +113,15 @@ A short rundown of some of the major features:
124
113
  * Database abstraction through simple adapters.
125
114
 
126
115
  # connect to SQLite3
127
- ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => "dbfile.sqlite3")
116
+ ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: 'dbfile.sqlite3')
128
117
 
129
118
  # connect to MySQL with authentication
130
119
  ActiveRecord::Base.establish_connection(
131
- :adapter => "mysql2",
132
- :host => "localhost",
133
- :username => "me",
134
- :password => "secret",
135
- :database => "activerecord"
120
+ adapter: 'mysql2',
121
+ host: 'localhost',
122
+ username: 'me',
123
+ password: 'secret',
124
+ database: 'activerecord'
136
125
  )
137
126
 
138
127
  {Learn more}[link:classes/ActiveRecord/Base.html] and read about the built-in support for
@@ -143,8 +132,8 @@ A short rundown of some of the major features:
143
132
 
144
133
  * Logging support for Log4r[http://log4r.sourceforge.net] and Logger[http://www.ruby-doc.org/stdlib/libdoc/logger/rdoc].
145
134
 
146
- ActiveRecord::Base.logger = Logger.new(STDOUT)
147
- ActiveRecord::Base.logger = Log4r::Logger.new("Application Log")
135
+ ActiveRecord::Base.logger = ActiveSupport::Logger.new(STDOUT)
136
+ ActiveRecord::Base.logger = Log4r::Logger.new('Application Log')
148
137
 
149
138
 
150
139
  * Database agnostic schema management with Migrations.
@@ -159,7 +148,7 @@ A short rundown of some of the major features:
159
148
  t.integer :position
160
149
  end
161
150
 
162
- SystemSetting.create :name => "notice", :label => "Use notice?", :value => 1
151
+ SystemSetting.create name: 'notice', label: 'Use notice?', value: 1
163
152
  end
164
153
 
165
154
  def down
@@ -203,12 +192,14 @@ The latest version of Active Record can be installed with RubyGems:
203
192
 
204
193
  Source code can be downloaded as part of the Rails project on GitHub
205
194
 
206
- * https://github.com/rails/rails/tree/3-2-stable/activerecord
195
+ * https://github.com/rails/rails/tree/master/activerecord
207
196
 
208
197
 
209
198
  == License
210
199
 
211
- Active Record is released under the MIT license.
200
+ Active Record is released under the MIT license:
201
+
202
+ * http://www.opensource.org/licenses/MIT
212
203
 
213
204
 
214
205
  == Support
@@ -143,7 +143,7 @@ Benchmark.ips(TIME) do |x|
143
143
  end
144
144
 
145
145
  x.report 'Resource#update' do
146
- Exhibit.first.update_attributes(:name => 'bob')
146
+ Exhibit.first.update(name: 'bob')
147
147
  end
148
148
 
149
149
  x.report 'Resource#destroy' do
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2004-2011 David Heinemeier Hansson
2
+ # Copyright (c) 2004-2013 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
@@ -22,24 +22,45 @@
22
22
  #++
23
23
 
24
24
  require 'active_support'
25
- require 'active_support/i18n'
25
+ require 'active_support/rails'
26
26
  require 'active_model'
27
27
  require 'arel'
28
+ require 'active_record/deprecated_finders'
28
29
 
29
30
  require 'active_record/version'
30
31
 
31
32
  module ActiveRecord
32
33
  extend ActiveSupport::Autoload
33
34
 
34
- # ActiveRecord::SessionStore depends on the abstract store in Action Pack.
35
- # Eager loading this class would break client code that eager loads Active
36
- # Record standalone.
37
- #
38
- # Note that the Rails application generator creates an initializer specific
39
- # for setting the session store. Thus, albeit in theory this autoload would
40
- # not be thread-safe, in practice it is because if the application uses this
41
- # session store its autoload happens at boot time.
42
- autoload :SessionStore
35
+ autoload :Base
36
+ autoload :Callbacks
37
+ autoload :Core
38
+ autoload :CounterCache
39
+ autoload :ConnectionHandling
40
+ autoload :DynamicMatchers
41
+ autoload :Explain
42
+ autoload :Inheritance
43
+ autoload :Integration
44
+ autoload :Migration
45
+ autoload :Migrator, 'active_record/migration'
46
+ autoload :ModelSchema
47
+ autoload :NestedAttributes
48
+ autoload :Persistence
49
+ autoload :QueryCache
50
+ autoload :Querying
51
+ autoload :ReadonlyAttributes
52
+ autoload :Reflection
53
+ autoload :Sanitization
54
+ autoload :Schema
55
+ autoload :SchemaDumper
56
+ autoload :SchemaMigration
57
+ autoload :Scoping
58
+ autoload :Serialization
59
+ autoload :Store
60
+ autoload :Timestamp
61
+ autoload :Transactions
62
+ autoload :Translation
63
+ autoload :Validations
43
64
 
44
65
  eager_autoload do
45
66
  autoload :ActiveRecordError, 'active_record/errors'
@@ -53,6 +74,7 @@ module ActiveRecord
53
74
  autoload :AutosaveAssociation
54
75
 
55
76
  autoload :Relation
77
+ autoload :NullRelation
56
78
 
57
79
  autoload_under 'relation' do
58
80
  autoload :QueryMethods
@@ -61,41 +83,10 @@ module ActiveRecord
61
83
  autoload :PredicateBuilder
62
84
  autoload :SpawnMethods
63
85
  autoload :Batches
64
- autoload :Explain
65
86
  autoload :Delegation
66
87
  end
67
88
 
68
- autoload :Base
69
- autoload :Callbacks
70
- autoload :CounterCache
71
- autoload :DynamicMatchers
72
- autoload :DynamicFinderMatch
73
- autoload :DynamicScopeMatch
74
- autoload :Explain
75
- autoload :IdentityMap
76
- autoload :Inheritance
77
- autoload :Integration
78
- autoload :Migration
79
- autoload :Migrator, 'active_record/migration'
80
- autoload :ModelSchema
81
- autoload :NestedAttributes
82
- autoload :Observer
83
- autoload :Persistence
84
- autoload :QueryCache
85
- autoload :Querying
86
- autoload :ReadonlyAttributes
87
- autoload :Reflection
88
89
  autoload :Result
89
- autoload :Sanitization
90
- autoload :Schema
91
- autoload :SchemaDumper
92
- autoload :Scoping
93
- autoload :Serialization
94
- autoload :Store
95
- autoload :Timestamp
96
- autoload :Transactions
97
- autoload :Translation
98
- autoload :Validations
99
90
  end
100
91
 
101
92
  module Coders
@@ -114,7 +105,6 @@ module ActiveRecord
114
105
  autoload :TimeZoneConversion
115
106
  autoload :Write
116
107
  autoload :Serialization
117
- autoload :DeprecatedUnderscoreRead
118
108
  end
119
109
  end
120
110
 
@@ -145,12 +135,33 @@ module ActiveRecord
145
135
  end
146
136
  end
147
137
 
138
+ module Tasks
139
+ extend ActiveSupport::Autoload
140
+
141
+ autoload :DatabaseTasks
142
+ autoload :SQLiteDatabaseTasks, 'active_record/tasks/sqlite_database_tasks'
143
+ autoload :MySQLDatabaseTasks, 'active_record/tasks/mysql_database_tasks'
144
+ autoload :PostgreSQLDatabaseTasks,
145
+ 'active_record/tasks/postgresql_database_tasks'
146
+ end
147
+
148
148
  autoload :TestCase
149
149
  autoload :TestFixtures, 'active_record/fixtures'
150
+
151
+ def self.eager_load!
152
+ super
153
+ ActiveRecord::Locking.eager_load!
154
+ ActiveRecord::Scoping.eager_load!
155
+ ActiveRecord::Associations.eager_load!
156
+ ActiveRecord::AttributeMethods.eager_load!
157
+ ActiveRecord::ConnectionAdapters.eager_load!
158
+ end
150
159
  end
151
160
 
152
161
  ActiveSupport.on_load(:active_record) do
153
162
  Arel::Table.engine = self
154
163
  end
155
164
 
156
- I18n.load_path << File.dirname(__FILE__) + '/active_record/locale/en.yml'
165
+ ActiveSupport.on_load(:i18n) do
166
+ I18n.load_path << File.dirname(__FILE__) + '/active_record/locale/en.yml'
167
+ end
@@ -10,14 +10,14 @@ module ActiveRecord
10
10
  # Active Record implements aggregation through a macro-like class method called +composed_of+
11
11
  # for representing attributes as value objects. It expresses relationships like "Account [is]
12
12
  # composed of Money [among other things]" or "Person [is] composed of [an] address". Each call
13
- # to the macro adds a description of how the value objects are created from the attributes of
14
- # the entity object (when the entity is initialized either as a new object or from finding an
15
- # existing object) and how it can be turned back into attributes (when the entity is saved to
13
+ # to the macro adds a description of how the value objects are created from the attributes of
14
+ # the entity object (when the entity is initialized either as a new object or from finding an
15
+ # existing object) and how it can be turned back into attributes (when the entity is saved to
16
16
  # the database).
17
17
  #
18
18
  # class Customer < ActiveRecord::Base
19
- # composed_of :balance, :class_name => "Money", :mapping => %w(balance amount)
20
- # composed_of :address, :mapping => [ %w(address_street street), %w(address_city city) ]
19
+ # composed_of :balance, class_name: "Money", mapping: %w(balance amount)
20
+ # composed_of :address, mapping: [ %w(address_street street), %w(address_city city) ]
21
21
  # end
22
22
  #
23
23
  # The customer class now has the following methods to manipulate the value objects:
@@ -71,7 +71,7 @@ module ActiveRecord
71
71
  # Now it's possible to access attributes from the database through the value objects instead. If
72
72
  # you choose to name the composition the same as the attribute's name, it will be the only way to
73
73
  # access that attribute. That's the case with our +balance+ attribute. You interact with the value
74
- # objects just like you would any other attribute, though:
74
+ # objects just like you would with any other attribute:
75
75
  #
76
76
  # customer.balance = Money.new(20) # sets the Money value object and the attribute
77
77
  # customer.balance # => Money value object
@@ -86,6 +86,12 @@ module ActiveRecord
86
86
  # customer.address_street = "Hyancintvej"
87
87
  # customer.address_city = "Copenhagen"
88
88
  # customer.address # => Address.new("Hyancintvej", "Copenhagen")
89
+ #
90
+ # customer.address_street = "Vesterbrogade"
91
+ # customer.address # => Address.new("Hyancintvej", "Copenhagen")
92
+ # customer.clear_aggregation_cache
93
+ # customer.address # => Address.new("Vesterbrogade", "Copenhagen")
94
+ #
89
95
  # customer.address = Address.new("May Street", "Chicago")
90
96
  # customer.address_street # => "May Street"
91
97
  # customer.address_city # => "Chicago"
@@ -101,13 +107,13 @@ module ActiveRecord
101
107
  # ActiveRecord::Base classes are entity objects.
102
108
  #
103
109
  # It's also important to treat the value objects as immutable. Don't allow the Money object to have
104
- # its amount changed after creation. Create a new Money object with the new value instead. This
105
- # is exemplified by the Money#exchange_to method that returns a new value object instead of changing
110
+ # its amount changed after creation. Create a new Money object with the new value instead. The
111
+ # Money#exchange_to method is an example of this. It returns a new value object instead of changing
106
112
  # its own values. Active Record won't persist value objects that have been changed through means
107
113
  # other than the writer method.
108
114
  #
109
115
  # The immutable requirement is enforced by Active Record by freezing any object assigned as a value
110
- # object. Attempting to change it afterwards will result in a ActiveSupport::FrozenObjectError.
116
+ # object. Attempting to change it afterwards will result in a RuntimeError.
111
117
  #
112
118
  # Read more about value objects on http://c2.com/cgi/wiki?ValueObject and on the dangers of not
113
119
  # keeping value objects immutable on http://c2.com/cgi/wiki?ValueObjectsShouldBeImmutable
@@ -119,7 +125,7 @@ module ActiveRecord
119
125
  # option, as arguments. If the value class doesn't support this convention then +composed_of+ allows
120
126
  # a custom constructor to be specified.
121
127
  #
122
- # When a new value is assigned to the value object the default assumption is that the new value
128
+ # When a new value is assigned to the value object, the default assumption is that the new value
123
129
  # is an instance of the value class. Specifying a custom converter allows the new value to be automatically
124
130
  # converted to an instance of value class if necessary.
125
131
  #
@@ -132,15 +138,15 @@ module ActiveRecord
132
138
  #
133
139
  # class NetworkResource < ActiveRecord::Base
134
140
  # composed_of :cidr,
135
- # :class_name => 'NetAddr::CIDR',
136
- # :mapping => [ %w(network_address network), %w(cidr_range bits) ],
137
- # :allow_nil => true,
138
- # :constructor => Proc.new { |network_address, cidr_range| NetAddr::CIDR.create("#{network_address}/#{cidr_range}") },
139
- # :converter => Proc.new { |value| NetAddr::CIDR.create(value.is_a?(Array) ? value.join('/') : value) }
141
+ # class_name: 'NetAddr::CIDR',
142
+ # mapping: [ %w(network_address network), %w(cidr_range bits) ],
143
+ # allow_nil: true,
144
+ # constructor: Proc.new { |network_address, cidr_range| NetAddr::CIDR.create("#{network_address}/#{cidr_range}") },
145
+ # converter: Proc.new { |value| NetAddr::CIDR.create(value.is_a?(Array) ? value.join('/') : value) }
140
146
  # end
141
147
  #
142
148
  # # This calls the :constructor
143
- # network_resource = NetworkResource.new(:network_address => '192.168.0.1', :cidr_range => 24)
149
+ # network_resource = NetworkResource.new(network_address: '192.168.0.1', cidr_range: 24)
144
150
  #
145
151
  # # These assignments will both use the :converter
146
152
  # network_resource.cidr = [ '192.168.2.1', 8 ]
@@ -159,7 +165,7 @@ module ActiveRecord
159
165
  # by specifying an instance of the value object in the conditions hash. The following example
160
166
  # finds all customers with +balance_amount+ equal to 20 and +balance_currency+ equal to "USD":
161
167
  #
162
- # Customer.where(:balance => Money.new(20, "USD")).all
168
+ # Customer.where(balance: Money.new(20, "USD"))
163
169
  #
164
170
  module ClassMethods
165
171
  # Adds reader and writer methods for manipulating a value object:
@@ -187,20 +193,21 @@ module ActiveRecord
187
193
  # * <tt>:converter</tt> - A symbol specifying the name of a class method of <tt>:class_name</tt>
188
194
  # or a Proc that is called when a new value is assigned to the value object. The converter is
189
195
  # passed the single value that is used in the assignment and is only called if the new value is
190
- # not an instance of <tt>:class_name</tt>.
196
+ # not an instance of <tt>:class_name</tt>. If <tt>:allow_nil</tt> is set to true, the converter
197
+ # can return nil to skip the assignment.
191
198
  #
192
199
  # Option examples:
193
- # composed_of :temperature, :mapping => %w(reading celsius)
194
- # composed_of :balance, :class_name => "Money", :mapping => %w(balance amount),
195
- # :converter => Proc.new { |balance| balance.to_money }
196
- # composed_of :address, :mapping => [ %w(address_street street), %w(address_city city) ]
200
+ # composed_of :temperature, mapping: %w(reading celsius)
201
+ # composed_of :balance, class_name: "Money", mapping: %w(balance amount),
202
+ # converter: Proc.new { |balance| balance.to_money }
203
+ # composed_of :address, mapping: [ %w(address_street street), %w(address_city city) ]
197
204
  # composed_of :gps_location
198
- # composed_of :gps_location, :allow_nil => true
205
+ # composed_of :gps_location, allow_nil: true
199
206
  # composed_of :ip_address,
200
- # :class_name => 'IPAddr',
201
- # :mapping => %w(ip to_i),
202
- # :constructor => Proc.new { |ip| IPAddr.new(ip, Socket::AF_INET) },
203
- # :converter => Proc.new { |ip| ip.is_a?(Integer) ? IPAddr.new(ip, Socket::AF_INET) : IPAddr.new(ip.to_s) }
207
+ # class_name: 'IPAddr',
208
+ # mapping: %w(ip to_i),
209
+ # constructor: Proc.new { |ip| IPAddr.new(ip, Socket::AF_INET) },
210
+ # converter: Proc.new { |ip| ip.is_a?(Integer) ? IPAddr.new(ip, Socket::AF_INET) : IPAddr.new(ip.to_s) }
204
211
  #
205
212
  def composed_of(part_id, options = {})
206
213
  options.assert_valid_keys(:class_name, :mapping, :allow_nil, :constructor, :converter)
@@ -216,7 +223,7 @@ module ActiveRecord
216
223
  reader_method(name, class_name, mapping, allow_nil, constructor)
217
224
  writer_method(name, class_name, mapping, allow_nil, converter)
218
225
 
219
- create_reflection(:composed_of, part_id, options, self)
226
+ create_reflection(:composed_of, part_id, nil, options, self)
220
227
  end
221
228
 
222
229
  private
@@ -235,16 +242,15 @@ module ActiveRecord
235
242
 
236
243
  def writer_method(name, class_name, mapping, allow_nil, converter)
237
244
  define_method("#{name}=") do |part|
245
+ klass = class_name.constantize
246
+ unless part.is_a?(klass) || converter.nil? || part.nil?
247
+ part = converter.respond_to?(:call) ? converter.call(part) : klass.send(converter, part)
248
+ end
249
+
238
250
  if part.nil? && allow_nil
239
251
  mapping.each { |pair| self[pair.first] = nil }
240
252
  @aggregation_cache[name] = nil
241
253
  else
242
- unless part.is_a?(class_name.constantize) || converter.nil?
243
- part = converter.respond_to?(:call) ?
244
- converter.call(part) :
245
- class_name.constantize.send(converter, part)
246
- end
247
-
248
254
  mapping.each { |pair| self[pair.first] = part.send(pair.last) }
249
255
  @aggregation_cache[name] = part.freeze
250
256
  end
@@ -1,10 +1,7 @@
1
- require 'active_support/core_ext/array/wrap'
2
1
  require 'active_support/core_ext/enumerable'
3
- require 'active_support/core_ext/module/delegation'
4
- require 'active_support/core_ext/object/blank'
5
2
  require 'active_support/core_ext/string/conversions'
6
3
  require 'active_support/core_ext/module/remove_method'
7
- require 'active_support/core_ext/class/attribute'
4
+ require 'active_record/errors'
8
5
 
9
6
  module ActiveRecord
10
7
  class InverseOfAssociationNotFoundError < ActiveRecordError #:nodoc:
@@ -21,7 +18,7 @@ module ActiveRecord
21
18
 
22
19
  class HasManyThroughAssociationPolymorphicSourceError < ActiveRecordError #:nodoc:
23
20
  def initialize(owner_class_name, reflection, source_reflection)
24
- super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' on the polymorphic object '#{source_reflection.class_name}##{source_reflection.name}'.")
21
+ super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' on the polymorphic object '#{source_reflection.class_name}##{source_reflection.name}' without 'source_type'. Try adding 'source_type: \"#{reflection.name.to_s.classify}\"' to 'has_many :through' definition.")
25
22
  end
26
23
  end
27
24
 
@@ -194,30 +191,10 @@ module ActiveRecord
194
191
  # * <tt>Project#portfolio, Project#portfolio=(portfolio), Project#portfolio.nil?</tt>
195
192
  # * <tt>Project#project_manager, Project#project_manager=(project_manager), Project#project_manager.nil?,</tt>
196
193
  # * <tt>Project#milestones.empty?, Project#milestones.size, Project#milestones, Project#milestones<<(milestone),</tt>
197
- # <tt>Project#milestones.delete(milestone), Project#milestones.find(milestone_id), Project#milestones.all(options),</tt>
194
+ # <tt>Project#milestones.delete(milestone), Project#milestones.destroy(milestone), Project#milestones.find(milestone_id),</tt>
198
195
  # <tt>Project#milestones.build, Project#milestones.create</tt>
199
196
  # * <tt>Project#categories.empty?, Project#categories.size, Project#categories, Project#categories<<(category1),</tt>
200
- # <tt>Project#categories.delete(category1)</tt>
201
- #
202
- # === Overriding generated methods
203
- #
204
- # Association methods are generated in a module that is included into the model class,
205
- # which allows you to easily override with your own methods and call the original
206
- # generated method with +super+. For example:
207
- #
208
- # class Car < ActiveRecord::Base
209
- # belongs_to :owner
210
- # belongs_to :old_owner
211
- # def owner=(new_owner)
212
- # self.old_owner = self.owner
213
- # super
214
- # end
215
- # end
216
- #
217
- # If your model class is <tt>Project</tt>, the module is
218
- # named <tt>Project::GeneratedFeatureMethods</tt>. The GeneratedFeatureMethods module is
219
- # included in the model class immediately after the (anonymous) generated attributes methods
220
- # module, meaning an association will override the methods for an attribute with the same name.
197
+ # <tt>Project#categories.delete(category1), Project#categories.destroy(category1)</tt>
221
198
  #
222
199
  # === A word of warning
223
200
  #
@@ -255,17 +232,38 @@ module ActiveRecord
255
232
  # others.size | X | X | X
256
233
  # others.length | X | X | X
257
234
  # others.count | X | X | X
258
- # others.sum(args*,&block) | X | X | X
235
+ # others.sum(*args) | X | X | X
259
236
  # others.empty? | X | X | X
260
237
  # others.clear | X | X | X
261
238
  # others.delete(other,other,...) | X | X | X
262
239
  # others.delete_all | X | X | X
240
+ # others.destroy(other,other,...) | X | X | X
263
241
  # others.destroy_all | X | X | X
264
242
  # others.find(*args) | X | X | X
265
243
  # others.exists? | X | X | X
266
244
  # others.uniq | X | X | X
267
245
  # others.reset | X | X | X
268
246
  #
247
+ # === Overriding generated methods
248
+ #
249
+ # Association methods are generated in a module that is included into the model class,
250
+ # which allows you to easily override with your own methods and call the original
251
+ # generated method with +super+. For example:
252
+ #
253
+ # class Car < ActiveRecord::Base
254
+ # belongs_to :owner
255
+ # belongs_to :old_owner
256
+ # def owner=(new_owner)
257
+ # self.old_owner = self.owner
258
+ # super
259
+ # end
260
+ # end
261
+ #
262
+ # If your model class is <tt>Project</tt>, the module is
263
+ # named <tt>Project::GeneratedFeatureMethods</tt>. The GeneratedFeatureMethods module is
264
+ # included in the model class immediately after the (anonymous) generated attributes methods
265
+ # module, meaning an association will override the methods for an attribute with the same name.
266
+ #
269
267
  # == Cardinality and associations
270
268
  #
271
269
  # Active Record associations can be used to describe one-to-one, one-to-many and many-to-many
@@ -308,11 +306,11 @@ module ActiveRecord
308
306
  # end
309
307
  # class Programmer < ActiveRecord::Base
310
308
  # has_many :assignments
311
- # has_many :projects, :through => :assignments
309
+ # has_many :projects, through: :assignments
312
310
  # end
313
311
  # class Project < ActiveRecord::Base
314
312
  # has_many :assignments
315
- # has_many :programmers, :through => :assignments
313
+ # has_many :programmers, through: :assignments
316
314
  # end
317
315
  #
318
316
  # For the second way, use +has_and_belongs_to_many+ in both models. This requires a join table
@@ -401,14 +399,35 @@ module ActiveRecord
401
399
  # * All unsaved (<tt>new_record? == true</tt>) members of the collection are automatically
402
400
  # saved when the parent is saved.
403
401
  #
404
- # === Association callbacks
402
+ # == Customizing the query
403
+ #
404
+ # Associations are built from <tt>Relation</tt>s, and you can use the <tt>Relation</tt> syntax
405
+ # to customize them. For example, to add a condition:
406
+ #
407
+ # class Blog < ActiveRecord::Base
408
+ # has_many :published_posts, -> { where published: true }, class_name: 'Post'
409
+ # end
410
+ #
411
+ # Inside the <tt>-> { ... }</tt> block you can use all of the usual <tt>Relation</tt> methods.
412
+ #
413
+ # === Accessing the owner object
414
+ #
415
+ # Sometimes it is useful to have access to the owner object when building the query. The owner
416
+ # is passed as a parameter to the block. For example, the following association would find all
417
+ # events that occur on the user's birthday:
418
+ #
419
+ # class User < ActiveRecord::Base
420
+ # has_many :birthday_events, ->(user) { where starts_on: user.birthday }, class_name: 'Event'
421
+ # end
422
+ #
423
+ # == Association callbacks
405
424
  #
406
425
  # Similar to the normal callbacks that hook into the life cycle of an Active Record object,
407
426
  # you can also define callbacks that get triggered when you add an object to or remove an
408
427
  # object from an association collection.
409
428
  #
410
429
  # class Project
411
- # has_and_belongs_to_many :developers, :after_add => :evaluate_velocity
430
+ # has_and_belongs_to_many :developers, after_add: :evaluate_velocity
412
431
  #
413
432
  # def evaluate_velocity(developer)
414
433
  # ...
@@ -419,7 +438,7 @@ module ActiveRecord
419
438
  #
420
439
  # class Project
421
440
  # has_and_belongs_to_many :developers,
422
- # :after_add => [:evaluate_velocity, Proc.new { |p, d| p.shipping_date = Time.now}]
441
+ # after_add: [:evaluate_velocity, Proc.new { |p, d| p.shipping_date = Time.now}]
423
442
  # end
424
443
  #
425
444
  # Possible callbacks are: +before_add+, +after_add+, +before_remove+ and +after_remove+.
@@ -428,7 +447,7 @@ module ActiveRecord
428
447
  # added to the collection. Same with the +before_remove+ callbacks; if an exception is
429
448
  # thrown the object doesn't get removed.
430
449
  #
431
- # === Association extensions
450
+ # == Association extensions
432
451
  #
433
452
  # The proxy objects that control the access to associations can be extended through anonymous
434
453
  # modules. This is especially beneficial for adding new finders, creators, and other
@@ -438,7 +457,7 @@ module ActiveRecord
438
457
  # has_many :people do
439
458
  # def find_or_create_by_name(name)
440
459
  # first_name, last_name = name.split(" ", 2)
441
- # find_or_create_by_first_name_and_last_name(first_name, last_name)
460
+ # find_or_create_by(first_name: first_name, last_name: last_name)
442
461
  # end
443
462
  # end
444
463
  # end
@@ -453,25 +472,16 @@ module ActiveRecord
453
472
  # module FindOrCreateByNameExtension
454
473
  # def find_or_create_by_name(name)
455
474
  # first_name, last_name = name.split(" ", 2)
456
- # find_or_create_by_first_name_and_last_name(first_name, last_name)
475
+ # find_or_create_by(first_name: first_name, last_name: last_name)
457
476
  # end
458
477
  # end
459
478
  #
460
479
  # class Account < ActiveRecord::Base
461
- # has_many :people, :extend => FindOrCreateByNameExtension
480
+ # has_many :people, -> { extending FindOrCreateByNameExtension }
462
481
  # end
463
482
  #
464
483
  # class Company < ActiveRecord::Base
465
- # has_many :people, :extend => FindOrCreateByNameExtension
466
- # end
467
- #
468
- # If you need to use multiple named extension modules, you can specify an array of modules
469
- # with the <tt>:extend</tt> option.
470
- # In the case of name conflicts between methods in the modules, methods in modules later
471
- # in the array supercede those earlier in the array.
472
- #
473
- # class Account < ActiveRecord::Base
474
- # has_many :people, :extend => [FindOrCreateByNameExtension, FindRecentExtension]
484
+ # has_many :people, -> { extending FindOrCreateByNameExtension }
475
485
  # end
476
486
  #
477
487
  # Some extensions can only be made to work with knowledge of the association's internals.
@@ -489,7 +499,7 @@ module ActiveRecord
489
499
  # the same object, allowing you to make calls like <tt>proxy_association.owner</tt> inside
490
500
  # association extensions.
491
501
  #
492
- # === Association Join Models
502
+ # == Association Join Models
493
503
  #
494
504
  # Has Many associations can be configured with the <tt>:through</tt> option to use an
495
505
  # explicit join model to retrieve the data. This operates similarly to a
@@ -498,7 +508,7 @@ module ActiveRecord
498
508
  #
499
509
  # class Author < ActiveRecord::Base
500
510
  # has_many :authorships
501
- # has_many :books, :through => :authorships
511
+ # has_many :books, through: :authorships
502
512
  # end
503
513
  #
504
514
  # class Authorship < ActiveRecord::Base
@@ -514,7 +524,7 @@ module ActiveRecord
514
524
  #
515
525
  # class Firm < ActiveRecord::Base
516
526
  # has_many :clients
517
- # has_many :invoices, :through => :clients
527
+ # has_many :invoices, through: :clients
518
528
  # end
519
529
  #
520
530
  # class Client < ActiveRecord::Base
@@ -534,7 +544,7 @@ module ActiveRecord
534
544
  #
535
545
  # class Group < ActiveRecord::Base
536
546
  # has_many :users
537
- # has_many :avatars, :through => :users
547
+ # has_many :avatars, through: :users
538
548
  # end
539
549
  #
540
550
  # class User < ActiveRecord::Base
@@ -547,7 +557,7 @@ module ActiveRecord
547
557
  # end
548
558
  #
549
559
  # @group = Group.first
550
- # @group.users.collect { |u| u.avatar }.flatten # select all avatars for all users in the group
560
+ # @group.users.collect { |u| u.avatar }.compact # select all avatars for all users in the group
551
561
  # @group.avatars # selects all avatars by going through the User join model.
552
562
  #
553
563
  # An important caveat with going through +has_one+ or +has_many+ associations on the
@@ -562,7 +572,7 @@ module ActiveRecord
562
572
  # works correctly (where <tt>tags</tt> is a +has_many+ <tt>:through</tt> association):
563
573
  #
564
574
  # @post = Post.first
565
- # @tag = @post.tags.build :name => "ruby"
575
+ # @tag = @post.tags.build name: "ruby"
566
576
  # @tag.save
567
577
  #
568
578
  # The last line ought to save the through record (a <tt>Taggable</tt>). This will only work if the
@@ -570,18 +580,18 @@ module ActiveRecord
570
580
  #
571
581
  # class Taggable < ActiveRecord::Base
572
582
  # belongs_to :post
573
- # belongs_to :tag, :inverse_of => :taggings
583
+ # belongs_to :tag, inverse_of: :taggings
574
584
  # end
575
585
  #
576
- # === Nested Associations
586
+ # == Nested Associations
577
587
  #
578
588
  # You can actually specify *any* association with the <tt>:through</tt> option, including an
579
589
  # association which has a <tt>:through</tt> option itself. For example:
580
590
  #
581
591
  # class Author < ActiveRecord::Base
582
592
  # has_many :posts
583
- # has_many :comments, :through => :posts
584
- # has_many :commenters, :through => :comments
593
+ # has_many :comments, through: :posts
594
+ # has_many :commenters, through: :comments
585
595
  # end
586
596
  #
587
597
  # class Post < ActiveRecord::Base
@@ -599,12 +609,12 @@ module ActiveRecord
599
609
  #
600
610
  # class Author < ActiveRecord::Base
601
611
  # has_many :posts
602
- # has_many :commenters, :through => :posts
612
+ # has_many :commenters, through: :posts
603
613
  # end
604
614
  #
605
615
  # class Post < ActiveRecord::Base
606
616
  # has_many :comments
607
- # has_many :commenters, :through => :comments
617
+ # has_many :commenters, through: :comments
608
618
  # end
609
619
  #
610
620
  # class Comment < ActiveRecord::Base
@@ -616,18 +626,18 @@ module ActiveRecord
616
626
  # add a <tt>Commenter</tt> in the example above, there would be no way to tell how to set up the
617
627
  # intermediate <tt>Post</tt> and <tt>Comment</tt> objects.
618
628
  #
619
- # === Polymorphic Associations
629
+ # == Polymorphic Associations
620
630
  #
621
631
  # Polymorphic associations on models are not restricted on what types of models they
622
632
  # can be associated with. Rather, they specify an interface that a +has_many+ association
623
633
  # must adhere to.
624
634
  #
625
635
  # class Asset < ActiveRecord::Base
626
- # belongs_to :attachable, :polymorphic => true
636
+ # belongs_to :attachable, polymorphic: true
627
637
  # end
628
638
  #
629
639
  # class Post < ActiveRecord::Base
630
- # has_many :assets, :as => :attachable # The :as option specifies the polymorphic interface to use.
640
+ # has_many :assets, as: :attachable # The :as option specifies the polymorphic interface to use.
631
641
  # end
632
642
  #
633
643
  # @asset.attachable = @post
@@ -644,7 +654,7 @@ module ActiveRecord
644
654
  # column in the posts table.
645
655
  #
646
656
  # class Asset < ActiveRecord::Base
647
- # belongs_to :attachable, :polymorphic => true
657
+ # belongs_to :attachable, polymorphic: true
648
658
  #
649
659
  # def attachable_type=(sType)
650
660
  # super(sType.to_s.classify.constantize.base_class.to_s)
@@ -652,8 +662,8 @@ module ActiveRecord
652
662
  # end
653
663
  #
654
664
  # class Post < ActiveRecord::Base
655
- # # because we store "Post" in attachable_type now :dependent => :destroy will work
656
- # has_many :assets, :as => :attachable, :dependent => :destroy
665
+ # # because we store "Post" in attachable_type now dependent: :destroy will work
666
+ # has_many :assets, as: :attachable, dependent: :destroy
657
667
  # end
658
668
  #
659
669
  # class GuestPost < Post
@@ -715,7 +725,7 @@ module ActiveRecord
715
725
  #
716
726
  # To include a deep hierarchy of associations, use a hash:
717
727
  #
718
- # Post.includes(:author, {:comments => {:author => :gravatar}}).each do |post|
728
+ # Post.includes(:author, {comments: {author: :gravatar}}).each do |post|
719
729
  #
720
730
  # That'll grab not only all the comments but all their authors and gravatar pictures.
721
731
  # You can mix and match symbols, arrays and hashes in any combination to describe the
@@ -731,7 +741,7 @@ module ActiveRecord
731
741
  # other than the main one. If this is the case Active Record falls back to the previously
732
742
  # used LEFT OUTER JOIN based strategy. For example
733
743
  #
734
- # Post.includes([:author, :comments]).where(['comments.approved = ?', true]).all
744
+ # Post.includes([:author, :comments]).where(['comments.approved = ?', true])
735
745
  #
736
746
  # This will result in a single SQL query with joins along the lines of:
737
747
  # <tt>LEFT OUTER JOIN comments ON comments.post_id = posts.id</tt> and
@@ -740,13 +750,13 @@ module ActiveRecord
740
750
  # In the above example posts with no approved comments are not returned at all, because
741
751
  # the conditions apply to the SQL statement as a whole and not just to the association.
742
752
  # You must disambiguate column references for this fallback to happen, for example
743
- # <tt>:order => "author.name DESC"</tt> will work but <tt>:order => "name DESC"</tt> will not.
753
+ # <tt>order: "author.name DESC"</tt> will work but <tt>order: "name DESC"</tt> will not.
744
754
  #
745
755
  # If you do want eager load only some members of an association it is usually more natural
746
756
  # to include an association which has conditions defined on it:
747
757
  #
748
758
  # class Post < ActiveRecord::Base
749
- # has_many :approved_comments, :class_name => 'Comment', :conditions => ['approved = ?', true]
759
+ # has_many :approved_comments, -> { where approved: true }, class_name: 'Comment'
750
760
  # end
751
761
  #
752
762
  # Post.includes(:approved_comments)
@@ -758,18 +768,15 @@ module ActiveRecord
758
768
  # returning all the associated objects:
759
769
  #
760
770
  # class Picture < ActiveRecord::Base
761
- # has_many :most_recent_comments, :class_name => 'Comment', :order => 'id DESC', :limit => 10
771
+ # has_many :most_recent_comments, -> { order('id DESC').limit(10) }, class_name: 'Comment'
762
772
  # end
763
773
  #
764
774
  # Picture.includes(:most_recent_comments).first.most_recent_comments # => returns all associated comments.
765
775
  #
766
- # When eager loaded, conditions are interpolated in the context of the model class, not
767
- # the model instance. Conditions are lazily interpolated before the actual model exists.
768
- #
769
776
  # Eager loading is supported with polymorphic associations.
770
777
  #
771
778
  # class Address < ActiveRecord::Base
772
- # belongs_to :addressable, :polymorphic => true
779
+ # belongs_to :addressable, polymorphic: true
773
780
  # end
774
781
  #
775
782
  # A call that tries to eager load the addressable model
@@ -803,10 +810,10 @@ module ActiveRecord
803
810
  #
804
811
  # TreeMixin.joins(:children)
805
812
  # # => SELECT ... FROM mixins INNER JOIN mixins childrens_mixins ...
806
- # TreeMixin.joins(:children => :parent)
813
+ # TreeMixin.joins(children: :parent)
807
814
  # # => SELECT ... FROM mixins INNER JOIN mixins childrens_mixins ...
808
815
  # INNER JOIN parents_mixins ...
809
- # TreeMixin.joins(:children => {:parent => :children})
816
+ # TreeMixin.joins(children: {parent: :children})
810
817
  # # => SELECT ... FROM mixins INNER JOIN mixins childrens_mixins ...
811
818
  # INNER JOIN parents_mixins ...
812
819
  # INNER JOIN mixins childrens_mixins_2
@@ -815,10 +822,10 @@ module ActiveRecord
815
822
  #
816
823
  # Post.joins(:categories)
817
824
  # # => SELECT ... FROM posts INNER JOIN categories_posts ... INNER JOIN categories ...
818
- # Post.joins(:categories => :posts)
825
+ # Post.joins(categories: :posts)
819
826
  # # => SELECT ... FROM posts INNER JOIN categories_posts ... INNER JOIN categories ...
820
827
  # INNER JOIN categories_posts posts_categories_join INNER JOIN posts posts_categories
821
- # Post.joins(:categories => {:posts => :categories})
828
+ # Post.joins(categories: {posts: :categories})
822
829
  # # => SELECT ... FROM posts INNER JOIN categories_posts ... INNER JOIN categories ...
823
830
  # INNER JOIN categories_posts posts_categories_join INNER JOIN posts posts_categories
824
831
  # INNER JOIN categories_posts categories_posts_join INNER JOIN categories categories_posts_2
@@ -843,8 +850,8 @@ module ActiveRecord
843
850
  # module MyApplication
844
851
  # module Business
845
852
  # class Firm < ActiveRecord::Base
846
- # has_many :clients
847
- # end
853
+ # has_many :clients
854
+ # end
848
855
  #
849
856
  # class Client < ActiveRecord::Base; end
850
857
  # end
@@ -862,7 +869,7 @@ module ActiveRecord
862
869
  #
863
870
  # module Billing
864
871
  # class Account < ActiveRecord::Base
865
- # belongs_to :firm, :class_name => "MyApplication::Business::Firm"
872
+ # belongs_to :firm, class_name: "MyApplication::Business::Firm"
866
873
  # end
867
874
  # end
868
875
  # end
@@ -904,16 +911,16 @@ module ActiveRecord
904
911
  # example, if we changed our model definitions to:
905
912
  #
906
913
  # class Dungeon < ActiveRecord::Base
907
- # has_many :traps, :inverse_of => :dungeon
908
- # has_one :evil_wizard, :inverse_of => :dungeon
914
+ # has_many :traps, inverse_of: :dungeon
915
+ # has_one :evil_wizard, inverse_of: :dungeon
909
916
  # end
910
917
  #
911
918
  # class Trap < ActiveRecord::Base
912
- # belongs_to :dungeon, :inverse_of => :traps
919
+ # belongs_to :dungeon, inverse_of: :traps
913
920
  # end
914
921
  #
915
922
  # class EvilWizard < ActiveRecord::Base
916
- # belongs_to :dungeon, :inverse_of => :evil_wizard
923
+ # belongs_to :dungeon, inverse_of: :evil_wizard
917
924
  # end
918
925
  #
919
926
  # Then, from our code snippet above, +d+ and <tt>t.dungeon</tt> are actually the same
@@ -936,13 +943,19 @@ module ActiveRecord
936
943
  # For example:
937
944
  #
938
945
  # class Author
939
- # has_many :posts, :dependent => :destroy
946
+ # has_many :posts, dependent: :destroy
940
947
  # end
941
948
  # Author.find(1).destroy # => Will destroy all of the author's posts, too
942
949
  #
943
950
  # The <tt>:dependent</tt> option can have different values which specify how the deletion
944
951
  # is done. For more information, see the documentation for this option on the different
945
- # specific association types.
952
+ # specific association types. When no option is given, the behavior is to do nothing
953
+ # with the associated records when destroying a record.
954
+ #
955
+ # Note that <tt>:dependent</tt> is implemented using Rails' callback
956
+ # system, which works by processing callbacks in order. Therefore, other
957
+ # callbacks declared either before or after the <tt>:dependent</tt> option
958
+ # can affect what it does.
946
959
  #
947
960
  # === Delete or destroy?
948
961
  #
@@ -952,8 +965,8 @@ module ActiveRecord
952
965
  # For +has_and_belongs_to_many+, <tt>delete</tt> and <tt>destroy</tt> are the same: they
953
966
  # cause the records in the join table to be removed.
954
967
  #
955
- # For +has_many+, <tt>destroy</tt> will always call the <tt>destroy</tt> method of the
956
- # record(s) being removed so that callbacks are run. However <tt>delete</tt> will either
968
+ # For +has_many+, <tt>destroy</tt> and <tt>destory_all</tt> will always call the <tt>destroy</tt> method of the
969
+ # record(s) being removed so that callbacks are run. However <tt>delete</tt> and <tt>delete_all</tt> will either
957
970
  # do the deletion according to the strategy specified by the <tt>:dependent</tt> option, or
958
971
  # if no <tt>:dependent</tt> option is given, then it will follow the default strategy.
959
972
  # The default strategy is <tt>:nullify</tt> (set the foreign keys to <tt>nil</tt>), except for
@@ -1014,12 +1027,18 @@ module ActiveRecord
1014
1027
  # parent object.
1015
1028
  # [collection.delete(object, ...)]
1016
1029
  # Removes one or more objects from the collection by setting their foreign keys to +NULL+.
1017
- # Objects will be in addition destroyed if they're associated with <tt>:dependent => :destroy</tt>,
1018
- # and deleted if they're associated with <tt>:dependent => :delete_all</tt>.
1030
+ # Objects will be in addition destroyed if they're associated with <tt>dependent: :destroy</tt>,
1031
+ # and deleted if they're associated with <tt>dependent: :delete_all</tt>.
1019
1032
  #
1020
1033
  # If the <tt>:through</tt> option is used, then the join records are deleted (rather than
1021
- # nullified) by default, but you can specify <tt>:dependent => :destroy</tt> or
1022
- # <tt>:dependent => :nullify</tt> to override this.
1034
+ # nullified) by default, but you can specify <tt>dependent: :destroy</tt> or
1035
+ # <tt>dependent: :nullify</tt> to override this.
1036
+ # [collection.destroy(object, ...)]
1037
+ # Removes one or more objects from the collection by running <tt>destroy</tt> on
1038
+ # each record, regardless of any dependent option, ensuring callbacks are run.
1039
+ #
1040
+ # If the <tt>:through</tt> option is used, then the join records are destroyed
1041
+ # instead, not the objects themselves.
1023
1042
  # [collection=objects]
1024
1043
  # Replaces the collections content by deleting and adding objects as appropriate. If the <tt>:through</tt>
1025
1044
  # option is true callbacks in the join models are triggered except destroy callbacks, since deletion is
@@ -1031,8 +1050,8 @@ module ActiveRecord
1031
1050
  # method loads the models and calls <tt>collection=</tt>. See above.
1032
1051
  # [collection.clear]
1033
1052
  # Removes every object from the collection. This destroys the associated objects if they
1034
- # are associated with <tt>:dependent => :destroy</tt>, deletes them directly from the
1035
- # database if <tt>:dependent => :delete_all</tt>, otherwise sets their foreign keys to +NULL+.
1053
+ # are associated with <tt>dependent: :destroy</tt>, deletes them directly from the
1054
+ # database if <tt>dependent: :delete_all</tt>, otherwise sets their foreign keys to +NULL+.
1036
1055
  # If the <tt>:through</tt> option is true no destroy callbacks are invoked on the join models.
1037
1056
  # Join models are directly deleted.
1038
1057
  # [collection.empty?]
@@ -1060,17 +1079,18 @@ module ActiveRecord
1060
1079
  # === Example
1061
1080
  #
1062
1081
  # Example: A Firm class declares <tt>has_many :clients</tt>, which will add:
1063
- # * <tt>Firm#clients</tt> (similar to <tt>Clients.all :conditions => ["firm_id = ?", id]</tt>)
1082
+ # * <tt>Firm#clients</tt> (similar to <tt>Client.where(firm_id: id)</tt>)
1064
1083
  # * <tt>Firm#clients<<</tt>
1065
1084
  # * <tt>Firm#clients.delete</tt>
1085
+ # * <tt>Firm#clients.destroy</tt>
1066
1086
  # * <tt>Firm#clients=</tt>
1067
1087
  # * <tt>Firm#client_ids</tt>
1068
1088
  # * <tt>Firm#client_ids=</tt>
1069
1089
  # * <tt>Firm#clients.clear</tt>
1070
1090
  # * <tt>Firm#clients.empty?</tt> (similar to <tt>firm.clients.size == 0</tt>)
1071
1091
  # * <tt>Firm#clients.size</tt> (similar to <tt>Client.count "firm_id = #{id}"</tt>)
1072
- # * <tt>Firm#clients.find</tt> (similar to <tt>Client.find(id, :conditions => "firm_id = #{id}")</tt>)
1073
- # * <tt>Firm#clients.exists?(:name => 'ACME')</tt> (similar to <tt>Client.exists?(:name => 'ACME', :firm_id => firm.id)</tt>)
1092
+ # * <tt>Firm#clients.find</tt> (similar to <tt>Client.where(firm_id: id).find(id)</tt>)
1093
+ # * <tt>Firm#clients.exists?(name: 'ACME')</tt> (similar to <tt>Client.exists?(name: 'ACME', firm_id: firm.id)</tt>)
1074
1094
  # * <tt>Firm#clients.build</tt> (similar to <tt>Client.new("firm_id" => id)</tt>)
1075
1095
  # * <tt>Firm#clients.create</tt> (similar to <tt>c = Client.new("firm_id" => id); c.save; c</tt>)
1076
1096
  # The declaration can also include an options hash to specialize the behavior of the association.
@@ -1081,15 +1101,6 @@ module ActiveRecord
1081
1101
  # from the association name. So <tt>has_many :products</tt> will by default be linked
1082
1102
  # to the Product class, but if the real class name is SpecialProduct, you'll have to
1083
1103
  # specify it with this option.
1084
- # [:conditions]
1085
- # Specify the conditions that the associated objects must meet in order to be included as a +WHERE+
1086
- # SQL fragment, such as <tt>price > 5 AND name LIKE 'B%'</tt>. Record creations from
1087
- # the association are scoped if a hash is used.
1088
- # <tt>has_many :posts, :conditions => {:published => true}</tt> will create published
1089
- # posts with <tt>@blog.posts.create</tt> or <tt>@blog.posts.build</tt>.
1090
- # [:order]
1091
- # Specify the order in which the associated objects are returned as an <tt>ORDER BY</tt> SQL fragment,
1092
- # such as <tt>last_name, first_name DESC</tt>.
1093
1104
  # [:foreign_key]
1094
1105
  # Specify the foreign key used for the association. By default this is guessed to be the name
1095
1106
  # of this class in lower-case and "_id" suffixed. So a Person class that makes a +has_many+
@@ -1097,44 +1108,24 @@ module ActiveRecord
1097
1108
  # [:primary_key]
1098
1109
  # Specify the method that returns the primary key used for the association. By default this is +id+.
1099
1110
  # [:dependent]
1100
- # If set to <tt>:destroy</tt> all the associated objects are destroyed
1101
- # alongside this object by calling their +destroy+ method. If set to <tt>:delete_all</tt> all associated
1102
- # objects are deleted *without* calling their +destroy+ method. If set to <tt>:nullify</tt> all associated
1103
- # objects' foreign keys are set to +NULL+ *without* calling their +save+ callbacks. If set to
1104
- # <tt>:restrict</tt> this object raises an <tt>ActiveRecord::DeleteRestrictionError</tt> exception and
1105
- # cannot be deleted if it has any associated objects.
1111
+ # Controls what happens to the associated objects when
1112
+ # their owner is destroyed. Note that these are implemented as
1113
+ # callbacks, and Rails executes callbacks in order. Therefore, other
1114
+ # similar callbacks may affect the :dependent behavior, and the
1115
+ # :dependent behavior may affect other callbacks.
1116
+ #
1117
+ # * <tt>:destroy</tt> causes all the associated objects to also be destroyed
1118
+ # * <tt>:delete_all</tt> causes all the asssociated objects to be deleted directly from the database (so callbacks will not execute)
1119
+ # * <tt>:nullify</tt> causes the foreign keys to be set to +NULL+. Callbacks are not executed.
1120
+ # * <tt>:restrict_with_exception</tt> causes an exception to be raised if there are any associated records
1121
+ # * <tt>:restrict_with_error</tt> causes an error to be added to the owner if there are any associated objects
1106
1122
  #
1107
1123
  # If using with the <tt>:through</tt> option, the association on the join model must be
1108
1124
  # a +belongs_to+, and the records which get deleted are the join records, rather than
1109
1125
  # the associated records.
1110
- #
1111
- # [:finder_sql]
1112
- # Specify a complete SQL statement to fetch the association. This is a good way to go for complex
1113
- # associations that depend on multiple tables. May be supplied as a string or a proc where interpolation is
1114
- # required. Note: When this option is used, +find_in_collection+
1115
- # is _not_ added.
1116
- # [:counter_sql]
1117
- # Specify a complete SQL statement to fetch the size of the association. If <tt>:finder_sql</tt> is
1118
- # specified but not <tt>:counter_sql</tt>, <tt>:counter_sql</tt> will be generated by
1119
- # replacing <tt>SELECT ... FROM</tt> with <tt>SELECT COUNT(*) FROM</tt>.
1120
- # [:extend]
1121
- # Specify a named module for extending the proxy. See "Association extensions".
1122
- # [:include]
1123
- # Specify second-order associations that should be eager loaded when the collection is loaded.
1124
- # [:group]
1125
- # An attribute name by which the result should be grouped. Uses the <tt>GROUP BY</tt> SQL-clause.
1126
- # [:having]
1127
- # Combined with +:group+ this can be used to filter the records that a <tt>GROUP BY</tt>
1128
- # returns. Uses the <tt>HAVING</tt> SQL-clause.
1129
- # [:limit]
1130
- # An integer determining the limit on the number of rows that should be returned.
1131
- # [:offset]
1132
- # An integer determining the offset from where the rows should be fetched. So at 5,
1133
- # it would skip the first 4 rows.
1134
- # [:select]
1135
- # By default, this is <tt>*</tt> as in <tt>SELECT * FROM</tt>, but can be changed if
1136
- # you, for example, want to do a join but not include the joined columns. Do not forget
1137
- # to include the primary and foreign keys, otherwise it will raise an error.
1126
+ # [:counter_cache]
1127
+ # This option can be used to configure a custom named <tt>:counter_cache.</tt> You only need this option,
1128
+ # when you customized the name of your <tt>:counter_cache</tt> on the <tt>belongs_to</tt> association.
1138
1129
  # [:as]
1139
1130
  # Specifies a polymorphic interface (See <tt>belongs_to</tt>).
1140
1131
  # [:through]
@@ -1156,21 +1147,21 @@ module ActiveRecord
1156
1147
  # [:source]
1157
1148
  # Specifies the source association name used by <tt>has_many :through</tt> queries.
1158
1149
  # Only use it if the name cannot be inferred from the association.
1159
- # <tt>has_many :subscribers, :through => :subscriptions</tt> will look for either <tt>:subscribers</tt> or
1150
+ # <tt>has_many :subscribers, through: :subscriptions</tt> will look for either <tt>:subscribers</tt> or
1160
1151
  # <tt>:subscriber</tt> on Subscription, unless a <tt>:source</tt> is given.
1161
1152
  # [:source_type]
1162
1153
  # Specifies type of the source association used by <tt>has_many :through</tt> queries where the source
1163
1154
  # association is a polymorphic +belongs_to+.
1164
- # [:uniq]
1165
- # If true, duplicates will be omitted from the collection. Useful in conjunction with <tt>:through</tt>.
1166
- # [:readonly]
1167
- # If true, all the associated objects are readonly through the association.
1168
1155
  # [:validate]
1169
1156
  # If +false+, don't validate the associated objects when saving the parent object. true by default.
1170
1157
  # [:autosave]
1171
1158
  # If true, always save the associated objects or destroy them if marked for destruction,
1172
1159
  # when saving the parent object. If false, never save or destroy the associated objects.
1173
- # By default, only save associated objects that are new records.
1160
+ # By default, only save associated objects that are new records. This option is implemented as a
1161
+ # before_save callback. Because callbacks are run in the order they are defined, associated objects
1162
+ # may need to be explicitly saved in any user-defined before_save callbacks.
1163
+ #
1164
+ # Note that <tt>accepts_nested_attributes_for</tt> sets <tt>:autosave</tt> to <tt>true</tt>.
1174
1165
  # [:inverse_of]
1175
1166
  # Specifies the name of the <tt>belongs_to</tt> association on the associated object
1176
1167
  # that is the inverse of this <tt>has_many</tt> association. Does not work in combination
@@ -1178,24 +1169,16 @@ module ActiveRecord
1178
1169
  # See ActiveRecord::Associations::ClassMethods's overview on Bi-directional associations for more detail.
1179
1170
  #
1180
1171
  # Option examples:
1181
- # has_many :comments, :order => "posted_on"
1182
- # has_many :comments, :include => :author
1183
- # has_many :people, :class_name => "Person", :conditions => "deleted = 0", :order => "name"
1184
- # has_many :tracks, :order => "position", :dependent => :destroy
1185
- # has_many :comments, :dependent => :nullify
1186
- # has_many :tags, :as => :taggable
1187
- # has_many :reports, :readonly => true
1188
- # has_many :subscribers, :through => :subscriptions, :source => :user
1189
- # has_many :subscribers, :class_name => "Person", :finder_sql => Proc.new {
1190
- # %Q{
1191
- # SELECT DISTINCT *
1192
- # FROM people p, post_subscriptions ps
1193
- # WHERE ps.post_id = #{id} AND ps.person_id = p.id
1194
- # ORDER BY p.first_name
1195
- # }
1196
- # }
1197
- def has_many(name, options = {}, &extension)
1198
- Builder::HasMany.build(self, name, options, &extension)
1172
+ # has_many :comments, -> { order "posted_on" }
1173
+ # has_many :comments, -> { includes :author }
1174
+ # has_many :people, -> { where("deleted = 0").order("name") }, class_name: "Person"
1175
+ # has_many :tracks, -> { order "position" }, dependent: :destroy
1176
+ # has_many :comments, dependent: :nullify
1177
+ # has_many :tags, as: :taggable
1178
+ # has_many :reports, -> { readonly }
1179
+ # has_many :subscribers, through: :subscriptions, source: :user
1180
+ def has_many(name, scope = nil, options = {}, &extension)
1181
+ Builder::HasMany.build(self, name, scope, options, &extension)
1199
1182
  end
1200
1183
 
1201
1184
  # Specifies a one-to-one association with another class. This method should only be used
@@ -1228,7 +1211,7 @@ module ActiveRecord
1228
1211
  # === Example
1229
1212
  #
1230
1213
  # An Account class declares <tt>has_one :beneficiary</tt>, which will add:
1231
- # * <tt>Account#beneficiary</tt> (similar to <tt>Beneficiary.first(:conditions => "account_id = #{id}")</tt>)
1214
+ # * <tt>Account#beneficiary</tt> (similar to <tt>Beneficiary.where(account_id: id).first</tt>)
1232
1215
  # * <tt>Account#beneficiary=(beneficiary)</tt> (similar to <tt>beneficiary.account_id = account.id; beneficiary.save</tt>)
1233
1216
  # * <tt>Account#build_beneficiary</tt> (similar to <tt>Beneficiary.new("account_id" => id)</tt>)
1234
1217
  # * <tt>Account#create_beneficiary</tt> (similar to <tt>b = Beneficiary.new("account_id" => id); b.save; b</tt>)
@@ -1243,34 +1226,23 @@ module ActiveRecord
1243
1226
  # Specify the class name of the association. Use it only if that name can't be inferred
1244
1227
  # from the association name. So <tt>has_one :manager</tt> will by default be linked to the Manager class, but
1245
1228
  # if the real class name is Person, you'll have to specify it with this option.
1246
- # [:conditions]
1247
- # Specify the conditions that the associated object must meet in order to be included as a +WHERE+
1248
- # SQL fragment, such as <tt>rank = 5</tt>. Record creation from the association is scoped if a hash
1249
- # is used. <tt>has_one :account, :conditions => {:enabled => true}</tt> will create
1250
- # an enabled account with <tt>@company.create_account</tt> or <tt>@company.build_account</tt>.
1251
- # [:order]
1252
- # Specify the order in which the associated objects are returned as an <tt>ORDER BY</tt> SQL fragment,
1253
- # such as <tt>last_name, first_name DESC</tt>.
1254
1229
  # [:dependent]
1255
- # If set to <tt>:destroy</tt>, the associated object is destroyed when this object is. If set to
1256
- # <tt>:delete</tt>, the associated object is deleted *without* calling its destroy method.
1257
- # If set to <tt>:nullify</tt>, the associated object's foreign key is set to +NULL+.
1258
- # Also, association is assigned. If set to <tt>:restrict</tt> this object raises an
1259
- # <tt>ActiveRecord::DeleteRestrictionError</tt> exception and cannot be deleted if it has any associated object.
1230
+ # Controls what happens to the associated object when
1231
+ # its owner is destroyed:
1232
+ #
1233
+ # * <tt>:destroy</tt> causes the associated object to also be destroyed
1234
+ # * <tt>:delete</tt> causes the asssociated object to be deleted directly from the database (so callbacks will not execute)
1235
+ # * <tt>:nullify</tt> causes the foreign key to be set to +NULL+. Callbacks are not executed.
1236
+ # * <tt>:restrict_with_exception</tt> causes an exception to be raised if there is an associated record
1237
+ # * <tt>:restrict_with_error</tt> causes an error to be added to the owner if there is an associated object
1260
1238
  # [:foreign_key]
1261
1239
  # Specify the foreign key used for the association. By default this is guessed to be the name
1262
1240
  # of this class in lower-case and "_id" suffixed. So a Person class that makes a +has_one+ association
1263
1241
  # will use "person_id" as the default <tt>:foreign_key</tt>.
1264
1242
  # [:primary_key]
1265
1243
  # Specify the method that returns the primary key used for the association. By default this is +id+.
1266
- # [:include]
1267
- # Specify second-order associations that should be eager loaded when this object is loaded.
1268
1244
  # [:as]
1269
1245
  # Specifies a polymorphic interface (See <tt>belongs_to</tt>).
1270
- # [:select]
1271
- # By default, this is <tt>*</tt> as in <tt>SELECT * FROM</tt>, but can be changed if, for example,
1272
- # you want to do a join but not include the joined columns. Do not forget to include the
1273
- # primary and foreign keys, otherwise it will raise an error.
1274
1246
  # [:through]
1275
1247
  # Specifies a Join Model through which to perform the query. Options for <tt>:class_name</tt>,
1276
1248
  # <tt>:primary_key</tt>, and <tt>:foreign_key</tt> are ignored, as the association uses the
@@ -1279,19 +1251,19 @@ module ActiveRecord
1279
1251
  # [:source]
1280
1252
  # Specifies the source association name used by <tt>has_one :through</tt> queries.
1281
1253
  # Only use it if the name cannot be inferred from the association.
1282
- # <tt>has_one :favorite, :through => :favorites</tt> will look for a
1254
+ # <tt>has_one :favorite, through: :favorites</tt> will look for a
1283
1255
  # <tt>:favorite</tt> on Favorite, unless a <tt>:source</tt> is given.
1284
1256
  # [:source_type]
1285
1257
  # Specifies type of the source association used by <tt>has_one :through</tt> queries where the source
1286
1258
  # association is a polymorphic +belongs_to+.
1287
- # [:readonly]
1288
- # If true, the associated object is readonly through the association.
1289
1259
  # [:validate]
1290
1260
  # If +false+, don't validate the associated object when saving the parent object. +false+ by default.
1291
1261
  # [:autosave]
1292
1262
  # If true, always save the associated object or destroy it if marked for destruction,
1293
1263
  # when saving the parent object. If false, never save or destroy the associated object.
1294
1264
  # By default, only save the associated object if it's a new record.
1265
+ #
1266
+ # Note that <tt>accepts_nested_attributes_for</tt> sets <tt>:autosave</tt> to <tt>true</tt>.
1295
1267
  # [:inverse_of]
1296
1268
  # Specifies the name of the <tt>belongs_to</tt> association on the associated object
1297
1269
  # that is the inverse of this <tt>has_one</tt> association. Does not work in combination
@@ -1299,17 +1271,17 @@ module ActiveRecord
1299
1271
  # See ActiveRecord::Associations::ClassMethods's overview on Bi-directional associations for more detail.
1300
1272
  #
1301
1273
  # Option examples:
1302
- # has_one :credit_card, :dependent => :destroy # destroys the associated credit card
1303
- # has_one :credit_card, :dependent => :nullify # updates the associated records foreign
1274
+ # has_one :credit_card, dependent: :destroy # destroys the associated credit card
1275
+ # has_one :credit_card, dependent: :nullify # updates the associated records foreign
1304
1276
  # # key value to NULL rather than destroying it
1305
- # has_one :last_comment, :class_name => "Comment", :order => "posted_on"
1306
- # has_one :project_manager, :class_name => "Person", :conditions => "role = 'project_manager'"
1307
- # has_one :attachment, :as => :attachable
1308
- # has_one :boss, :readonly => :true
1309
- # has_one :club, :through => :membership
1310
- # has_one :primary_address, :through => :addressables, :conditions => ["addressable.primary = ?", true], :source => :addressable
1311
- def has_one(name, options = {})
1312
- Builder::HasOne.build(self, name, options)
1277
+ # has_one :last_comment, -> { order 'posted_on' }, class_name: "Comment"
1278
+ # has_one :project_manager, -> { where role: 'project_manager' }, class_name: "Person"
1279
+ # has_one :attachment, as: :attachable
1280
+ # has_one :boss, readonly: :true
1281
+ # has_one :club, through: :membership
1282
+ # has_one :primary_address, -> { where primary: true }, through: :addressables, source: :addressable
1283
+ def has_one(name, scope = nil, options = {})
1284
+ Builder::HasOne.build(self, name, scope, options)
1313
1285
  end
1314
1286
 
1315
1287
  # Specifies a one-to-one association with another class. This method should only be used
@@ -1354,23 +1326,16 @@ module ActiveRecord
1354
1326
  # Specify the class name of the association. Use it only if that name can't be inferred
1355
1327
  # from the association name. So <tt>belongs_to :author</tt> will by default be linked to the Author class, but
1356
1328
  # if the real class name is Person, you'll have to specify it with this option.
1357
- # [:conditions]
1358
- # Specify the conditions that the associated object must meet in order to be included as a +WHERE+
1359
- # SQL fragment, such as <tt>authorized = 1</tt>.
1360
- # [:select]
1361
- # By default, this is <tt>*</tt> as in <tt>SELECT * FROM</tt>, but can be changed
1362
- # if, for example, you want to do a join but not include the joined columns. Do not
1363
- # forget to include the primary and foreign keys, otherwise it will raise an error.
1364
1329
  # [:foreign_key]
1365
1330
  # Specify the foreign key used for the association. By default this is guessed to be the name
1366
1331
  # of the association with an "_id" suffix. So a class that defines a <tt>belongs_to :person</tt>
1367
1332
  # association will use "person_id" as the default <tt>:foreign_key</tt>. Similarly,
1368
- # <tt>belongs_to :favorite_person, :class_name => "Person"</tt> will use a foreign key
1333
+ # <tt>belongs_to :favorite_person, class_name: "Person"</tt> will use a foreign key
1369
1334
  # of "favorite_person_id".
1370
1335
  # [:foreign_type]
1371
1336
  # Specify the column used to store the associated object's type, if this is a polymorphic
1372
1337
  # association. By default this is guessed to be the name of the association with a "_type"
1373
- # suffix. So a class that defines a <tt>belongs_to :taggable, :polymorphic => true</tt>
1338
+ # suffix. So a class that defines a <tt>belongs_to :taggable, polymorphic: true</tt>
1374
1339
  # association will use "taggable_type" as the default <tt>:foreign_type</tt>.
1375
1340
  # [:primary_key]
1376
1341
  # Specify the method that returns the primary key of associated object used for the association.
@@ -1386,19 +1351,17 @@ module ActiveRecord
1386
1351
  # and +decrement_counter+. The counter cache is incremented when an object of this
1387
1352
  # class is created and decremented when it's destroyed. This requires that a column
1388
1353
  # named <tt>#{table_name}_count</tt> (such as +comments_count+ for a belonging Comment class)
1389
- # is used on the associate class (such as a Post class). You can also specify a custom counter
1354
+ # is used on the associate class (such as a Post class) - that is the migration for
1355
+ # <tt>#{table_name}_count</tt> is created on the associate class (such that Post.comments_count will
1356
+ # return the count cached, see note below). You can also specify a custom counter
1390
1357
  # cache column by providing a column name instead of a +true+/+false+ value to this
1391
- # option (e.g., <tt>:counter_cache => :my_custom_counter</tt>.)
1358
+ # option (e.g., <tt>counter_cache: :my_custom_counter</tt>.)
1392
1359
  # Note: Specifying a counter cache will add it to that model's list of readonly attributes
1393
1360
  # using +attr_readonly+.
1394
- # [:include]
1395
- # Specify second-order associations that should be eager loaded when this object is loaded.
1396
1361
  # [:polymorphic]
1397
1362
  # Specify this association is a polymorphic association by passing +true+.
1398
1363
  # Note: If you've enabled the counter cache, then you may want to add the counter cache attribute
1399
1364
  # to the +attr_readonly+ list in the associated classes (e.g. <tt>class Post; attr_readonly :comments_count; end</tt>).
1400
- # [:readonly]
1401
- # If true, the associated object is readonly through the association.
1402
1365
  # [:validate]
1403
1366
  # If +false+, don't validate the associated objects when saving the parent object. +false+ by default.
1404
1367
  # [:autosave]
@@ -1406,6 +1369,8 @@ module ActiveRecord
1406
1369
  # saving the parent object.
1407
1370
  # If false, never save or destroy the associated object.
1408
1371
  # By default, only save the associated object if it's a new record.
1372
+ #
1373
+ # Note that <tt>accepts_nested_attributes_for</tt> sets <tt>:autosave</tt> to <tt>true</tt>.
1409
1374
  # [:touch]
1410
1375
  # If true, the associated object will be touched (the updated_at/on attributes set to now)
1411
1376
  # when this record is either saved or destroyed. If you specify a symbol, that attribute
@@ -1417,24 +1382,24 @@ module ActiveRecord
1417
1382
  # See ActiveRecord::Associations::ClassMethods's overview on Bi-directional associations for more detail.
1418
1383
  #
1419
1384
  # Option examples:
1420
- # belongs_to :firm, :foreign_key => "client_of"
1421
- # belongs_to :person, :primary_key => "name", :foreign_key => "person_name"
1422
- # belongs_to :author, :class_name => "Person", :foreign_key => "author_id"
1423
- # belongs_to :valid_coupon, :class_name => "Coupon", :foreign_key => "coupon_id",
1424
- # :conditions => 'discounts > #{payments_count}'
1425
- # belongs_to :attachable, :polymorphic => true
1426
- # belongs_to :project, :readonly => true
1427
- # belongs_to :post, :counter_cache => true
1428
- # belongs_to :company, :touch => true
1429
- # belongs_to :company, :touch => :employees_last_updated_at
1430
- def belongs_to(name, options = {})
1431
- Builder::BelongsTo.build(self, name, options)
1385
+ # belongs_to :firm, foreign_key: "client_of"
1386
+ # belongs_to :person, primary_key: "name", foreign_key: "person_name"
1387
+ # belongs_to :author, class_name: "Person", foreign_key: "author_id"
1388
+ # belongs_to :valid_coupon, ->(o) { where "discounts > #{o.payments_count}" },
1389
+ # class_name: "Coupon", foreign_key: "coupon_id"
1390
+ # belongs_to :attachable, polymorphic: true
1391
+ # belongs_to :project, readonly: true
1392
+ # belongs_to :post, counter_cache: true
1393
+ # belongs_to :company, touch: true
1394
+ # belongs_to :company, touch: :employees_last_updated_at
1395
+ def belongs_to(name, scope = nil, options = {})
1396
+ Builder::BelongsTo.build(self, name, scope, options)
1432
1397
  end
1433
1398
 
1434
1399
  # Specifies a many-to-many relationship with another class. This associates two classes via an
1435
1400
  # intermediate join table. Unless the join table is explicitly specified as an option, it is
1436
1401
  # guessed using the lexical order of the class names. So a join between Developer and Project
1437
- # will give the default join table name of "developers_projects" because "D" outranks "P".
1402
+ # will give the default join table name of "developers_projects" because "D" precedes "P" alphabetically.
1438
1403
  # Note that this precedence is calculated using the <tt><</tt> operator for String. This
1439
1404
  # means that if the strings are of different lengths, and the strings are equal when compared
1440
1405
  # up to the shortest length, then the longer string is considered of higher
@@ -1448,7 +1413,7 @@ module ActiveRecord
1448
1413
  #
1449
1414
  # class CreateDevelopersProjectsJoinTable < ActiveRecord::Migration
1450
1415
  # def change
1451
- # create_table :developers_projects, :id => false do |t|
1416
+ # create_table :developers_projects, id: false do |t|
1452
1417
  # t.integer :developer_id
1453
1418
  # t.integer :project_id
1454
1419
  # end
@@ -1472,6 +1437,9 @@ module ActiveRecord
1472
1437
  # [collection.delete(object, ...)]
1473
1438
  # Removes one or more objects from the collection by removing their associations from the join table.
1474
1439
  # This does not destroy the objects.
1440
+ # [collection.destroy(object, ...)]
1441
+ # Removes one or more objects from the collection by running destroy on each association in the join table, overriding any dependent option.
1442
+ # This does not destroy the objects.
1475
1443
  # [collection=objects]
1476
1444
  # Replaces the collection's content by deleting and adding objects as appropriate.
1477
1445
  # [collection_singular_ids]
@@ -1508,6 +1476,7 @@ module ActiveRecord
1508
1476
  # * <tt>Developer#projects</tt>
1509
1477
  # * <tt>Developer#projects<<</tt>
1510
1478
  # * <tt>Developer#projects.delete</tt>
1479
+ # * <tt>Developer#projects.destroy</tt>
1511
1480
  # * <tt>Developer#projects=</tt>
1512
1481
  # * <tt>Developer#project_ids</tt>
1513
1482
  # * <tt>Developer#project_ids=</tt>
@@ -1540,47 +1509,6 @@ module ActiveRecord
1540
1509
  # By default this is guessed to be the name of the associated class in lower-case and "_id" suffixed.
1541
1510
  # So if a Person class makes a +has_and_belongs_to_many+ association to Project,
1542
1511
  # the association will use "project_id" as the default <tt>:association_foreign_key</tt>.
1543
- # [:conditions]
1544
- # Specify the conditions that the associated object must meet in order to be included as a +WHERE+
1545
- # SQL fragment, such as <tt>authorized = 1</tt>. Record creations from the association are
1546
- # scoped if a hash is used.
1547
- # <tt>has_many :posts, :conditions => {:published => true}</tt> will create published posts with <tt>@blog.posts.create</tt>
1548
- # or <tt>@blog.posts.build</tt>.
1549
- # [:order]
1550
- # Specify the order in which the associated objects are returned as an <tt>ORDER BY</tt> SQL fragment,
1551
- # such as <tt>last_name, first_name DESC</tt>
1552
- # [:uniq]
1553
- # If true, duplicate associated objects will be ignored by accessors and query methods.
1554
- # [:finder_sql]
1555
- # Overwrite the default generated SQL statement used to fetch the association with a manual statement
1556
- # [:counter_sql]
1557
- # Specify a complete SQL statement to fetch the size of the association. If <tt>:finder_sql</tt> is
1558
- # specified but not <tt>:counter_sql</tt>, <tt>:counter_sql</tt> will be generated by
1559
- # replacing <tt>SELECT ... FROM</tt> with <tt>SELECT COUNT(*) FROM</tt>.
1560
- # [:delete_sql]
1561
- # Overwrite the default generated SQL statement used to remove links between the associated
1562
- # classes with a manual statement.
1563
- # [:insert_sql]
1564
- # Overwrite the default generated SQL statement used to add links between the associated classes
1565
- # with a manual statement.
1566
- # [:extend]
1567
- # Anonymous module for extending the proxy, see "Association extensions".
1568
- # [:include]
1569
- # Specify second-order associations that should be eager loaded when the collection is loaded.
1570
- # [:group]
1571
- # An attribute name by which the result should be grouped. Uses the <tt>GROUP BY</tt> SQL-clause.
1572
- # [:having]
1573
- # Combined with +:group+ this can be used to filter the records that a <tt>GROUP BY</tt> returns.
1574
- # Uses the <tt>HAVING</tt> SQL-clause.
1575
- # [:limit]
1576
- # An integer determining the limit on the number of rows that should be returned.
1577
- # [:offset]
1578
- # An integer determining the offset from where the rows should be fetched. So at 5,
1579
- # it would skip the first 4 rows.
1580
- # [:select]
1581
- # By default, this is <tt>*</tt> as in <tt>SELECT * FROM</tt>, but can be changed if, for example,
1582
- # you want to do a join but not include the joined columns. Do not forget to include the primary
1583
- # and foreign keys, otherwise it will raise an error.
1584
1512
  # [:readonly]
1585
1513
  # If true, all the associated objects are readonly through the association.
1586
1514
  # [:validate]
@@ -1591,16 +1519,16 @@ module ActiveRecord
1591
1519
  # If false, never save or destroy the associated objects.
1592
1520
  # By default, only save associated objects that are new records.
1593
1521
  #
1522
+ # Note that <tt>accepts_nested_attributes_for</tt> sets <tt>:autosave</tt> to <tt>true</tt>.
1523
+ #
1594
1524
  # Option examples:
1595
1525
  # has_and_belongs_to_many :projects
1596
- # has_and_belongs_to_many :projects, :include => [ :milestones, :manager ]
1597
- # has_and_belongs_to_many :nations, :class_name => "Country"
1598
- # has_and_belongs_to_many :categories, :join_table => "prods_cats"
1599
- # has_and_belongs_to_many :categories, :readonly => true
1600
- # has_and_belongs_to_many :active_projects, :join_table => 'developers_projects', :delete_sql =>
1601
- # "DELETE FROM developers_projects WHERE active=1 AND developer_id = #{id} AND project_id = #{record.id}"
1602
- def has_and_belongs_to_many(name, options = {}, &extension)
1603
- Builder::HasAndBelongsToMany.build(self, name, options, &extension)
1526
+ # has_and_belongs_to_many :projects, -> { includes :milestones, :manager }
1527
+ # has_and_belongs_to_many :nations, class_name: "Country"
1528
+ # has_and_belongs_to_many :categories, join_table: "prods_cats"
1529
+ # has_and_belongs_to_many :categories, -> { readonly }
1530
+ def has_and_belongs_to_many(name, scope = nil, options = {}, &extension)
1531
+ Builder::HasAndBelongsToMany.build(self, name, scope, options, &extension)
1604
1532
  end
1605
1533
  end
1606
1534
  end