activerecord 5.0.7.2 → 5.1.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 +5 -5
- data/CHANGELOG.md +389 -2252
- 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.rb +20 -20
- data/lib/active_record/aggregations.rb +244 -244
- data/lib/active_record/association_relation.rb +5 -5
- data/lib/active_record/associations.rb +1579 -1569
- data/lib/active_record/associations/alias_tracker.rb +1 -1
- data/lib/active_record/associations/association.rb +23 -15
- data/lib/active_record/associations/association_scope.rb +83 -81
- data/lib/active_record/associations/belongs_to_association.rb +0 -1
- data/lib/active_record/associations/builder/belongs_to.rb +16 -14
- 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 +74 -241
- data/lib/active_record/associations/collection_proxy.rb +144 -70
- data/lib/active_record/associations/has_many_association.rb +15 -19
- data/lib/active_record/associations/has_many_through_association.rb +12 -5
- data/lib/active_record/associations/has_one_association.rb +22 -28
- data/lib/active_record/associations/has_one_through_association.rb +5 -1
- data/lib/active_record/associations/join_dependency.rb +117 -115
- data/lib/active_record/associations/join_dependency/join_association.rb +16 -13
- 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/preloader.rb +94 -94
- data/lib/active_record/associations/preloader/association.rb +87 -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 +34 -41
- data/lib/active_record/associations/singular_association.rb +8 -25
- data/lib/active_record/associations/through_association.rb +3 -6
- data/lib/active_record/attribute.rb +98 -71
- data/lib/active_record/attribute/user_provided_default.rb +4 -2
- data/lib/active_record/attribute_assignment.rb +61 -61
- data/lib/active_record/attribute_decorators.rb +35 -13
- data/lib/active_record/attribute_methods.rb +56 -65
- data/lib/active_record/attribute_methods/before_type_cast.rb +7 -7
- data/lib/active_record/attribute_methods/dirty.rb +216 -34
- data/lib/active_record/attribute_methods/primary_key.rb +78 -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 +36 -30
- data/lib/active_record/attribute_mutation_tracker.rb +53 -10
- data/lib/active_record/attribute_set.rb +9 -6
- data/lib/active_record/attribute_set/builder.rb +41 -49
- data/lib/active_record/attribute_set/yaml_encoder.rb +41 -0
- data/lib/active_record/attributes.rb +21 -21
- data/lib/active_record/autosave_association.rb +13 -13
- data/lib/active_record/base.rb +24 -22
- data/lib/active_record/callbacks.rb +52 -14
- data/lib/active_record/coders/yaml_column.rb +9 -11
- data/lib/active_record/collection_cache_key.rb +6 -17
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +320 -278
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +1 -3
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +22 -34
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +31 -27
- data/lib/active_record/connection_adapters/abstract/quoting.rb +44 -57
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +9 -19
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +78 -79
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +53 -41
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +99 -93
- data/lib/active_record/connection_adapters/abstract/transaction.rb +1 -5
- data/lib/active_record/connection_adapters/abstract_adapter.rb +156 -128
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +424 -382
- data/lib/active_record/connection_adapters/column.rb +27 -5
- 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 +45 -43
- 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 +49 -31
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +5 -6
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +24 -26
- data/lib/active_record/connection_adapters/postgresql/column.rb +1 -28
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +46 -35
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid.rb +22 -21
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +9 -9
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +1 -1
- 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/enum.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +16 -16
- 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 +28 -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/quoting.rb +38 -36
- 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 +161 -170
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -7
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +179 -152
- 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 -20
- 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_adapter.rb +187 -130
- 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 +110 -93
- data/lib/active_record/counter_cache.rb +62 -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 +58 -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 +3 -3
- 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 +64 -56
- data/lib/active_record/locking/pessimistic.rb +10 -1
- data/lib/active_record/log_subscriber.rb +29 -29
- data/lib/active_record/migration.rb +155 -172
- data/lib/active_record/migration/command_recorder.rb +94 -94
- data/lib/active_record/migration/compatibility.rb +76 -37
- data/lib/active_record/migration/join_table.rb +6 -6
- data/lib/active_record/model_schema.rb +85 -119
- data/lib/active_record/nested_attributes.rb +200 -199
- data/lib/active_record/null_relation.rb +10 -33
- data/lib/active_record/persistence.rb +45 -38
- data/lib/active_record/query_cache.rb +4 -8
- data/lib/active_record/querying.rb +2 -3
- 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 +125 -140
- 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 +79 -96
- data/lib/active_record/relation.rb +72 -115
- data/lib/active_record/relation/batches.rb +87 -58
- data/lib/active_record/relation/batches/batch_enumerator.rb +1 -1
- data/lib/active_record/relation/calculations.rb +154 -160
- data/lib/active_record/relation/delegation.rb +30 -29
- data/lib/active_record/relation/finder_methods.rb +195 -226
- data/lib/active_record/relation/merger.rb +58 -62
- data/lib/active_record/relation/predicate_builder.rb +92 -89
- 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/query_attribute.rb +1 -1
- data/lib/active_record/relation/query_methods.rb +247 -295
- 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 +79 -65
- data/lib/active_record/relation/where_clause_factory.rb +47 -8
- data/lib/active_record/result.rb +29 -31
- data/lib/active_record/runtime_registry.rb +3 -3
- data/lib/active_record/sanitization.rb +182 -197
- data/lib/active_record/schema.rb +3 -3
- data/lib/active_record/schema_dumper.rb +14 -37
- data/lib/active_record/schema_migration.rb +3 -3
- data/lib/active_record/scoping.rb +9 -10
- data/lib/active_record/scoping/default.rb +87 -91
- data/lib/active_record/scoping/named.rb +16 -28
- 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 +72 -65
- data/lib/active_record/tasks/mysql_database_tasks.rb +75 -72
- data/lib/active_record/tasks/postgresql_database_tasks.rb +53 -48
- data/lib/active_record/tasks/sqlite_database_tasks.rb +18 -16
- data/lib/active_record/timestamp.rb +39 -25
- data/lib/active_record/touch_later.rb +1 -2
- data/lib/active_record/transactions.rb +98 -110
- data/lib/active_record/type.rb +17 -13
- data/lib/active_record/type/adapter_specific_registry.rb +46 -42
- data/lib/active_record/type/decimal_without_scale.rb +9 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +3 -3
- data/lib/active_record/type/serialized.rb +8 -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_caster.rb +2 -2
- data/lib/active_record/type_caster/connection.rb +8 -6
- data/lib/active_record/type_caster/map.rb +3 -1
- data/lib/active_record/validations.rb +4 -4
- 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/version.rb +1 -1
- data/lib/rails/generators/active_record.rb +4 -4
- data/lib/rails/generators/active_record/migration.rb +2 -2
- data/lib/rails/generators/active_record/migration/migration_generator.rb +37 -34
- data/lib/rails/generators/active_record/model/model_generator.rb +9 -9
- metadata +22 -13
- data/lib/active_record/relation/predicate_builder/class_handler.rb +0 -27
data/lib/active_record/schema.rb
CHANGED
@@ -40,7 +40,7 @@ module ActiveRecord
|
|
40
40
|
# ActiveRecord::Schema.define(version: 20380119000001) do
|
41
41
|
# ...
|
42
42
|
# end
|
43
|
-
def self.define(info={}, &block)
|
43
|
+
def self.define(info = {}, &block)
|
44
44
|
new.define(info, &block)
|
45
45
|
end
|
46
46
|
|
@@ -48,7 +48,7 @@ module ActiveRecord
|
|
48
48
|
instance_eval(&block)
|
49
49
|
|
50
50
|
if info[:version].present?
|
51
|
-
|
51
|
+
ActiveRecord::SchemaMigration.create_table
|
52
52
|
connection.assume_migrated_upto_version(info[:version], migrations_paths)
|
53
53
|
end
|
54
54
|
|
@@ -61,7 +61,7 @@ module ActiveRecord
|
|
61
61
|
#
|
62
62
|
# ActiveRecord::Schema.new.migrations_paths
|
63
63
|
# # => ["db/migrate"] # Rails migration path by default.
|
64
|
-
def migrations_paths
|
64
|
+
def migrations_paths
|
65
65
|
ActiveRecord::Migrator.migrations_paths
|
66
66
|
end
|
67
67
|
end
|
@@ -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
|
@@ -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
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "active_support/per_thread_registry"
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
4
|
module Scoping
|
@@ -10,8 +10,8 @@ module ActiveRecord
|
|
10
10
|
end
|
11
11
|
|
12
12
|
module ClassMethods
|
13
|
-
def current_scope
|
14
|
-
ScopeRegistry.value_for(:current_scope, self
|
13
|
+
def current_scope #:nodoc:
|
14
|
+
ScopeRegistry.value_for(:current_scope, self)
|
15
15
|
end
|
16
16
|
|
17
17
|
def current_scope=(scope) #:nodoc:
|
@@ -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
|
@@ -75,9 +75,8 @@ module ActiveRecord
|
|
75
75
|
end
|
76
76
|
|
77
77
|
# Obtains the value for a given +scope_type+ and +model+.
|
78
|
-
def value_for(scope_type, model
|
78
|
+
def value_for(scope_type, model)
|
79
79
|
raise_invalid_scope_type!(scope_type)
|
80
|
-
return @registry[scope_type][model.name] if skip_inherited_scope
|
81
80
|
klass = model
|
82
81
|
base = model.base_class
|
83
82
|
while klass <= base
|
@@ -95,11 +94,11 @@ module ActiveRecord
|
|
95
94
|
|
96
95
|
private
|
97
96
|
|
98
|
-
|
99
|
-
|
100
|
-
|
97
|
+
def raise_invalid_scope_type!(scope_type)
|
98
|
+
if !VALID_SCOPE_TYPES.include?(scope_type)
|
99
|
+
raise ArgumentError, "Invalid scope type '#{scope_type}' sent to the registry. Scope types must be included in VALID_SCOPE_TYPES"
|
100
|
+
end
|
101
101
|
end
|
102
|
-
end
|
103
102
|
end
|
104
103
|
end
|
105
104
|
end
|
@@ -44,109 +44,105 @@ 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
|
-
end
|
110
|
-
|
111
|
-
if self.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
|
107
|
+
if default_scope_override.nil?
|
108
|
+
self.default_scope_override = !Base.is_a?(method(:default_scope).owner)
|
117
109
|
end
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
110
|
+
|
111
|
+
if default_scope_override
|
112
|
+
# The user has defined their own default scope method, so call that
|
113
|
+
evaluate_default_scope { default_scope }
|
114
|
+
elsif default_scopes.any?
|
115
|
+
base_rel ||= relation
|
116
|
+
evaluate_default_scope do
|
117
|
+
default_scopes.inject(base_rel) do |default_scope, scope|
|
118
|
+
scope = scope.respond_to?(:to_proc) ? scope : scope.method(:call)
|
119
|
+
default_scope.merge(base_rel.instance_exec(&scope))
|
120
|
+
end
|
124
121
|
end
|
125
122
|
end
|
126
123
|
end
|
127
|
-
end
|
128
124
|
|
129
|
-
|
130
|
-
|
131
|
-
|
125
|
+
def ignore_default_scope?
|
126
|
+
ScopeRegistry.value_for(:ignore_default_scope, base_class)
|
127
|
+
end
|
132
128
|
|
133
|
-
|
134
|
-
|
135
|
-
|
129
|
+
def ignore_default_scope=(ignore)
|
130
|
+
ScopeRegistry.set_value_for(:ignore_default_scope, base_class, ignore)
|
131
|
+
end
|
136
132
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
133
|
+
# The ignore_default_scope flag is used to prevent an infinite recursion
|
134
|
+
# situation where a default scope references a scope which has a default
|
135
|
+
# scope which references a scope...
|
136
|
+
def evaluate_default_scope
|
137
|
+
return if ignore_default_scope?
|
138
|
+
|
139
|
+
begin
|
140
|
+
self.ignore_default_scope = true
|
141
|
+
yield
|
142
|
+
ensure
|
143
|
+
self.ignore_default_scope = false
|
144
|
+
end
|
148
145
|
end
|
149
|
-
end
|
150
146
|
end
|
151
147
|
end
|
152
148
|
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
|
@@ -29,32 +29,20 @@ module ActiveRecord
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
-
def
|
33
|
-
|
32
|
+
def default_scoped # :nodoc:
|
33
|
+
scope = build_default_scope
|
34
34
|
|
35
|
-
if
|
36
|
-
scope
|
35
|
+
if scope
|
36
|
+
relation.spawn.merge!(scope)
|
37
37
|
else
|
38
|
-
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
def default_scoped(scope = relation) # :nodoc:
|
43
|
-
build_default_scope(scope) || scope
|
44
|
-
end
|
45
|
-
|
46
|
-
def default_extensions # :nodoc:
|
47
|
-
if scope = current_scope || build_default_scope
|
48
|
-
scope.extensions
|
49
|
-
else
|
50
|
-
[]
|
38
|
+
relation
|
51
39
|
end
|
52
40
|
end
|
53
41
|
|
54
42
|
# Adds a class method for retrieving and querying objects.
|
55
43
|
# The method is intended to return an ActiveRecord::Relation
|
56
44
|
# object, which is composable with other scopes.
|
57
|
-
# If it returns nil or false
|
45
|
+
# If it returns +nil+ or +false+, an
|
58
46
|
# {all}[rdoc-ref:Scoping::Named::ClassMethods#all] scope is returned instead.
|
59
47
|
#
|
60
48
|
# A \scope represents a narrowing of a database query, such as
|
@@ -154,7 +142,7 @@ module ActiveRecord
|
|
154
142
|
# Article.featured.titles
|
155
143
|
def scope(name, body, &block)
|
156
144
|
unless body.respond_to?(:call)
|
157
|
-
raise ArgumentError,
|
145
|
+
raise ArgumentError, "The scope body needs to be callable."
|
158
146
|
end
|
159
147
|
|
160
148
|
if dangerous_class_method?(name)
|
@@ -183,14 +171,14 @@ module ActiveRecord
|
|
183
171
|
end
|
184
172
|
end
|
185
173
|
|
186
|
-
|
174
|
+
private
|
187
175
|
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
176
|
+
def valid_scope_name?(name)
|
177
|
+
if respond_to?(name, true) && logger
|
178
|
+
logger.warn "Creating scope :#{name}. " \
|
179
|
+
"Overwriting existing method #{self.name}.#{name}."
|
180
|
+
end
|
192
181
|
end
|
193
|
-
end
|
194
182
|
end
|
195
183
|
end
|
196
184
|
end
|