Skip to content
This repository
Browse code

Remove IdentityMap

  • Loading branch information...
commit a8dd21d8b459ce4d57160a359798c577085a95e9 1 parent c1f397f
Carlos Antonio da Silva authored March 02, 2012

Showing 33 changed files with 36 additions and 966 deletions. Show diff stats Hide diff stats

  1. 2  activerecord/CHANGELOG.md
  2. 7  activerecord/RUNNING_UNIT_TESTS
  3. 1  activerecord/lib/active_record.rb
  4. 13  activerecord/lib/active_record/associations/association.rb
  5. 5  activerecord/lib/active_record/attribute_methods/dirty.rb
  6. 6  activerecord/lib/active_record/autosave_association.rb
  7. 2  activerecord/lib/active_record/counter_cache.rb
  8. 4  activerecord/lib/active_record/fixtures.rb
  9. 144  activerecord/lib/active_record/identity_map.rb
  10. 23  activerecord/lib/active_record/inheritance.rb
  11. 1  activerecord/lib/active_record/model.rb
  12. 16  activerecord/lib/active_record/persistence.rb
  13. 5  activerecord/lib/active_record/railtie.rb
  14. 11  activerecord/lib/active_record/relation.rb
  15. 10  activerecord/lib/active_record/relation/finder_methods.rb
  16. 10  activerecord/lib/active_record/test_case.rb
  17. 2  activerecord/lib/active_record/transactions.rb
  18. 1  activerecord/test/cases/associations/eager_load_includes_full_sti_class_test.rb
  19. 20  activerecord/test/cases/associations/eager_test.rb
  20. 137  activerecord/test/cases/associations/identity_map_test.rb
  21. 8  activerecord/test/cases/autosave_association_test.rb
  22. 4  activerecord/test/cases/base_test.rb
  23. 3  activerecord/test/cases/helper.rb
  24. 74  activerecord/test/cases/identity_map/middleware_test.rb
  25. 439  activerecord/test/cases/identity_map_test.rb
  26. 12  activerecord/test/cases/log_subscriber_test.rb
  27. 2  activerecord/test/cases/query_cache_test.rb
  28. 16  activerecord/test/cases/relations_test.rb
  29. 2  activerecord/test/support/connection.rb
  30. 9  ci/travis.rb
  31. 2  railties/guides/source/configuring.textile
  32. 4  railties/lib/rails/test_help.rb
  33. 7  railties/test/application/middleware_test.rb
2  activerecord/CHANGELOG.md
Source Rendered
... ...
@@ -1,5 +1,7 @@
1 1
 ## Rails 4.0.0 (unreleased) ##
2 2
 
  3
+*   Remove IdentityMap *Carlos Antonio da Silva*
  4
+
3 5
 *   Added the schema cache dump feature.
4 6
 
5 7
     `Schema cache dump` feature was implemetend. This feature can dump/load internal state of `SchemaCache` instance
7  activerecord/RUNNING_UNIT_TESTS
@@ -26,13 +26,6 @@ You can run all the tests for a given database via rake:
26 26
 
27 27
 The 'rake test' task will run all the tests for mysql, mysql2, sqlite3 and postgresql.
28 28
 
29  
-== Identity Map
30  
-
31  
-By default the tests run with the Identity Map turned off. But all tests should pass whether or
32  
-not the identity map is on or off. You can turn it on using the IM env variable:
33  
-
34  
-  $ IM=true ruby -Itest test/case/base_test.rb
35  
-
36 29
 == Config file
37 30
 
38 31
 By default, the config file is expected to be at the path test/config.yml. You can specify a
1  activerecord/lib/active_record.rb
@@ -65,7 +65,6 @@ module ActiveRecord
65 65
     autoload :DynamicFinderMatch
66 66
     autoload :DynamicScopeMatch
67 67
     autoload :Explain
68  
-    autoload :IdentityMap
69 68
     autoload :Inheritance
70 69
     autoload :Integration
71 70
     autoload :Migration
13  activerecord/lib/active_record/associations/association.rb
@@ -45,7 +45,6 @@ def aliased_table_name
45 45
       # Resets the \loaded flag to +false+ and sets the \target to +nil+.
46 46
       def reset
47 47
         @loaded = false
48  
-        IdentityMap.remove(target) if IdentityMap.enabled? && target
49 48
         @target = nil
50 49
       end
51 50
 
@@ -135,17 +134,7 @@ def target_scope
135 134
       # ActiveRecord::RecordNotFound is rescued within the method, and it is
136 135
       # not reraised. The proxy is \reset and +nil+ is the return value.
137 136
       def load_target
138  
-        if find_target?
139  
-          begin
140  
-            if IdentityMap.enabled? && association_class && association_class.respond_to?(:base_class)
141  
-              @target = IdentityMap.get(association_class, owner[reflection.foreign_key])
142  
-            end
143  
-          rescue NameError
144  
-            nil
145  
-          ensure
146  
-            @target ||= find_target
147  
-          end
148  
-        end
  137
+        @target ||= find_target if find_target?
149 138
         loaded! unless loaded?
150 139
         target
151 140
       rescue ActiveRecord::RecordNotFound
5  activerecord/lib/active_record/attribute_methods/dirty.rb
@@ -22,8 +22,6 @@ def save(*) #:nodoc:
22 22
         if status = super
23 23
           @previously_changed = changes
24 24
           @changed_attributes.clear
25  
-        elsif IdentityMap.enabled?
26  
-          IdentityMap.remove(self)
27 25
         end
28 26
         status
29 27
       end
@@ -34,9 +32,6 @@ def save!(*) #:nodoc:
34 32
           @previously_changed = changes
35 33
           @changed_attributes.clear
36 34
         end
37  
-      rescue
38  
-        IdentityMap.remove(self) if IdentityMap.enabled?
39  
-        raise
40 35
       end
41 36
 
42 37
       # <tt>reload</tt> the record and clears changed attributes.
6  activerecord/lib/active_record/autosave_association.rb
@@ -328,7 +328,6 @@ def save_collection_association(reflection)
328 328
         autosave = reflection.options[:autosave]
329 329
 
330 330
         if records = associated_records_to_validate_or_save(association, @new_record_before_save, autosave)
331  
-          begin
332 331
           records.each do |record|
333 332
             next if record.destroyed?
334 333
 
@@ -348,11 +347,6 @@ def save_collection_association(reflection)
348 347
 
349 348
             raise ActiveRecord::Rollback unless saved
350 349
           end
351  
-          rescue
352  
-            records.each {|x| IdentityMap.remove(x) } if IdentityMap.enabled?
353  
-            raise
354  
-          end
355  
-
356 350
         end
