activerecord 2.2.3 → 2.3.2

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.

Files changed (120) hide show
  1. data/CHANGELOG +438 -396
  2. data/Rakefile +4 -2
  3. data/lib/active_record.rb +46 -43
  4. data/lib/active_record/association_preload.rb +34 -19
  5. data/lib/active_record/associations.rb +193 -251
  6. data/lib/active_record/associations/association_collection.rb +38 -21
  7. data/lib/active_record/associations/association_proxy.rb +11 -4
  8. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +2 -2
  9. data/lib/active_record/associations/has_many_association.rb +2 -2
  10. data/lib/active_record/associations/has_many_through_association.rb +8 -8
  11. data/lib/active_record/associations/has_one_association.rb +11 -2
  12. data/lib/active_record/attribute_methods.rb +1 -0
  13. data/lib/active_record/autosave_association.rb +349 -0
  14. data/lib/active_record/base.rb +292 -106
  15. data/lib/active_record/batches.rb +73 -0
  16. data/lib/active_record/calculations.rb +34 -16
  17. data/lib/active_record/callbacks.rb +37 -8
  18. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +16 -0
  19. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +3 -0
  20. data/lib/active_record/connection_adapters/abstract/database_statements.rb +103 -15
  21. data/lib/active_record/connection_adapters/abstract/query_cache.rb +6 -6
  22. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +28 -25
  23. data/lib/active_record/connection_adapters/abstract_adapter.rb +29 -5
  24. data/lib/active_record/connection_adapters/mysql_adapter.rb +50 -21
  25. data/lib/active_record/connection_adapters/postgresql_adapter.rb +26 -41
  26. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +1 -1
  27. data/lib/active_record/connection_adapters/sqlite_adapter.rb +41 -21
  28. data/lib/active_record/dirty.rb +1 -1
  29. data/lib/active_record/dynamic_scope_match.rb +25 -0
  30. data/lib/active_record/fixtures.rb +193 -198
  31. data/lib/active_record/locale/en.yml +1 -1
  32. data/lib/active_record/locking/optimistic.rb +33 -0
  33. data/lib/active_record/migration.rb +8 -2
  34. data/lib/active_record/named_scope.rb +13 -6
  35. data/lib/active_record/nested_attributes.rb +329 -0
  36. data/lib/active_record/query_cache.rb +25 -13
  37. data/lib/active_record/reflection.rb +6 -1
  38. data/lib/active_record/schema_dumper.rb +2 -0
  39. data/lib/active_record/serialization.rb +3 -1
  40. data/lib/active_record/serializers/json_serializer.rb +19 -0
  41. data/lib/active_record/serializers/xml_serializer.rb +28 -13
  42. data/lib/active_record/session_store.rb +318 -0
  43. data/lib/active_record/test_case.rb +15 -9
  44. data/lib/active_record/timestamp.rb +2 -2
  45. data/lib/active_record/transactions.rb +58 -8
  46. data/lib/active_record/validations.rb +29 -24
  47. data/lib/active_record/version.rb +2 -2
  48. data/test/cases/ar_schema_test.rb +0 -1
  49. data/test/cases/associations/belongs_to_associations_test.rb +35 -131
  50. data/test/cases/associations/cascaded_eager_loading_test.rb +8 -0
  51. data/test/cases/associations/eager_load_nested_include_test.rb +29 -0
  52. data/test/cases/associations/eager_test.rb +137 -7
  53. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +45 -7
  54. data/test/cases/associations/has_many_associations_test.rb +110 -149
  55. data/test/cases/associations/has_many_through_associations_test.rb +39 -7
  56. data/test/cases/associations/has_one_associations_test.rb +39 -92
  57. data/test/cases/associations/has_one_through_associations_test.rb +34 -3
  58. data/test/cases/associations/inner_join_association_test.rb +0 -5
  59. data/test/cases/associations/join_model_test.rb +5 -7
  60. data/test/cases/attribute_methods_test.rb +13 -1
  61. data/test/cases/autosave_association_test.rb +901 -0
  62. data/test/cases/base_test.rb +41 -21
  63. data/test/cases/batches_test.rb +61 -0
  64. data/test/cases/calculations_test.rb +37 -17
  65. data/test/cases/callbacks_test.rb +43 -5
  66. data/test/cases/connection_pool_test.rb +25 -0
  67. data/test/cases/copy_table_test_sqlite.rb +11 -0
  68. data/test/cases/datatype_test_postgresql.rb +1 -0
  69. data/test/cases/defaults_test.rb +37 -26
  70. data/test/cases/dirty_test.rb +26 -2
  71. data/test/cases/finder_test.rb +79 -44
  72. data/test/cases/fixtures_test.rb +15 -19
  73. data/test/cases/helper.rb +26 -19
  74. data/test/cases/inheritance_test.rb +2 -2
  75. data/test/cases/json_serialization_test.rb +1 -1
  76. data/test/cases/locking_test.rb +23 -5
  77. data/test/cases/method_scoping_test.rb +126 -3
  78. data/test/cases/migration_test.rb +253 -237
  79. data/test/cases/named_scope_test.rb +73 -3
  80. data/test/cases/nested_attributes_test.rb +509 -0
  81. data/test/cases/query_cache_test.rb +0 -4
  82. data/test/cases/reflection_test.rb +13 -3
  83. data/test/cases/reload_models_test.rb +3 -1
  84. data/test/cases/repair_helper.rb +50 -0
  85. data/test/cases/schema_dumper_test.rb +0 -1
  86. data/test/cases/transactions_test.rb +177 -12
  87. data/test/cases/validations_i18n_test.rb +288 -294
  88. data/test/cases/validations_test.rb +230 -180
  89. data/test/cases/xml_serialization_test.rb +19 -1
  90. data/test/fixtures/fixture_database.sqlite3 +0 -0
  91. data/test/fixtures/fixture_database_2.sqlite3 +0 -0
  92. data/test/fixtures/member_types.yml +6 -0
  93. data/test/fixtures/members.yml +3 -1
  94. data/test/fixtures/people.yml +10 -1
  95. data/test/fixtures/toys.yml +4 -0
  96. data/test/models/author.rb +1 -2
  97. data/test/models/bird.rb +3 -0
  98. data/test/models/category.rb +1 -0
  99. data/test/models/company.rb +3 -0
  100. data/test/models/developer.rb +12 -0
  101. data/test/models/event.rb +3 -0
  102. data/test/models/member.rb +1 -0
  103. data/test/models/member_detail.rb +1 -0
  104. data/test/models/member_type.rb +3 -0
  105. data/test/models/owner.rb +2 -1
  106. data/test/models/parrot.rb +2 -0
  107. data/test/models/person.rb +6 -0
  108. data/test/models/pet.rb +2 -1
  109. data/test/models/pirate.rb +55 -1
  110. data/test/models/post.rb +6 -0
  111. data/test/models/project.rb +1 -0
  112. data/test/models/reply.rb +6 -0
  113. data/test/models/ship.rb +8 -1
  114. data/test/models/ship_part.rb +5 -0
  115. data/test/models/topic.rb +13 -1
  116. data/test/models/toy.rb +4 -0
  117. data/test/schema/schema.rb +35 -2
  118. metadata +70 -9
  119. data/test/fixtures/fixture_database.sqlite +0 -0
  120. data/test/fixtures/fixture_database_2.sqlite +0 -0
