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
@@ -37,7 +37,7 @@ module ActiveRecord
37
37
  end
38
38
 
39
39
  # Given an attributes hash, +instantiate+ returns a new instance of
40
- # the appropriate class.
40
+ # the appropriate class. Accepts only keys as strings.
41
41
  #
42
42
  # For example, +Post.all+ may return Comments, Messages, and Emails
43
43
  # by storing the record's subclass in a +type+ attribute. By calling
@@ -46,10 +46,10 @@ module ActiveRecord
46
46
  #
47
47
  # See +ActiveRecord::Inheritance#discriminate_class_for_record+ to see
48
48
  # how this "single-table" inheritance mapping is implemented.
49
- def instantiate(record, column_types = {})
50
- klass = discriminate_class_for_record(record)
49
+ def instantiate(attributes, column_types = {})
50
+ klass = discriminate_class_for_record(attributes)
51
51
  column_types = klass.decorate_columns(column_types.dup)
52
- klass.allocate.init_with('attributes' => record, 'column_types' => column_types)
52
+ klass.allocate.init_with('attributes' => attributes, 'column_types' => column_types)
53
53
  end
54
54
 
55
55
  private
@@ -181,6 +181,8 @@ module ActiveRecord
181
181
  became = klass.new
182
182
  became.instance_variable_set("@attributes", @attributes)
183
183
  became.instance_variable_set("@attributes_cache", @attributes_cache)
184
+ changed_attributes = @changed_attributes if defined?(@changed_attributes)
185
+ became.instance_variable_set("@changed_attributes", changed_attributes || {})
184
186
  became.instance_variable_set("@new_record", new_record?)
185
187
  became.instance_variable_set("@destroyed", destroyed?)
186
188
  became.instance_variable_set("@errors", errors)
@@ -268,7 +270,7 @@ module ActiveRecord
268
270
  # This method raises an +ActiveRecord::ActiveRecordError+ when called on new
269
271
  # objects, or when at least one of the attributes is marked as readonly.
270
272
  def update_columns(attributes)
271
- raise ActiveRecordError, "can not update on a new record object" unless persisted?
273
+ raise ActiveRecordError, "cannot update on a new record object" unless persisted?
272
274
 
273
275
  attributes.each_key do |key|
274
276
  verify_readonly_attribute(key.to_s)
@@ -346,7 +348,8 @@ module ActiveRecord
346
348
  # # Account Load (1.2ms) SELECT "accounts".* FROM "accounts" WHERE "accounts"."id" = $1 LIMIT 1 [["id", 1]]
347
349
  # # => #<Account id: 1, email: 'account@example.com'>
348
350
  #
349
- # Attributes are updated, and caches busted, in particular the associations cache.
351
+ # Attributes are reloaded from the database, and caches busted, in
352
+ # particular the associations cache.
350
353
  #
351
354
  # If the record no longer exists in the database <tt>ActiveRecord::RecordNotFound</tt>
352
355
  # is raised. Otherwise, in addition to the in-place modification the method
@@ -364,7 +367,7 @@ module ActiveRecord
364
367
  # assert_equal 25, account.credit # check it is updated in memory
365
368
  # assert_equal 25, account.reload.credit # check it is also persisted
366
369
  #
367
- # Another commom use case is optimistic locking handling:
370
+ # Another common use case is optimistic locking handling:
368
371
  #
369
372
  # def with_optimistic_retry
370
373
  # begin
@@ -397,12 +400,13 @@ module ActiveRecord
397
400
  @column_types = self.class.column_types
398
401
  @column_types_override = fresh_object.instance_variable_get('@column_types_override')
399
402
  @attributes_cache = {}
403
+ @new_record = false
400
404
  self
401
405
  end
402
406
 
403
407
  # Saves the record with the updated_at/on attributes set to the current time.
404
- # Please note that no validation is performed and only the +after_touch+
405
- # callback is executed.
408
+ # Please note that no validation is performed and only the +after_touch+,
409
+ # +after_commit+ and +after_rollback+ callbacks are executed.
406
410
  # If an attribute name is passed, that attribute is updated along with
