activerecord 3.1.10 → 4.2.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +6 -6
- data/CHANGELOG.md +1837 -338
- data/MIT-LICENSE +1 -1
- data/README.rdoc +39 -43
- data/examples/performance.rb +51 -20
- data/examples/simple.rb +4 -4
- data/lib/active_record/aggregations.rb +57 -43
- data/lib/active_record/association_relation.rb +35 -0
- data/lib/active_record/associations/alias_tracker.rb +47 -39
- data/lib/active_record/associations/association.rb +71 -85
- data/lib/active_record/associations/association_scope.rb +138 -89
- data/lib/active_record/associations/belongs_to_association.rb +65 -25
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +9 -3
- data/lib/active_record/associations/builder/association.rb +125 -29
- data/lib/active_record/associations/builder/belongs_to.rb +91 -60
- data/lib/active_record/associations/builder/collection_association.rb +69 -49
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +113 -42
- data/lib/active_record/associations/builder/has_many.rb +8 -64
- data/lib/active_record/associations/builder/has_one.rb +12 -52
- data/lib/active_record/associations/builder/singular_association.rb +22 -29
- data/lib/active_record/associations/collection_association.rb +294 -187
- data/lib/active_record/associations/collection_proxy.rb +961 -94
- data/lib/active_record/associations/foreign_association.rb +11 -0
- data/lib/active_record/associations/has_many_association.rb +118 -23
- data/lib/active_record/associations/has_many_through_association.rb +115 -45
- data/lib/active_record/associations/has_one_association.rb +57 -24
- data/lib/active_record/associations/has_one_through_association.rb +1 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +76 -102
- data/lib/active_record/associations/join_dependency/join_base.rb +7 -9
- data/lib/active_record/associations/join_dependency/join_part.rb +30 -37
- data/lib/active_record/associations/join_dependency.rb +230 -156
- data/lib/active_record/associations/preloader/association.rb +96 -55
- data/lib/active_record/associations/preloader/collection_association.rb +3 -3
- data/lib/active_record/associations/preloader/has_many_through.rb +7 -3
- data/lib/active_record/associations/preloader/has_one.rb +1 -1
- data/lib/active_record/associations/preloader/singular_association.rb +3 -3
- data/lib/active_record/associations/preloader/through_association.rb +61 -32
- data/lib/active_record/associations/preloader.rb +113 -87
- data/lib/active_record/associations/singular_association.rb +29 -13
- data/lib/active_record/associations/through_association.rb +37 -19
- data/lib/active_record/associations.rb +505 -371
- data/lib/active_record/attribute.rb +163 -0
- data/lib/active_record/attribute_assignment.rb +212 -0
- data/lib/active_record/attribute_decorators.rb +66 -0
- data/lib/active_record/attribute_methods/before_type_cast.rb +52 -7
- data/lib/active_record/attribute_methods/dirty.rb +141 -51
- data/lib/active_record/attribute_methods/primary_key.rb +87 -36
- data/lib/active_record/attribute_methods/query.rb +5 -4
- data/lib/active_record/attribute_methods/read.rb +74 -117
- data/lib/active_record/attribute_methods/serialization.rb +70 -0
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +49 -47
- data/lib/active_record/attribute_methods/write.rb +60 -21
- data/lib/active_record/attribute_methods.rb +409 -48
- data/lib/active_record/attribute_set/builder.rb +106 -0
- data/lib/active_record/attribute_set.rb +81 -0
- data/lib/active_record/attributes.rb +147 -0
- data/lib/active_record/autosave_association.rb +279 -232
- data/lib/active_record/base.rb +84 -1969
- data/lib/active_record/callbacks.rb +66 -28
- data/lib/active_record/coders/json.rb +13 -0
- data/lib/active_record/coders/yaml_column.rb +18 -21
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +422 -243
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +9 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +170 -194
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +32 -19
- data/lib/active_record/connection_adapters/abstract/quoting.rb +79 -57
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +21 -0
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +125 -0
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +273 -170
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +50 -0
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +731 -254
- data/lib/active_record/connection_adapters/abstract/transaction.rb +215 -0
- data/lib/active_record/connection_adapters/abstract_adapter.rb +339 -95
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +946 -0
- data/lib/active_record/connection_adapters/column.rb +33 -221
- data/lib/active_record/connection_adapters/connection_specification.rb +275 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +140 -602
- data/lib/active_record/connection_adapters/mysql_adapter.rb +254 -756
- data/lib/active_record/connection_adapters/postgresql/array_parser.rb +93 -0
- data/lib/active_record/connection_adapters/postgresql/column.rb +20 -0
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +232 -0
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +100 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +52 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +13 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +46 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +11 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +36 -0
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +13 -0
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +19 -0
- data/lib/active_record/connection_adapters/postgresql/oid/float.rb +21 -0
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +59 -0
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +13 -0
- data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +13 -0
- data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +11 -0
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +35 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +23 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +43 -0
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +43 -0
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +79 -0
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +19 -0
- data/lib/active_record/connection_adapters/postgresql/oid/time.rb +11 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +109 -0
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +21 -0
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +26 -0
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +28 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +36 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +108 -0
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +30 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +152 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +596 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +77 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +445 -902
- data/lib/active_record/connection_adapters/schema_cache.rb +94 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +578 -25
- data/lib/active_record/connection_handling.rb +132 -0
- data/lib/active_record/core.rb +579 -0
- data/lib/active_record/counter_cache.rb +159 -102
- data/lib/active_record/dynamic_matchers.rb +140 -0
- data/lib/active_record/enum.rb +197 -0
- data/lib/active_record/errors.rb +102 -34
- data/lib/active_record/explain.rb +38 -0
- data/lib/active_record/explain_registry.rb +30 -0
- data/lib/active_record/explain_subscriber.rb +29 -0
- data/lib/active_record/fixture_set/file.rb +56 -0
- data/lib/active_record/fixtures.rb +318 -260
- data/lib/active_record/gem_version.rb +15 -0
- data/lib/active_record/inheritance.rb +247 -0
- data/lib/active_record/integration.rb +113 -0
- data/lib/active_record/legacy_yaml_adapter.rb +30 -0
- data/lib/active_record/locale/en.yml +8 -1
- data/lib/active_record/locking/optimistic.rb +80 -52
- data/lib/active_record/locking/pessimistic.rb +27 -5
- data/lib/active_record/log_subscriber.rb +25 -18
- data/lib/active_record/migration/command_recorder.rb +130 -38
- data/lib/active_record/migration/join_table.rb +15 -0
- data/lib/active_record/migration.rb +532 -201
- data/lib/active_record/model_schema.rb +342 -0
- data/lib/active_record/nested_attributes.rb +229 -139
- data/lib/active_record/no_touching.rb +52 -0
- data/lib/active_record/null_relation.rb +81 -0
- data/lib/active_record/persistence.rb +304 -99
- data/lib/active_record/query_cache.rb +25 -43
- data/lib/active_record/querying.rb +68 -0
- data/lib/active_record/railtie.rb +86 -45
- data/lib/active_record/railties/console_sandbox.rb +3 -4
- data/lib/active_record/railties/controller_runtime.rb +7 -4
- data/lib/active_record/railties/databases.rake +198 -377
- data/lib/active_record/railties/jdbcmysql_error.rb +2 -2
- data/lib/active_record/readonly_attributes.rb +23 -0
- data/lib/active_record/reflection.rb +516 -165
- data/lib/active_record/relation/batches.rb +96 -45
- data/lib/active_record/relation/calculations.rb +221 -144
- data/lib/active_record/relation/delegation.rb +140 -0
- data/lib/active_record/relation/finder_methods.rb +362 -243
- data/lib/active_record/relation/merger.rb +193 -0
- data/lib/active_record/relation/predicate_builder/array_handler.rb +48 -0
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +13 -0
- data/lib/active_record/relation/predicate_builder.rb +135 -41
- data/lib/active_record/relation/query_methods.rb +982 -155
- data/lib/active_record/relation/spawn_methods.rb +50 -110
- data/lib/active_record/relation.rb +371 -180
- data/lib/active_record/result.rb +109 -12
- data/lib/active_record/runtime_registry.rb +22 -0
- data/lib/active_record/sanitization.rb +191 -0
- data/lib/active_record/schema.rb +19 -13
- data/lib/active_record/schema_dumper.rb +111 -61
- data/lib/active_record/schema_migration.rb +53 -0
- data/lib/active_record/scoping/default.rb +135 -0
- data/lib/active_record/scoping/named.rb +164 -0
- data/lib/active_record/scoping.rb +87 -0
- data/lib/active_record/serialization.rb +7 -45
- data/lib/active_record/serializers/xml_serializer.rb +14 -65
- data/lib/active_record/statement_cache.rb +111 -0
- data/lib/active_record/store.rb +205 -0
- data/lib/active_record/tasks/database_tasks.rb +299 -0
- data/lib/active_record/tasks/mysql_database_tasks.rb +159 -0
- data/lib/active_record/tasks/postgresql_database_tasks.rb +101 -0
- data/lib/active_record/tasks/sqlite_database_tasks.rb +55 -0
- data/lib/active_record/timestamp.rb +35 -14
- data/lib/active_record/transactions.rb +141 -74
- data/lib/active_record/translation.rb +22 -0
- data/lib/active_record/type/big_integer.rb +13 -0
- data/lib/active_record/type/binary.rb +50 -0
- data/lib/active_record/type/boolean.rb +31 -0
- data/lib/active_record/type/date.rb +50 -0
- data/lib/active_record/type/date_time.rb +54 -0
- data/lib/active_record/type/decimal.rb +64 -0
- data/lib/active_record/type/decimal_without_scale.rb +11 -0
- data/lib/active_record/type/decorator.rb +14 -0
- data/lib/active_record/type/float.rb +19 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +23 -0
- data/lib/active_record/type/integer.rb +59 -0
- data/lib/active_record/type/mutable.rb +16 -0
- data/lib/active_record/type/numeric.rb +36 -0
- data/lib/active_record/type/serialized.rb +62 -0
- data/lib/active_record/type/string.rb +40 -0
- data/lib/active_record/type/text.rb +11 -0
- data/lib/active_record/type/time.rb +26 -0
- data/lib/active_record/type/time_value.rb +38 -0
- data/lib/active_record/type/type_map.rb +64 -0
- data/lib/active_record/type/unsigned_integer.rb +15 -0
- data/lib/active_record/type/value.rb +110 -0
- data/lib/active_record/type.rb +23 -0
- data/lib/active_record/validations/associated.rb +27 -18
- data/lib/active_record/validations/presence.rb +67 -0
- data/lib/active_record/validations/uniqueness.rb +125 -66
- data/lib/active_record/validations.rb +37 -30
- data/lib/active_record/version.rb +5 -7
- data/lib/active_record.rb +80 -25
- data/lib/rails/generators/active_record/migration/migration_generator.rb +54 -9
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +19 -0
- data/lib/rails/generators/active_record/migration/templates/migration.rb +25 -11
- data/lib/rails/generators/active_record/migration.rb +11 -8
- data/lib/rails/generators/active_record/model/model_generator.rb +17 -4
- data/lib/rails/generators/active_record/model/templates/model.rb +5 -2
- data/lib/rails/generators/active_record/model/templates/module.rb +1 -1
- data/lib/rails/generators/active_record.rb +3 -11
- metadata +132 -53
- data/examples/associations.png +0 -0
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +0 -62
- data/lib/active_record/associations/join_helper.rb +0 -55
- data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +0 -60
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +0 -135
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +0 -556
- data/lib/active_record/dynamic_finder_match.rb +0 -56
- data/lib/active_record/dynamic_scope_match.rb +0 -23
- data/lib/active_record/identity_map.rb +0 -163
- data/lib/active_record/named_scope.rb +0 -200
- data/lib/active_record/observer.rb +0 -121
- data/lib/active_record/session_store.rb +0 -358
- data/lib/active_record/test_case.rb +0 -69
- data/lib/rails/generators/active_record/model/templates/migration.rb +0 -17
- data/lib/rails/generators/active_record/observer/observer_generator.rb +0 -15
- data/lib/rails/generators/active_record/observer/templates/observer.rb +0 -4
- data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +0 -25
- data/lib/rails/generators/active_record/session_migration/templates/migration.rb +0 -16
@@ -1,39 +1,24 @@
|
|
1
1
|
require 'erb'
|
2
|
-
|
3
|
-
begin
|
4
|
-
require 'psych'
|
5
|
-
rescue LoadError
|
6
|
-
end
|
7
|
-
|
8
2
|
require 'yaml'
|
9
|
-
require 'csv'
|
10
3
|
require 'zlib'
|
11
4
|
require 'active_support/dependencies'
|
12
|
-
require 'active_support/core_ext/
|
13
|
-
require '
|
14
|
-
require '
|
15
|
-
require 'active_support/ordered_hash'
|
16
|
-
require 'active_support/core_ext/module/deprecation'
|
5
|
+
require 'active_support/core_ext/digest/uuid'
|
6
|
+
require 'active_record/fixture_set/file'
|
7
|
+
require 'active_record/errors'
|
17
8
|
|
18
|
-
|
9
|
+
module ActiveRecord
|
19
10
|
class FixtureClassNotFound < ActiveRecord::ActiveRecordError #:nodoc:
|
20
11
|
end
|
21
|
-
else
|
22
|
-
class FixtureClassNotFound < StandardError #:nodoc:
|
23
|
-
end
|
24
|
-
end
|
25
12
|
|
26
|
-
class FixturesFileNotFound < StandardError; end
|
27
|
-
|
28
|
-
module ActiveRecord
|
29
13
|
# \Fixtures are a way of organizing data that you want to test against; in short, sample data.
|
30
14
|
#
|
31
15
|
# They are stored in YAML files, one file per model, which are placed in the directory
|
32
16
|
# appointed by <tt>ActiveSupport::TestCase.fixture_path=(path)</tt> (this is automatically
|
33
17
|
# configured for Rails, so you can just put your files in <tt><your-rails-app>/test/fixtures/</tt>).
|
34
|
-
# The fixture file ends with the
|
35
|
-
# <tt><your-rails-app>/test/fixtures/web_sites.yml</tt>).
|
36
|
-
#
|
18
|
+
# The fixture file ends with the +.yml+ file extension, for example:
|
19
|
+
# <tt><your-rails-app>/test/fixtures/web_sites.yml</tt>).
|
20
|
+
#
|
21
|
+
# The format of a fixture file looks like this:
|
37
22
|
#
|
38
23
|
# rubyonrails:
|
39
24
|
# id: 1
|
@@ -49,7 +34,7 @@ module ActiveRecord
|
|
49
34
|
# is followed by an indented list of key/value pairs in the "key: value" format. Records are
|
50
35
|
# separated by a blank line for your viewing pleasure.
|
51
36
|
#
|
52
|
-
# Note
|
37
|
+
# Note: Fixtures are unordered. If you want ordered fixtures, use the omap YAML type.
|
53
38
|
# See http://yaml.org/type/omap.html
|
54
39
|
# for the specification. You will need ordered fixtures when you have foreign key constraints
|
55
40
|
# on keys in the same table. This is commonly needed for tree structures. Example:
|
@@ -77,8 +62,8 @@ module ActiveRecord
|
|
77
62
|
# end
|
78
63
|
# end
|
79
64
|
#
|
80
|
-
# By default,
|
81
|
-
# so this test will succeed.
|
65
|
+
# By default, +test_helper.rb+ will load all of your fixtures into your test
|
66
|
+
# database, so this test will succeed.
|
82
67
|
#
|
83
68
|
# The testing environment will automatically load the all fixtures into the database before each
|
84
69
|
# test. To ensure consistent data, the environment deletes the fixtures before running the load.
|
@@ -99,7 +84,7 @@ module ActiveRecord
|
|
99
84
|
# end
|
100
85
|
#
|
101
86
|
# test "find_alt_method_2" do
|
102
|
-
# assert_equal "Ruby on Rails", @rubyonrails.
|
87
|
+
# assert_equal "Ruby on Rails", @rubyonrails.name
|
103
88
|
# end
|
104
89
|
#
|
105
90
|
# In order to use these methods to access fixtured data within your testcases, you must specify one of the
|
@@ -136,6 +121,23 @@ module ActiveRecord
|
|
136
121
|
# perhaps you should reexamine whether your application is properly testable. Hence, dynamic values
|
137
122
|
# in fixtures are to be considered a code smell.
|
138
123
|
#
|
124
|
+
# Helper methods defined in a fixture will not be available in other fixtures, to prevent against
|
125
|
+
# unwanted inter-test dependencies. Methods used by multiple fixtures should be defined in a module
|
126
|
+
# that is included in <tt>ActiveRecord::FixtureSet.context_class</tt>.
|
127
|
+
#
|
128
|
+
# - define a helper method in `test_helper.rb`
|
129
|
+
# module FixtureFileHelpers
|
130
|
+
# def file_sha(path)
|
131
|
+
# Digest::SHA2.hexdigest(File.read(Rails.root.join('test/fixtures', path)))
|
132
|
+
# end
|
133
|
+
# end
|
134
|
+
# ActiveRecord::FixtureSet.context_class.send :include, FixtureFileHelpers
|
135
|
+
#
|
136
|
+
# - use the helper method in a fixture
|
137
|
+
# photo:
|
138
|
+
# name: kitten.png
|
139
|
+
# sha: <%= file_sha 'files/kitten.png' %>
|
140
|
+
#
|
139
141
|
# = Transactional Fixtures
|
140
142
|
#
|
141
143
|
# Test cases can use begin+rollback to isolate their changes to the database instead of having to
|
@@ -179,6 +181,9 @@ module ActiveRecord
|
|
179
181
|
# * Stable, autogenerated IDs
|
180
182
|
# * Label references for associations (belongs_to, has_one, has_many)
|
181
183
|
# * HABTM associations as inline lists
|
184
|
+
#
|
185
|
+
# There are some more advanced features available even if the id is specified:
|
186
|
+
#
|
182
187
|
# * Autofilled timestamp columns
|
183
188
|
# * Fixture label interpolation
|
184
189
|
# * Support for YAML defaults
|
@@ -265,7 +270,7 @@ module ActiveRecord
|
|
265
270
|
#
|
266
271
|
# ### in fruit.rb
|
267
272
|
#
|
268
|
-
# belongs_to :eater, :
|
273
|
+
# belongs_to :eater, polymorphic: true
|
269
274
|
#
|
270
275
|
# ### in fruits.yml
|
271
276
|
#
|
@@ -361,41 +366,54 @@ module ActiveRecord
|
|
361
366
|
# geeksomnia:
|
362
367
|
# name: Geeksomnia's Account
|
363
368
|
# subdomain: $LABEL
|
369
|
+
# email: $LABEL@email.com
|
364
370
|
#
|
365
371
|
# Also, sometimes (like when porting older join table fixtures) you'll need
|
366
372
|
# to be able to get a hold of the identifier for a given label. ERB
|
367
373
|
# to the rescue:
|
368
374
|
#
|
369
375
|
# george_reginald:
|
370
|
-
# monkey_id: <%= ActiveRecord::
|
371
|
-
# pirate_id: <%= ActiveRecord::
|
376
|
+
# monkey_id: <%= ActiveRecord::FixtureSet.identify(:reginald) %>
|
377
|
+
# pirate_id: <%= ActiveRecord::FixtureSet.identify(:george) %>
|
372
378
|
#
|
373
379
|
# == Support for YAML defaults
|
374
380
|
#
|
375
|
-
# You
|
376
|
-
#
|
381
|
+
# You can set and reuse defaults in your fixtures YAML file.
|
382
|
+
# This is the same technique used in the +database.yml+ file to specify
|
383
|
+
# defaults:
|
377
384
|
#
|
378
385
|
# DEFAULTS: &DEFAULTS
|
379
386
|
# created_on: <%= 3.weeks.ago.to_s(:db) %>
|
380
387
|
#
|
381
388
|
# first:
|
382
389
|
# name: Smurf
|
383
|
-
# *DEFAULTS
|
390
|
+
# <<: *DEFAULTS
|
384
391
|
#
|
385
392
|
# second:
|
386
393
|
# name: Fraggle
|
387
|
-
# *DEFAULTS
|
394
|
+
# <<: *DEFAULTS
|
388
395
|
#
|
389
396
|
# Any fixture labeled "DEFAULTS" is safely ignored.
|
390
|
-
class
|
397
|
+
class FixtureSet
|
398
|
+
#--
|
399
|
+
# An instance of FixtureSet is normally stored in a single YAML file and
|
400
|
+
# possibly in a folder with the same name.
|
401
|
+
#++
|
402
|
+
|
391
403
|
MAX_ID = 2 ** 30 - 1
|
392
404
|
|
393
405
|
@@all_cached_fixtures = Hash.new { |h,k| h[k] = {} }
|
394
406
|
|
395
|
-
def self.
|
396
|
-
|
397
|
-
|
398
|
-
|
407
|
+
def self.default_fixture_model_name(fixture_set_name, config = ActiveRecord::Base) # :nodoc:
|
408
|
+
config.pluralize_table_names ?
|
409
|
+
fixture_set_name.singularize.camelize :
|
410
|
+
fixture_set_name.camelize
|
411
|
+
end
|
412
|
+
|
413
|
+
def self.default_fixture_table_name(fixture_set_name, config = ActiveRecord::Base) # :nodoc:
|
414
|
+
"#{ config.table_name_prefix }"\
|
415
|
+
"#{ fixture_set_name.tr('/', '_') }"\
|
416
|
+
"#{ config.table_name_suffix }".to_sym
|
399
417
|
end
|
400
418
|
|
401
419
|
def self.reset_cache
|
@@ -422,11 +440,11 @@ module ActiveRecord
|
|
422
440
|
cache_for_connection(connection).update(fixtures_map)
|
423
441
|
end
|
424
442
|
|
425
|
-
def self.instantiate_fixtures(object,
|
443
|
+
def self.instantiate_fixtures(object, fixture_set, load_instances = true)
|
426
444
|
if load_instances
|
427
|
-
|
445
|
+
fixture_set.each do |fixture_name, fixture|
|
428
446
|
begin
|
429
|
-
object.instance_variable_set "@#{
|
447
|
+
object.instance_variable_set "@#{fixture_name}", fixture.find
|
430
448
|
rescue FixtureClassNotFound
|
431
449
|
nil
|
432
450
|
end
|
@@ -435,63 +453,91 @@ module ActiveRecord
|
|
435
453
|
end
|
436
454
|
|
437
455
|
def self.instantiate_all_loaded_fixtures(object, load_instances = true)
|
438
|
-
all_loaded_fixtures.
|
439
|
-
|
456
|
+
all_loaded_fixtures.each_value do |fixture_set|
|
457
|
+
instantiate_fixtures(object, fixture_set, load_instances)
|
440
458
|
end
|
441
459
|
end
|
442
460
|
|
443
461
|
cattr_accessor :all_loaded_fixtures
|
444
462
|
self.all_loaded_fixtures = {}
|
445
463
|
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
464
|
+
class ClassCache
|
465
|
+
def initialize(class_names, config)
|
466
|
+
@class_names = class_names.stringify_keys
|
467
|
+
@config = config
|
468
|
+
|
469
|
+
# Remove string values that aren't constants or subclasses of AR
|
470
|
+
@class_names.delete_if { |klass_name, klass| !insert_class(@class_names, klass_name, klass) }
|
471
|
+
end
|
472
|
+
|
473
|
+
def [](fs_name)
|
474
|
+
@class_names.fetch(fs_name) {
|
475
|
+
klass = default_fixture_model(fs_name, @config).safe_constantize
|
476
|
+
insert_class(@class_names, fs_name, klass)
|
477
|
+
}
|
478
|
+
end
|
479
|
+
|
480
|
+
private
|
481
|
+
|
482
|
+
def insert_class(class_names, name, klass)
|
483
|
+
# We only want to deal with AR objects.
|
484
|
+
if klass && klass < ActiveRecord::Base
|
485
|
+
class_names[name] = klass
|
486
|
+
else
|
487
|
+
class_names[name] = nil
|
488
|
+
end
|
489
|
+
end
|
490
|
+
|
491
|
+
def default_fixture_model(fs_name, config)
|
492
|
+
ActiveRecord::FixtureSet.default_fixture_model_name(fs_name, config)
|
493
|
+
end
|
494
|
+
end
|
495
|
+
|
496
|
+
def self.create_fixtures(fixtures_directory, fixture_set_names, class_names = {}, config = ActiveRecord::Base)
|
497
|
+
fixture_set_names = Array(fixture_set_names).map(&:to_s)
|
498
|
+
class_names = ClassCache.new class_names, config
|
451
499
|
|
452
500
|
# FIXME: Apparently JK uses this.
|
453
501
|
connection = block_given? ? yield : ActiveRecord::Base.connection
|
454
502
|
|
455
|
-
files_to_read =
|
456
|
-
fixture_is_cached?(connection,
|
503
|
+
files_to_read = fixture_set_names.reject { |fs_name|
|
504
|
+
fixture_is_cached?(connection, fs_name)
|
457
505
|
}
|
458
506
|
|
459
507
|
unless files_to_read.empty?
|
460
508
|
connection.disable_referential_integrity do
|
461
509
|
fixtures_map = {}
|
462
510
|
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
fixtures_map[
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
File.join(fixtures_directory,
|
511
|
+
fixture_sets = files_to_read.map do |fs_name|
|
512
|
+
klass = class_names[fs_name]
|
513
|
+
conn = klass ? klass.connection : connection
|
514
|
+
fixtures_map[fs_name] = new( # ActiveRecord::FixtureSet.new
|
515
|
+
conn,
|
516
|
+
fs_name,
|
517
|
+
klass,
|
518
|
+
::File.join(fixtures_directory, fs_name))
|
471
519
|
end
|
472
520
|
|
473
|
-
|
521
|
+
update_all_loaded_fixtures fixtures_map
|
474
522
|
|
475
523
|
connection.transaction(:requires_new => true) do
|
476
|
-
|
477
|
-
conn =
|
478
|
-
table_rows =
|
524
|
+
fixture_sets.each do |fs|
|
525
|
+
conn = fs.model_class.respond_to?(:connection) ? fs.model_class.connection : connection
|
526
|
+
table_rows = fs.table_rows
|
479
527
|
|
480
|
-
table_rows.
|
528
|
+
table_rows.each_key do |table|
|
481
529
|
conn.delete "DELETE FROM #{conn.quote_table_name(table)}", 'Fixture Delete'
|
482
530
|
end
|
483
531
|
|
484
|
-
table_rows.each do |
|
532
|
+
table_rows.each do |fixture_set_name, rows|
|
485
533
|
rows.each do |row|
|
486
|
-
conn.insert_fixture(row,
|
534
|
+
conn.insert_fixture(row, fixture_set_name)
|
487
535
|
end
|
488
536
|
end
|
489
|
-
end
|
490
537
|
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
connection.reset_pk_sequence!(table_name.tr('/', '_'))
|
538
|
+
# Cap primary key sequences to max(pk).
|
539
|
+
if conn.respond_to?(:reset_pk_sequence!)
|
540
|
+
conn.reset_pk_sequence!(fs.table_name)
|
495
541
|
end
|
496
542
|
end
|
497
543
|
end
|
@@ -499,37 +545,49 @@ module ActiveRecord
|
|
499
545
|
cache_fixtures(connection, fixtures_map)
|
500
546
|
end
|
501
547
|
end
|
502
|
-
cached_fixtures(connection,
|
548
|
+
cached_fixtures(connection, fixture_set_names)
|
503
549
|
end
|
504
550
|
|
505
551
|
# Returns a consistent, platform-independent identifier for +label+.
|
506
|
-
#
|
507
|
-
def self.identify(label)
|
508
|
-
|
552
|
+
# Integer identifiers are values less than 2^30. UUIDs are RFC 4122 version 5 SHA-1 hashes.
|
553
|
+
def self.identify(label, column_type = :integer)
|
554
|
+
if column_type == :uuid
|
555
|
+
Digest::UUID.uuid_v5(Digest::UUID::OID_NAMESPACE, label.to_s)
|
556
|
+
else
|
557
|
+
Zlib.crc32(label.to_s) % MAX_ID
|
558
|
+
end
|
509
559
|
end
|
510
560
|
|
511
|
-
|
561
|
+
# Superclass for the evaluation contexts used by ERB fixtures.
|
562
|
+
def self.context_class
|
563
|
+
@context_class ||= Class.new
|
564
|
+
end
|
512
565
|
|
513
|
-
def
|
514
|
-
|
515
|
-
|
516
|
-
@fixture_path = fixture_path
|
517
|
-
@name = table_name # preserve fixture base name
|
518
|
-
@class_name = class_name
|
566
|
+
def self.update_all_loaded_fixtures(fixtures_map) # :nodoc:
|
567
|
+
all_loaded_fixtures.update(fixtures_map)
|
568
|
+
end
|
519
569
|
|
520
|
-
|
521
|
-
@table_name = "#{ActiveRecord::Base.table_name_prefix}#{@table_name}#{ActiveRecord::Base.table_name_suffix}"
|
570
|
+
attr_reader :table_name, :name, :fixtures, :model_class, :config
|
522
571
|
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
572
|
+
def initialize(connection, name, class_name, path, config = ActiveRecord::Base)
|
573
|
+
@name = name
|
574
|
+
@path = path
|
575
|
+
@config = config
|
576
|
+
@model_class = nil
|
577
|
+
|
578
|
+
if class_name.is_a?(Class) # TODO: Should be an AR::Base type class, or any?
|
579
|
+
@model_class = class_name
|
528
580
|
else
|
529
|
-
@model_class
|
581
|
+
@model_class = class_name.safe_constantize if class_name
|
530
582
|
end
|
531
583
|
|
532
|
-
|
584
|
+
@connection = connection
|
585
|
+
|
586
|
+
@table_name = ( model_class.respond_to?(:table_name) ?
|
587
|
+
model_class.table_name :
|
588
|
+
self.class.default_fixture_table_name(name, config) )
|
589
|
+
|
590
|
+
@fixtures = read_fixture_files path, @model_class
|
533
591
|
end
|
534
592
|
|
535
593
|
def [](x)
|
@@ -548,10 +606,10 @@ module ActiveRecord
|
|
548
606
|
fixtures.size
|
549
607
|
end
|
550
608
|
|
551
|
-
#
|
609
|
+
# Returns a hash of rows to be inserted. The key is the table, the value is
|
552
610
|
# a list of rows to insert to that table.
|
553
611
|
def table_rows
|
554
|
-
now =
|
612
|
+
now = config.default_timezone == :utc ? Time.now.utc : Time.now
|
555
613
|
now = now.to_s(:db)
|
556
614
|
|
557
615
|
# allow a standard key to be used for doing defaults in YAML
|
@@ -563,22 +621,22 @@ module ActiveRecord
|
|
563
621
|
rows[table_name] = fixtures.map do |label, fixture|
|
564
622
|
row = fixture.to_hash
|
565
623
|
|
566
|
-
if model_class
|
624
|
+
if model_class
|
567
625
|
# fill in timestamp columns if they aren't specified and the model is set to record_timestamps
|
568
626
|
if model_class.record_timestamps
|
569
|
-
timestamp_column_names.each do |
|
570
|
-
row[
|
627
|
+
timestamp_column_names.each do |c_name|
|
628
|
+
row[c_name] = now unless row.key?(c_name)
|
571
629
|
end
|
572
630
|
end
|
573
631
|
|
574
632
|
# interpolate the fixture label
|
575
633
|
row.each do |key, value|
|
576
|
-
row[key] = label if value
|
634
|
+
row[key] = value.gsub("$LABEL", label.to_s) if value.is_a?(String)
|
577
635
|
end
|
578
636
|
|
579
637
|
# generate a primary key if necessary
|
580
638
|
if has_primary_key_column? && !row.include?(primary_key_name)
|
581
|
-
row[primary_key_name] = ActiveRecord::
|
639
|
+
row[primary_key_name] = ActiveRecord::FixtureSet.identify(label, primary_key_type)
|
582
640
|
end
|
583
641
|
|
584
642
|
# If STI is used, find the correct subclass for association reflection
|
@@ -589,28 +647,24 @@ module ActiveRecord
|
|
589
647
|
model_class
|
590
648
|
end
|
591
649
|
|
592
|
-
reflection_class.
|
650
|
+
reflection_class._reflections.each_value do |association|
|
593
651
|
case association.macro
|
594
652
|
when :belongs_to
|
595
653
|
# Do not replace association name with association foreign key if they are named the same
|
596
654
|
fk_name = (association.options[:foreign_key] || "#{association.name}_id").to_s
|
597
655
|
|
598
656
|
if association.name.to_s != fk_name && value = row.delete(association.name.to_s)
|
599
|
-
if association.
|
657
|
+
if association.polymorphic? && value.sub!(/\s*\(([^\)]*)\)\s*$/, "")
|
600
658
|
# support polymorphic belongs_to as "label (Type)"
|
601
659
|
row[association.foreign_type] = $1
|
602
660
|
end
|
603
661
|
|
604
|
-
|
662
|
+
fk_type = reflection_class.columns_hash[fk_name].type
|
663
|
+
row[fk_name] = ActiveRecord::FixtureSet.identify(value, fk_type)
|
605
664
|
end
|
606
|
-
when :
|
607
|
-
if
|
608
|
-
|
609
|
-
table_name = association.options[:join_table]
|
610
|
-
rows[table_name].concat targets.map { |target|
|
611
|
-
{ association.foreign_key => row[primary_key_name],
|
612
|
-
association.association_foreign_key => ActiveRecord::Fixtures.identify(target) }
|
613
|
-
}
|
665
|
+
when :has_many
|
666
|
+
if association.options[:through]
|
667
|
+
add_join_records(rows, row, HasManyThroughProxy.new(association))
|
614
668
|
end
|
615
669
|
end
|
616
670
|
end
|
@@ -621,107 +675,107 @@ module ActiveRecord
|
|
621
675
|
rows
|
622
676
|
end
|
623
677
|
|
624
|
-
|
625
|
-
def
|
626
|
-
@
|
678
|
+
class ReflectionProxy # :nodoc:
|
679
|
+
def initialize(association)
|
680
|
+
@association = association
|
627
681
|
end
|
628
682
|
|
629
|
-
def
|
630
|
-
@
|
631
|
-
model_class.columns.any? { |c| c.name == primary_key_name }
|
683
|
+
def join_table
|
684
|
+
@association.join_table
|
632
685
|
end
|
633
686
|
|
634
|
-
def
|
635
|
-
@
|
636
|
-
%w(created_at created_on updated_at updated_on) & column_names
|
687
|
+
def name
|
688
|
+
@association.name
|
637
689
|
end
|
638
690
|
|
639
|
-
def
|
640
|
-
@
|
691
|
+
def primary_key_type
|
692
|
+
@association.klass.column_types[@association.klass.primary_key].type
|
641
693
|
end
|
694
|
+
end
|
642
695
|
|
643
|
-
|
644
|
-
|
696
|
+
class HasManyThroughProxy < ReflectionProxy # :nodoc:
|
697
|
+
def rhs_key
|
698
|
+
@association.foreign_key
|
645
699
|
end
|
646
700
|
|
647
|
-
def
|
648
|
-
|
649
|
-
read_yaml_fixture_files
|
650
|
-
elsif File.file?(csv_file_path)
|
651
|
-
read_csv_fixture_files
|
652
|
-
else
|
653
|
-
raise FixturesFileNotFound, "Could not find #{yaml_file_path} or #{csv_file_path}"
|
654
|
-
end
|
701
|
+
def lhs_key
|
702
|
+
@association.through_reflection.foreign_key
|
655
703
|
end
|
656
704
|
|
657
|
-
def
|
658
|
-
|
659
|
-
|
660
|
-
|
705
|
+
def join_table
|
706
|
+
@association.through_reflection.table_name
|
707
|
+
end
|
708
|
+
end
|
661
709
|
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
yaml.value
|
667
|
-
else
|
668
|
-
[yaml]
|
669
|
-
end
|
710
|
+
private
|
711
|
+
def primary_key_name
|
712
|
+
@primary_key_name ||= model_class && model_class.primary_key
|
713
|
+
end
|
670
714
|
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
unless data
|
675
|
-
raise Fixture::FormatError, "Bad data for #{@class_name} fixture named #{name} (nil)"
|
676
|
-
end
|
715
|
+
def primary_key_type
|
716
|
+
@primary_key_type ||= model_class && model_class.column_types[model_class.primary_key].type
|
717
|
+
end
|
677
718
|
|
678
|
-
|
679
|
-
|
680
|
-
|
719
|
+
def add_join_records(rows, row, association)
|
720
|
+
# This is the case when the join table has no fixtures file
|
721
|
+
if (targets = row.delete(association.name.to_s))
|
722
|
+
table_name = association.join_table
|
723
|
+
column_type = association.primary_key_type
|
724
|
+
lhs_key = association.lhs_key
|
725
|
+
rhs_key = association.rhs_key
|
726
|
+
|
727
|
+
targets = targets.is_a?(Array) ? targets : targets.split(/\s*,\s*/)
|
728
|
+
rows[table_name].concat targets.map { |target|
|
729
|
+
{ lhs_key => row[primary_key_name],
|
730
|
+
rhs_key => ActiveRecord::FixtureSet.identify(target, column_type) }
|
731
|
+
}
|
681
732
|
end
|
682
733
|
end
|
683
734
|
|
684
|
-
def
|
685
|
-
|
686
|
-
|
687
|
-
i = 0
|
688
|
-
reader.each do |row|
|
689
|
-
data = {}
|
690
|
-
row.each_with_index { |cell, j| data[header[j].to_s.strip] = cell.to_s.strip }
|
691
|
-
fixtures["#{@class_name.to_s.underscore}_#{i+=1}"] = ActiveRecord::Fixture.new(data, model_class)
|
692
|
-
end
|
735
|
+
def has_primary_key_column?
|
736
|
+
@has_primary_key_column ||= primary_key_name &&
|
737
|
+
model_class.columns.any? { |c| c.name == primary_key_name }
|
693
738
|
end
|
694
|
-
deprecate :read_csv_fixture_files
|
695
739
|
|
696
|
-
def
|
697
|
-
|
740
|
+
def timestamp_column_names
|
741
|
+
@timestamp_column_names ||=
|
742
|
+
%w(created_at created_on updated_at updated_on) & column_names
|
698
743
|
end
|
699
744
|
|
700
|
-
def
|
701
|
-
@
|
745
|
+
def inheritance_column_name
|
746
|
+
@inheritance_column_name ||= model_class && model_class.inheritance_column
|
702
747
|
end
|
703
748
|
|
704
|
-
def
|
705
|
-
|
749
|
+
def column_names
|
750
|
+
@column_names ||= @connection.columns(@table_name).collect { |c| c.name }
|
706
751
|
end
|
707
752
|
|
708
|
-
|
753
|
+
def read_fixture_files(path, model_class)
|
754
|
+
yaml_files = Dir["#{path}/{**,*}/*.yml"].select { |f|
|
755
|
+
::File.file?(f)
|
756
|
+
} + [yaml_file_path(path)]
|
709
757
|
|
710
|
-
|
711
|
-
|
758
|
+
yaml_files.each_with_object({}) do |file, fixtures|
|
759
|
+
FixtureSet::File.open(file) do |fh|
|
760
|
+
fh.each do |fixture_name, row|
|
761
|
+
fixtures[fixture_name] = ActiveRecord::Fixture.new(row, model_class)
|
762
|
+
end
|
763
|
+
end
|
764
|
+
end
|
712
765
|
end
|
713
766
|
|
714
|
-
def
|
715
|
-
|
716
|
-
rescue *RESCUE_ERRORS => error
|
717
|
-
raise Fixture::FormatError, "a YAML error occurred parsing #{yaml_file_path}. Please note that YAML must be consistently indented using spaces. Tabs are not allowed. Please have a look at http://www.yaml.org/faq.html\nThe exact error was:\n #{error.class}: #{error}", error.backtrace
|
767
|
+
def yaml_file_path(path)
|
768
|
+
"#{path}.yml"
|
718
769
|
end
|
719
770
|
|
720
|
-
def erb_render(fixture_content)
|
721
|
-
ERB.new(fixture_content).result
|
722
|
-
end
|
723
771
|
end
|
724
772
|
|
773
|
+
#--
|
774
|
+
# Deprecate 'Fixtures' in favor of 'FixtureSet'.
|
775
|
+
#++
|
776
|
+
# :nodoc:
|
777
|
+
Fixtures = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('ActiveRecord::Fixtures', 'ActiveRecord::FixtureSet')
|
778
|
+
|
725
779
|
class Fixture #:nodoc:
|
726
780
|
include Enumerable
|
727
781
|
|
@@ -754,7 +808,9 @@ module ActiveRecord
|
|
754
808
|
|
755
809
|
def find
|
756
810
|
if model_class
|
757
|
-
model_class.
|
811
|
+
model_class.unscoped do
|
812
|
+
model_class.find(fixture[model_class.primary_key])
|
813
|
+
end
|
758
814
|
else
|
759
815
|
raise FixtureClassNotFound, "No class attached to find."
|
760
816
|
end
|
@@ -766,91 +822,87 @@ module ActiveRecord
|
|
766
822
|
module TestFixtures
|
767
823
|
extend ActiveSupport::Concern
|
768
824
|
|
769
|
-
|
770
|
-
|
771
|
-
|
825
|
+
def before_setup
|
826
|
+
setup_fixtures
|
827
|
+
super
|
828
|
+
end
|
829
|
+
|
830
|
+
def after_teardown
|
831
|
+
super
|
832
|
+
teardown_fixtures
|
833
|
+
end
|
772
834
|
|
773
|
-
|
835
|
+
included do
|
836
|
+
class_attribute :fixture_path, :instance_writer => false
|
774
837
|
class_attribute :fixture_table_names
|
775
838
|
class_attribute :fixture_class_names
|
776
839
|
class_attribute :use_transactional_fixtures
|
777
|
-
class_attribute :use_instantiated_fixtures
|
840
|
+
class_attribute :use_instantiated_fixtures # true, false, or :no_instances
|
778
841
|
class_attribute :pre_loaded_fixtures
|
842
|
+
class_attribute :config
|
779
843
|
|
780
844
|
self.fixture_table_names = []
|
781
845
|
self.use_transactional_fixtures = true
|
782
846
|
self.use_instantiated_fixtures = false
|
783
847
|
self.pre_loaded_fixtures = false
|
848
|
+
self.config = ActiveRecord::Base
|
784
849
|
|
785
|
-
self.fixture_class_names = Hash.new do |h,
|
786
|
-
h[
|
850
|
+
self.fixture_class_names = Hash.new do |h, fixture_set_name|
|
851
|
+
h[fixture_set_name] = ActiveRecord::FixtureSet.default_fixture_model_name(fixture_set_name, self.config)
|
787
852
|
end
|
788
853
|
end
|
789
854
|
|
790
855
|
module ClassMethods
|
856
|
+
# Sets the model class for a fixture when the class name cannot be inferred from the fixture name.
|
857
|
+
#
|
858
|
+
# Examples:
|
859
|
+
#
|
860
|
+
# set_fixture_class some_fixture: SomeModel,
|
861
|
+
# 'namespaced/fixture' => Another::Model
|
862
|
+
#
|
863
|
+
# The keys must be the fixture names, that coincide with the short paths to the fixture files.
|
791
864
|
def set_fixture_class(class_names = {})
|
792
|
-
self.fixture_class_names = self.fixture_class_names.merge(class_names)
|
865
|
+
self.fixture_class_names = self.fixture_class_names.merge(class_names.stringify_keys)
|
793
866
|
end
|
794
867
|
|
795
|
-
def fixtures(*
|
796
|
-
if
|
797
|
-
|
798
|
-
|
868
|
+
def fixtures(*fixture_set_names)
|
869
|
+
if fixture_set_names.first == :all
|
870
|
+
fixture_set_names = Dir["#{fixture_path}/{**,*}/*.{yml}"]
|
871
|
+
fixture_set_names.map! { |f| f[(fixture_path.to_s.size + 1)..-5] }
|
799
872
|
else
|
800
|
-
|
873
|
+
fixture_set_names = fixture_set_names.flatten.map { |n| n.to_s }
|
801
874
|
end
|
802
875
|
|
803
|
-
self.fixture_table_names |=
|
804
|
-
|
805
|
-
setup_fixture_accessors(fixture_names)
|
806
|
-
end
|
807
|
-
|
808
|
-
def try_to_load_dependency(file_name)
|
809
|
-
require_dependency file_name
|
810
|
-
rescue LoadError => e
|
811
|
-
# Let's hope the developer has included it himself
|
812
|
-
|
813
|
-
# Let's warn in case this is a subdependency, otherwise
|
814
|
-
# subdependency error messages are totally cryptic
|
815
|
-
if ActiveRecord::Base.logger
|
816
|
-
ActiveRecord::Base.logger.warn("Unable to load #{file_name}, underlying cause #{e.message} \n\n #{e.backtrace.join("\n")}")
|
817
|
-
end
|
876
|
+
self.fixture_table_names |= fixture_set_names
|
877
|
+
setup_fixture_accessors(fixture_set_names)
|
818
878
|
end
|
819
879
|
|
820
|
-
def
|
821
|
-
(
|
822
|
-
file_name = fixture_name.to_s
|
823
|
-
file_name = file_name.singularize if ActiveRecord::Base.pluralize_table_names
|
824
|
-
try_to_load_dependency(file_name)
|
825
|
-
end
|
826
|
-
end
|
827
|
-
|
828
|
-
def setup_fixture_accessors(fixture_names = nil)
|
829
|
-
fixture_names = Array.wrap(fixture_names || fixture_table_names)
|
880
|
+
def setup_fixture_accessors(fixture_set_names = nil)
|
881
|
+
fixture_set_names = Array(fixture_set_names || fixture_table_names)
|
830
882
|
methods = Module.new do
|
831
|
-
|
832
|
-
|
883
|
+
fixture_set_names.each do |fs_name|
|
884
|
+
fs_name = fs_name.to_s
|
885
|
+
accessor_name = fs_name.tr('/', '_').to_sym
|
833
886
|
|
834
|
-
define_method(
|
835
|
-
force_reload =
|
887
|
+
define_method(accessor_name) do |*fixture_names|
|
888
|
+
force_reload = fixture_names.pop if fixture_names.last == true || fixture_names.last == :reload
|
836
889
|
|
837
|
-
@fixture_cache[
|
890
|
+
@fixture_cache[fs_name] ||= {}
|
838
891
|
|
839
|
-
instances =
|
840
|
-
|
892
|
+
instances = fixture_names.map do |f_name|
|
893
|
+
f_name = f_name.to_s
|
894
|
+
@fixture_cache[fs_name].delete(f_name) if force_reload
|
841
895
|
|
842
|
-
if @loaded_fixtures[
|
843
|
-
|
844
|
-
@fixture_cache[fixture_name][fixture] ||= @loaded_fixtures[fixture_name][fixture.to_s].find
|
845
|
-
end
|
896
|
+
if @loaded_fixtures[fs_name][f_name]
|
897
|
+
@fixture_cache[fs_name][f_name] ||= @loaded_fixtures[fs_name][f_name].find
|
846
898
|
else
|
847
|
-
raise StandardError, "No fixture
|
899
|
+
raise StandardError, "No fixture named '#{f_name}' found for fixture set '#{fs_name}'"
|
848
900
|
end
|
849
901
|
end
|
850
902
|
|
851
903
|
instances.size == 1 ? instances.first : instances
|
852
904
|
end
|
853
|
-
private
|
905
|
+
private accessor_name
|
854
906
|
end
|
855
907
|
end
|
856
908
|
include methods
|
@@ -872,14 +924,13 @@ module ActiveRecord
|
|
872
924
|
!self.class.uses_transaction?(method_name)
|
873
925
|
end
|
874
926
|
|
875
|
-
def setup_fixtures
|
876
|
-
return unless !ActiveRecord::Base.configurations.blank?
|
877
|
-
|
927
|
+
def setup_fixtures(config = ActiveRecord::Base)
|
878
928
|
if pre_loaded_fixtures && !use_transactional_fixtures
|
879
929
|
raise RuntimeError, 'pre_loaded_fixtures requires use_transactional_fixtures'
|
880
930
|
end
|
881
931
|
|
882
932
|
@fixture_cache = {}
|
933
|
+
@fixture_connections = []
|
883
934
|
@@already_loaded_fixtures ||= {}
|
884
935
|
|
885
936
|
# Load fixtures once and begin transaction.
|
@@ -887,17 +938,18 @@ module ActiveRecord
|
|
887
938
|
if @@already_loaded_fixtures[self.class]
|
888
939
|
@loaded_fixtures = @@already_loaded_fixtures[self.class]
|
889
940
|
else
|
890
|
-
@loaded_fixtures = load_fixtures
|
941
|
+
@loaded_fixtures = load_fixtures(config)
|
891
942
|
@@already_loaded_fixtures[self.class] = @loaded_fixtures
|
892
943
|
end
|
893
|
-
|
894
|
-
|
895
|
-
|
944
|
+
@fixture_connections = enlist_fixture_connections
|
945
|
+
@fixture_connections.each do |connection|
|
946
|
+
connection.begin_transaction joinable: false
|
947
|
+
end
|
896
948
|
# Load fixtures for every test.
|
897
949
|
else
|
898
|
-
ActiveRecord::
|
950
|
+
ActiveRecord::FixtureSet.reset_cache
|
899
951
|
@@already_loaded_fixtures[self.class] = nil
|
900
|
-
@loaded_fixtures = load_fixtures
|
952
|
+
@loaded_fixtures = load_fixtures(config)
|
901
953
|
end
|
902
954
|
|
903
955
|
# Instantiate fixtures for every test if requested.
|
@@ -905,41 +957,37 @@ module ActiveRecord
|
|
905
957
|
end
|
906
958
|
|
907
959
|
def teardown_fixtures
|
908
|
-
return unless defined?(ActiveRecord) && !ActiveRecord::Base.configurations.blank?
|
909
|
-
|
910
|
-
unless run_in_transaction?
|
911
|
-
ActiveRecord::Fixtures.reset_cache
|
912
|
-
end
|
913
|
-
|
914
960
|
# Rollback changes if a transaction is active.
|
915
|
-
if run_in_transaction?
|
916
|
-
|
917
|
-
|
961
|
+
if run_in_transaction?
|
962
|
+
@fixture_connections.each do |connection|
|
963
|
+
connection.rollback_transaction if connection.transaction_open?
|
964
|
+
end
|
965
|
+
@fixture_connections.clear
|
966
|
+
else
|
967
|
+
ActiveRecord::FixtureSet.reset_cache
|
918
968
|
end
|
969
|
+
|
919
970
|
ActiveRecord::Base.clear_active_connections!
|
920
971
|
end
|
921
972
|
|
973
|
+
def enlist_fixture_connections
|
974
|
+
ActiveRecord::Base.connection_handler.connection_pool_list.map(&:connection)
|
975
|
+
end
|
976
|
+
|
922
977
|
private
|
923
|
-
def load_fixtures
|
924
|
-
fixtures = ActiveRecord::
|
978
|
+
def load_fixtures(config)
|
979
|
+
fixtures = ActiveRecord::FixtureSet.create_fixtures(fixture_path, fixture_table_names, fixture_class_names, config)
|
925
980
|
Hash[fixtures.map { |f| [f.name, f] }]
|
926
981
|
end
|
927
982
|
|
928
|
-
# for pre_loaded_fixtures, only require the classes once. huge speed improvement
|
929
|
-
@@required_fixture_classes = false
|
930
|
-
|
931
983
|
def instantiate_fixtures
|
932
984
|
if pre_loaded_fixtures
|
933
|
-
raise RuntimeError, 'Load fixtures before instantiating them.' if ActiveRecord::
|
934
|
-
|
935
|
-
self.class.require_fixture_classes ActiveRecord::Fixtures.all_loaded_fixtures.keys
|
936
|
-
@@required_fixture_classes = true
|
937
|
-
end
|
938
|
-
ActiveRecord::Fixtures.instantiate_all_loaded_fixtures(self, load_instances?)
|
985
|
+
raise RuntimeError, 'Load fixtures before instantiating them.' if ActiveRecord::FixtureSet.all_loaded_fixtures.empty?
|
986
|
+
ActiveRecord::FixtureSet.instantiate_all_loaded_fixtures(self, load_instances?)
|
939
987
|
else
|
940
988
|
raise RuntimeError, 'Load fixtures before instantiating them.' if @loaded_fixtures.nil?
|
941
|
-
@loaded_fixtures.
|
942
|
-
ActiveRecord::
|
989
|
+
@loaded_fixtures.each_value do |fixture_set|
|
990
|
+
ActiveRecord::FixtureSet.instantiate_fixtures(self, fixture_set, load_instances?)
|
943
991
|
end
|
944
992
|
end
|
945
993
|
end
|
@@ -949,3 +997,13 @@ module ActiveRecord
|
|
949
997
|
end
|
950
998
|
end
|
951
999
|
end
|
1000
|
+
|
1001
|
+
class ActiveRecord::FixtureSet::RenderContext # :nodoc:
|
1002
|
+
def self.create_subclass
|
1003
|
+
Class.new ActiveRecord::FixtureSet.context_class do
|
1004
|
+
def get_binding
|
1005
|
+
binding()
|
1006
|
+
end
|
1007
|
+
end
|
1008
|
+
end
|
1009
|
+
end
|