@@ -174,7 +174,7 @@ module ActiveRecord
174
174
  alias_attribute_without_dirty(new_name, old_name)
175
175
  DIRTY_SUFFIXES.each do |suffix|
176
176
  module_eval <<-STR, __FILE__, __LINE__+1
177
- def #{new_name}#{suffix}; self.#{old_name}#{suffix}; end
177
+ def #{new_name}#{suffix}; self.#{old_name}#{suffix}; end # def subject_changed?; self.title_changed?; end
178
178
  STR
179
179
  end
180
180
  end
@@ -0,0 +1,25 @@
1
+ module ActiveRecord
2
+ class DynamicScopeMatch
3
+ def self.match(method)
4
+ ds_match = self.new(method)
5
+ ds_match.scope ? ds_match : nil
6
+ end
7
+
8
+ def initialize(method)
9
+ @scope = true
10
+ case method.to_s
11
+ when /^scoped_by_([_a-zA-Z]\w*)$/
12
+ names = $1
13
+ else
14
+ @scope = nil
15
+ end
16
+ @attribute_names = names && names.split('_and_')
17
+ end
18
+
19
+ attr_reader :scope, :attribute_names
20
+
21
+ def scope?
22
+ !@scope.nil?
23
+ end
24
+ end
25
+ end
@@ -1,6 +1,7 @@
1
1
  require 'erb'
