activerecord 4.2.11.3 → 5.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 +5 -5
- data/CHANGELOG.md +1029 -1349
- data/MIT-LICENSE +1 -1
- data/README.rdoc +6 -7
- data/examples/performance.rb +2 -2
- data/lib/active_record.rb +7 -3
- data/lib/active_record/aggregations.rb +35 -25
- data/lib/active_record/association_relation.rb +2 -2
- data/lib/active_record/associations.rb +305 -204
- data/lib/active_record/associations/alias_tracker.rb +19 -16
- data/lib/active_record/associations/association.rb +10 -8
- data/lib/active_record/associations/association_scope.rb +73 -102
- data/lib/active_record/associations/belongs_to_association.rb +20 -32
- data/lib/active_record/associations/builder/association.rb +28 -34
- data/lib/active_record/associations/builder/belongs_to.rb +41 -18
- data/lib/active_record/associations/builder/collection_association.rb +8 -24
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +11 -11
- data/lib/active_record/associations/builder/has_many.rb +4 -4
- data/lib/active_record/associations/builder/has_one.rb +10 -5
- data/lib/active_record/associations/builder/singular_association.rb +2 -9
- data/lib/active_record/associations/collection_association.rb +40 -43
- data/lib/active_record/associations/collection_proxy.rb +55 -29
- data/lib/active_record/associations/foreign_association.rb +1 -1
- data/lib/active_record/associations/has_many_association.rb +20 -71
- data/lib/active_record/associations/has_many_through_association.rb +8 -52
- data/lib/active_record/associations/has_one_association.rb +12 -5
- data/lib/active_record/associations/join_dependency.rb +28 -18
- data/lib/active_record/associations/join_dependency/join_association.rb +13 -12
- data/lib/active_record/associations/preloader.rb +13 -4
- data/lib/active_record/associations/preloader/association.rb +45 -51
- data/lib/active_record/associations/preloader/collection_association.rb +0 -6
- data/lib/active_record/associations/preloader/has_many_through.rb +1 -1
- data/lib/active_record/associations/preloader/has_one.rb +0 -8
- data/lib/active_record/associations/preloader/through_association.rb +5 -4
- data/lib/active_record/associations/singular_association.rb +6 -0
- data/lib/active_record/associations/through_association.rb +11 -3
- data/lib/active_record/attribute.rb +61 -17
- data/lib/active_record/attribute/user_provided_default.rb +23 -0
- data/lib/active_record/attribute_assignment.rb +27 -140
- data/lib/active_record/attribute_decorators.rb +6 -5
- data/lib/active_record/attribute_methods.rb +79 -26
- data/lib/active_record/attribute_methods/before_type_cast.rb +1 -1
- data/lib/active_record/attribute_methods/dirty.rb +46 -86
- data/lib/active_record/attribute_methods/primary_key.rb +2 -2
- data/lib/active_record/attribute_methods/query.rb +2 -2
- data/lib/active_record/attribute_methods/read.rb +26 -42
- data/lib/active_record/attribute_methods/serialization.rb +13 -16
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +42 -9
- data/lib/active_record/attribute_methods/write.rb +13 -24
- data/lib/active_record/attribute_mutation_tracker.rb +70 -0
- data/lib/active_record/attribute_set.rb +30 -3
- data/lib/active_record/attribute_set/builder.rb +6 -4
- data/lib/active_record/attributes.rb +194 -81
- data/lib/active_record/autosave_association.rb +33 -15
- data/lib/active_record/base.rb +30 -18
- data/lib/active_record/callbacks.rb +36 -40
- data/lib/active_record/coders/yaml_column.rb +20 -8
- data/lib/active_record/collection_cache_key.rb +31 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +431 -122
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +40 -22
- data/lib/active_record/connection_adapters/abstract/quoting.rb +62 -8
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +46 -38
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +229 -185
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +52 -13
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +275 -115
- data/lib/active_record/connection_adapters/abstract/transaction.rb +32 -33
- data/lib/active_record/connection_adapters/abstract_adapter.rb +83 -32
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +384 -221
- data/lib/active_record/connection_adapters/column.rb +27 -41
- data/lib/active_record/connection_adapters/connection_specification.rb +2 -21
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +22 -0
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +57 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +69 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +59 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +22 -101
- data/lib/active_record/connection_adapters/postgresql/column.rb +6 -10
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid.rb +1 -6
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +23 -57
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -2
- 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 +7 -22
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +1 -26
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +0 -2
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +50 -0
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +23 -16
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +0 -4
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +18 -11
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +29 -10
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -79
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +54 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +174 -128
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +35 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +184 -112
- data/lib/active_record/connection_adapters/schema_cache.rb +36 -23
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +32 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +15 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +134 -110
- data/lib/active_record/connection_adapters/statement_pool.rb +28 -11
- data/lib/active_record/connection_handling.rb +5 -5
- data/lib/active_record/core.rb +72 -104
- data/lib/active_record/counter_cache.rb +9 -20
- data/lib/active_record/dynamic_matchers.rb +1 -20
- data/lib/active_record/enum.rb +110 -76
- data/lib/active_record/errors.rb +72 -47
- data/lib/active_record/explain_registry.rb +1 -1
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixture_set/file.rb +19 -4
- data/lib/active_record/fixtures.rb +76 -40
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +27 -40
- data/lib/active_record/integration.rb +4 -4
- data/lib/active_record/legacy_yaml_adapter.rb +18 -2
- data/lib/active_record/locale/en.yml +3 -2
- data/lib/active_record/locking/optimistic.rb +10 -14
- data/lib/active_record/locking/pessimistic.rb +1 -1
- data/lib/active_record/log_subscriber.rb +40 -22
- data/lib/active_record/migration.rb +304 -133
- data/lib/active_record/migration/command_recorder.rb +59 -18
- data/lib/active_record/migration/compatibility.rb +90 -0
- data/lib/active_record/model_schema.rb +92 -40
- data/lib/active_record/nested_attributes.rb +45 -34
- data/lib/active_record/null_relation.rb +15 -7
- data/lib/active_record/persistence.rb +112 -72
- data/lib/active_record/querying.rb +6 -5
- data/lib/active_record/railtie.rb +20 -13
- data/lib/active_record/railties/controller_runtime.rb +1 -1
- data/lib/active_record/railties/databases.rake +47 -38
- data/lib/active_record/readonly_attributes.rb +1 -1
- data/lib/active_record/reflection.rb +182 -57
- data/lib/active_record/relation.rb +152 -100
- data/lib/active_record/relation/batches.rb +133 -33
- data/lib/active_record/relation/batches/batch_enumerator.rb +67 -0
- data/lib/active_record/relation/calculations.rb +80 -101
- data/lib/active_record/relation/delegation.rb +6 -19
- data/lib/active_record/relation/finder_methods.rb +58 -46
- data/lib/active_record/relation/from_clause.rb +32 -0
- data/lib/active_record/relation/merger.rb +13 -42
- data/lib/active_record/relation/predicate_builder.rb +99 -105
- data/lib/active_record/relation/predicate_builder/array_handler.rb +11 -16
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +78 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +17 -0
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +17 -0
- data/lib/active_record/relation/predicate_builder/class_handler.rb +27 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +17 -0
- data/lib/active_record/relation/query_attribute.rb +19 -0
- data/lib/active_record/relation/query_methods.rb +274 -238
- data/lib/active_record/relation/record_fetch_warning.rb +51 -0
- data/lib/active_record/relation/spawn_methods.rb +3 -6
- data/lib/active_record/relation/where_clause.rb +173 -0
- data/lib/active_record/relation/where_clause_factory.rb +37 -0
- data/lib/active_record/result.rb +4 -3
- data/lib/active_record/runtime_registry.rb +1 -1
- data/lib/active_record/sanitization.rb +94 -65
- data/lib/active_record/schema.rb +23 -22
- data/lib/active_record/schema_dumper.rb +33 -22
- data/lib/active_record/schema_migration.rb +10 -4
- data/lib/active_record/scoping.rb +17 -6
- data/lib/active_record/scoping/default.rb +19 -6
- data/lib/active_record/scoping/named.rb +39 -28
- data/lib/active_record/secure_token.rb +38 -0
- data/lib/active_record/serialization.rb +2 -4
- data/lib/active_record/statement_cache.rb +15 -13
- data/lib/active_record/store.rb +8 -3
- data/lib/active_record/suppressor.rb +54 -0
- data/lib/active_record/table_metadata.rb +64 -0
- data/lib/active_record/tasks/database_tasks.rb +30 -40
- data/lib/active_record/tasks/mysql_database_tasks.rb +7 -15
- data/lib/active_record/tasks/postgresql_database_tasks.rb +11 -2
- data/lib/active_record/tasks/sqlite_database_tasks.rb +5 -1
- data/lib/active_record/timestamp.rb +16 -9
- data/lib/active_record/touch_later.rb +58 -0
- data/lib/active_record/transactions.rb +138 -56
- data/lib/active_record/type.rb +66 -17
- data/lib/active_record/type/adapter_specific_registry.rb +130 -0
- data/lib/active_record/type/date.rb +2 -45
- data/lib/active_record/type/date_time.rb +2 -49
- data/lib/active_record/type/internal/abstract_json.rb +33 -0
- data/lib/active_record/type/internal/timezone.rb +15 -0
- data/lib/active_record/type/serialized.rb +9 -14
- data/lib/active_record/type/time.rb +3 -21
- data/lib/active_record/type/type_map.rb +4 -4
- data/lib/active_record/type_caster.rb +7 -0
- data/lib/active_record/type_caster/connection.rb +29 -0
- data/lib/active_record/type_caster/map.rb +19 -0
- data/lib/active_record/validations.rb +33 -32
- data/lib/active_record/validations/absence.rb +24 -0
- data/lib/active_record/validations/associated.rb +10 -3
- data/lib/active_record/validations/length.rb +36 -0
- data/lib/active_record/validations/presence.rb +12 -12
- data/lib/active_record/validations/uniqueness.rb +24 -21
- data/lib/rails/generators/active_record/migration.rb +7 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +7 -4
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +8 -3
- data/lib/rails/generators/active_record/migration/templates/migration.rb +4 -1
- data/lib/rails/generators/active_record/model/model_generator.rb +21 -15
- data/lib/rails/generators/active_record/model/templates/model.rb +3 -0
- metadata +50 -35
- data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -498
- data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +0 -11
- data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
- data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
- data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
- data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
- data/lib/active_record/serializers/xml_serializer.rb +0 -193
- data/lib/active_record/type/big_integer.rb +0 -13
- data/lib/active_record/type/binary.rb +0 -50
- data/lib/active_record/type/boolean.rb +0 -31
- data/lib/active_record/type/decimal.rb +0 -64
- data/lib/active_record/type/decimal_without_scale.rb +0 -11
- data/lib/active_record/type/decorator.rb +0 -14
- data/lib/active_record/type/float.rb +0 -19
- data/lib/active_record/type/integer.rb +0 -59
- data/lib/active_record/type/mutable.rb +0 -16
- data/lib/active_record/type/numeric.rb +0 -36
- data/lib/active_record/type/string.rb +0 -40
- data/lib/active_record/type/text.rb +0 -11
- data/lib/active_record/type/time_value.rb +0 -38
- data/lib/active_record/type/unsigned_integer.rb +0 -15
- data/lib/active_record/type/value.rb +0 -110
data/lib/active_record/schema.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
module ActiveRecord
|
2
|
-
# = Active Record Schema
|
2
|
+
# = Active Record \Schema
|
3
3
|
#
|
4
4
|
# Allows programmers to programmatically define a schema in a portable
|
5
5
|
# DSL. This means you can define tables, indexes, etc. without using SQL
|
@@ -27,29 +27,12 @@ module ActiveRecord
|
|
27
27
|
#
|
28
28
|
# ActiveRecord::Schema is only supported by database adapters that also
|
29
29
|
# support migrations, the two features being very similar.
|
30
|
-
class Schema < Migration
|
31
|
-
|
32
|
-
# Returns the migrations paths.
|
33
|
-
#
|
34
|
-
# ActiveRecord::Schema.new.migrations_paths
|
35
|
-
# # => ["db/migrate"] # Rails migration path by default.
|
36
|
-
def migrations_paths
|
37
|
-
ActiveRecord::Migrator.migrations_paths
|
38
|
-
end
|
39
|
-
|
40
|
-
def define(info, &block) # :nodoc:
|
41
|
-
instance_eval(&block)
|
42
|
-
|
43
|
-
unless info[:version].blank?
|
44
|
-
initialize_schema_migrations_table
|
45
|
-
connection.assume_migrated_upto_version(info[:version], migrations_paths)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
30
|
+
class Schema < Migration::Current
|
49
31
|
# Eval the given block. All methods available to the current connection
|
50
32
|
# adapter are available within the block, so you can easily use the
|
51
|
-
# database definition DSL to build up your schema (
|
52
|
-
#
|
33
|
+
# database definition DSL to build up your schema (
|
34
|
+
# {create_table}[rdoc-ref:ConnectionAdapters::SchemaStatements#create_table],
|
35
|
+
# {add_index}[rdoc-ref:ConnectionAdapters::SchemaStatements#add_index], etc.).
|
53
36
|
#
|
54
37
|
# The +info+ hash is optional, and if given is used to define metadata
|
55
38
|
# about the current schema (currently, only the schema's version):
|
@@ -60,5 +43,23 @@ module ActiveRecord
|
|
60
43
|
def self.define(info={}, &block)
|
61
44
|
new.define(info, &block)
|
62
45
|
end
|
46
|
+
|
47
|
+
def define(info, &block) # :nodoc:
|
48
|
+
instance_eval(&block)
|
49
|
+
|
50
|
+
if info[:version].present?
|
51
|
+
initialize_schema_migrations_table
|
52
|
+
connection.assume_migrated_upto_version(info[:version], migrations_paths)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
# Returns the migrations paths.
|
58
|
+
#
|
59
|
+
# ActiveRecord::Schema.new.migrations_paths
|
60
|
+
# # => ["db/migrate"] # Rails migration path by default.
|
61
|
+
def migrations_paths # :nodoc:
|
62
|
+
ActiveRecord::Migrator.migrations_paths
|
63
|
+
end
|
63
64
|
end
|
64
65
|
end
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'stringio'
|
2
|
-
require 'active_support/core_ext/big_decimal'
|
3
2
|
|
4
3
|
module ActiveRecord
|
5
4
|
# = Active Record Schema Dumper
|
@@ -44,7 +43,6 @@ module ActiveRecord
|
|
44
43
|
|
45
44
|
def initialize(connection, options = {})
|
46
45
|
@connection = connection
|
47
|
-
@types = @connection.native_database_types
|
48
46
|
@version = Migrator::current_version rescue nil
|
49
47
|
@options = options
|
50
48
|
end
|
@@ -91,7 +89,7 @@ HEADER
|
|
91
89
|
end
|
92
90
|
|
93
91
|
def tables(stream)
|
94
|
-
sorted_tables = @connection.
|
92
|
+
sorted_tables = @connection.data_sources.sort - @connection.views
|
95
93
|
|
96
94
|
sorted_tables.each do |table_name|
|
97
95
|
table(table_name, stream) unless ignored?(table_name)
|
@@ -106,35 +104,50 @@ HEADER
|
|
106
104
|
end
|
107
105
|
|
108
106
|
def table(table, stream)
|
109
|
-
columns = @connection.columns(table)
|
107
|
+
columns = @connection.columns(table).map do |column|
|
108
|
+
column.instance_variable_set(:@table_name, table)
|
109
|
+
column
|
110
|
+
end
|
110
111
|
begin
|
111
112
|
tbl = StringIO.new
|
112
113
|
|
113
114
|
# first dump primary key column
|
114
|
-
|
115
|
+
if @connection.respond_to?(:primary_keys)
|
116
|
+
pk = @connection.primary_keys(table)
|
117
|
+
pk = pk.first unless pk.size > 1
|
118
|
+
else
|
119
|
+
pk = @connection.primary_key(table)
|
120
|
+
end
|
115
121
|
|
116
122
|
tbl.print " create_table #{remove_prefix_and_suffix(table).inspect}"
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
123
|
+
|
124
|
+
case pk
|
125
|
+
when String
|
126
|
+
tbl.print ", primary_key: #{pk.inspect}" unless pk == 'id'
|
127
|
+
pkcol = columns.detect { |c| c.name == pk }
|
128
|
+
pkcolspec = @connection.column_spec_for_primary_key(pkcol)
|
129
|
+
if pkcolspec
|
130
|
+
pkcolspec.each do |key, value|
|
131
|
+
tbl.print ", #{key}: #{value}"
|
132
|
+
end
|
126
133
|
end
|
134
|
+
when Array
|
135
|
+
tbl.print ", primary_key: #{pk.inspect}"
|
127
136
|
else
|
128
137
|
tbl.print ", id: false"
|
129
138
|
end
|
130
139
|
tbl.print ", force: :cascade"
|
140
|
+
|
141
|
+
table_options = @connection.table_options(table)
|
142
|
+
tbl.print ", options: #{table_options.inspect}" unless table_options.blank?
|
143
|
+
|
131
144
|
tbl.puts " do |t|"
|
132
145
|
|
133
146
|
# then dump all non-primary key columns
|
134
147
|
column_specs = columns.map do |column|
|
135
148
|
raise StandardError, "Unknown type '#{column.sql_type}' for column '#{column.name}'" unless @connection.valid_type?(column.type)
|
136
149
|
next if column.name == pk
|
137
|
-
@connection.column_spec(column
|
150
|
+
@connection.column_spec(column)
|
138
151
|
end.compact
|
139
152
|
|
140
153
|
# find all migration keys used in this table
|
@@ -165,11 +178,11 @@ HEADER
|
|
165
178
|
tbl.puts
|
166
179
|
end
|
167
180
|
|
181
|
+
indexes(table, tbl)
|
182
|
+
|
168
183
|
tbl.puts " end"
|
169
184
|
tbl.puts
|
170
185
|
|
171
|
-
indexes(table, tbl)
|
172
|
-
|
173
186
|
tbl.rewind
|
174
187
|
stream.print tbl.read
|
175
188
|
rescue => e
|
@@ -185,8 +198,7 @@ HEADER
|
|
185
198
|
if (indexes = @connection.indexes(table)).any?
|
186
199
|
add_index_statements = indexes.map do |index|
|
187
200
|
statement_parts = [
|
188
|
-
"
|
189
|
-
index.columns.inspect,
|
201
|
+
"t.index #{index.columns.inspect}",
|
190
202
|
"name: #{index.name.inspect}",
|
191
203
|
]
|
192
204
|
statement_parts << 'unique: true' if index.unique
|
@@ -200,11 +212,10 @@ HEADER
|
|
200
212
|
statement_parts << "using: #{index.using.inspect}" if index.using
|
201
213
|
statement_parts << "type: #{index.type.inspect}" if index.type
|
202
214
|
|
203
|
-
"
|
215
|
+
" #{statement_parts.join(', ')}"
|
204
216
|
end
|
205
217
|
|
206
218
|
stream.puts add_index_statements.sort.join("\n")
|
207
|
-
stream.puts
|
208
219
|
end
|
209
220
|
end
|
210
221
|
|
@@ -243,7 +254,7 @@ HEADER
|
|
243
254
|
end
|
244
255
|
|
245
256
|
def ignored?(table_name)
|
246
|
-
[
|
257
|
+
[ActiveRecord::Base.schema_migrations_table_name, ignore_tables].flatten.any? do |ignored|
|
247
258
|
ignored === remove_prefix_and_suffix(table_name)
|
248
259
|
end
|
249
260
|
end
|
@@ -1,9 +1,12 @@
|
|
1
1
|
require 'active_record/scoping/default'
|
2
2
|
require 'active_record/scoping/named'
|
3
|
-
require 'active_record/base'
|
4
3
|
|
5
4
|
module ActiveRecord
|
6
|
-
class
|
5
|
+
# This class is used to create a table that keeps track of which migrations
|
6
|
+
# have been applied to a given database. When a migration is run, its schema
|
7
|
+
# number is inserted in to the `SchemaMigration.table_name` so it doesn't need
|
8
|
+
# to be executed the next time.
|
9
|
+
class SchemaMigration < ActiveRecord::Base # :nodoc:
|
7
10
|
class << self
|
8
11
|
def primary_key
|
9
12
|
nil
|
@@ -18,7 +21,7 @@ module ActiveRecord
|
|
18
21
|
end
|
19
22
|
|
20
23
|
def table_exists?
|
21
|
-
connection.table_exists?(table_name)
|
24
|
+
ActiveSupport::Deprecation.silence { connection.table_exists?(table_name) }
|
22
25
|
end
|
23
26
|
|
24
27
|
def create_table(limit=nil)
|
@@ -34,7 +37,10 @@ module ActiveRecord
|
|
34
37
|
end
|
35
38
|
|
36
39
|
def drop_table
|
37
|
-
|
40
|
+
if table_exists?
|
41
|
+
connection.remove_index table_name, name: index_name
|
42
|
+
connection.drop_table(table_name)
|
43
|
+
end
|
38
44
|
end
|
39
45
|
|
40
46
|
def normalize_migration_number(number)
|
@@ -11,15 +11,26 @@ module ActiveRecord
|
|
11
11
|
|
12
12
|
module ClassMethods
|
13
13
|
def current_scope #:nodoc:
|
14
|
-
ScopeRegistry.value_for(:current_scope,
|
14
|
+
ScopeRegistry.value_for(:current_scope, self.to_s)
|
15
15
|
end
|
16
16
|
|
17
17
|
def current_scope=(scope) #:nodoc:
|
18
|
-
ScopeRegistry.set_value_for(:current_scope,
|
18
|
+
ScopeRegistry.set_value_for(:current_scope, self.to_s, scope)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Collects attributes from scopes that should be applied when creating
|
22
|
+
# an AR instance for the particular class this is called on.
|
23
|
+
def scope_attributes # :nodoc:
|
24
|
+
all.scope_for_create
|
25
|
+
end
|
26
|
+
|
27
|
+
# Are there attributes associated with this scope?
|
28
|
+
def scope_attributes? # :nodoc:
|
29
|
+
current_scope
|
19
30
|
end
|
20
31
|
end
|
21
32
|
|
22
|
-
def populate_with_current_scope_attributes
|
33
|
+
def populate_with_current_scope_attributes # :nodoc:
|
23
34
|
return unless self.class.scope_attributes?
|
24
35
|
|
25
36
|
self.class.scope_attributes.each do |att,value|
|
@@ -27,7 +38,7 @@ module ActiveRecord
|
|
27
38
|
end
|
28
39
|
end
|
29
40
|
|
30
|
-
def initialize_internals_callback
|
41
|
+
def initialize_internals_callback # :nodoc:
|
31
42
|
super
|
32
43
|
populate_with_current_scope_attributes
|
33
44
|
end
|
@@ -48,8 +59,8 @@ module ActiveRecord
|
|
48
59
|
#
|
49
60
|
# registry.value_for(:current_scope, "Board")
|
50
61
|
#
|
51
|
-
# You will obtain whatever was defined in +some_new_scope+. The
|
52
|
-
# and
|
62
|
+
# You will obtain whatever was defined in +some_new_scope+. The #value_for
|
63
|
+
# and #set_value_for methods are delegated to the current ScopeRegistry
|
53
64
|
# object, so the above example code can also be called as:
|
54
65
|
#
|
55
66
|
# ActiveRecord::Scoping::ScopeRegistry.set_value_for(:current_scope,
|
@@ -6,8 +6,10 @@ module ActiveRecord
|
|
6
6
|
included do
|
7
7
|
# Stores the default scope for the class.
|
8
8
|
class_attribute :default_scopes, instance_writer: false, instance_predicate: false
|
9
|
+
class_attribute :default_scope_override, instance_predicate: false
|
9
10
|
|
10
11
|
self.default_scopes = []
|
12
|
+
self.default_scope_override = nil
|
11
13
|
end
|
12
14
|
|
13
15
|
module ClassMethods
|
@@ -15,7 +17,7 @@ module ActiveRecord
|
|
15
17
|
#
|
16
18
|
# class Post < ActiveRecord::Base
|
17
19
|
# def self.default_scope
|
18
|
-
# where
|
20
|
+
# where(published: true)
|
19
21
|
# end
|
20
22
|
# end
|
21
23
|
#
|
@@ -33,6 +35,11 @@ module ActiveRecord
|
|
33
35
|
block_given? ? relation.scoping { yield } : relation
|
34
36
|
end
|
35
37
|
|
38
|
+
# Are there attributes associated with this scope?
|
39
|
+
def scope_attributes? # :nodoc:
|
40
|
+
super || default_scopes.any? || respond_to?(:default_scope)
|
41
|
+
end
|
42
|
+
|
36
43
|
def before_remove_const #:nodoc:
|
37
44
|
self.current_scope = nil
|
38
45
|
end
|
@@ -48,7 +55,7 @@ module ActiveRecord
|
|
48
55
|
#
|
49
56
|
# Article.all # => SELECT * FROM articles WHERE published = true
|
50
57
|
#
|
51
|
-
# The
|
58
|
+
# The #default_scope is also applied while creating/building a record.
|
52
59
|
# It is not applied while updating a record.
|
53
60
|
#
|
54
61
|
# Article.new.published # => true
|
@@ -58,7 +65,7 @@ module ActiveRecord
|
|
58
65
|
# +default_scope+ macro, and it will be called when building the
|
59
66
|
# default scope.)
|
60
67
|
#
|
61
|
-
# If you use multiple
|
68
|
+
# If you use multiple #default_scope declarations in your model then
|
62
69
|
# they will be merged together:
|
63
70
|
#
|
64
71
|
# class Article < ActiveRecord::Base
|
@@ -69,7 +76,7 @@ module ActiveRecord
|
|
69
76
|
# Article.all # => SELECT * FROM articles WHERE published = true AND rating = 'G'
|
70
77
|
#
|
71
78
|
# This is also the case with inheritance and module includes where the
|
72
|
-
# parent or module defines a
|
79
|
+
# parent or module defines a #default_scope and the child or including
|
73
80
|
# class defines a second one.
|
74
81
|
#
|
75
82
|
# If you need to do more complex things with a default scope, you can
|
@@ -94,12 +101,18 @@ module ActiveRecord
|
|
94
101
|
self.default_scopes += [scope]
|
95
102
|
end
|
96
103
|
|
97
|
-
def build_default_scope(base_rel =
|
104
|
+
def build_default_scope(base_rel = nil) # :nodoc:
|
98
105
|
return if abstract_class?
|
99
|
-
|
106
|
+
|
107
|
+
if self.default_scope_override.nil?
|
108
|
+
self.default_scope_override = !Base.is_a?(method(:default_scope).owner)
|
109
|
+
end
|
110
|
+
|
111
|
+
if self.default_scope_override
|
100
112
|
# The user has defined their own default scope method, so call that
|
101
113
|
evaluate_default_scope { default_scope }
|
102
114
|
elsif default_scopes.any?
|
115
|
+
base_rel ||= relation
|
103
116
|
evaluate_default_scope do
|
104
117
|
default_scopes.inject(base_rel) do |default_scope, scope|
|
105
118
|
default_scope.merge(base_rel.scoping { scope.call })
|
@@ -9,7 +9,7 @@ module ActiveRecord
|
|
9
9
|
extend ActiveSupport::Concern
|
10
10
|
|
11
11
|
module ClassMethods
|
12
|
-
# Returns an
|
12
|
+
# Returns an ActiveRecord::Relation scope object.
|
13
13
|
#
|
14
14
|
# posts = Post.all
|
15
15
|
# posts.size # Fires "select count(*) from posts" and returns the count
|
@@ -20,7 +20,7 @@ module ActiveRecord
|
|
20
20
|
# fruits = fruits.limit(10) if limited?
|
21
21
|
#
|
22
22
|
# You can define a scope that applies to all finders using
|
23
|
-
#
|
23
|
+
# {default_scope}[rdoc-ref:Scoping::Default::ClassMethods#default_scope].
|
24
24
|
def all
|
25
25
|
if current_scope
|
26
26
|
current_scope.clone
|
@@ -30,22 +30,22 @@ module ActiveRecord
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def default_scoped # :nodoc:
|
33
|
-
|
34
|
-
end
|
35
|
-
|
36
|
-
# Collects attributes from scopes that should be applied when creating
|
37
|
-
# an AR instance for the particular class this is called on.
|
38
|
-
def scope_attributes # :nodoc:
|
39
|
-
all.scope_for_create
|
40
|
-
end
|
33
|
+
scope = build_default_scope
|
41
34
|
|
42
|
-
|
43
|
-
|
44
|
-
|
35
|
+
if scope
|
36
|
+
relation.spawn.merge!(scope)
|
37
|
+
else
|
38
|
+
relation
|
39
|
+
end
|
45
40
|
end
|
46
41
|
|
47
|
-
# Adds a class method for retrieving and querying objects.
|
48
|
-
#
|
42
|
+
# Adds a class method for retrieving and querying objects.
|
43
|
+
# The method is intended to return an ActiveRecord::Relation
|
44
|
+
# object, which is composable with other scopes.
|
45
|
+
# If it returns nil or false, an
|
46
|
+
# {all}[rdoc-ref:Scoping::Named::ClassMethods#all] scope is returned instead.
|
47
|
+
#
|
48
|
+
# A \scope represents a narrowing of a database query, such as
|
49
49
|
# <tt>where(color: :red).select('shirts.*').includes(:washing_instructions)</tt>.
|
50
50
|
#
|
51
51
|
# class Shirt < ActiveRecord::Base
|
@@ -53,12 +53,12 @@ module ActiveRecord
|
|
53
53
|
# scope :dry_clean_only, -> { joins(:washing_instructions).where('washing_instructions.dry_clean_only = ?', true) }
|
54
54
|
# end
|
55
55
|
#
|
56
|
-
# The above calls to
|
56
|
+
# The above calls to #scope define class methods <tt>Shirt.red</tt> and
|
57
57
|
# <tt>Shirt.dry_clean_only</tt>. <tt>Shirt.red</tt>, in effect,
|
58
58
|
# represents the query <tt>Shirt.where(color: 'red')</tt>.
|
59
59
|
#
|
60
60
|
# You should always pass a callable object to the scopes defined
|
61
|
-
# with
|
61
|
+
# with #scope. This ensures that the scope is re-evaluated each
|
62
62
|
# time it is called.
|
63
63
|
#
|
64
64
|
# Note that this is simply 'syntactic sugar' for defining an actual
|
@@ -71,14 +71,15 @@ module ActiveRecord
|
|
71
71
|
# end
|
72
72
|
#
|
73
73
|
# Unlike <tt>Shirt.find(...)</tt>, however, the object returned by
|
74
|
-
# <tt>Shirt.red</tt> is not an Array
|
75
|
-
#
|
76
|
-
#
|
74
|
+
# <tt>Shirt.red</tt> is not an Array but an ActiveRecord::Relation,
|
75
|
+
# which is composable with other scopes; it resembles the association object
|
76
|
+
# constructed by a {has_many}[rdoc-ref:Associations::ClassMethods#has_many]
|
77
|
+
# declaration. For instance, you can invoke <tt>Shirt.red.first</tt>, <tt>Shirt.red.count</tt>,
|
77
78
|
# <tt>Shirt.red.where(size: 'small')</tt>. Also, just as with the
|
78
79
|
# association objects, named \scopes act like an Array, implementing
|
79
80
|
# Enumerable; <tt>Shirt.red.each(&block)</tt>, <tt>Shirt.red.first</tt>,
|
80
81
|
# and <tt>Shirt.red.inject(memo, &block)</tt> all behave as if
|
81
|
-
# <tt>Shirt.red</tt> really was an
|
82
|
+
# <tt>Shirt.red</tt> really was an array.
|
82
83
|
#
|
83
84
|
# These named \scopes are composable. For instance,
|
84
85
|
# <tt>Shirt.red.dry_clean_only</tt> will produce all shirts that are
|
@@ -89,7 +90,8 @@ module ActiveRecord
|
|
89
90
|
#
|
90
91
|
# All scopes are available as class methods on the ActiveRecord::Base
|
91
92
|
# descendant upon which the \scopes were defined. But they are also
|
92
|
-
# available to
|
93
|
+
# available to {has_many}[rdoc-ref:Associations::ClassMethods#has_many]
|
94
|
+
# associations. If,
|
93
95
|
#
|
94
96
|
# class Person < ActiveRecord::Base
|
95
97
|
# has_many :shirts
|
@@ -98,8 +100,8 @@ module ActiveRecord
|
|
98
100
|
# then <tt>elton.shirts.red.dry_clean_only</tt> will return all of
|
99
101
|
# Elton's red, dry clean only shirts.
|
100
102
|
#
|
101
|
-
# \Named scopes can also have extensions, just as with
|
102
|
-
# declarations:
|
103
|
+
# \Named scopes can also have extensions, just as with
|
104
|
+
# {has_many}[rdoc-ref:Associations::ClassMethods#has_many] declarations:
|
103
105
|
#
|
104
106
|
# class Shirt < ActiveRecord::Base
|
105
107
|
# scope :red, -> { where(color: 'red') } do
|
@@ -151,11 +153,20 @@ module ActiveRecord
|
|
151
153
|
|
152
154
|
extension = Module.new(&block) if block
|
153
155
|
|
154
|
-
|
155
|
-
|
156
|
-
|
156
|
+
if body.respond_to?(:to_proc)
|
157
|
+
singleton_class.send(:define_method, name) do |*args|
|
158
|
+
scope = all.scoping { instance_exec(*args, &body) }
|
159
|
+
scope = scope.extending(extension) if extension
|
160
|
+
|
161
|
+
scope || all
|
162
|
+
end
|
163
|
+
else
|
164
|
+
singleton_class.send(:define_method, name) do |*args|
|
165
|
+
scope = all.scoping { body.call(*args) }
|
166
|
+
scope = scope.extending(extension) if extension
|
157
167
|
|
158
|
-
|
168
|
+
scope || all
|
169
|
+
end
|
159
170
|
end
|
160
171
|
end
|
161
172
|
end
|