activerecord 4.1.15 → 4.2.11.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/CHANGELOG.md +1162 -1792
- data/README.rdoc +15 -10
- data/lib/active_record.rb +4 -0
- data/lib/active_record/aggregations.rb +15 -8
- data/lib/active_record/association_relation.rb +13 -0
- data/lib/active_record/associations.rb +158 -49
- data/lib/active_record/associations/alias_tracker.rb +3 -12
- data/lib/active_record/associations/association.rb +16 -4
- data/lib/active_record/associations/association_scope.rb +83 -38
- data/lib/active_record/associations/belongs_to_association.rb +28 -10
- data/lib/active_record/associations/builder/association.rb +15 -4
- data/lib/active_record/associations/builder/belongs_to.rb +7 -29
- data/lib/active_record/associations/builder/collection_association.rb +5 -1
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +8 -13
- data/lib/active_record/associations/builder/has_many.rb +1 -1
- data/lib/active_record/associations/builder/has_one.rb +2 -2
- data/lib/active_record/associations/builder/singular_association.rb +8 -1
- data/lib/active_record/associations/collection_association.rb +63 -27
- data/lib/active_record/associations/collection_proxy.rb +29 -35
- data/lib/active_record/associations/foreign_association.rb +11 -0
- data/lib/active_record/associations/has_many_association.rb +83 -22
- data/lib/active_record/associations/has_many_through_association.rb +49 -26
- data/lib/active_record/associations/has_one_association.rb +1 -1
- data/lib/active_record/associations/join_dependency.rb +26 -13
- data/lib/active_record/associations/join_dependency/join_association.rb +25 -15
- data/lib/active_record/associations/join_dependency/join_part.rb +0 -1
- data/lib/active_record/associations/preloader.rb +36 -26
- data/lib/active_record/associations/preloader/association.rb +14 -11
- data/lib/active_record/associations/preloader/through_association.rb +4 -3
- data/lib/active_record/associations/singular_association.rb +17 -2
- data/lib/active_record/associations/through_association.rb +5 -12
- data/lib/active_record/attribute.rb +163 -0
- data/lib/active_record/attribute_assignment.rb +19 -11
- data/lib/active_record/attribute_decorators.rb +66 -0
- data/lib/active_record/attribute_methods.rb +56 -94
- data/lib/active_record/attribute_methods/before_type_cast.rb +7 -2
- data/lib/active_record/attribute_methods/dirty.rb +107 -43
- data/lib/active_record/attribute_methods/primary_key.rb +7 -8
- data/lib/active_record/attribute_methods/query.rb +1 -1
- data/lib/active_record/attribute_methods/read.rb +22 -59
- data/lib/active_record/attribute_methods/serialization.rb +16 -150
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +38 -40
- data/lib/active_record/attribute_methods/write.rb +9 -24
- data/lib/active_record/attribute_set.rb +81 -0
- data/lib/active_record/attribute_set/builder.rb +106 -0
- data/lib/active_record/attributes.rb +147 -0
- data/lib/active_record/autosave_association.rb +19 -12
- data/lib/active_record/base.rb +13 -24
- data/lib/active_record/callbacks.rb +6 -6
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +84 -52
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +52 -50
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/quoting.rb +60 -60
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +39 -4
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +138 -56
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +14 -34
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +268 -71
- data/lib/active_record/connection_adapters/abstract/transaction.rb +125 -118
- data/lib/active_record/connection_adapters/abstract_adapter.rb +171 -59
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +293 -139
- data/lib/active_record/connection_adapters/column.rb +29 -240
- data/lib/active_record/connection_adapters/connection_specification.rb +15 -24
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +16 -32
- data/lib/active_record/connection_adapters/mysql_adapter.rb +67 -144
- data/lib/active_record/connection_adapters/postgresql/array_parser.rb +15 -27
- data/lib/active_record/connection_adapters/postgresql/column.rb +20 -0
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +40 -25
- data/lib/active_record/connection_adapters/postgresql/oid.rb +29 -388
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +100 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +52 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +13 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +46 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +11 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +36 -0
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +13 -0
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +19 -0
- data/lib/active_record/connection_adapters/postgresql/oid/float.rb +21 -0
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +59 -0
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +13 -0
- data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +13 -0
- data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +11 -0
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +35 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +23 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +43 -0
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +43 -0
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +79 -0
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +19 -0
- data/lib/active_record/connection_adapters/postgresql/oid/time.rb +11 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +109 -0
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +21 -0
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +26 -0
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +28 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +46 -136
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +152 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +131 -43
- data/lib/active_record/connection_adapters/postgresql/utils.rb +77 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +224 -477
- data/lib/active_record/connection_adapters/schema_cache.rb +14 -28
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +61 -75
- data/lib/active_record/connection_handling.rb +1 -1
- data/lib/active_record/core.rb +163 -39
- data/lib/active_record/counter_cache.rb +60 -6
- data/lib/active_record/enum.rb +9 -11
- data/lib/active_record/errors.rb +53 -30
- data/lib/active_record/explain.rb +1 -1
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixtures.rb +55 -69
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +35 -10
- data/lib/active_record/integration.rb +4 -4
- data/lib/active_record/legacy_yaml_adapter.rb +30 -0
- data/lib/active_record/locking/optimistic.rb +46 -26
- data/lib/active_record/migration.rb +71 -46
- data/lib/active_record/migration/command_recorder.rb +19 -2
- data/lib/active_record/migration/join_table.rb +1 -1
- data/lib/active_record/model_schema.rb +52 -58
- data/lib/active_record/nested_attributes.rb +5 -5
- data/lib/active_record/no_touching.rb +1 -1
- data/lib/active_record/persistence.rb +46 -26
- data/lib/active_record/query_cache.rb +3 -3
- data/lib/active_record/querying.rb +10 -7
- data/lib/active_record/railtie.rb +18 -11
- data/lib/active_record/railties/databases.rake +50 -51
- data/lib/active_record/readonly_attributes.rb +0 -1
- data/lib/active_record/reflection.rb +273 -114
- data/lib/active_record/relation.rb +57 -25
- data/lib/active_record/relation/batches.rb +0 -2
- data/lib/active_record/relation/calculations.rb +41 -37
- data/lib/active_record/relation/finder_methods.rb +70 -47
- data/lib/active_record/relation/merger.rb +39 -29
- data/lib/active_record/relation/predicate_builder.rb +16 -8
- data/lib/active_record/relation/predicate_builder/array_handler.rb +32 -13
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -5
- data/lib/active_record/relation/query_methods.rb +114 -65
- data/lib/active_record/relation/spawn_methods.rb +3 -0
- data/lib/active_record/result.rb +18 -7
- data/lib/active_record/sanitization.rb +12 -2
- data/lib/active_record/schema.rb +0 -1
- data/lib/active_record/schema_dumper.rb +59 -28
- data/lib/active_record/schema_migration.rb +5 -4
- data/lib/active_record/scoping/default.rb +6 -4
- data/lib/active_record/scoping/named.rb +4 -0
- data/lib/active_record/serializers/xml_serializer.rb +3 -7
- data/lib/active_record/statement_cache.rb +95 -10
- data/lib/active_record/store.rb +5 -5
- data/lib/active_record/tasks/database_tasks.rb +61 -6
- data/lib/active_record/tasks/mysql_database_tasks.rb +32 -17
- data/lib/active_record/tasks/postgresql_database_tasks.rb +20 -9
- data/lib/active_record/timestamp.rb +9 -7
- data/lib/active_record/transactions.rb +53 -27
- data/lib/active_record/type.rb +23 -0
- data/lib/active_record/type/big_integer.rb +13 -0
- data/lib/active_record/type/binary.rb +50 -0
- data/lib/active_record/type/boolean.rb +31 -0
- data/lib/active_record/type/date.rb +50 -0
- data/lib/active_record/type/date_time.rb +54 -0
- data/lib/active_record/type/decimal.rb +64 -0
- data/lib/active_record/type/decimal_without_scale.rb +11 -0
- data/lib/active_record/type/decorator.rb +14 -0
- data/lib/active_record/type/float.rb +19 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +23 -0
- data/lib/active_record/type/integer.rb +59 -0
- data/lib/active_record/type/mutable.rb +16 -0
- data/lib/active_record/type/numeric.rb +36 -0
- data/lib/active_record/type/serialized.rb +62 -0
- data/lib/active_record/type/string.rb +40 -0
- data/lib/active_record/type/text.rb +11 -0
- data/lib/active_record/type/time.rb +26 -0
- data/lib/active_record/type/time_value.rb +38 -0
- data/lib/active_record/type/type_map.rb +64 -0
- data/lib/active_record/type/unsigned_integer.rb +15 -0
- data/lib/active_record/type/value.rb +110 -0
- data/lib/active_record/validations.rb +25 -19
- data/lib/active_record/validations/associated.rb +5 -3
- data/lib/active_record/validations/presence.rb +5 -3
- data/lib/active_record/validations/uniqueness.rb +25 -29
- data/lib/rails/generators/active_record/migration/migration_generator.rb +8 -4
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +1 -1
- data/lib/rails/generators/active_record/model/templates/model.rb +1 -1
- metadata +66 -11
- data/lib/active_record/connection_adapters/postgresql/cast.rb +0 -168
data/lib/active_record/store.rb
CHANGED
@@ -99,7 +99,7 @@ module ActiveRecord
|
|
99
99
|
self.local_stored_attributes[store_attribute] |= keys
|
100
100
|
end
|
101
101
|
|
102
|
-
def _store_accessors_module
|
102
|
+
def _store_accessors_module # :nodoc:
|
103
103
|
@_store_accessors_module ||= begin
|
104
104
|
mod = Module.new
|
105
105
|
include mod
|
@@ -129,10 +129,10 @@ module ActiveRecord
|
|
129
129
|
|
130
130
|
private
|
131
131
|
def store_accessor_for(store_attribute)
|
132
|
-
|
132
|
+
type_for_attribute(store_attribute.to_s).accessor
|
133
133
|
end
|
134
134
|
|
135
|
-
class HashAccessor
|
135
|
+
class HashAccessor # :nodoc:
|
136
136
|
def self.read(object, attribute, key)
|
137
137
|
prepare(object, attribute)
|
138
138
|
object.public_send(attribute)[key]
|
@@ -151,7 +151,7 @@ module ActiveRecord
|
|
151
151
|
end
|
152
152
|
end
|
153
153
|
|
154
|
-
class StringKeyedHashAccessor < HashAccessor
|
154
|
+
class StringKeyedHashAccessor < HashAccessor # :nodoc:
|
155
155
|
def self.read(object, attribute, key)
|
156
156
|
super object, attribute, key.to_s
|
157
157
|
end
|
@@ -161,7 +161,7 @@ module ActiveRecord
|
|
161
161
|
end
|
162
162
|
end
|
163
163
|
|
164
|
-
class IndifferentHashAccessor < ActiveRecord::Store::HashAccessor
|
164
|
+
class IndifferentHashAccessor < ActiveRecord::Store::HashAccessor # :nodoc:
|
165
165
|
def self.prepare(object, store_attribute)
|
166
166
|
attribute = object.send(store_attribute)
|
167
167
|
unless attribute.is_a?(ActiveSupport::HashWithIndifferentAccess)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'active_support/core_ext/string/filters'
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module Tasks # :nodoc:
|
3
5
|
class DatabaseAlreadyExists < StandardError; end # :nodoc:
|
@@ -6,7 +8,7 @@ module ActiveRecord
|
|
6
8
|
# <tt>ActiveRecord::Tasks::DatabaseTasks</tt> is a utility class, which encapsulates
|
7
9
|
# logic behind common tasks used to manage database and migrations.
|
8
10
|
#
|
9
|
-
# The tasks defined here are used
|
11
|
+
# The tasks defined here are used with Rake tasks provided by Active Record.
|
10
12
|
#
|
11
13
|
# In order to use DatabaseTasks, a few config values need to be set. All the needed
|
12
14
|
# config values are set by Rails already, so it's necessary to do it only if you
|
@@ -14,7 +16,6 @@ module ActiveRecord
|
|
14
16
|
# (in such case after configuring the database tasks, you can also use the rake tasks
|
15
17
|
# defined in Active Record).
|
16
18
|
#
|
17
|
-
#
|
18
19
|
# The possible config values are:
|
19
20
|
#
|
20
21
|
# * +env+: current environment (like Rails.env).
|
@@ -28,7 +29,7 @@ module ActiveRecord
|
|
28
29
|
# Example usage of +DatabaseTasks+ outside Rails could look as such:
|
29
30
|
#
|
30
31
|
# include ActiveRecord::Tasks
|
31
|
-
# DatabaseTasks.database_configuration = YAML.
|
32
|
+
# DatabaseTasks.database_configuration = YAML.load_file('my_database_config.yml')
|
32
33
|
# DatabaseTasks.db_dir = 'db'
|
33
34
|
# # other settings...
|
34
35
|
#
|
@@ -59,7 +60,11 @@ module ActiveRecord
|
|
59
60
|
end
|
60
61
|
|
61
62
|
def fixtures_path
|
62
|
-
@fixtures_path ||=
|
63
|
+
@fixtures_path ||= if ENV['FIXTURES_PATH']
|
64
|
+
File.join(root, ENV['FIXTURES_PATH'])
|
65
|
+
else
|
66
|
+
File.join(root, 'test', 'fixtures')
|
67
|
+
end
|
63
68
|
end
|
64
69
|
|
65
70
|
def root
|
@@ -107,6 +112,8 @@ module ActiveRecord
|
|
107
112
|
def drop(*arguments)
|
108
113
|
configuration = arguments.first
|
109
114
|
class_for_adapter(configuration['adapter']).new(*arguments).drop
|
115
|
+
rescue ActiveRecord::NoDatabaseError
|
116
|
+
$stderr.puts "Database '#{configuration['database']}' does not exist"
|
110
117
|
rescue Exception => error
|
111
118
|
$stderr.puts error, *(error.backtrace)
|
112
119
|
$stderr.puts "Couldn't drop #{configuration['database']}"
|
@@ -122,6 +129,21 @@ module ActiveRecord
|
|
122
129
|
}
|
123
130
|
end
|
124
131
|
|
132
|
+
def migrate
|
133
|
+
raise "Empty VERSION provided" if ENV["VERSION"] && ENV["VERSION"].empty?
|
134
|
+
|
135
|
+
verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true
|
136
|
+
version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil
|
137
|
+
scope = ENV['SCOPE']
|
138
|
+
verbose_was, Migration.verbose = Migration.verbose, verbose
|
139
|
+
Migrator.migrate(migrations_paths, version) do |migration|
|
140
|
+
scope.blank? || scope == migration.scope
|
141
|
+
end
|
142
|
+
ActiveRecord::Base.clear_cache!
|
143
|
+
ensure
|
144
|
+
Migration.verbose = verbose_was
|
145
|
+
end
|
146
|
+
|
125
147
|
def charset_current(environment = env)
|
126
148
|
charset ActiveRecord::Base.configurations[environment]
|
127
149
|
end
|
@@ -144,6 +166,19 @@ module ActiveRecord
|
|
144
166
|
class_for_adapter(configuration['adapter']).new(configuration).purge
|
145
167
|
end
|
146
168
|
|
169
|
+
def purge_all
|
170
|
+
each_local_configuration { |configuration|
|
171
|
+
purge configuration
|
172
|
+
}
|
173
|
+
end
|
174
|
+
|
175
|
+
def purge_current(environment = env)
|
176
|
+
each_current_configuration(environment) { |configuration|
|
177
|
+
purge configuration
|
178
|
+
}
|
179
|
+
ActiveRecord::Base.establish_connection(environment.to_sym)
|
180
|
+
end
|
181
|
+
|
147
182
|
def structure_dump(*arguments)
|
148
183
|
configuration = arguments.first
|
149
184
|
filename = arguments.delete_at 1
|
@@ -157,20 +192,34 @@ module ActiveRecord
|
|
157
192
|
end
|
158
193
|
|
159
194
|
def load_schema(format = ActiveRecord::Base.schema_format, file = nil)
|
195
|
+
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
196
|
+
This method will act on a specific connection in the future.
|
197
|
+
To act on the current connection, use `load_schema_current` instead.
|
198
|
+
MSG
|
199
|
+
|
160
200
|
load_schema_current(format, file)
|
161
201
|
end
|
162
202
|
|
203
|
+
def schema_file(format = ActiveRecord::Base.schema_format)
|
204
|
+
case format
|
205
|
+
when :ruby
|
206
|
+
File.join(db_dir, "schema.rb")
|
207
|
+
when :sql
|
208
|
+
File.join(db_dir, "structure.sql")
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
163
212
|
# This method is the successor of +load_schema+. We should rename it
|
164
213
|
# after +load_schema+ went through a deprecation cycle. (Rails > 4.2)
|
165
214
|
def load_schema_for(configuration, format = ActiveRecord::Base.schema_format, file = nil) # :nodoc:
|
215
|
+
file ||= schema_file(format)
|
216
|
+
|
166
217
|
case format
|
167
218
|
when :ruby
|
168
|
-
file ||= File.join(db_dir, "schema.rb")
|
169
219
|
check_schema_file(file)
|
170
220
|
ActiveRecord::Base.establish_connection(configuration)
|
171
221
|
load(file)
|
172
222
|
when :sql
|
173
|
-
file ||= File.join(db_dir, "structure.sql")
|
174
223
|
check_schema_file(file)
|
175
224
|
structure_load(configuration, file)
|
176
225
|
else
|
@@ -178,6 +227,12 @@ module ActiveRecord
|
|
178
227
|
end
|
179
228
|
end
|
180
229
|
|
230
|
+
def load_schema_current_if_exists(format = ActiveRecord::Base.schema_format, file = nil, environment = env)
|
231
|
+
if File.exist?(file || schema_file(format))
|
232
|
+
load_schema_current(format, file, environment)
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
181
236
|
def load_schema_current(format = ActiveRecord::Base.schema_format, file = nil, environment = env)
|
182
237
|
each_current_configuration(environment) { |configuration|
|
183
238
|
load_schema_for configuration, format, file
|
@@ -31,6 +31,7 @@ module ActiveRecord
|
|
31
31
|
end
|
32
32
|
establish_connection configuration
|
33
33
|
else
|
34
|
+
$stderr.puts error.inspect
|
34
35
|
$stderr.puts "Couldn't create database for #{configuration.inspect}, #{creation_options.inspect}"
|
35
36
|
$stderr.puts "(If you set the charset manually, make sure you have a matching collation)" if configuration['encoding']
|
36
37
|
end
|
@@ -55,21 +56,20 @@ module ActiveRecord
|
|
55
56
|
end
|
56
57
|
|
57
58
|
def structure_dump(filename)
|
58
|
-
args = prepare_command_options
|
59
|
+
args = prepare_command_options
|
59
60
|
args.concat(["--result-file", "#{filename}"])
|
60
61
|
args.concat(["--no-data"])
|
61
62
|
args.concat(["#{configuration['database']}"])
|
62
|
-
|
63
|
-
|
64
|
-
"Make sure `mysqldump` is in your PATH and check the command output for warnings."
|
65
|
-
end
|
63
|
+
|
64
|
+
run_cmd('mysqldump', args, 'dumping')
|
66
65
|
end
|
67
66
|
|
68
67
|
def structure_load(filename)
|
69
|
-
args = prepare_command_options
|
68
|
+
args = prepare_command_options
|
70
69
|
args.concat(['--execute', %{SET FOREIGN_KEY_CHECKS = 0; SOURCE #{filename}; SET FOREIGN_KEY_CHECKS = 1}])
|
71
70
|
args.concat(["--database", "#{configuration['database']}"])
|
72
|
-
|
71
|
+
|
72
|
+
run_cmd('mysql', args, 'loading')
|
73
73
|
end
|
74
74
|
|
75
75
|
private
|
@@ -124,20 +124,35 @@ IDENTIFIED BY '#{configuration['password']}' WITH GRANT OPTION;
|
|
124
124
|
end
|
125
125
|
|
126
126
|
def root_password
|
127
|
-
$stdout.print "Please provide the root password for your
|
127
|
+
$stdout.print "Please provide the root password for your MySQL installation\n>"
|
128
128
|
$stdin.gets.strip
|
129
129
|
end
|
130
130
|
|
131
|
-
def prepare_command_options
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
131
|
+
def prepare_command_options
|
132
|
+
{
|
133
|
+
'host' => '--host',
|
134
|
+
'port' => '--port',
|
135
|
+
'socket' => '--socket',
|
136
|
+
'username' => '--user',
|
137
|
+
'password' => '--password',
|
138
|
+
'encoding' => '--default-character-set',
|
139
|
+
'sslca' => '--ssl-ca',
|
140
|
+
'sslcert' => '--ssl-cert',
|
141
|
+
'sslcapath' => '--ssl-capath',
|
142
|
+
'sslcipher' => '--ssl-cipher',
|
143
|
+
'sslkey' => '--ssl-key'
|
144
|
+
}.map { |opt, arg| "#{arg}=#{configuration[opt]}" if configuration[opt] }.compact
|
145
|
+
end
|
146
|
+
|
147
|
+
def run_cmd(cmd, args, action)
|
148
|
+
fail run_cmd_error(cmd, args, action) unless Kernel.system(cmd, *args)
|
149
|
+
end
|
139
150
|
|
140
|
-
|
151
|
+
def run_cmd_error(cmd, args, action)
|
152
|
+
msg = "failed to execute:\n"
|
153
|
+
msg << "#{cmd}"
|
154
|
+
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"
|
155
|
+
msg
|
141
156
|
end
|
142
157
|
end
|
143
158
|
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,22 @@ module ActiveRecord
|
|
46
44
|
|
47
45
|
def structure_dump(filename)
|
48
46
|
set_psql_env
|
47
|
+
args = ['-s', '-x', '-O', '-f', filename]
|
49
48
|
search_path = configuration['schema_search_path']
|
50
49
|
unless search_path.blank?
|
51
|
-
|
50
|
+
args += search_path.split(',').map do |part|
|
51
|
+
"--schema=#{part.strip}"
|
52
|
+
end
|
52
53
|
end
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
File.open(filename, "a") { |f| f << "SET search_path TO #{ActiveRecord::Base.connection.schema_search_path};\n\n" }
|
54
|
+
args << configuration['database']
|
55
|
+
run_cmd('pg_dump', args, 'dumping')
|
56
|
+
File.open(filename, "a") { |f| f << "SET search_path TO #{connection.schema_search_path};\n\n" }
|
58
57
|
end
|
59
58
|
|
60
59
|
def structure_load(filename)
|
61
60
|
set_psql_env
|
62
|
-
|
61
|
+
args = [ '-q', '-f', filename, configuration['database'] ]
|
62
|
+
run_cmd('psql', args, 'loading')
|
63
63
|
end
|
64
64
|
|
65
65
|
private
|
@@ -85,6 +85,17 @@ module ActiveRecord
|
|
85
85
|
ENV['PGPASSWORD'] = configuration['password'].to_s if configuration['password']
|
86
86
|
ENV['PGUSER'] = configuration['username'].to_s if configuration['username']
|
87
87
|
end
|
88
|
+
|
89
|
+
def run_cmd(cmd, args, action)
|
90
|
+
fail run_cmd_error(cmd, args, action) unless Kernel.system(cmd, *args)
|
91
|
+
end
|
92
|
+
|
93
|
+
def run_cmd_error(cmd, args, action)
|
94
|
+
msg = "failed to execute:\n"
|
95
|
+
msg << "#{cmd} #{args.join(' ')}\n\n"
|
96
|
+
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"
|
97
|
+
msg
|
98
|
+
end
|
88
99
|
end
|
89
100
|
end
|
90
101
|
end
|
@@ -1,4 +1,3 @@
|
|
1
|
-
|
2
1
|
module ActiveRecord
|
3
2
|
# = Active Record Timestamp
|
4
3
|
#
|
@@ -48,8 +47,9 @@ module ActiveRecord
|
|
48
47
|
current_time = current_time_from_proper_timezone
|
49
48
|
|
50
49
|
all_timestamp_attributes.each do |column|
|
51
|
-
|
52
|
-
|
50
|
+
column = column.to_s
|
51
|
+
if has_attribute?(column) && !attribute_present?(column)
|
52
|
+
write_attribute(column, current_time)
|
53
53
|
end
|
54
54
|
end
|
55
55
|
end
|
@@ -99,9 +99,11 @@ module ActiveRecord
|
|
99
99
|
end
|
100
100
|
|
101
101
|
def max_updated_column_timestamp(timestamp_names = timestamp_attributes_for_update)
|
102
|
-
|
103
|
-
|
104
|
-
|
102
|
+
timestamp_names
|
103
|
+
.map { |attr| self[attr] }
|
104
|
+
.compact
|
105
|
+
.map(&:to_time)
|
106
|
+
.max
|
105
107
|
end
|
106
108
|
|
107
109
|
def current_time_from_proper_timezone
|
@@ -112,7 +114,7 @@ module ActiveRecord
|
|
112
114
|
def clear_timestamp_attributes
|
113
115
|
all_timestamp_attributes_in_model.each do |attribute_name|
|
114
116
|
self[attribute_name] = nil
|
115
|
-
|
117
|
+
clear_attribute_changes([attribute_name])
|
116
118
|
end
|
117
119
|
end
|
118
120
|
end
|
@@ -1,15 +1,27 @@
|
|
1
|
-
require 'thread'
|
2
|
-
|
3
1
|
module ActiveRecord
|
4
2
|
# See ActiveRecord::Transactions::ClassMethods for documentation.
|
5
3
|
module Transactions
|
6
4
|
extend ActiveSupport::Concern
|
5
|
+
#:nodoc:
|
7
6
|
ACTIONS = [:create, :destroy, :update]
|
7
|
+
#:nodoc:
|
8
|
+
CALLBACK_WARN_MESSAGE = "Currently, Active Record suppresses errors raised " \
|
9
|
+
"within `after_rollback`/`after_commit` callbacks and only print them to " \
|
10
|
+
"the logs. In the next version, these errors will no longer be suppressed. " \
|
11
|
+
"Instead, the errors will propagate normally just like in other Active " \
|
12
|
+
"Record callbacks.\n" \
|
13
|
+
"\n" \
|
14
|
+
"You can opt into the new behavior and remove this warning by setting:\n" \
|
15
|
+
"\n" \
|
16
|
+
" config.active_record.raise_in_transactional_callbacks = true\n\n"
|
8
17
|
|
9
18
|
included do
|
10
19
|
define_callbacks :commit, :rollback,
|
11
20
|
terminator: ->(_, result) { result == false },
|
12
21
|
scope: [:kind, :name]
|
22
|
+
|
23
|
+
mattr_accessor :raise_in_transactional_callbacks, instance_writer: false
|
24
|
+
self.raise_in_transactional_callbacks = false
|
13
25
|
end
|
14
26
|
|
15
27
|
# = Active Record Transactions
|
@@ -225,6 +237,9 @@ module ActiveRecord
|
|
225
237
|
def after_commit(*args, &block)
|
226
238
|
set_options_for_callbacks!(args)
|
227
239
|
set_callback(:commit, :after, *args, &block)
|
240
|
+
unless ActiveRecord::Base.raise_in_transactional_callbacks
|
241
|
+
ActiveSupport::Deprecation.warn(CALLBACK_WARN_MESSAGE)
|
242
|
+
end
|
228
243
|
end
|
229
244
|
|
230
245
|
# This callback is called after a create, update, or destroy are rolled back.
|
@@ -233,6 +248,9 @@ module ActiveRecord
|
|
233
248
|
def after_rollback(*args, &block)
|
234
249
|
set_options_for_callbacks!(args)
|
235
250
|
set_callback(:rollback, :after, *args, &block)
|
251
|
+
unless ActiveRecord::Base.raise_in_transactional_callbacks
|
252
|
+
ActiveSupport::Deprecation.warn(CALLBACK_WARN_MESSAGE)
|
253
|
+
end
|
236
254
|
end
|
237
255
|
|
238
256
|
private
|
@@ -292,16 +310,16 @@ module ActiveRecord
|
|
292
310
|
#
|
293
311
|
# Ensure that it is not called if the object was never persisted (failed create),
|
294
312
|
# but call it after the commit of a destroyed object.
|
295
|
-
def committed! #:nodoc:
|
296
|
-
|
313
|
+
def committed!(should_run_callbacks = true) #:nodoc:
|
314
|
+
_run_commit_callbacks if should_run_callbacks && destroyed? || persisted?
|
297
315
|
ensure
|
298
|
-
|
316
|
+
force_clear_transaction_record_state
|
299
317
|
end
|
300
318
|
|
301
319
|
# Call the +after_rollback+ callbacks. The +force_restore_state+ argument indicates if the record
|
302
320
|
# state should be rolled back to the beginning or just to the last savepoint.
|
303
|
-
def rolledback!(force_restore_state = false) #:nodoc:
|
304
|
-
|
321
|
+
def rolledback!(force_restore_state = false, should_run_callbacks = true) #:nodoc:
|
322
|
+
_run_rollback_callbacks if should_run_callbacks
|
305
323
|
ensure
|
306
324
|
restore_transaction_record_state(force_restore_state)
|
307
325
|
clear_transaction_record_state
|
@@ -310,9 +328,13 @@ module ActiveRecord
|
|
310
328
|
# Add the record to the current transaction so that the +after_rollback+ and +after_commit+ callbacks
|
311
329
|
# can be called.
|
312
330
|
def add_to_transaction
|
313
|
-
if
|
314
|
-
|
331
|
+
if has_transactional_callbacks?
|
332
|
+
self.class.connection.add_transaction_record(self)
|
333
|
+
else
|
334
|
+
sync_with_transaction_state
|
335
|
+
set_transaction_state(self.class.connection.transaction_state)
|
315
336
|
end
|
337
|
+
remember_transaction_record_state
|
316
338
|
end
|
317
339
|
|
318
340
|
# Executes +method+ within a transaction and captures its return value as a
|
@@ -328,34 +350,41 @@ module ActiveRecord
|
|
328
350
|
begin
|
329
351
|
status = yield
|
330
352
|
rescue ActiveRecord::Rollback
|
331
|
-
|
353
|
+
clear_transaction_record_state
|
332
354
|
status = nil
|
333
355
|
end
|
334
356
|
|
335
357
|
raise ActiveRecord::Rollback unless status
|
336
358
|
end
|
337
359
|
status
|
360
|
+
ensure
|
361
|
+
if @transaction_state && @transaction_state.committed?
|
362
|
+
clear_transaction_record_state
|
363
|
+
end
|
338
364
|
end
|
339
365
|
|
340
366
|
protected
|
341
367
|
|
342
368
|
# Save the new record state and id of a record so it can be restored later if a transaction fails.
|
343
369
|
def remember_transaction_record_state #:nodoc:
|
344
|
-
@_start_transaction_state[:id] = id
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
end
|
370
|
+
@_start_transaction_state[:id] = id
|
371
|
+
@_start_transaction_state.reverse_merge!(
|
372
|
+
new_record: @new_record,
|
373
|
+
destroyed: @destroyed,
|
374
|
+
frozen?: frozen?,
|
375
|
+
)
|
351
376
|
@_start_transaction_state[:level] = (@_start_transaction_state[:level] || 0) + 1
|
352
|
-
@_start_transaction_state[:frozen?] = @attributes.frozen?
|
353
377
|
end
|
354
378
|
|
355
379
|
# Clear the new record state and id of a record.
|
356
380
|
def clear_transaction_record_state #:nodoc:
|
357
381
|
@_start_transaction_state[:level] = (@_start_transaction_state[:level] || 0) - 1
|
358
|
-
|
382
|
+
force_clear_transaction_record_state if @_start_transaction_state[:level] < 1
|
383
|
+
end
|
384
|
+
|
385
|
+
# Force to clear the transaction record state.
|
386
|
+
def force_clear_transaction_record_state #:nodoc:
|
387
|
+
@_start_transaction_state.clear
|
359
388
|
end
|
360
389
|
|
361
390
|
# Restore the new record state and id of a record that was previously saved by a call to save_record_state.
|
@@ -364,17 +393,14 @@ module ActiveRecord
|
|
364
393
|
transaction_level = (@_start_transaction_state[:level] || 0) - 1
|
365
394
|
if transaction_level < 1 || force
|
366
395
|
restore_state = @_start_transaction_state
|
367
|
-
|
368
|
-
@attributes = @attributes.dup if @attributes.frozen?
|
396
|
+
thaw
|
369
397
|
@new_record = restore_state[:new_record]
|
370
398
|
@destroyed = restore_state[:destroyed]
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
@attributes.delete(self.class.primary_key)
|
375
|
-
@attributes_cache.delete(self.class.primary_key)
|
399
|
+
pk = self.class.primary_key
|
400
|
+
if pk && read_attribute(pk) != restore_state[:id]
|
401
|
+
write_attribute(pk, restore_state[:id])
|
376
402
|
end
|
377
|
-
|
403
|
+
freeze if restore_state[:frozen?]
|
378
404
|
end
|
379
405
|
end
|
380
406
|
end
|