2
2
  require 'yaml'
3
3
  require 'csv'
4
+ require 'active_support/dependencies'
4
5
  require 'active_support/test_case'
5
6
 
6
7
  if RUBY_VERSION < '1.9'
@@ -20,13 +21,17 @@ else
20
21
  end
21
22
  end
22
23
 
23
- # Fixtures are a way of organizing data that you want to test against; in short, sample data. They come in 3 flavors:
24
+ # Fixtures are a way of organizing data that you want to test against; in short, sample data.
25
+ #
26
+ # = Fixture formats
27
+ #
28
+ # Fixtures come in 3 flavors:
24
29
  #
25
30
  # 1. YAML fixtures
26
31
  # 2. CSV fixtures
27
32
  # 3. Single-file fixtures
28
33
  #
29
- # = YAML fixtures
34
+ # == YAML fixtures
30
35
  #
31
36
  # This type of fixture is in YAML format and the preferred default. YAML is a file format which describes data structures
32
37
  # in a non-verbose, human-readable format. It ships with Ruby 1.8.1+.
@@ -64,9 +69,9 @@ end
64
69
  # parent_id: 1
65
70
  # title: Child
66
71
  #
67
- # = CSV fixtures
72
+ # == CSV fixtures
68
73
  #
69
- # Fixtures can also be kept in the Comma Separated Value format. Akin to YAML fixtures, CSV fixtures are stored
74
+ # Fixtures can also be kept in the Comma Separated Value (CSV) format. Akin to YAML fixtures, CSV fixtures are stored
70
75
  # in a single file, but instead end with the <tt>.csv</tt> file extension
71
76
  # (Rails example: <tt><your-rails-app>/test/fixtures/web_sites.csv</tt>).
72
77
  #
@@ -89,7 +94,7 @@ end
89
94
  # Most databases and spreadsheets support exporting to CSV format, so this is a great format for you to choose if you
90
95
  # have existing data somewhere already.
91
96
  #
92
- # = Single-file fixtures
97
+ # == Single-file fixtures
93
98
  #
94
99
  # This type of fixture was the original format for Active Record that has since been deprecated in favor of the YAML and CSV formats.
95
100
  # Fixtures for this format are created by placing text files in a sub-directory (with the name of the model) to the directory
@@ -112,65 +117,53 @@ end
112
117
  # name => Ruby on Rails
113
118
  # url => http://www.rubyonrails.org
114
119
  #
115
- # = Using Fixtures
120
+ # = Using fixtures in testcases
116
121
  #
117
122
  # Since fixtures are a testing construct, we use them in our unit and functional tests. There are two ways to use the
118
123
  # fixtures, but first let's take a look at a sample unit test:
119
124
  #
120
- # require 'web_site'
125
+ # require 'test_helper'
121
126
  #
122
127
  # class WebSiteTest < ActiveSupport::TestCase
123
- # def test_web_site_count
128
+ # test "web_site_count" do
124
129
  # assert_equal 2, WebSite.count
125
130
  # end
126
131
  # end
127
132
  #
128
- # As it stands, unless we pre-load the web_site table in our database with two records, this test will fail. Here's the
129
- # easiest way to add fixtures to the database:
130
- #
131
- # ...
132
- # class WebSiteTest < ActiveSupport::TestCase
133
- # fixtures :web_sites # add more by separating the symbols with commas
134
- # ...
135
- #
136
- # By adding a "fixtures" method to the test case and passing it a list of symbols (only one is shown here though), we trigger
137
- # the testing environment to automatically load the appropriate fixtures into the database before each test.
133
+ # By default, the <tt>test_helper module</tt> will load all of your fixtures into your test database, so this test will succeed.
134
+ # The testing environment will automatically load the all fixtures into the database before each test.
138
135
  # To ensure consistent data, the environment deletes the fixtures before running the load.
139
136
  #
140
- # In addition to being available in the database, the fixtures are also loaded into a hash stored in an instance variable
141
- # of the test case. It is named after the symbol... so, in our example, there would be a hash available called
142
- # <tt>@web_sites</tt>. This is where the "fixture name" comes into play.
143
- #
144
- # On top of that, each record is automatically "found" (using <tt>Model.find(id)</tt>) and placed in the instance variable of its name.
145
- # So for the YAML fixtures, we'd get <tt>@rubyonrails</tt> and <tt>@google</tt>, which could be interrogated using regular Active Record semantics:
137
+ # In addition to being available in the database, the fixture's data may also be accessed by
138
+ # using a special dynamic method, which has the same name as the model, and accepts the
139
+ # name of the fixture to instantiate:
146
140
  #