407
411
  # updated_at/on attributes.
408
412
  #
@@ -429,7 +433,7 @@ module ActiveRecord
429
433
  # ball.touch(:updated_at) # => raises ActiveRecordError
430
434
  #
431
435
  def touch(name = nil)
432
- raise ActiveRecordError, "can not touch on a new record object" unless persisted?
436
+ raise ActiveRecordError, "cannot touch on a new record object" unless persisted?
433
437
 
434
438
  attributes = timestamp_attributes_for_update_in_model
435
439
  attributes << name if name
@@ -445,9 +449,11 @@ module ActiveRecord
445
449
 
446
450
  changes[self.class.locking_column] = increment_lock if locking_enabled?
447
451
 
448
- @changed_attributes.except!(*changes.keys)
452
+ changed_attributes.except!(*changes.keys)
449
453
  primary_key = self.class.primary_key
450
454
  self.class.unscoped.where(primary_key => self[primary_key]).update_all(changes) == 1
455
+ else
456
+ true
451
457
  end
452
458
  end
453
459
 
@@ -475,36 +481,24 @@ module ActiveRecord
475
481
 
476
482
  def create_or_update
477
483
  raise ReadOnlyRecord if readonly?
478
- result = new_record? ? create_record : update_record
484
+ result = new_record? ? _create_record : _update_record
479
485
  result != false
480
486
  end
481
487
 
482
488
  # Updates the associated record with values matching those of the instance attributes.
483
489
  # Returns the number of affected rows.
484
- def update_record(attribute_names = @attributes.keys)
485
- attributes_with_values = arel_attributes_with_values_for_update(attribute_names)
486
- if attributes_with_values.empty?
490
+ def _update_record(attribute_names = @attributes.keys)
491
+ attributes_values = arel_attributes_with_values_for_update(attribute_names)
492
+ if attributes_values.empty?
487
493
  0
488
494
  else
489
- klass = self.class
490
- column_hash = klass.connection.schema_cache.columns_hash klass.table_name
491
- db_columns_with_values = attributes_with_values.map { |attr,value|
492
- real_column = column_hash[attr.name]
493
- [real_column, value]
494
- }
495
- bind_attrs = attributes_with_values.dup
496
- bind_attrs.keys.each_with_index do |column, i|
497
- real_column = db_columns_with_values[i].first
498
- bind_attrs[column] = klass.connection.substitute_at(real_column, i)
499
- end
500
- stmt = klass.unscoped.where(klass.arel_table[klass.primary_key].eq(id_was || id)).arel.compile_update(bind_attrs)
501
- klass.connection.update stmt, 'SQL', db_columns_with_values
495
+ self.class.unscoped._update_record attributes_values, id, id_was
502
496
  end
503
497
  end
504
498
 
505
499
  # Creates a record with values matching those of the instance attributes
506
500
  # and returns its id.
507
- def create_record(attribute_names = @attributes.keys)
501
+ def _create_record(attribute_names = @attributes.keys)
508
502
  attributes_values = arel_attributes_with_values_for_create(attribute_names)
509
503
 
510
504
  new_id = self.class.unscoped.insert attributes_values
@@ -1,20 +1,22 @@
1
1
  module ActiveRecord
2
2
  module Querying
