activerecord 4.0.4 → 4.1.16

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 (143) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1632 -1797
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +2 -2
  5. data/examples/performance.rb +30 -18
  6. data/examples/simple.rb +4 -4
  7. data/lib/active_record/aggregations.rb +2 -1
  8. data/lib/active_record/association_relation.rb +4 -0
  9. data/lib/active_record/associations/alias_tracker.rb +49 -29
  10. data/lib/active_record/associations/association.rb +9 -17
  11. data/lib/active_record/associations/association_scope.rb +59 -49
  12. data/lib/active_record/associations/belongs_to_association.rb +34 -25
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +6 -1
  14. data/lib/active_record/associations/builder/association.rb +84 -54
  15. data/lib/active_record/associations/builder/belongs_to.rb +90 -58
  16. data/lib/active_record/associations/builder/collection_association.rb +47 -45
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +119 -25
  18. data/lib/active_record/associations/builder/has_many.rb +3 -3
  19. data/lib/active_record/associations/builder/has_one.rb +5 -7
  20. data/lib/active_record/associations/builder/singular_association.rb +6 -7
  21. data/lib/active_record/associations/collection_association.rb +121 -111
  22. data/lib/active_record/associations/collection_proxy.rb +73 -18
  23. data/lib/active_record/associations/has_many_association.rb +14 -11
  24. data/lib/active_record/associations/has_many_through_association.rb +33 -6
  25. data/lib/active_record/associations/has_one_association.rb +1 -1
  26. data/lib/active_record/associations/join_dependency/join_association.rb +46 -104
  27. data/lib/active_record/associations/join_dependency/join_base.rb +6 -8
  28. data/lib/active_record/associations/join_dependency/join_part.rb +18 -37
  29. data/lib/active_record/associations/join_dependency.rb +208 -168
  30. data/lib/active_record/associations/preloader/association.rb +69 -27
  31. data/lib/active_record/associations/preloader/collection_association.rb +2 -2
  32. data/lib/active_record/associations/preloader/has_many_through.rb +1 -1
  33. data/lib/active_record/associations/preloader/singular_association.rb +3 -3
  34. data/lib/active_record/associations/preloader/through_association.rb +58 -26
  35. data/lib/active_record/associations/preloader.rb +63 -49
  36. data/lib/active_record/associations/singular_association.rb +6 -5
  37. data/lib/active_record/associations/through_association.rb +30 -9
  38. data/lib/active_record/associations.rb +116 -42
  39. data/lib/active_record/attribute_assignment.rb +6 -3
  40. data/lib/active_record/attribute_methods/before_type_cast.rb +2 -1
  41. data/lib/active_record/attribute_methods/dirty.rb +35 -26
  42. data/lib/active_record/attribute_methods/primary_key.rb +8 -1
  43. data/lib/active_record/attribute_methods/read.rb +56 -29
  44. data/lib/active_record/attribute_methods/serialization.rb +44 -12
  45. data/lib/active_record/attribute_methods/time_zone_conversion.rb +13 -1
  46. data/lib/active_record/attribute_methods/write.rb +59 -26
  47. data/lib/active_record/attribute_methods.rb +82 -43
  48. data/lib/active_record/autosave_association.rb +209 -194
  49. data/lib/active_record/base.rb +6 -2
  50. data/lib/active_record/callbacks.rb +2 -2
  51. data/lib/active_record/coders/json.rb +13 -0
  52. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +5 -10
  53. data/lib/active_record/connection_adapters/abstract/database_statements.rb +14 -24
  54. data/lib/active_record/connection_adapters/abstract/query_cache.rb +13 -13
  55. data/lib/active_record/connection_adapters/abstract/quoting.rb +6 -3
  56. data/lib/active_record/connection_adapters/abstract/savepoints.rb +21 -0
  57. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +90 -0
  58. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +9 -8
  59. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +45 -70
  60. data/lib/active_record/connection_adapters/abstract/transaction.rb +1 -0
  61. data/lib/active_record/connection_adapters/abstract_adapter.rb +28 -96
  62. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +74 -66
  63. data/lib/active_record/connection_adapters/column.rb +1 -35
  64. data/lib/active_record/connection_adapters/connection_specification.rb +231 -43
  65. data/lib/active_record/connection_adapters/mysql2_adapter.rb +10 -5
  66. data/lib/active_record/connection_adapters/mysql_adapter.rb +24 -17
  67. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +22 -15
  68. data/lib/active_record/connection_adapters/postgresql/cast.rb +12 -4
  69. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +18 -44
  70. data/lib/active_record/connection_adapters/postgresql/oid.rb +38 -14
  71. data/lib/active_record/connection_adapters/postgresql/quoting.rb +37 -12
  72. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +20 -11
  73. data/lib/active_record/connection_adapters/postgresql_adapter.rb +98 -52
  74. data/lib/active_record/connection_adapters/schema_cache.rb +8 -29
  75. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +55 -60
  76. data/lib/active_record/connection_handling.rb +39 -5
  77. data/lib/active_record/core.rb +38 -54
  78. data/lib/active_record/counter_cache.rb +9 -10
  79. data/lib/active_record/dynamic_matchers.rb +6 -2
  80. data/lib/active_record/enum.rb +199 -0
  81. data/lib/active_record/errors.rb +22 -5
  82. data/lib/active_record/fixture_set/file.rb +2 -1
  83. data/lib/active_record/fixtures.rb +173 -76
  84. data/lib/active_record/gem_version.rb +15 -0
  85. data/lib/active_record/inheritance.rb +23 -9
  86. data/lib/active_record/integration.rb +54 -1
  87. data/lib/active_record/locking/optimistic.rb +7 -2
  88. data/lib/active_record/locking/pessimistic.rb +1 -1
  89. data/lib/active_record/log_subscriber.rb +6 -13
  90. data/lib/active_record/migration/command_recorder.rb +8 -2
  91. data/lib/active_record/migration.rb +91 -56
  92. data/lib/active_record/model_schema.rb +7 -14
  93. data/lib/active_record/nested_attributes.rb +25 -13
  94. data/lib/active_record/no_touching.rb +52 -0
  95. data/lib/active_record/null_relation.rb +26 -6
  96. data/lib/active_record/persistence.rb +23 -29
  97. data/lib/active_record/querying.rb +15 -12
  98. data/lib/active_record/railtie.rb +12 -61
  99. data/lib/active_record/railties/databases.rake +37 -56
  100. data/lib/active_record/readonly_attributes.rb +0 -6
  101. data/lib/active_record/reflection.rb +230 -79
  102. data/lib/active_record/relation/batches.rb +74 -24
  103. data/lib/active_record/relation/calculations.rb +52 -48
  104. data/lib/active_record/relation/delegation.rb +54 -39
  105. data/lib/active_record/relation/finder_methods.rb +210 -67
  106. data/lib/active_record/relation/merger.rb +15 -12
  107. data/lib/active_record/relation/predicate_builder/array_handler.rb +29 -0
  108. data/lib/active_record/relation/predicate_builder/relation_handler.rb +17 -0
  109. data/lib/active_record/relation/predicate_builder.rb +81 -40
  110. data/lib/active_record/relation/query_methods.rb +185 -108
  111. data/lib/active_record/relation/spawn_methods.rb +8 -5
  112. data/lib/active_record/relation.rb +79 -84
  113. data/lib/active_record/result.rb +45 -6
  114. data/lib/active_record/runtime_registry.rb +5 -0
  115. data/lib/active_record/sanitization.rb +4 -4
  116. data/lib/active_record/schema_dumper.rb +18 -6
  117. data/lib/active_record/schema_migration.rb +31 -18
  118. data/lib/active_record/scoping/default.rb +5 -18
  119. data/lib/active_record/scoping/named.rb +14 -29
  120. data/lib/active_record/scoping.rb +5 -0
  121. data/lib/active_record/store.rb +67 -18
  122. data/lib/active_record/tasks/database_tasks.rb +66 -26
  123. data/lib/active_record/tasks/mysql_database_tasks.rb +16 -10
  124. data/lib/active_record/tasks/postgresql_database_tasks.rb +1 -1
  125. data/lib/active_record/tasks/sqlite_database_tasks.rb +5 -1
  126. data/lib/active_record/timestamp.rb +6 -6
  127. data/lib/active_record/transactions.rb +10 -12
  128. data/lib/active_record/validations/presence.rb +1 -1
  129. data/lib/active_record/validations/uniqueness.rb +19 -9
  130. data/lib/active_record/version.rb +4 -7
  131. data/lib/active_record.rb +5 -7
  132. data/lib/rails/generators/active_record/migration/migration_generator.rb +4 -0
  133. data/lib/rails/generators/active_record/migration.rb +18 -0
  134. data/lib/rails/generators/active_record/model/model_generator.rb +4 -0
  135. data/lib/rails/generators/active_record.rb +2 -8
  136. metadata +18 -30
  137. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +0 -65
  138. data/lib/active_record/associations/join_helper.rb +0 -45
  139. data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +0 -60
  140. data/lib/active_record/tasks/firebird_database_tasks.rb +0 -56
  141. data/lib/active_record/tasks/oracle_database_tasks.rb +0 -45
  142. data/lib/active_record/tasks/sqlserver_database_tasks.rb +0 -48
  143. data/lib/active_record/test_case.rb +0 -96
