activerecord 5.0.7 → 5.1.7
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 +5 -5
- data/CHANGELOG.md +657 -2080
- data/MIT-LICENSE +1 -1
- data/README.rdoc +1 -1
- data/examples/performance.rb +28 -28
- data/examples/simple.rb +3 -3
- data/lib/active_record/aggregations.rb +244 -244
- data/lib/active_record/association_relation.rb +5 -5
- data/lib/active_record/associations/alias_tracker.rb +10 -11
- data/lib/active_record/associations/association.rb +23 -5
- data/lib/active_record/associations/association_scope.rb +95 -81
- data/lib/active_record/associations/belongs_to_association.rb +7 -4
- data/lib/active_record/associations/builder/belongs_to.rb +30 -16
- data/lib/active_record/associations/builder/collection_association.rb +1 -2
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +27 -27
- data/lib/active_record/associations/collection_association.rb +36 -205
- data/lib/active_record/associations/collection_proxy.rb +132 -63
- data/lib/active_record/associations/has_many_association.rb +10 -19
- data/lib/active_record/associations/has_many_through_association.rb +12 -4
- data/lib/active_record/associations/has_one_association.rb +24 -28
- data/lib/active_record/associations/has_one_through_association.rb +5 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +4 -28
- data/lib/active_record/associations/join_dependency/join_base.rb +1 -1
- data/lib/active_record/associations/join_dependency/join_part.rb +1 -1
- data/lib/active_record/associations/join_dependency.rb +121 -118
- data/lib/active_record/associations/preloader/association.rb +64 -64
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -2
- data/lib/active_record/associations/preloader/collection_association.rb +6 -6
- data/lib/active_record/associations/preloader/has_many.rb +0 -2
- data/lib/active_record/associations/preloader/singular_association.rb +6 -8
- data/lib/active_record/associations/preloader/through_association.rb +41 -41
- data/lib/active_record/associations/preloader.rb +94 -94
- data/lib/active_record/associations/singular_association.rb +8 -25
- data/lib/active_record/associations/through_association.rb +2 -5
- data/lib/active_record/associations.rb +1591 -1562
- data/lib/active_record/attribute/user_provided_default.rb +4 -2
- data/lib/active_record/attribute.rb +98 -71
- data/lib/active_record/attribute_assignment.rb +61 -61
- data/lib/active_record/attribute_decorators.rb +35 -13
- data/lib/active_record/attribute_methods/before_type_cast.rb +7 -7
- data/lib/active_record/attribute_methods/dirty.rb +229 -46
- data/lib/active_record/attribute_methods/primary_key.rb +74 -73
- data/lib/active_record/attribute_methods/read.rb +39 -35
- data/lib/active_record/attribute_methods/serialization.rb +7 -7
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +35 -58
- data/lib/active_record/attribute_methods/write.rb +30 -33
- data/lib/active_record/attribute_methods.rb +56 -65
- data/lib/active_record/attribute_mutation_tracker.rb +63 -11
- data/lib/active_record/attribute_set/builder.rb +27 -33
- data/lib/active_record/attribute_set/yaml_encoder.rb +41 -0
- data/lib/active_record/attribute_set.rb +9 -6
- data/lib/active_record/attributes.rb +22 -22
- data/lib/active_record/autosave_association.rb +18 -13
- data/lib/active_record/base.rb +24 -22
- data/lib/active_record/callbacks.rb +56 -14
- data/lib/active_record/coders/yaml_column.rb +9 -11
- data/lib/active_record/collection_cache_key.rb +3 -4
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +330 -284
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +1 -3
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +39 -37
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +32 -27
- data/lib/active_record/connection_adapters/abstract/quoting.rb +62 -51
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +10 -20
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +74 -79
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +53 -41
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +120 -100
- data/lib/active_record/connection_adapters/abstract/transaction.rb +49 -43
- data/lib/active_record/connection_adapters/abstract_adapter.rb +165 -135
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +404 -424
- data/lib/active_record/connection_adapters/column.rb +26 -4
- data/lib/active_record/connection_adapters/connection_specification.rb +128 -118
- data/lib/active_record/connection_adapters/mysql/column.rb +6 -31
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +36 -49
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +22 -22
- data/lib/active_record/connection_adapters/mysql/quoting.rb +6 -12
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +49 -45
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +16 -19
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +54 -28
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +43 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +7 -6
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +23 -27
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +32 -53
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +19 -9
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +16 -16
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +0 -10
- data/lib/active_record/connection_adapters/postgresql/oid/{rails_5_1_point.rb → legacy_point.rb} +9 -16
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +13 -0
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +28 -8
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +32 -30
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +2 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +51 -51
- data/lib/active_record/connection_adapters/postgresql/oid.rb +22 -21
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +40 -35
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +37 -24
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +19 -23
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +182 -222
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +6 -4
- data/lib/active_record/connection_adapters/postgresql/utils.rb +7 -5
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +198 -167
- data/lib/active_record/connection_adapters/schema_cache.rb +16 -7
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +3 -3
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +1 -1
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +16 -19
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +1 -8
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +28 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +17 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +32 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +184 -167
- data/lib/active_record/connection_adapters/statement_pool.rb +7 -7
- data/lib/active_record/connection_handling.rb +14 -26
- data/lib/active_record/core.rb +109 -93
- data/lib/active_record/counter_cache.rb +60 -13
- data/lib/active_record/define_callbacks.rb +20 -0
- data/lib/active_record/dynamic_matchers.rb +80 -79
- data/lib/active_record/enum.rb +8 -6
- data/lib/active_record/errors.rb +64 -15
- data/lib/active_record/explain.rb +1 -2
- data/lib/active_record/explain_registry.rb +1 -1
- data/lib/active_record/explain_subscriber.rb +7 -4
- data/lib/active_record/fixture_set/file.rb +11 -8
- data/lib/active_record/fixtures.rb +66 -53
- data/lib/active_record/gem_version.rb +1 -1
- data/lib/active_record/inheritance.rb +93 -79
- data/lib/active_record/integration.rb +7 -7
- data/lib/active_record/internal_metadata.rb +3 -16
- data/lib/active_record/legacy_yaml_adapter.rb +1 -1
- data/lib/active_record/locking/optimistic.rb +69 -74
- data/lib/active_record/locking/pessimistic.rb +10 -1
- data/lib/active_record/log_subscriber.rb +23 -28
- data/lib/active_record/migration/command_recorder.rb +94 -94
- data/lib/active_record/migration/compatibility.rb +100 -47
- data/lib/active_record/migration/join_table.rb +6 -6
- data/lib/active_record/migration.rb +153 -155
- data/lib/active_record/model_schema.rb +94 -107
- data/lib/active_record/nested_attributes.rb +200 -199
- data/lib/active_record/null_relation.rb +11 -34
- data/lib/active_record/persistence.rb +65 -50
- data/lib/active_record/query_cache.rb +2 -6
- data/lib/active_record/querying.rb +3 -4
- data/lib/active_record/railtie.rb +16 -17
- data/lib/active_record/railties/controller_runtime.rb +6 -2
- data/lib/active_record/railties/databases.rake +105 -133
- data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
- data/lib/active_record/readonly_attributes.rb +2 -2
- data/lib/active_record/reflection.rb +154 -108
- data/lib/active_record/relation/batches/batch_enumerator.rb +1 -1
- data/lib/active_record/relation/batches.rb +80 -51
- data/lib/active_record/relation/calculations.rb +169 -162
- data/lib/active_record/relation/delegation.rb +32 -31
- data/lib/active_record/relation/finder_methods.rb +197 -231
- data/lib/active_record/relation/merger.rb +58 -62
- data/lib/active_record/relation/predicate_builder/array_handler.rb +7 -5
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +23 -23
- data/lib/active_record/relation/predicate_builder/base_handler.rb +3 -1
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +0 -8
- data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +12 -10
- data/lib/active_record/relation/predicate_builder/range_handler.rb +0 -8
- data/lib/active_record/relation/predicate_builder.rb +92 -89
- data/lib/active_record/relation/query_attribute.rb +1 -1
- data/lib/active_record/relation/query_methods.rb +255 -293
- data/lib/active_record/relation/record_fetch_warning.rb +3 -3
- data/lib/active_record/relation/spawn_methods.rb +4 -5
- data/lib/active_record/relation/where_clause.rb +80 -65
- data/lib/active_record/relation/where_clause_factory.rb +47 -8
- data/lib/active_record/relation.rb +93 -119
- data/lib/active_record/result.rb +41 -32
- data/lib/active_record/runtime_registry.rb +3 -3
- data/lib/active_record/sanitization.rb +176 -192
- data/lib/active_record/schema.rb +3 -3
- data/lib/active_record/schema_dumper.rb +15 -38
- data/lib/active_record/schema_migration.rb +8 -4
- data/lib/active_record/scoping/default.rb +90 -90
- data/lib/active_record/scoping/named.rb +11 -11
- data/lib/active_record/scoping.rb +6 -6
- data/lib/active_record/secure_token.rb +2 -2
- data/lib/active_record/statement_cache.rb +13 -15
- data/lib/active_record/store.rb +31 -32
- data/lib/active_record/suppressor.rb +2 -1
- data/lib/active_record/table_metadata.rb +9 -5
- data/lib/active_record/tasks/database_tasks.rb +65 -55
- data/lib/active_record/tasks/mysql_database_tasks.rb +76 -73
- data/lib/active_record/tasks/postgresql_database_tasks.rb +72 -47
- data/lib/active_record/tasks/sqlite_database_tasks.rb +18 -16
- data/lib/active_record/timestamp.rb +46 -25
- data/lib/active_record/touch_later.rb +1 -2
- data/lib/active_record/transactions.rb +97 -109
- data/lib/active_record/type/adapter_specific_registry.rb +46 -42
- data/lib/active_record/type/decimal_without_scale.rb +13 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +3 -3
- data/lib/active_record/type/internal/abstract_json.rb +4 -0
- data/lib/active_record/type/serialized.rb +14 -8
- data/lib/active_record/type/text.rb +9 -0
- data/lib/active_record/type/time.rb +0 -1
- data/lib/active_record/type/type_map.rb +11 -15
- data/lib/active_record/type/unsigned_integer.rb +15 -0
- data/lib/active_record/type.rb +17 -13
- data/lib/active_record/type_caster/connection.rb +8 -6
- data/lib/active_record/type_caster/map.rb +3 -1
- data/lib/active_record/type_caster.rb +2 -2
- data/lib/active_record/validations/associated.rb +1 -1
- data/lib/active_record/validations/presence.rb +2 -2
- data/lib/active_record/validations/uniqueness.rb +8 -39
- data/lib/active_record/validations.rb +4 -4
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +20 -20
- data/lib/rails/generators/active_record/migration/migration_generator.rb +37 -34
- data/lib/rails/generators/active_record/migration.rb +1 -1
- data/lib/rails/generators/active_record/model/model_generator.rb +9 -9
- data/lib/rails/generators/active_record.rb +4 -4
- metadata +24 -13
- data/lib/active_record/relation/predicate_builder/class_handler.rb +0 -27
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "stringio"
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
4
|
# = Active Record Schema Dumper
|
@@ -17,7 +17,7 @@ module ActiveRecord
|
|
17
17
|
@@ignore_tables = []
|
18
18
|
|
19
19
|
class << self
|
20
|
-
def dump(connection=ActiveRecord::Base.connection, stream=STDOUT, config = ActiveRecord::Base)
|
20
|
+
def dump(connection = ActiveRecord::Base.connection, stream = STDOUT, config = ActiveRecord::Base)
|
21
21
|
new(connection, generate_options(config)).dump(stream)
|
22
22
|
stream
|
23
23
|
end
|
@@ -85,7 +85,7 @@ HEADER
|
|
85
85
|
end
|
86
86
|
|
87
87
|
def tables(stream)
|
88
|
-
sorted_tables = @connection.
|
88
|
+
sorted_tables = @connection.tables.sort
|
89
89
|
|
90
90
|
sorted_tables.each do |table_name|
|
91
91
|
table(table_name, stream) unless ignored?(table_name)
|
@@ -111,13 +111,11 @@ HEADER
|
|
111
111
|
|
112
112
|
case pk
|
113
113
|
when String
|
114
|
-
tbl.print ", primary_key: #{pk.inspect}" unless pk ==
|
114
|
+
tbl.print ", primary_key: #{pk.inspect}" unless pk == "id"
|
115
115
|
pkcol = columns.detect { |c| c.name == pk }
|
116
116
|
pkcolspec = @connection.column_spec_for_primary_key(pkcol)
|
117
117
|
if pkcolspec.present?
|
118
|
-
|
119
|
-
tbl.print ", #{key}: #{value}"
|
120
|
-
end
|
118
|
+
tbl.print ", #{format_colspec(pkcolspec)}"
|
121
119
|
end
|
122
120
|
when Array
|
123
121
|
tbl.print ", primary_key: #{pk.inspect}"
|
@@ -134,37 +132,12 @@ HEADER
|
|
134
132
|
tbl.puts " do |t|"
|
135
133
|
|
136
134
|
# then dump all non-primary key columns
|
137
|
-
|
135
|
+
columns.each do |column|
|
138
136
|
raise StandardError, "Unknown type '#{column.sql_type}' for column '#{column.name}'" unless @connection.valid_type?(column.type)
|
139
137
|
next if column.name == pk
|
140
|
-
@connection.column_spec(column)
|
141
|
-
|
142
|
-
|
143
|
-
# find all migration keys used in this table
|
144
|
-
keys = @connection.migration_keys
|
145
|
-
|
146
|
-
# figure out the lengths for each column based on above keys
|
147
|
-
lengths = keys.map { |key|
|
148
|
-
column_specs.map { |spec|
|
149
|
-
spec[key] ? spec[key].length + 2 : 0
|
150
|
-
}.max
|
151
|
-
}
|
152
|
-
|
153
|
-
# the string we're going to sprintf our values against, with standardized column widths
|
154
|
-
format_string = lengths.map{ |len| "%-#{len}s" }
|
155
|
-
|
156
|
-
# find the max length for the 'type' column, which is special
|
157
|
-
type_length = column_specs.map{ |column| column[:type].length }.max
|
158
|
-
|
159
|
-
# add column type definition to our format string
|
160
|
-
format_string.unshift " t.%-#{type_length}s "
|
161
|
-
|
162
|
-
format_string *= ''
|
163
|
-
|
164
|
-
column_specs.each do |colspec|
|
165
|
-
values = keys.zip(lengths).map{ |key, len| colspec.key?(key) ? colspec[key] + ", " : " " * len }
|
166
|
-
values.unshift colspec[:type]
|
167
|
-
tbl.print((format_string % values).gsub(/,\s*$/, ''))
|
138
|
+
type, colspec = @connection.column_spec(column)
|
139
|
+
tbl.print " t.#{type} #{column.name.inspect}"
|
140
|
+
tbl.print ", #{format_colspec(colspec)}" if colspec.present?
|
168
141
|
tbl.puts
|
169
142
|
end
|
170
143
|
|
@@ -189,7 +162,7 @@ HEADER
|
|
189
162
|
if (indexes = @connection.indexes(table)).any?
|
190
163
|
add_index_statements = indexes.map do |index|
|
191
164
|
table_name = remove_prefix_and_suffix(index.table).inspect
|
192
|
-
" add_index #{([table_name]+index_parts(index)).join(', ')}"
|
165
|
+
" add_index #{([table_name] + index_parts(index)).join(', ')}"
|
193
166
|
end
|
194
167
|
|
195
168
|
stream.puts add_index_statements.sort.join("\n")
|
@@ -215,7 +188,7 @@ HEADER
|
|
215
188
|
index_parts << "length: { #{format_options(index.lengths)} }" if index.lengths.present?
|
216
189
|
index_parts << "order: { #{format_options(index.orders)} }" if index.orders.present?
|
217
190
|
index_parts << "where: #{index.where.inspect}" if index.where
|
218
|
-
index_parts << "using: #{index.using.inspect}" if index
|
191
|
+
index_parts << "using: #{index.using.inspect}" if !@connection.default_index_type?(index)
|
219
192
|
index_parts << "type: #{index.type.inspect}" if index.type
|
220
193
|
index_parts << "comment: #{index.comment.inspect}" if index.comment
|
221
194
|
index_parts
|
@@ -251,6 +224,10 @@ HEADER
|
|
251
224
|
end
|
252
225
|
end
|
253
226
|
|
227
|
+
def format_colspec(colspec)
|
228
|
+
colspec.map { |key, value| "#{key}: #{value}" }.join(", ")
|
229
|
+
end
|
230
|
+
|
254
231
|
def format_options(options)
|
255
232
|
options.map { |key, value| "#{key}: #{value.inspect}" }.join(", ")
|
256
233
|
end
|
@@ -1,5 +1,5 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "active_record/scoping/default"
|
2
|
+
require "active_record/scoping/named"
|
3
3
|
|
4
4
|
module ActiveRecord
|
5
5
|
# This class is used to create a table that keeps track of which migrations
|
@@ -17,7 +17,7 @@ module ActiveRecord
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def table_exists?
|
20
|
-
|
20
|
+
connection.table_exists?(table_name)
|
21
21
|
end
|
22
22
|
|
23
23
|
def create_table
|
@@ -39,7 +39,11 @@ module ActiveRecord
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def normalized_versions
|
42
|
-
|
42
|
+
all_versions.map { |v| normalize_migration_number v }
|
43
|
+
end
|
44
|
+
|
45
|
+
def all_versions
|
46
|
+
order(:version).pluck(:version)
|
43
47
|
end
|
44
48
|
end
|
45
49
|
|
@@ -44,109 +44,109 @@ module ActiveRecord
|
|
44
44
|
self.current_scope = nil
|
45
45
|
end
|
46
46
|
|
47
|
-
|
47
|
+
private
|
48
|
+
|
49
|
+
# Use this macro in your model to set a default scope for all operations on
|
50
|
+
# the model.
|
51
|
+
#
|
52
|
+
# class Article < ActiveRecord::Base
|
53
|
+
# default_scope { where(published: true) }
|
54
|
+
# end
|
55
|
+
#
|
56
|
+
# Article.all # => SELECT * FROM articles WHERE published = true
|
57
|
+
#
|
58
|
+
# The #default_scope is also applied while creating/building a record.
|
59
|
+
# It is not applied while updating a record.
|
60
|
+
#
|
61
|
+
# Article.new.published # => true
|
62
|
+
# Article.create.published # => true
|
63
|
+
#
|
64
|
+
# (You can also pass any object which responds to +call+ to the
|
65
|
+
# +default_scope+ macro, and it will be called when building the
|
66
|
+
# default scope.)
|
67
|
+
#
|
68
|
+
# If you use multiple #default_scope declarations in your model then
|
69
|
+
# they will be merged together:
|
70
|
+
#
|
71
|
+
# class Article < ActiveRecord::Base
|
72
|
+
# default_scope { where(published: true) }
|
73
|
+
# default_scope { where(rating: 'G') }
|
74
|
+
# end
|
75
|
+
#
|
76
|
+
# Article.all # => SELECT * FROM articles WHERE published = true AND rating = 'G'
|
77
|
+
#
|
78
|
+
# This is also the case with inheritance and module includes where the
|
79
|
+
# parent or module defines a #default_scope and the child or including
|
80
|
+
# class defines a second one.
|
81
|
+
#
|
82
|
+
# If you need to do more complex things with a default scope, you can
|
83
|
+
# alternatively define it as a class method:
|
84
|
+
#
|
85
|
+
# class Article < ActiveRecord::Base
|
86
|
+
# def self.default_scope
|
87
|
+
# # Should return a scope, you can call 'super' here etc.
|
88
|
+
# end
|
89
|
+
# end
|
90
|
+
def default_scope(scope = nil) # :doc:
|
91
|
+
scope = Proc.new if block_given?
|
92
|
+
|
93
|
+
if scope.is_a?(Relation) || !scope.respond_to?(:call)
|
94
|
+
raise ArgumentError,
|
95
|
+
"Support for calling #default_scope without a block is removed. For example instead " \
|
96
|
+
"of `default_scope where(color: 'red')`, please use " \
|
97
|
+
"`default_scope { where(color: 'red') }`. (Alternatively you can just redefine " \
|
98
|
+
"self.default_scope.)"
|
99
|
+
end
|
48
100
|
|
49
|
-
|
50
|
-
# the model.
|
51
|
-
#
|
52
|
-
# class Article < ActiveRecord::Base
|
53
|
-
# default_scope { where(published: true) }
|
54
|
-
# end
|
55
|
-
#
|
56
|
-
# Article.all # => SELECT * FROM articles WHERE published = true
|
57
|
-
#
|
58
|
-
# The #default_scope is also applied while creating/building a record.
|
59
|
-
# It is not applied while updating a record.
|
60
|
-
#
|
61
|
-
# Article.new.published # => true
|
62
|
-
# Article.create.published # => true
|
63
|
-
#
|
64
|
-
# (You can also pass any object which responds to +call+ to the
|
65
|
-
# +default_scope+ macro, and it will be called when building the
|
66
|
-
# default scope.)
|
67
|
-
#
|
68
|
-
# If you use multiple #default_scope declarations in your model then
|
69
|
-
# they will be merged together:
|
70
|
-
#
|
71
|
-
# class Article < ActiveRecord::Base
|
72
|
-
# default_scope { where(published: true) }
|
73
|
-
# default_scope { where(rating: 'G') }
|
74
|
-
# end
|
75
|
-
#
|
76
|
-
# Article.all # => SELECT * FROM articles WHERE published = true AND rating = 'G'
|
77
|
-
#
|
78
|
-
# This is also the case with inheritance and module includes where the
|
79
|
-
# parent or module defines a #default_scope and the child or including
|
80
|
-
# class defines a second one.
|
81
|
-
#
|
82
|
-
# If you need to do more complex things with a default scope, you can
|
83
|
-
# alternatively define it as a class method:
|
84
|
-
#
|
85
|
-
# class Article < ActiveRecord::Base
|
86
|
-
# def self.default_scope
|
87
|
-
# # Should return a scope, you can call 'super' here etc.
|
88
|
-
# end
|
89
|
-
# end
|
90
|
-
def default_scope(scope = nil)
|
91
|
-
scope = Proc.new if block_given?
|
92
|
-
|
93
|
-
if scope.is_a?(Relation) || !scope.respond_to?(:call)
|
94
|
-
raise ArgumentError,
|
95
|
-
"Support for calling #default_scope without a block is removed. For example instead " \
|
96
|
-
"of `default_scope where(color: 'red')`, please use " \
|
97
|
-
"`default_scope { where(color: 'red') }`. (Alternatively you can just redefine " \
|
98
|
-
"self.default_scope.)"
|
101
|
+
self.default_scopes += [scope]
|
99
102
|
end
|
100
103
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
def build_default_scope(base_rel = nil) # :nodoc:
|
105
|
-
return if abstract_class?
|
104
|
+
def build_default_scope(base_rel = nil)
|
105
|
+
return if abstract_class?
|
106
106
|
|
107
|
-
|
108
|
-
|
109
|
-
|
107
|
+
if default_scope_override.nil?
|
108
|
+
self.default_scope_override = !Base.is_a?(method(:default_scope).owner)
|
109
|
+
end
|
110
110
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
111
|
+
if default_scope_override
|
112
|
+
# The user has defined their own default scope method, so call that
|
113
|
+
evaluate_default_scope do
|
114
|
+
if scope = default_scope
|
115
|
+
(base_rel ||= relation).merge(scope)
|
116
|
+
end
|
116
117
|
end
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
118
|
+
elsif default_scopes.any?
|
119
|
+
base_rel ||= relation
|
120
|
+
evaluate_default_scope do
|
121
|
+
default_scopes.inject(base_rel) do |default_scope, scope|
|
122
|
+
scope = scope.respond_to?(:to_proc) ? scope : scope.method(:call)
|
123
|
+
default_scope.merge(base_rel.instance_exec(&scope))
|
124
|
+
end
|
124
125
|
end
|
125
126
|
end
|
126
127
|
end
|
127
|
-
end
|
128
128
|
|
129
|
-
|
130
|
-
|
131
|
-
|
129
|
+
def ignore_default_scope?
|
130
|
+
ScopeRegistry.value_for(:ignore_default_scope, base_class)
|
131
|
+
end
|
132
132
|
|
133
|
-
|
134
|
-
|
135
|
-
|
133
|
+
def ignore_default_scope=(ignore)
|
134
|
+
ScopeRegistry.set_value_for(:ignore_default_scope, base_class, ignore)
|
135
|
+
end
|
136
136
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
137
|
+
# The ignore_default_scope flag is used to prevent an infinite recursion
|
138
|
+
# situation where a default scope references a scope which has a default
|
139
|
+
# scope which references a scope...
|
140
|
+
def evaluate_default_scope
|
141
|
+
return if ignore_default_scope?
|
142
|
+
|
143
|
+
begin
|
144
|
+
self.ignore_default_scope = true
|
145
|
+
yield
|
146
|
+
ensure
|
147
|
+
self.ignore_default_scope = false
|
148
|
+
end
|
148
149
|
end
|
149
|
-
end
|
150
150
|
end
|
151
151
|
end
|
152
152
|
end
|
@@ -1,6 +1,6 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
1
|
+
require "active_support/core_ext/array"
|
2
|
+
require "active_support/core_ext/hash/except"
|
3
|
+
require "active_support/core_ext/kernel/singleton_class"
|
4
4
|
|
5
5
|
module ActiveRecord
|
6
6
|
# = Active Record \Named \Scopes
|
@@ -54,7 +54,7 @@ module ActiveRecord
|
|
54
54
|
# Adds a class method for retrieving and querying objects.
|
55
55
|
# The method is intended to return an ActiveRecord::Relation
|
56
56
|
# object, which is composable with other scopes.
|
57
|
-
# If it returns nil or false
|
57
|
+
# If it returns +nil+ or +false+, an
|
58
58
|
# {all}[rdoc-ref:Scoping::Named::ClassMethods#all] scope is returned instead.
|
59
59
|
#
|
60
60
|
# A \scope represents a narrowing of a database query, such as
|
@@ -154,7 +154,7 @@ module ActiveRecord
|
|
154
154
|
# Article.featured.titles
|
155
155
|
def scope(name, body, &block)
|
156
156
|
unless body.respond_to?(:call)
|
157
|
-
raise ArgumentError,
|
157
|
+
raise ArgumentError, "The scope body needs to be callable."
|
158
158
|
end
|
159
159
|
|
160
160
|
if dangerous_class_method?(name)
|
@@ -183,14 +183,14 @@ module ActiveRecord
|
|
183
183
|
end
|
184
184
|
end
|
185
185
|
|
186
|
-
|
186
|
+
private
|
187
187
|
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
188
|
+
def valid_scope_name?(name)
|
189
|
+
if respond_to?(name, true) && logger
|
190
|
+
logger.warn "Creating scope :#{name}. " \
|
191
|
+
"Overwriting existing method #{self.name}.#{name}."
|
192
|
+
end
|
192
193
|
end
|
193
|
-
end
|
194
194
|
end
|
195
195
|
end
|
196
196
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "active_support/per_thread_registry"
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
4
|
module Scoping
|
@@ -33,7 +33,7 @@ module ActiveRecord
|
|
33
33
|
def populate_with_current_scope_attributes # :nodoc:
|
34
34
|
return unless self.class.scope_attributes?
|
35
35
|
|
36
|
-
self.class.scope_attributes.each do |att,value|
|
36
|
+
self.class.scope_attributes.each do |att, value|
|
37
37
|
send("#{att}=", value) if respond_to?("#{att}=")
|
38
38
|
end
|
39
39
|
end
|
@@ -95,11 +95,11 @@ module ActiveRecord
|
|
95
95
|
|
96
96
|
private
|
97
97
|
|
98
|
-
|
99
|
-
|
100
|
-
|
98
|
+
def raise_invalid_scope_type!(scope_type)
|
99
|
+
if !VALID_SCOPE_TYPES.include?(scope_type)
|
100
|
+
raise ArgumentError, "Invalid scope type '#{scope_type}' sent to the registry. Scope types must be included in VALID_SCOPE_TYPES"
|
101
|
+
end
|
101
102
|
end
|
102
|
-
end
|
103
103
|
end
|
104
104
|
end
|
105
105
|
end
|
@@ -25,9 +25,9 @@ module ActiveRecord
|
|
25
25
|
# You're encouraged to add a unique index in the database to deal with this even more unlikely scenario.
|
26
26
|
def has_secure_token(attribute = :token)
|
27
27
|
# Load securerandom only when has_secure_token is used.
|
28
|
-
require
|
28
|
+
require "active_support/core_ext/securerandom"
|
29
29
|
define_method("regenerate_#{attribute}") { update! attribute => self.class.generate_unique_secure_token }
|
30
|
-
before_create {
|
30
|
+
before_create { send("#{attribute}=", self.class.generate_unique_secure_token) unless send("#{attribute}?") }
|
31
31
|
end
|
32
32
|
|
33
33
|
def generate_unique_secure_token
|
@@ -1,5 +1,4 @@
|
|
1
1
|
module ActiveRecord
|
2
|
-
|
3
2
|
# Statement cache is used to cache a single statement in order to avoid creating the AST again.
|
4
3
|
# Initializing the cache is done by passing the statement in the create block:
|
5
4
|
#
|
@@ -8,12 +7,12 @@ module ActiveRecord
|
|
8
7
|
# end
|
9
8
|
#
|
10
9
|
# The cached statement is executed by using the
|
11
|
-
#
|
10
|
+
# {connection.execute}[rdoc-ref:ConnectionAdapters::DatabaseStatements#execute] method:
|
12
11
|
#
|
13
12
|
# cache.execute([], Book, Book.connection)
|
14
13
|
#
|
15
14
|
# The relation returned by the block is cached, and for each
|
16
|
-
# [
|
15
|
+
# {execute}[rdoc-ref:ConnectionAdapters::DatabaseStatements#execute]
|
17
16
|
# call the cached relation gets duped. Database is queried when +to_a+ is called on the relation.
|
18
17
|
#
|
19
18
|
# If you want to cache the statement without the values you can use the +bind+ method of the
|
@@ -40,28 +39,27 @@ module ActiveRecord
|
|
40
39
|
end
|
41
40
|
|
42
41
|
class PartialQuery < Query # :nodoc:
|
43
|
-
def initialize
|
42
|
+
def initialize(values)
|
44
43
|
@values = values
|
45
|
-
@indexes = values.each_with_index.find_all { |thing,i|
|
44
|
+
@indexes = values.each_with_index.find_all { |thing, i|
|
46
45
|
Arel::Nodes::BindParam === thing
|
47
46
|
}.map(&:last)
|
48
47
|
end
|
49
48
|
|
50
49
|
def sql_for(binds, connection)
|
51
50
|
val = @values.dup
|
52
|
-
|
53
|
-
@indexes.each { |i| val[i] = connection.quote(
|
51
|
+
casted_binds = binds.map(&:value_for_database)
|
52
|
+
@indexes.each { |i| val[i] = connection.quote(casted_binds.shift) }
|
54
53
|
val.join
|
55
54
|
end
|
56
55
|
end
|
57
56
|
|
58
|
-
def self.query(
|
59
|
-
Query.new
|
57
|
+
def self.query(sql)
|
58
|
+
Query.new(sql)
|
60
59
|
end
|
61
60
|
|
62
|
-
def self.partial_query(
|
63
|
-
|
64
|
-
PartialQuery.new collected
|
61
|
+
def self.partial_query(values)
|
62
|
+
PartialQuery.new(values)
|
65
63
|
end
|
66
64
|
|
67
65
|
class Params # :nodoc:
|
@@ -70,7 +68,7 @@ module ActiveRecord
|
|
70
68
|
|
71
69
|
class BindMap # :nodoc:
|
72
70
|
def initialize(bound_attributes)
|
73
|
-
@indexes
|
71
|
+
@indexes = []
|
74
72
|
@bound_attributes = bound_attributes
|
75
73
|
|
76
74
|
bound_attributes.each_with_index do |attr, i|
|
@@ -82,7 +80,7 @@ module ActiveRecord
|
|
82
80
|
|
83
81
|
def bind(values)
|
84
82
|
bas = @bound_attributes.dup
|
85
|
-
@indexes.each_with_index { |offset,i| bas[offset] = bas[offset].with_cast_value(values[i]) }
|
83
|
+
@indexes.each_with_index { |offset, i| bas[offset] = bas[offset].with_cast_value(values[i]) }
|
86
84
|
bas
|
87
85
|
end
|
88
86
|
end
|
@@ -92,7 +90,7 @@ module ActiveRecord
|
|
92
90
|
def self.create(connection, block = Proc.new)
|
93
91
|
relation = block.call Params.new
|
94
92
|
bind_map = BindMap.new relation.bound_attributes
|
95
|
-
query_builder = connection.cacheable_query relation.arel
|
93
|
+
query_builder = connection.cacheable_query(self, relation.arel)
|
96
94
|
new query_builder, bind_map
|
97
95
|
end
|
98
96
|
|
data/lib/active_record/store.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "active_support/core_ext/hash/indifferent_access"
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
4
|
# Store gives you a thin wrapper around serialize for the purpose of storing hashes in a single column.
|
@@ -78,7 +78,7 @@ module ActiveRecord
|
|
78
78
|
|
79
79
|
module ClassMethods
|
80
80
|
def store(store_attribute, options = {})
|
81
|
-
serialize store_attribute, IndifferentCoder.new(options[:coder])
|
81
|
+
serialize store_attribute, IndifferentCoder.new(store_attribute, options[:coder])
|
82
82
|
store_accessor(store_attribute, options[:accessors]) if options.has_key? :accessors
|
83
83
|
end
|
84
84
|
|
@@ -114,25 +114,24 @@ module ActiveRecord
|
|
114
114
|
|
115
115
|
def stored_attributes
|
116
116
|
parent = superclass.respond_to?(:stored_attributes) ? superclass.stored_attributes : {}
|
117
|
-
if
|
118
|
-
parent.merge!(
|
117
|
+
if local_stored_attributes
|
118
|
+
parent.merge!(local_stored_attributes) { |k, a, b| a | b }
|
119
119
|
end
|
120
120
|
parent
|
121
121
|
end
|
122
122
|
end
|
123
123
|
|
124
|
-
|
125
|
-
def read_store_attribute(store_attribute, key)
|
124
|
+
private
|
125
|
+
def read_store_attribute(store_attribute, key) # :doc:
|
126
126
|
accessor = store_accessor_for(store_attribute)
|
127
127
|
accessor.read(self, store_attribute, key)
|
128
128
|
end
|
129
129
|
|
130
|
-
def write_store_attribute(store_attribute, key, value)
|
130
|
+
def write_store_attribute(store_attribute, key, value) # :doc:
|
131
131
|
accessor = store_accessor_for(store_attribute)
|
132
132
|
accessor.write(self, store_attribute, key, value)
|
133
133
|
end
|
134
134
|
|
135
|
-
private
|
136
135
|
def store_accessor_for(store_attribute)
|
137
136
|
type_for_attribute(store_attribute.to_s).accessor
|
138
137
|
end
|
@@ -177,34 +176,34 @@ module ActiveRecord
|
|
177
176
|
end
|
178
177
|
end
|
179
178
|
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
179
|
+
class IndifferentCoder # :nodoc:
|
180
|
+
def initialize(attr_name, coder_or_class_name)
|
181
|
+
@coder =
|
182
|
+
if coder_or_class_name.respond_to?(:load) && coder_or_class_name.respond_to?(:dump)
|
183
|
+
coder_or_class_name
|
184
|
+
else
|
185
|
+
ActiveRecord::Coders::YAMLColumn.new(attr_name, coder_or_class_name || Object)
|
186
|
+
end
|
187
|
+
end
|
189
188
|
|
190
|
-
|
191
|
-
|
192
|
-
|
189
|
+
def dump(obj)
|
190
|
+
@coder.dump self.class.as_indifferent_hash(obj)
|
191
|
+
end
|
193
192
|
|
194
|
-
|
195
|
-
|
196
|
-
|
193
|
+
def load(yaml)
|
194
|
+
self.class.as_indifferent_hash(@coder.load(yaml || ""))
|
195
|
+
end
|
197
196
|
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
197
|
+
def self.as_indifferent_hash(obj)
|
198
|
+
case obj
|
199
|
+
when ActiveSupport::HashWithIndifferentAccess
|
200
|
+
obj
|
201
|
+
when Hash
|
202
|
+
obj.with_indifferent_access
|
203
|
+
else
|
204
|
+
ActiveSupport::HashWithIndifferentAccess.new
|
205
|
+
end
|
206
206
|
end
|
207
207
|
end
|
208
|
-
end
|
209
208
|
end
|
210
209
|
end
|
@@ -30,10 +30,11 @@ module ActiveRecord
|
|
30
30
|
|
31
31
|
module ClassMethods
|
32
32
|
def suppress(&block)
|
33
|
+
previous_state = SuppressorRegistry.suppressed[name]
|
33
34
|
SuppressorRegistry.suppressed[name] = true
|
34
35
|
yield
|
35
36
|
ensure
|
36
|
-
SuppressorRegistry.suppressed[name] =
|
37
|
+
SuppressorRegistry.suppressed[name] = previous_state
|
37
38
|
end
|
38
39
|
end
|
39
40
|
|
@@ -10,9 +10,7 @@ module ActiveRecord
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def resolve_column_aliases(hash)
|
13
|
-
|
14
|
-
# https://bugs.ruby-lang.org/issues/7166
|
15
|
-
new_hash = Hash[hash]
|
13
|
+
new_hash = hash.dup
|
16
14
|
hash.each do |key, _|
|
17
15
|
if (key.is_a?(Symbol)) && klass.attribute_alias?(key)
|
18
16
|
new_hash[klass.attribute_alias(key)] = new_hash.delete(key)
|
@@ -33,10 +31,14 @@ module ActiveRecord
|
|
33
31
|
if klass
|
34
32
|
klass.type_for_attribute(column_name.to_s)
|
35
33
|
else
|
36
|
-
Type
|
34
|
+
Type.default_value
|
37
35
|
end
|
38
36
|
end
|
39
37
|
|
38
|
+
def has_column?(column_name)
|
39
|
+
klass && klass.columns_hash.key?(column_name.to_s)
|
40
|
+
end
|
41
|
+
|
40
42
|
def associated_with?(association_name)
|
41
43
|
klass && klass._reflect_on_association(association_name)
|
42
44
|
end
|
@@ -62,8 +64,10 @@ module ActiveRecord
|
|
62
64
|
association && association.polymorphic?
|
63
65
|
end
|
64
66
|
|
67
|
+
# TODO Change this to private once we've dropped Ruby 2.2 support.
|
68
|
+
# Workaround for Ruby 2.2 "private attribute?" warning.
|
65
69
|
protected
|
66
70
|
|
67
|
-
|
71
|
+
attr_reader :klass, :arel_table, :association
|
68
72
|
end
|
69
73
|
end
|