3
- delegate :find, :take, :take!, :first, :first!, :last, :last!, :exists?, :any?, :many?, :to => :all
4
- delegate :first_or_create, :first_or_create!, :first_or_initialize, :to => :all
5
- delegate :find_or_create_by, :find_or_create_by!, :find_or_initialize_by, :to => :all
6
- delegate :find_by, :find_by!, :to => :all
7
- delegate :destroy, :destroy_all, :delete, :delete_all, :update, :update_all, :to => :all
8
- delegate :find_each, :find_in_batches, :to => :all
3
+ delegate :find, :take, :take!, :first, :first!, :last, :last!, :exists?, :any?, :many?, to: :all
4
+ delegate :second, :second!, :third, :third!, :fourth, :fourth!, :fifth, :fifth!, :forty_two, :forty_two!, to: :all
5
+ delegate :first_or_create, :first_or_create!, :first_or_initialize, to: :all
6
+ delegate :find_or_create_by, :find_or_create_by!, :find_or_initialize_by, to: :all
7
+ delegate :find_by, :find_by!, to: :all
8
+ delegate :destroy, :destroy_all, :delete, :delete_all, :update, :update_all, to: :all
9
+ delegate :find_each, :find_in_batches, to: :all
9
10
  delegate :select, :group, :order, :except, :reorder, :limit, :offset, :joins,
10
- :where, :preload, :eager_load, :includes, :from, :lock, :readonly,
11
- :having, :create_with, :uniq, :distinct, :references, :none, :unscope, :to => :all
12
- delegate :count, :average, :minimum, :maximum, :sum, :calculate, :pluck, :ids, :to => :all
11
+ :where, :rewhere, :preload, :eager_load, :includes, :from, :lock, :readonly,
12
+ :having, :create_with, :uniq, :distinct, :references, :none, :unscope, to: :all
13
+ delegate :count, :average, :minimum, :maximum, :sum, :calculate, to: :all
14
+ delegate :pluck, :ids, to: :all
13
15
 
14
16
  # Executes a custom SQL query against your database and returns all the results. The results will
15
17
  # be returned as an array with columns requested encapsulated as attributes of the model you call
16
18
  # this method from. If you call <tt>Product.find_by_sql</tt> then the results will be returned in
17
- # a Product object with the attributes you specified in the SQL query.
19
+ # a +Product+ object with the attributes you specified in the SQL query.
18
20
  #
19
21
  # If you call a complicated SQL query which spans multiple tables the columns specified by the
20
22
  # SELECT will be attributes of the model, whether or not they are columns of the corresponding
@@ -29,9 +31,10 @@ module ActiveRecord
29
31
  # Post.find_by_sql "SELECT p.title, c.author FROM posts p, comments c WHERE p.id = c.post_id"
30
32
  # # => [#<Post:0x36bff9c @attributes={"title"=>"Ruby Meetup", "first_name"=>"Quentin"}>, ...]
31
33
  #
32
- # # You can use the same string replacement techniques as you can with ActiveRecord#find
34
+ # You can use the same string replacement techniques as you can with <tt>ActiveRecord::QueryMethods#where</tt>:
35
+ #
33
36
  # Post.find_by_sql ["SELECT title FROM posts WHERE author = ? AND created > ?", author_id, start_date]
34
- # # => [#<Post:0x36bff9c @attributes={"title"=>"The Cheap Man Buys Twice"}>, ...]
37
+ # Post.find_by_sql ["SELECT body FROM comments WHERE author = :user_id OR approved_by = :user_id", { :user_id => user_id }]
35
38
  def find_by_sql(sql, binds = [])
36
39
  result_set = connection.select_all(sanitize_sql(sql), "#{name} Load", binds)
37
40
  column_types = {}
@@ -31,22 +31,14 @@ module ActiveRecord
31
31
 
32
32
 
33
33
  config.active_record.use_schema_cache_dump = true
34
+ config.active_record.maintain_test_schema = true
34
35
 
35
36
  config.eager_load_namespaces << ActiveRecord
36
37
 
37
38
  rake_tasks do
38
- require "active_record/base"
39
-
40
- ActiveRecord::Tasks::DatabaseTasks.seed_loader = Rails.application
41
- ActiveRecord::Tasks::DatabaseTasks.env = Rails.env
42
-
43
39
  namespace :db do
44
40
  task :load_config do
45
- ActiveRecord::Tasks::DatabaseTasks.db_dir = Rails.application.config.paths["db"].first
46
41
  ActiveRecord::Tasks::DatabaseTasks.database_configuration = Rails.application.config.database_configuration