147
- # # test if the object created from the fixture data has the same attributes as the data itself
148
- # def test_find
149
- # assert_equal @web_sites["rubyonrails"]["name"], @rubyonrails.name
141
+ # test "find" do
142
+ # assert_equal "Ruby on Rails", web_sites(:rubyonrails).name
150
143
  # end
151
144
  #
152
- # As seen above, the data hash created from the YAML fixtures would have <tt>@web_sites["rubyonrails"]["url"]</tt> return
153
- # "http://www.rubyonrails.org" and <tt>@web_sites["google"]["name"]</tt> would return "Google". The same fixtures, but loaded
154
- # from a CSV fixture file, would be accessible via <tt>@web_sites["web_site_1"]["name"] == "Ruby on Rails"</tt> and have the individual
155
- # fixtures available as instance variables <tt>@web_site_1</tt> and <tt>@web_site_2</tt>.
145
+ # Alternatively, you may enable auto-instantiation of the fixture data. For instance, take the following tests:
156
146
  #
157
- # If you do not wish to use instantiated fixtures (usually for performance reasons) there are two options.
147
+ # test "find_alt_method_1" do
148
+ # assert_equal "Ruby on Rails", @web_sites['rubyonrails']['name']
149
+ # end
158
150
  #
159
- # - to completely disable instantiated fixtures:
160
- # self.use_instantiated_fixtures = false
151
+ # test "find_alt_method_2" do
152
+ # assert_equal "Ruby on Rails", @rubyonrails.news
153
+ # end
161
154
  #
162
- # - to keep the fixture instance (@web_sites) available, but do not automatically 'find' each instance:
163
- # self.use_instantiated_fixtures = :no_instances
155
+ # In order to use these methods to access fixtured data within your testcases, you must specify one of the
156
+ # following in your <tt>ActiveSupport::TestCase</tt>-derived class:
164
157
  #
165
- # Even if auto-instantiated fixtures are disabled, you can still access them
166
- # by name via special dynamic methods. Each method has the same name as the
167
- # model, and accepts the name of the fixture to instantiate:
158
+ # - to fully enable instantiated fixtures (enable alternate methods #1 and #2 above)
159
+ # self.use_instantiated_fixtures = true
168
160
  #
169
- # fixtures :web_sites
161
+ # - create only the hash for the fixtures, do not 'find' each instance (enable alternate method #1 only)
162
+ # self.use_instantiated_fixtures = :no_instances
170
163
  #
171
- # def test_find
172
- # assert_equal "Ruby on Rails", web_sites(:rubyonrails).name
173
- # end
164
+ # Using either of these alternate methods incurs a performance hit, as the fixtured data must be fully
165
+ # traversed in the database to create the fixture hash and/or instance variables. This is expensive for
166
+ # large sets of fixtured data.
174
167
  #
175
168
  # = Dynamic fixtures with ERb
176
169
  #
@@ -193,21 +186,17 @@ end
193
186
  # = Transactional fixtures
194
187
  #
195
188
  # TestCases can use begin+rollback to isolate their changes to the database instead of having to delete+insert for every test case.
196
- # They can also turn off auto-instantiation of fixture data since the feature is costly and often unused.
197
189
  #
198
190
  # class FooTest < ActiveSupport::TestCase
199
191
  # self.use_transactional_fixtures = true
200
- # self.use_instantiated_fixtures = false
201
- #
202
- # fixtures :foos
203
192
  #
204
- # def test_godzilla
193
+ # test "godzilla" do
205
194
  # assert !Foo.find(:all).empty?
206
195
  # Foo.destroy_all
207
196
  # assert Foo.find(:all).empty?
208
197
  # end
209
198
  #
210
- # def test_godzilla_aftermath
199
+ # test "godzilla aftermath" do
211
200
  # assert !Foo.find(:all).empty?
212
201
  # end
213
202
  # end
@@ -219,24 +208,25 @@ end
219
208
  # access to fixture data for every table that has been loaded through fixtures (depending on the value of +use_instantiated_fixtures+)
220
209
  #
221
210
  # When *not* to use transactional fixtures:
222
- # 1. You're testing whether a transaction works correctly. Nested transactions don't commit until all parent transactions commit,
223
- # particularly, the fixtures transaction which is begun in setup and rolled back in teardown. Thus, you won't be able to verify
224
- # the results of your transaction until Active Record supports nested transactions or savepoints (in progress).
225
- # 2. Your database does not support transactions. Every Active Record database supports transactions except MySQL MyISAM.
226
- # Use InnoDB, MaxDB, or NDB instead.
211
+ #
212
+ # 1. You're testing whether a transaction works correctly. Nested transactions don't commit until all parent transactions commit,
213
+ # particularly, the fixtures transaction which is begun in setup and rolled back in teardown. Thus, you won't be able to verify
214
+ # the results of your transaction until Active Record supports nested transactions or savepoints (in progress).
215
+ # 2. Your database does not support transactions. Every Active Record database supports transactions except MySQL MyISAM.
216
+ # Use InnoDB, MaxDB, or NDB instead.
227
217
  #
228
218
  # = Advanced YAML Fixtures
229
219
  #
230
220
  # YAML fixtures that don't specify an ID get some extra features:
231
221
  #
232
- # * Stable, autogenerated ID's
222
+ # * Stable, autogenerated IDs
233
223
  # * Label references for associations (belongs_to, has_one, has_many)
234
224
  # * HABTM associations as inline lists
235
225
  # * Autofilled timestamp columns
236
226
  # * Fixture label interpolation
237
227
  # * Support for YAML defaults
238
228
  #
239
- # == Stable, autogenerated ID's
229
+ # == Stable, autogenerated IDs
240
230
  #
241
231
  # Here, have a monkey fixture:
242
232
  #
@@ -291,7 +281,7 @@ end
291
281
  #
292
282
  # Add a few more monkeys and pirates and break this into multiple files,
293
283
  # and it gets pretty hard to keep track of what's going on. Let's
294
- # use labels instead of ID's:
284
+ # use labels instead of IDs:
295
285
  #
296
286
  # ### in pirates.yml
297
287
  #
@@ -515,7 +505,7 @@ class Fixtures < (RUBY_VERSION < '1.9' ? YAML::Omap : Hash)
515
505
 
516
506
  all_loaded_fixtures.update(fixtures_map)
517
507
 
518
- connection.transaction(connection.open_transactions.zero?) do
508
+ connection.transaction(:requires_new => true) do
519
509
  fixtures.reverse.each { |fixture| fixture.delete_existing_fixtures }
520
510
  fixtures.each { |fixture| fixture.insert_fixtures }
521
511
 
@@ -813,186 +803,191 @@ class Fixture #:nodoc:
813
803
  end
814
804
  end
815
805
 
816
- module Test #:nodoc:
817
- module Unit #:nodoc:
818
- class TestCase #:nodoc:
819
- setup :setup_fixtures
820
- teardown :teardown_fixtures
821
-
822
- superclass_delegating_accessor :fixture_path
823
- superclass_delegating_accessor :fixture_table_names
824
- superclass_delegating_accessor :fixture_class_names
825
- superclass_delegating_accessor :use_transactional_fixtures
826
- superclass_delegating_accessor :use_instantiated_fixtures # true, false, or :no_instances
827
- superclass_delegating_accessor :pre_loaded_fixtures
828
-
829
- self.fixture_table_names = []
830
- self.use_transactional_fixtures = false
831
- self.use_instantiated_fixtures = true
832
- self.pre_loaded_fixtures = false
833
-
834
- @@already_loaded_fixtures = {}
835
- self.fixture_class_names = {}
836
-
837
- class << self
838
- def set_fixture_class(class_names = {})
839
- self.fixture_class_names = self.fixture_class_names.merge(class_names)
840
- end
806
+ module ActiveRecord
807
+ module TestFixtures
808
+ def self.included(base)
809
+ base.class_eval do
810
+ setup :setup_fixtures
811
+ teardown :teardown_fixtures
812
+
813
+ superclass_delegating_accessor :fixture_path
814
+ superclass_delegating_accessor :fixture_table_names
815
+ superclass_delegating_accessor :fixture_class_names
816
+ superclass_delegating_accessor :use_transactional_fixtures
817
+ superclass_delegating_accessor :use_instantiated_fixtures # true, false, or :no_instances
818
+ superclass_delegating_accessor :pre_loaded_fixtures
819
+
820
+ self.fixture_table_names = []
821
+ self.use_transactional_fixtures = false
822
+ self.use_instantiated_fixtures = true
823
+ self.pre_loaded_fixtures = false
824
+
825
+ self.fixture_class_names = {}
826
+ end
841
827
 
