activerecord 4.2.0 → 5.0.0
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 +1537 -789
- 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 +37 -23
- data/lib/active_record/association_relation.rb +16 -3
- data/lib/active_record/associations/alias_tracker.rb +19 -16
- data/lib/active_record/associations/association.rb +23 -9
- data/lib/active_record/associations/association_scope.rb +74 -102
- data/lib/active_record/associations/belongs_to_association.rb +26 -29
- 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 +12 -20
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +22 -15
- 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 +61 -33
- data/lib/active_record/associations/collection_proxy.rb +81 -35
- data/lib/active_record/associations/foreign_association.rb +11 -0
- data/lib/active_record/associations/has_many_association.rb +21 -57
- data/lib/active_record/associations/has_many_through_association.rb +15 -45
- data/lib/active_record/associations/has_one_association.rb +13 -5
- data/lib/active_record/associations/join_dependency/join_association.rb +20 -8
- data/lib/active_record/associations/join_dependency.rb +37 -21
- data/lib/active_record/associations/preloader/association.rb +51 -53
- 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 +18 -8
- data/lib/active_record/associations/singular_association.rb +8 -8
- data/lib/active_record/associations/through_association.rb +22 -9
- data/lib/active_record/associations.rb +321 -212
- data/lib/active_record/attribute/user_provided_default.rb +28 -0
- data/lib/active_record/attribute.rb +79 -15
- data/lib/active_record/attribute_assignment.rb +20 -141
- data/lib/active_record/attribute_decorators.rb +6 -5
- data/lib/active_record/attribute_methods/before_type_cast.rb +6 -1
- data/lib/active_record/attribute_methods/dirty.rb +51 -81
- 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 +65 -14
- data/lib/active_record/attribute_methods/write.rb +14 -38
- data/lib/active_record/attribute_methods.rb +70 -45
- data/lib/active_record/attribute_mutation_tracker.rb +70 -0
- data/lib/active_record/attribute_set/builder.rb +37 -15
- data/lib/active_record/attribute_set.rb +34 -3
- data/lib/active_record/attributes.rb +199 -73
- data/lib/active_record/autosave_association.rb +73 -25
- data/lib/active_record/base.rb +35 -27
- 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 +457 -181
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +83 -59
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/quoting.rb +74 -9
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -4
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +61 -39
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +246 -185
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +72 -17
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +438 -136
- data/lib/active_record/connection_adapters/abstract/transaction.rb +53 -40
- data/lib/active_record/connection_adapters/abstract_adapter.rb +166 -66
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +429 -335
- 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 +26 -177
- data/lib/active_record/connection_adapters/postgresql/column.rb +5 -10
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +11 -73
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +42 -0
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +27 -56
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -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 -13
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +3 -1
- 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/type_map_initializer.rb +17 -5
- 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 +248 -154
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +35 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +258 -170
- 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 +150 -209
- data/lib/active_record/connection_adapters/statement_pool.rb +31 -12
- data/lib/active_record/connection_handling.rb +38 -15
- data/lib/active_record/core.rb +109 -114
- data/lib/active_record/counter_cache.rb +14 -25
- data/lib/active_record/dynamic_matchers.rb +1 -20
- data/lib/active_record/enum.rb +115 -79
- data/lib/active_record/errors.rb +88 -48
- data/lib/active_record/explain_registry.rb +1 -1
- data/lib/active_record/explain_subscriber.rb +2 -2
- data/lib/active_record/fixture_set/file.rb +26 -5
- data/lib/active_record/fixtures.rb +84 -46
- data/lib/active_record/gem_version.rb +2 -2
- 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 +46 -0
- data/lib/active_record/locale/en.yml +3 -2
- data/lib/active_record/locking/optimistic.rb +27 -25
- 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 +372 -114
- data/lib/active_record/model_schema.rb +128 -38
- data/lib/active_record/nested_attributes.rb +71 -32
- data/lib/active_record/no_touching.rb +1 -1
- data/lib/active_record/null_relation.rb +16 -8
- data/lib/active_record/persistence.rb +124 -80
- data/lib/active_record/query_cache.rb +15 -18
- data/lib/active_record/querying.rb +10 -9
- data/lib/active_record/railtie.rb +28 -19
- data/lib/active_record/railties/controller_runtime.rb +1 -1
- data/lib/active_record/railties/databases.rake +67 -51
- data/lib/active_record/readonly_attributes.rb +1 -1
- data/lib/active_record/reflection.rb +318 -139
- 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 +80 -102
- data/lib/active_record/relation/delegation.rb +7 -20
- data/lib/active_record/relation/finder_methods.rb +167 -97
- data/lib/active_record/relation/from_clause.rb +32 -0
- data/lib/active_record/relation/merger.rb +38 -41
- data/lib/active_record/relation/predicate_builder/array_handler.rb +12 -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 +124 -82
- data/lib/active_record/relation/query_attribute.rb +19 -0
- data/lib/active_record/relation/query_methods.rb +323 -257
- data/lib/active_record/relation/record_fetch_warning.rb +49 -0
- data/lib/active_record/relation/spawn_methods.rb +11 -10
- 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 -115
- 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 -17
- data/lib/active_record/scoping/default.rb +24 -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 +59 -42
- data/lib/active_record/tasks/mysql_database_tasks.rb +32 -26
- data/lib/active_record/tasks/postgresql_database_tasks.rb +29 -9
- 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 +159 -67
- data/lib/active_record/type/adapter_specific_registry.rb +130 -0
- data/lib/active_record/type/date.rb +2 -41
- data/lib/active_record/type/date_time.rb +2 -38
- data/lib/active_record/type/hash_lookup_type_map.rb +8 -2
- 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 +21 -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 +29 -18
- data/lib/active_record/validations.rb +33 -32
- data/lib/active_record.rb +9 -2
- 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 -6
- data/lib/rails/generators/active_record/migration/templates/migration.rb +8 -7
- 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 -491
- 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 -30
- data/lib/active_record/type/decimal.rb +0 -40
- 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 -55
- 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 -36
- 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 -101
@@ -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|
|
@@ -534,12 +553,10 @@ module ActiveRecord
|
|
534
553
|
conn.insert_fixture(row, fixture_set_name)
|
535
554
|
end
|
536
555
|
end
|
537
|
-
end
|
538
556
|
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
connection.reset_pk_sequence!(fs.table_name)
|
557
|
+
# Cap primary key sequences to max(pk).
|
558
|
+
if conn.respond_to?(:reset_pk_sequence!)
|
559
|
+
conn.reset_pk_sequence!(fs.table_name)
|
543
560
|
end
|
544
561
|
end
|
545
562
|
end
|
@@ -575,21 +592,16 @@ module ActiveRecord
|
|
575
592
|
@name = name
|
576
593
|
@path = path
|
577
594
|
@config = config
|
578
|
-
@model_class = nil
|
579
595
|
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
@model_class = class_name.safe_constantize if class_name
|
584
|
-
end
|
596
|
+
self.model_class = class_name
|
597
|
+
|
598
|
+
@fixtures = read_fixture_files(path)
|
585
599
|
|
586
600
|
@connection = connection
|
587
601
|
|
588
602
|
@table_name = ( model_class.respond_to?(:table_name) ?
|
589
603
|
model_class.table_name :
|
590
604
|
self.class.default_fixture_table_name(name, config) )
|
591
|
-
|
592
|
-
@fixtures = read_fixture_files path, @model_class
|
593
605
|
end
|
594
606
|
|
595
607
|
def [](x)
|
@@ -612,7 +624,6 @@ module ActiveRecord
|
|
612
624
|
# a list of rows to insert to that table.
|
613
625
|
def table_rows
|
614
626
|
now = config.default_timezone == :utc ? Time.now.utc : Time.now
|
615
|
-
now = now.to_s(:db)
|
616
627
|
|
617
628
|
# allow a standard key to be used for doing defaults in YAML
|
618
629
|
fixtures.delete('DEFAULTS')
|
@@ -633,7 +644,7 @@ module ActiveRecord
|
|
633
644
|
|
634
645
|
# interpolate the fixture label
|
635
646
|
row.each do |key, value|
|
636
|
-
row[key] = value.gsub("$LABEL", label) if value.is_a?(String)
|
647
|
+
row[key] = value.gsub("$LABEL", label.to_s) if value.is_a?(String)
|
637
648
|
end
|
638
649
|
|
639
650
|
# generate a primary key if necessary
|
@@ -641,6 +652,13 @@ module ActiveRecord
|
|
641
652
|
row[primary_key_name] = ActiveRecord::FixtureSet.identify(label, primary_key_type)
|
642
653
|
end
|
643
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
|
+
|
644
662
|
# If STI is used, find the correct subclass for association reflection
|
645
663
|
reflection_class =
|
646
664
|
if row.include?(inheritance_column_name)
|
@@ -661,7 +679,7 @@ module ActiveRecord
|
|
661
679
|
row[association.foreign_type] = $1
|
662
680
|
end
|
663
681
|
|
664
|
-
fk_type =
|
682
|
+
fk_type = reflection_class.type_for_attribute(fk_name).type
|
665
683
|
row[fk_name] = ActiveRecord::FixtureSet.identify(value, fk_type)
|
666
684
|
end
|
667
685
|
when :has_many
|
@@ -691,7 +709,7 @@ module ActiveRecord
|
|
691
709
|
end
|
692
710
|
|
693
711
|
def primary_key_type
|
694
|
-
@association.klass.
|
712
|
+
@association.klass.type_for_attribute(@association.klass.primary_key).type
|
695
713
|
end
|
696
714
|
end
|
697
715
|
|
@@ -703,6 +721,10 @@ module ActiveRecord
|
|
703
721
|
def lhs_key
|
704
722
|
@association.through_reflection.foreign_key
|
705
723
|
end
|
724
|
+
|
725
|
+
def join_table
|
726
|
+
@association.through_reflection.table_name
|
727
|
+
end
|
706
728
|
end
|
707
729
|
|
708
730
|
private
|
@@ -711,7 +733,7 @@ module ActiveRecord
|
|
711
733
|
end
|
712
734
|
|
713
735
|
def primary_key_type
|
714
|
-
@primary_key_type ||= model_class && model_class.
|
736
|
+
@primary_key_type ||= model_class && model_class.type_for_attribute(model_class.primary_key).type
|
715
737
|
end
|
716
738
|
|
717
739
|
def add_join_records(rows, row, association)
|
@@ -745,16 +767,28 @@ module ActiveRecord
|
|
745
767
|
end
|
746
768
|
|
747
769
|
def column_names
|
748
|
-
@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
|
749
779
|
end
|
750
780
|
|
751
|
-
|
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)
|
752
785
|
yaml_files = Dir["#{path}/{**,*}/*.yml"].select { |f|
|
753
786
|
::File.file?(f)
|
754
787
|
} + [yaml_file_path(path)]
|
755
788
|
|
756
789
|
yaml_files.each_with_object({}) do |file, fixtures|
|
757
790
|
FixtureSet::File.open(file) do |fh|
|
791
|
+
self.model_class ||= fh.model_class if fh.model_class
|
758
792
|
fh.each do |fixture_name, row|
|
759
793
|
fixtures[fixture_name] = ActiveRecord::Fixture.new(row, model_class)
|
760
794
|
end
|
@@ -768,12 +802,6 @@ module ActiveRecord
|
|
768
802
|
|
769
803
|
end
|
770
804
|
|
771
|
-
#--
|
772
|
-
# Deprecate 'Fixtures' in favor of 'FixtureSet'.
|
773
|
-
#++
|
774
|
-
# :nodoc:
|
775
|
-
Fixtures = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('ActiveRecord::Fixtures', 'ActiveRecord::FixtureSet')
|
776
|
-
|
777
805
|
class Fixture #:nodoc:
|
778
806
|
include Enumerable
|
779
807
|
|
@@ -820,12 +848,12 @@ module ActiveRecord
|
|
820
848
|
module TestFixtures
|
821
849
|
extend ActiveSupport::Concern
|
822
850
|
|
823
|
-
def before_setup
|
851
|
+
def before_setup # :nodoc:
|
824
852
|
setup_fixtures
|
825
853
|
super
|
826
854
|
end
|
827
855
|
|
828
|
-
def after_teardown
|
856
|
+
def after_teardown # :nodoc:
|
829
857
|
super
|
830
858
|
teardown_fixtures
|
831
859
|
end
|
@@ -834,19 +862,29 @@ module ActiveRecord
|
|
834
862
|
class_attribute :fixture_path, :instance_writer => false
|
835
863
|
class_attribute :fixture_table_names
|
836
864
|
class_attribute :fixture_class_names
|
865
|
+
class_attribute :use_transactional_tests
|
837
866
|
class_attribute :use_transactional_fixtures
|
838
867
|
class_attribute :use_instantiated_fixtures # true, false, or :no_instances
|
839
868
|
class_attribute :pre_loaded_fixtures
|
840
869
|
class_attribute :config
|
841
870
|
|
871
|
+
singleton_class.deprecate 'use_transactional_fixtures=' => 'use use_transactional_tests= instead'
|
872
|
+
|
842
873
|
self.fixture_table_names = []
|
843
|
-
self.use_transactional_fixtures = true
|
844
874
|
self.use_instantiated_fixtures = false
|
845
875
|
self.pre_loaded_fixtures = false
|
846
876
|
self.config = ActiveRecord::Base
|
847
877
|
|
848
|
-
self.fixture_class_names =
|
849
|
-
|
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
|
850
888
|
end
|
851
889
|
end
|
852
890
|
|
@@ -868,7 +906,7 @@ module ActiveRecord
|
|
868
906
|
fixture_set_names = Dir["#{fixture_path}/{**,*}/*.{yml}"]
|
869
907
|
fixture_set_names.map! { |f| f[(fixture_path.to_s.size + 1)..-5] }
|
870
908
|
else
|
871
|
-
fixture_set_names = fixture_set_names.flatten.map
|
909
|
+
fixture_set_names = fixture_set_names.flatten.map(&:to_s)
|
872
910
|
end
|
873
911
|
|
874
912
|
self.fixture_table_names |= fixture_set_names
|
@@ -888,7 +926,7 @@ module ActiveRecord
|
|
888
926
|
@fixture_cache[fs_name] ||= {}
|
889
927
|
|
890
928
|
instances = fixture_names.map do |f_name|
|
891
|
-
f_name = f_name.to_s
|
929
|
+
f_name = f_name.to_s if f_name.is_a?(Symbol)
|
892
930
|
@fixture_cache[fs_name].delete(f_name) if force_reload
|
893
931
|
|
894
932
|
if @loaded_fixtures[fs_name][f_name]
|
@@ -908,7 +946,7 @@ module ActiveRecord
|
|
908
946
|
|
909
947
|
def uses_transaction(*methods)
|
910
948
|
@uses_transaction = [] unless defined?(@uses_transaction)
|
911
|
-
@uses_transaction.concat methods.map
|
949
|
+
@uses_transaction.concat methods.map(&:to_s)
|
912
950
|
end
|
913
951
|
|
914
952
|
def uses_transaction?(method)
|
@@ -918,13 +956,13 @@ module ActiveRecord
|
|
918
956
|
end
|
919
957
|
|
920
958
|
def run_in_transaction?
|
921
|
-
|
959
|
+
use_transactional_tests &&
|
922
960
|
!self.class.uses_transaction?(method_name)
|
923
961
|
end
|
924
962
|
|
925
963
|
def setup_fixtures(config = ActiveRecord::Base)
|
926
|
-
if pre_loaded_fixtures && !
|
927
|
-
raise RuntimeError, 'pre_loaded_fixtures requires
|
964
|
+
if pre_loaded_fixtures && !use_transactional_tests
|
965
|
+
raise RuntimeError, 'pre_loaded_fixtures requires use_transactional_tests'
|
928
966
|
end
|
929
967
|
|
930
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
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module LegacyYamlAdapter
|
3
|
+
def self.convert(klass, coder)
|
4
|
+
return coder unless coder.is_a?(Psych::Coder)
|
5
|
+
|
6
|
+
case coder["active_record_yaml_version"]
|
7
|
+
when 1 then coder
|
8
|
+
else
|
9
|
+
if coder["attributes"].is_a?(AttributeSet)
|
10
|
+
Rails420.convert(klass, coder)
|
11
|
+
else
|
12
|
+
Rails41.convert(klass, coder)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
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
|
+
|
33
|
+
module Rails41
|
34
|
+
def self.convert(klass, coder)
|
35
|
+
attributes = klass.attributes_builder
|
36
|
+
.build_from_database(coder["attributes"])
|
37
|
+
new_record = coder["attributes"][klass.primary_key].blank?
|
38
|
+
|
39
|
+
{
|
40
|
+
"attributes" => attributes,
|
41
|
+
"new_record" => new_record,
|
42
|
+
}
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -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.
|