@@ -31,6 +31,12 @@ module ActiveRecord
31
31
  db.busy_timeout(ConnectionAdapters::SQLite3Adapter.type_cast_config_to_integer(config[:timeout])) if config[:timeout]
32
32
 
33
33
  ConnectionAdapters::SQLite3Adapter.new(db, logger, config)
34
+ rescue Errno::ENOENT => error
35
+ if error.message.include?("No such file or directory")
36
+ raise ActiveRecord::NoDatabaseError.new(error.message)
37
+ else
38
+ raise error
39
+ end
34
40
  end
35
41
  end
36
42
 
@@ -53,6 +59,23 @@ module ActiveRecord
53
59
  #
54
60
  # * <tt>:database</tt> - Path to the database file.
55
61
  class SQLite3Adapter < AbstractAdapter
62
+ include Savepoints
63
+
64
+ NATIVE_DATABASE_TYPES = {
65
+ primary_key: 'INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL',
66
+ string: { name: "varchar", limit: 255 },
67
+ text: { name: "text" },
68
+ integer: { name: "integer" },
69
+ float: { name: "float" },
70
+ decimal: { name: "decimal" },
71
+ datetime: { name: "datetime" },
72
+ timestamp: { name: "datetime" },
73
+ time: { name: "time" },
74
+ date: { name: "date" },
75
+ binary: { name: "blob" },
76
+ boolean: { name: "boolean" }
77
+ }
78
+
56
79
  class Version