357 351
 
358 352
         # reconstruct the scope now that we know the owner's id
2  activerecord/lib/active_record/counter_cache.rb
@@ -69,8 +69,6 @@ def update_counters(id, counters)
69 69
         "#{quoted_column} = COALESCE(#{quoted_column}, 0) #{operator} #{value.abs}"
70 70
       end
71 71
 
72  
-      IdentityMap.remove_by_id(symbolized_base_class, id) if IdentityMap.enabled?
73  
-
74 72
       update_all(updates.join(', '), primary_key => id)
75 73
     end
76 74
 
4  activerecord/lib/active_record/fixtures.rb
@@ -796,9 +796,7 @@ def setup_fixture_accessors(fixture_names = nil)
796 796
                 @fixture_cache[fixture_name].delete(fixture) if force_reload
797 797
 
798 798
                 if @loaded_fixtures[fixture_name][fixture.to_s]
799  
-                  ActiveRecord::IdentityMap.without do
800  
-                    @fixture_cache[fixture_name][fixture] ||= @loaded_fixtures[fixture_name][fixture.to_s].find
801  
-                  end
  799
+                  @fixture_cache[fixture_name][fixture] ||= @loaded_fixtures[fixture_name][fixture.to_s].find
802 800
                 else
803 801
                   raise StandardError, "No entry named '#{fixture}' found for fixture collection '#{fixture_name}'"
804 802
                 end
144  activerecord/lib/active_record/identity_map.rb
... ...
@@ -1,144 +0,0 @@
1  
-module ActiveRecord
2  
-  # = Active Record Identity Map
3  
-  #
4  
-  # Ensures that each object gets loaded only once by keeping every loaded
5  
-  # object in a map. Looks up objects using the map when referring to them.
6  
-  #
7  
-  # More information on Identity Map pattern:
8  
-  #   http://www.martinfowler.com/eaaCatalog/identityMap.html
9  
-  #
10  
-  # == Configuration
11  
-  #
12  
-  # In order to enable IdentityMap, set <tt>config.active_record.identity_map = true</tt>
13  
-  # in your <tt>config/application.rb</tt> file.
14  
-  #
15  
-  # IdentityMap is disabled by default and still in development (i.e. use it with care).
16  
-  #
17  
-  # == Associations
18  
-  #
19  
-  # Active Record Identity Map does not track associations yet. For example:
20  
-  #
21  
-  #   comment = @post.comments.first
22  
-  #   comment.post = nil
23  
-  #   @post.comments.include?(comment) #=> true
24  
-  #
25  
-  # Ideally, the example above would return false, removing the comment object from the
26  
-  # post association when the association is nullified. This may cause side effects, as
27  
-  # in the situation below, if Identity Map is enabled:
28  
-  #
29  
-  #   Post.has_many :comments, :dependent => :destroy
30  
-  #
31  
-  #   comment = @post.comments.first
32  
-  #   comment.post = nil
33  
-  #   comment.save
34  
-  #   Post.destroy(@post.id)
35  
-  #
36  
-  # Without using Identity Map, the code above will destroy the @post object leaving
37  
-  # the comment object intact. However, once we enable Identity Map, the post loaded
38  
-  # by Post.destroy is exactly the same object as the object @post. As the object @post
39  
-  # still has the comment object in @post.comments, once Identity Map is enabled, the
40  
-  # comment object will be accidently removed.
41  
-  #
42  
-  # This inconsistency is meant to be fixed in future Rails releases.
43  
-  #
44  
-  module IdentityMap
45  
-
46  
-    class << self
47  
-      def enabled=(flag)
48  
-        Thread.current[:identity_map_enabled] = flag
49  
-      end
50  
-
51  
-      def enabled
52  
-        Thread.current[:identity_map_enabled]
53  
-      end
54  
-      alias enabled? enabled
55  
-
56  
-      def repository
57  
-        Thread.current[:identity_map] ||= Hash.new { |h,k| h[k] = {} }
58  
-      end
59  
-
60  
-      def use
61  
-        old, self.enabled = enabled, true
62  
-
63  
-        yield if block_given?
64  
-      ensure
65  
-        self.enabled = old
66  
-        clear
67  
-      end
68  
-
69  
-      def without
70  
-        old, self.enabled = enabled, false
71  
-
72  
-        yield if block_given?
73  
-      ensure
74  
-        self.enabled = old
75  
-      end
76  
-
77  
-      def get(klass, primary_key)
78  
-        record = repository[klass.symbolized_sti_name][primary_key]
79  
-
80  
-        if record.is_a?(klass)
81  
-          ActiveSupport::Notifications.instrument("identity.active_record",
82  
-            :line => "From Identity Map (id: #{primary_key})",
83  
-            :name => "#{klass} Loaded",
84  
-            :connection_id => object_id)
85  
-
86  
-          record
87  
-        else
88  
-          nil
89  
-        end
90  
-      end
91  
-
92  
-      def add(record)
93  
-        repository[record.class.symbolized_sti_name][record.id] = record
94  
-      end
95  
-
96  
-      def remove(record)
97  
-        repository[record.class.symbolized_sti_name].delete(record.id)
98  
-      end
99  
-
100  
-      def remove_by_id(symbolized_sti_name, id)
101  
-        repository[symbolized_sti_name].delete(id)
102  
-      end
103  
-
104  
-      def clear
105  
-        repository.clear
106  
-      end
107  
-    end
108  
-
109  
-    # Reinitialize an Identity Map model object from +coder+.
110  
-    # +coder+ must contain the attributes necessary for initializing an empty
111  
-    # model object.
112  
-    def reinit_with(coder)
113  
-      @attributes_cache = {}
114  
-      dirty      = @changed_attributes.keys
115  
-      attributes = self.class.initialize_attributes(coder['attributes'].except(*dirty))
116  
-      @attributes.update(attributes)
117  
-      @changed_attributes.update(coder['attributes'].slice(*dirty))
118  
-      @changed_attributes.delete_if{|k,v| v.eql? @attributes[k]}
119  
-
120  
-      run_callbacks :find
121  
-
122  
-      self
123  
-    end
124  
-
125  
-    class Middleware
126  
-      def initialize(app)
127  
-        @app = app
128  
-      end
129  
-
130  
-      def call(env)
131  
-        enabled = IdentityMap.enabled
132  
-        IdentityMap.enabled = true
133  
-
134  
-        response = @app.call(env)
135  
-        response[2] = Rack::BodyProxy.new(response[2]) do
136  
-          IdentityMap.enabled = enabled
137  
-          IdentityMap.clear
138  
-        end
139  
-
140  
-        response
141  
-      end
142  
-    end
143  
-  end
144  
-end
23  activerecord/lib/active_record/inheritance.rb
@@ -63,26 +63,9 @@ def sti_name
63 63
       # single-table inheritance model that makes it possible to create