47
- ActiveRecord::Tasks::DatabaseTasks.migrations_paths = Rails.application.paths['db/migrate'].to_a
48
- ActiveRecord::Tasks::DatabaseTasks.fixtures_path = File.join Rails.root, 'test', 'fixtures'
49
- ActiveRecord::Tasks::DatabaseTasks.root = Rails.root
50
42
 
51
43
  if defined?(ENGINE_PATH) && engine = Rails::Engine.find(ENGINE_PATH)
52
44
  if engine.paths['db/migrate'].existent
@@ -112,56 +104,6 @@ module ActiveRecord
112
104
 
113
105
  initializer "active_record.set_configs" do |app|
114
106
  ActiveSupport.on_load(:active_record) do
115
- begin
116
- old_behavior, ActiveSupport::Deprecation.behavior = ActiveSupport::Deprecation.behavior, :stderr
117
- whitelist_attributes = app.config.active_record.delete(:whitelist_attributes)
118
-
119
- if respond_to?(:mass_assignment_sanitizer=)
120
- mass_assignment_sanitizer = nil
121
- else
122
- mass_assignment_sanitizer = app.config.active_record.delete(:mass_assignment_sanitizer)
123
- end
124
-
125
- unless whitelist_attributes.nil? && mass_assignment_sanitizer.nil?
126
- ActiveSupport::Deprecation.warn <<-EOF.strip_heredoc, []
127
- Model based mass assignment security has been extracted
128
- out of Rails into a gem. Please use the new recommended protection model for
129
- params or add `protected_attributes` to your Gemfile to use the old one.
130
-
131
- To disable this message remove the `whitelist_attributes` option from your
132
- `config/application.rb` file and any `mass_assignment_sanitizer` options
133
- from your `config/environments/*.rb` files.
134
-
135
- See http://guides.rubyonrails.org/security.html#mass-assignment for more information.
136
- EOF
137
- end
138
-
139
- unless app.config.active_record.delete(:auto_explain_threshold_in_seconds).nil?
140
- ActiveSupport::Deprecation.warn <<-EOF.strip_heredoc, []
141
- The Active Record auto explain feature has been removed.
142
-
143
- To disable this message remove the `active_record.auto_explain_threshold_in_seconds`
144
- option from the `config/environments/*.rb` config file.
145
-
146
- See http://guides.rubyonrails.org/4_0_release_notes.html for more information.
147
- EOF
148
- end
149
-
150
- unless app.config.active_record.delete(:observers).nil?
151
- ActiveSupport::Deprecation.warn <<-EOF.strip_heredoc, []
152
- Active Record Observers has been extracted out of Rails into a gem.
153
- Please use callbacks or add `rails-observers` to your Gemfile to use observers.
154
-
155
- To disable this message remove the `observers` option from your
156
- `config/application.rb` or from your initializers.
157
-
158
- See http://guides.rubyonrails.org/4_0_release_notes.html for more information.
159
- EOF
160
- end
161
- ensure
162
- ActiveSupport::Deprecation.behavior = old_behavior
163
- end
164
-
165
107
  app.config.active_record.each do |k,v|
166
108
  send "#{k}=", v
167
109
  end
@@ -172,7 +114,16 @@ module ActiveRecord
172
114
  # and then establishes the connection.
173
115
  initializer "active_record.initialize_database" do |app|
174
116
  ActiveSupport.on_load(:active_record) do
175
- self.configurations = app.config.database_configuration || {}
117
+
118
+ class ActiveRecord::NoDatabaseError
119
+ remove_possible_method :extend_message
120
+ def extend_message(message)
121
+ message << "Run `$ bin/rake db:create db:migrate` to create your database"
122
+ message
123
+ end
124
+ end
125
+
126
+ self.configurations = Rails.application.config.database_configuration
176
127
  establish_connection
177
128
  end
178
129
  end
@@ -191,8 +142,8 @@ module ActiveRecord
191
142
  ActiveSupport.on_load(:active_record) do