57
80
  include Comparable
58
81
 
@@ -124,14 +147,16 @@ module ActiveRecord
124
147
  'SQLite'
125
148
  end
126
149
 
127
- # Returns true
128
150
  def supports_ddl_transactions?
129
151
  true
130
152
  end
131
153
 
132
- # Returns true if SQLite version is '3.6.8' or greater, false otherwise.
133
154
  def supports_savepoints?
134
- sqlite_version >= '3.6.8'
155
+ true
156
+ end
157
+
158
+ def supports_partial_index?
159
+ sqlite_version >= '3.8.0'
135
160
  end
136
161
 
137
162
  # Returns true, since this connection adapter supports prepared statement
@@ -145,7 +170,6 @@ module ActiveRecord
145
170
  true
146
171
  end
147
172
 
148
- # Returns true.
149
173
  def supports_primary_key? #:nodoc:
150
174
  true
151
175
  end
@@ -154,7 +178,6 @@ module ActiveRecord
154
178
  true
155
179
  end
156
180
 
157
- # Returns true
158
181
  def supports_add_column?
159
182
  true
160
183
  end
@@ -176,16 +199,6 @@ module ActiveRecord
176
199
  @statements.clear
177
200
  end
178
201
 
179
- # Returns true
180
- def supports_count_distinct? #:nodoc:
181
- true
182
- end
183
-
184
- # Returns true
185
- def supports_autoincrement? #:nodoc:
186
- true
187
- end
188
-
189
202
  def supports_index_sort_order?
190
203
  true
191
204
  end
@@ -198,20 +211,7 @@ module ActiveRecord
198
211
  end