64 64
       # objects of different types from the same table.
65 65
       def instantiate(record, column_types = {})
66  
-        sti_class = find_sti_class(record[inheritance_column])
67  
-        record_id = sti_class.primary_key && record[sti_class.primary_key]
68  
-
69  
-        if ActiveRecord::IdentityMap.enabled? && record_id
70  
-          if (column = sti_class.columns_hash[sti_class.primary_key]) && column.number?
71  
-            record_id = record_id.to_i
72  
-          end
73  
-          if instance = IdentityMap.get(sti_class, record_id)
74  
-            instance.reinit_with('attributes' => record)
75  
-          else
76  
-            instance = sti_class.allocate.init_with('attributes' => record)
77  
-            IdentityMap.add(instance)
78  
-          end
79  
-        else
80  
-          column_types = sti_class.decorate_columns(column_types)
81  
-          instance = sti_class.allocate.init_with('attributes' => record,
82  
-                                                  'column_types' => column_types)
83  
-        end
84  
-
85  
-        instance
  66
+        sti_class    = find_sti_class(record[inheritance_column])
  67
+        column_types = sti_class.decorate_columns(column_types)
  68
+        sti_class.allocate.init_with('attributes' => record, 'column_types' => column_types)
86 69
       end
87 70
 
88 71
       # For internal use.
1  activerecord/lib/active_record/model.rb
@@ -60,7 +60,6 @@ def self.extend(*modules)
60 60
     include AttributeMethods
61 61
     include Callbacks, ActiveModel::Observing, Timestamp
62 62
     include Associations
63  
-    include IdentityMap
64 63
     include ActiveModel::SecurePassword
65 64
     include AutosaveAssociation, NestedAttributes
66 65
     include Aggregations, Transactions, Reflection, Serialization, Store
16  activerecord/lib/active_record/persistence.rb
@@ -115,10 +115,7 @@ def save!(*)
115 115
     # callbacks, Observer methods, or any <tt>:dependent</tt> association
116 116
     # options, use <tt>#destroy</tt>.
117 117
     def delete
118  
-      if persisted?
119  
-        self.class.delete(id)
120  
-        IdentityMap.remove(self) if IdentityMap.enabled?
121  
-      end
  118
+      self.class.delete(id) if persisted?
122 119
       @destroyed = true
123 120
       freeze
124 121
     end
@@ -129,7 +126,6 @@ def destroy
129 126
       destroy_associations
130 127
 
131 128
       if persisted?
132  
-        IdentityMap.remove(self) if IdentityMap.enabled?
133 129
         pk         = self.class.primary_key
134 130
         column     = self.class.columns_hash[pk]
135 131
         substitute = connection.substitute_at(column, 0)
@@ -284,11 +280,9 @@ def reload(options = nil)
284 280
       clear_aggregation_cache
285 281
       clear_association_cache
286 282
 
287  
-      IdentityMap.without do
288  
-        fresh_object = self.class.unscoped { self.class.find(id, options) }
289  
-        @attributes.update(fresh_object.instance_variable_get('@attributes'))
290  
-        @columns_hash = fresh_object.instance_variable_get('@columns_hash')
291  
-      end
  283
+      fresh_object = self.class.unscoped { self.class.find(id, options) }
  284
+      @attributes.update(fresh_object.instance_variable_get('@attributes'))
  285
+      @columns_hash = fresh_object.instance_variable_get('@columns_hash')
292 286
 
293 287
       @attributes_cache = {}
294 288
       self
@@ -363,10 +357,8 @@ def create
363 357
       attributes_values = arel_attributes_with_values_for_create(!id.nil?)
364 358
 
365 359
       new_id = self.class.unscoped.insert attributes_values
366  
-
367 360
       self.id ||= new_id if self.class.primary_key
368 361
 
369  
-      IdentityMap.add(self) if IdentityMap.enabled?
370 362
       @new_record = false
371 363
       id
372 364
     end
5  activerecord/lib/active_record/railtie.rb
@@ -53,11 +53,6 @@ class Railtie < Rails::Railtie
53 53
       ActiveSupport.on_load(:active_record) { self.logger ||= ::Rails.logger }
54 54
     end
55 55
 
56  
-    initializer "active_record.identity_map" do |app|
57  
-      config.app_middleware.insert_after "::ActionDispatch::Callbacks",
58  
-        "ActiveRecord::IdentityMap::Middleware" if config.active_record.delete(:identity_map)
59  
-    end
60  
-
61 56
     initializer "active_record.set_configs" do |app|
62 57
       ActiveSupport.on_load(:active_record) do
63 58
         if app.config.active_record.delete(:whitelist_attributes)
11  activerecord/lib/active_record/relation.rb
@@ -168,13 +168,7 @@ def exec_queries
168 168
       default_scoped = with_default_scope
169 169
 
170 170
       if default_scoped.equal?(self)
171  
-        @records = if @readonly_value.nil? && !@klass.locking_enabled?
172  
-          eager_loading? ? find_with_associations : @klass.find_by_sql(arel, @bind_values)
173  
-        else
174  
-          IdentityMap.without do
175  
-            eager_loading? ? find_with_associations : @klass.find_by_sql(arel, @bind_values)
176  
-          end
177  
-        end
  171
+        @records = eager_loading? ? find_with_associations : @klass.find_by_sql(arel, @bind_values)
178 172
 
179 173
         preload = @preload_values
180 174
         preload +=  @includes_values unless eager_loading?
@@ -274,7 +268,6 @@ def scoping
274 268
     #   # The same idea applies to limit and order
275 269
     #   Book.where('title LIKE ?', '%Rails%').order(:created_at).limit(5).update_all(:author => 'David')
276 270
     def update_all(updates, conditions = nil, options = {})
277  
-      IdentityMap.repository[symbolized_base_class].clear if IdentityMap.enabled?
278 271
       if conditions || options.present?
279 272
         where(conditions).apply_finder_options(options.slice(:limit, :order)).update_all(updates)
280 273
       else
@@ -404,7 +397,6 @@ def destroy(id)
404 397
     # If you need to destroy dependent associations or call your <tt>before_*</tt> or
405 398
     # +after_destroy+ callbacks, use the +destroy_all+ method instead.
406 399
     def delete_all(conditions = nil)