842
- def fixtures(*table_names)
843
- if table_names.first == :all
844
- table_names = Dir["#{fixture_path}/*.yml"] + Dir["#{fixture_path}/*.csv"]
845
- table_names.map! { |f| File.basename(f).split('.')[0..-2].join('.') }
846
- else
847
- table_names = table_names.flatten.map { |n| n.to_s }
848
- end
828
+ base.extend ClassMethods
829
+ end
830
+
831
+ module ClassMethods
832
+ def set_fixture_class(class_names = {})
833
+ self.fixture_class_names = self.fixture_class_names.merge(class_names)
834
+ end
849
835
 
850
- self.fixture_table_names |= table_names
851
- require_fixture_classes(table_names)
852
- setup_fixture_accessors(table_names)
836
+ def fixtures(*table_names)
837
+ if table_names.first == :all
838
+ table_names = Dir["#{fixture_path}/*.yml"] + Dir["#{fixture_path}/*.csv"]
839
+ table_names.map! { |f| File.basename(f).split('.')[0..-2].join('.') }
840
+ else
841
+ table_names = table_names.flatten.map { |n| n.to_s }
853
842
  end
854
843
 
855
- def try_to_load_dependency(file_name)
856
- require_dependency file_name
857
- rescue LoadError => e
858
- # Let's hope the developer has included it himself
844
+ self.fixture_table_names |= table_names
845
+ require_fixture_classes(table_names)
846
+ setup_fixture_accessors(table_names)
847
+ end
859
848
 
860
- # Let's warn in case this is a subdependency, otherwise
861
- # subdependency error messages are totally cryptic
862
- if ActiveRecord::Base.logger
863
- ActiveRecord::Base.logger.warn("Unable to load #{file_name}, underlying cause #{e.message} \n\n #{e.backtrace.join("\n")}")
864
- end
849
+ def try_to_load_dependency(file_name)
850
+ require_dependency file_name
851
+ rescue LoadError => e
852
+ # Let's hope the developer has included it himself
853
+
854
+ # Let's warn in case this is a subdependency, otherwise
855
+ # subdependency error messages are totally cryptic
856
+ if ActiveRecord::Base.logger
857
+ ActiveRecord::Base.logger.warn("Unable to load #{file_name}, underlying cause #{e.message} \n\n #{e.backtrace.join("\n")}")
865
858
  end
859
+ end
866
860
 
867
- def require_fixture_classes(table_names = nil)
868
- (table_names || fixture_table_names).each do |table_name|
869
- file_name = table_name.to_s
870
- file_name = file_name.singularize if ActiveRecord::Base.pluralize_table_names
871
- try_to_load_dependency(file_name)
872
- end
861
+ def require_fixture_classes(table_names = nil)
862
+ (table_names || fixture_table_names).each do |table_name|
863
+ file_name = table_name.to_s
864
+ file_name = file_name.singularize if ActiveRecord::Base.pluralize_table_names
865
+ try_to_load_dependency(file_name)
873
866
  end
867
+ end
874
868
 
875
- def setup_fixture_accessors(table_names = nil)
876
- table_names = [table_names] if table_names && !table_names.respond_to?(:each)
877
- (table_names || fixture_table_names).each do |table_name|
878
- table_name = table_name.to_s.tr('.', '_')
869
+ def setup_fixture_accessors(table_names = nil)
870
+ table_names = [table_names] if table_names && !table_names.respond_to?(:each)
871
+ (table_names || fixture_table_names).each do |table_name|
872
+ table_name = table_name.to_s.tr('.', '_')
879
873
 
880
- define_method(table_name) do |*fixtures|
881
- force_reload = fixtures.pop if fixtures.last == true || fixtures.last == :reload
874
+ define_method(table_name) do |*fixtures|
875
+ force_reload = fixtures.pop if fixtures.last == true || fixtures.last == :reload
882
876
 
883
- @fixture_cache[table_name] ||= {}
877
+ @fixture_cache[table_name] ||= {}
884
878
 
885
- instances = fixtures.map do |fixture|
886
- @fixture_cache[table_name].delete(fixture) if force_reload
879
+ instances = fixtures.map do |fixture|
880
+ @fixture_cache[table_name].delete(fixture) if force_reload
887
881
 