199
212
 
200
213
  def native_database_types #:nodoc:
201
- {
202
- :primary_key => default_primary_key_type,
203
- :string => { :name => "varchar", :limit => 255 },
204
- :text => { :name => "text" },
205
- :integer => { :name => "integer" },
206
- :float => { :name => "float" },
207
- :decimal => { :name => "decimal" },
208
- :datetime => { :name => "datetime" },
209
- :timestamp => { :name => "datetime" },
210
- :time => { :name => "time" },
211
- :date => { :name => "date" },
212
- :binary => { :name => "blob" },
213
- :boolean => { :name => "boolean" }
214
- }
214
+ NATIVE_DATABASE_TYPES
215
215
  end
216
216
 
217
217
  # Returns the current database encoding format as a string, eg: 'UTF-8'
@@ -219,7 +219,6 @@ module ActiveRecord
219
219
  @connection.encoding.to_s
220
220
  end
221
221
 
222
- # Returns true.
223
222
  def supports_explain?
224
223
  true
225
224
  end
@@ -227,8 +226,8 @@ module ActiveRecord
227
226
  # QUOTING ==================================================
228
227
 
229
228
  def quote(value, column = nil)
230
- if value.kind_of?(String) && column && column.type == :binary && column.class.respond_to?(:string_to_binary)
231
- s = column.class.string_to_binary(value).unpack("H*")[0]
229
+ if value.kind_of?(String) && column && column.type == :binary
230
+ s = value.unpack("H*")[0]
232
231
  "x'#{s}'"
233
232
  else
234
233
  super
@@ -292,14 +291,20 @@ module ActiveRecord
292
291
  end
293
292
 
294
293
  def exec_query(sql, name = nil, binds = [])
295
- log(sql, name, binds) do
294
+ type_casted_binds = binds.map { |col, val|
295
+ [col, type_cast(val, col)]
296
+ }
296
297
 
298
+ log(sql, name, type_casted_binds) do
297
299
  # Don't cache statements if they are not prepared
298
300
  if without_prepared_statement?(binds)
299
301
  stmt = @connection.prepare(sql)
300
- cols = stmt.columns
301
- records = stmt.to_a
302
- stmt.close
302
+ begin
303
+ cols = stmt.columns
304
+ records = stmt.to_a
305
+ ensure
306
+ stmt.close
307
+ end
303
308
  stmt = records
304
309
  else
305
310
  cache = @statements[sql] ||= {
@@ -308,9 +313,7 @@ module ActiveRecord
308
313
  stmt = cache[:stmt]
309
314
  cols = cache[:cols] ||= stmt.columns
310
315
  stmt.reset!
311
- stmt.bind_params binds.map { |col, val|
312
- type_cast(val, col)
313
- }
316
+ stmt.bind_params type_casted_binds.map { |_, val| val }
314
317
  end
315
318
 
316
319
  ActiveRecord::Result.new(cols, stmt.to_a)
@@ -351,18 +354,6 @@ module ActiveRecord
351
354
  exec_query(sql, name, binds).rows
352
355
  end
353
356
 
354
- def create_savepoint
355
- execute("SAVEPOINT #{current_savepoint_name}")
356
- end
357
-
358
- def rollback_to_savepoint
359
- execute("ROLLBACK TO SAVEPOINT #{current_savepoint_name}")
360
- end
361
-
362
- def release_savepoint
363
- execute("RELEASE SAVEPOINT #{current_savepoint_name}")
364
- end
365
-
366
357
  def begin_db_transaction #:nodoc:
367
358
  log('begin transaction',nil) { @connection.transaction }
368
359
  end
@@ -413,13 +404,25 @@ module ActiveRecord
413
404
  # Returns an array of indexes for the given table.
414
405
  def indexes(table_name, name = nil) #:nodoc:
415
406
  exec_query("PRAGMA index_list(#{quote_table_name(table_name)})", 'SCHEMA').map do |row|
407
+ sql = <<-SQL
408
+ SELECT sql
409
+ FROM sqlite_master
410
+ WHERE name=#{quote(row['name'])} AND type='index'
411
+ UNION ALL
412
+ SELECT sql
413
+ FROM sqlite_temp_master
414
+ WHERE name=#{quote(row['name'])} AND type='index'
415
+ SQL
416
+ index_sql = exec_query(sql).first['sql']
417
+ match = /\sWHERE\s+(.+)$/i.match(index_sql)
418
+ where = match[1] if match
416
419
  IndexDefinition.new(
417
420
  table_name,
418
421
  row['name'],
419
422
  row['unique'] != 0,
420
423
  exec_query("PRAGMA index_info('#{row['name']}')", "SCHEMA").map { |col|
421
424
  col['name']
422
- })
425
+ }, nil, nil, where)
423
426
  end