407  
-      IdentityMap.repository[symbolized_base_class] = {} if IdentityMap.enabled?
408 400
       if conditions
409 401
         where(conditions).delete_all
410 402
       else
@@ -437,7 +429,6 @@ def delete_all(conditions = nil)
437 429
     #   # Delete multiple rows
438 430
     #   Todo.delete([2,3,4])
439 431
     def delete(id_or_array)
440  
-      IdentityMap.remove_by_id(self.symbolized_base_class, id_or_array) if IdentityMap.enabled?
441 432
       where(primary_key => id_or_array).delete_all
442 433
     end
443 434
 
10  activerecord/lib/active_record/relation/finder_methods.rb
@@ -318,17 +318,7 @@ def find_with_ids(*ids)
318 318
     def find_one(id)
319 319
       id = id.id if ActiveRecord::Base === id
320 320
 
321  
-      if IdentityMap.enabled? && where_values.blank? &&
322  
-        limit_value.blank? && order_values.blank? &&
323  
-        includes_values.blank? && preload_values.blank? &&
324  
-        readonly_value.nil? && joins_values.blank? &&
325  
-        !@klass.locking_enabled? &&
326  
-        record = IdentityMap.get(@klass, id)
327  
-        return record
328  
-      end
329  
-
330 321
       column = columns_hash[primary_key]
331  
-
332 322
       substitute = connection.substitute_at(column, @bind_values.length)
333 323
       relation = where(table[primary_key].eq(substitute))
334 324
       relation.bind_values += [[column, id]]
10  activerecord/lib/active_record/test_case.rb
@@ -7,20 +7,10 @@ module ActiveRecord
7 7
   #
8 8
   # Defines some test assertions to test against SQL queries.
9 9
   class TestCase < ActiveSupport::TestCase #:nodoc:
10  
-    setup :cleanup_identity_map
11  
-
12  
-    def setup
13  
-      cleanup_identity_map
14  
-    end
15  
-
16 10
     def teardown
17 11
       SQLCounter.log.clear
18 12
     end
19 13
 
20  
-    def cleanup_identity_map
21  
-      ActiveRecord::IdentityMap.clear
22  
-    end
23  
-
24 14
     def assert_date_from_db(expected, actual, message = nil)
25 15
       # SybaseAdapter doesn't have a separate column type just for dates,
26 16
       # so the time is in the string and incorrectly formatted
2  activerecord/lib/active_record/transactions.rb
@@ -251,7 +251,6 @@ def rollback_active_record_state!
251 251
       remember_transaction_record_state
252 252
       yield
253 253
     rescue Exception
254  
-      IdentityMap.remove(self) if IdentityMap.enabled?
255 254
       restore_transaction_record_state
256 255
       raise
257 256
     ensure
@@ -270,7 +269,6 @@ def committed! #:nodoc:
270 269
     def rolledback!(force_restore_state = false) #:nodoc:
271 270
       run_callbacks :rollback
272 271
     ensure
273  
-      IdentityMap.remove(self) if IdentityMap.enabled?
274 272
       restore_transaction_record_state(force_restore_state)
275 273
     end
276 274
 
1  activerecord/test/cases/associations/eager_load_includes_full_sti_class_test.rb
@@ -27,7 +27,6 @@ def test_class_names
27 27
     post = Namespaced::Post.find_by_title( 'Great stuff', :include => :tagging )
28 28
     assert_nil post.tagging
29 29
 
30  
-    ActiveRecord::IdentityMap.clear
31 30
     ActiveRecord::Base.store_full_sti_class = true
32 31
     post = Namespaced::Post.find_by_title( 'Great stuff', :include => :tagging )
33 32
     assert_instance_of Tagging, post.tagging
20  activerecord/test/cases/associations/eager_test.rb
@@ -197,7 +197,7 @@ def test_finding_with_includes_on_has_one_assocation_with_same_include_includes_
197 197
     author = authors(:david)
198 198
     post = author.post_about_thinking_with_last_comment
199 199
     last_comment = post.last_comment
200  
-    author = assert_queries(ActiveRecord::IdentityMap.enabled? ? 2 : 3) { Author.find(author.id, :include => {:post_about_thinking_with_last_comment => :last_comment})} # find the author, then find the posts, then find the comments
  200
+    author = assert_queries(3) { Author.find(author.id, :include => {:post_about_thinking_with_last_comment => :last_comment})} # find the author, then find the posts, then find the comments
201 201
     assert_no_queries do
202 202
       assert_equal post, author.post_about_thinking_with_last_comment
203 203
       assert_equal last_comment, author.post_about_thinking_with_last_comment.last_comment
@@ -208,7 +208,7 @@ def test_finding_with_includes_on_belongs_to_association_with_same_include_inclu
208 208
     post = posts(:welcome)
209 209
     author = post.author
210 210
     author_address = author.author_address
211  
-    post = assert_queries(ActiveRecord::IdentityMap.enabled? ? 2 : 3) { Post.find(post.id, :include => {:author_with_address => :author_address}) } # find the post, then find the author, then find the address
  211
+    post = assert_queries(3) { Post.find(post.id, :include => {:author_with_address => :author_address}) } # find the post, then find the author, then find the address
212 212
     assert_no_queries do
213 213
       assert_equal author, post.author_with_address
214 214
       assert_equal author_address, post.author_with_address.author_address
@@ -611,9 +611,9 @@ def test_eager_with_has_and_belongs_to_many_and_limit
611 611
     assert posts[1].categories.include?(categories(:general))
612 612
   end
613 613
 
614  
-  # This is only really relevant when the identity map is off. Since the preloader for habtm
615  
-  # gets raw row hashes from the database and then instantiates them, this test ensures that
616  
-  # it only instantiates one actual object per record from the database.
  614
+  # Since the preloader for habtm gets raw row hashes from the database and then
  615
+  # instantiates them, this test ensures that it only instantiates one actual
  616
+  # object per record from the database.
617 617
   def test_has_and_belongs_to_many_should_not_instantiate_same_records_multiple_times
618 618
     welcome    = posts(:welcome)
619 619
     categories = Category.includes(:posts)
@@ -1002,18 +1002,18 @@ def test_eager_loading_with_conditions_on_joined_table_preloads
1002 1002
     assert_equal [posts(:welcome)], posts
1003 1003
     assert_equal authors(:david), assert_no_queries { posts[0].author}
1004 1004
 
1005  
-    posts = assert_queries(ActiveRecord::IdentityMap.enabled? ? 1 : 2) do
  1005
