activerecord 4.2.0 → 5.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1537 -789
- data/MIT-LICENSE +2 -2
- data/README.rdoc +7 -8
- data/examples/performance.rb +2 -3
- data/examples/simple.rb +0 -1
- data/lib/active_record/aggregations.rb +37 -23
- data/lib/active_record/association_relation.rb +16 -3
- data/lib/active_record/associations/alias_tracker.rb +19 -16
- data/lib/active_record/associations/association.rb +23 -9
- data/lib/active_record/associations/association_scope.rb +74 -102
- data/lib/active_record/associations/belongs_to_association.rb +26 -29
- data/lib/active_record/associations/builder/association.rb +28 -34
- data/lib/active_record/associations/builder/belongs_to.rb +43 -18
- data/lib/active_record/associations/builder/collection_association.rb +12 -20
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +22 -15
- data/lib/active_record/associations/builder/has_many.rb +4 -4
- data/lib/active_record/associations/builder/has_one.rb +11 -6
- data/lib/active_record/associations/builder/singular_association.rb +3 -10
- data/lib/active_record/associations/collection_association.rb +61 -33
- data/lib/active_record/associations/collection_proxy.rb +81 -35
- data/lib/active_record/associations/foreign_association.rb +11 -0
- data/lib/active_record/associations/has_many_association.rb +21 -57
- data/lib/active_record/associations/has_many_through_association.rb +15 -45
- data/lib/active_record/associations/has_one_association.rb +13 -5
- data/lib/active_record/associations/join_dependency/join_association.rb +20 -8
- data/lib/active_record/associations/join_dependency.rb +37 -21
- data/lib/active_record/associations/preloader/association.rb +51 -53
- data/lib/active_record/associations/preloader/collection_association.rb +0 -6
- data/lib/active_record/associations/preloader/has_many_through.rb +1 -1
- data/lib/active_record/associations/preloader/has_one.rb +0 -8
- data/lib/active_record/associations/preloader/through_association.rb +27 -14
- data/lib/active_record/associations/preloader.rb +18 -8
- data/lib/active_record/associations/singular_association.rb +8 -8
- data/lib/active_record/associations/through_association.rb +22 -9
- data/lib/active_record/associations.rb +321 -212
- data/lib/active_record/attribute/user_provided_default.rb +28 -0
- data/lib/active_record/attribute.rb +79 -15
- data/lib/active_record/attribute_assignment.rb +20 -141
- data/lib/active_record/attribute_decorators.rb +6 -5
- data/lib/active_record/attribute_methods/before_type_cast.rb +6 -1
- data/lib/active_record/attribute_methods/dirty.rb +51 -81
- data/lib/active_record/attribute_methods/primary_key.rb +2 -2
- data/lib/active_record/attribute_methods/query.rb +2 -2
- data/lib/active_record/attribute_methods/read.rb +31 -59
- data/lib/active_record/attribute_methods/serialization.rb +13 -16
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +65 -14
- data/lib/active_record/attribute_methods/write.rb +14 -38
- data/lib/active_record/attribute_methods.rb +70 -45
- data/lib/active_record/attribute_mutation_tracker.rb +70 -0
- data/lib/active_record/attribute_set/builder.rb +37 -15
- data/lib/active_record/attribute_set.rb +34 -3
- data/lib/active_record/attributes.rb +199 -73
- data/lib/active_record/autosave_association.rb +73 -25
- data/lib/active_record/base.rb +35 -27
- data/lib/active_record/callbacks.rb +39 -43
- data/lib/active_record/coders/json.rb +1 -1
- data/lib/active_record/coders/yaml_column.rb +20 -8
- data/lib/active_record/collection_cache_key.rb +40 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +457 -181
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +83 -59
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/quoting.rb +74 -9
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -4
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +61 -39
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +246 -185
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +72 -17
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +438 -136
- data/lib/active_record/connection_adapters/abstract/transaction.rb +53 -40
- data/lib/active_record/connection_adapters/abstract_adapter.rb +166 -66
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +429 -335
- data/lib/active_record/connection_adapters/column.rb +28 -43
- data/lib/active_record/connection_adapters/connection_specification.rb +15 -27
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +22 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +50 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +125 -0
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +70 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +51 -0
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +67 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +93 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +54 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +32 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +26 -177
- data/lib/active_record/connection_adapters/postgresql/column.rb +5 -10
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +11 -73
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +42 -0
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +27 -56
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -1
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +7 -13
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +1 -26
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +0 -4
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +50 -0
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +31 -17
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +17 -5
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid.rb +1 -6
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +26 -18
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +29 -10
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -79
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +47 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +248 -154
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +35 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +258 -170
- data/lib/active_record/connection_adapters/schema_cache.rb +36 -23
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +32 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +19 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +48 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +150 -209
- data/lib/active_record/connection_adapters/statement_pool.rb +31 -12
- data/lib/active_record/connection_handling.rb +38 -15
- data/lib/active_record/core.rb +109 -114
- data/lib/active_record/counter_cache.rb +14 -25
- data/lib/active_record/dynamic_matchers.rb +1 -20
- data/lib/active_record/enum.rb +115 -79
- data/lib/active_record/errors.rb +88 -48
- data/lib/active_record/explain_registry.rb +1 -1
- data/lib/active_record/explain_subscriber.rb +2 -2
- data/lib/active_record/fixture_set/file.rb +26 -5
- data/lib/active_record/fixtures.rb +84 -46
- data/lib/active_record/gem_version.rb +2 -2
- data/lib/active_record/inheritance.rb +32 -40
- data/lib/active_record/integration.rb +4 -4
- data/lib/active_record/internal_metadata.rb +56 -0
- data/lib/active_record/legacy_yaml_adapter.rb +46 -0
- data/lib/active_record/locale/en.yml +3 -2
- data/lib/active_record/locking/optimistic.rb +27 -25
- data/lib/active_record/locking/pessimistic.rb +1 -1
- data/lib/active_record/log_subscriber.rb +43 -21
- data/lib/active_record/migration/command_recorder.rb +59 -18
- data/lib/active_record/migration/compatibility.rb +126 -0
- data/lib/active_record/migration.rb +372 -114
- data/lib/active_record/model_schema.rb +128 -38
- data/lib/active_record/nested_attributes.rb +71 -32
- data/lib/active_record/no_touching.rb +1 -1
- data/lib/active_record/null_relation.rb +16 -8
- data/lib/active_record/persistence.rb +124 -80
- data/lib/active_record/query_cache.rb +15 -18
- data/lib/active_record/querying.rb +10 -9
- data/lib/active_record/railtie.rb +28 -19
- data/lib/active_record/railties/controller_runtime.rb +1 -1
- data/lib/active_record/railties/databases.rake +67 -51
- data/lib/active_record/readonly_attributes.rb +1 -1
- data/lib/active_record/reflection.rb +318 -139
- data/lib/active_record/relation/batches/batch_enumerator.rb +67 -0
- data/lib/active_record/relation/batches.rb +139 -34
- data/lib/active_record/relation/calculations.rb +80 -102
- data/lib/active_record/relation/delegation.rb +7 -20
- data/lib/active_record/relation/finder_methods.rb +167 -97
- data/lib/active_record/relation/from_clause.rb +32 -0
- data/lib/active_record/relation/merger.rb +38 -41
- data/lib/active_record/relation/predicate_builder/array_handler.rb +12 -16
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +88 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +17 -0
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +17 -0
- data/lib/active_record/relation/predicate_builder/class_handler.rb +27 -0
- data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +57 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +33 -0
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
- data/lib/active_record/relation/predicate_builder.rb +124 -82
- data/lib/active_record/relation/query_attribute.rb +19 -0
- data/lib/active_record/relation/query_methods.rb +323 -257
- data/lib/active_record/relation/record_fetch_warning.rb +49 -0
- data/lib/active_record/relation/spawn_methods.rb +11 -10
- data/lib/active_record/relation/where_clause.rb +174 -0
- data/lib/active_record/relation/where_clause_factory.rb +38 -0
- data/lib/active_record/relation.rb +176 -115
- data/lib/active_record/result.rb +4 -3
- data/lib/active_record/runtime_registry.rb +1 -1
- data/lib/active_record/sanitization.rb +95 -66
- data/lib/active_record/schema.rb +26 -22
- data/lib/active_record/schema_dumper.rb +62 -38
- data/lib/active_record/schema_migration.rb +11 -17
- data/lib/active_record/scoping/default.rb +24 -9
- data/lib/active_record/scoping/named.rb +49 -28
- data/lib/active_record/scoping.rb +32 -15
- data/lib/active_record/secure_token.rb +38 -0
- data/lib/active_record/serialization.rb +2 -4
- data/lib/active_record/statement_cache.rb +16 -14
- data/lib/active_record/store.rb +8 -3
- data/lib/active_record/suppressor.rb +58 -0
- data/lib/active_record/table_metadata.rb +68 -0
- data/lib/active_record/tasks/database_tasks.rb +59 -42
- data/lib/active_record/tasks/mysql_database_tasks.rb +32 -26
- data/lib/active_record/tasks/postgresql_database_tasks.rb +29 -9
- data/lib/active_record/tasks/sqlite_database_tasks.rb +5 -1
- data/lib/active_record/timestamp.rb +20 -9
- data/lib/active_record/touch_later.rb +58 -0
- data/lib/active_record/transactions.rb +159 -67
- data/lib/active_record/type/adapter_specific_registry.rb +130 -0
- data/lib/active_record/type/date.rb +2 -41
- data/lib/active_record/type/date_time.rb +2 -38
- data/lib/active_record/type/hash_lookup_type_map.rb +8 -2
- data/lib/active_record/type/internal/abstract_json.rb +29 -0
- data/lib/active_record/type/internal/timezone.rb +15 -0
- data/lib/active_record/type/serialized.rb +21 -14
- data/lib/active_record/type/time.rb +10 -16
- data/lib/active_record/type/type_map.rb +4 -4
- data/lib/active_record/type.rb +66 -17
- data/lib/active_record/type_caster/connection.rb +29 -0
- data/lib/active_record/type_caster/map.rb +19 -0
- data/lib/active_record/type_caster.rb +7 -0
- data/lib/active_record/validations/absence.rb +23 -0
- data/lib/active_record/validations/associated.rb +10 -3
- data/lib/active_record/validations/length.rb +24 -0
- data/lib/active_record/validations/presence.rb +11 -12
- data/lib/active_record/validations/uniqueness.rb +29 -18
- data/lib/active_record/validations.rb +33 -32
- data/lib/active_record.rb +9 -2
- data/lib/rails/generators/active_record/migration/migration_generator.rb +7 -4
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +8 -6
- data/lib/rails/generators/active_record/migration/templates/migration.rb +8 -7
- data/lib/rails/generators/active_record/migration.rb +7 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +32 -15
- data/lib/rails/generators/active_record/model/templates/application_record.rb +5 -0
- data/lib/rails/generators/active_record/model/templates/model.rb +3 -0
- metadata +60 -34
- data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -491
- data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +0 -11
- data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
- data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
- data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
- data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
- data/lib/active_record/serializers/xml_serializer.rb +0 -193
- data/lib/active_record/type/big_integer.rb +0 -13
- data/lib/active_record/type/binary.rb +0 -50
- data/lib/active_record/type/boolean.rb +0 -30
- data/lib/active_record/type/decimal.rb +0 -40
- data/lib/active_record/type/decimal_without_scale.rb +0 -11
- data/lib/active_record/type/decorator.rb +0 -14
- data/lib/active_record/type/float.rb +0 -19
- data/lib/active_record/type/integer.rb +0 -55
- data/lib/active_record/type/mutable.rb +0 -16
- data/lib/active_record/type/numeric.rb +0 -36
- data/lib/active_record/type/string.rb +0 -36
- data/lib/active_record/type/text.rb +0 -11
- data/lib/active_record/type/time_value.rb +0 -38
- data/lib/active_record/type/unsigned_integer.rb +0 -15
- data/lib/active_record/type/value.rb +0 -101
@@ -5,7 +5,7 @@ module ActiveRecord
|
|
5
5
|
class DatabaseAlreadyExists < StandardError; end # :nodoc:
|
6
6
|
class DatabaseNotSupported < StandardError; end # :nodoc:
|
7
7
|
|
8
|
-
#
|
8
|
+
# ActiveRecord::Tasks::DatabaseTasks is a utility class, which encapsulates
|
9
9
|
# logic behind common tasks used to manage database and migrations.
|
10
10
|
#
|
11
11
|
# The tasks defined here are used with Rake tasks provided by Active Record.
|
@@ -18,15 +18,15 @@ module ActiveRecord
|
|
18
18
|
#
|
19
19
|
# The possible config values are:
|
20
20
|
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
21
|
+
# * +env+: current environment (like Rails.env).
|
22
|
+
# * +database_configuration+: configuration of your databases (as in +config/database.yml+).
|
23
|
+
# * +db_dir+: your +db+ directory.
|
24
|
+
# * +fixtures_path+: a path to fixtures directory.
|
25
|
+
# * +migrations_paths+: a list of paths to directories with migrations.
|
26
|
+
# * +seed_loader+: an object which will load seeds, it needs to respond to the +load_seed+ method.
|
27
|
+
# * +root+: a path to the root of the application.
|
28
28
|
#
|
29
|
-
# Example usage of
|
29
|
+
# Example usage of DatabaseTasks outside Rails could look as such:
|
30
30
|
#
|
31
31
|
# include ActiveRecord::Tasks
|
32
32
|
# DatabaseTasks.database_configuration = YAML.load_file('my_database_config.yml')
|
@@ -42,6 +42,22 @@ module ActiveRecord
|
|
42
42
|
|
43
43
|
LOCAL_HOSTS = ['127.0.0.1', 'localhost']
|
44
44
|
|
45
|
+
def check_protected_environments!
|
46
|
+
unless ENV['DISABLE_DATABASE_ENVIRONMENT_CHECK']
|
47
|
+
current = ActiveRecord::Migrator.current_environment
|
48
|
+
stored = ActiveRecord::Migrator.last_stored_environment
|
49
|
+
|
50
|
+
if ActiveRecord::Migrator.protected_environment?
|
51
|
+
raise ActiveRecord::ProtectedEnvironmentError.new(stored)
|
52
|
+
end
|
53
|
+
|
54
|
+
if stored && stored != current
|
55
|
+
raise ActiveRecord::EnvironmentMismatchError.new(current: current, stored: stored)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
rescue ActiveRecord::NoDatabaseError
|
59
|
+
end
|
60
|
+
|
45
61
|
def register_task(pattern, task)
|
46
62
|
@tasks ||= {}
|
47
63
|
@tasks[pattern] = task
|
@@ -91,15 +107,21 @@ module ActiveRecord
|
|
91
107
|
def create(*arguments)
|
92
108
|
configuration = arguments.first
|
93
109
|
class_for_adapter(configuration['adapter']).new(*arguments).create
|
110
|
+
$stdout.puts "Created database '#{configuration['database']}'"
|
94
111
|
rescue DatabaseAlreadyExists
|
95
|
-
$stderr.puts "#{configuration['database']} already exists"
|
112
|
+
$stderr.puts "Database '#{configuration['database']}' already exists"
|
96
113
|
rescue Exception => error
|
97
|
-
$stderr.puts error
|
114
|
+
$stderr.puts error
|
98
115
|
$stderr.puts "Couldn't create database for #{configuration.inspect}"
|
116
|
+
raise
|
99
117
|
end
|
100
118
|
|
101
119
|
def create_all
|
120
|
+
old_pool = ActiveRecord::Base.connection_handler.retrieve_connection_pool(ActiveRecord::Base.connection_specification_name)
|
102
121
|
each_local_configuration { |configuration| create configuration }
|
122
|
+
if old_pool
|
123
|
+
ActiveRecord::Base.connection_handler.establish_connection(old_pool.spec)
|
124
|
+
end
|
103
125
|
end
|
104
126
|
|
105
127
|
def create_current(environment = env)
|
@@ -112,11 +134,13 @@ module ActiveRecord
|
|
112
134
|
def drop(*arguments)
|
113
135
|
configuration = arguments.first
|
114
136
|
class_for_adapter(configuration['adapter']).new(*arguments).drop
|
137
|
+
$stdout.puts "Dropped database '#{configuration['database']}'"
|
115
138
|
rescue ActiveRecord::NoDatabaseError
|
116
139
|
$stderr.puts "Database '#{configuration['database']}' does not exist"
|
117
140
|
rescue Exception => error
|
118
|
-
$stderr.puts error
|
119
|
-
$stderr.puts "Couldn't drop #{configuration['database']}"
|
141
|
+
$stderr.puts error
|
142
|
+
$stderr.puts "Couldn't drop database '#{configuration['database']}'"
|
143
|
+
raise
|
120
144
|
end
|
121
145
|
|
122
146
|
def drop_all
|
@@ -134,9 +158,10 @@ module ActiveRecord
|
|
134
158
|
version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil
|
135
159
|
scope = ENV['SCOPE']
|
136
160
|
verbose_was, Migration.verbose = Migration.verbose, verbose
|
137
|
-
Migrator.migrate(
|
161
|
+
Migrator.migrate(migrations_paths, version) do |migration|
|
138
162
|
scope.blank? || scope == migration.scope
|
139
163
|
end
|
164
|
+
ActiveRecord::Base.clear_cache!
|
140
165
|
ensure
|
141
166
|
Migration.verbose = verbose_was
|
142
167
|
end
|
@@ -188,27 +213,7 @@ module ActiveRecord
|
|
188
213
|
class_for_adapter(configuration['adapter']).new(*arguments).structure_load(filename)
|
189
214
|
end
|
190
215
|
|
191
|
-
def load_schema(format = ActiveRecord::Base.schema_format, file = nil)
|
192
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
193
|
-
This method will act on a specific connection in the future.
|
194
|
-
To act on the current connection, use `load_schema_current` instead.
|
195
|
-
MSG
|
196
|
-
|
197
|
-
load_schema_current(format, file)
|
198
|
-
end
|
199
|
-
|
200
|
-
def schema_file(format = ActiveSupport::Base.schema_format)
|
201
|
-
case format
|
202
|
-
when :ruby
|
203
|
-
File.join(db_dir, "schema.rb")
|
204
|
-
when :sql
|
205
|
-
File.join(db_dir, "structure.sql")
|
206
|
-
end
|
207
|
-
end
|
208
|
-
|
209
|
-
# This method is the successor of +load_schema+. We should rename it
|
210
|
-
# after +load_schema+ went through a deprecation cycle. (Rails > 4.2)
|
211
|
-
def load_schema_for(configuration, format = ActiveRecord::Base.schema_format, file = nil) # :nodoc:
|
216
|
+
def load_schema(configuration, format = ActiveRecord::Base.schema_format, file = nil) # :nodoc:
|
212
217
|
file ||= schema_file(format)
|
213
218
|
|
214
219
|
case format
|
@@ -222,24 +227,37 @@ module ActiveRecord
|
|
222
227
|
else
|
223
228
|
raise ArgumentError, "unknown format #{format.inspect}"
|
224
229
|
end
|
230
|
+
ActiveRecord::InternalMetadata.create_table
|
231
|
+
ActiveRecord::InternalMetadata[:environment] = ActiveRecord::Migrator.current_environment
|
225
232
|
end
|
226
233
|
|
227
|
-
def
|
228
|
-
|
229
|
-
|
234
|
+
def load_schema_for(*args)
|
235
|
+
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
236
|
+
This method was renamed to `#load_schema` and will be removed in the future.
|
237
|
+
Use `#load_schema` instead.
|
238
|
+
MSG
|
239
|
+
load_schema(*args)
|
240
|
+
end
|
241
|
+
|
242
|
+
def schema_file(format = ActiveRecord::Base.schema_format)
|
243
|
+
case format
|
244
|
+
when :ruby
|
245
|
+
File.join(db_dir, "schema.rb")
|
246
|
+
when :sql
|
247
|
+
File.join(db_dir, "structure.sql")
|
230
248
|
end
|
231
249
|
end
|
232
250
|
|
233
251
|
def load_schema_current(format = ActiveRecord::Base.schema_format, file = nil, environment = env)
|
234
252
|
each_current_configuration(environment) { |configuration|
|
235
|
-
|
253
|
+
load_schema configuration, format, file
|
236
254
|
}
|
237
255
|
ActiveRecord::Base.establish_connection(environment.to_sym)
|
238
256
|
end
|
239
257
|
|
240
258
|
def check_schema_file(filename)
|
241
259
|
unless File.exist?(filename)
|
242
|
-
message = %{#{filename} doesn't exist yet. Run `
|
260
|
+
message = %{#{filename} doesn't exist yet. Run `rails db:migrate` to create it, then try again.}
|
243
261
|
message << %{ 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.} if defined?(::Rails)
|
244
262
|
Kernel.abort message
|
245
263
|
end
|
@@ -267,8 +285,7 @@ module ActiveRecord
|
|
267
285
|
|
268
286
|
def each_current_configuration(environment)
|
269
287
|
environments = [environment]
|
270
|
-
|
271
|
-
environments << 'test' if environment == 'development' && ENV['RAILS_ENV'].nil?
|
288
|
+
environments << 'test' if environment == 'development'
|
272
289
|
|
273
290
|
configurations = ActiveRecord::Base.configurations.values_at(*environments)
|
274
291
|
configurations.compact.each do |configuration|
|
@@ -1,8 +1,6 @@
|
|
1
1
|
module ActiveRecord
|
2
2
|
module Tasks # :nodoc:
|
3
3
|
class MySQLDatabaseTasks # :nodoc:
|
4
|
-
DEFAULT_CHARSET = ENV['CHARSET'] || 'utf8'
|
5
|
-
DEFAULT_COLLATION = ENV['COLLATION'] || 'utf8_unicode_ci'
|
6
4
|
ACCESS_DENIED_ERROR = 1045
|
7
5
|
|
8
6
|
delegate :connection, :establish_connection, to: ActiveRecord::Base
|
@@ -23,7 +21,7 @@ module ActiveRecord
|
|
23
21
|
end
|
24
22
|
rescue error_class => error
|
25
23
|
if error.respond_to?(:errno) && error.errno == ACCESS_DENIED_ERROR
|
26
|
-
$stdout.print error.
|
24
|
+
$stdout.print error.message
|
27
25
|
establish_connection root_configuration_without_database
|
28
26
|
connection.create_database configuration['database'], creation_options
|
29
27
|
if configuration['username'] != 'root'
|
@@ -56,21 +54,21 @@ module ActiveRecord
|
|
56
54
|
end
|
57
55
|
|
58
56
|
def structure_dump(filename)
|
59
|
-
args = prepare_command_options
|
57
|
+
args = prepare_command_options
|
60
58
|
args.concat(["--result-file", "#{filename}"])
|
61
59
|
args.concat(["--no-data"])
|
60
|
+
args.concat(["--routines"])
|
62
61
|
args.concat(["#{configuration['database']}"])
|
63
|
-
|
64
|
-
|
65
|
-
"Make sure `mysqldump` is in your PATH and check the command output for warnings."
|
66
|
-
end
|
62
|
+
|
63
|
+
run_cmd('mysqldump', args, 'dumping')
|
67
64
|
end
|
68
65
|
|
69
66
|
def structure_load(filename)
|
70
|
-
args = prepare_command_options
|
67
|
+
args = prepare_command_options
|
71
68
|
args.concat(['--execute', %{SET FOREIGN_KEY_CHECKS = 0; SOURCE #{filename}; SET FOREIGN_KEY_CHECKS = 1}])
|
72
69
|
args.concat(["--database", "#{configuration['database']}"])
|
73
|
-
|
70
|
+
|
71
|
+
run_cmd('mysql', args, 'loading')
|
74
72
|
end
|
75
73
|
|
76
74
|
private
|
@@ -87,12 +85,6 @@ module ActiveRecord
|
|
87
85
|
Hash.new.tap do |options|
|
88
86
|
options[:charset] = configuration['encoding'] if configuration.include? 'encoding'
|
89
87
|
options[:collation] = configuration['collation'] if configuration.include? 'collation'
|
90
|
-
|
91
|
-
# Set default charset only when collation isn't set.
|
92
|
-
options[:charset] ||= DEFAULT_CHARSET unless options[:collation]
|
93
|
-
|
94
|
-
# Set default collation only when charset is also default.
|
95
|
-
options[:collation] ||= DEFAULT_COLLATION if options[:charset] == DEFAULT_CHARSET
|
96
88
|
end
|
97
89
|
end
|
98
90
|
|
@@ -102,8 +94,6 @@ module ActiveRecord
|
|
102
94
|
ArJdbcMySQL::Error
|
103
95
|
elsif defined?(Mysql2)
|
104
96
|
Mysql2::Error
|
105
|
-
elsif defined?(Mysql)
|
106
|
-
Mysql::Error
|
107
97
|
else
|
108
98
|
StandardError
|
109
99
|
end
|
@@ -129,17 +119,33 @@ IDENTIFIED BY '#{configuration['password']}' WITH GRANT OPTION;
|
|
129
119
|
$stdin.gets.strip
|
130
120
|
end
|
131
121
|
|
132
|
-
def prepare_command_options
|
133
|
-
args =
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
122
|
+
def prepare_command_options
|
123
|
+
args = {
|
124
|
+
'host' => '--host',
|
125
|
+
'port' => '--port',
|
126
|
+
'socket' => '--socket',
|
127
|
+
'username' => '--user',
|
128
|
+
'password' => '--password',
|
129
|
+
'encoding' => '--default-character-set',
|
130
|
+
'sslca' => '--ssl-ca',
|
131
|
+
'sslcert' => '--ssl-cert',
|
132
|
+
'sslcapath' => '--ssl-capath',
|
133
|
+
'sslcipher' => '--ssl-cipher',
|
134
|
+
'sslkey' => '--ssl-key'
|
135
|
+
}.map { |opt, arg| "#{arg}=#{configuration[opt]}" if configuration[opt] }.compact
|
140
136
|
|
141
137
|
args
|
142
138
|
end
|
139
|
+
|
140
|
+
def run_cmd(cmd, args, action)
|
141
|
+
fail run_cmd_error(cmd, args, action) unless Kernel.system(cmd, *args)
|
142
|
+
end
|
143
|
+
|
144
|
+
def run_cmd_error(cmd, args, action)
|
145
|
+
msg = "failed to execute: `#{cmd}`\n"
|
146
|
+
msg << "Please check the output above for any errors and make sure that `#{cmd}` is installed in your PATH and has proper permissions.\n\n"
|
147
|
+
msg
|
148
|
+
end
|
143
149
|
end
|
144
150
|
end
|
145
151
|
end
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'shellwords'
|
2
|
-
|
3
1
|
module ActiveRecord
|
4
2
|
module Tasks # :nodoc:
|
5
3
|
class PostgreSQLDatabaseTasks # :nodoc:
|
@@ -46,20 +44,31 @@ module ActiveRecord
|
|
46
44
|
|
47
45
|
def structure_dump(filename)
|
48
46
|
set_psql_env
|
49
|
-
search_path = configuration['schema_search_path']
|
50
|
-
unless search_path.blank?
|
51
|
-
search_path = search_path.split(",").map{|search_path_part| "--schema=#{Shellwords.escape(search_path_part.strip)}" }.join(" ")
|
52
|
-
end
|
53
47
|
|
54
|
-
|
55
|
-
|
48
|
+
search_path = case ActiveRecord::Base.dump_schemas
|
49
|
+
when :schema_search_path
|
50
|
+
configuration['schema_search_path']
|
51
|
+
when :all
|
52
|
+
nil
|
53
|
+
when String
|
54
|
+
ActiveRecord::Base.dump_schemas
|
55
|
+
end
|
56
56
|
|
57
|
+
args = ['-s', '-x', '-O', '-f', filename]
|
58
|
+
unless search_path.blank?
|
59
|
+
args += search_path.split(',').map do |part|
|
60
|
+
"--schema=#{part.strip}"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
args << configuration['database']
|
64
|
+
run_cmd('pg_dump', args, 'dumping')
|
57
65
|
File.open(filename, "a") { |f| f << "SET search_path TO #{connection.schema_search_path};\n\n" }
|
58
66
|
end
|
59
67
|
|
60
68
|
def structure_load(filename)
|
61
69
|
set_psql_env
|
62
|
-
|
70
|
+
args = [ '-q', '-f', filename, configuration['database'] ]
|
71
|
+
run_cmd('psql', args, 'loading' )
|
63
72
|
end
|
64
73
|
|
65
74
|
private
|
@@ -85,6 +94,17 @@ module ActiveRecord
|
|
85
94
|
ENV['PGPASSWORD'] = configuration['password'].to_s if configuration['password']
|
86
95
|
ENV['PGUSER'] = configuration['username'].to_s if configuration['username']
|
87
96
|
end
|
97
|
+
|
98
|
+
def run_cmd(cmd, args, action)
|
99
|
+
fail run_cmd_error(cmd, args, action) unless Kernel.system(cmd, *args)
|
100
|
+
end
|
101
|
+
|
102
|
+
def run_cmd_error(cmd, args, action)
|
103
|
+
msg = "failed to execute:\n"
|
104
|
+
msg << "#{cmd} #{args.join(' ')}\n\n"
|
105
|
+
msg << "Please check the output above for any errors and make sure that `#{cmd}` is installed in your PATH and has proper permissions.\n\n"
|
106
|
+
msg
|
107
|
+
end
|
88
108
|
end
|
89
109
|
end
|
90
110
|
end
|
@@ -19,11 +19,15 @@ module ActiveRecord
|
|
19
19
|
path = Pathname.new configuration['database']
|
20
20
|
file = path.absolute? ? path.to_s : File.join(root, path)
|
21
21
|
|
22
|
-
FileUtils.rm(file)
|
22
|
+
FileUtils.rm(file)
|
23
|
+
rescue Errno::ENOENT => error
|
24
|
+
raise NoDatabaseError.new(error.message, error)
|
23
25
|
end
|
24
26
|
|
25
27
|
def purge
|
26
28
|
drop
|
29
|
+
rescue NoDatabaseError
|
30
|
+
ensure
|
27
31
|
create
|
28
32
|
end
|
29
33
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module ActiveRecord
|
2
|
-
# = Active Record Timestamp
|
2
|
+
# = Active Record \Timestamp
|
3
3
|
#
|
4
4
|
# Active Record automatically timestamps create and update operations if the
|
5
5
|
# table has fields named <tt>created_at/created_on</tt> or
|
@@ -15,14 +15,25 @@ module ActiveRecord
|
|
15
15
|
#
|
16
16
|
# == Time Zone aware attributes
|
17
17
|
#
|
18
|
-
#
|
18
|
+
# Active Record keeps all the <tt>datetime</tt> and <tt>time</tt> columns
|
19
|
+
# timezone aware. By default, these values are stored in the database as UTC
|
20
|
+
# and converted back to the current <tt>Time.zone</tt> when pulled from the database.
|
19
21
|
#
|
20
|
-
#
|
22
|
+
# This feature can be turned off completely by setting:
|
21
23
|
#
|
22
|
-
#
|
24
|
+
# config.active_record.time_zone_aware_attributes = false
|
23
25
|
#
|
24
|
-
#
|
25
|
-
#
|
26
|
+
# You can also specify that only <tt>datetime</tt> columns should be time-zone
|
27
|
+
# aware (while <tt>time</tt> should not) by setting:
|
28
|
+
#
|
29
|
+
# ActiveRecord::Base.time_zone_aware_types = [:datetime]
|
30
|
+
#
|
31
|
+
# You can also add database specific timezone aware types. For example, for PostgreSQL:
|
32
|
+
#
|
33
|
+
# ActiveRecord::Base.time_zone_aware_types += [:tsrange, :tstzrange]
|
34
|
+
#
|
35
|
+
# Finally, you can indicate specific attributes of a model for which time zone
|
36
|
+
# conversion should not applied, for instance by setting:
|
26
37
|
#
|
27
38
|
# class Topic < ActiveRecord::Base
|
28
39
|
# self.skip_time_zone_conversion_for_attributes = [:written_on]
|
@@ -57,8 +68,8 @@ module ActiveRecord
|
|
57
68
|
super
|
58
69
|
end
|
59
70
|
|
60
|
-
def _update_record(*args)
|
61
|
-
if should_record_timestamps?
|
71
|
+
def _update_record(*args, touch: true, **options)
|
72
|
+
if touch && should_record_timestamps?
|
62
73
|
current_time = current_time_from_proper_timezone
|
63
74
|
|
64
75
|
timestamp_attributes_for_update_in_model.each do |column|
|
@@ -67,7 +78,7 @@ module ActiveRecord
|
|
67
78
|
write_attribute(column, current_time)
|
68
79
|
end
|
69
80
|
end
|
70
|
-
super
|
81
|
+
super(*args)
|
71
82
|
end
|
72
83
|
|
73
84
|
def should_record_timestamps?
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
# = Active Record Touch Later
|
3
|
+
module TouchLater
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
before_commit_without_transaction_enrollment :touch_deferred_attributes
|
8
|
+
end
|
9
|
+
|
10
|
+
def touch_later(*names) # :nodoc:
|
11
|
+
raise ActiveRecordError, "cannot touch on a new record object" unless persisted?
|
12
|
+
|
13
|
+
@_defer_touch_attrs ||= timestamp_attributes_for_update_in_model
|
14
|
+
@_defer_touch_attrs |= names
|
15
|
+
@_touch_time = current_time_from_proper_timezone
|
16
|
+
|
17
|
+
surreptitiously_touch @_defer_touch_attrs
|
18
|
+
self.class.connection.add_transaction_record self
|
19
|
+
|
20
|
+
# touch the parents as we are not calling the after_save callbacks
|
21
|
+
self.class.reflect_on_all_associations(:belongs_to).each do |r|
|
22
|
+
if touch = r.options[:touch]
|
23
|
+
ActiveRecord::Associations::Builder::BelongsTo.touch_record(self, r.foreign_key, r.name, touch, :touch_later)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def touch(*names, time: nil) # :nodoc:
|
29
|
+
if has_defer_touch_attrs?
|
30
|
+
names |= @_defer_touch_attrs
|
31
|
+
end
|
32
|
+
super(*names, time: time)
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def surreptitiously_touch(attrs)
|
38
|
+
attrs.each { |attr| write_attribute attr, @_touch_time }
|
39
|
+
clear_attribute_changes attrs
|
40
|
+
end
|
41
|
+
|
42
|
+
def touch_deferred_attributes
|
43
|
+
if has_defer_touch_attrs? && persisted?
|
44
|
+
touch(*@_defer_touch_attrs, time: @_touch_time)
|
45
|
+
@_defer_touch_attrs, @_touch_time = nil, nil
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def has_defer_touch_attrs?
|
50
|
+
defined?(@_defer_touch_attrs) && @_defer_touch_attrs.present?
|
51
|
+
end
|
52
|
+
|
53
|
+
def belongs_to_touch_method
|
54
|
+
:touch_later
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|