424
427
  end
425
428
 
@@ -606,14 +609,6 @@ module ActiveRecord
606
609
  @sqlite_version ||= SQLite3Adapter::Version.new(select_value('select sqlite_version(*)'))
607
610
  end
608
611
 
609
- def default_primary_key_type
610
- if supports_autoincrement?
611
- 'INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL'
612
- else
613
- 'INTEGER PRIMARY KEY NOT NULL'
614
- end
615
- end
616
-
617
612
  def translate_exception(exception, message)
618
613
  case exception.message
619
614
  # SQLite 3.8.2 returns a newly formatted error message:
@@ -1,5 +1,8 @@
1
1
  module ActiveRecord
2
2
  module ConnectionHandling
3
+ RAILS_ENV = -> { (Rails.env if defined?(Rails)) || ENV["RAILS_ENV"] || ENV["RACK_ENV"] }
4
+ DEFAULT_ENV = -> { RAILS_ENV.call || "default_env" }
5
+
3
6
  # Establishes the connection to the database. Accepts a hash as input where
4
7
  # the <tt>:adapter</tt> key must be specified with the name of a database adapter (in lower-case)
5
8
  # example for regular databases (MySQL, Postgresql, etc):
@@ -15,14 +18,14 @@ module ActiveRecord
15
18
  # Example for SQLite database:
16
19
  #
17
20
  # ActiveRecord::Base.establish_connection(
18
- # adapter: "sqlite",
21
+ # adapter: "sqlite3",
19
22
  # database: "path/to/dbfile"
20
23
  # )
21
24
  #
22
25
  # Also accepts keys as strings (for parsing from YAML for example):
23
26
  #
24
27
  # ActiveRecord::Base.establish_connection(
25
- # "adapter" => "sqlite",
28
+ # "adapter" => "sqlite3",
26
29
  # "database" => "path/to/dbfile"
27
30
  # )
28
31
  #
@@ -32,11 +35,19 @@ module ActiveRecord
32
35
  # "postgres://myuser:mypass@localhost/somedatabase"
33
36
  # )
34
37
  #
38
+ # In case <tt>ActiveRecord::Base.configurations</tt> is set (Rails
39
+ # automatically loads the contents of config/database.yml into it),
40
+ # a symbol can also be given as argument, representing a key in the
41
+ # configuration hash:
42
+ #
43
+ # ActiveRecord::Base.establish_connection(:production)
44
+ #
35
45
  # The exceptions AdapterNotSpecified, AdapterNotFound and ArgumentError
36
46
  # may be returned on an error.
37
- def establish_connection(spec = ENV["DATABASE_URL"])
38
- resolver = ConnectionAdapters::ConnectionSpecification::Resolver.new spec, configurations
39
- spec = resolver.spec
47
+ def establish_connection(spec = nil)
48
+ spec ||= DEFAULT_ENV.call.to_sym
49
+ resolver = ConnectionAdapters::ConnectionSpecification::Resolver.new configurations
50
+ spec = resolver.spec(spec)
40
51
 
41
52
  unless respond_to?(spec.adapter_method)
42
53
  raise AdapterNotFound, "database configuration specifies nonexistent #{spec.config[:adapter]} adapter"
@@ -46,6 +57,29 @@ module ActiveRecord
46
57
  connection_handler.establish_connection self, spec
47
58
  end
48
59
 