+    posts = assert_queries(2) do
1006 1006
       Post.find(:all, :select => 'distinct posts.*', :include => :author, :joins => [:comments], :conditions => "comments.body like 'Thank you%'", :order => 'posts.id')
1007 1007
     end
1008 1008
     assert_equal [posts(:welcome)], posts
1009 1009
     assert_equal authors(:david), assert_no_queries { posts[0].author}
1010 1010
 
1011  
-    posts = assert_queries(ActiveRecord::IdentityMap.enabled? ? 1 : 2) do
  1011
+    posts = assert_queries(2) do
1012 1012
       Post.find(:all, :include => :author, :joins => {:taggings => :tag}, :conditions => "tags.name = 'General'", :order => 'posts.id')
1013 1013
     end
1014 1014
     assert_equal posts(:welcome, :thinking), posts
1015 1015
 
1016  
-    posts = assert_queries(ActiveRecord::IdentityMap.enabled? ? 1 : 2) do
  1016
+    posts = assert_queries(2) do
1017 1017
       Post.find(:all, :include => :author, :joins => {:taggings => {:tag => :taggings}}, :conditions => "taggings_tags.super_tag_id=2", :order => 'posts.id')
1018 1018
     end
1019 1019
     assert_equal posts(:welcome, :thinking), posts
@@ -1027,7 +1027,7 @@ def test_eager_loading_with_conditions_on_string_joined_table_preloads
1027 1027
     assert_equal [posts(:welcome)], posts
1028 1028
     assert_equal authors(:david), assert_no_queries { posts[0].author}
1029 1029
 
1030  
-    posts = assert_queries(ActiveRecord::IdentityMap.enabled? ? 1 : 2) do
  1030
+    posts = assert_queries(2) do
1031 1031
       Post.find(:all, :select => 'distinct posts.*', :include => :author, :joins => ["INNER JOIN comments on comments.post_id = posts.id"], :conditions => "comments.body like 'Thank you%'", :order => 'posts.id')
1032 1032
     end
1033 1033
     assert_equal [posts(:welcome)], posts
@@ -1116,7 +1116,7 @@ def test_preloading_empty_belongs_to
1116 1116
   def test_preloading_empty_belongs_to_polymorphic
1117 1117
     t = Tagging.create!(:taggable_type => 'Post', :taggable_id => Post.maximum(:id) + 1, :tag => tags(:general))
1118 1118
 
1119  
-    tagging = assert_queries(ActiveRecord::IdentityMap.enabled? ? 1 : 2) { Tagging.preload(:taggable).find(t.id) }
  1119
+    tagging = assert_queries(2) { Tagging.preload(:taggable).find(t.id) }
1120 1120
     assert_no_queries { assert_nil tagging.taggable }
1121 1121
   end
1122 1122
 