192
143
  ActionDispatch::Reloader.send(hook) do
193
144
  if ActiveRecord::Base.connected?
194
- ActiveRecord::Base.clear_reloadable_connections!
195
145
  ActiveRecord::Base.clear_cache!
146
+ ActiveRecord::Base.clear_reloadable_connections!
196
147
  end
197
148
  end
198
149
  end
@@ -2,7 +2,7 @@ require 'active_record'
2
2
 
3
3
  db_namespace = namespace :db do
4
4
  task :load_config do
5
- ActiveRecord::Base.configurations = ActiveRecord::Tasks::DatabaseTasks.database_configuration || {}
5
+ ActiveRecord::Base.configurations = ActiveRecord::Tasks::DatabaseTasks.database_configuration || {}
6
6
  ActiveRecord::Migrator.migrations_paths = ActiveRecord::Tasks::DatabaseTasks.migrations_paths
7
7
  end
8
8
 
@@ -12,13 +12,9 @@ db_namespace = namespace :db do
12
12
  end
13
13
  end
14
14
 
15
- desc 'Create the database from DATABASE_URL or config/database.yml for the current Rails.env (use db:create:all to create all dbs in the config)'
15
+ desc 'Creates the database from DATABASE_URL or config/database.yml for the current RAILS_ENV (use db:create:all to create all databases in the config). Without RAILS_ENV it defaults to creating the development and test databases.'
16
16
  task :create => [:load_config] do
17
- if ENV['DATABASE_URL']
18
- ActiveRecord::Tasks::DatabaseTasks.create_database_url
19
- else
20
- ActiveRecord::Tasks::DatabaseTasks.create_current
21
- end
17
+ ActiveRecord::Tasks::DatabaseTasks.create_current
22
18
  end
23
19
 
24
20
  namespace :drop do
@@ -27,13 +23,9 @@ db_namespace = namespace :db do
27
23
  end
28
24
  end
29
25
 
30
- desc 'Drops the database using DATABASE_URL or the current Rails.env (use db:drop:all to drop all databases)'
26
+ desc 'Drops the database from DATABASE_URL or config/database.yml for the current RAILS_ENV (use db:drop:all to drop all databases in the config). Without RAILS_ENV it defaults to dropping the development and test databases.'
31
27
  task :drop => [:load_config] do
32
- if ENV['DATABASE_URL']
33
- ActiveRecord::Tasks::DatabaseTasks.drop_database_url
34
- else
35
- ActiveRecord::Tasks::DatabaseTasks.drop_current
36
- end
28
+ ActiveRecord::Tasks::DatabaseTasks.drop_current
37
29
  end
38
30
 
39
31
  desc "Migrate the database (options: VERSION=x, VERBOSE=false, SCOPE=blog)."
@@ -42,7 +34,7 @@ db_namespace = namespace :db do
42
34
  ActiveRecord::Migrator.migrate(ActiveRecord::Migrator.migrations_paths, ENV["VERSION"] ? ENV["VERSION"].to_i : nil) do |migration|
43
35
  ENV["SCOPE"].blank? || (ENV["SCOPE"] == migration.scope)
44
36
  end
45
- db_namespace['_dump'].invoke
37
+ db_namespace['_dump'].invoke if ActiveRecord::Base.dump_schema_after_migration
46
38
  end
47
39
 
48
40
  task :_dump do
@@ -83,7 +75,7 @@ db_namespace = namespace :db do
83
75
  # desc 'Runs the "down" for a given migration VERSION.'
84
76
  task :down => [:environment, :load_config] do
85
77
  version = ENV['VERSION'] ? ENV['VERSION'].to_i : nil
86
- raise 'VERSION is required' unless version
78
+ raise 'VERSION is required - To go down one migration, run db:rollback' unless version
87
79
  ActiveRecord::Migrator.run(:down, ActiveRecord::Migrator.migrations_paths, version)
88
80
  db_namespace['_dump'].invoke
89
81
  end