888
- if @loaded_fixtures[table_name][fixture.to_s]
889
- @fixture_cache[table_name][fixture] ||= @loaded_fixtures[table_name][fixture.to_s].find
890
- else
891
- raise StandardError, "No fixture with name '#{fixture}' found for table '#{table_name}'"
892
- end
882
+ if @loaded_fixtures[table_name][fixture.to_s]
883
+ @fixture_cache[table_name][fixture] ||= @loaded_fixtures[table_name][fixture.to_s].find
884
+ else
885
+ raise StandardError, "No fixture with name '#{fixture}' found for table '#{table_name}'"
893
886
  end
894
-
895
- instances.size == 1 ? instances.first : instances
896
887
  end
897
- end
898
- end
899
888
 
900
- def uses_transaction(*methods)
901
- @uses_transaction = [] unless defined?(@uses_transaction)
902
- @uses_transaction.concat methods.map(&:to_s)
889
+ instances.size == 1 ? instances.first : instances
890
+ end
903
891
  end
892
+ end
904
893
 
905
- def uses_transaction?(method)
906
- @uses_transaction = [] unless defined?(@uses_transaction)
907
- @uses_transaction.include?(method.to_s)
908
- end
894
+ def uses_transaction(*methods)
895
+ @uses_transaction = [] unless defined?(@uses_transaction)
896
+ @uses_transaction.concat methods.map(&:to_s)
909
897
  end
910
898
 
911
- def use_transactional_fixtures?
912
- use_transactional_fixtures &&
913
- !self.class.uses_transaction?(method_name)
899
+ def uses_transaction?(method)
900
+ @uses_transaction = [] unless defined?(@uses_transaction)
901
+ @uses_transaction.include?(method.to_s)
914
902
  end
903
+ end
915
904
 
916
- def setup_fixtures
917
- return unless defined?(ActiveRecord) && !ActiveRecord::Base.configurations.blank?
905
+ def run_in_transaction?
906
+ use_transactional_fixtures &&
907
+ !self.class.uses_transaction?(method_name)
908
+ end
918
909
 
919
- if pre_loaded_fixtures && !use_transactional_fixtures
920
- raise RuntimeError, 'pre_loaded_fixtures requires use_transactional_fixtures'
921
- end
910
+ def setup_fixtures
911
+ return unless defined?(ActiveRecord) && !ActiveRecord::Base.configurations.blank?
922
912
 
923
- @fixture_cache = {}
913
+ if pre_loaded_fixtures && !use_transactional_fixtures
914
+ raise RuntimeError, 'pre_loaded_fixtures requires use_transactional_fixtures'
915
+ end
924
916
 
925
- # Load fixtures once and begin transaction.
926
- if use_transactional_fixtures?
927
- if @@already_loaded_fixtures[self.class]
928
- @loaded_fixtures = @@already_loaded_fixtures[self.class]
929
- else
930
- load_fixtures
931
- @@already_loaded_fixtures[self.class] = @loaded_fixtures
932
- end
933
- ActiveRecord::Base.connection.increment_open_transactions
934
- ActiveRecord::Base.connection.begin_db_transaction
935
- # Load fixtures for every test.
917
+ @fixture_cache = {}
918
+ @@already_loaded_fixtures ||= {}
919
+
920
+ # Load fixtures once and begin transaction.
921
+ if run_in_transaction?
922
+ if @@already_loaded_fixtures[self.class]
923
+ @loaded_fixtures = @@already_loaded_fixtures[self.class]
936
924
  else
937
- Fixtures.reset_cache
938
- @@already_loaded_fixtures[self.class] = nil
939
925
  load_fixtures
926
+ @@already_loaded_fixtures[self.class] = @loaded_fixtures
940
927
  end
941
-
942
- # Instantiate fixtures for every test if requested.
943
- instantiate_fixtures if use_instantiated_fixtures
928
+ ActiveRecord::Base.connection.increment_open_transactions
929
+ ActiveRecord::Base.connection.transaction_joinable = false
930
+ ActiveRecord::Base.connection.begin_db_transaction
931
+ # Load fixtures for every test.
932
+ else
933
+ Fixtures.reset_cache
934
+ @@already_loaded_fixtures[self.class] = nil
935
+ load_fixtures
944
936
  end
945
937
 