137  activerecord/test/cases/associations/identity_map_test.rb
... ...
@@ -1,137 +0,0 @@
1  
-require "cases/helper"
2  
-require 'models/author'
3  
-require 'models/post'
4  
-
5  
-if ActiveRecord::IdentityMap.enabled?
6  
-class InverseHasManyIdentityMapTest < ActiveRecord::TestCase
7  
-  fixtures :authors, :posts
8  
-
9  
-  def test_parent_instance_should_be_shared_with_every_child_on_find
10  
-    m = Author.first
11  
-    is = m.posts
12  
-    is.each do |i|
13  
-      assert_equal m.name, i.author.name, "Name of man should be the same before changes to parent instance"
14  
-      m.name = 'Bongo'
15  
-      assert_equal m.name, i.author.name, "Name of man should be the same after changes to parent instance"
16  
-      i.author.name = 'Mungo'
17  
-      assert_equal m.name, i.author.name, "Name of man should be the same after changes to child-owned instance"
18  
-    end
19  
-  end
20  
-
21  
-  def test_parent_instance_should_be_shared_with_eager_loaded_children
22  
-    m = Author.find(:first, :include => :posts)
23  
-    is = m.posts
24  
-    is.each do |i|
25  
-      assert_equal m.name, i.author.name, "Name of man should be the same before changes to parent instance"
26  
-      m.name = 'Bongo'
27  
-      assert_equal m.name, i.author.name, "Name of man should be the same after changes to parent instance"
28  
-      i.author.name = 'Mungo'
29  
-      assert_equal m.name, i.author.name, "Name of man should be the same after changes to child-owned instance"
30  
-    end
31  
-
32  
-    m = Author.find(:first, :include => :posts, :order => 'posts.id')
33  
-    is = m.posts
34  
-    is.each do |i|
35  
-      assert_equal m.name, i.author.name, "Name of man should be the same before changes to parent instance"
36  
-      m.name = 'Bongo'
37  
-      assert_equal m.name, i.author.name, "Name of man should be the same after changes to parent instance"
38  
-      i.author.name = 'Mungo'
39  
-      assert_equal m.name, i.author.name, "Name of man should be the same after changes to child-owned instance"
40  
-    end
41  
-  end
42  
-
43  
-  def test_parent_instance_should_be_shared_with_newly_built_child
44  
-    m = Author.first
45  
-    i = m.posts.build(:title => 'Industrial Revolution Re-enactment', :body => 'Lorem ipsum')
46  
-    assert_not_nil i.author
47  
-    assert_equal m.name, i.author.name, "Name of man should be the same before changes to parent instance"
48  
-    m.name = 'Bongo'
49  
-    assert_equal m.name, i.author.name, "Name of man should be the same after changes to parent instance"
50  
-    i.author.name = 'Mungo'
51  
-    assert_equal m.name, i.author.name, "Name of man should be the same after changes to just-built-child-owned instance"
52  
-  end
53  
-
54  
-  def test_parent_instance_should_be_shared_with_newly_block_style_built_child
55  
-    m = Author.first
56  
-    i = m.posts.build {|ii| ii.title = 'Industrial Revolution Re-enactment'; ii.body = 'Lorem ipsum'}
57  
-    assert_not_nil i.title, "Child attributes supplied to build via blocks should be populated"
58  
-    assert_not_nil i.author
59  
-    assert_equal m.name, i.author.name, "Name of man should be the same before changes to parent instance"
60  
-    m.name = 'Bongo'
61  
-    assert_equal m.name, i.author.name, "Name of man should be the same after changes to parent instance"
62  
-    i.author.name = 'Mungo'
63  
-    assert_equal m.name, i.author.name, "Name of man should be the same after changes to just-built-child-owned instance"
64  
-  end
65  
-
66  
-  def test_parent_instance_should_be_shared_with_newly_created_child
67  
-    m = Author.first
68  
-    i = m.posts.create(:title => 'Industrial Revolution Re-enactment', :body => 'Lorem ipsum')
69  
-    assert_not_nil i.author
70  
-    assert_equal m.name, i.author.name, "Name of man should be the same before changes to parent instance"
71  
-    m.name = 'Bongo'
72  
-    assert_equal m.name, i.author.name, "Name of man should be the same after changes to parent instance"
73  
-    i.author.name = 'Mungo'
74  
-    assert_equal m.name, i.author.name, "Name of man should be the same after changes to newly-created-child-owned instance"
75  
-  end
76  
-
77  
-  def test_parent_instance_should_be_shared_with_newly_created_via_bang_method_child
78  
-    m = Author.first
79  
-    i = m.posts.create!(:title => 'Industrial Revolution Re-enactment', :body => 'Lorem ipsum')
80  
-    assert_not_nil i.author
81  
-    assert_equal m.name, i.author.name, "Name of man should be the same before changes to parent instance"
82  
-    m.name = 'Bongo'
83  
-    assert_equal m.name, i.author.name, "Name of man should be the same after changes to parent instance"
84  
-    i.author.name = 'Mungo'
85  
-    assert_equal m.name, i.author.name, "Name of man should be the same after changes to newly-created-child-owned instance"
86  
-  end
87  
-
88  
-  def test_parent_instance_should_be_shared_with_newly_block_style_created_child
89  
-    m = Author.first
90  
-    i = m.posts.create {|ii| ii.title = 'Industrial Revolution Re-enactment'; ii.body = 'Lorem ipsum'}
91  
-    assert_not_nil i.title, "Child attributes supplied to create via blocks should be populated"
92  
-    assert_not_nil i.author
93  
-    assert_equal m.name, i.author.name, "Name of man should be the same before changes to parent instance"
94  
-    m.name = 'Bongo'
95  
-    assert_equal m.name, i.author.name, "Name of man should be the same after changes to parent instance"
96  
-    i.author.name = 'Mungo'
97  
-    assert_equal m.name, i.author.name, "Name of man should be the same after changes to newly-created-child-owned instance"
98  
-  end
99  
-
100  
-  def test_parent_instance_should_be_shared_with_poked_in_child
101  
-    m = Author.first
102  
-    i = Post.create(:title => 'Industrial Revolution Re-enactment', :body => 'Lorem ipsum')
103  
-    m.posts << i
104  
-    assert_not_nil i.author
105  
-    assert_equal m.name, i.author.name, "Name of man should be the same before changes to parent instance"
106  
-    m.name = 'Bongo'
107  
-    assert_equal m.name, i.author.name, "Name of man should be the same after changes to parent instance"
108  
-    i.author.name = 'Mungo'
109  
-    assert_equal m.name, i.author.name, "Name of man should be the same after changes to newly-created-child-owned instance"
110  
-  end
111  
-
112  
-  def test_parent_instance_should_be_shared_with_replaced_via_accessor_children
113  
-    m = Author.first
114  
-    i = Post.new(:title => 'Industrial Revolution Re-enactment', :body => 'Lorem ipsum')
115  
-    m.posts = [i]
116  
-    assert_same m, i.author
117  
-    assert_not_nil i.author
118  
-    assert_equal m.name, i.author.name, "Name of man should be the same before changes to parent instance"
119  
-    m.name = 'Bongo'
120  
-    assert_equal m.name, i.author.name, "Name of man should be the same after changes to parent instance"
121  
-    i.author.name = 'Mungo'
122  
-    assert_equal m.name, i.author.name, "Name of man should be the same after changes to replaced-child-owned instance"
123  
-  end
124  
-
125  
-  def test_parent_instance_should_be_shared_with_replaced_via_method_children
126  
-    m = Author.first
127  
-    i = Post.new(:title => 'Industrial Revolution Re-enactment', :body => 'Lorem ipsum')
128  
-    m.posts = [i]
129  
-    assert_not_nil i.author
130  
-    assert_equal m.name, i.author.name, "Name of man should be the same before changes to parent instance"
131  
-    m.name = 'Bongo'
132  
-    assert_equal m.name, i.author.name, "Name of man should be the same after changes to parent instance"
133  
-    i.author.name = 'Mungo'
134  
-    assert_equal m.name, i.author.name, "Name of man should be the same after changes to replaced-child-owned instance"
135  
-  end
136  
-end
137  
-end
8  activerecord/test/cases/autosave_association_test.rb
@@ -978,10 +978,7 @@ def test_should_allow_to_bypass_validations_on_associated_models_at_any_depth
978 978
     values = [@pirate.reload.catchphrase, @pirate.ship.name, *@pirate.ship.parts.map(&:name)]
979 979
     # Oracle saves empty string as NULL
980 980
     if current_adapter?(:OracleAdapter)
981  
-      expected = ActiveRecord::IdentityMap.enabled? ?
982  
-        [nil, nil, '', ''] :
983  
-        [nil, nil, nil, nil]
984  
-      assert_equal expected, values
  981
+      assert_equal [nil, nil, nil, nil], values
985 982
     else
986 983
       assert_equal ['', '', '', ''], values
987 984
     end
@@ -1077,8 +1074,7 @@ def test_should_still_allow_to_bypass_validations_on_the_associated_model
1077 1074
     @ship.save(:validate => false)
1078 1075
     # Oracle saves empty string as NULL
1079 1076
     if current_adapter?(:OracleAdapter)
1080  
-      expected = ActiveRecord::IdentityMap.enabled? ?  [nil, ''] : [nil, nil]
1081  
-      assert_equal expected, [@ship.reload.name, @ship.pirate.catchphrase]
  1077
+      assert_equal [nil, nil], [@ship.reload.name, @ship.pirate.catchphrase]
1082 1078
     else
1083 1079
       assert_equal ['', ''], [@ship.reload.name, @ship.pirate.catchphrase]
1084 1080
     end
4  activerecord/test/cases/base_test.rb
@@ -1139,7 +1139,7 @@ def test_geometric_content
1139 1139
       assert g.save
1140 1140
 
1141 1141
       # Reload and check that we have all the geometric attributes.
1142  
-      h = ActiveRecord::IdentityMap.without { Geometric.find(g.id) }
  1142
+      h = Geometric.find(g.id)
1143 1143
 
1144 1144
       assert_equal '(5,6.1)', h.a_point
1145 1145
       assert_equal '[(2,3),(5.5,7)]', h.a_line_segment
@@ -1168,7 +1168,7 @@ def test_geometric_content
1168 1168
       assert g.save
1169 1169
 
1170 1170
       # Reload and check that we have all the geometric attributes.
