From a8dd21d8b459ce4d57160a359798c577085a95e9 Mon Sep 17 00:00:00 2001 From: Carlos Antonio da Silva Date: Fri, 2 Mar 2012 00:10:06 -0300 Subject: Remove IdentityMap --- activerecord/lib/active_record.rb | 1 - .../lib/active_record/associations/association.rb | 13 +- .../lib/active_record/attribute_methods/dirty.rb | 5 - .../lib/active_record/autosave_association.rb | 6 - activerecord/lib/active_record/counter_cache.rb | 2 - activerecord/lib/active_record/fixtures.rb | 4 +- activerecord/lib/active_record/identity_map.rb | 144 --------------------- activerecord/lib/active_record/inheritance.rb | 23 +--- activerecord/lib/active_record/model.rb | 1 - activerecord/lib/active_record/persistence.rb | 16 +-- activerecord/lib/active_record/railtie.rb | 5 - activerecord/lib/active_record/relation.rb | 11 +- .../lib/active_record/relation/finder_methods.rb | 10 -- activerecord/lib/active_record/test_case.rb | 10 -- activerecord/lib/active_record/transactions.rb | 2 - 15 files changed, 10 insertions(+), 243 deletions(-) delete mode 100644 activerecord/lib/active_record/identity_map.rb (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record.rb b/activerecord/lib/active_record.rb index 73c8a06ab7..0cb0644bcf 100644 --- a/activerecord/lib/active_record.rb +++ b/activerecord/lib/active_record.rb @@ -65,7 +65,6 @@ module ActiveRecord autoload :DynamicFinderMatch autoload :DynamicScopeMatch autoload :Explain - autoload :IdentityMap autoload :Inheritance autoload :Integration autoload :Migration diff --git a/activerecord/lib/active_record/associations/association.rb b/activerecord/lib/active_record/associations/association.rb index 512c52338e..fb0ca15c23 100644 --- a/activerecord/lib/active_record/associations/association.rb +++ b/activerecord/lib/active_record/associations/association.rb @@ -45,7 +45,6 @@ module ActiveRecord # Resets the \loaded flag to +false+ and sets the \target to +nil+. def reset @loaded = false - IdentityMap.remove(target) if IdentityMap.enabled? && target @target = nil end @@ -135,17 +134,7 @@ module ActiveRecord # ActiveRecord::RecordNotFound is rescued within the method, and it is # not reraised. The proxy is \reset and +nil+ is the return value. def load_target - if find_target? - begin - if IdentityMap.enabled? && association_class && association_class.respond_to?(:base_class) - @target = IdentityMap.get(association_class, owner[reflection.foreign_key]) - end - rescue NameError - nil - ensure - @target ||= find_target - end - end + @target ||= find_target if find_target? loaded! unless loaded? target rescue ActiveRecord::RecordNotFound diff --git a/activerecord/lib/active_record/attribute_methods/dirty.rb b/activerecord/lib/active_record/attribute_methods/dirty.rb index 3a737e5b35..11c63591e3 100644 --- a/activerecord/lib/active_record/attribute_methods/dirty.rb +++ b/activerecord/lib/active_record/attribute_methods/dirty.rb @@ -22,8 +22,6 @@ module ActiveRecord if status = super @previously_changed = changes @changed_attributes.clear - elsif IdentityMap.enabled? - IdentityMap.remove(self) end status end @@ -34,9 +32,6 @@ module ActiveRecord @previously_changed = changes @changed_attributes.clear end - rescue - IdentityMap.remove(self) if IdentityMap.enabled? - raise end # reload the record and clears changed attributes. diff --git a/activerecord/lib/active_record/autosave_association.rb b/activerecord/lib/active_record/autosave_association.rb index eb3ae7014e..be0af081d1 100644 --- a/activerecord/lib/active_record/autosave_association.rb +++ b/activerecord/lib/active_record/autosave_association.rb @@ -328,7 +328,6 @@ module ActiveRecord autosave = reflection.options[:autosave] if records = associated_records_to_validate_or_save(association, @new_record_before_save, autosave) - begin records.each do |record| next if record.destroyed? @@ -348,11 +347,6 @@ module ActiveRecord raise ActiveRecord::Rollback unless saved end - rescue - records.each {|x| IdentityMap.remove(x) } if IdentityMap.enabled? - raise - end - end # reconstruct the scope now that we know the owner's id diff --git a/activerecord/lib/active_record/counter_cache.rb b/activerecord/lib/active_record/counter_cache.rb index 8d5388e1f3..f52979ebd9 100644 --- a/activerecord/lib/active_record/counter_cache.rb +++ b/activerecord/lib/active_record/counter_cache.rb @@ -69,8 +69,6 @@ module ActiveRecord "#{quoted_column} = COALESCE(#{quoted_column}, 0) #{operator} #{value.abs}" end - IdentityMap.remove_by_id(symbolized_base_class, id) if IdentityMap.enabled? - update_all(updates.join(', '), primary_key => id) end diff --git a/activerecord/lib/active_record/fixtures.rb b/activerecord/lib/active_record/fixtures.rb index b82d5b5621..5c42e8f719 100644 --- a/activerecord/lib/active_record/fixtures.rb +++ b/activerecord/lib/active_record/fixtures.rb @@ -796,9 +796,7 @@ module ActiveRecord @fixture_cache[fixture_name].delete(fixture) if force_reload if @loaded_fixtures[fixture_name][fixture.to_s] - ActiveRecord::IdentityMap.without do - @fixture_cache[fixture_name][fixture] ||= @loaded_fixtures[fixture_name][fixture.to_s].find - end + @fixture_cache[fixture_name][fixture] ||= @loaded_fixtures[fixture_name][fixture.to_s].find else raise StandardError, "No entry named '#{fixture}' found for fixture collection '#{fixture_name}'" end diff --git a/activerecord/lib/active_record/identity_map.rb b/activerecord/lib/active_record/identity_map.rb deleted file mode 100644 index d9777bb2f6..0000000000 --- a/activerecord/lib/active_record/identity_map.rb +++ /dev/null @@ -1,144 +0,0 @@ -module ActiveRecord - # = Active Record Identity Map - # - # Ensures that each object gets loaded only once by keeping every loaded - # object in a map. Looks up objects using the map when referring to them. - # - # More information on Identity Map pattern: - # http://www.martinfowler.com/eaaCatalog/identityMap.html - # - # == Configuration - # - # In order to enable IdentityMap, set config.active_record.identity_map = true - # in your config/application.rb file. - # - # IdentityMap is disabled by default and still in development (i.e. use it with care). - # - # == Associations - # - # Active Record Identity Map does not track associations yet. For example: - # - # comment = @post.comments.first - # comment.post = nil - # @post.comments.include?(comment) #=> true - # - # Ideally, the example above would return false, removing the comment object from the - # post association when the association is nullified. This may cause side effects, as - # in the situation below, if Identity Map is enabled: - # - # Post.has_many :comments, :dependent => :destroy - # - # comment = @post.comments.first - # comment.post = nil - # comment.save - # Post.destroy(@post.id) - # - # Without using Identity Map, the code above will destroy the @post object leaving - # the comment object intact. However, once we enable Identity Map, the post loaded - # by Post.destroy is exactly the same object as the object @post. As the object @post - # still has the comment object in @post.comments, once Identity Map is enabled, the - # comment object will be accidently removed. - # - # This inconsistency is meant to be fixed in future Rails releases. - # - module IdentityMap - - class << self - def enabled=(flag) - Thread.current[:identity_map_enabled] = flag - end - - def enabled - Thread.current[:identity_map_enabled] - end - alias enabled? enabled - - def repository - Thread.current[:identity_map] ||= Hash.new { |h,k| h[k] = {} } - end - - def use - old, self.enabled = enabled, true - - yield if block_given? - ensure - self.enabled = old - clear - end - - def without - old, self.enabled = enabled, false - - yield if block_given? - ensure - self.enabled = old - end - - def get(klass, primary_key) - record = repository[klass.symbolized_sti_name][primary_key] - - if record.is_a?(klass) - ActiveSupport::Notifications.instrument("identity.active_record", - :line => "From Identity Map (id: #{primary_key})", - :name => "#{klass} Loaded", - :connection_id => object_id) - - record - else - nil - end - end - - def add(record) - repository[record.class.symbolized_sti_name][record.id] = record - end - - def remove(record) - repository[record.class.symbolized_sti_name].delete(record.id) - end - - def remove_by_id(symbolized_sti_name, id) - repository[symbolized_sti_name].delete(id) - end - - def clear - repository.clear - end - end - - # Reinitialize an Identity Map model object from +coder+. - # +coder+ must contain the attributes necessary for initializing an empty - # model object. - def reinit_with(coder) - @attributes_cache = {} - dirty = @changed_attributes.keys - attributes = self.class.initialize_attributes(coder['attributes'].except(*dirty)) - @attributes.update(attributes) - @changed_attributes.update(coder['attributes'].slice(*dirty)) - @changed_attributes.delete_if{|k,v| v.eql? @attributes[k]} - - run_callbacks :find - - self - end - - class Middleware - def initialize(app) - @app = app - end - - def call(env) - enabled = IdentityMap.enabled - IdentityMap.enabled = true - - response = @app.call(env) - response[2] = Rack::BodyProxy.new(response[2]) do - IdentityMap.enabled = enabled - IdentityMap.clear - end - - response - end - end - end -end diff --git a/activerecord/lib/active_record/inheritance.rb b/activerecord/lib/active_record/inheritance.rb index 2c766411a0..ebe244c6a6 100644 --- a/activerecord/lib/active_record/inheritance.rb +++ b/activerecord/lib/active_record/inheritance.rb @@ -63,26 +63,9 @@ module ActiveRecord # single-table inheritance model that makes it possible to create # objects of different types from the same table. def instantiate(record, column_types = {}) - sti_class = find_sti_class(record[inheritance_column]) - record_id = sti_class.primary_key && record[sti_class.primary_key] - - if ActiveRecord::IdentityMap.enabled? && record_id - if (column = sti_class.columns_hash[sti_class.primary_key]) && column.number? - record_id = record_id.to_i - end - if instance = IdentityMap.get(sti_class, record_id) - instance.reinit_with('attributes' => record) - else - instance = sti_class.allocate.init_with('attributes' => record) - IdentityMap.add(instance) - end - else - column_types = sti_class.decorate_columns(column_types) - instance = sti_class.allocate.init_with('attributes' => record, - 'column_types' => column_types) - end - - instance + sti_class = find_sti_class(record[inheritance_column]) + column_types = sti_class.decorate_columns(column_types) + sti_class.allocate.init_with('attributes' => record, 'column_types' => column_types) end # For internal use. diff --git a/activerecord/lib/active_record/model.rb b/activerecord/lib/active_record/model.rb index 86de5ab2fa..105d1e0e2b 100644 --- a/activerecord/lib/active_record/model.rb +++ b/activerecord/lib/active_record/model.rb @@ -60,7 +60,6 @@ module ActiveRecord include AttributeMethods include Callbacks, ActiveModel::Observing, Timestamp include Associations - include IdentityMap include ActiveModel::SecurePassword include AutosaveAssociation, NestedAttributes include Aggregations, Transactions, Reflection, Serialization, Store diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb index 09502bb52c..35c922e979 100644 --- a/activerecord/lib/active_record/persistence.rb +++ b/activerecord/lib/active_record/persistence.rb @@ -115,10 +115,7 @@ module ActiveRecord # callbacks, Observer methods, or any :dependent association # options, use #destroy. def delete - if persisted? - self.class.delete(id) - IdentityMap.remove(self) if IdentityMap.enabled? - end + self.class.delete(id) if persisted? @destroyed = true freeze end @@ -129,7 +126,6 @@ module ActiveRecord destroy_associations if persisted? - IdentityMap.remove(self) if IdentityMap.enabled? pk = self.class.primary_key column = self.class.columns_hash[pk] substitute = connection.substitute_at(column, 0) @@ -284,11 +280,9 @@ module ActiveRecord clear_aggregation_cache clear_association_cache - IdentityMap.without do - fresh_object = self.class.unscoped { self.class.find(id, options) } - @attributes.update(fresh_object.instance_variable_get('@attributes')) - @columns_hash = fresh_object.instance_variable_get('@columns_hash') - end + fresh_object = self.class.unscoped { self.class.find(id, options) } + @attributes.update(fresh_object.instance_variable_get('@attributes')) + @columns_hash = fresh_object.instance_variable_get('@columns_hash') @attributes_cache = {} self @@ -363,10 +357,8 @@ module ActiveRecord attributes_values = arel_attributes_with_values_for_create(!id.nil?) new_id = self.class.unscoped.insert attributes_values - self.id ||= new_id if self.class.primary_key - IdentityMap.add(self) if IdentityMap.enabled? @new_record = false id end diff --git a/activerecord/lib/active_record/railtie.rb b/activerecord/lib/active_record/railtie.rb index 516c450f85..ee3a6bf8c0 100644 --- a/activerecord/lib/active_record/railtie.rb +++ b/activerecord/lib/active_record/railtie.rb @@ -53,11 +53,6 @@ module ActiveRecord ActiveSupport.on_load(:active_record) { self.logger ||= ::Rails.logger } end - initializer "active_record.identity_map" do |app| - config.app_middleware.insert_after "::ActionDispatch::Callbacks", - "ActiveRecord::IdentityMap::Middleware" if config.active_record.delete(:identity_map) - end - initializer "active_record.set_configs" do |app| ActiveSupport.on_load(:active_record) do if app.config.active_record.delete(:whitelist_attributes) diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 7531e1fe6f..6f39708ec3 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -168,13 +168,7 @@ module ActiveRecord default_scoped = with_default_scope if default_scoped.equal?(self) - @records = if @readonly_value.nil? && !@klass.locking_enabled? - eager_loading? ? find_with_associations : @klass.find_by_sql(arel, @bind_values) - else - IdentityMap.without do - eager_loading? ? find_with_associations : @klass.find_by_sql(arel, @bind_values) - end - end + @records = eager_loading? ? find_with_associations : @klass.find_by_sql(arel, @bind_values) preload = @preload_values preload += @includes_values unless eager_loading? @@ -274,7 +268,6 @@ module ActiveRecord # # The same idea applies to limit and order # Book.where('title LIKE ?', '%Rails%').order(:created_at).limit(5).update_all(:author => 'David') def update_all(updates, conditions = nil, options = {}) - IdentityMap.repository[symbolized_base_class].clear if IdentityMap.enabled? if conditions || options.present? where(conditions).apply_finder_options(options.slice(:limit, :order)).update_all(updates) else @@ -404,7 +397,6 @@ module ActiveRecord # If you need to destroy dependent associations or call your before_* or # +after_destroy+ callbacks, use the +destroy_all+ method instead. def delete_all(conditions = nil) - IdentityMap.repository[symbolized_base_class] = {} if IdentityMap.enabled? if conditions where(conditions).delete_all else @@ -437,7 +429,6 @@ module ActiveRecord # # Delete multiple rows # Todo.delete([2,3,4]) def delete(id_or_array) - IdentityMap.remove_by_id(self.symbolized_base_class, id_or_array) if IdentityMap.enabled? where(primary_key => id_or_array).delete_all end diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb index adfacf37ee..52e67ecc6e 100644 --- a/activerecord/lib/active_record/relation/finder_methods.rb +++ b/activerecord/lib/active_record/relation/finder_methods.rb @@ -318,17 +318,7 @@ module ActiveRecord def find_one(id) id = id.id if ActiveRecord::Base === id - if IdentityMap.enabled? && where_values.blank? && - limit_value.blank? && order_values.blank? && - includes_values.blank? && preload_values.blank? && - readonly_value.nil? && joins_values.blank? && - !@klass.locking_enabled? && - record = IdentityMap.get(@klass, id) - return record - end - column = columns_hash[primary_key] - substitute = connection.substitute_at(column, @bind_values.length) relation = where(table[primary_key].eq(substitute)) relation.bind_values += [[column, id]] diff --git a/activerecord/lib/active_record/test_case.rb b/activerecord/lib/active_record/test_case.rb index 4d881f0f7d..fcaa4b74a6 100644 --- a/activerecord/lib/active_record/test_case.rb +++ b/activerecord/lib/active_record/test_case.rb @@ -7,20 +7,10 @@ module ActiveRecord # # Defines some test assertions to test against SQL queries. class TestCase < ActiveSupport::TestCase #:nodoc: - setup :cleanup_identity_map - - def setup - cleanup_identity_map - end - def teardown SQLCounter.log.clear end - def cleanup_identity_map - ActiveRecord::IdentityMap.clear - end - def assert_date_from_db(expected, actual, message = nil) # SybaseAdapter doesn't have a separate column type just for dates, # so the time is in the string and incorrectly formatted diff --git a/activerecord/lib/active_record/transactions.rb b/activerecord/lib/active_record/transactions.rb index b492377d18..743dfc5a38 100644 --- a/activerecord/lib/active_record/transactions.rb +++ b/activerecord/lib/active_record/transactions.rb @@ -251,7 +251,6 @@ module ActiveRecord remember_transaction_record_state yield rescue Exception - IdentityMap.remove(self) if IdentityMap.enabled? restore_transaction_record_state raise ensure @@ -270,7 +269,6 @@ module ActiveRecord def rolledback!(force_restore_state = false) #:nodoc: run_callbacks :rollback ensure - IdentityMap.remove(self) if IdentityMap.enabled? restore_transaction_record_state(force_restore_state) end -- cgit v1.2.3