reference_tracking 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,13 @@
1
+ require 'active_support/core_ext/kernel/singleton_class'
2
+ require 'action_controller'
3
+
4
+ module ReferenceTracking
5
+ TAGS_HEADER = 'rack-cache.tags'
6
+
7
+ autoload :ActionController, 'reference_tracking/action_controller'
8
+ autoload :IvarProxy, 'reference_tracking/ivar_proxy'
9
+ autoload :Tracker, 'reference_tracking/tracker'
10
+ autoload :References, 'reference_tracking/references'
11
+ end
12
+
13
+ ActionController::Base.send(:extend, ReferenceTracking::ActionController::ActMacro)
@@ -0,0 +1,40 @@
1
+ module ReferenceTracking
2
+ module ActionController
3
+ module ActMacro
4
+ def tracks(*args)
5
+ unless tracks_references?
6
+ include ReferenceTracking::ActionController
7
+
8
+ class_inheritable_accessor :reference_tracking_options
9
+ self.reference_tracking_options = { :header => TAGS_HEADER }
10
+ end
11
+
12
+ options = args.extract_options!
13
+ actions = Array(options.delete(:only) || [:index, :show]) - Array(options.delete(:except))
14
+ args << options unless options.empty?
15
+
16
+ actions.map(&:to_sym).each do |action|
17
+ self.reference_tracking_options[action] ||= []
18
+ self.reference_tracking_options[action] += args
19
+ end
20
+ end
21
+
22
+ def tracks_references?
23
+ respond_to?(:reference_tracking_options) && reference_tracking_options.present?
24
+ end
25
+ end
26
+
27
+ # TODO could this hook into instrumentation?
28
+ # ActiveSupport::Notifications.instrument("render_template.action_view", ...)?
29
+
30
+ def render(*)
31
+ methods = reference_tracking_options[params[:action].to_sym] || {}
32
+ @_references = ReferenceTracking::References.new(self, methods)
33
+
34
+ result = super
35
+
36
+ headers[reference_tracking_options[:header]] = @_references.tags
37
+ result
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,26 @@
1
+ module ReferenceTracking
2
+ class IvarProxy
3
+ instance_methods.each { |m| undef_method(m) unless %w(__send__ __id__ inspect).include?(m) }
4
+
5
+ def initialize(owner, name, object, references)
6
+ @owner = owner
7
+ @name = name
8
+ @object = object
9
+ @references = references
10
+ end
11
+
12
+ def respond_to?(method)
13
+ @object.respond_to?(method)
14
+ end
15
+
16
+ def method_missing(method, *args, &block)
17
+ respond_to?(method) ? __track__(method, *args, &block) : super
18
+ end
19
+
20
+ def __track__(method, *args, &block)
21
+ @references << [@object, nil]
22
+ @owner.instance_variable_set(@name, @object)
23
+ @object.send(method, *args, &block)
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,13 @@
1
+ module ReferenceTracking
2
+ class References < Array
3
+ def initialize(object, methods)
4
+ Tracker.setup(object, self, methods)
5
+ end
6
+
7
+ def tags
8
+ map do |object, method|
9
+ "#{object.class.name.underscore}-#{object.id}#{":#{method}" if method}"
10
+ end.uniq
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,56 @@
1
+ # tracks :post # => tags post-1.*
2
+ # tracks 'post.title' # => tags post-1.title
3
+ # tracks :post => :blog # => tags blog-1.*
4
+ # tracks :blog => :posts # => tags post-1.*, post-1.*, ...
5
+
6
+ require 'active_support/core_ext/array/wrap'
7
+
8
+ module ReferenceTracking
9
+ module Tracker
10
+ class << self
11
+ def setup(object, references, targets, options = {})
12
+ Array.wrap(targets).each do |target|
13
+ if target.is_a?(Hash)
14
+ target.each { |target, nested| delegate_tracking(object, references, target, nested) }
15
+ elsif options[:delegated]
16
+ send(options[:delegated], object, references, target)
17
+ elsif target.to_s.include?('.')
18
+ delegate_tracking(object, references, *target.to_s.split('.') << :track_calls_to)
19
+ else
20
+ track_calls_on(object, references, target)
21
+ end
22
+ end
23
+ end
24
+
25
+ def tracker_for(object)
26
+ Module.new.tap { |tracker| object.singleton_class.send(:include, tracker) }
27
+ end
28
+
29
+ def track_calls_on(object, references, target)
30
+ tracker_for(object).send(:define_method, target) do |*args|
31
+ super.tap { |object| Array(object).each { |object| references << [object, nil] } }
32
+ end
33
+ end
34
+
35
+ def track_calls_to(object, references, method)
36
+ method = method.to_s.split('.').last if method.to_s.include?('.')
37
+ tracker_for(object).send(:define_method, method) do |*args|
38
+ references << [self, method]
39
+ super
40
+ end
41
+ end
42
+
43
+ def delegate_tracking(object, references, target, delegateds, method = :track_calls_on)
44
+ tracker_for(object).send(:define_method, target) do |*|
45
+ super.tap do |object|
46
+ Array.wrap(delegateds).each do |delegated|
47
+ delegated = [delegated] if delegated.is_a?(Hash)
48
+ _method = delegated.to_s.start_with?('.') ? :track_calls_to : method
49
+ Tracker.setup(object, references, delegated, :delegated => _method)
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,3 @@
1
+ module ReferenceTracking
2
+ VERSION = "0.0.1"
3
+ end
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: reference_tracking
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Sven Fuchs
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-09-04 00:00:00 +02:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: "[description]"
23
+ email: svenfuchs@artweb-design.de
24
+ executables: []
25
+
26
+ extensions: []
27
+
28
+ extra_rdoc_files: []
29
+
30
+ files:
31
+ - lib/reference_tracking.rb
32
+ - lib/reference_tracking/action_controller.rb
33
+ - lib/reference_tracking/ivar_proxy.rb
34
+ - lib/reference_tracking/references.rb
35
+ - lib/reference_tracking/tracker.rb
36
+ - lib/reference_tracking/version.rb
37
+ has_rdoc: true
38
+ homepage: http://github.com/svenfuchs/reference_tracking
39
+ licenses: []
40
+
41
+ post_install_message:
42
+ rdoc_options: []
43
+
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ none: false
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ hash: 3
52
+ segments:
53
+ - 0
54
+ version: "0"
55
+ required_rubygems_version: !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ hash: 23
61
+ segments:
62
+ - 1
63
+ - 3
64
+ - 6
65
+ version: 1.3.6
66
+ requirements: []
67
+
68
+ rubyforge_project: "[none]"
69
+ rubygems_version: 1.3.7
70
+ signing_key:
71
+ specification_version: 3
72
+ summary: "[summary]"
73
+ test_files: []
74
+