1171  
-      h = ActiveRecord::IdentityMap.without { Geometric.find(g.id) }
  1171
+      h = Geometric.find(g.id)
1172 1172
 
1173 1173
       assert_equal '(5,6.1)', h.a_point
1174 1174
       assert_equal '[(2,3),(5.5,7)]', h.a_line_segment
3  activerecord/test/cases/helper.rb
@@ -19,9 +19,6 @@
19 19
 # Show backtraces for deprecated behavior for quicker cleanup.
20 20
 ActiveSupport::Deprecation.debug = true
21 21
 
22  
-# Enable Identity Map only when ENV['IM'] is set to "true"
23  
-ActiveRecord::IdentityMap.enabled = (ENV['IM'] == "true")
24  
-
25 22
 # Avoid deprecation warning setting dependent_restrict_raises to false. The default is true
26 23
 ActiveRecord::Base.dependent_restrict_raises = false
27 24
 
74  activerecord/test/cases/identity_map/middleware_test.rb
... ...
@@ -1,74 +0,0 @@
1  
-require "cases/helper"
2  
-require "rack"
3  
-
4  
-module ActiveRecord
5  
-  module IdentityMap
6  
-    class MiddlewareTest < ActiveRecord::TestCase
7  
-      def setup
8  
-        super
9  
-        @enabled = IdentityMap.enabled
10  
-        IdentityMap.enabled = false
11  
-      end
12  
-
13  
-      def teardown
14  
-        super
15  
-        IdentityMap.enabled = @enabled
16  
-        IdentityMap.clear
17  
-      end
18  
-
19  
-      def test_delegates
20  
-        called = false
21  
-        mw = Middleware.new lambda { |env|
22  
-          called = true
23  
-          [200, {}, nil]
24  
-        }
25  
-        mw.call({})
26  
-        assert called, 'middleware delegated'
27  
-      end
28  
-
29  
-      def test_im_enabled_during_delegation
30  
-        mw = Middleware.new lambda { |env|
31  
-          assert IdentityMap.enabled?, 'identity map should be enabled'
32  
-          [200, {}, nil]
33  
-        }
34  
-        mw.call({})
35  
-      end
36  
-
37  
-      class Enum < Struct.new(:iter)
38  
-        def each(&b)
39  
-          iter.call(&b)
40  
-        end
41  
-      end
42  
-
43  
-      def test_im_enabled_during_body_each
44  
-        mw = Middleware.new lambda { |env|
45  
-          [200, {}, Enum.new(lambda { |&b|
46  
-            assert IdentityMap.enabled?, 'identity map should be enabled'
47  
-            b.call "hello"
48  
-          })]
49  
-        }
50  
-        body = mw.call({}).last
51  
-        body.each { |x| assert_equal 'hello', x }
52  
-      end
53  
-
54  
-      def test_im_disabled_after_body_close
55  
-        mw = Middleware.new lambda { |env| [200, {}, []] }
56  
-        body = mw.call({}).last
57  
-        assert IdentityMap.enabled?, 'identity map should be enabled'
58  
-        body.close
59  
-        assert !IdentityMap.enabled?, 'identity map should be disabled'
60  
-      end
61  
-
62  
-      def test_im_cleared_after_body_close
63  
-        mw = Middleware.new lambda { |env| [200, {}, []] }
64  
-        body = mw.call({}).last
65  
-
66  
-        IdentityMap.repository['hello'] = 'world'
67  
-        assert !IdentityMap.repository.empty?, 'repo should not be empty'
68  
-
69  
-        body.close
70  
-        assert IdentityMap.repository.empty?, 'repo should be empty'
71  
-      end
72  
-    end
73  
-  end
74  
-end
439  activerecord/test/cases/identity_map_test.rb
... ...
@@ -1,439 +0,0 @@
1  
-require "cases/helper"
2  
-
3  
-require 'models/developer'
4  
-require 'models/project'
5  
-require 'models/company'
6  
-require 'models/topic'
7  
-require 'models/reply'
8  
-require 'models/computer'
9  
-require 'models/customer'
10  
-require 'models/order'
11  
-require 'models/post'
12  
-require 'models/author'
13  
-require 'models/tag'
14  
-require 'models/tagging'
15  
-require 'models/comment'
16  
-require 'models/sponsor'
17  
-require 'models/member'
18  
-require 'models/essay'
19  
-require 'models/subscriber'
20  
-require "models/pirate"
21  
-require "models/bird"
22  
-require "models/parrot"
23  
-
24  
-if ActiveRecord::IdentityMap.enabled?
25  
-class IdentityMapTest < ActiveRecord::TestCase
26  
-  fixtures :accounts, :companies, :developers, :projects, :topics,
27  
-    :developers_projects, :computers, :authors, :author_addresses,
28  
-    :posts, :tags, :taggings, :comments, :subscribers
29  
-
30  
-  ##############################################################################
31  
-  # Basic tests checking if IM is functioning properly on basic find operations#
32  
-  ##############################################################################
33  
-
34  
-  def test_find_id
35  
-    assert_same(Client.find(3), Client.find(3))
36  
-  end
37  
-
38  
-  def test_find_id_without_identity_map
39  
-    ActiveRecord::IdentityMap.without do
40  
-      assert_not_same(Client.find(3), Client.find(3))
41  
-    end
42  
-  end
43  
-
44  
-  def test_find_id_use_identity_map
45  
-    ActiveRecord::IdentityMap.enabled = false
46  
-    ActiveRecord::IdentityMap.use do
47  
-      assert_same(Client.find(3), Client.find(3))
48  
-    end
49  
-    ActiveRecord::IdentityMap.enabled = true
50  
-  end
51  
-
52  
-  def test_find_pkey
53  
-    assert_same(
54  
-      Subscriber.find('swistak'),
55  
-      Subscriber.find('swistak')
56  
-    )
57  
-  end
58  
-
59  
-  def test_find_by_id
60  
-    assert_same(
61  
-      Client.find_by_id(3),
62  
-      Client.find_by_id(3)
63  
-    )
64  
-  end
65  
-
66  
-  def test_find_by_string_and_numeric_id
67  
-    assert_same(
68  
-      Client.find_by_id("3"),
69  
-      Client.find_by_id(3)
70  
-    )
71  
-  end
72  
-
73  
-  def test_find_by_pkey
74  
-    assert_same(
75  
-      Subscriber.find_by_nick('swistak'),
76  
-      Subscriber.find_by_nick('swistak')
77  
-    )
78  
-  end
79  
-
80  
-  def test_find_first_id
81  
-    assert_same(
82  
-      Client.find(:first, :conditions => {:id => 1}),
83  
-      Client.find(:first, :conditions => {:id => 1})
84  
-    )
85  
-  end
86  
-
87  
-  def test_find_first_pkey
88  
-    assert_same(
89  
-      Subscriber.find(:first, :conditions => {:nick => 'swistak'}),
90  
-      Subscriber.find(:first, :conditions => {:nick => 'swistak'})
91  
-    )
92  
-  end
93  
-
94  
-  def test_queries_are_not_executed_when_finding_by_id
95  
-    Post.find 1
96  
-    assert_no_queries do
97  
-      Post.find 1
98  
-    end
99  
-  end
100  
-
101  
-  ##############################################################################
102  
-  # Tests checking if IM is functioning properly on more advanced finds        #
103  
-  # and associations                                                           #
104  
-  ##############################################################################
105  
-
106  
-  def test_owner_object_is_associated_from_identity_map
107  
-    post = Post.find(1)
108  
-    comment = post.comments.first
109  
-
110  
-    assert_no_queries do
111  
-      comment.post
112  
-    end
113  
-    assert_same post, comment.post
114  
-  end
115  
-
116  
-  def test_associated_object_are_assigned_from_identity_map
117  
-    post = Post.find(1)
118  
-
119  
-    post.comments.each do |comment|
120  
-      assert_same post, comment.post
121  
-      assert_equal post.object_id, comment.post.object_id
122  
-    end
123  
-  end
124  
-
125  
-  def test_creation
126  
-    t1 = Topic.create("title" => "t1")
127  
-    t2 = Topic.find(t1.id)
128  
-    assert_same(t1, t2)
129  
-  end
130  
-
131  
-  ##############################################################################
132  
-  # Tests checking if IM is functioning properly on classes with multiple      #
133  
-  # types of inheritance                                                       #
134  
-  ##############################################################################
135  
-
136  
-  def test_inherited_without_type_attribute_without_identity_map
137  
-    ActiveRecord::IdentityMap.without do
138  
-      p1 = DestructivePirate.create!(:catchphrase => "I'm not a regular Pirate")
139  
-      p2 = Pirate.find(p1.id)
140  
-      assert_not_same(p1, p2)
141  
-    end
142  
-  end
143  
-
144  
-  def test_inherited_with_type_attribute_without_identity_map
145  
-    ActiveRecord::IdentityMap.without do
146  
-      c = comments(:sub_special_comment)
147  
-      c1 = SubSpecialComment.find(c.id)
148  
-      c2 = Comment.find(c.id)
149  
-      assert_same(c1.class, c2.class)
150  
-    end
151  
-  end
152  
-
153  
-  def test_inherited_without_type_attribute
154  
-    p1 = DestructivePirate.create!(:catchphrase => "I'm not a regular Pirate")
155  
-    p2 = Pirate.find(p1.id)
156  
-    assert_not_same(p1, p2)
157  
-  end
158  
-
159  
-  def test_inherited_with_type_attribute
160  
-    c = comments(:sub_special_comment)
161  
-    c1 = SubSpecialComment.find(c.id)
162  
-    c2 = Comment.find(c.id)
163  
-    assert_same(c1, c2)
164  
-  end
165  
-
166  
-  ##############################################################################
167  
-  # Tests checking dirty attribute behavior with IM                            #
168  
-  ##############################################################################
169  
-
170  
-  def test_loading_new_instance_should_not_update_dirty_attributes
171  
-    swistak = Subscriber.find(:first, :conditions => {:nick => 'swistak'})
172  
-    swistak.name = "Swistak Sreberkowiec"
173  
-    assert_equal(["name"], swistak.changed)
174  
-    assert_equal({"name" => ["Marcin Raczkowski", "Swistak Sreberkowiec"]}, swistak.changes)
175  
-
176  
-    assert swistak.name_changed?
177  
-    assert_equal("Swistak Sreberkowiec", swistak.name)
178  
-  end
179  
-
180  
-  def test_loading_new_instance_should_change_dirty_attribute_original_value
181  
-    swistak = Subscriber.find(:first, :conditions => {:nick => 'swistak'})
182  
-    swistak.name = "Swistak Sreberkowiec"
183  
-
184  
-    Subscriber.update_all({:name => "Raczkowski Marcin"}, {:name => "Marcin Raczkowski"})
185  
-
186  
-    assert_equal({"name"=>["Marcin Raczkowski", "Swistak Sreberkowiec"]}, swistak.changes)
187  
-    assert_equal("Swistak Sreberkowiec", swistak.name)
188  
-  end
189  
-
190  
-  def test_loading_new_instance_should_remove_dirt
191  
-    swistak = Subscriber.find(:first, :conditions => {:nick => 'swistak'})
192  
-    swistak.name = "Swistak Sreberkowiec"
193  
-
194  
-    assert_equal({"name" => ["Marcin Raczkowski", "Swistak Sreberkowiec"]}, swistak.changes)
195  
-
196  
-    Subscriber.update_all({:name => "Swistak Sreberkowiec"}, {:name => "Marcin Raczkowski"})
197  
-
198  
-    assert_equal("Swistak Sreberkowiec", swistak.name)
199  
-    assert_equal({"name"=>["Marcin Raczkowski", "Swistak Sreberkowiec"]}, swistak.changes)
200  
-    assert swistak.name_changed?
201  
-  end
202  
-
203  
-  def test_has_many_associations
204  
-    pirate = Pirate.create!(:catchphrase => "Don' botharrr talkin' like one, savvy?")
205  
-    pirate.birds.create!(:name => 'Posideons Killer')
206  
-    pirate.birds.create!(:name => 'Killer bandita Dionne')
207  
-
208  
-    posideons, _ = pirate.birds
209  
-
210  
-    pirate.reload
211  
-
212  
-    pirate.birds_attributes = [{ :id => posideons.id, :name => 'Grace OMalley' }]
213  
-    assert_equal 'Grace OMalley', pirate.birds.to_a.find { |r| r.id == posideons.id }.name
214  
-  end
215  
-
216  
-  def test_changing_associations
217  
-    post1 = Post.create("title" => "One post", "body" => "Posting...")
218  
-    post2 = Post.create("title" => "Another post", "body" => "Posting... Again...")
219  
-    comment = Comment.new("body" => "comment")
220  
-
221  
-    comment.post = post1
222  
-    assert comment.save
223  
-
224  
-    assert_same(post1.comments.first, comment)
225  
-
226  
-    comment.post = post2
227  
-    assert comment.save
228  
-
229  
-    assert_same(post2.comments.first, comment)