60
+ class MergeAndResolveDefaultUrlConfig # :nodoc:
61
+ def initialize(raw_configurations)
62
+ @raw_config = raw_configurations.dup
63
+ @env = DEFAULT_ENV.call.to_s
64
+ end
65
+
66
+ # Returns fully resolved connection hashes.
67
+ # Merges connection information from `ENV['DATABASE_URL']` if available.
68
+ def resolve
69
+ ConnectionAdapters::ConnectionSpecification::Resolver.new(config).resolve_all
70
+ end
71
+
72
+ private
73
+ def config
74
+ @raw_config.dup.tap do |cfg|
75
+ if url = ENV['DATABASE_URL']
76
+ cfg[@env] ||= {}
77
+ cfg[@env]["url"] ||= url
78
+ end
79
+ end
80
+ end
81
+ end
82
+
49
83
  # Returns the connection currently associated with the class. This can
50
84
  # also be used to "borrow" the connection to do database work unrelated
51
85
  # to any of the specific Active Records.
@@ -42,9 +42,16 @@ module ActiveRecord
42
42
  # 'database' => 'db/production.sqlite3'
43
43
  # }
44
44
  # }
45
- mattr_accessor :configurations, instance_writer: false
45
+ def self.configurations=(config)
46
+ @@configurations = ActiveRecord::ConnectionHandling::MergeAndResolveDefaultUrlConfig.new(config).resolve
47
+ end
46
48
  self.configurations = {}
47
49
 
50
+ # Returns fully resolved configurations hash
51
+ def self.configurations
52
+ @@configurations
53
+ end
54
+
48
55
  ##
49
56
  # :singleton-method:
50
57
  # Determines whether to use Time.utc (using :utc) or Time.local (using :local) when pulling
@@ -71,11 +78,19 @@ module ActiveRecord
71
78
 
72
79
  ##
73
80
  # :singleton-method:
74
- # Disable implicit join references. This feature was deprecated with Rails 4.
75
- # If you don't make use of implicit references but still see deprecation warnings
76
- # you can disable the feature entirely. This will be the default with Rails 4.1.
77
- mattr_accessor :disable_implicit_join_references, instance_writer: false
78
- self.disable_implicit_join_references = false
81
+ # Specify whether schema dump should happen at the end of the
82
+ # db:migrate rake task. This is true by default, which is useful for the
83
+ # development environment. This should ideally be false in the production
84
+ # environment where dumping schema is rarely needed.
85
+ mattr_accessor :dump_schema_after_migration, instance_writer: false
86
+ self.dump_schema_after_migration = true
87
+
88
+ mattr_accessor :maintain_test_schema, instance_accessor: false
89
+
90
+ def self.disable_implicit_join_references=(value)
91
+ ActiveSupport::Deprecation.warn("Implicit join references were removed with Rails 4.1." \
92
+ "Make sure to remove this configuration because it does nothing.")
93
+ end
79
94
 
80
95
  class_attribute :default_connection_handler, instance_writer: false
81
96
 
@@ -92,14 +107,12 @@ module ActiveRecord
92
107
 
93
108
  module ClassMethods
94
109
  def initialize_generated_modules
95
- super
96
-
97
- generated_feature_methods
110
+ generated_association_methods
98
111
  end
99
112
 
100
- def generated_feature_methods
101
- @generated_feature_methods ||= begin
102
- mod = const_set(:GeneratedFeatureMethods, Module.new)
113
+ def generated_association_methods
114
+ @generated_association_methods ||= begin
115
+ mod = const_set(:GeneratedAssociationMethods, Module.new)
103
116
  include mod
104
117
  mod
105
118
  end
@@ -131,25 +144,24 @@ module ActiveRecord
131
144
  # class Post < ActiveRecord::Base
132
145
  # scope :published_and_commented, -> { published.and(self.arel_table[:comments_count].gt(0)) }
133
146
  # end
134
- def arel_table
147
+ def arel_table # :nodoc:
135
148
  @arel_table ||= Arel::Table.new(table_name, arel_engine)
136
149
  end
137
150
 
138
151
  # Returns the Arel engine.
139
- def arel_engine
140
- @arel_engine ||= begin
152
+ def arel_engine # :nodoc:
153
+ @arel_engine ||=
141
154
  if Base == self || connection_handler.retrieve_connection_pool(self)
142
155
  self
