# HG changeset patch # User Alessio Caiazza # Date 1266059225 -3600 # Node ID 356177366517d4f88605867faceeff6ee8a9c210 # Parent 3ed2e6884cb2a9863b993d38f002f04925e63184 fix the access to collection_singular_ids and allows to use collection.includes?(obj) with SigleTableInheritance w/out :select => :type Accessing collection_singular_ids with Rails 2.3.4 no longer causes the loaded? NoMethodError. If you use a collection with SigleTableInheritance and with :select option, but you didn't select the type attribute, the collection.include?(obj) method will not find any inherited object. diff -r 3ed2e6884cb2a9863b993d38f002f04925e63184 -r 356177366517d4f88605867faceeff6ee8a9c210 has_and_belongs_to_many_with_deferred_save/lib/has_and_belongs_to_many_with_deferred_save.rb --- a/has_and_belongs_to_many_with_deferred_save/lib/has_and_belongs_to_many_with_deferred_save.rb Fri Feb 12 19:45:26 2010 +0100 +++ b/has_and_belongs_to_many_with_deferred_save/lib/has_and_belongs_to_many_with_deferred_save.rb Sat Feb 13 12:07:05 2010 +0100 @@ -20,6 +20,7 @@ def has_and_belongs_to_many_with_deferred_save(*args) has_and_belongs_to_many *args collection_name = args[0].to_s + collection_singular_ids = collection_name.singularize + "_ids" attr_accessor :"unsaved_#{collection_name}" attr_accessor :"use_original_collection_reader_behavior_for_#{collection_name}" @@ -43,6 +44,19 @@ alias_method_chain :"#{collection_name}=", 'deferred_save' alias_method_chain :"#{collection_name}", 'deferred_save' + define_method "#{collection_singular_ids}_with_deferred_save" do |*args| + if self.send("use_original_collection_reader_behavior_for_#{collection_name}") + self.send("#{collection_singular_ids}_without_deferred_save") + else + if self.send("unsaved_#{collection_name}").nil? + send("initialize_unsaved_#{collection_name}", *args) + end + self.send("unsaved_#{collection_name}").map { |e| e[:id] } + end + end + + alias_method_chain :"#{collection_singular_ids}", 'deferred_save' + define_method "before_save_with_deferred_save_for_#{collection_name}" do # Question: Why do we need this @use_original_collection_reader_behavior stuff? @@ -90,7 +104,23 @@ # Important: If we don't use clone, then it does an assignment by reference and any changes to unsaved_collection # will also change *collection_without_deferred_save*! (Not what we want! Would result in us saving things # immediately, which is exactly what we're trying to avoid.) + + # trick collection_name.include?(obj) + # If you use a collection of SignelTableInheritance and didn't :select 'type' the + # include? method will not find any subclassed object. + class << eval("@unsaved_#{collection_name}") + def include_with_deferred_save?(obj) + if self.find { |itm| itm == obj || (itm[:id] == obj[:id] && obj.is_a?(itm.class) ) } + return true + else + return false + end + end + alias_method_chain :include?, 'deferred_save' + end end + private :"initialize_unsaved_#{collection_name}" + end end end