activerecord 3.2.22.5 → 4.0.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 +1024 -543
- data/MIT-LICENSE +1 -1
- data/README.rdoc +20 -29
- data/examples/performance.rb +1 -1
- data/lib/active_record.rb +55 -44
- data/lib/active_record/aggregations.rb +40 -34
- data/lib/active_record/associations.rb +204 -276
- data/lib/active_record/associations/alias_tracker.rb +1 -1
- data/lib/active_record/associations/association.rb +30 -35
- data/lib/active_record/associations/association_scope.rb +40 -40
- data/lib/active_record/associations/belongs_to_association.rb +15 -2
- data/lib/active_record/associations/builder/association.rb +81 -28
- data/lib/active_record/associations/builder/belongs_to.rb +35 -57
- data/lib/active_record/associations/builder/collection_association.rb +54 -40
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +23 -41
- data/lib/active_record/associations/builder/has_many.rb +8 -64
- data/lib/active_record/associations/builder/has_one.rb +13 -50
- data/lib/active_record/associations/builder/singular_association.rb +13 -13
- data/lib/active_record/associations/collection_association.rb +92 -88
- data/lib/active_record/associations/collection_proxy.rb +913 -63
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +12 -10
- data/lib/active_record/associations/has_many_association.rb +35 -9
- data/lib/active_record/associations/has_many_through_association.rb +24 -14
- data/lib/active_record/associations/has_one_association.rb +33 -13
- data/lib/active_record/associations/has_one_through_association.rb +1 -1
- data/lib/active_record/associations/join_dependency.rb +2 -2
- data/lib/active_record/associations/join_dependency/join_association.rb +17 -22
- data/lib/active_record/associations/join_dependency/join_part.rb +1 -1
- data/lib/active_record/associations/join_helper.rb +1 -11
- data/lib/active_record/associations/preloader.rb +14 -17
- data/lib/active_record/associations/preloader/association.rb +29 -33
- data/lib/active_record/associations/preloader/collection_association.rb +1 -1
- data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +1 -1
- data/lib/active_record/associations/preloader/has_many_through.rb +1 -1
- data/lib/active_record/associations/preloader/has_one.rb +1 -1
- data/lib/active_record/associations/preloader/through_association.rb +13 -17
- data/lib/active_record/associations/singular_association.rb +11 -11
- data/lib/active_record/associations/through_association.rb +2 -2
- data/lib/active_record/attribute_assignment.rb +133 -153
- data/lib/active_record/attribute_methods.rb +196 -93
- data/lib/active_record/attribute_methods/before_type_cast.rb +44 -5
- data/lib/active_record/attribute_methods/dirty.rb +31 -28
- data/lib/active_record/attribute_methods/primary_key.rb +38 -30
- data/lib/active_record/attribute_methods/query.rb +5 -4
- data/lib/active_record/attribute_methods/read.rb +62 -91
- data/lib/active_record/attribute_methods/serialization.rb +97 -66
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +39 -45
- data/lib/active_record/attribute_methods/write.rb +32 -39
- data/lib/active_record/autosave_association.rb +56 -70
- data/lib/active_record/base.rb +53 -450
- data/lib/active_record/callbacks.rb +53 -18
- data/lib/active_record/coders/yaml_column.rb +11 -9
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +353 -197
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +9 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +130 -131
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +24 -19
- data/lib/active_record/connection_adapters/abstract/quoting.rb +23 -3
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +101 -91
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +59 -0
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +225 -96
- data/lib/active_record/connection_adapters/abstract/transaction.rb +203 -0
- data/lib/active_record/connection_adapters/abstract_adapter.rb +99 -46
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +114 -36
- data/lib/active_record/connection_adapters/column.rb +46 -24
- data/lib/active_record/connection_adapters/connection_specification.rb +96 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +16 -32
- data/lib/active_record/connection_adapters/mysql_adapter.rb +181 -64
- data/lib/active_record/connection_adapters/postgresql/array_parser.rb +97 -0
- data/lib/active_record/connection_adapters/postgresql/cast.rb +132 -0
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +242 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +347 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +158 -0
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +30 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +448 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +454 -885
- data/lib/active_record/connection_adapters/schema_cache.rb +48 -16
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +574 -13
- data/lib/active_record/connection_handling.rb +98 -0
- data/lib/active_record/core.rb +428 -0
- data/lib/active_record/counter_cache.rb +106 -108
- data/lib/active_record/dynamic_matchers.rb +110 -63
- data/lib/active_record/errors.rb +25 -8
- data/lib/active_record/explain.rb +8 -58
- data/lib/active_record/explain_subscriber.rb +6 -3
- data/lib/active_record/fixture_set/file.rb +56 -0
- data/lib/active_record/fixtures.rb +146 -148
- data/lib/active_record/inheritance.rb +77 -59
- data/lib/active_record/integration.rb +5 -5
- data/lib/active_record/locale/en.yml +8 -1
- data/lib/active_record/locking/optimistic.rb +38 -42
- data/lib/active_record/locking/pessimistic.rb +4 -4
- data/lib/active_record/log_subscriber.rb +19 -9
- data/lib/active_record/migration.rb +318 -153
- data/lib/active_record/migration/command_recorder.rb +90 -31
- data/lib/active_record/migration/join_table.rb +15 -0
- data/lib/active_record/model_schema.rb +69 -92
- data/lib/active_record/nested_attributes.rb +113 -148
- data/lib/active_record/null_relation.rb +65 -0
- data/lib/active_record/persistence.rb +188 -97
- data/lib/active_record/query_cache.rb +18 -36
- data/lib/active_record/querying.rb +19 -15
- data/lib/active_record/railtie.rb +91 -36
- data/lib/active_record/railties/console_sandbox.rb +0 -2
- data/lib/active_record/railties/controller_runtime.rb +2 -2
- data/lib/active_record/railties/databases.rake +90 -309
- data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
- data/lib/active_record/readonly_attributes.rb +7 -3
- data/lib/active_record/reflection.rb +72 -56
- data/lib/active_record/relation.rb +241 -157
- data/lib/active_record/relation/batches.rb +25 -22
- data/lib/active_record/relation/calculations.rb +143 -121
- data/lib/active_record/relation/delegation.rb +96 -18
- data/lib/active_record/relation/finder_methods.rb +117 -183
- data/lib/active_record/relation/merger.rb +133 -0
- data/lib/active_record/relation/predicate_builder.rb +90 -42
- data/lib/active_record/relation/query_methods.rb +666 -136
- data/lib/active_record/relation/spawn_methods.rb +43 -150
- data/lib/active_record/result.rb +33 -6
- data/lib/active_record/sanitization.rb +24 -50
- data/lib/active_record/schema.rb +19 -12
- data/lib/active_record/schema_dumper.rb +31 -39
- data/lib/active_record/schema_migration.rb +36 -0
- data/lib/active_record/scoping.rb +0 -124
- data/lib/active_record/scoping/default.rb +48 -45
- data/lib/active_record/scoping/named.rb +74 -103
- data/lib/active_record/serialization.rb +6 -2
- data/lib/active_record/serializers/xml_serializer.rb +9 -15
- data/lib/active_record/store.rb +119 -15
- data/lib/active_record/tasks/database_tasks.rb +158 -0
- data/lib/active_record/tasks/mysql_database_tasks.rb +138 -0
- data/lib/active_record/tasks/postgresql_database_tasks.rb +90 -0
- data/lib/active_record/tasks/sqlite_database_tasks.rb +51 -0
- data/lib/active_record/test_case.rb +61 -38
- data/lib/active_record/timestamp.rb +8 -9
- data/lib/active_record/transactions.rb +65 -51
- data/lib/active_record/validations.rb +17 -15
- data/lib/active_record/validations/associated.rb +20 -14
- data/lib/active_record/validations/presence.rb +65 -0
- data/lib/active_record/validations/uniqueness.rb +93 -52
- data/lib/active_record/version.rb +4 -4
- data/lib/rails/generators/active_record.rb +3 -5
- data/lib/rails/generators/active_record/migration/migration_generator.rb +37 -7
- data/lib/rails/generators/active_record/migration/templates/migration.rb +20 -15
- data/lib/rails/generators/active_record/model/model_generator.rb +4 -3
- data/lib/rails/generators/active_record/model/templates/model.rb +1 -6
- data/lib/rails/generators/active_record/model/templates/module.rb +1 -1
- metadata +53 -46
- data/lib/active_record/attribute_methods/deprecated_underscore_read.rb +0 -32
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +0 -191
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +0 -583
- data/lib/active_record/dynamic_finder_match.rb +0 -68
- data/lib/active_record/dynamic_scope_match.rb +0 -23
- data/lib/active_record/fixtures/file.rb +0 -65
- data/lib/active_record/identity_map.rb +0 -162
- data/lib/active_record/observer.rb +0 -121
- data/lib/active_record/session_store.rb +0 -360
- data/lib/rails/generators/active_record/migration.rb +0 -15
- data/lib/rails/generators/active_record/observer/observer_generator.rb +0 -15
- data/lib/rails/generators/active_record/observer/templates/observer.rb +0 -4
- data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +0 -25
- data/lib/rails/generators/active_record/session_migration/templates/migration.rb +0 -12
@@ -24,6 +24,7 @@ module ActiveRecord
|
|
24
24
|
|
25
25
|
def dump(stream)
|
26
26
|
header(stream)
|
27
|
+
extensions(stream)
|
27
28
|
tables(stream)
|
28
29
|
trailer(stream)
|
29
30
|
stream
|
@@ -38,7 +39,7 @@ module ActiveRecord
|
|
38
39
|
end
|
39
40
|
|
40
41
|
def header(stream)
|
41
|
-
define_params = @version ? ":
|
42
|
+
define_params = @version ? "version: #{@version}" : ""
|
42
43
|
|
43
44
|
if stream.respond_to?(:external_encoding) && stream.external_encoding
|
44
45
|
stream.puts "# encoding: #{stream.external_encoding.name}"
|
@@ -55,7 +56,7 @@ module ActiveRecord
|
|
55
56
|
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
|
56
57
|
# you'll amass, the slower it'll run and the greater likelihood for issues).
|
57
58
|
#
|
58
|
-
# It's strongly recommended
|
59
|
+
# It's strongly recommended that you check this file into your version control system.
|
59
60
|
|
60
61
|
ActiveRecord::Schema.define(#{define_params}) do
|
61
62
|
|
@@ -66,6 +67,18 @@ HEADER
|
|
66
67
|
stream.puts "end"
|
67
68
|
end
|
68
69
|
|
70
|
+
def extensions(stream)
|
71
|
+
return unless @connection.supports_extensions?
|
72
|
+
extensions = @connection.extensions
|
73
|
+
if extensions.any?
|
74
|
+
stream.puts " # These are extensions that must be enabled in order to support this database"
|
75
|
+
extensions.each do |extension|
|
76
|
+
stream.puts " enable_extension #{extension.inspect}"
|
77
|
+
end
|
78
|
+
stream.puts
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
69
82
|
def tables(stream)
|
70
83
|
@connection.tables.sort.each do |tbl|
|
71
84
|
next if ['schema_migrations', ignore_tables].flatten.any? do |ignored|
|
@@ -95,42 +108,30 @@ HEADER
|
|
95
108
|
tbl.print " create_table #{remove_prefix_and_suffix(table).inspect}"
|
96
109
|
if columns.detect { |c| c.name == pk }
|
97
110
|
if pk != 'id'
|
98
|
-
tbl.print %Q(, :
|
111
|
+
tbl.print %Q(, primary_key: "#{pk}")
|
99
112
|
end
|
100
113
|
else
|
101
|
-
tbl.print ", :
|
114
|
+
tbl.print ", id: false"
|
102
115
|
end
|
103
|
-
tbl.print ", :
|
116
|
+
tbl.print ", force: true"
|
104
117
|
tbl.puts " do |t|"
|
105
118
|
|
106
119
|
# then dump all non-primary key columns
|
107
120
|
column_specs = columns.map do |column|
|
108
121
|
raise StandardError, "Unknown type '#{column.sql_type}' for column '#{column.name}'" if @types[column.type].nil?
|
109
122
|
next if column.name == pk
|
110
|
-
|
111
|
-
spec[:name] = column.name.inspect
|
112
|
-
|
113
|
-
# AR has an optimization which handles zero-scale decimals as integers. This
|
114
|
-
# code ensures that the dumper still dumps the column as a decimal.
|
115
|
-
spec[:type] = if column.type == :integer && [/^numeric/, /^decimal/].any? { |e| e.match(column.sql_type) }
|
116
|
-
'decimal'
|
117
|
-
else
|
118
|
-
column.type.to_s
|
119
|
-
end
|
120
|
-
spec[:limit] = column.limit.inspect if column.limit != @types[column.type][:limit] && spec[:type] != 'decimal'
|
121
|
-
spec[:precision] = column.precision.inspect if column.precision
|
122
|
-
spec[:scale] = column.scale.inspect if column.scale
|
123
|
-
spec[:null] = 'false' unless column.null
|
124
|
-
spec[:default] = default_string(column.default) if column.has_default?
|
125
|
-
(spec.keys - [:name, :type]).each{ |k| spec[k].insert(0, "#{k.inspect} => ")}
|
126
|
-
spec
|
123
|
+
@connection.column_spec(column, @types)
|
127
124
|
end.compact
|
128
125
|
|
129
126
|
# find all migration keys used in this table
|
130
|
-
keys =
|
127
|
+
keys = @connection.migration_keys
|
131
128
|
|
132
129
|
# figure out the lengths for each column based on above keys
|
133
|
-
lengths = keys.map{ |key|
|
130
|
+
lengths = keys.map { |key|
|
131
|
+
column_specs.map { |spec|
|
132
|
+
spec[key] ? spec[key].length + 2 : 0
|
133
|
+
}.max
|
134
|
+
}
|
134
135
|
|
135
136
|
# the string we're going to sprintf our values against, with standardized column widths
|
136
137
|
format_string = lengths.map{ |len| "%-#{len}s" }
|
@@ -166,32 +167,23 @@ HEADER
|
|
166
167
|
stream
|
167
168
|
end
|
168
169
|
|
169
|
-
def default_string(value)
|
170
|
-
case value
|
171
|
-
when BigDecimal
|
172
|
-
value.to_s
|
173
|
-
when Date, DateTime, Time
|
174
|
-
"'" + value.to_s(:db) + "'"
|
175
|
-
else
|
176
|
-
value.inspect
|
177
|
-
end
|
178
|
-
end
|
179
|
-
|
180
170
|
def indexes(table, stream)
|
181
171
|
if (indexes = @connection.indexes(table)).any?
|
182
172
|
add_index_statements = indexes.map do |index|
|
183
173
|
statement_parts = [
|
184
174
|
('add_index ' + remove_prefix_and_suffix(index.table).inspect),
|
185
175
|
index.columns.inspect,
|
186
|
-
(':
|
176
|
+
('name: ' + index.name.inspect),
|
187
177
|
]
|
188
|
-
statement_parts << ':
|
178
|
+
statement_parts << 'unique: true' if index.unique
|
189
179
|
|
190
180
|
index_lengths = (index.lengths || []).compact
|
191
|
-
statement_parts << (':
|
181
|
+
statement_parts << ('length: ' + Hash[index.columns.zip(index.lengths)].inspect) unless index_lengths.empty?
|
192
182
|
|
193
183
|
index_orders = (index.orders || {})
|
194
|
-
statement_parts << (':
|
184
|
+
statement_parts << ('order: ' + index.orders.inspect) unless index_orders.empty?
|
185
|
+
|
186
|
+
statement_parts << ('where: ' + index.where.inspect) if index.where
|
195
187
|
|
196
188
|
' ' + statement_parts.join(', ')
|
197
189
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'active_record/scoping/default'
|
2
|
+
require 'active_record/scoping/named'
|
3
|
+
require 'active_record/base'
|
4
|
+
|
5
|
+
module ActiveRecord
|
6
|
+
class SchemaMigration < ActiveRecord::Base
|
7
|
+
|
8
|
+
def self.table_name
|
9
|
+
"#{Base.table_name_prefix}schema_migrations#{Base.table_name_suffix}"
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.index_name
|
13
|
+
"#{Base.table_name_prefix}unique_schema_migrations#{Base.table_name_suffix}"
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.create_table
|
17
|
+
unless connection.table_exists?(table_name)
|
18
|
+
connection.create_table(table_name, :id => false) do |t|
|
19
|
+
t.column :version, :string, :null => false
|
20
|
+
end
|
21
|
+
connection.add_index table_name, :version, :unique => true, :name => index_name
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.drop_table
|
26
|
+
if connection.table_exists?(table_name)
|
27
|
+
connection.remove_index table_name, :name => index_name
|
28
|
+
connection.drop_table(table_name)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def version
|
33
|
+
super.to_i
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'active_support/concern'
|
2
|
-
|
3
1
|
module ActiveRecord
|
4
2
|
module Scoping
|
5
3
|
extend ActiveSupport::Concern
|
@@ -10,118 +8,6 @@ module ActiveRecord
|
|
10
8
|
end
|
11
9
|
|
12
10
|
module ClassMethods
|
13
|
-
# with_scope lets you apply options to inner block incrementally. It takes a hash and the keys must be
|
14
|
-
# <tt>:find</tt> or <tt>:create</tt>. <tt>:find</tt> parameter is <tt>Relation</tt> while
|
15
|
-
# <tt>:create</tt> parameters are an attributes hash.
|
16
|
-
#
|
17
|
-
# class Article < ActiveRecord::Base
|
18
|
-
# def self.create_with_scope
|
19
|
-
# with_scope(:find => where(:blog_id => 1), :create => { :blog_id => 1 }) do
|
20
|
-
# find(1) # => SELECT * from articles WHERE blog_id = 1 AND id = 1
|
21
|
-
# a = create(1)
|
22
|
-
# a.blog_id # => 1
|
23
|
-
# end
|
24
|
-
# end
|
25
|
-
# end
|
26
|
-
#
|
27
|
-
# In nested scopings, all previous parameters are overwritten by the innermost rule, with the exception of
|
28
|
-
# <tt>where</tt>, <tt>includes</tt>, and <tt>joins</tt> operations in <tt>Relation</tt>, which are merged.
|
29
|
-
#
|
30
|
-
# <tt>joins</tt> operations are uniqued so multiple scopes can join in the same table without table aliasing
|
31
|
-
# problems. If you need to join multiple tables, but still want one of the tables to be uniqued, use the
|
32
|
-
# array of strings format for your joins.
|
33
|
-
#
|
34
|
-
# class Article < ActiveRecord::Base
|
35
|
-
# def self.find_with_scope
|
36
|
-
# with_scope(:find => where(:blog_id => 1).limit(1), :create => { :blog_id => 1 }) do
|
37
|
-
# with_scope(:find => limit(10)) do
|
38
|
-
# all # => SELECT * from articles WHERE blog_id = 1 LIMIT 10
|
39
|
-
# end
|
40
|
-
# with_scope(:find => where(:author_id => 3)) do
|
41
|
-
# all # => SELECT * from articles WHERE blog_id = 1 AND author_id = 3 LIMIT 1
|
42
|
-
# end
|
43
|
-
# end
|
44
|
-
# end
|
45
|
-
# end
|
46
|
-
#
|
47
|
-
# You can ignore any previous scopings by using the <tt>with_exclusive_scope</tt> method.
|
48
|
-
#
|
49
|
-
# class Article < ActiveRecord::Base
|
50
|
-
# def self.find_with_exclusive_scope
|
51
|
-
# with_scope(:find => where(:blog_id => 1).limit(1)) do
|
52
|
-
# with_exclusive_scope(:find => limit(10)) do
|
53
|
-
# all # => SELECT * from articles LIMIT 10
|
54
|
-
# end
|
55
|
-
# end
|
56
|
-
# end
|
57
|
-
# end
|
58
|
-
#
|
59
|
-
# *Note*: the +:find+ scope also has effect on update and deletion methods, like +update_all+ and +delete_all+.
|
60
|
-
def with_scope(scope = {}, action = :merge, &block)
|
61
|
-
# If another Active Record class has been passed in, get its current scope
|
62
|
-
scope = scope.current_scope if !scope.is_a?(Relation) && scope.respond_to?(:current_scope)
|
63
|
-
|
64
|
-
previous_scope = self.current_scope
|
65
|
-
|
66
|
-
if scope.is_a?(Hash)
|
67
|
-
# Dup first and second level of hash (method and params).
|
68
|
-
scope = scope.dup
|
69
|
-
scope.each do |method, params|
|
70
|
-
scope[method] = params.dup unless params == true
|
71
|
-
end
|
72
|
-
|
73
|
-
scope.assert_valid_keys([ :find, :create ])
|
74
|
-
relation = construct_finder_arel(scope[:find] || {})
|
75
|
-
relation.default_scoped = true unless action == :overwrite
|
76
|
-
|
77
|
-
if previous_scope && previous_scope.create_with_value && scope[:create]
|
78
|
-
scope_for_create = if action == :merge
|
79
|
-
previous_scope.create_with_value.merge(scope[:create])
|
80
|
-
else
|
81
|
-
scope[:create]
|
82
|
-
end
|
83
|
-
|
84
|
-
relation = relation.create_with(scope_for_create)
|
85
|
-
else
|
86
|
-
scope_for_create = scope[:create]
|
87
|
-
scope_for_create ||= previous_scope.create_with_value if previous_scope
|
88
|
-
relation = relation.create_with(scope_for_create) if scope_for_create
|
89
|
-
end
|
90
|
-
|
91
|
-
scope = relation
|
92
|
-
end
|
93
|
-
|
94
|
-
scope = previous_scope.merge(scope) if previous_scope && action == :merge
|
95
|
-
|
96
|
-
self.current_scope = scope
|
97
|
-
begin
|
98
|
-
yield
|
99
|
-
ensure
|
100
|
-
self.current_scope = previous_scope
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
protected
|
105
|
-
|
106
|
-
# Works like with_scope, but discards any nested properties.
|
107
|
-
def with_exclusive_scope(method_scoping = {}, &block)
|
108
|
-
if method_scoping.values.any? { |e| e.is_a?(ActiveRecord::Relation) }
|
109
|
-
raise ArgumentError, <<-MSG
|
110
|
-
New finder API can not be used with_exclusive_scope. You can either call unscoped to get an anonymous scope not bound to the default_scope:
|
111
|
-
|
112
|
-
User.unscoped.where(:active => true)
|
113
|
-
|
114
|
-
Or call unscoped with a block:
|
115
|
-
|
116
|
-
User.unscoped do
|
117
|
-
User.where(:active => true).all
|
118
|
-
end
|
119
|
-
|
120
|
-
MSG
|
121
|
-
end
|
122
|
-
with_scope(method_scoping, :overwrite, &block)
|
123
|
-
end
|
124
|
-
|
125
11
|
def current_scope #:nodoc:
|
126
12
|
Thread.current["#{self}_current_scope"]
|
127
13
|
end
|
@@ -129,15 +15,6 @@ module ActiveRecord
|
|
129
15
|
def current_scope=(scope) #:nodoc:
|
130
16
|
Thread.current["#{self}_current_scope"] = scope
|
131
17
|
end
|
132
|
-
|
133
|
-
private
|
134
|
-
|
135
|
-
def construct_finder_arel(options = {}, scope = nil)
|
136
|
-
relation = options.is_a?(Hash) ? unscoped.apply_finder_options(options) : options
|
137
|
-
relation = scope.merge(relation) if scope
|
138
|
-
relation
|
139
|
-
end
|
140
|
-
|
141
18
|
end
|
142
19
|
|
143
20
|
def populate_with_current_scope_attributes
|
@@ -147,6 +24,5 @@ module ActiveRecord
|
|
147
24
|
send("#{att}=", value) if respond_to?("#{att}=")
|
148
25
|
end
|
149
26
|
end
|
150
|
-
|
151
27
|
end
|
152
28
|
end
|
@@ -1,22 +1,20 @@
|
|
1
|
-
require 'active_support/concern'
|
2
|
-
|
3
1
|
module ActiveRecord
|
4
2
|
module Scoping
|
5
3
|
module Default
|
6
4
|
extend ActiveSupport::Concern
|
7
5
|
|
8
6
|
included do
|
9
|
-
# Stores the default scope for the class
|
10
|
-
class_attribute :default_scopes, :
|
7
|
+
# Stores the default scope for the class.
|
8
|
+
class_attribute :default_scopes, instance_writer: false
|
11
9
|
self.default_scopes = []
|
12
10
|
end
|
13
11
|
|
14
12
|
module ClassMethods
|
15
|
-
# Returns a scope for the model without the default_scope
|
13
|
+
# Returns a scope for the model without the +default_scope+.
|
16
14
|
#
|
17
15
|
# class Post < ActiveRecord::Base
|
18
16
|
# def self.default_scope
|
19
|
-
# where :
|
17
|
+
# where published: true
|
20
18
|
# end
|
21
19
|
# end
|
22
20
|
#
|
@@ -24,20 +22,20 @@ module ActiveRecord
|
|
24
22
|
# Post.unscoped.all # Fires "SELECT * FROM posts"
|
25
23
|
#
|
26
24
|
# This method also accepts a block. All queries inside the block will
|
27
|
-
# not use the default_scope
|
25
|
+
# not use the +default_scope+:
|
28
26
|
#
|
29
27
|
# Post.unscoped {
|
30
28
|
# Post.limit(10) # Fires "SELECT * FROM posts LIMIT 10"
|
31
29
|
# }
|
32
30
|
#
|
33
|
-
# It is recommended
|
34
|
-
# unscoped with
|
35
|
-
#
|
36
|
-
# are equal: the default_scope is applied on both.
|
31
|
+
# It is recommended that you use the block form of unscoped because
|
32
|
+
# chaining unscoped with +scope+ does not work. Assuming that
|
33
|
+
# +published+ is a +scope+, the following two statements
|
34
|
+
# are equal: the +default_scope+ is applied on both.
|
37
35
|
#
|
38
36
|
# Post.unscoped.published
|
39
37
|
# Post.published
|
40
|
-
def unscoped
|
38
|
+
def unscoped
|
41
39
|
block_given? ? relation.scoping { yield } : relation
|
42
40
|
end
|
43
41
|
|
@@ -51,62 +49,67 @@ module ActiveRecord
|
|
51
49
|
# the model.
|
52
50
|
#
|
53
51
|
# class Article < ActiveRecord::Base
|
54
|
-
# default_scope where(:
|
52
|
+
# default_scope { where(published: true) }
|
55
53
|
# end
|
56
54
|
#
|
57
55
|
# Article.all # => SELECT * FROM articles WHERE published = true
|
58
56
|
#
|
59
|
-
# The
|
60
|
-
# applied while updating a record.
|
57
|
+
# The +default_scope+ is also applied while creating/building a record.
|
58
|
+
# It is not applied while updating a record.
|
61
59
|
#
|
62
60
|
# Article.new.published # => true
|
63
61
|
# Article.create.published # => true
|
64
62
|
#
|
65
|
-
# You can also
|
66
|
-
#
|
67
|
-
#
|
68
|
-
# default_scope { where(:published_at => Time.now - 1.week) }
|
69
|
-
# end
|
70
|
-
#
|
71
|
-
# (You can also pass any object which responds to <tt>call</tt> to the <tt>default_scope</tt>
|
72
|
-
# macro, and it will be called when building the default scope.)
|
63
|
+
# (You can also pass any object which responds to +call+ to the
|
64
|
+
# +default_scope+ macro, and it will be called when building the
|
65
|
+
# default scope.)
|
73
66
|
#
|
74
|
-
# If you use multiple
|
75
|
-
# be merged together:
|
67
|
+
# If you use multiple +default_scope+ declarations in your model then
|
68
|
+
# they will be merged together:
|
76
69
|
#
|
77
70
|
# class Article < ActiveRecord::Base
|
78
|
-
# default_scope where(:
|
79
|
-
# default_scope where(:
|
71
|
+
# default_scope { where(published: true) }
|
72
|
+
# default_scope { where(rating: 'G') }
|
80
73
|
# end
|
81
74
|
#
|
82
75
|
# Article.all # => SELECT * FROM articles WHERE published = true AND rating = 'G'
|
83
76
|
#
|
84
|
-
# This is also the case with inheritance and module includes where the
|
85
|
-
# defines a
|
77
|
+
# This is also the case with inheritance and module includes where the
|
78
|
+
# parent or module defines a +default_scope+ and the child or including
|
79
|
+
# class defines a second one.
|
86
80
|
#
|
87
|
-
# If you need to do more complex things with a default scope, you can
|
88
|
-
# define it as a class method:
|
81
|
+
# If you need to do more complex things with a default scope, you can
|
82
|
+
# alternatively define it as a class method:
|
89
83
|
#
|
90
84
|
# class Article < ActiveRecord::Base
|
91
85
|
# def self.default_scope
|
92
86
|
# # Should return a scope, you can call 'super' here etc.
|
93
87
|
# end
|
94
88
|
# end
|
95
|
-
def default_scope(scope =
|
89
|
+
def default_scope(scope = nil)
|
96
90
|
scope = Proc.new if block_given?
|
97
|
-
|
91
|
+
|
92
|
+
if scope.is_a?(Relation) || !scope.respond_to?(:call)
|
93
|
+
ActiveSupport::Deprecation.warn(
|
94
|
+
"Calling #default_scope without a block is deprecated. For example instead " \
|
95
|
+
"of `default_scope where(color: 'red')`, please use " \
|
96
|
+
"`default_scope { where(color: 'red') }`. (Alternatively you can just redefine " \
|
97
|
+
"self.default_scope.)"
|
98
|
+
)
|
99
|
+
end
|
100
|
+
|
101
|
+
self.default_scopes += [scope]
|
98
102
|
end
|
99
103
|
|
100
|
-
def build_default_scope
|
101
|
-
if method(:default_scope).owner
|
104
|
+
def build_default_scope # :nodoc:
|
105
|
+
if !Base.is_a?(method(:default_scope).owner)
|
106
|
+
# The user has defined their own default scope method, so call that
|
102
107
|
evaluate_default_scope { default_scope }
|
103
108
|
elsif default_scopes.any?
|
104
109
|
evaluate_default_scope do
|
105
110
|
default_scopes.inject(relation) do |default_scope, scope|
|
106
|
-
if scope.is_a?(
|
107
|
-
default_scope.
|
108
|
-
elsif !scope.is_a?(Relation) && scope.respond_to?(:call)
|
109
|
-
default_scope.merge(scope.call)
|
111
|
+
if !scope.is_a?(Relation) && scope.respond_to?(:call)
|
112
|
+
default_scope.merge(unscoped { scope.call })
|
110
113
|
else
|
111
114
|
default_scope.merge(scope)
|
112
115
|
end
|
@@ -115,17 +118,18 @@ module ActiveRecord
|
|
115
118
|
end
|
116
119
|
end
|
117
120
|
|
118
|
-
def ignore_default_scope?
|
121
|
+
def ignore_default_scope? # :nodoc:
|
119
122
|
Thread.current["#{self}_ignore_default_scope"]
|
120
123
|
end
|
121
124
|
|
122
|
-
def ignore_default_scope=(ignore)
|
125
|
+
def ignore_default_scope=(ignore) # :nodoc:
|
123
126
|
Thread.current["#{self}_ignore_default_scope"] = ignore
|
124
127
|
end
|
125
128
|
|
126
|
-
# The ignore_default_scope flag is used to prevent an infinite recursion
|
127
|
-
# a default scope references a scope which has a default
|
128
|
-
|
129
|
+
# The ignore_default_scope flag is used to prevent an infinite recursion
|
130
|
+
# situation where a default scope references a scope which has a default
|
131
|
+
# scope which references a scope...
|
132
|
+
def evaluate_default_scope # :nodoc:
|
129
133
|
return if ignore_default_scope?
|
130
134
|
|
131
135
|
begin
|
@@ -135,7 +139,6 @@ module ActiveRecord
|
|
135
139
|
self.ignore_default_scope = false
|
136
140
|
end
|
137
141
|
end
|
138
|
-
|
139
142
|
end
|
140
143
|
end
|
141
144
|
end
|