activerecord 4.1.15 → 4.2.0.beta1
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 +634 -2176
- data/README.rdoc +15 -10
- data/lib/active_record/aggregations.rb +12 -8
- data/lib/active_record/associations/association.rb +1 -1
- data/lib/active_record/associations/association_scope.rb +53 -21
- data/lib/active_record/associations/belongs_to_association.rb +15 -5
- data/lib/active_record/associations/builder/association.rb +16 -5
- data/lib/active_record/associations/builder/belongs_to.rb +7 -29
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +2 -11
- 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 +32 -44
- data/lib/active_record/associations/collection_proxy.rb +1 -10
- data/lib/active_record/associations/has_many_association.rb +60 -14
- data/lib/active_record/associations/has_many_through_association.rb +34 -23
- data/lib/active_record/associations/has_one_association.rb +0 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +18 -14
- data/lib/active_record/associations/join_dependency.rb +7 -9
- data/lib/active_record/associations/preloader/association.rb +9 -5
- data/lib/active_record/associations/preloader/through_association.rb +3 -3
- data/lib/active_record/associations/preloader.rb +2 -2
- data/lib/active_record/associations/singular_association.rb +16 -1
- data/lib/active_record/associations/through_association.rb +6 -22
- data/lib/active_record/associations.rb +58 -33
- data/lib/active_record/attribute.rb +131 -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/before_type_cast.rb +2 -2
- data/lib/active_record/attribute_methods/dirty.rb +85 -42
- data/lib/active_record/attribute_methods/primary_key.rb +6 -8
- data/lib/active_record/attribute_methods/read.rb +14 -57
- data/lib/active_record/attribute_methods/serialization.rb +12 -146
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +32 -40
- data/lib/active_record/attribute_methods/write.rb +8 -23
- data/lib/active_record/attribute_methods.rb +53 -90
- data/lib/active_record/attribute_set/builder.rb +32 -0
- data/lib/active_record/attribute_set.rb +77 -0
- data/lib/active_record/attributes.rb +122 -0
- data/lib/active_record/autosave_association.rb +11 -21
- data/lib/active_record/base.rb +9 -19
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +69 -45
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +22 -42
- data/lib/active_record/connection_adapters/abstract/quoting.rb +59 -60
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +37 -2
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +102 -21
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +9 -33
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +178 -55
- data/lib/active_record/connection_adapters/abstract/transaction.rb +120 -115
- data/lib/active_record/connection_adapters/abstract_adapter.rb +143 -57
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +156 -107
- data/lib/active_record/connection_adapters/column.rb +13 -244
- data/lib/active_record/connection_adapters/connection_specification.rb +6 -20
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +12 -15
- data/lib/active_record/connection_adapters/mysql_adapter.rb +55 -143
- 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 +39 -20
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +96 -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 +14 -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 +27 -0
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +13 -0
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +17 -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 +76 -0
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +15 -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 +85 -0
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +26 -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/oid.rb +29 -388
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +42 -122
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +154 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +86 -34
- data/lib/active_record/connection_adapters/postgresql/utils.rb +66 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +188 -452
- data/lib/active_record/connection_adapters/schema_cache.rb +14 -28
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +54 -47
- data/lib/active_record/connection_handling.rb +1 -1
- data/lib/active_record/core.rb +119 -22
- data/lib/active_record/counter_cache.rb +60 -6
- data/lib/active_record/enum.rb +9 -10
- data/lib/active_record/errors.rb +27 -26
- data/lib/active_record/explain.rb +1 -1
- data/lib/active_record/fixtures.rb +52 -45
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +33 -8
- data/lib/active_record/integration.rb +4 -4
- data/lib/active_record/locking/optimistic.rb +34 -16
- data/lib/active_record/migration/command_recorder.rb +19 -2
- data/lib/active_record/migration/join_table.rb +1 -1
- data/lib/active_record/migration.rb +22 -32
- data/lib/active_record/model_schema.rb +39 -48
- data/lib/active_record/nested_attributes.rb +8 -18
- data/lib/active_record/persistence.rb +39 -22
- data/lib/active_record/query_cache.rb +3 -3
- data/lib/active_record/querying.rb +1 -8
- data/lib/active_record/railtie.rb +17 -10
- data/lib/active_record/railties/databases.rake +47 -42
- data/lib/active_record/readonly_attributes.rb +0 -1
- data/lib/active_record/reflection.rb +225 -92
- data/lib/active_record/relation/batches.rb +0 -2
- data/lib/active_record/relation/calculations.rb +28 -32
- data/lib/active_record/relation/delegation.rb +1 -1
- data/lib/active_record/relation/finder_methods.rb +42 -20
- data/lib/active_record/relation/merger.rb +0 -1
- data/lib/active_record/relation/predicate_builder/array_handler.rb +16 -11
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +0 -4
- data/lib/active_record/relation/predicate_builder.rb +1 -22
- data/lib/active_record/relation/query_methods.rb +98 -62
- data/lib/active_record/relation/spawn_methods.rb +6 -7
- data/lib/active_record/relation.rb +35 -11
- data/lib/active_record/result.rb +16 -9
- data/lib/active_record/sanitization.rb +8 -1
- data/lib/active_record/schema.rb +0 -1
- data/lib/active_record/schema_dumper.rb +51 -9
- data/lib/active_record/schema_migration.rb +4 -0
- data/lib/active_record/scoping/default.rb +5 -4
- data/lib/active_record/serializers/xml_serializer.rb +3 -7
- data/lib/active_record/statement_cache.rb +79 -5
- data/lib/active_record/store.rb +5 -5
- data/lib/active_record/tasks/database_tasks.rb +37 -5
- data/lib/active_record/tasks/mysql_database_tasks.rb +1 -1
- data/lib/active_record/tasks/postgresql_database_tasks.rb +2 -2
- data/lib/active_record/timestamp.rb +9 -7
- data/lib/active_record/transactions.rb +35 -21
- data/lib/active_record/type/binary.rb +40 -0
- data/lib/active_record/type/boolean.rb +19 -0
- data/lib/active_record/type/date.rb +46 -0
- data/lib/active_record/type/date_time.rb +43 -0
- data/lib/active_record/type/decimal.rb +40 -0
- data/lib/active_record/type/decimal_without_scale.rb +11 -0
- data/lib/active_record/type/float.rb +19 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +19 -0
- data/lib/active_record/type/integer.rb +23 -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 +51 -0
- data/lib/active_record/type/string.rb +36 -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 +48 -0
- data/lib/active_record/type/value.rb +101 -0
- data/lib/active_record/type.rb +20 -0
- data/lib/active_record/validations/uniqueness.rb +9 -23
- data/lib/active_record/validations.rb +21 -16
- data/lib/active_record.rb +2 -1
- 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 +71 -14
- data/lib/active_record/connection_adapters/postgresql/cast.rb +0 -168
@@ -180,13 +180,9 @@ module ActiveRecord #:nodoc:
|
|
180
180
|
class Attribute < ActiveModel::Serializers::Xml::Serializer::Attribute #:nodoc:
|
181
181
|
def compute_type
|
182
182
|
klass = @serializable.class
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
klass.columns_hash[name].type
|
187
|
-
else
|
188
|
-
NilClass
|
189
|
-
end
|
183
|
+
column = klass.columns_hash[name] || Type::Value.new
|
184
|
+
|
185
|
+
type = ActiveSupport::XmlMini::TYPE_NAMES[value.class.name] || column.type
|
190
186
|
|
191
187
|
{ :text => :string,
|
192
188
|
:time => :datetime }[type] || type
|
@@ -14,13 +14,87 @@ module ActiveRecord
|
|
14
14
|
# The relation returned by the block is cached, and for each +execute+ call the cached relation gets duped.
|
15
15
|
# Database is queried when +to_a+ is called on the relation.
|
16
16
|
class StatementCache
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
class Substitute; end
|
18
|
+
|
19
|
+
class Query
|
20
|
+
def initialize(sql)
|
21
|
+
@sql = sql
|
22
|
+
end
|
23
|
+
|
24
|
+
def sql_for(binds, connection)
|
25
|
+
@sql
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class PartialQuery < Query
|
30
|
+
def initialize values
|
31
|
+
@values = values
|
32
|
+
@indexes = values.each_with_index.find_all { |thing,i|
|
33
|
+
Arel::Nodes::BindParam === thing
|
34
|
+
}.map(&:last)
|
35
|
+
end
|
36
|
+
|
37
|
+
def sql_for(binds, connection)
|
38
|
+
val = @values.dup
|
39
|
+
binds = binds.dup
|
40
|
+
@indexes.each { |i| val[i] = connection.quote(*binds.shift.reverse) }
|
41
|
+
val.join
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.query(visitor, ast)
|
46
|
+
Query.new visitor.accept(ast, Arel::Collectors::SQLString.new).value
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.partial_query(visitor, ast, collector)
|
50
|
+
collected = visitor.accept(ast, collector).value
|
51
|
+
PartialQuery.new collected
|
52
|
+
end
|
53
|
+
|
54
|
+
class Params
|
55
|
+
def bind; Substitute.new; end
|
20
56
|
end
|
21
57
|
|
22
|
-
|
23
|
-
|
58
|
+
class BindMap
|
59
|
+
def initialize(bind_values)
|
60
|
+
@indexes = []
|
61
|
+
@bind_values = bind_values
|
62
|
+
|
63
|
+
bind_values.each_with_index do |(_, value), i|
|
64
|
+
if Substitute === value
|
65
|
+
@indexes << i
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def bind(values)
|
71
|
+
bvs = @bind_values.map { |pair| pair.dup }
|
72
|
+
@indexes.each_with_index { |offset,i| bvs[offset][1] = values[i] }
|
73
|
+
bvs
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
attr_reader :bind_map, :query_builder
|
78
|
+
|
79
|
+
def self.create(connection, block = Proc.new)
|
80
|
+
relation = block.call Params.new
|
81
|
+
bind_map = BindMap.new relation.bind_values
|
82
|
+
query_builder = connection.cacheable_query relation.arel
|
83
|
+
new query_builder, bind_map
|
84
|
+
end
|
85
|
+
|
86
|
+
def initialize(query_builder, bind_map)
|
87
|
+
@query_builder = query_builder
|
88
|
+
@bind_map = bind_map
|
89
|
+
end
|
90
|
+
|
91
|
+
def execute(params, klass, connection)
|
92
|
+
bind_values = bind_map.bind params
|
93
|
+
|
94
|
+
sql = query_builder.sql_for bind_values, connection
|
95
|
+
|
96
|
+
klass.find_by_sql sql, bind_values
|
24
97
|
end
|
98
|
+
alias :call :execute
|
25
99
|
end
|
26
100
|
end
|
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)
|
@@ -6,7 +6,7 @@ module ActiveRecord
|
|
6
6
|
# <tt>ActiveRecord::Tasks::DatabaseTasks</tt> is a utility class, which encapsulates
|
7
7
|
# logic behind common tasks used to manage database and migrations.
|
8
8
|
#
|
9
|
-
# The tasks defined here are used
|
9
|
+
# The tasks defined here are used with Rake tasks provided by Active Record.
|
10
10
|
#
|
11
11
|
# In order to use DatabaseTasks, a few config values need to be set. All the needed
|
12
12
|
# config values are set by Rails already, so it's necessary to do it only if you
|
@@ -14,7 +14,6 @@ module ActiveRecord
|
|
14
14
|
# (in such case after configuring the database tasks, you can also use the rake tasks
|
15
15
|
# defined in Active Record).
|
16
16
|
#
|
17
|
-
#
|
18
17
|
# The possible config values are:
|
19
18
|
#
|
20
19
|
# * +env+: current environment (like Rails.env).
|
@@ -28,7 +27,7 @@ module ActiveRecord
|
|
28
27
|
# Example usage of +DatabaseTasks+ outside Rails could look as such:
|
29
28
|
#
|
30
29
|
# include ActiveRecord::Tasks
|
31
|
-
# DatabaseTasks.database_configuration = YAML.
|
30
|
+
# DatabaseTasks.database_configuration = YAML.load_file('my_database_config.yml')
|
32
31
|
# DatabaseTasks.db_dir = 'db'
|
33
32
|
# # other settings...
|
34
33
|
#
|
@@ -59,7 +58,11 @@ module ActiveRecord
|
|
59
58
|
end
|
60
59
|
|
61
60
|
def fixtures_path
|
62
|
-
@fixtures_path ||=
|
61
|
+
@fixtures_path ||= if ENV['FIXTURES_PATH']
|
62
|
+
File.join(root, ENV['FIXTURES_PATH'])
|
63
|
+
else
|
64
|
+
File.join(root, 'test', 'fixtures')
|
65
|
+
end
|
63
66
|
end
|
64
67
|
|
65
68
|
def root
|
@@ -107,6 +110,8 @@ module ActiveRecord
|
|
107
110
|
def drop(*arguments)
|
108
111
|
configuration = arguments.first
|
109
112
|
class_for_adapter(configuration['adapter']).new(*arguments).drop
|
113
|
+
rescue ActiveRecord::NoDatabaseError
|
114
|
+
$stderr.puts "Database '#{configuration['database']}' does not exist"
|
110
115
|
rescue Exception => error
|
111
116
|
$stderr.puts error, *(error.backtrace)
|
112
117
|
$stderr.puts "Couldn't drop #{configuration['database']}"
|
@@ -122,6 +127,16 @@ module ActiveRecord
|
|
122
127
|
}
|
123
128
|
end
|
124
129
|
|
130
|
+
def migrate
|
131
|
+
verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true
|
132
|
+
version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil
|
133
|
+
scope = ENV['SCOPE']
|
134
|
+
Migration.verbose = verbose
|
135
|
+
Migrator.migrate(Migrator.migrations_paths, version) do |migration|
|
136
|
+
scope.blank? || scope == migration.scope
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
125
140
|
def charset_current(environment = env)
|
126
141
|
charset ActiveRecord::Base.configurations[environment]
|
127
142
|
end
|
@@ -144,6 +159,18 @@ module ActiveRecord
|
|
144
159
|
class_for_adapter(configuration['adapter']).new(configuration).purge
|
145
160
|
end
|
146
161
|
|
162
|
+
def purge_all
|
163
|
+
each_local_configuration { |configuration|
|
164
|
+
purge configuration
|
165
|
+
}
|
166
|
+
end
|
167
|
+
|
168
|
+
def purge_current(environment = env)
|
169
|
+
each_current_configuration(environment) { |configuration|
|
170
|
+
purge configuration
|
171
|
+
}
|
172
|
+
end
|
173
|
+
|
147
174
|
def structure_dump(*arguments)
|
148
175
|
configuration = arguments.first
|
149
176
|
filename = arguments.delete_at 1
|
@@ -157,6 +184,10 @@ module ActiveRecord
|
|
157
184
|
end
|
158
185
|
|
159
186
|
def load_schema(format = ActiveRecord::Base.schema_format, file = nil)
|
187
|
+
ActiveSupport::Deprecation.warn(<<-MESSAGE.strip_heredoc)
|
188
|
+
This method will act on a specific connection in the future.
|
189
|
+
To act on the current connection, use `load_schema_current` instead.
|
190
|
+
MESSAGE
|
160
191
|
load_schema_current(format, file)
|
161
192
|
end
|
162
193
|
|
@@ -167,11 +198,13 @@ module ActiveRecord
|
|
167
198
|
when :ruby
|
168
199
|
file ||= File.join(db_dir, "schema.rb")
|
169
200
|
check_schema_file(file)
|
201
|
+
purge(configuration)
|
170
202
|
ActiveRecord::Base.establish_connection(configuration)
|
171
203
|
load(file)
|
172
204
|
when :sql
|
173
205
|
file ||= File.join(db_dir, "structure.sql")
|
174
206
|
check_schema_file(file)
|
207
|
+
purge(configuration)
|
175
208
|
structure_load(configuration, file)
|
176
209
|
else
|
177
210
|
raise ArgumentError, "unknown format #{format.inspect}"
|
@@ -182,7 +215,6 @@ module ActiveRecord
|
|
182
215
|
each_current_configuration(environment) { |configuration|
|
183
216
|
load_schema_for configuration, format, file
|
184
217
|
}
|
185
|
-
ActiveRecord::Base.establish_connection(environment.to_sym)
|
186
218
|
end
|
187
219
|
|
188
220
|
def check_schema_file(filename)
|
@@ -124,7 +124,7 @@ 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
|
|
@@ -51,10 +51,10 @@ module ActiveRecord
|
|
51
51
|
search_path = search_path.split(",").map{|search_path_part| "--schema=#{Shellwords.escape(search_path_part.strip)}" }.join(" ")
|
52
52
|
end
|
53
53
|
|
54
|
-
command = "pg_dump -s -x -O -f #{Shellwords.escape(filename)} #{search_path} #{Shellwords.escape(configuration['database'])}"
|
54
|
+
command = "pg_dump -i -s -x -O -f #{Shellwords.escape(filename)} #{search_path} #{Shellwords.escape(configuration['database'])}"
|
55
55
|
raise 'Error dumping database' unless Kernel.system(command)
|
56
56
|
|
57
|
-
File.open(filename, "a") { |f| f << "SET search_path TO #{
|
57
|
+
File.open(filename, "a") { |f| f << "SET search_path TO #{connection.schema_search_path};\n\n" }
|
58
58
|
end
|
59
59
|
|
60
60
|
def structure_load(filename)
|
@@ -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,25 @@
|
|
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
|
7
5
|
ACTIONS = [:create, :destroy, :update]
|
6
|
+
CALLBACK_WARN_MESSAGE = <<-EOF
|
7
|
+
Currently, Active Record will rescue any errors raised within
|
8
|
+
after_rollback/after_commit callbacks and print them to the logs. In the next
|
9
|
+
version, these errors will no longer be rescued. Instead, they will simply
|
10
|
+
bubble just like other Active Record callbacks.
|
11
|
+
|
12
|
+
You can opt into the new behavior and remove this warning by setting
|
13
|
+
config.active_record.raise_in_transactional_callbacks to true.
|
14
|
+
EOF
|
8
15
|
|
9
16
|
included do
|
10
17
|
define_callbacks :commit, :rollback,
|
11
18
|
terminator: ->(_, result) { result == false },
|
12
19
|
scope: [:kind, :name]
|
20
|
+
|
21
|
+
mattr_accessor :raise_in_transactional_callbacks, instance_writer: false
|
22
|
+
self.raise_in_transactional_callbacks = false
|
13
23
|
end
|
14
24
|
|
15
25
|
# = Active Record Transactions
|
@@ -225,6 +235,9 @@ module ActiveRecord
|
|
225
235
|
def after_commit(*args, &block)
|
226
236
|
set_options_for_callbacks!(args)
|
227
237
|
set_callback(:commit, :after, *args, &block)
|
238
|
+
unless ActiveRecord::Base.raise_in_transactional_callbacks
|
239
|
+
ActiveSupport::Deprecation.warn(CALLBACK_WARN_MESSAGE)
|
240
|
+
end
|
228
241
|
end
|
229
242
|
|
230
243
|
# This callback is called after a create, update, or destroy are rolled back.
|
@@ -233,6 +246,9 @@ module ActiveRecord
|
|
233
246
|
def after_rollback(*args, &block)
|
234
247
|
set_options_for_callbacks!(args)
|
235
248
|
set_callback(:rollback, :after, *args, &block)
|
249
|
+
unless ActiveRecord::Base.raise_in_transactional_callbacks
|
250
|
+
ActiveSupport::Deprecation.warn(CALLBACK_WARN_MESSAGE)
|
251
|
+
end
|
236
252
|
end
|
237
253
|
|
238
254
|
private
|
@@ -249,7 +265,7 @@ module ActiveRecord
|
|
249
265
|
|
250
266
|
def assert_valid_transaction_action(actions)
|
251
267
|
if (actions - ACTIONS).any?
|
252
|
-
raise ArgumentError, ":on conditions for after_commit and after_rollback callbacks have to be one of #{ACTIONS}"
|
268
|
+
raise ArgumentError, ":on conditions for after_commit and after_rollback callbacks have to be one of #{ACTIONS.join(",")}"
|
253
269
|
end
|
254
270
|
end
|
255
271
|
end
|
@@ -292,16 +308,16 @@ module ActiveRecord
|
|
292
308
|
#
|
293
309
|
# Ensure that it is not called if the object was never persisted (failed create),
|
294
310
|
# but call it after the commit of a destroyed object.
|
295
|
-
def committed! #:nodoc:
|
296
|
-
run_callbacks :commit if destroyed? || persisted?
|
311
|
+
def committed!(should_run_callbacks = true) #:nodoc:
|
312
|
+
run_callbacks :commit if should_run_callbacks && destroyed? || persisted?
|
297
313
|
ensure
|
298
|
-
|
314
|
+
force_clear_transaction_record_state
|
299
315
|
end
|
300
316
|
|
301
317
|
# Call the +after_rollback+ callbacks. The +force_restore_state+ argument indicates if the record
|
302
318
|
# state should be rolled back to the beginning or just to the last savepoint.
|
303
|
-
def rolledback!(force_restore_state = false) #:nodoc:
|
304
|
-
run_callbacks :rollback
|
319
|
+
def rolledback!(force_restore_state = false, should_run_callbacks = true) #:nodoc:
|
320
|
+
run_callbacks :rollback if should_run_callbacks
|
305
321
|
ensure
|
306
322
|
restore_transaction_record_state(force_restore_state)
|
307
323
|
clear_transaction_record_state
|
@@ -328,7 +344,7 @@ module ActiveRecord
|
|
328
344
|
begin
|
329
345
|
status = yield
|
330
346
|
rescue ActiveRecord::Rollback
|
331
|
-
|
347
|
+
clear_transaction_record_state
|
332
348
|
status = nil
|
333
349
|
end
|
334
350
|
|
@@ -341,7 +357,7 @@ module ActiveRecord
|
|
341
357
|
|
342
358
|
# Save the new record state and id of a record so it can be restored later if a transaction fails.
|
343
359
|
def remember_transaction_record_state #:nodoc:
|
344
|
-
@_start_transaction_state[:id] = id
|
360
|
+
@_start_transaction_state[:id] = id
|
345
361
|
unless @_start_transaction_state.include?(:new_record)
|
346
362
|
@_start_transaction_state[:new_record] = @new_record
|
347
363
|
end
|
@@ -349,13 +365,18 @@ module ActiveRecord
|
|
349
365
|
@_start_transaction_state[:destroyed] = @destroyed
|
350
366
|
end
|
351
367
|
@_start_transaction_state[:level] = (@_start_transaction_state[:level] || 0) + 1
|
352
|
-
@_start_transaction_state[:frozen?] =
|
368
|
+
@_start_transaction_state[:frozen?] = frozen?
|
353
369
|
end
|
354
370
|
|
355
371
|
# Clear the new record state and id of a record.
|
356
372
|
def clear_transaction_record_state #:nodoc:
|
357
373
|
@_start_transaction_state[:level] = (@_start_transaction_state[:level] || 0) - 1
|
358
|
-
|
374
|
+
force_clear_transaction_record_state if @_start_transaction_state[:level] < 1
|
375
|
+
end
|
376
|
+
|
377
|
+
# Force to clear the transaction record state.
|
378
|
+
def force_clear_transaction_record_state #:nodoc:
|
379
|
+
@_start_transaction_state.clear
|
359
380
|
end
|
360
381
|
|
361
382
|
# Restore the new record state and id of a record that was previously saved by a call to save_record_state.
|
@@ -364,17 +385,10 @@ module ActiveRecord
|
|
364
385
|
transaction_level = (@_start_transaction_state[:level] || 0) - 1
|
365
386
|
if transaction_level < 1 || force
|
366
387
|
restore_state = @_start_transaction_state
|
367
|
-
|
368
|
-
@attributes = @attributes.dup if @attributes.frozen?
|
388
|
+
thaw unless restore_state[:frozen?]
|
369
389
|
@new_record = restore_state[:new_record]
|
370
390
|
@destroyed = restore_state[:destroyed]
|
371
|
-
|
372
|
-
write_attribute(self.class.primary_key, restore_state[:id])
|
373
|
-
else
|
374
|
-
@attributes.delete(self.class.primary_key)
|
375
|
-
@attributes_cache.delete(self.class.primary_key)
|
376
|
-
end
|
377
|
-
@attributes.freeze if was_frozen
|
391
|
+
write_attribute(self.class.primary_key, restore_state[:id])
|
378
392
|
end
|
379
393
|
end
|
380
394
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module Type
|
3
|
+
class Binary < Value # :nodoc:
|
4
|
+
def type
|
5
|
+
:binary
|
6
|
+
end
|
7
|
+
|
8
|
+
def binary?
|
9
|
+
true
|
10
|
+
end
|
11
|
+
|
12
|
+
def type_cast(value)
|
13
|
+
if value.is_a?(Data)
|
14
|
+
value.to_s
|
15
|
+
else
|
16
|
+
super
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def type_cast_for_database(value)
|
21
|
+
return if value.nil?
|
22
|
+
Data.new(super)
|
23
|
+
end
|
24
|
+
|
25
|
+
class Data # :nodoc:
|
26
|
+
def initialize(value)
|
27
|
+
@value = value.to_s
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_s
|
31
|
+
@value
|
32
|
+
end
|
33
|
+
|
34
|
+
def hex
|
35
|
+
@value.unpack('H*')[0]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module Type
|
3
|
+
class Boolean < Value # :nodoc:
|
4
|
+
def type
|
5
|
+
:boolean
|
6
|
+
end
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def cast_value(value)
|
11
|
+
if value == ''
|
12
|
+
nil
|
13
|
+
else
|
14
|
+
ConnectionAdapters::Column::TRUE_VALUES.include?(value)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module Type
|
3
|
+
class Date < Value # :nodoc:
|
4
|
+
def type
|
5
|
+
:date
|
6
|
+
end
|
7
|
+
|
8
|
+
def klass
|
9
|
+
::Date
|
10
|
+
end
|
11
|
+
|
12
|
+
def type_cast_for_schema(value)
|
13
|
+
"'#{value.to_s(:db)}'"
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def cast_value(value)
|
19
|
+
if value.is_a?(::String)
|
20
|
+
return if value.empty?
|
21
|
+
fast_string_to_date(value) || fallback_string_to_date(value)
|
22
|
+
elsif value.respond_to?(:to_date)
|
23
|
+
value.to_date
|
24
|
+
else
|
25
|
+
value
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def fast_string_to_date(string)
|
30
|
+
if string =~ ConnectionAdapters::Column::Format::ISO_DATE
|
31
|
+
new_date $1.to_i, $2.to_i, $3.to_i
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def fallback_string_to_date(string)
|
36
|
+
new_date(*::Date._parse(string, false).values_at(:year, :mon, :mday))
|
37
|
+
end
|
38
|
+
|
39
|
+
def new_date(year, mon, mday)
|
40
|
+
if year && year != 0
|
41
|
+
::Date.new(year, mon, mday) rescue nil
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module Type
|
3
|
+
class DateTime < Value # :nodoc:
|
4
|
+
include TimeValue
|
5
|
+
|
6
|
+
def type
|
7
|
+
:datetime
|
8
|
+
end
|
9
|
+
|
10
|
+
def type_cast_for_database(value)
|
11
|
+
zone_conversion_method = ActiveRecord::Base.default_timezone == :utc ? :getutc : :getlocal
|
12
|
+
|
13
|
+
if value.acts_like?(:time)
|
14
|
+
value.send(zone_conversion_method)
|
15
|
+
else
|
16
|
+
super
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def cast_value(string)
|
23
|
+
return string unless string.is_a?(::String)
|
24
|
+
return if string.empty?
|
25
|
+
|
26
|
+
fast_string_to_time(string) || fallback_string_to_time(string)
|
27
|
+
end
|
28
|
+
|
29
|
+
# '0.123456' -> 123456
|
30
|
+
# '1.123456' -> 123456
|
31
|
+
def microseconds(time)
|
32
|
+
time[:sec_fraction] ? (time[:sec_fraction] * 1_000_000).to_i : 0
|
33
|
+
end
|
34
|
+
|
35
|
+
def fallback_string_to_time(string)
|
36
|
+
time_hash = ::Date._parse(string)
|
37
|
+
time_hash[:sec_fraction] = microseconds(time_hash)
|
38
|
+
|
39
|
+
new_time(*time_hash.values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction, :offset))
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module Type
|
3
|
+
class Decimal < Value # :nodoc:
|
4
|
+
include Numeric
|
5
|
+
|
6
|
+
def type
|
7
|
+
:decimal
|
8
|
+
end
|
9
|
+
|
10
|
+
def type_cast_for_schema(value)
|
11
|
+
value.to_s
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def cast_value(value)
|
17
|
+
case value
|
18
|
+
when ::Float
|
19
|
+
BigDecimal(value, float_precision)
|
20
|
+
when ::Numeric, ::String
|
21
|
+
BigDecimal(value, precision.to_i)
|
22
|
+
else
|
23
|
+
if value.respond_to?(:to_d)
|
24
|
+
value.to_d
|
25
|
+
else
|
26
|
+
cast_value(value.to_s)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def float_precision
|
32
|
+
if precision.to_i > ::Float::DIG + 1
|
33
|
+
::Float::DIG + 1
|
34
|
+
else
|
35
|
+
precision.to_i
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|