activerecord 4.2.11.3 → 5.0.0.1
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 +1281 -1204
- data/MIT-LICENSE +2 -2
- data/README.rdoc +7 -8
- data/examples/performance.rb +2 -3
- data/examples/simple.rb +0 -1
- data/lib/active_record/aggregations.rb +35 -24
- data/lib/active_record/association_relation.rb +3 -3
- data/lib/active_record/associations/alias_tracker.rb +19 -16
- data/lib/active_record/associations/association.rb +11 -9
- data/lib/active_record/associations/association_scope.rb +73 -102
- data/lib/active_record/associations/belongs_to_association.rb +21 -32
- data/lib/active_record/associations/builder/association.rb +28 -34
- data/lib/active_record/associations/builder/belongs_to.rb +43 -18
- data/lib/active_record/associations/builder/collection_association.rb +7 -19
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +14 -11
- data/lib/active_record/associations/builder/has_many.rb +4 -4
- data/lib/active_record/associations/builder/has_one.rb +11 -6
- data/lib/active_record/associations/builder/singular_association.rb +3 -10
- data/lib/active_record/associations/collection_association.rb +49 -41
- data/lib/active_record/associations/collection_proxy.rb +67 -27
- 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 -47
- data/lib/active_record/associations/has_one_association.rb +12 -5
- data/lib/active_record/associations/join_dependency/join_association.rb +16 -10
- data/lib/active_record/associations/join_dependency.rb +29 -19
- data/lib/active_record/associations/preloader/association.rb +46 -52
- 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 +27 -14
- data/lib/active_record/associations/preloader.rb +14 -4
- data/lib/active_record/associations/singular_association.rb +7 -1
- data/lib/active_record/associations/through_association.rb +11 -3
- data/lib/active_record/associations.rb +317 -209
- data/lib/active_record/attribute/user_provided_default.rb +28 -0
- data/lib/active_record/attribute.rb +68 -18
- data/lib/active_record/attribute_assignment.rb +19 -140
- data/lib/active_record/attribute_decorators.rb +6 -5
- 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 +31 -59
- data/lib/active_record/attribute_methods/serialization.rb +13 -16
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +61 -14
- data/lib/active_record/attribute_methods/write.rb +13 -37
- data/lib/active_record/attribute_methods.rb +76 -47
- data/lib/active_record/attribute_mutation_tracker.rb +70 -0
- data/lib/active_record/attribute_set/builder.rb +6 -4
- data/lib/active_record/attribute_set.rb +30 -3
- data/lib/active_record/attributes.rb +199 -81
- data/lib/active_record/autosave_association.rb +49 -16
- data/lib/active_record/base.rb +32 -23
- data/lib/active_record/callbacks.rb +39 -43
- data/lib/active_record/coders/json.rb +1 -1
- data/lib/active_record/coders/yaml_column.rb +20 -8
- data/lib/active_record/collection_cache_key.rb +40 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +452 -182
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +65 -61
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +2 -2
- data/lib/active_record/connection_adapters/abstract/quoting.rb +74 -10
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +61 -39
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +236 -185
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +72 -17
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +380 -141
- data/lib/active_record/connection_adapters/abstract/transaction.rb +51 -34
- data/lib/active_record/connection_adapters/abstract_adapter.rb +141 -59
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +401 -370
- data/lib/active_record/connection_adapters/column.rb +28 -43
- data/lib/active_record/connection_adapters/connection_specification.rb +15 -27
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +22 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +50 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +125 -0
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +70 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +51 -0
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +67 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +93 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +54 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +32 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +29 -166
- data/lib/active_record/connection_adapters/postgresql/column.rb +5 -10
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +10 -72
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +42 -0
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +27 -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 +3 -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 -4
- 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 +31 -17
- 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/oid.rb +1 -6
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +26 -18
- 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 +47 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +234 -148
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +35 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +248 -160
- 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/explain_pretty_printer.rb +19 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +48 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +149 -192
- data/lib/active_record/connection_adapters/statement_pool.rb +31 -12
- data/lib/active_record/connection_handling.rb +37 -14
- data/lib/active_record/core.rb +89 -107
- data/lib/active_record/counter_cache.rb +13 -24
- data/lib/active_record/dynamic_matchers.rb +1 -20
- data/lib/active_record/enum.rb +113 -76
- data/lib/active_record/errors.rb +87 -48
- 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 +26 -5
- data/lib/active_record/fixtures.rb +76 -40
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +32 -40
- data/lib/active_record/integration.rb +4 -4
- data/lib/active_record/internal_metadata.rb +56 -0
- 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 +15 -15
- data/lib/active_record/locking/pessimistic.rb +1 -1
- data/lib/active_record/log_subscriber.rb +43 -21
- data/lib/active_record/migration/command_recorder.rb +59 -18
- data/lib/active_record/migration/compatibility.rb +126 -0
- data/lib/active_record/migration.rb +363 -133
- data/lib/active_record/model_schema.rb +129 -41
- data/lib/active_record/nested_attributes.rb +58 -29
- data/lib/active_record/null_relation.rb +16 -8
- data/lib/active_record/persistence.rb +121 -80
- data/lib/active_record/query_cache.rb +15 -18
- data/lib/active_record/querying.rb +10 -9
- data/lib/active_record/railtie.rb +23 -16
- data/lib/active_record/railties/controller_runtime.rb +1 -1
- data/lib/active_record/railties/databases.rake +69 -46
- data/lib/active_record/readonly_attributes.rb +1 -1
- data/lib/active_record/reflection.rb +282 -115
- data/lib/active_record/relation/batches/batch_enumerator.rb +67 -0
- data/lib/active_record/relation/batches.rb +139 -34
- data/lib/active_record/relation/calculations.rb +79 -108
- data/lib/active_record/relation/delegation.rb +7 -20
- data/lib/active_record/relation/finder_methods.rb +163 -81
- data/lib/active_record/relation/from_clause.rb +32 -0
- data/lib/active_record/relation/merger.rb +16 -42
- data/lib/active_record/relation/predicate_builder/array_handler.rb +11 -16
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +88 -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/polymorphic_array_handler.rb +57 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +33 -0
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
- data/lib/active_record/relation/predicate_builder.rb +120 -107
- data/lib/active_record/relation/query_attribute.rb +19 -0
- data/lib/active_record/relation/query_methods.rb +308 -244
- data/lib/active_record/relation/record_fetch_warning.rb +49 -0
- data/lib/active_record/relation/spawn_methods.rb +4 -7
- data/lib/active_record/relation/where_clause.rb +174 -0
- data/lib/active_record/relation/where_clause_factory.rb +38 -0
- data/lib/active_record/relation.rb +176 -116
- data/lib/active_record/result.rb +4 -3
- data/lib/active_record/runtime_registry.rb +1 -1
- data/lib/active_record/sanitization.rb +95 -66
- data/lib/active_record/schema.rb +26 -22
- data/lib/active_record/schema_dumper.rb +62 -38
- data/lib/active_record/schema_migration.rb +11 -14
- data/lib/active_record/scoping/default.rb +23 -9
- data/lib/active_record/scoping/named.rb +49 -28
- data/lib/active_record/scoping.rb +32 -15
- data/lib/active_record/secure_token.rb +38 -0
- data/lib/active_record/serialization.rb +2 -4
- data/lib/active_record/statement_cache.rb +16 -14
- data/lib/active_record/store.rb +8 -3
- data/lib/active_record/suppressor.rb +58 -0
- data/lib/active_record/table_metadata.rb +68 -0
- data/lib/active_record/tasks/database_tasks.rb +57 -43
- data/lib/active_record/tasks/mysql_database_tasks.rb +6 -14
- 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 +20 -9
- data/lib/active_record/touch_later.rb +58 -0
- data/lib/active_record/transactions.rb +138 -56
- 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 +29 -0
- data/lib/active_record/type/internal/timezone.rb +15 -0
- data/lib/active_record/type/serialized.rb +15 -14
- data/lib/active_record/type/time.rb +10 -16
- data/lib/active_record/type/type_map.rb +4 -4
- data/lib/active_record/type.rb +66 -17
- data/lib/active_record/type_caster/connection.rb +29 -0
- data/lib/active_record/type_caster/map.rb +19 -0
- data/lib/active_record/type_caster.rb +7 -0
- data/lib/active_record/validations/absence.rb +23 -0
- data/lib/active_record/validations/associated.rb +10 -3
- data/lib/active_record/validations/length.rb +24 -0
- data/lib/active_record/validations/presence.rb +11 -12
- data/lib/active_record/validations/uniqueness.rb +30 -29
- data/lib/active_record/validations.rb +33 -32
- data/lib/active_record.rb +8 -4
- 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 +8 -1
- data/lib/rails/generators/active_record/migration.rb +7 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +32 -15
- data/lib/rails/generators/active_record/model/templates/application_record.rb +5 -0
- data/lib/rails/generators/active_record/model/templates/model.rb +3 -0
- metadata +60 -34
- 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
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'erb'
|
2
2
|
require 'yaml'
|
3
3
|
require 'zlib'
|
4
|
+
require 'set'
|
4
5
|
require 'active_support/dependencies'
|
5
6
|
require 'active_support/core_ext/digest/uuid'
|
6
7
|
require 'active_record/fixture_set/file'
|
@@ -88,7 +89,7 @@ module ActiveRecord
|
|
88
89
|
# end
|
89
90
|
#
|
90
91
|
# In order to use these methods to access fixtured data within your testcases, you must specify one of the
|
91
|
-
# following in your
|
92
|
+
# following in your ActiveSupport::TestCase-derived class:
|
92
93
|
#
|
93
94
|
# - to fully enable instantiated fixtures (enable alternate methods #1 and #2 above)
|
94
95
|
# self.use_instantiated_fixtures = true
|
@@ -109,7 +110,7 @@ module ActiveRecord
|
|
109
110
|
# <% 1.upto(1000) do |i| %>
|
110
111
|
# fix_<%= i %>:
|
111
112
|
# id: <%= i %>
|
112
|
-
# name: guy_<%=
|
113
|
+
# name: guy_<%= i %>
|
113
114
|
# <% end %>
|
114
115
|
#
|
115
116
|
# This will create 1000 very simple fixtures.
|
@@ -123,7 +124,7 @@ module ActiveRecord
|
|
123
124
|
#
|
124
125
|
# Helper methods defined in a fixture will not be available in other fixtures, to prevent against
|
125
126
|
# unwanted inter-test dependencies. Methods used by multiple fixtures should be defined in a module
|
126
|
-
# that is included in
|
127
|
+
# that is included in ActiveRecord::FixtureSet.context_class.
|
127
128
|
#
|
128
129
|
# - define a helper method in `test_helper.rb`
|
129
130
|
# module FixtureFileHelpers
|
@@ -131,20 +132,20 @@ module ActiveRecord
|
|
131
132
|
# Digest::SHA2.hexdigest(File.read(Rails.root.join('test/fixtures', path)))
|
132
133
|
# end
|
133
134
|
# end
|
134
|
-
# ActiveRecord::FixtureSet.context_class.
|
135
|
+
# ActiveRecord::FixtureSet.context_class.include FixtureFileHelpers
|
135
136
|
#
|
136
137
|
# - use the helper method in a fixture
|
137
138
|
# photo:
|
138
139
|
# name: kitten.png
|
139
140
|
# sha: <%= file_sha 'files/kitten.png' %>
|
140
141
|
#
|
141
|
-
# = Transactional
|
142
|
+
# = Transactional Tests
|
142
143
|
#
|
143
144
|
# Test cases can use begin+rollback to isolate their changes to the database instead of having to
|
144
145
|
# delete+insert for every test case.
|
145
146
|
#
|
146
147
|
# class FooTest < ActiveSupport::TestCase
|
147
|
-
# self.
|
148
|
+
# self.use_transactional_tests = true
|
148
149
|
#
|
149
150
|
# test "godzilla" do
|
150
151
|
# assert !Foo.all.empty?
|
@@ -158,14 +159,14 @@ module ActiveRecord
|
|
158
159
|
# end
|
159
160
|
#
|
160
161
|
# If you preload your test database with all fixture data (probably in the rake task) and use
|
161
|
-
# transactional
|
162
|
+
# transactional tests, then you may omit all fixtures declarations in your test cases since
|
162
163
|
# all the data's already there and every case rolls back its changes.
|
163
164
|
#
|
164
165
|
# In order to use instantiated fixtures with preloaded data, set +self.pre_loaded_fixtures+ to
|
165
166
|
# true. This will provide access to fixture data for every table that has been loaded through
|
166
167
|
# fixtures (depending on the value of +use_instantiated_fixtures+).
|
167
168
|
#
|
168
|
-
# When *not* to use transactional
|
169
|
+
# When *not* to use transactional tests:
|
169
170
|
#
|
170
171
|
# 1. You're testing whether a transaction works correctly. Nested transactions don't commit until
|
171
172
|
# all parent transactions commit, particularly, the fixtures transaction which is begun in setup
|
@@ -394,6 +395,20 @@ module ActiveRecord
|
|
394
395
|
# <<: *DEFAULTS
|
395
396
|
#
|
396
397
|
# Any fixture labeled "DEFAULTS" is safely ignored.
|
398
|
+
#
|
399
|
+
# == Configure the fixture model class
|
400
|
+
#
|
401
|
+
# It's possible to set the fixture's model class directly in the YAML file.
|
402
|
+
# This is helpful when fixtures are loaded outside tests and
|
403
|
+
# +set_fixture_class+ is not available (e.g.
|
404
|
+
# when running <tt>rails db:fixtures:load</tt>).
|
405
|
+
#
|
406
|
+
# _fixture:
|
407
|
+
# model_class: User
|
408
|
+
# david:
|
409
|
+
# name: David
|
410
|
+
#
|
411
|
+
# Any fixtures labeled "_fixture" are safely ignored.
|
397
412
|
class FixtureSet
|
398
413
|
#--
|
399
414
|
# An instance of FixtureSet is normally stored in a single YAML file and
|
@@ -521,12 +536,16 @@ module ActiveRecord
|
|
521
536
|
update_all_loaded_fixtures fixtures_map
|
522
537
|
|
523
538
|
connection.transaction(:requires_new => true) do
|
539
|
+
deleted_tables = Set.new
|
524
540
|
fixture_sets.each do |fs|
|
525
541
|
conn = fs.model_class.respond_to?(:connection) ? fs.model_class.connection : connection
|
526
542
|
table_rows = fs.table_rows
|
527
543
|
|
528
544
|
table_rows.each_key do |table|
|
529
|
-
|
545
|
+
unless deleted_tables.include? table
|
546
|
+
conn.delete "DELETE FROM #{conn.quote_table_name(table)}", 'Fixture Delete'
|
547
|
+
end
|
548
|
+
deleted_tables << table
|
530
549
|
end
|
531
550
|
|
532
551
|
table_rows.each do |fixture_set_name, rows|
|
@@ -573,21 +592,16 @@ module ActiveRecord
|
|
573
592
|
@name = name
|
574
593
|
@path = path
|
575
594
|
@config = config
|
576
|
-
@model_class = nil
|
577
595
|
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
@model_class = class_name.safe_constantize if class_name
|
582
|
-
end
|
596
|
+
self.model_class = class_name
|
597
|
+
|
598
|
+
@fixtures = read_fixture_files(path)
|
583
599
|
|
584
600
|
@connection = connection
|
585
601
|
|
586
602
|
@table_name = ( model_class.respond_to?(:table_name) ?
|
587
603
|
model_class.table_name :
|
588
604
|
self.class.default_fixture_table_name(name, config) )
|
589
|
-
|
590
|
-
@fixtures = read_fixture_files path, @model_class
|
591
605
|
end
|
592
606
|
|
593
607
|
def [](x)
|
@@ -610,7 +624,6 @@ module ActiveRecord
|
|
610
624
|
# a list of rows to insert to that table.
|
611
625
|
def table_rows
|
612
626
|
now = config.default_timezone == :utc ? Time.now.utc : Time.now
|
613
|
-
now = now.to_s(:db)
|
614
627
|
|
615
628
|
# allow a standard key to be used for doing defaults in YAML
|
616
629
|
fixtures.delete('DEFAULTS')
|
@@ -639,6 +652,13 @@ module ActiveRecord
|
|
639
652
|
row[primary_key_name] = ActiveRecord::FixtureSet.identify(label, primary_key_type)
|
640
653
|
end
|
641
654
|
|
655
|
+
# Resolve enums
|
656
|
+
model_class.defined_enums.each do |name, values|
|
657
|
+
if row.include?(name)
|
658
|
+
row[name] = values.fetch(row[name], row[name])
|
659
|
+
end
|
660
|
+
end
|
661
|
+
|
642
662
|
# If STI is used, find the correct subclass for association reflection
|
643
663
|
reflection_class =
|
644
664
|
if row.include?(inheritance_column_name)
|
@@ -659,7 +679,7 @@ module ActiveRecord
|
|
659
679
|
row[association.foreign_type] = $1
|
660
680
|
end
|
661
681
|
|
662
|
-
fk_type = reflection_class.
|
682
|
+
fk_type = reflection_class.type_for_attribute(fk_name).type
|
663
683
|
row[fk_name] = ActiveRecord::FixtureSet.identify(value, fk_type)
|
664
684
|
end
|
665
685
|
when :has_many
|
@@ -689,7 +709,7 @@ module ActiveRecord
|
|
689
709
|
end
|
690
710
|
|
691
711
|
def primary_key_type
|
692
|
-
@association.klass.
|
712
|
+
@association.klass.type_for_attribute(@association.klass.primary_key).type
|
693
713
|
end
|
694
714
|
end
|
695
715
|
|
@@ -713,7 +733,7 @@ module ActiveRecord
|
|
713
733
|
end
|
714
734
|
|
715
735
|
def primary_key_type
|
716
|
-
@primary_key_type ||= model_class && model_class.
|
736
|
+
@primary_key_type ||= model_class && model_class.type_for_attribute(model_class.primary_key).type
|
717
737
|
end
|
718
738
|
|
719
739
|
def add_join_records(rows, row, association)
|
@@ -747,16 +767,28 @@ module ActiveRecord
|
|
747
767
|
end
|
748
768
|
|
749
769
|
def column_names
|
750
|
-
@column_names ||= @connection.columns(@table_name).collect
|
770
|
+
@column_names ||= @connection.columns(@table_name).collect(&:name)
|
771
|
+
end
|
772
|
+
|
773
|
+
def model_class=(class_name)
|
774
|
+
if class_name.is_a?(Class) # TODO: Should be an AR::Base type class, or any?
|
775
|
+
@model_class = class_name
|
776
|
+
else
|
777
|
+
@model_class = class_name.safe_constantize if class_name
|
778
|
+
end
|
751
779
|
end
|
752
780
|
|
753
|
-
|
781
|
+
# Loads the fixtures from the YAML file at +path+.
|
782
|
+
# If the file sets the +model_class+ and current instance value is not set,
|
783
|
+
# it uses the file value.
|
784
|
+
def read_fixture_files(path)
|
754
785
|
yaml_files = Dir["#{path}/{**,*}/*.yml"].select { |f|
|
755
786
|
::File.file?(f)
|
756
787
|
} + [yaml_file_path(path)]
|
757
788
|
|
758
789
|
yaml_files.each_with_object({}) do |file, fixtures|
|
759
790
|
FixtureSet::File.open(file) do |fh|
|
791
|
+
self.model_class ||= fh.model_class if fh.model_class
|
760
792
|
fh.each do |fixture_name, row|
|
761
793
|
fixtures[fixture_name] = ActiveRecord::Fixture.new(row, model_class)
|
762
794
|
end
|
@@ -770,12 +802,6 @@ module ActiveRecord
|
|
770
802
|
|
771
803
|
end
|
772
804
|
|
773
|
-
#--
|
774
|
-
# Deprecate 'Fixtures' in favor of 'FixtureSet'.
|
775
|
-
#++
|
776
|
-
# :nodoc:
|
777
|
-
Fixtures = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('ActiveRecord::Fixtures', 'ActiveRecord::FixtureSet')
|
778
|
-
|
779
805
|
class Fixture #:nodoc:
|
780
806
|
include Enumerable
|
781
807
|
|
@@ -822,12 +848,12 @@ module ActiveRecord
|
|
822
848
|
module TestFixtures
|
823
849
|
extend ActiveSupport::Concern
|
824
850
|
|
825
|
-
def before_setup
|
851
|
+
def before_setup # :nodoc:
|
826
852
|
setup_fixtures
|
827
853
|
super
|
828
854
|
end
|
829
855
|
|
830
|
-
def after_teardown
|
856
|
+
def after_teardown # :nodoc:
|
831
857
|
super
|
832
858
|
teardown_fixtures
|
833
859
|
end
|
@@ -836,19 +862,29 @@ module ActiveRecord
|
|
836
862
|
class_attribute :fixture_path, :instance_writer => false
|
837
863
|
class_attribute :fixture_table_names
|
838
864
|
class_attribute :fixture_class_names
|
865
|
+
class_attribute :use_transactional_tests
|
839
866
|
class_attribute :use_transactional_fixtures
|
840
867
|
class_attribute :use_instantiated_fixtures # true, false, or :no_instances
|
841
868
|
class_attribute :pre_loaded_fixtures
|
842
869
|
class_attribute :config
|
843
870
|
|
871
|
+
singleton_class.deprecate 'use_transactional_fixtures=' => 'use use_transactional_tests= instead'
|
872
|
+
|
844
873
|
self.fixture_table_names = []
|
845
|
-
self.use_transactional_fixtures = true
|
846
874
|
self.use_instantiated_fixtures = false
|
847
875
|
self.pre_loaded_fixtures = false
|
848
876
|
self.config = ActiveRecord::Base
|
849
877
|
|
850
|
-
self.fixture_class_names =
|
851
|
-
|
878
|
+
self.fixture_class_names = {}
|
879
|
+
|
880
|
+
silence_warnings do
|
881
|
+
define_singleton_method :use_transactional_tests do
|
882
|
+
if use_transactional_fixtures.nil?
|
883
|
+
true
|
884
|
+
else
|
885
|
+
use_transactional_fixtures
|
886
|
+
end
|
887
|
+
end
|
852
888
|
end
|
853
889
|
end
|
854
890
|
|
@@ -870,7 +906,7 @@ module ActiveRecord
|
|
870
906
|
fixture_set_names = Dir["#{fixture_path}/{**,*}/*.{yml}"]
|
871
907
|
fixture_set_names.map! { |f| f[(fixture_path.to_s.size + 1)..-5] }
|
872
908
|
else
|
873
|
-
fixture_set_names = fixture_set_names.flatten.map
|
909
|
+
fixture_set_names = fixture_set_names.flatten.map(&:to_s)
|
874
910
|
end
|
875
911
|
|
876
912
|
self.fixture_table_names |= fixture_set_names
|
@@ -890,7 +926,7 @@ module ActiveRecord
|
|
890
926
|
@fixture_cache[fs_name] ||= {}
|
891
927
|
|
892
928
|
instances = fixture_names.map do |f_name|
|
893
|
-
f_name = f_name.to_s
|
929
|
+
f_name = f_name.to_s if f_name.is_a?(Symbol)
|
894
930
|
@fixture_cache[fs_name].delete(f_name) if force_reload
|
895
931
|
|
896
932
|
if @loaded_fixtures[fs_name][f_name]
|
@@ -910,7 +946,7 @@ module ActiveRecord
|
|
910
946
|
|
911
947
|
def uses_transaction(*methods)
|
912
948
|
@uses_transaction = [] unless defined?(@uses_transaction)
|
913
|
-
@uses_transaction.concat methods.map
|
949
|
+
@uses_transaction.concat methods.map(&:to_s)
|
914
950
|
end
|
915
951
|
|
916
952
|
def uses_transaction?(method)
|
@@ -920,13 +956,13 @@ module ActiveRecord
|
|
920
956
|
end
|
921
957
|
|
922
958
|
def run_in_transaction?
|
923
|
-
|
959
|
+
use_transactional_tests &&
|
924
960
|
!self.class.uses_transaction?(method_name)
|
925
961
|
end
|
926
962
|
|
927
963
|
def setup_fixtures(config = ActiveRecord::Base)
|
928
|
-
if pre_loaded_fixtures && !
|
929
|
-
raise RuntimeError, 'pre_loaded_fixtures requires
|
964
|
+
if pre_loaded_fixtures && !use_transactional_tests
|
965
|
+
raise RuntimeError, 'pre_loaded_fixtures requires use_transactional_tests'
|
930
966
|
end
|
931
967
|
|
932
968
|
@fixture_cache = {}
|
@@ -51,11 +51,15 @@ module ActiveRecord
|
|
51
51
|
end
|
52
52
|
|
53
53
|
attrs = args.first
|
54
|
-
if
|
54
|
+
if has_attribute?(inheritance_column)
|
55
55
|
subclass = subclass_from_attributes(attrs)
|
56
|
+
|
57
|
+
if subclass.nil? && base_class == self
|
58
|
+
subclass = subclass_from_attributes(column_defaults)
|
59
|
+
end
|
56
60
|
end
|
57
61
|
|
58
|
-
if subclass
|
62
|
+
if subclass && subclass != self
|
59
63
|
subclass.new(*args, &block)
|
60
64
|
else
|
61
65
|
super
|
@@ -79,20 +83,10 @@ module ActiveRecord
|
|
79
83
|
:true == (@finder_needs_type_condition ||= descends_from_active_record? ? :false : :true)
|
80
84
|
end
|
81
85
|
|
82
|
-
def symbolized_base_class
|
83
|
-
ActiveSupport::Deprecation.warn('`ActiveRecord::Base.symbolized_base_class` is deprecated and will be removed without replacement.')
|
84
|
-
@symbolized_base_class ||= base_class.to_s.to_sym
|
85
|
-
end
|
86
|
-
|
87
|
-
def symbolized_sti_name
|
88
|
-
ActiveSupport::Deprecation.warn('`ActiveRecord::Base.symbolized_sti_name` is deprecated and will be removed without replacement.')
|
89
|
-
@symbolized_sti_name ||= sti_name.present? ? sti_name.to_sym : symbolized_base_class
|
90
|
-
end
|
91
|
-
|
92
86
|
# Returns the class descending directly from ActiveRecord::Base, or
|
93
87
|
# an abstract class, if any, in the inheritance hierarchy.
|
94
88
|
#
|
95
|
-
# If A extends
|
89
|
+
# If A extends ActiveRecord::Base, A.base_class will return A. If B descends from A
|
96
90
|
# through some arbitrarily deep hierarchy, B.base_class will return A.
|
97
91
|
#
|
98
92
|
# If B < A and C < B and if A is an abstract_class then both B.base_class
|
@@ -173,49 +167,47 @@ module ActiveRecord
|
|
173
167
|
end
|
174
168
|
|
175
169
|
def using_single_table_inheritance?(record)
|
176
|
-
record[inheritance_column].present? &&
|
170
|
+
record[inheritance_column].present? && has_attribute?(inheritance_column)
|
177
171
|
end
|
178
172
|
|
179
173
|
def find_sti_class(type_name)
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
174
|
+
type_name = base_class.type_for_attribute(inheritance_column).cast(type_name)
|
175
|
+
subclass = begin
|
176
|
+
if store_full_sti_class
|
177
|
+
ActiveSupport::Dependencies.constantize(type_name)
|
178
|
+
else
|
179
|
+
compute_type(type_name)
|
180
|
+
end
|
181
|
+
rescue NameError
|
182
|
+
raise SubclassNotFound,
|
183
|
+
"The single-table inheritance mechanism failed to locate the subclass: '#{type_name}'. " \
|
184
|
+
"This error is raised because the column '#{inheritance_column}' is reserved for storing the class in case of inheritance. " \
|
185
|
+
"Please rename this column if you didn't intend it to be used for storing the inheritance class " \
|
186
|
+
"or overwrite #{name}.inheritance_column to use another column for that information."
|
184
187
|
end
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
"Please rename this column if you didn't intend it to be used for storing the inheritance class " +
|
190
|
-
"or overwrite #{name}.inheritance_column to use another column for that information."
|
188
|
+
unless subclass == self || descendants.include?(subclass)
|
189
|
+
raise SubclassNotFound, "Invalid single-table inheritance type: #{subclass.name} is not a subclass of #{name}"
|
190
|
+
end
|
191
|
+
subclass
|
191
192
|
end
|
192
193
|
|
193
194
|
def type_condition(table = arel_table)
|
194
|
-
sti_column = table
|
195
|
-
sti_names = ([self] + descendants).map
|
195
|
+
sti_column = arel_attribute(inheritance_column, table)
|
196
|
+
sti_names = ([self] + descendants).map(&:sti_name)
|
196
197
|
|
197
198
|
sti_column.in(sti_names)
|
198
199
|
end
|
199
200
|
|
200
201
|
# Detect the subclass from the inheritance column of attrs. If the inheritance column value
|
201
202
|
# is not self or a valid subclass, raises ActiveRecord::SubclassNotFound
|
202
|
-
# If this is a StrongParameters hash, and access to inheritance_column is not permitted,
|
203
|
-
# this will ignore the inheritance column and return nil
|
204
|
-
def subclass_from_attributes?(attrs)
|
205
|
-
columns_hash.include?(inheritance_column) && attrs.is_a?(Hash)
|
206
|
-
end
|
207
|
-
|
208
203
|
def subclass_from_attributes(attrs)
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
subclass = subclass_name.safe_constantize
|
204
|
+
attrs = attrs.to_h if attrs.respond_to?(:permitted?)
|
205
|
+
if attrs.is_a?(Hash)
|
206
|
+
subclass_name = attrs.with_indifferent_access[inheritance_column]
|
213
207
|
|
214
|
-
|
215
|
-
|
208
|
+
if subclass_name.present?
|
209
|
+
find_sti_class(subclass_name)
|
216
210
|
end
|
217
|
-
|
218
|
-
subclass
|
219
211
|
end
|
220
212
|
end
|
221
213
|
end
|
@@ -10,12 +10,12 @@ module ActiveRecord
|
|
10
10
|
# Indicates the format used to generate the timestamp in the cache key.
|
11
11
|
# Accepts any of the symbols in <tt>Time::DATE_FORMATS</tt>.
|
12
12
|
#
|
13
|
-
# This is +:
|
13
|
+
# This is +:usec+, by default.
|
14
14
|
class_attribute :cache_timestamp_format, :instance_writer => false
|
15
|
-
self.cache_timestamp_format = :
|
15
|
+
self.cache_timestamp_format = :usec
|
16
16
|
end
|
17
17
|
|
18
|
-
# Returns a String, which Action Pack uses for constructing
|
18
|
+
# Returns a String, which Action Pack uses for constructing a URL to this
|
19
19
|
# object. The default implementation returns this record's id as a String,
|
20
20
|
# or nil if this record's unsaved.
|
21
21
|
#
|
@@ -84,7 +84,7 @@ module ActiveRecord
|
|
84
84
|
# Values longer than 20 characters will be truncated. The value
|
85
85
|
# is truncated word by word.
|
86
86
|
#
|
87
|
-
# user = User.find_by(name: 'David
|
87
|
+
# user = User.find_by(name: 'David Heinemeier Hansson')
|
88
88
|
# user.id # => 125
|
89
89
|
# user_path(user) # => "/users/125-david"
|
90
90
|
#
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'active_record/scoping/default'
|
2
|
+
require 'active_record/scoping/named'
|
3
|
+
|
4
|
+
module ActiveRecord
|
5
|
+
# This class is used to create a table that keeps track of values and keys such
|
6
|
+
# as which environment migrations were run in.
|
7
|
+
class InternalMetadata < ActiveRecord::Base # :nodoc:
|
8
|
+
class << self
|
9
|
+
def primary_key
|
10
|
+
"key"
|
11
|
+
end
|
12
|
+
|
13
|
+
def table_name
|
14
|
+
"#{table_name_prefix}#{ActiveRecord::Base.internal_metadata_table_name}#{table_name_suffix}"
|
15
|
+
end
|
16
|
+
|
17
|
+
def original_table_name
|
18
|
+
"#{table_name_prefix}active_record_internal_metadatas#{table_name_suffix}"
|
19
|
+
end
|
20
|
+
|
21
|
+
def []=(key, value)
|
22
|
+
find_or_initialize_by(key: key).update_attributes!(value: value)
|
23
|
+
end
|
24
|
+
|
25
|
+
def [](key)
|
26
|
+
where(key: key).pluck(:value).first
|
27
|
+
end
|
28
|
+
|
29
|
+
def table_exists?
|
30
|
+
ActiveSupport::Deprecation.silence { connection.table_exists?(table_name) }
|
31
|
+
end
|
32
|
+
|
33
|
+
def original_table_exists?
|
34
|
+
# This method will be removed in Rails 5.1
|
35
|
+
# Since it is only necessary when `active_record_internal_metadatas` could exist
|
36
|
+
ActiveSupport::Deprecation.silence { connection.table_exists?(original_table_name) }
|
37
|
+
end
|
38
|
+
|
39
|
+
# Creates an internal metadata table with columns +key+ and +value+
|
40
|
+
def create_table
|
41
|
+
if original_table_exists?
|
42
|
+
connection.rename_table(original_table_name, table_name)
|
43
|
+
end
|
44
|
+
unless table_exists?
|
45
|
+
key_options = connection.internal_string_options_for_primary_key
|
46
|
+
|
47
|
+
connection.create_table(table_name, id: false) do |t|
|
48
|
+
t.string :key, key_options
|
49
|
+
t.string :value
|
50
|
+
t.timestamps
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -4,16 +4,32 @@ module ActiveRecord
|
|
4
4
|
return coder unless coder.is_a?(Psych::Coder)
|
5
5
|
|
6
6
|
case coder["active_record_yaml_version"]
|
7
|
-
when
|
7
|
+
when 1 then coder
|
8
8
|
else
|
9
9
|
if coder["attributes"].is_a?(AttributeSet)
|
10
|
-
coder
|
10
|
+
Rails420.convert(klass, coder)
|
11
11
|
else
|
12
12
|
Rails41.convert(klass, coder)
|
13
13
|
end
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
+
module Rails420
|
18
|
+
def self.convert(klass, coder)
|
19
|
+
attribute_set = coder["attributes"]
|
20
|
+
|
21
|
+
klass.attribute_names.each do |attr_name|
|
22
|
+
attribute = attribute_set[attr_name]
|
23
|
+
if attribute.type.is_a?(Delegator)
|
24
|
+
type_from_klass = klass.type_for_attribute(attr_name)
|
25
|
+
attribute_set[attr_name] = attribute.with_type(type_from_klass)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
coder
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
17
33
|
module Rails41
|
18
34
|
def self.convert(klass, coder)
|
19
35
|
attributes = klass.attributes_builder
|
@@ -7,6 +7,7 @@ en:
|
|
7
7
|
# Default error messages
|
8
8
|
errors:
|
9
9
|
messages:
|
10
|
+
required: "must exist"
|
10
11
|
taken: "has already been taken"
|
11
12
|
|
12
13
|
# Active Record models configuration
|
@@ -15,8 +16,8 @@ en:
|
|
15
16
|
messages:
|
16
17
|
record_invalid: "Validation failed: %{errors}"
|
17
18
|
restrict_dependent_destroy:
|
18
|
-
|
19
|
-
|
19
|
+
has_one: "Cannot delete record because a dependent %{record} exists"
|
20
|
+
has_many: "Cannot delete record because dependent %{record} exist"
|
20
21
|
# Append your own errors here or at the model/attributes scope.
|
21
22
|
|
22
23
|
# You can define own errors for models or model attributes.
|
@@ -11,7 +11,7 @@ module ActiveRecord
|
|
11
11
|
#
|
12
12
|
# == Usage
|
13
13
|
#
|
14
|
-
# Active
|
14
|
+
# Active Record supports optimistic locking if the +lock_version+ field is present. Each update to the
|
15
15
|
# record increments the +lock_version+ column and the locking facilities ensure that records instantiated twice
|
16
16
|
# will let the last one saved raise a +StaleObjectError+ if the first was also updated. Example:
|
17
17
|
#
|
@@ -22,7 +22,7 @@ module ActiveRecord
|
|
22
22
|
# p1.save
|
23
23
|
#
|
24
24
|
# p2.first_name = "should fail"
|
25
|
-
# p2.save # Raises
|
25
|
+
# p2.save # Raises an ActiveRecord::StaleObjectError
|
26
26
|
#
|
27
27
|
# Optimistic locking will also check for stale data when objects are destroyed. Example:
|
28
28
|
#
|
@@ -32,7 +32,7 @@ module ActiveRecord
|
|
32
32
|
# p1.first_name = "Michael"
|
33
33
|
# p1.save
|
34
34
|
#
|
35
|
-
# p2.destroy # Raises
|
35
|
+
# p2.destroy # Raises an ActiveRecord::StaleObjectError
|
36
36
|
#
|
37
37
|
# You're then responsible for dealing with the conflict by rescuing the exception and either rolling back, merging,
|
38
38
|
# or otherwise apply the business logic needed to resolve the conflict.
|
@@ -93,9 +93,9 @@ module ActiveRecord
|
|
93
93
|
self.class.primary_key => id,
|
94
94
|
lock_col => previous_lock_value,
|
95
95
|
).update_all(
|
96
|
-
|
96
|
+
attributes_for_update(attribute_names).map do |name|
|
97
97
|
[name, _read_attribute(name)]
|
98
|
-
end
|
98
|
+
end.to_h
|
99
99
|
)
|
100
100
|
|
101
101
|
unless affected_rows == 1
|
@@ -125,12 +125,8 @@ module ActiveRecord
|
|
125
125
|
relation = super
|
126
126
|
|
127
127
|
if locking_enabled?
|
128
|
-
|
129
|
-
|
130
|
-
substitute = self.class.connection.substitute_at(column)
|
131
|
-
|
132
|
-
relation = relation.where(self.class.arel_table[column_name].eq(substitute))
|
133
|
-
relation.bind_values << [column, self[column_name].to_i]
|
128
|
+
locking_column = self.class.locking_column
|
129
|
+
relation = relation.where(locking_column => _read_attribute(locking_column))
|
134
130
|
end
|
135
131
|
|
136
132
|
relation
|
@@ -148,13 +144,13 @@ module ActiveRecord
|
|
148
144
|
|
149
145
|
# Set the column to use for optimistic locking. Defaults to +lock_version+.
|
150
146
|
def locking_column=(value)
|
151
|
-
|
147
|
+
reload_schema_from_cache
|
152
148
|
@locking_column = value.to_s
|
153
149
|
end
|
154
150
|
|
155
151
|
# The version column used for optimistic locking. Defaults to +lock_version+.
|
156
152
|
def locking_column
|
157
|
-
|
153
|
+
@locking_column = DEFAULT_LOCKING_COLUMN unless defined?(@locking_column)
|
158
154
|
@locking_column
|
159
155
|
end
|
160
156
|
|
@@ -188,12 +184,16 @@ module ActiveRecord
|
|
188
184
|
end
|
189
185
|
end
|
190
186
|
|
191
|
-
class LockingType <
|
192
|
-
def
|
187
|
+
class LockingType < DelegateClass(Type::Value) # :nodoc:
|
188
|
+
def deserialize(value)
|
193
189
|
# `nil` *should* be changed to 0
|
194
190
|
super.to_i
|
195
191
|
end
|
196
192
|
|
193
|
+
def serialize(value)
|
194
|
+
super.to_i
|
195
|
+
end
|
196
|
+
|
197
197
|
def init_with(coder)
|
198
198
|
__setobj__(coder['subtype'])
|
199
199
|
end
|
@@ -51,7 +51,7 @@ module ActiveRecord
|
|
51
51
|
# end
|
52
52
|
#
|
53
53
|
# Database-specific information on row locking:
|
54
|
-
# MySQL: http://dev.mysql.com/doc/refman/5.
|
54
|
+
# MySQL: http://dev.mysql.com/doc/refman/5.7/en/innodb-locking-reads.html
|
55
55
|
# PostgreSQL: http://www.postgresql.org/docs/current/interactive/sql-select.html#SQL-FOR-UPDATE-SHARE
|
56
56
|
module Pessimistic
|
57
57
|
# Obtain a row lock on this record. Reloads the record to obtain the requested
|