Skip to content
Browse files

cache array in @attributes_cache and detect changes

  • Loading branch information...
1 parent a62fd27 commit bd8fc1e6a34ead0242d219b56be9db3cb2f4f32f @funny-falcon committed Feb 11, 2012
View
2 .gitignore
@@ -1,4 +1,6 @@
*.swo
*.swp
+*gem*
+rdoc
pkg
*~
View
9 README
@@ -38,4 +38,13 @@ Installation
gem install ar_pg_array
+Changelog
+=========
+
+ 0.9.13
+
+ Since version 0.9.13 ar_pg_array will try to detect arrays changed inplace.
+ And parsed arrays are now cached in @attributes_cache.
+ Thanks to Romain Beauxis (https://github.com/toots ) for being insistent about this.
+
Copyright (c) 2010 Sokolov Yura aka funny_falcon, released under the MIT license
View
7 lib/ar_pg_array.rb
@@ -5,8 +5,11 @@
require 'ar_pg_array/schema'
require 'ar_pg_array/schema_cacheable'
require 'ar_pg_array/querying'
+require 'ar_pg_array/allways_save'
require 'ar_pg_array/references_by'
-if defined? ::Arel
+if ActiveRecord::VERSION::MAJOR >= 3
require 'ar_pg_array/schema_arel'
require 'ar_pg_array/querying_arel'
-end
+else
+ require 'ar_pg_array/schema_fix_will_change'
+end
View
38 lib/ar_pg_array/allways_save.rb
@@ -0,0 +1,38 @@
+module ActiveRecord
+ module CheckArrayBeforeUpdate
+ def mark_arrays_for_update
+ @attributes_cache.each do |name, value|
+ attribute_will_change!(name) if Array === value && _read_attribute(name) != value
+ end
+ end
+ end
+ if VERSION::MAJOR < 3
+ module CheckArrayBeforeUpdate
+ def self.included(base)
+ base.alias_method_chain :update, :check_array
+ base.send(:alias_method, :_read_attribute, :read_attribute)
+ end
+
+ def update_with_check_array
+ mark_arrays_for_update
+ update_without_check_array
+ end
+ end
+ else
+ module CheckArrayBeforeUpdate
+ include ActiveSupport::Concern
+
+ if VERSION::MAJOR == 3 && VERSION::MINOR >= 2
+ def _read_attribute(attr_name)
+ column_for_attribute(attr_name).type_cast(@attributes[attr_name])
+ end
+ end
+
+ def update(*)
+ mark_arrays_for_update
+ super
+ end
+ end
+ end
+ Base.__send__ :include, CheckArrayBeforeUpdate
+end
View
11 lib/ar_pg_array/schema_cachable.rb
@@ -0,0 +1,11 @@
+adjust_cached_types = lambda do |atcbd|
+ atcbd << /_array$/
+ def atcbd.include?(val)
+ any?{|type| type === val}
+ end
+end
+if ActiveRecord::VERSION::MAJOR < 3
+ adjust_cached_types.call(ActiveRecord::AttributeMethods::ATTRIBUTE_TYPES_CACHED_BY_DEFAULT)
+else
+ adjust_cached_types.call(ActiveRecord::AttributeMethods::Read::ATTRIBUTE_TYPES_CACHED_BY_DEFAULT)
+end
View
11 lib/ar_pg_array/schema_cacheable.rb
@@ -0,0 +1,11 @@
+adjust_cached_types = lambda do |atcbd|
+ atcbd << /_array$/
+ def atcbd.include?(val)
+ any?{|type| type === val}
+ end
+end
+if ActiveRecord::VERSION::MAJOR < 3
+ adjust_cached_types.call(ActiveRecord::AttributeMethods::ATTRIBUTE_TYPES_CACHED_BY_DEFAULT)
+else
+ adjust_cached_types.call(ActiveRecord::AttributeMethods::Read::ATTRIBUTE_TYPES_CACHED_BY_DEFAULT)
+end
View
13 lib/ar_pg_array/schema_fix_will_change.rb
@@ -0,0 +1,13 @@
+module ActiveRecord
+ module Dirty
+ private
+ def attribute_will_change!(attr)
+ val = changed_attributes[attr] = clone_attribute_value(:read_attribute, attr)
+ if Array === val && !(Array === @attributes[attr])
+ send(attr) unless @attributes_cache.has_key?(attr)
+ @attributes[attr] = @attributes_cache[attr]
+ end
+ val
+ end
+ end
+end
View
23 spec/pg_array_spec.rb
@@ -132,11 +132,24 @@ def ab
end
it "should be cached in @attributes_cache" do
- bulk = Bulk.find(5)
- ar = bulk.texts
- $stderr.puts bulk.instance_variable_get('@attributes_cache').inspect
- $stderr.puts bulk.class.cached_attributes.inspect
- bulk.instance_variable_get('@attributes_cache')['texts'].should.equal?(ar)
+ bulk = Bulk.find(1)
+ ar = bulk.ints
+ bulk.ints.should.equal?(ar)
+ ard = ar.dup
+ arn = (bulk.ints << 1)
+ arn.should.equal?(ar)
+ bulk.ints.should.equal?(ar)
+ bulk.ints.should == (ard + [1])
+ end
+
+ it 'should allways save changed value' do
+ bulk = Bulk.find(1)
+ old = bulk.ints.dup
+ bulk.ints << 2
+ new = bulk.ints.dup
+ bulk.save
+ bulk.reload
+ bulk.ints.should == new
end
def map_times(times)

0 comments on commit bd8fc1e

Please sign in to comment.
Something went wrong with that request. Please try again.