946
- def teardown_fixtures
947
- return unless defined?(ActiveRecord) && !ActiveRecord::Base.configurations.blank?
938
+ # Instantiate fixtures for every test if requested.
939
+ instantiate_fixtures if use_instantiated_fixtures
940
+ end
948
941
 
949
- unless use_transactional_fixtures?
950
- Fixtures.reset_cache
951
- end
942
+ def teardown_fixtures
943
+ return unless defined?(ActiveRecord) && !ActiveRecord::Base.configurations.blank?
952
944
 
953
- # Rollback changes if a transaction is active.
954
- if use_transactional_fixtures? && ActiveRecord::Base.connection.open_transactions != 0
955
- ActiveRecord::Base.connection.rollback_db_transaction
956
- ActiveRecord::Base.connection.decrement_open_transactions
957
- end
958
- ActiveRecord::Base.clear_active_connections!
945
+ unless run_in_transaction?
946
+ Fixtures.reset_cache
959
947
  end
960
948
 
961
- private
962
- def load_fixtures
963
- @loaded_fixtures = {}
964
- fixtures = Fixtures.create_fixtures(fixture_path, fixture_table_names, fixture_class_names)
965
- unless fixtures.nil?
966
- if fixtures.instance_of?(Fixtures)
967
- @loaded_fixtures[fixtures.name] = fixtures
968
- else
969
- fixtures.each { |f| @loaded_fixtures[f.name] = f }
970
- end
949
+ # Rollback changes if a transaction is active.
950
+ if run_in_transaction? && ActiveRecord::Base.connection.open_transactions != 0
951
+ ActiveRecord::Base.connection.rollback_db_transaction
952
+ ActiveRecord::Base.connection.decrement_open_transactions
953
+ end
954
+ ActiveRecord::Base.clear_active_connections!
955
+ end
956
+
957
+ private
958
+ def load_fixtures
959
+ @loaded_fixtures = {}
960
+ fixtures = Fixtures.create_fixtures(fixture_path, fixture_table_names, fixture_class_names)
961
+ unless fixtures.nil?
962
+ if fixtures.instance_of?(Fixtures)
963
+ @loaded_fixtures[fixtures.name] = fixtures
964
+ else
965
+ fixtures.each { |f| @loaded_fixtures[f.name] = f }
971
966
  end
972
967
  end
968
+ end
973
969
 
974
- # for pre_loaded_fixtures, only require the classes once. huge speed improvement
975
- @@required_fixture_classes = false
970
+ # for pre_loaded_fixtures, only require the classes once. huge speed improvement
971
+ @@required_fixture_classes = false
976
972
 
977
- def instantiate_fixtures
978
- if pre_loaded_fixtures
979
- raise RuntimeError, 'Load fixtures before instantiating them.' if Fixtures.all_loaded_fixtures.empty?
980
- unless @@required_fixture_classes
981
- self.class.require_fixture_classes Fixtures.all_loaded_fixtures.keys
982
- @@required_fixture_classes = true
983
- end
984
- Fixtures.instantiate_all_loaded_fixtures(self, load_instances?)
985
- else
986
- raise RuntimeError, 'Load fixtures before instantiating them.' if @loaded_fixtures.nil?
987
- @loaded_fixtures.each do |table_name, fixtures|
988
- Fixtures.instantiate_fixtures(self, table_name, fixtures, load_instances?)
989
- end
973
+ def instantiate_fixtures
974
+ if pre_loaded_fixtures
975
+ raise RuntimeError, 'Load fixtures before instantiating them.' if Fixtures.all_loaded_fixtures.empty?
976
+ unless @@required_fixture_classes
977
+ self.class.require_fixture_classes Fixtures.all_loaded_fixtures.keys
978
+ @@required_fixture_classes = true
979
+ end
980
+ Fixtures.instantiate_all_loaded_fixtures(self, load_instances?)
981
+ else
982
+ raise RuntimeError, 'Load fixtures before instantiating them.' if @loaded_fixtures.nil?
983
+ @loaded_fixtures.each do |table_name, fixtures|
984
+ Fixtures.instantiate_fixtures(self, table_name, fixtures, load_instances?)
990
985
  end
991
986
  end
987
+ end
992
988
 
993
- def load_instances?
994
- use_instantiated_fixtures != :no_instances
995
- end
996
- end
989
+ def load_instances?
990
+ use_instantiated_fixtures != :no_instances
991
+ end
997
992
  end
998
993
  end