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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1632 -1797
- data/MIT-LICENSE +1 -1
- data/README.rdoc +2 -2
- data/examples/performance.rb +30 -18
- data/examples/simple.rb +4 -4
- data/lib/active_record/aggregations.rb +2 -1
- data/lib/active_record/association_relation.rb +4 -0
- data/lib/active_record/associations/alias_tracker.rb +49 -29
- data/lib/active_record/associations/association.rb +9 -17
- data/lib/active_record/associations/association_scope.rb +59 -49
- data/lib/active_record/associations/belongs_to_association.rb +34 -25
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +6 -1
- data/lib/active_record/associations/builder/association.rb +84 -54
- data/lib/active_record/associations/builder/belongs_to.rb +90 -58
- data/lib/active_record/associations/builder/collection_association.rb +47 -45
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +119 -25
- data/lib/active_record/associations/builder/has_many.rb +3 -3
- data/lib/active_record/associations/builder/has_one.rb +5 -7
- data/lib/active_record/associations/builder/singular_association.rb +6 -7
- data/lib/active_record/associations/collection_association.rb +121 -111
- data/lib/active_record/associations/collection_proxy.rb +73 -18
- data/lib/active_record/associations/has_many_association.rb +14 -11
- data/lib/active_record/associations/has_many_through_association.rb +33 -6
- data/lib/active_record/associations/has_one_association.rb +1 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +46 -104
- data/lib/active_record/associations/join_dependency/join_base.rb +6 -8
- data/lib/active_record/associations/join_dependency/join_part.rb +18 -37
- data/lib/active_record/associations/join_dependency.rb +208 -168
- data/lib/active_record/associations/preloader/association.rb +69 -27
- data/lib/active_record/associations/preloader/collection_association.rb +2 -2
- data/lib/active_record/associations/preloader/has_many_through.rb +1 -1
- data/lib/active_record/associations/preloader/singular_association.rb +3 -3
- data/lib/active_record/associations/preloader/through_association.rb +58 -26
- data/lib/active_record/associations/preloader.rb +63 -49
- data/lib/active_record/associations/singular_association.rb +6 -5
- data/lib/active_record/associations/through_association.rb +30 -9
- data/lib/active_record/associations.rb +116 -42
- data/lib/active_record/attribute_assignment.rb +6 -3
- data/lib/active_record/attribute_methods/before_type_cast.rb +2 -1
- data/lib/active_record/attribute_methods/dirty.rb +35 -26
- data/lib/active_record/attribute_methods/primary_key.rb +8 -1
- data/lib/active_record/attribute_methods/read.rb +56 -29
- data/lib/active_record/attribute_methods/serialization.rb +44 -12
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +13 -1
- data/lib/active_record/attribute_methods/write.rb +59 -26
- data/lib/active_record/attribute_methods.rb +82 -43
- data/lib/active_record/autosave_association.rb +209 -194
- data/lib/active_record/base.rb +6 -2
- data/lib/active_record/callbacks.rb +2 -2
- data/lib/active_record/coders/json.rb +13 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +5 -10
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +14 -24
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +13 -13
- data/lib/active_record/connection_adapters/abstract/quoting.rb +6 -3
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +21 -0
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +90 -0
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +9 -8
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +45 -70
- data/lib/active_record/connection_adapters/abstract/transaction.rb +1 -0
- data/lib/active_record/connection_adapters/abstract_adapter.rb +28 -96
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +74 -66
- data/lib/active_record/connection_adapters/column.rb +1 -35
- data/lib/active_record/connection_adapters/connection_specification.rb +231 -43
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +10 -5
- data/lib/active_record/connection_adapters/mysql_adapter.rb +24 -17
- data/lib/active_record/connection_adapters/postgresql/array_parser.rb +22 -15
- data/lib/active_record/connection_adapters/postgresql/cast.rb +12 -4
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +18 -44
- data/lib/active_record/connection_adapters/postgresql/oid.rb +38 -14
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +37 -12
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +20 -11
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +98 -52
- data/lib/active_record/connection_adapters/schema_cache.rb +8 -29
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +55 -60
- data/lib/active_record/connection_handling.rb +39 -5
- data/lib/active_record/core.rb +38 -54
- data/lib/active_record/counter_cache.rb +9 -10
- data/lib/active_record/dynamic_matchers.rb +6 -2
- data/lib/active_record/enum.rb +199 -0
- data/lib/active_record/errors.rb +22 -5
- data/lib/active_record/fixture_set/file.rb +2 -1
- data/lib/active_record/fixtures.rb +173 -76
- data/lib/active_record/gem_version.rb +15 -0
- data/lib/active_record/inheritance.rb +23 -9
- data/lib/active_record/integration.rb +54 -1
- data/lib/active_record/locking/optimistic.rb +7 -2
- data/lib/active_record/locking/pessimistic.rb +1 -1
- data/lib/active_record/log_subscriber.rb +6 -13
- data/lib/active_record/migration/command_recorder.rb +8 -2
- data/lib/active_record/migration.rb +91 -56
- data/lib/active_record/model_schema.rb +7 -14
- data/lib/active_record/nested_attributes.rb +25 -13
- data/lib/active_record/no_touching.rb +52 -0
- data/lib/active_record/null_relation.rb +26 -6
- data/lib/active_record/persistence.rb +23 -29
- data/lib/active_record/querying.rb +15 -12
- data/lib/active_record/railtie.rb +12 -61
- data/lib/active_record/railties/databases.rake +37 -56
- data/lib/active_record/readonly_attributes.rb +0 -6
- data/lib/active_record/reflection.rb +230 -79
- data/lib/active_record/relation/batches.rb +74 -24
- data/lib/active_record/relation/calculations.rb +52 -48
- data/lib/active_record/relation/delegation.rb +54 -39
- data/lib/active_record/relation/finder_methods.rb +210 -67
- data/lib/active_record/relation/merger.rb +15 -12
- data/lib/active_record/relation/predicate_builder/array_handler.rb +29 -0
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +17 -0
- data/lib/active_record/relation/predicate_builder.rb +81 -40
- data/lib/active_record/relation/query_methods.rb +185 -108
- data/lib/active_record/relation/spawn_methods.rb +8 -5
- data/lib/active_record/relation.rb +79 -84
- data/lib/active_record/result.rb +45 -6
- data/lib/active_record/runtime_registry.rb +5 -0
- data/lib/active_record/sanitization.rb +4 -4
- data/lib/active_record/schema_dumper.rb +18 -6
- data/lib/active_record/schema_migration.rb +31 -18
- data/lib/active_record/scoping/default.rb +5 -18
- data/lib/active_record/scoping/named.rb +14 -29
- data/lib/active_record/scoping.rb +5 -0
- data/lib/active_record/store.rb +67 -18
- data/lib/active_record/tasks/database_tasks.rb +66 -26
- data/lib/active_record/tasks/mysql_database_tasks.rb +16 -10
- data/lib/active_record/tasks/postgresql_database_tasks.rb +1 -1
- data/lib/active_record/tasks/sqlite_database_tasks.rb +5 -1
- data/lib/active_record/timestamp.rb +6 -6
- data/lib/active_record/transactions.rb +10 -12
- data/lib/active_record/validations/presence.rb +1 -1
- data/lib/active_record/validations/uniqueness.rb +19 -9
- data/lib/active_record/version.rb +4 -7
- data/lib/active_record.rb +5 -7
- data/lib/rails/generators/active_record/migration/migration_generator.rb +4 -0
- data/lib/rails/generators/active_record/migration.rb +18 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +4 -0
- data/lib/rails/generators/active_record.rb +2 -8
- metadata +18 -30
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +0 -65
- data/lib/active_record/associations/join_helper.rb +0 -45
- data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +0 -60
- data/lib/active_record/tasks/firebird_database_tasks.rb +0 -56
- data/lib/active_record/tasks/oracle_database_tasks.rb +0 -45
- data/lib/active_record/tasks/sqlserver_database_tasks.rb +0 -48
- data/lib/active_record/test_case.rb +0 -96
@@ -64,7 +64,7 @@ module ActiveRecord
|
|
64
64
|
end
|
65
65
|
|
66
66
|
# Wraps the passed block in a transaction, locking the object
|
67
|
-
# before yielding. You pass
|
67
|
+
# before yielding. You can pass the SQL locking clause
|
68
68
|
# as argument (see <tt>lock!</tt>).
|
69
69
|
def with_lock(lock = true)
|
70
70
|
transaction do
|
@@ -17,13 +17,15 @@ module ActiveRecord
|
|
17
17
|
|
18
18
|
def initialize
|
19
19
|
super
|
20
|
-
@
|
20
|
+
@odd = false
|
21
21
|
end
|
22
22
|
|
23
23
|
def render_bind(column, value)
|
24
24
|
if column
|
25
25
|
if column.binary?
|
26
|
-
|
26
|
+
# This specifically deals with the PG adapter that casts bytea columns into a Hash.
|
27
|
+
value = value[:value] if value.is_a?(Hash)
|
28
|
+
value = value ? "<#{value.bytesize} bytes of binary data>" : "<NULL binary data>"
|
27
29
|
end
|
28
30
|
|
29
31
|
[column.name, value]
|
@@ -41,7 +43,7 @@ module ActiveRecord
|
|
41
43
|
return if IGNORE_PAYLOAD_NAMES.include?(payload[:name])
|
42
44
|
|
43
45
|
name = "#{payload[:name]} (#{event.duration.round(1)}ms)"
|
44
|
-
sql = payload[:sql]
|
46
|
+
sql = payload[:sql]
|
45
47
|
binds = nil
|
46
48
|
|
47
49
|
unless (payload[:binds] || []).empty?
|
@@ -60,17 +62,8 @@ module ActiveRecord
|
|
60
62
|
debug " #{name} #{sql}#{binds}"
|
61
63
|
end
|
62
64
|
|
63
|
-
def identity(event)
|
64
|
-
return unless logger.debug?
|
65
|
-
|
66
|
-
name = color(event.payload[:name], odd? ? CYAN : MAGENTA, true)
|
67
|
-
line = odd? ? color(event.payload[:line], nil, true) : event.payload[:line]
|
68
|
-
|
69
|
-
debug " #{name} #{line}"
|
70
|
-
end
|
71
|
-
|
72
65
|
def odd?
|
73
|
-
@
|
66
|
+
@odd = !@odd
|
74
67
|
end
|
75
68
|
|
76
69
|
def logger
|
@@ -73,8 +73,8 @@ module ActiveRecord
|
|
73
73
|
[:create_table, :create_join_table, :rename_table, :add_column, :remove_column,
|
74
74
|
:rename_index, :rename_column, :add_index, :remove_index, :add_timestamps, :remove_timestamps,
|
75
75
|
:change_column_default, :add_reference, :remove_reference, :transaction,
|
76
|
-
:drop_join_table, :drop_table, :execute_block,
|
77
|
-
:change_column, :execute, :remove_columns, # irreversible methods need to be here too
|
76
|
+
:drop_join_table, :drop_table, :execute_block, :enable_extension,
|
77
|
+
:change_column, :execute, :remove_columns, :change_column_null # irreversible methods need to be here too
|
78
78
|
].each do |method|
|
79
79
|
class_eval <<-EOV, __FILE__, __LINE__ + 1
|
80
80
|
def #{method}(*args, &block) # def create_table(*args, &block)
|
@@ -100,6 +100,7 @@ module ActiveRecord
|
|
100
100
|
add_column: :remove_column,
|
101
101
|
add_timestamps: :remove_timestamps,
|
102
102
|
add_reference: :remove_reference,
|
103
|
+
enable_extension: :disable_extension
|
103
104
|
}.each do |cmd, inv|
|
104
105
|
[[inv, cmd], [cmd, inv]].uniq.each do |method, inverse|
|
105
106
|
class_eval <<-EOV, __FILE__, __LINE__ + 1
|
@@ -161,6 +162,11 @@ module ActiveRecord
|
|
161
162
|
alias :invert_add_belongs_to :invert_add_reference
|
162
163
|
alias :invert_remove_belongs_to :invert_remove_reference
|
163
164
|
|
165
|
+
def invert_change_column_null(args)
|
166
|
+
args[2] = !args[2]
|
167
|
+
[:change_column_null, args]
|
168
|
+
end
|
169
|
+
|
164
170
|
# Forwards any missing method call to the \target.
|
165
171
|
def method_missing(method, *args, &block)
|
166
172
|
if @delegate.respond_to?(method)
|
@@ -1,41 +1,48 @@
|
|
1
|
-
require "active_support/core_ext/
|
1
|
+
require "active_support/core_ext/module/attribute_accessors"
|
2
2
|
require 'set'
|
3
3
|
|
4
4
|
module ActiveRecord
|
5
|
+
class MigrationError < ActiveRecordError#:nodoc:
|
6
|
+
def initialize(message = nil)
|
7
|
+
message = "\n\n#{message}\n\n" if message
|
8
|
+
super
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
5
12
|
# Exception that can be raised to stop migrations from going backwards.
|
6
|
-
class IrreversibleMigration <
|
13
|
+
class IrreversibleMigration < MigrationError
|
7
14
|
end
|
8
15
|
|
9
|
-
class DuplicateMigrationVersionError <
|
16
|
+
class DuplicateMigrationVersionError < MigrationError#:nodoc:
|
10
17
|
def initialize(version)
|
11
18
|
super("Multiple migrations have the version number #{version}")
|
12
19
|
end
|
13
20
|
end
|
14
21
|
|
15
|
-
class DuplicateMigrationNameError <
|
22
|
+
class DuplicateMigrationNameError < MigrationError#:nodoc:
|
16
23
|
def initialize(name)
|
17
24
|
super("Multiple migrations have the name #{name}")
|
18
25
|
end
|
19
26
|
end
|
20
27
|
|
21
|
-
class UnknownMigrationVersionError <
|
28
|
+
class UnknownMigrationVersionError < MigrationError #:nodoc:
|
22
29
|
def initialize(version)
|
23
30
|
super("No migration with version number #{version}")
|
24
31
|
end
|
25
32
|
end
|
26
33
|
|
27
|
-
class IllegalMigrationNameError <
|
34
|
+
class IllegalMigrationNameError < MigrationError#:nodoc:
|
28
35
|
def initialize(name)
|
29
36
|
super("Illegal name for migration file: #{name}\n\t(only lower case letters, numbers, and '_' allowed)")
|
30
37
|
end
|
31
38
|
end
|
32
39
|
|
33
|
-
class PendingMigrationError <
|
40
|
+
class PendingMigrationError < MigrationError#:nodoc:
|
34
41
|
def initialize
|
35
42
|
if defined?(Rails)
|
36
|
-
super("Migrations are pending
|
43
|
+
super("Migrations are pending. To resolve this issue, run:\n\n\tbin/rake db:migrate RAILS_ENV=#{::Rails.env}")
|
37
44
|
else
|
38
|
-
super("Migrations are pending
|
45
|
+
super("Migrations are pending. To resolve this issue, run:\n\n\tbin/rake db:migrate")
|
39
46
|
end
|
40
47
|
end
|
41
48
|
end
|
@@ -377,23 +384,43 @@ module ActiveRecord
|
|
377
384
|
class << self
|
378
385
|
attr_accessor :delegate # :nodoc:
|
379
386
|
attr_accessor :disable_ddl_transaction # :nodoc:
|
380
|
-
end
|
381
387
|
|
382
|
-
|
383
|
-
|
384
|
-
|
388
|
+
def check_pending!(connection = Base.connection)
|
389
|
+
raise ActiveRecord::PendingMigrationError if ActiveRecord::Migrator.needs_migration?(connection)
|
390
|
+
end
|
385
391
|
|
386
|
-
|
387
|
-
|
388
|
-
|
392
|
+
def load_schema_if_pending!
|
393
|
+
if ActiveRecord::Migrator.needs_migration?
|
394
|
+
# Roundrip to Rake to allow plugins to hook into database initialization.
|
395
|
+
FileUtils.cd Rails.root do
|
396
|
+
current_config = Base.connection_config
|
397
|
+
Base.clear_all_connections!
|
398
|
+
system("bin/rake db:test:prepare")
|
399
|
+
# Establish a new connection, the old database may be gone (db:test:prepare uses purge)
|
400
|
+
Base.establish_connection(current_config)
|
401
|
+
end
|
402
|
+
check_pending!
|
403
|
+
end
|
404
|
+
end
|
389
405
|
|
390
|
-
|
391
|
-
|
392
|
-
|
406
|
+
def maintain_test_schema! # :nodoc:
|
407
|
+
if ActiveRecord::Base.maintain_test_schema
|
408
|
+
suppress_messages { load_schema_if_pending! }
|
409
|
+
end
|
410
|
+
end
|
393
411
|
|
394
|
-
|
395
|
-
|
396
|
-
|
412
|
+
def method_missing(name, *args, &block) # :nodoc:
|
413
|
+
(delegate || superclass.delegate).send(name, *args, &block)
|
414
|
+
end
|
415
|
+
|
416
|
+
def migrate(direction)
|
417
|
+
new.migrate direction
|
418
|
+
end
|
419
|
+
|
420
|
+
# Disable DDL transactions for this migration.
|
421
|
+
def disable_ddl_transaction!
|
422
|
+
@disable_ddl_transaction = true
|
423
|
+
end
|
397
424
|
end
|
398
425
|
|
399
426
|
def disable_ddl_transaction # :nodoc:
|
@@ -620,9 +647,9 @@ module ActiveRecord
|
|
620
647
|
|
621
648
|
say_with_time "#{method}(#{arg_list})" do
|
622
649
|
unless @connection.respond_to? :revert
|
623
|
-
unless arguments.empty? ||
|
624
|
-
arguments[0] =
|
625
|
-
arguments[1] =
|
650
|
+
unless arguments.empty? || [:execute, :enable_extension, :disable_extension].include?(method)
|
651
|
+
arguments[0] = proper_table_name(arguments.first, table_name_options)
|
652
|
+
arguments[1] = proper_table_name(arguments.second, table_name_options) if method == :rename_table
|
626
653
|
end
|
627
654
|
end
|
628
655
|
return super unless connection.respond_to?(method)
|
@@ -675,14 +702,33 @@ module ActiveRecord
|
|
675
702
|
copied
|
676
703
|
end
|
677
704
|
|
705
|
+
# Finds the correct table name given an Active Record object.
|
706
|
+
# Uses the Active Record object's own table_name, or pre/suffix from the
|
707
|
+
# options passed in.
|
708
|
+
def proper_table_name(name, options = {})
|
709
|
+
if name.respond_to? :table_name
|
710
|
+
name.table_name
|
711
|
+
else
|
712
|
+
"#{options[:table_name_prefix]}#{name}#{options[:table_name_suffix]}"
|
713
|
+
end
|
714
|
+
end
|
715
|
+
|
716
|
+
# Determines the version number of the next migration.
|
678
717
|
def next_migration_number(number)
|
679
718
|
if ActiveRecord::Base.timestamped_migrations
|
680
719
|
[Time.now.utc.strftime("%Y%m%d%H%M%S"), "%.14d" % number].max
|
681
720
|
else
|
682
|
-
|
721
|
+
SchemaMigration.normalize_migration_number(number)
|
683
722
|
end
|
684
723
|
end
|
685
724
|
|
725
|
+
def table_name_options(config = ActiveRecord::Base)
|
726
|
+
{
|
727
|
+
table_name_prefix: config.table_name_prefix,
|
728
|
+
table_name_suffix: config.table_name_suffix
|
729
|
+
}
|
730
|
+
end
|
731
|
+
|
686
732
|
private
|
687
733
|
def execute_block
|
688
734
|
if connection.respond_to? :execute_block
|
@@ -787,21 +833,20 @@ module ActiveRecord
|
|
787
833
|
SchemaMigration.table_name
|
788
834
|
end
|
789
835
|
|
790
|
-
def get_all_versions
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
def current_version
|
795
|
-
sm_table = schema_migrations_table_name
|
796
|
-
if Base.connection.table_exists?(sm_table)
|
797
|
-
get_all_versions.max || 0
|
836
|
+
def get_all_versions(connection = Base.connection)
|
837
|
+
if connection.table_exists?(schema_migrations_table_name)
|
838
|
+
SchemaMigration.all.map { |x| x.version.to_i }.sort
|
798
839
|
else
|
799
|
-
|
840
|
+
[]
|
800
841
|
end
|
801
842
|
end
|
802
843
|
|
803
|
-
def
|
804
|
-
|
844
|
+
def current_version(connection = Base.connection)
|
845
|
+
get_all_versions(connection).max || 0
|
846
|
+
end
|
847
|
+
|
848
|
+
def needs_migration?(connection = Base.connection)
|
849
|
+
(migrations(migrations_paths).collect(&:version) - get_all_versions(connection)).size > 0
|
805
850
|
end
|
806
851
|
|
807
852
|
def last_version
|
@@ -812,12 +857,16 @@ module ActiveRecord
|
|
812
857
|
migrations(migrations_paths).last || NullMigration.new
|
813
858
|
end
|
814
859
|
|
815
|
-
def proper_table_name(name)
|
816
|
-
|
860
|
+
def proper_table_name(name, options = {})
|
861
|
+
ActiveSupport::Deprecation.warn "ActiveRecord::Migrator.proper_table_name is deprecated and will be removed in Rails 4.2. Use the proper_table_name instance method on ActiveRecord::Migration instead"
|
862
|
+
options = {
|
863
|
+
table_name_prefix: ActiveRecord::Base.table_name_prefix,
|
864
|
+
table_name_suffix: ActiveRecord::Base.table_name_suffix
|
865
|
+
}.merge(options)
|
817
866
|
if name.respond_to? :table_name
|
818
867
|
name.table_name
|
819
868
|
else
|
820
|
-
"#{
|
869
|
+
"#{options[:table_name_prefix]}#{name}#{options[:table_name_suffix]}"
|
821
870
|
end
|
822
871
|
end
|
823
872
|
|
@@ -869,13 +918,7 @@ module ActiveRecord
|
|
869
918
|
@direction = direction
|
870
919
|
@target_version = target_version
|
871
920
|
@migrated_versions = nil
|
872
|
-
|
873
|
-
if Array(migrations).grep(String).empty?
|
874
|
-
@migrations = migrations
|
875
|
-
else
|
876
|
-
ActiveSupport::Deprecation.warn "instantiate this class with a list of migrations"
|
877
|
-
@migrations = self.class.migrations(migrations)
|
878
|
-
end
|
921
|
+
@migrations = migrations
|
879
922
|
|
880
923
|
validate(@migrations)
|
881
924
|
|
@@ -909,15 +952,7 @@ module ActiveRecord
|
|
909
952
|
raise UnknownMigrationVersionError.new(@target_version)
|
910
953
|
end
|
911
954
|
|
912
|
-
|
913
|
-
|
914
|
-
if block_given?
|
915
|
-
message = "block argument to migrate is deprecated, please filter migrations before constructing the migrator"
|
916
|
-
ActiveSupport::Deprecation.warn message
|
917
|
-
running.select! { |m| yield m }
|
918
|
-
end
|
919
|
-
|
920
|
-
running.each do |migration|
|
955
|
+
runnable.each do |migration|
|
921
956
|
Base.logger.info "Migrating to #{migration.name} (#{migration.version})" if Base.logger
|
922
957
|
|
923
958
|
begin
|
@@ -32,6 +32,12 @@ module ActiveRecord
|
|
32
32
|
class_attribute :table_name_suffix, instance_writer: false
|
33
33
|
self.table_name_suffix = ""
|
34
34
|
|
35
|
+
##
|
36
|
+
# :singleton-method:
|
37
|
+
# Accessor for the name of the schema migrations table. By default, the value is "schema_migrations"
|
38
|
+
class_attribute :schema_migrations_table_name, instance_accessor: false
|
39
|
+
self.schema_migrations_table_name = "schema_migrations"
|
40
|
+
|
35
41
|
##
|
36
42
|
# :singleton-method:
|
37
43
|
# Indicates whether table names should be the pluralized versions of the corresponding class names.
|
@@ -124,7 +130,7 @@ module ActiveRecord
|
|
124
130
|
@quoted_table_name = nil
|
125
131
|
@arel_table = nil
|
126
132
|
@sequence_name = nil unless defined?(@explicit_sequence_name) && @explicit_sequence_name
|
127
|
-
@relation = Relation.
|
133
|
+
@relation = Relation.create(self, arel_table)
|
128
134
|
end
|
129
135
|
|
130
136
|
# Returns a quoted version of the table name, used to construct SQL statements.
|
@@ -260,19 +266,6 @@ module ActiveRecord
|
|
260
266
|
@content_columns ||= columns.reject { |c| c.primary || c.name =~ /(_id|_count)$/ || c.name == inheritance_column }
|
261
267
|
end
|
262
268
|
|
263
|
-
# Returns a hash of all the methods added to query each of the columns in the table with the name of the method as the key
|
264
|
-
# and true as the value. This makes it possible to do O(1) lookups in respond_to? to check if a given method for attribute
|
265
|
-
# is available.
|
266
|
-
def column_methods_hash #:nodoc:
|
267
|
-
@dynamic_methods_hash ||= column_names.each_with_object(Hash.new(false)) do |attr, methods|
|
268
|
-
attr_name = attr.to_s
|
269
|
-
methods[attr.to_sym] = attr_name
|
270
|
-
methods["#{attr}=".to_sym] = attr_name
|
271
|
-
methods["#{attr}?".to_sym] = attr_name
|
272
|
-
methods["#{attr}_before_type_cast".to_sym] = attr_name
|
273
|
-
end
|
274
|
-
end
|
275
|
-
|
276
269
|
# Resets all the cached information about columns, which will cause them
|
277
270
|
# to be reloaded on the next request.
|
278
271
|
#
|
@@ -230,6 +230,10 @@ module ActiveRecord
|
|
230
230
|
# validates_presence_of :member
|
231
231
|
# end
|
232
232
|
#
|
233
|
+
# Note that if you do not specify the <tt>inverse_of</tt> option, then
|
234
|
+
# Active Record will try to automatically guess the inverse association
|
235
|
+
# based on heuristics.
|
236
|
+
#
|
233
237
|
# For one-to-one nested associations, if you build the new (in-memory)
|
234
238
|
# child object yourself before assignment, then this module will not
|
235
239
|
# overwrite it, e.g.:
|
@@ -301,9 +305,9 @@ module ActiveRecord
|
|
301
305
|
options[:reject_if] = REJECT_ALL_BLANK_PROC if options[:reject_if] == :all_blank
|
302
306
|
|
303
307
|
attr_names.each do |association_name|
|
304
|
-
if reflection =
|
305
|
-
reflection.
|
306
|
-
|
308
|
+
if reflection = _reflect_on_association(association_name)
|
309
|
+
reflection.autosave = true
|
310
|
+
define_autosave_validation_callbacks(reflection)
|
307
311
|
|
308
312
|
nested_attributes_options = self.nested_attributes_options.dup
|
309
313
|
nested_attributes_options[association_name.to_sym] = options
|
@@ -331,7 +335,7 @@ module ActiveRecord
|
|
331
335
|
# the helper methods defined below. Makes it seem like the nested
|
332
336
|
# associations are just regular associations.
|
333
337
|
def generate_association_writer(association_name, type)
|
334
|
-
|
338
|
+
generated_association_methods.module_eval <<-eoruby, __FILE__, __LINE__ + 1
|
335
339
|
if method_defined?(:#{association_name}_attributes=)
|
336
340
|
remove_method(:#{association_name}_attributes=)
|
337
341
|
end
|
@@ -461,19 +465,17 @@ module ActiveRecord
|
|
461
465
|
association.build(attributes.except(*UNASSIGNABLE_KEYS))
|
462
466
|
end
|
463
467
|
elsif existing_record = existing_records.detect { |record| record.id.to_s == attributes['id'].to_s }
|
464
|
-
unless
|
468
|
+
unless call_reject_if(association_name, attributes)
|
465
469
|
# Make sure we are operating on the actual object which is in the association's
|
466
470
|
# proxy_target array (either by finding it, or adding it if not found)
|
467
|
-
|
468
|
-
|
471
|
+
# Take into account that the proxy_target may have changed due to callbacks
|
472
|
+
target_record = association.target.detect { |record| record.id.to_s == attributes['id'].to_s }
|
469
473
|
if target_record
|
470
474
|
existing_record = target_record
|
471
475
|
else
|
472
|
-
association.add_to_target(existing_record)
|
476
|
+
association.add_to_target(existing_record, :skip_callbacks)
|
473
477
|
end
|
474
|
-
end
|
475
478
|
|
476
|
-
if !call_reject_if(association_name, attributes)
|
477
479
|
assign_to_or_mark_for_destruction(existing_record, attributes, options[:allow_destroy])
|
478
480
|
end
|
479
481
|
else
|
@@ -521,7 +523,7 @@ module ActiveRecord
|
|
521
523
|
# has_destroy_flag? or if a <tt>:reject_if</tt> proc exists for this
|
522
524
|
# association and evaluates to +true+.
|
523
525
|
def reject_new_record?(association_name, attributes)
|
524
|
-
|
526
|
+
will_be_destroyed?(association_name, attributes) || call_reject_if(association_name, attributes)
|
525
527
|
end
|
526
528
|
|
527
529
|
# Determines if a record with the particular +attributes+ should be
|
@@ -530,7 +532,8 @@ module ActiveRecord
|
|
530
532
|
#
|
531
533
|
# Returns false if there is a +destroy_flag+ on the attributes.
|
532
534
|
def call_reject_if(association_name, attributes)
|
533
|
-
return false if
|
535
|
+
return false if will_be_destroyed?(association_name, attributes)
|
536
|
+
|
534
537
|
case callback = self.nested_attributes_options[association_name][:reject_if]
|
535
538
|
when Symbol
|
536
539
|
method(callback).arity == 0 ? send(callback) : send(callback, attributes)
|
@@ -539,8 +542,17 @@ module ActiveRecord
|
|
539
542
|
end
|
540
543
|
end
|
541
544
|
|
545
|
+
# Only take into account the destroy flag if <tt>:allow_destroy</tt> is true
|
546
|
+
def will_be_destroyed?(association_name, attributes)
|
547
|
+
allow_destroy?(association_name) && has_destroy_flag?(attributes)
|
548
|
+
end
|
549
|
+
|
550
|
+
def allow_destroy?(association_name)
|
551
|
+
self.nested_attributes_options[association_name][:allow_destroy]
|
552
|
+
end
|
553
|
+
|
542
554
|
def raise_nested_attributes_record_not_found!(association_name, record_id)
|
543
|
-
raise RecordNotFound, "Couldn't find #{self.class.
|
555
|
+
raise RecordNotFound, "Couldn't find #{self.class._reflect_on_association(association_name).klass.name} with ID=#{record_id} for #{self.class.name} with ID=#{id}"
|
544
556
|
end
|
545
557
|
end
|
546
558
|
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
# = Active Record No Touching
|
3
|
+
module NoTouching
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
module ClassMethods
|
7
|
+
# Lets you selectively disable calls to `touch` for the
|
8
|
+
# duration of a block.
|
9
|
+
#
|
10
|
+
# ==== Examples
|
11
|
+
# ActiveRecord::Base.no_touching do
|
12
|
+
# Project.first.touch # does nothing
|
13
|
+
# Message.first.touch # does nothing
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# Project.no_touching do
|
17
|
+
# Project.first.touch # does nothing
|
18
|
+
# Message.first.touch # works, but does not touch the associated project
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
def no_touching(&block)
|
22
|
+
NoTouching.apply_to(self, &block)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class << self
|
27
|
+
def apply_to(klass) #:nodoc:
|
28
|
+
klasses.push(klass)
|
29
|
+
yield
|
30
|
+
ensure
|
31
|
+
klasses.pop
|
32
|
+
end
|
33
|
+
|
34
|
+
def applied_to?(klass) #:nodoc:
|
35
|
+
klasses.any? { |k| k >= klass }
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
def klasses
|
40
|
+
Thread.current[:no_touching_classes] ||= []
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def no_touching?
|
45
|
+
NoTouching.applied_to?(self.class)
|
46
|
+
end
|
47
|
+
|
48
|
+
def touch(*)
|
49
|
+
super unless no_touching?
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -23,7 +23,7 @@ module ActiveRecord
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def size
|
26
|
-
|
26
|
+
calculate :size, nil
|
27
27
|
end
|
28
28
|
|
29
29
|
def empty?
|
@@ -39,19 +39,39 @@ module ActiveRecord
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def to_sql
|
42
|
-
|
42
|
+
""
|
43
43
|
end
|
44
44
|
|
45
45
|
def count(*)
|
46
|
-
|
46
|
+
calculate :count, nil
|
47
47
|
end
|
48
48
|
|
49
49
|
def sum(*)
|
50
|
-
|
50
|
+
calculate :sum, nil
|
51
|
+
end
|
52
|
+
|
53
|
+
def average(*)
|
54
|
+
calculate :average, nil
|
55
|
+
end
|
56
|
+
|
57
|
+
def minimum(*)
|
58
|
+
calculate :minimum, nil
|
59
|
+
end
|
60
|
+
|
61
|
+
def maximum(*)
|
62
|
+
calculate :maximum, nil
|
51
63
|
end
|
52
64
|
|
53
|
-
def calculate(
|
54
|
-
|
65
|
+
def calculate(operation, _column_name, _options = {})
|
66
|
+
# TODO: Remove _options argument as soon we remove support to
|
67
|
+
# activerecord-deprecated_finders.
|
68
|
+
if [:count, :sum, :size].include? operation
|
69
|
+
group_values.any? ? Hash.new : 0
|
70
|
+
elsif [:average, :minimum, :maximum].include?(operation) && group_values.any?
|
71
|
+
Hash.new
|
72
|
+
else
|
73
|
+
nil
|
74
|
+
end
|
55
75
|
end
|
56
76
|
|
57
77
|
def exists?(_id = false)
|