reference_tracking 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
@@ -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
|
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
|
+
|