@@ -95,14 +87,15 @@ db_namespace = namespace :db do
95
87
  next # means "return" for rake task
96
88
  end
97
89
  db_list = ActiveRecord::Base.connection.select_values("SELECT version FROM #{ActiveRecord::Migrator.schema_migrations_table_name}")
98
- db_list.map! { |version| "%.3d" % version }
90
+ db_list.map! { |version| ActiveRecord::SchemaMigration.normalize_migration_number(version) }
99
91
  file_list = []
100
92
  ActiveRecord::Migrator.migrations_paths.each do |path|
101
93
  Dir.foreach(path) do |file|
102
94
  # match "20091231235959_some_name.rb" and "001_some_name.rb" pattern
103
95
  if match_data = /^(\d{3,})_(.+)\.rb$/.match(file)
104
- status = db_list.delete(match_data[1]) ? 'up' : 'down'
105
- file_list << [status, match_data[1], match_data[2].humanize]
96
+ version = ActiveRecord::SchemaMigration.normalize_migration_number(match_data[1])
97
+ status = db_list.delete(version) ? 'up' : 'down'
98
+ file_list << [status, version, match_data[2].humanize]
106
99
  end
107
100
  end
108
101
  end
@@ -172,7 +165,7 @@ db_namespace = namespace :db do
172
165
  end
173
166
  end
174
167
 
175
- desc 'Create the database, load the schema, and initialize with the seed data (use db:reset to also drop the db first)'
168
+ desc 'Create the database, load the schema, and initialize with the seed data (use db:reset to also drop the database first)'
176
169
  task :setup => ['db:schema:load_if_ruby', 'db:structure:load_if_sql', :seed]
177
170
 
178
171
  desc 'Load the seed data from db/seeds.rb'
@@ -187,9 +180,6 @@ db_namespace = namespace :db do
187
180
  require 'active_record/fixtures'
188
181
 
189
182
  base_dir = if ENV['FIXTURES_PATH']
190
- STDERR.puts "Using FIXTURES_PATH env variable is deprecated, please use " +
191
- "ActiveRecord::Tasks::DatabaseTasks.fixtures_path = '/path/to/fixtures' " +
192
- "instead."
193
183
  File.join [Rails.root, ENV['FIXTURES_PATH'] || %w{test fixtures}].flatten
194
184
  else
195
185
  ActiveRecord::Tasks::DatabaseTasks.fixtures_path
@@ -197,7 +187,7 @@ db_namespace = namespace :db do
197
187
 
198
188
  fixtures_dir = File.join [base_dir, ENV['FIXTURES_DIR']].compact
199
189
 
200
- (ENV['FIXTURES'] ? ENV['FIXTURES'].split(/,/) : Dir["#{fixtures_dir}/**/*.yml"].map {|f| f[(fixtures_dir.size + 1)..-5] }).each do |fixture_file|
190
+ (ENV['FIXTURES'] ? ENV['FIXTURES'].split(',') : Dir["#{fixtures_dir}/**/*.yml"].map {|f| f[(fixtures_dir.size + 1)..-5] }).each do |fixture_file|
201
191
  ActiveRecord::FixtureSet.create_fixtures(fixtures_dir, fixture_file)
202
192
  end
203
193
  end
@@ -212,9 +202,6 @@ db_namespace = namespace :db do
212
202
  puts %Q(The fixture ID for "#{label}" is #{ActiveRecord::FixtureSet.identify(label)}.) if label
213
203
 
214
204
  base_dir = if ENV['FIXTURES_PATH']
215
- STDERR.puts "Using FIXTURES_PATH env variable is deprecated, please use " +
216
- "ActiveRecord::Tasks::DatabaseTasks.fixtures_path = '/path/to/fixtures' " +
217
- "instead."
218
205
  File.join [Rails.root, ENV['FIXTURES_PATH'] || %w{test fixtures}].flatten
219
206
  else
220
207
  ActiveRecord::Tasks::DatabaseTasks.fixtures_path
@@ -236,7 +223,7 @@ db_namespace = namespace :db do
236
223
  end
237
224
 
238
225
  namespace :schema do
239
- desc 'Create a db/schema.rb file that can be portably used against any DB supported by AR'
226
+ desc 'Create a db/schema.rb file that is portable against any DB supported by AR'
240
227
  task :dump => [:environment, :load_config] do
241
228
  require 'active_record/schema_dumper'
242
229
  filename = ENV['SCHEMA'] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, 'schema.rb')
