cached_values 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt ADDED
@@ -0,0 +1,3 @@
1
+ === 1.0.0 / 2008-03-06
2
+
3
+ * Converted from a Rails plugin
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2007 [name of plugin creator]
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Manifest.txt ADDED
@@ -0,0 +1,17 @@
1
+ History.txt
2
+ MIT-LICENSE
3
+ Manifest.txt
4
+ README.txt
5
+ Rakefile
6
+ init.rb
7
+ install.rb
8
+ lib/cached_values.rb
9
+ lib/cached_values/cached_value.rb
10
+ lib/cached_values/caches_value.rb
11
+ tasks/cached_values_tasks.rake
12
+ test/database.yml
13
+ test/leprechaun.rb
14
+ test/schema.rb
15
+ test/test_cached_values.rb
16
+ test/test_helper.rb
17
+ uninstall.rb
data/README.txt ADDED
@@ -0,0 +1,66 @@
1
+ = Cached Values
2
+
3
+ * http://github.com/JackDanger/cached_values/
4
+
5
+ A dead-simple way to calculate any value via Ruby or SQL and (optionally) have it saved in a database field.
6
+
7
+ == REQUIREMENTS:
8
+
9
+ * ObjectProxy
10
+
11
+ == INSTALL:
12
+
13
+ * as gem: sudo gem install cached_values
14
+ * as plugin: ./script/plugin install git://github.com/JackDanger/cached_values.git
15
+
16
+ == USAGE:
17
+
18
+ You can calculate values with a single line in any ActiveRecord model. To actually save those values you'll need to create
19
+ an attribute in your schema. By default the cached_value instance will look for an attribute with the same name as itself.
20
+ You can override this by specifying a :cache => :some_attribute option
21
+
22
+ A very simple case in which cached_values works just like the .count method on a has_many association:
23
+
24
+ class Leprechaun < ActiveRecord::Base
25
+ caches_value :total_gold_coins, :sql => 'select count(*) from gold_coins where leprechaun_id = #{id}'
26
+ end
27
+
28
+ Company.find(4).total_employees # => 45
29
+
30
+ A more sophisticated example:
31
+
32
+ class Leprechaun < ActiveRecord::Base
33
+ has_many :lucky_charms
34
+ has_many :deceived_children, :through => :lucky_charms
35
+ caches_value :total_children_remaining_to_be_deceived, :sql => '... very complicated sql here ...'
36
+ end
37
+
38
+ Leprechaun.find(14).total_children_remaining_to_be_deceived # => 6,692,243,122
39
+
40
+ The values can be of any type. The plugin will attempt to cast SQL results to the type corresponding with their database cache
41
+ but calculations in Ruby are left alone.
42
+
43
+ You can also calculate the value in Ruby using a string to be eval'ed or a Proc. Both are evaluated
44
+ in the context of the record instance.
45
+
46
+ class Leprechaun < ActiveRecord::Base
47
+ caches_value :total_gold, :eval => "some_archaic_and_silly_calculation(self.gold_coins)"
48
+ caches_value :total_lucky_charms, :eval => Proc.new {|record| record.calculate_total_lucky_charms }
49
+ end
50
+
51
+ The cache is customizable, you can specify which attribute should be used as a cache:
52
+
53
+ caches_value :runic_formula, :sql => '...' # uses 'full_formula' column if it exists
54
+ caches_value :standard_deviation_of_gold_over_time, # uses 'std' column if it exists
55
+ :sql => '...', :cache => 'std'
56
+ caches_value :id, :sql => '...', :cache => false # does NOT save any cache. This avoids overwriting an attribute
57
+
58
+ ActiveRecord callbacks can be used to call load (make sure the value is in memory), clear (flush the cache and
59
+ delete the instance), or reload (flush cache and reload instance) at certain times:
60
+
61
+ caches_value :standard_deviation, :sql => '...', :reload => [:after_save, :before_validation]
62
+ caches_value :full_formula, :sql => '...', :clear => :after_find
63
+
64
+ Bugs can be filed at http://code.lighthouseapp.com/projects/4502-hoopla-rails-plugins/
65
+
66
+ Copyright (c) 2007 Jack Danger Canty @ http://6brand.com, released under the MIT license
data/Rakefile ADDED
@@ -0,0 +1,17 @@
1
+ # -*- ruby -*-
2
+
3
+ $:.unshift(File.dirname(__FILE__) + '/lib')
4
+ $:.unshift(File.dirname(__FILE__) + '/lib/cached_values')
5
+
6
+
7
+ require 'rubygems'
8
+ require 'hoe'
9
+ require "cached_values"
10
+
11
+ Hoe.new('cached_values', CachedValues::VERSION) do |p|
12
+ p.rubyforge_name = 'cachedvalues' # if different than lowercase project name
13
+ p.remote_rdoc_dir = '' # Release to root
14
+ p.developer('Jack Danger Canty', 'rubygems_cached_values@6brand.com')
15
+ end
16
+
17
+ # vim: syntax=Ruby
data/init.rb ADDED
@@ -0,0 +1,3 @@
1
+ require 'cached_value'
2
+ require 'cached_values'
3
+ ActiveRecord::Base.send :include, CachedValues
data/install.rb ADDED
@@ -0,0 +1 @@
1
+ puts IO.read(File.join(File.dirname(__FILE__), 'README.txt'))
@@ -0,0 +1,145 @@
1
+ require 'object_proxy'
2
+
3
+ module ActiveRecord
4
+ class CachedValue < ObjectProxy
5
+
6
+ def initialize(owner, reflection)
7
+ @owner, @reflection = owner, reflection
8
+ reset
9
+ end
10
+
11
+ def reset
12
+ @target = nil
13
+ @loaded = false
14
+ end
15
+
16
+ def load
17
+ reset
18
+ load_target
19
+ end
20
+
21
+ def reload
22
+ @owner.instance_variable_set("@#{@reflection.name}", nil)
23
+ reset
24
+ @target = find_target(true)
25
+ @owner.send @reflection.name
26
+ end
27
+
28
+ alias update reload
29
+
30
+ def clear
31
+ clear_cache
32
+ @owner.instance_variable_set("@#{@reflection.name}", nil)
33
+ end
34
+
35
+ def loaded?
36
+ @loaded
37
+ end
38
+
39
+ def loaded
40
+ @loaded = true
41
+ end
42
+
43
+ def target
44
+ @target
45
+ end
46
+
47
+ protected
48
+
49
+ def load_target
50
+ return nil unless defined?(@loaded)
51
+ @target = find_target unless loaded?
52
+ @loaded = true
53
+ @target
54
+ end
55
+
56
+ def find_target(skip_cache = false)
57
+ target = find_target_from_cache unless skip_cache
58
+ unless target
59
+ target ||= @reflection.options[:sql] ? find_target_by_sql : find_target_by_eval
60
+ update_cache(target)
61
+ end
62
+ target
63
+ end
64
+
65
+ def find_target_from_cache
66
+ @owner.send(:read_attribute, cache_column) if has_cache?
67
+ end
68
+
69
+ def find_target_by_sql
70
+ sql = sanitize_sql(interpolate_sql(@reflection.options[:sql]))
71
+ result = @owner.class.connection.select_value(sql)
72
+ result = typecast_result(result)
73
+ result
74
+ end
75
+
76
+ def find_target_by_eval
77
+ if @reflection.options[:eval].is_a?(String)
78
+ eval(@reflection.options[:eval], @owner.send(:binding))
79
+ elsif @reflection.options[:eval].is_a?(Proc)
80
+ @reflection.options[:eval].call(@owner)
81
+ elsif @reflection.options[:eval].is_a?(Symbol)
82
+ @owner.send @reflection.options[:eval]
83
+ else
84
+ raise ArgumentError.new("The :eval option on a cached_values must be a String or a Proc or a Symbol")
85
+ end
86
+ end
87
+
88
+ def cache_column
89
+ @reflection.options[:cache]
90
+ end
91
+
92
+ def has_cache?
93
+ @reflection.options[:cache] && @owner.attribute_names.include?(@reflection.options[:cache].to_s)
94
+ end
95
+
96
+ def clear_cache
97
+ update_cache(nil)
98
+ end
99
+
100
+ def update_cache(value)
101
+ return unless has_cache?
102
+ unless @owner.new_record?
103
+ @owner.class.update_all(["#{cache_column} = ?", value], ["id = ?", @owner.id])
104
+ end
105
+ @owner.send(:write_attribute, cache_column, value)
106
+ end
107
+
108
+ def typecast_result(result)
109
+ if has_cache?
110
+ typecast_sql_result_by_cache_column_type(result)
111
+ else
112
+ if result =~ /^\d+\.\d+$/
113
+ result.to_f
114
+ elsif result =~ /^\d+$/
115
+ result.to_i
116
+ else
117
+ result
118
+ end
119
+ end
120
+ end
121
+
122
+ def typecast_sql_result_by_cache_column_type(result)
123
+ type = @owner.column_for_attribute(cache_column).type
124
+ case type
125
+ when :integer
126
+ result.to_i
127
+ when :float
128
+ result.to_f
129
+ when :boolean
130
+ [0,'0', 'NULL', 'nil', 'false', '', 'FALSE', 'False'].include?(result)
131
+ else
132
+ result
133
+ end
134
+ end
135
+
136
+ def interpolate_sql(sql, record = nil)
137
+ @owner.send(:interpolate_sql, sql, record)
138
+ end
139
+
140
+ def sanitize_sql(sql)
141
+ @owner.class.send(:sanitize_sql, sql)
142
+ end
143
+
144
+ end
145
+ end
@@ -0,0 +1,104 @@
1
+ require 'active_record'
2
+ require File.expand_path(File.dirname(__FILE__) + '/cached_value')
3
+
4
+ module CachesValues # :nodoc:
5
+
6
+ def self.included(base)
7
+ unless base.extended_by.include?(CachesValues::ClassMethods)
8
+ base.extend(ClassMethods)
9
+ end
10
+ end
11
+
12
+ module ClassMethods
13
+ # USAGE:
14
+ #
15
+ # a very simple case in which cached_values works just like the .count method on a has_many association:
16
+ #
17
+ # class Company < ActiveRecord::Base
18
+ # caches_value :total_employees, :sql => 'select count(*) from employees where company_id = #{id}'
19
+ # end
20
+ #
21
+ # a more sophisticated example:
22
+ #
23
+ # class User < ActiveRecord::Base
24
+ # has_many :trinkets
25
+ # has_many :sales, :through => :trinkets
26
+ # caches_value :remaining_trinket_sales_allotted, :sql => '... very complicated sql here ...'
27
+ # end
28
+ #
29
+ # user = User.find(:first)
30
+ # user.remaining_trinket_sales_allotted # => 70
31
+ # Trinket.delete_all # <= any operation that would affect our value
32
+ # user.remaining_trinket_sales_allotted # => 70
33
+ # user.remaining_trinket_sales_allotted.reload # => 113
34
+ #
35
+ # You can also calculate the value in Ruby. This can be done by a string to be eval'ed or a Proc. Both are evaluated
36
+ # in the context of the record instance.
37
+ #
38
+ # class User < ActiveRecord::Base
39
+ # caches_value :expensive_calculation, :eval => "some_big_expensize_calculation(self.id)"
40
+ # caches_value :other_expensive_process, :eval => Proc.new {|record| record.other_expensize_process }
41
+ # end
42
+ #
43
+
44
+ def caches_value(name, options = {})
45
+ reflection = create_cached_value_reflection(name, options)
46
+
47
+ configure_dependency_for_cached_value(reflection)
48
+
49
+ reflection.options[:cache] ||= reflection.name unless false == options[:cache]
50
+
51
+ cached_value_accessor_method(reflection, ActiveRecord::CachedValue)
52
+ cached_value_callback_methods(reflection)
53
+ end
54
+
55
+ private
56
+
57
+ def configure_dependency_for_cached_value(reflection)
58
+
59
+ if !reflection.options[:sql] && !reflection.options[:eval]
60
+ raise ArgumentError, "You must specify either the :eval or :sql options for caches_value in #{self.name}"
61
+ end
62
+
63
+ if reflection.options[:sql] && reflection.options[:eval]
64
+ raise ArgumentError, ":eval and :sql are mutually exclusive options. You may specify one or the other for caches_value in #{self.name}"
65
+ end
66
+ end
67
+
68
+ def create_cached_value_reflection(name, options)
69
+ options.assert_valid_keys(:sql, :eval, :cache, :clear, :load, :reload)
70
+
71
+ reflection = ActiveRecord::Reflection::MacroReflection.new(:cached_value, name, options, self)
72
+ write_inheritable_hash :reflections, name => reflection
73
+ reflection
74
+ end
75
+
76
+ def cached_value_accessor_method(reflection, association_proxy_class)
77
+ define_method(reflection.name) do |*params|
78
+ force_reload = params.first unless params.empty?
79
+ association = instance_variable_get("@#{reflection.name}")
80
+
81
+ if association.nil? || force_reload
82
+ association = association_proxy_class.new(self, reflection)
83
+ instance_variable_set("@#{reflection.name}", association)
84
+ force_reload ? association.reload : association.load
85
+ end
86
+ association.target.nil? ? nil : association
87
+ end
88
+ end
89
+
90
+ def cached_value_callback_methods(reflection)
91
+ %w{clear reload}.each do |operation|
92
+ if events = reflection.options[operation.to_sym]
93
+ events = [events] unless events.is_a?(Array)
94
+ events.map! { |event| event.to_s }
95
+ ActiveRecord::Callbacks::CALLBACKS.each do |callback|
96
+ if events.include?(callback)
97
+ send(callback, Proc.new {|record| record.send(reflection.name).send(operation)})
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,9 @@
1
+ require 'active_record'
2
+ require File.expand_path(File.dirname(__FILE__) + "/cached_values/cached_value")
3
+ require File.expand_path(File.dirname(__FILE__) + "/cached_values/caches_value")
4
+
5
+ module CachedValues # :nodoc:
6
+ VERSION = '1.0.0'
7
+ end
8
+
9
+ ActiveRecord::Base.send :include, CachesValues
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :cached_values do
3
+ # # Task goes here
4
+ # end
data/test/database.yml ADDED
@@ -0,0 +1,18 @@
1
+ sqlite:
2
+ :adapter: sqlite
3
+ :dbfile: plugin.sqlite.db
4
+ sqlite3:
5
+ :adapter: sqlite3
6
+ :dbfile: ":memory:"
7
+ postgresql:
8
+ :adapter: postgresql
9
+ :username: postgres
10
+ :password: postgres
11
+ :database: plugin_test
12
+ :min_messages: ERROR
13
+ mysql:
14
+ :adapter: mysql
15
+ :host: localhost
16
+ :username: rails
17
+ :password:
18
+ :database: plugin_test
@@ -0,0 +1,17 @@
1
+ class Leprechaun < ActiveRecord::Base
2
+ caches_value :favorite_color_in_rot_13, :eval => Proc.new {|leprechaun| leprechaun.favorite_color.tr "A-Za-z", "N-ZA-Mn-za-m" }
3
+ caches_value :favorite_color_turned_uppercase, :eval => "favorite_color.upcase"
4
+ caches_value :number_of_gold_coins, :eval => :calculate_gold
5
+ caches_value :id_of_first_leprechaun_with_same_favorite_color, :sql => 'select id from leprechauns where leprechauns.favorite_color = "#{favorite_color}" and leprechauns.id <> #{id} limit 1'
6
+ caches_value :favorite_color_in_rot_13_without_cache, :eval => Proc.new {|leprechaun| leprechaun.favorite_color.tr "A-Za-z", "N-ZA-Mn-za-m" }, :cache => false
7
+ caches_value :favorite_color_turned_uppercase_with_explicit_cache, :eval => "favorite_color.upcase", :cache => 'some_other_cache_field'
8
+ caches_value :reload_callback, :eval => "rand(1000)", :reload => [:before_save, :after_validation]
9
+ caches_value :clear_callback, :eval => "rand(1000)", :clear => :before_validation
10
+ caches_value :float_cast, :sql => "select 82343.222"
11
+ caches_value :integer_cast, :sql => "select 19"
12
+ caches_value :string_cast, :sql => 'select "Top \'o the mornin\' to ya"'
13
+
14
+ def calculate_gold
15
+ '127 gold coins'
16
+ end
17
+ end
data/test/schema.rb ADDED
@@ -0,0 +1,22 @@
1
+
2
+ require File.expand_path(File.dirname(__FILE__) + "/leprechaun")
3
+
4
+ ActiveRecord::Schema.define(:version => 1) do
5
+
6
+ create_table :leprechauns do |t|
7
+ t.column :name, :string
8
+ t.column :favorite_color, :string
9
+ t.column :favorite_color_in_rot_13, :string
10
+ t.column :favorite_color_in_rot_13_without_cache, :string
11
+ t.column :favorite_color_turned_uppercase, :string
12
+ t.column :id_of_first_leprechaun_with_same_favorite_color, :integer
13
+ t.column :some_other_cache_field, :string
14
+ t.column :reload_callback, :float
15
+ t.column :clear_callback, :float
16
+ end
17
+
18
+ Leprechaun.create!(:name => 'Mc Nairn', :favorite_color => 'blue')
19
+ Leprechaun.create!(:name => "O' Houhlihan", :favorite_color => 'ochre')
20
+ Leprechaun.create!(:name => "Danger Cáinte", :favorite_color => 'blue')
21
+
22
+ end
@@ -0,0 +1,118 @@
1
+ require 'test/unit'
2
+ require File.expand_path(File.dirname(__FILE__) + "/test_helper")
3
+
4
+ class CachedValuesTest < Test::Unit::TestCase
5
+
6
+ def setup
7
+ @mc_nairn = Leprechaun.find(:first)
8
+ @mc_nairn.favorite_color_in_rot_13.clear
9
+ @mc_nairn.favorite_color_turned_uppercase.clear
10
+ @mc_nairn.id_of_first_leprechaun_with_same_favorite_color.clear
11
+ @mc_nairn.favorite_color_in_rot_13_without_cache.clear
12
+ @mc_nairn.favorite_color_turned_uppercase_with_explicit_cache.clear
13
+ @mc_nairn.favorite_color = 'blue'
14
+ @mc_nairn.save!
15
+ end
16
+
17
+ def test_proc_should_properly_calculate_value
18
+ assert_equal 'blue', @mc_nairn.favorite_color
19
+ assert_equal 'oyhr', @mc_nairn.favorite_color.tr("A-Za-z", "N-ZA-Mn-za-m")
20
+ assert_equal 'oyhr', @mc_nairn.favorite_color_in_rot_13
21
+ end
22
+
23
+ def test_string_should_properly_calculate_value
24
+ assert_equal 'blue', @mc_nairn.favorite_color
25
+ assert_equal 'BLUE', @mc_nairn.favorite_color_turned_uppercase
26
+ @mc_nairn.update_attribute(:favorite_color, 'gold')
27
+ assert_equal 'BLUE', @mc_nairn.favorite_color_turned_uppercase
28
+ assert_equal 'GOLD', @mc_nairn.favorite_color_turned_uppercase.reload
29
+ end
30
+
31
+ def test_symbol_should_calculate_value_from_method_call
32
+ assert_equal '127 gold coins', @mc_nairn.number_of_gold_coins
33
+ assert_equal '127 gold coins', @mc_nairn.calculate_gold
34
+ @mc_nairn.class.class_eval { def calculate_gold; '255 gold coins'; end }
35
+ assert_equal '255 gold coins', @mc_nairn.calculate_gold
36
+ assert_equal '127 gold coins', @mc_nairn.number_of_gold_coins
37
+ assert_equal '255 gold coins', @mc_nairn.number_of_gold_coins.reload
38
+ end
39
+
40
+ def test_sql_should_properly_calculate_value
41
+ assert_equal 3, @mc_nairn.id_of_first_leprechaun_with_same_favorite_color
42
+ Leprechaun.find_by_name("O' Houhlihan").update_attribute(:favorite_color, 'blue')
43
+ assert_equal 3, @mc_nairn.id_of_first_leprechaun_with_same_favorite_color
44
+ assert_equal 2, @mc_nairn.id_of_first_leprechaun_with_same_favorite_color.reload
45
+ end
46
+
47
+ def test_should_cache_value
48
+ assert_equal 'blue', @mc_nairn.favorite_color
49
+ assert_equal 'oyhr', @mc_nairn.favorite_color_in_rot_13
50
+ @mc_nairn.update_attribute(:favorite_color, 'red')
51
+ assert_equal 'erq', @mc_nairn.favorite_color.tr("A-Za-z", "N-ZA-Mn-za-m")
52
+ assert_equal 'oyhr', @mc_nairn.favorite_color_in_rot_13
53
+ end
54
+
55
+ def test_cache_should_be_invalidated_on_clear
56
+ assert_equal 'blue', @mc_nairn.favorite_color
57
+ assert_equal 'oyhr', @mc_nairn.favorite_color_in_rot_13
58
+ @mc_nairn.favorite_color_in_rot_13.clear
59
+ assert_nil @mc_nairn.send(:read_attribute, :favorite_color_in_rot_13)
60
+ end
61
+
62
+ def test_value_should_be_updated_after_its_cleared
63
+ assert_equal 'blue', @mc_nairn.favorite_color
64
+ assert_equal 'oyhr', @mc_nairn.favorite_color_in_rot_13
65
+ @mc_nairn.update_attribute(:favorite_color, 'red')
66
+ assert_equal 'oyhr', @mc_nairn.favorite_color_in_rot_13
67
+ @mc_nairn.favorite_color_in_rot_13.clear
68
+ assert_equal 'erq', @mc_nairn.favorite_color_in_rot_13
69
+ end
70
+
71
+ def test_should_not_cache_explicitly_noncaching_values
72
+ assert_equal 'blue', @mc_nairn.favorite_color
73
+ assert_equal 'oyhr', @mc_nairn.favorite_color_in_rot_13_without_cache
74
+ assert_nil @mc_nairn.send(:read_attribute, :favorite_color_in_rot_13_without_cache)
75
+ @mc_nairn.update_attribute(:favorite_color, 'red')
76
+ assert_equal 'erq', @mc_nairn.favorite_color.tr("A-Za-z", "N-ZA-Mn-za-m")
77
+ assert_equal 'erq', @mc_nairn.favorite_color_in_rot_13_without_cache.reload
78
+ assert_nil @mc_nairn.send(:read_attribute, :favorite_color_in_rot_13_without_cache)
79
+ end
80
+
81
+ def test_should_respect_explicit_cache_column
82
+ assert_equal 'BLUE', @mc_nairn.favorite_color_turned_uppercase_with_explicit_cache
83
+ assert_equal 'BLUE', @mc_nairn.send(:read_attribute, :some_other_cache_field)
84
+ @mc_nairn.update_attribute(:favorite_color, 'red')
85
+ assert_equal 'BLUE', @mc_nairn.send(:read_attribute, :some_other_cache_field)
86
+ assert_equal 'RED', @mc_nairn.favorite_color_turned_uppercase_with_explicit_cache.reload
87
+ end
88
+
89
+ def test_reload_callback_should_fire
90
+ value = @mc_nairn.reload_callback.to_s
91
+ assert_equal value.to_i, @mc_nairn.reload_callback
92
+ @mc_nairn.save!
93
+ assert_not_equal value.to_i, @mc_nairn.reload_callback.reload
94
+ value = @mc_nairn.reload_callback.to_s
95
+ assert_equal value.to_i, @mc_nairn.reload_callback
96
+ @mc_nairn.valid?
97
+ assert_not_equal value.to_i, @mc_nairn.reload_callback
98
+ end
99
+
100
+ def test_clear_callback_should_fire
101
+ assert @mc_nairn.clear_callback
102
+ assert @mc_nairn.instance_variable_get("@clear_callback")
103
+ @mc_nairn.valid?
104
+ assert_nil @mc_nairn.instance_variable_get("@clear_callback")
105
+ end
106
+
107
+ def test_sql_should_cast_to_integer
108
+ assert @mc_nairn.integer_cast.is_a?(Fixnum)
109
+ end
110
+
111
+ def test_sql_should_cast_to_string
112
+ assert @mc_nairn.string_cast.is_a?(String)
113
+ end
114
+
115
+ def test_sql_should_cast_to_float
116
+ assert @mc_nairn.float_cast.is_a?(Float)
117
+ end
118
+ end
@@ -0,0 +1,36 @@
1
+ # Include this file in your test by copying the following line to your test:
2
+ # require File.expand_path(File.dirname(__FILE__) + "/test_helper")
3
+
4
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
5
+
6
+ require 'rubygems'
7
+ require 'test/unit'
8
+ require 'active_record'
9
+ require 'active_record/fixtures'
10
+ require "cached_values"
11
+ require File.expand_path(File.dirname(__FILE__) + "/leprechaun")
12
+
13
+ config = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml'))
14
+ ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + "/debug.log")
15
+ ActiveRecord::Base.establish_connection(config[ENV['DB'] || 'sqlite3'])
16
+
17
+ load(File.dirname(__FILE__) + "/schema.rb") if File.exist?(File.dirname(__FILE__) + "/schema.rb")
18
+
19
+ class Test::Unit::TestCase #:nodoc:
20
+
21
+ # def create_fixtures(*table_names)
22
+ # if block_given?
23
+ # Fixtures.create_fixtures(Test::Unit::TestCase.fixture_path, table_names) { yield }
24
+ # else
25
+ # Fixtures.create_fixtures(Test::Unit::TestCase.fixture_path, table_names)
26
+ # end
27
+ # end
28
+
29
+ # Turn off transactional fixtures if you're working with MyISAM tables in MySQL
30
+ self.use_transactional_fixtures = true
31
+
32
+ # Instantiated fixtures are slow, but give you @david where you otherwise would need people(:david)
33
+ self.use_instantiated_fixtures = false
34
+
35
+ # Add more helper methods to be used by all tests here...
36
+ end
data/uninstall.rb ADDED
@@ -0,0 +1 @@
1
+ # Uninstall hook code here
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cached_values
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Jack Danger Canty
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-03-07 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: hoe
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 1.5.1
23
+ version:
24
+ description: ""
25
+ email:
26
+ - rubygems_cached_values@6brand.com
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - History.txt
33
+ - Manifest.txt
34
+ - README.txt
35
+ files:
36
+ - History.txt
37
+ - MIT-LICENSE
38
+ - Manifest.txt
39
+ - README.txt
40
+ - Rakefile
41
+ - init.rb
42
+ - install.rb
43
+ - lib/cached_values.rb
44
+ - lib/cached_values/cached_value.rb
45
+ - lib/cached_values/caches_value.rb
46
+ - tasks/cached_values_tasks.rake
47
+ - test/database.yml
48
+ - test/leprechaun.rb
49
+ - test/schema.rb
50
+ - test/test_cached_values.rb
51
+ - test/test_helper.rb
52
+ - uninstall.rb
53
+ has_rdoc: true
54
+ homepage: http://github.com/JackDanger/cached_values/
55
+ post_install_message:
56
+ rdoc_options:
57
+ - --main
58
+ - README.txt
59
+ require_paths:
60
+ - lib
61
+ required_ruby_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: "0"
66
+ version:
67
+ required_rubygems_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: "0"
72
+ version:
73
+ requirements: []
74
+
75
+ rubyforge_project: cachedvalues
76
+ rubygems_version: 1.0.1
77
+ signing_key:
78
+ specification_version: 2
79
+ summary: ""
80
+ test_files:
81
+ - test/test_cached_values.rb
82
+ - test/test_helper.rb