143
156
  else
144
157
  superclass.arel_engine
145
158
  end
146
- end
147
159
  end
148
160
 
149
161
  private
150
162
 
151
163
  def relation #:nodoc:
152
- relation = Relation.new(self, arel_table)
164
+ relation = Relation.create(self, arel_table)
153
165
 
154
166
  if finder_needs_type_condition?
155
167
  relation.where(type_condition).create_with(inheritance_column.to_sym => sti_name)
@@ -176,9 +188,7 @@ module ActiveRecord
176
188
  @column_types = self.class.column_types
177
189
 
178
190
  init_internals
179
- init_changed_attributes
180
- ensure_proper_type
181
- populate_with_current_scope_attributes
191
+ initialize_internals_callback
182
192
 
183
193
  # +options+ argument is only needed to make protected_attributes gem easier to hook.
184
194
  # Remove it when we drop support to this gem.
@@ -207,6 +217,8 @@ module ActiveRecord
207
217
 
208
218
  @new_record = false
209
219
 
220
+ self.class.define_attribute_methods
221
+
210
222
  run_callbacks :find
211
223
  run_callbacks :initialize
212
224
 
@@ -249,16 +261,13 @@ module ActiveRecord
249
261
 
250
262
  run_callbacks(:initialize) unless _initialize_callbacks.empty?
251
263
 
252
- @changed_attributes = {}
253
- init_changed_attributes
254
-
255
264
  @aggregation_cache = {}
256
265
  @association_cache = {}
257
266
  @attributes_cache = {}
258
267
 
259
268
  @new_record = true
269
+ @destroyed = false
260
270
 
261
- ensure_proper_type
262
271
  super
263
272
  end
264
273
 
@@ -290,7 +299,7 @@ module ActiveRecord
290
299
  def ==(comparison_object)
291
300
  super ||
292
301
  comparison_object.instance_of?(self.class) &&
293
- id.present? &&
302
+ !id.nil? &&
294
303
  comparison_object.id == id
295
304
  end
296
305
  alias :eql? :==
@@ -318,6 +327,8 @@ module ActiveRecord
318
327
  def <=>(other_object)
319
328
  if other_object.is_a?(self.class)
320
329
  self.to_key <=> other_object.to_key
330
+ else
331
+ super
321
332
  end
322
333
  end
323
334
 
@@ -332,14 +343,6 @@ module ActiveRecord
332
343
  @readonly = true
333
344
  end
334
345
 
335
- # Returns the connection currently associated with the class. This can
336
- # also be used to "borrow" the connection to do database work that isn't
337
- # easily done without going straight to SQL.
338
- def connection
339
- ActiveSupport::Deprecation.warn("#connection is deprecated in favour of accessing it via the class")
340
- self.class.connection
341
- end
342
-
343
346
  def connection_handler
344
347
  self.class.connection_handler
345
348
  end
@@ -362,7 +365,7 @@ module ActiveRecord
362
365
 
363
366
  # Returns a hash of the given methods with their names as keys and returned values as values.
364
367
  def slice(*methods)
365
- Hash[methods.map { |method| [method, public_send(method)] }].with_indifferent_access
368
+ Hash[methods.map! { |method| [method, public_send(method)] }].with_indifferent_access
366
369
  end
367
370
 
368
371
  def set_transaction_state(state) # :nodoc:
@@ -373,17 +376,6 @@ module ActiveRecord
373
376
  !_rollback_callbacks.empty? || !_commit_callbacks.empty? || !_create_callbacks.empty?
374
377
  end
375
378
 
376
- # Required to deserialize Syck properly.
377
- if YAML.const_defined?(:ENGINE) && YAML::ENGINE.syck?
378
- ActiveSupport::Deprecation.warn(
379
- "Syck is deprecated and support for serialization has been removed." \
380
- " ActiveRecord::Core#yaml_initialize will be removed in 4.1 which will break deserialization support with Syck."
381
- )
382
- def yaml_initialize(tag, coder) # :nodoc:
383
- init_with(coder)
384
- end
385
- end
386
-
387
379
  private
388
380
 
389
381
  # Updates the attributes on this particular ActiveRecord object so that