@@ -248,12 +235,7 @@ db_namespace = namespace :db do
248
235
 
249
236
  desc 'Load a schema.rb file into the database'
250
237
  task :load => [:environment, :load_config] do
251
- file = ENV['SCHEMA'] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, 'schema.rb')
252
- if File.exist?(file)
253
- load(file)
254
- else
255
- abort %{#{file} doesn't exist yet. Run `rake db:migrate` to create it, then try again. If you do not intend to use a database, you should instead alter #{Rails.root}/config/application.rb to limit the frameworks that will be loaded.}
256
- end
238
+ ActiveRecord::Tasks::DatabaseTasks.load_schema_current(:ruby, ENV['SCHEMA'])
257
239
  end
258
240
 
259
241
  task :load_if_ruby => ['db:create', :environment] do
@@ -287,9 +269,11 @@ db_namespace = namespace :db do
287
269
  current_config = ActiveRecord::Tasks::DatabaseTasks.current_config
288
270
  ActiveRecord::Tasks::DatabaseTasks.structure_dump(current_config, filename)
289
271
 
290
- if ActiveRecord::Base.connection.supports_migrations?
272
+ if ActiveRecord::Base.connection.supports_migrations? &&
273
+ ActiveRecord::SchemaMigration.table_exists?
291
274
  File.open(filename, "a") do |f|
292
275
  f.puts ActiveRecord::Base.connection.dump_schema_information
276
+ f.print "\n"
293
277
  end
294
278
  end
295
279
  db_namespace['structure:dump'].reenable
@@ -297,9 +281,7 @@ db_namespace = namespace :db do
297
281
 
298
282
  # desc "Recreate the databases from the structure.sql file"
299
283
  task :load => [:environment, :load_config] do
300
- filename = ENV['DB_STRUCTURE'] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "structure.sql")
301
- current_config = ActiveRecord::Tasks::DatabaseTasks.current_config
302
- ActiveRecord::Tasks::DatabaseTasks.structure_load(current_config, filename)
284
+ ActiveRecord::Tasks::DatabaseTasks.load_schema_current(:sql, ENV['DB_STRUCTURE'])
303
285
  end
304
286
 
305
287
  task :load_if_sql => ['db:create', :environment] do
@@ -309,8 +291,15 @@ db_namespace = namespace :db do
309
291
 
310
292
  namespace :test do
311
293
 
294
+ task :deprecated do
295
+ Rake.application.top_level_tasks.grep(/^db:test:/).each do |task|
296
+ $stderr.puts "WARNING: #{task} is deprecated. The Rails test helper now maintains " \
297
+ "your test schema automatically, see the release notes for details."
298
+ end
299
+ end
300
+
312
301
  # desc "Recreate the test database from the current schema"
313
- task :load => 'db:test:purge' do
302
+ task :load => %w(db:test:purge) do
314
303
  case ActiveRecord::Base.schema_format
315
304
  when :ruby
316
305
  db_namespace["test:load_schema"].invoke
@@ -320,12 +309,11 @@ db_namespace = namespace :db do
320
309
  end
321
310
 
322
311
  # desc "Recreate the test database from an existent schema.rb file"
323
- task :load_schema => 'db:test:purge' do
312
+ task :load_schema => %w(db:test:purge) do
324
313
  begin
325
314
  should_reconnect = ActiveRecord::Base.connection_pool.active_connection?
326
- ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations['test'])
327
315
  ActiveRecord::Schema.verbose = false
