acts_as_cached 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README ADDED
@@ -0,0 +1,4 @@
1
+ ActsAsCached
2
+ ============
3
+
4
+ Description goes here
@@ -0,0 +1,77 @@
1
+ require 'active_record'
2
+ require 'view_extensions'
3
+
4
+ module Adocca
5
+ module Acts
6
+ module ActsAsCached
7
+
8
+ class CacheObserver
9
+
10
+ # class_name: The name of the class whose namespace we'll invalidate
11
+ # id_column: The column of the monitored object that contains the id
12
+ # of the object we'll invalidate
13
+ # type_column: For polymorphic associations, this is the column of the
14
+ # monitored object that contains the class name of the
15
+ # associated object. E.g. for trigs, "triggable_type"
16
+
17
+ def initialize(class_name, id_column, type_column = nil)
18
+ @class_name, @id_column, @type_column = class_name, id_column, type_column
19
+ end
20
+
21
+ def update(method_name, object)
22
+ if method_name == :after_save || method_name == :after_destroy
23
+ # in case of polymorphic associations, make sure the monitored object
24
+ # is attached to the right type
25
+ if @type_column.nil? || object[@type_column] == @class_name
26
+ namespace = "#{@class_name}:#{object[@id_column]}"
27
+ #puts 'Invalidating: ' + namespace + ' for change on object ' + object.class.name
28
+ RAILS_DEFAULT_LOGGER.debug "ActsAsCached, Invalidating namespace: #{namespace}"
29
+ CACHE.invalidate_namespace(namespace)
30
+ end
31
+ end
32
+ true
33
+ end
34
+ end
35
+
36
+ def self.append_features(base)
37
+ super
38
+ base.extend(ClassMethods)
39
+ end
40
+
41
+ module ClassMethods
42
+ def acts_as_cached(options = {})
43
+ if assocs = options[:depends]
44
+ assocs = [ assocs ] if assocs.kind_of? Symbol
45
+
46
+ assocs.each do |assoc|
47
+ unless reflection = reflect_on_association(assoc)
48
+ raise "Association not found"
49
+ end
50
+
51
+ # For trough reflections, we need to observe both the
52
+ # intermediate model (e.g. Tagging for tags) and the
53
+ # and the associated (Tag for tags)
54
+ # For now, only the through reflection since it's pain
55
+ # in the ASS to do this correctly. This works for tags :)
56
+ if through = reflection.through_reflection
57
+ reflection = through
58
+ end
59
+
60
+ if as = reflection.options[:as]
61
+ type_column = "#{as}_type"
62
+ else
63
+ type_column = nil
64
+ end
65
+
66
+ reflection.klass.add_observer CacheObserver.new(self.name, reflection.primary_key_name, type_column)
67
+ end
68
+ end
69
+
70
+ self.add_observer CacheObserver.new(self.name, self.primary_key.to_sym)
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
76
+
77
+ ActiveRecord::Base.send(:include, Adocca::Acts::ActsAsCached)
@@ -0,0 +1,83 @@
1
+ require 'set'
2
+
3
+ ActionView::Base.class_eval do
4
+ class RenderOptions
5
+
6
+ def initialize(*init_values)
7
+ @set = Set.new(init_values)
8
+ end
9
+
10
+ def <<(key)
11
+ @set << key
12
+ end
13
+
14
+ def length
15
+ @set.length
16
+ end
17
+
18
+ alias_method :add, :<<
19
+
20
+ def method_missing(name)
21
+ if name.to_s =~ /(\w+)\?/
22
+ return @set.include?($1.to_sym)
23
+ else
24
+ super
25
+ end
26
+ end
27
+
28
+ def to_key
29
+ @set.to_a.collect{ |sym| sym.to_s }.sort.join(':')
30
+ end
31
+
32
+ end
33
+
34
+ def render_object(object, view, options = {})
35
+
36
+ logger.info "render_cached: object: #{object} view: #{view} options #{options.inspect}"
37
+
38
+
39
+ # XXX validate that object is an acts_as_cached FIXME
40
+
41
+ namespace = "#{object.class.name}:#{object.id}"
42
+ if render_options = options[:options]
43
+ key = "#{view}:#{render_options.to_key}"
44
+ else
45
+ render_options = RenderOptions.new
46
+ key = view
47
+ end
48
+
49
+ fragment_proc = Proc.new do
50
+ partial = options[:partial]
51
+ class_lower = object.class.name.underscore
52
+ unless partial
53
+ if directory = options[:directory]
54
+ partial = "#{directory}/#{class_lower}_#{view}"
55
+ else
56
+ partial = "#{class_lower}_#{view}"
57
+ end
58
+ end
59
+ render :partial => partial, :locals => { class_lower.to_sym => object, :options => render_options }
60
+ end
61
+
62
+ unless options[:cache] == false
63
+ fragment = cache_value([namespace, key], options[:expiry] || 0, &fragment_proc)
64
+ else
65
+ fragment = fragment_proc.call
66
+ end
67
+
68
+ if transformer = options[:transform]
69
+ case transformer
70
+ when Symbol
71
+ return send(transformer, object, fragment)
72
+ when Proc
73
+ return transformer.call(object, fragment)
74
+ else
75
+ raise TypeError, "Transformer must be either symbol or proc"
76
+ end
77
+ else
78
+ return fragment
79
+ end
80
+
81
+ end
82
+ end
83
+
@@ -0,0 +1,8 @@
1
+ require 'test/unit'
2
+
3
+ class ActsAsCachedTest < Test::Unit::TestCase
4
+ # Replace this with your real tests.
5
+ def test_this_plugin
6
+ flunk
7
+ end
8
+ end
metadata ADDED
@@ -0,0 +1,50 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.0
3
+ specification_version: 1
4
+ name: acts_as_cached
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.1.0
7
+ date: 2006-11-13 00:00:00 +01:00
8
+ summary: Caching helpers for Rails
9
+ require_paths:
10
+ - lib
11
+ email:
12
+ homepage:
13
+ rubyforge_project:
14
+ description:
15
+ autorequire: acts_as_cached
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ post_install_message:
29
+ authors:
30
+ - Adocca Entertainment AB
31
+ files:
32
+ - lib/acts_as_cached.rb
33
+ - lib/view_extensions.rb
34
+ - test/acts_as_cached_test.rb
35
+ - README
36
+ test_files: []
37
+
38
+ rdoc_options:
39
+ - --line-numbers
40
+ - --inline-source
41
+ extra_rdoc_files:
42
+ - README
43
+ executables: []
44
+
45
+ extensions: []
46
+
47
+ requirements: []
48
+
49
+ dependencies: []
50
+