@@ -440,8 +432,6 @@ module ActiveRecord
440
432
  @aggregation_cache = {}
441
433
  @association_cache = {}
442
434
  @attributes_cache = {}
443
- @previously_changed = {}
444
- @changed_attributes = {}
445
435
  @readonly = false
446
436
  @destroyed = false
447
437
  @marked_for_destruction = false
@@ -453,13 +443,7 @@ module ActiveRecord
453
443
  @reflects_state = [false]
454
444
  end
455
445
 
456
- def init_changed_attributes
457
- # Intentionally avoid using #column_defaults since overridden defaults (as is done in
458
- # optimistic locking) won't get written unless they get marked as changed
459
- self.class.columns.each do |c|
460
- attr, orig_value = c.name, c.default
461
- @changed_attributes[attr] = orig_value if _field_changed?(attr, orig_value, @attributes[attr])
462
- end
446
+ def initialize_internals_callback
463
447
  end
464
448
 
465
449
  # This method is needed to make protected_attributes gem easier to hook.
@@ -20,7 +20,7 @@ module ActiveRecord
20
20
  def reset_counters(id, *counters)
21
21
  object = find(id)
22
22
  counters.each do |association|
23
- has_many_association = reflect_on_association(association.to_sym)
23
+ has_many_association = _reflect_on_association(association.to_sym)
24
24
  raise ArgumentError, "'#{self.name}' has no association called '#{association}'" unless has_many_association
25
25
 
26
26
  if has_many_association.is_a? ActiveRecord::Reflection::ThroughReflection
@@ -29,13 +29,12 @@ module ActiveRecord
29
29
 
30
30
  foreign_key = has_many_association.foreign_key.to_s
31
31
  child_class = has_many_association.klass
32
- belongs_to = child_class.reflect_on_all_associations(:belongs_to)
33
- reflection = belongs_to.find { |e| e.foreign_key.to_s == foreign_key && e.options[:counter_cache].present? }
32
+ reflection = child_class._reflections.values.find { |e| :belongs_to == e.macro && e.foreign_key.to_s == foreign_key && e.options[:counter_cache].present? }
34
33
  counter_name = reflection.counter_cache_column
35
34
 
36
35
  stmt = unscoped.where(arel_table[primary_key].eq(object.id)).arel.compile_update({
37
- arel_table[counter_name] => object.send(association).count
38
- })
36
+ arel_table[counter_name] => object.send(association).count(:all)
37
+ }, primary_key)
39
38
  connection.update stmt
40
39
  end
41
40
  return true
@@ -50,7 +49,7 @@ module ActiveRecord
50
49
  # ==== Parameters
51
50
  #
52
51
  # * +id+ - The id of the object you wish to update a counter on or an Array of ids.
53
- # * +counters+ - An Array of Hashes containing the names of the fields
52
+ # * +counters+ - A Hash containing the names of the fields
54
53
  # to update as keys and the amount to update the field by as values.
55
54
  #
56
55
  # ==== Examples
@@ -82,10 +81,10 @@ module ActiveRecord
82
81
 
83
82
  # Increment a numeric field by one, via a direct SQL update.
84
83
  #
85
- # This method is used primarily for maintaining counter_cache columns used to
86
- # store aggregate values. For example, a DiscussionBoard may cache posts_count
87
- # and comments_count to avoid running an SQL query to calculate the number of
88
- # posts and comments there are each time it is displayed.
84
+ # This method is used primarily for maintaining counter_cache columns that are
85
+ # used to store aggregate values. For example, a DiscussionBoard may cache
86
+ # posts_count and comments_count to avoid running an SQL query to calculate the
87
+ # number of posts and comments there are, each time it is displayed.
89
88
  #
90
89
  # ==== Parameters
91
90
  #
@@ -6,8 +6,12 @@ module ActiveRecord
6
6
  # then we can remove the indirection.
7
7
 
8
8
  def respond_to?(name, include_private = false)
9
- match = Method.match(self, name)
10
- match && match.valid? || super
9
+ if self == Base
10
+ super
11
+ else
12
+ match = Method.match(self, name)
13
+ match && match.valid? || super
14
+ end
11
15
  end
12
16
 
13
17
  private