328
- db_namespace["schema:load"].invoke
316
+ ActiveRecord::Tasks::DatabaseTasks.load_schema_for ActiveRecord::Base.configurations['test'], :ruby, ENV['SCHEMA']
329
317
  ensure
330
318
  if should_reconnect
331
319
  ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations[ActiveRecord::Tasks::DatabaseTasks.env])
@@ -334,17 +322,12 @@ db_namespace = namespace :db do
334
322
  end
335
323
 
336
324
  # desc "Recreate the test database from an existent structure.sql file"
337
- task :load_structure => 'db:test:purge' do
338
- begin
339
- ActiveRecord::Tasks::DatabaseTasks.current_config(:config => ActiveRecord::Base.configurations['test'])
340
- db_namespace["structure:load"].invoke
341
- ensure
342
- ActiveRecord::Tasks::DatabaseTasks.current_config(:config => nil)
343
- end
325
+ task :load_structure => %w(db:test:purge) do
326
+ ActiveRecord::Tasks::DatabaseTasks.load_schema_for ActiveRecord::Base.configurations['test'], :sql, ENV['SCHEMA']
344
327
  end
345
328
 
346
329
  # desc "Recreate the test database from a fresh schema"
347
- task :clone => :environment do
330
+ task :clone => %w(db:test:deprecated environment) do
348
331
  case ActiveRecord::Base.schema_format
349
332
  when :ruby
350
333
  db_namespace["test:clone_schema"].invoke
@@ -354,18 +337,18 @@ db_namespace = namespace :db do
354
337
  end
355
338
 
356
339
  # desc "Recreate the test database from a fresh schema.rb file"
357
- task :clone_schema => ["db:schema:dump", "db:test:load_schema"]
340
+ task :clone_schema => %w(db:test:deprecated db:schema:dump db:test:load_schema)
358
341
 
359
342
  # desc "Recreate the test database from a fresh structure.sql file"
360
- task :clone_structure => [ "db:structure:dump", "db:test:load_structure" ]
343
+ task :clone_structure => %w(db:test:deprecated db:structure:dump db:test:load_structure)
361
344
 
362
345
  # desc "Empty the test database"
363
- task :purge => [:environment, :load_config] do
346
+ task :purge => %w(environment load_config) do
364
347
  ActiveRecord::Tasks::DatabaseTasks.purge ActiveRecord::Base.configurations['test']
365
348
  end
366
349
 
367
350
  # desc 'Check for pending migrations and load the test schema'
368
- task :prepare => [:environment, :load_config] do
351
+ task :prepare => %w(environment load_config) do
369
352
  unless ActiveRecord::Base.configurations.blank?
370
353
  db_namespace['test:load'].invoke
371
354
  end
@@ -379,7 +362,7 @@ namespace :railties do
379
362
  task :migrations => :'db:load_config' do
380
363
  to_load = ENV['FROM'].blank? ? :all : ENV['FROM'].split(",").map {|n| n.strip }
381
364
  railties = {}
382
- Rails.application.railties.each do |railtie|
365
+ Rails.application.migration_railties.each do |railtie|
383
366
  next unless to_load == :all || to_load.include?(railtie.railtie_name)
384
367
 
385
368
  if railtie.respond_to?(:paths) && (path = railtie.paths['db/migrate'].first)
@@ -400,5 +383,3 @@ namespace :railties do
400
383
  end
401
384
  end
402
385
  end
403
-
404
- task 'test:prepare' => ['db:test:prepare', 'db:test:load', 'db:abort_if_pending_migrations']
@@ -20,11 +20,5 @@ module ActiveRecord
20
20
  self._attr_readonly
21
21
  end
22
22
  end
23
-
24
- def _attr_readonly
25
- message = "Instance level _attr_readonly method is deprecated, please use class level method."
26
- ActiveSupport::Deprecation.warn message
27
- defined?(@_attr_readonly) ? @_attr_readonly : self.class._attr_readonly
28
- end
29
23
  end
30
24
  end