methodmissing-scrooge 1.0.4 → 2.0.0
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.
- data/README.textile +139 -449
- data/Rakefile +20 -19
- data/VERSION.yml +2 -2
- data/lib/attributes_proxy.rb +121 -0
- data/lib/scrooge.rb +206 -47
- data/rails/init.rb +1 -10
- data/test/helper.rb +88 -0
- data/test/models/mysql_user.rb +4 -0
- data/test/scrooge_test.rb +75 -0
- data/test/setup.rb +3 -0
- metadata +11 -76
- data/assets/config/scrooge.yml.template +0 -27
- data/lib/scrooge/core/string.rb +0 -29
- data/lib/scrooge/core/symbol.rb +0 -21
- data/lib/scrooge/core/thread.rb +0 -26
- data/lib/scrooge/framework/base.rb +0 -315
- data/lib/scrooge/framework/rails.rb +0 -132
- data/lib/scrooge/middleware/tracker.rb +0 -46
- data/lib/scrooge/orm/active_record.rb +0 -159
- data/lib/scrooge/orm/base.rb +0 -102
- data/lib/scrooge/profile.rb +0 -223
- data/lib/scrooge/storage/base.rb +0 -46
- data/lib/scrooge/storage/memory.rb +0 -25
- data/lib/scrooge/strategy/base.rb +0 -74
- data/lib/scrooge/strategy/controller.rb +0 -31
- data/lib/scrooge/strategy/scope.rb +0 -15
- data/lib/scrooge/strategy/stage.rb +0 -77
- data/lib/scrooge/strategy/track.rb +0 -19
- data/lib/scrooge/strategy/track_then_scope.rb +0 -41
- data/lib/scrooge/tracker/app.rb +0 -161
- data/lib/scrooge/tracker/base.rb +0 -66
- data/lib/scrooge/tracker/model.rb +0 -150
- data/lib/scrooge/tracker/resource.rb +0 -181
- data/spec/fixtures/config/scrooge/scopes/1234567891/scope.yml +0 -2
- data/spec/fixtures/config/scrooge.yml +0 -20
- data/spec/helpers/framework/rails/cache.rb +0 -25
- data/spec/spec_helper.rb +0 -55
- data/spec/units/scrooge/core/string_spec.rb +0 -21
- data/spec/units/scrooge/core/symbol_spec.rb +0 -13
- data/spec/units/scrooge/core/thread_spec.rb +0 -15
- data/spec/units/scrooge/framework/base_spec.rb +0 -160
- data/spec/units/scrooge/framework/rails_spec.rb +0 -40
- data/spec/units/scrooge/orm/base_spec.rb +0 -61
- data/spec/units/scrooge/profile_spec.rb +0 -79
- data/spec/units/scrooge/storage/base_spec.rb +0 -35
- data/spec/units/scrooge/storage/memory_spec.rb +0 -20
- data/spec/units/scrooge/strategy/base_spec.rb +0 -62
- data/spec/units/scrooge/strategy/controller_spec.rb +0 -26
- data/spec/units/scrooge/strategy/scope_spec.rb +0 -18
- data/spec/units/scrooge/strategy/stage_spec.rb +0 -35
- data/spec/units/scrooge/strategy/track_spec.rb +0 -19
- data/spec/units/scrooge/strategy/track_then_scope_spec.rb +0 -22
- data/spec/units/scrooge/tracker/app_spec.rb +0 -68
- data/spec/units/scrooge/tracker/base_spec.rb +0 -29
- data/spec/units/scrooge/tracker/model_spec.rb +0 -79
- data/spec/units/scrooge/tracker/resource_spec.rb +0 -115
- data/spec/units/scrooge_spec.rb +0 -13
- data/tasks/scrooge.rake +0 -43
@@ -1,77 +0,0 @@
|
|
1
|
-
module Scrooge
|
2
|
-
module Strategy
|
3
|
-
class Stage
|
4
|
-
|
5
|
-
# Represents a duration sensitive stage / phase of execution.
|
6
|
-
|
7
|
-
STATES = { :initialized => 0,
|
8
|
-
:execute => 1,
|
9
|
-
:terminated => 2 }
|
10
|
-
|
11
|
-
attr_accessor :signature,
|
12
|
-
:duration,
|
13
|
-
:payload
|
14
|
-
|
15
|
-
# Requires a unique signature and stores a payload for later execution.
|
16
|
-
#
|
17
|
-
# Valid options is
|
18
|
-
# * :for : the phase / stage duration, in seconds
|
19
|
-
#
|
20
|
-
def initialize( signature, options = {}, &block )
|
21
|
-
@signature = signature
|
22
|
-
@duration = options[:for] || 0
|
23
|
-
@payload = block
|
24
|
-
@state = :initialized
|
25
|
-
end
|
26
|
-
|
27
|
-
# Always executeable when initialized and not yet terminated.
|
28
|
-
#
|
29
|
-
def executeable?
|
30
|
-
initialized? && !terminated?
|
31
|
-
end
|
32
|
-
|
33
|
-
# Enter the :execute state, call the payload and sleep for the defined duration.
|
34
|
-
# Returns the payload result on completion and ensures that the current state is
|
35
|
-
# :terminated.
|
36
|
-
#
|
37
|
-
def execute!
|
38
|
-
begin
|
39
|
-
Scrooge::Base.profile.log( "Execute stage #{signature.inspect} ...", true)
|
40
|
-
@state = :execute
|
41
|
-
result = call!
|
42
|
-
sleep( @duration )
|
43
|
-
result
|
44
|
-
ensure
|
45
|
-
@state = :terminated
|
46
|
-
end
|
47
|
-
end
|
48
|
-
alias :run! :execute!
|
49
|
-
|
50
|
-
# Are we running ?
|
51
|
-
#
|
52
|
-
def execute?
|
53
|
-
@state == :execute
|
54
|
-
end
|
55
|
-
alias :running? :execute?
|
56
|
-
|
57
|
-
# Is this stage pending execution ?
|
58
|
-
#
|
59
|
-
def initialized?
|
60
|
-
@state == :initialized
|
61
|
-
end
|
62
|
-
|
63
|
-
# Has this stage already terminated ?
|
64
|
-
#
|
65
|
-
def terminated?
|
66
|
-
@state == :terminated
|
67
|
-
end
|
68
|
-
|
69
|
-
private
|
70
|
-
|
71
|
-
def call! #:nodoc:
|
72
|
-
Scrooge::Base.profile.instance_eval( &@payload )
|
73
|
-
end
|
74
|
-
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
@@ -1,19 +0,0 @@
|
|
1
|
-
module Scrooge
|
2
|
-
module Strategy
|
3
|
-
class Track < Base
|
4
|
-
|
5
|
-
stage :track, :for => Scrooge::Base.profile.warmup do
|
6
|
-
|
7
|
-
log( "Tracking", true )
|
8
|
-
framework.install_tracking_middleware()
|
9
|
-
start_tracking!
|
10
|
-
::Kernel.at_exit do
|
11
|
-
log( "Shutdown ...", true )
|
12
|
-
framework.scope! if tracker.any?
|
13
|
-
end
|
14
|
-
|
15
|
-
end
|
16
|
-
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
@@ -1,41 +0,0 @@
|
|
1
|
-
module Scrooge
|
2
|
-
module Strategy
|
3
|
-
class TrackThenScope < Base
|
4
|
-
|
5
|
-
stage :track, :for => Scrooge::Base.profile.warmup do
|
6
|
-
|
7
|
-
log( "Installing tracking middleware ... ", true )
|
8
|
-
framework.install_tracking_middleware()
|
9
|
-
log( "Start tracking ... ", true )
|
10
|
-
start_tracking!
|
11
|
-
|
12
|
-
end
|
13
|
-
|
14
|
-
stage :synchronize, :for => 10 do
|
15
|
-
|
16
|
-
log( "Uninstalling tracking middleware ... ", true )
|
17
|
-
framework.uninstall_tracking_middleware
|
18
|
-
log( "Stop tracking ... ", true )
|
19
|
-
stop_tracking!
|
20
|
-
log( "Synchronize results with other processes ...", true )
|
21
|
-
tracker.synchronize!
|
22
|
-
|
23
|
-
end
|
24
|
-
|
25
|
-
stage :aggregate, :for => 10 do
|
26
|
-
|
27
|
-
log( "Aggregate results from other processes ...", true )
|
28
|
-
tracker.aggregate!
|
29
|
-
|
30
|
-
end
|
31
|
-
|
32
|
-
stage :scope do
|
33
|
-
|
34
|
-
log( "Scope ...", true )
|
35
|
-
framework.install_scope_middleware( tracker )
|
36
|
-
|
37
|
-
end
|
38
|
-
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
data/lib/scrooge/tracker/app.rb
DELETED
@@ -1,161 +0,0 @@
|
|
1
|
-
module Scrooge
|
2
|
-
module Tracker
|
3
|
-
class App < Scrooge::Tracker::Base
|
4
|
-
|
5
|
-
# Application container for various Resources.
|
6
|
-
|
7
|
-
GUARD = Monitor.new
|
8
|
-
|
9
|
-
AGGREGATION_BUCKET = 'scrooge_tracker_aggregation'.freeze
|
10
|
-
|
11
|
-
attr_accessor :resources
|
12
|
-
|
13
|
-
def initialize
|
14
|
-
super()
|
15
|
-
@resources = Set.new
|
16
|
-
end
|
17
|
-
|
18
|
-
# Push this tracker instance to the framework's cache store.
|
19
|
-
# A synchronization signature unique for this Process is also logged in a synchronization
|
20
|
-
# bucket which maintain references to each Process's tracker.
|
21
|
-
#
|
22
|
-
def synchronize!
|
23
|
-
GUARD.synchronize do
|
24
|
-
write_cache( synchronization_signature, marshal_dump )
|
25
|
-
register_synchronization_signature!
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
# Process previously synchronized tracking data by recursively merging all trackers from
|
30
|
-
# all Processes to have a Tracker representative of the whole cluster.
|
31
|
-
#
|
32
|
-
def aggregate!
|
33
|
-
GUARD.synchronize do
|
34
|
-
read_cache( AGGREGATION_BUCKET ).each do |tracker|
|
35
|
-
tracker_data = read_cache( tracker )
|
36
|
-
merge( self.class.load( tracker_data ) )
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
# Merge this Tracker with another Tracker ( multi-process aggregation )
|
42
|
-
#
|
43
|
-
def merge( other_tracker )
|
44
|
-
return unless other_tracker
|
45
|
-
resources.merge( other_tracker.resources )
|
46
|
-
resources.each do |res|
|
47
|
-
res.merge( other_tracker.resource( res ) )
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
# Find a given resource instance
|
52
|
-
#
|
53
|
-
def resource( resource )
|
54
|
-
resources.detect{|r| r.signature == resource.signature }
|
55
|
-
end
|
56
|
-
|
57
|
-
# Has any Resources been tracked ?
|
58
|
-
#
|
59
|
-
def any?
|
60
|
-
GUARD.synchronize do
|
61
|
-
!@resources.empty?
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
# Add a Resource instance to this tracker.
|
66
|
-
#
|
67
|
-
def <<( resource )
|
68
|
-
GUARD.synchronize do
|
69
|
-
@resources << setup_resource( resource )
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
def marshal_dump #:nodoc:
|
74
|
-
GUARD.synchronize do
|
75
|
-
dumped_resources()
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
def marshal_load( data ) #:nodoc:
|
80
|
-
GUARD.synchronize do
|
81
|
-
@resources = Set.new( restored_resources( data ) )
|
82
|
-
end
|
83
|
-
self
|
84
|
-
end
|
85
|
-
|
86
|
-
# Track a given Resource.
|
87
|
-
#
|
88
|
-
def track( resource )
|
89
|
-
begin
|
90
|
-
yield
|
91
|
-
ensure
|
92
|
-
self << resource if resource.any?
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
def inspect #:nodoc:
|
97
|
-
if any?
|
98
|
-
@resources.map{|r| r.inspect }.join( "\n\n" )
|
99
|
-
else
|
100
|
-
super
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
# If we've seen this resource before, return the original, else, returns
|
105
|
-
# the given resource.
|
106
|
-
#
|
107
|
-
def resource_for( res )
|
108
|
-
resource( res ) || res
|
109
|
-
end
|
110
|
-
|
111
|
-
private
|
112
|
-
|
113
|
-
def read_cache( key ) #:nodoc:
|
114
|
-
Scrooge::Base.profile.framework.read_cache( key )
|
115
|
-
end
|
116
|
-
|
117
|
-
def write_cache( key, value ) #:nodoc:
|
118
|
-
Scrooge::Base.profile.framework.write_cache( key, value )
|
119
|
-
end
|
120
|
-
|
121
|
-
def register_synchronization_signature! #:nodoc:
|
122
|
-
if bucket = read_cache( AGGREGATION_BUCKET )
|
123
|
-
write_cache( AGGREGATION_BUCKET, (bucket << synchronization_signature) )
|
124
|
-
else
|
125
|
-
write_cache( AGGREGATION_BUCKET, [synchronization_signature] )
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
def synchronization_signature #:nodoc:
|
130
|
-
@synchronization_signature ||= "#{Thread.current.object_id}_#{Process.pid}_#{rand(1000000)}"
|
131
|
-
end
|
132
|
-
|
133
|
-
def setup_resource( resource ) #:nodoc:
|
134
|
-
GUARD.synchronize do
|
135
|
-
resource_for( resource )
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
def environment #:nodoc:
|
140
|
-
profile.framework.environment
|
141
|
-
end
|
142
|
-
|
143
|
-
def restored_resources( data ) #:nodoc:
|
144
|
-
GUARD.synchronize do
|
145
|
-
data.map do |resource|
|
146
|
-
Resource.load( resource )
|
147
|
-
end
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
def dumped_resources #:nodoc:
|
152
|
-
GUARD.synchronize do
|
153
|
-
@resources.to_a.map do |resource|
|
154
|
-
resource.marshal_dump
|
155
|
-
end
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
|
-
end
|
160
|
-
end
|
161
|
-
end
|
data/lib/scrooge/tracker/base.rb
DELETED
@@ -1,66 +0,0 @@
|
|
1
|
-
require 'set'
|
2
|
-
|
3
|
-
module Scrooge
|
4
|
-
module Tracker
|
5
|
-
|
6
|
-
autoload :App, 'scrooge/tracker/app'
|
7
|
-
autoload :Resource, 'scrooge/tracker/resource'
|
8
|
-
autoload :Model, 'scrooge/tracker/model'
|
9
|
-
|
10
|
-
class Base < Scrooge::Base
|
11
|
-
include Comparable
|
12
|
-
|
13
|
-
# Scrooge Tracker base class.
|
14
|
-
|
15
|
-
class NotImplemented < StandardError
|
16
|
-
end
|
17
|
-
|
18
|
-
class << self
|
19
|
-
|
20
|
-
# Marshal helper.
|
21
|
-
#
|
22
|
-
def load( data )
|
23
|
-
new.marshal_load( data )
|
24
|
-
end
|
25
|
-
|
26
|
-
end
|
27
|
-
|
28
|
-
attr_accessor :counter
|
29
|
-
|
30
|
-
def initialize
|
31
|
-
@counter = 0
|
32
|
-
end
|
33
|
-
|
34
|
-
def to_i
|
35
|
-
@counter
|
36
|
-
end
|
37
|
-
|
38
|
-
# Requires subclasses to implement a custom marshal_dump
|
39
|
-
#
|
40
|
-
def marshal_dump
|
41
|
-
raise NotImplemented
|
42
|
-
end
|
43
|
-
|
44
|
-
# Requires subclasses to implement a custom marshal_load
|
45
|
-
#
|
46
|
-
def marshal_load( data )
|
47
|
-
raise NotImplemented
|
48
|
-
end
|
49
|
-
|
50
|
-
# Compare trackers through their Marshal representations.
|
51
|
-
#
|
52
|
-
def ==( tracker )
|
53
|
-
compare_to( tracker )
|
54
|
-
end
|
55
|
-
alias :eql? :==
|
56
|
-
alias :<=> :==
|
57
|
-
|
58
|
-
private
|
59
|
-
|
60
|
-
def compare_to( tracker ) #:nodoc:
|
61
|
-
marshal_dump == tracker.marshal_dump
|
62
|
-
end
|
63
|
-
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
@@ -1,150 +0,0 @@
|
|
1
|
-
module Scrooge
|
2
|
-
module Tracker
|
3
|
-
class Model < Base
|
4
|
-
|
5
|
-
GUARD = Monitor.new
|
6
|
-
|
7
|
-
attr_accessor :model,
|
8
|
-
:attributes
|
9
|
-
|
10
|
-
def initialize( model )
|
11
|
-
super()
|
12
|
-
@model = model
|
13
|
-
@attributes = Set.new
|
14
|
-
end
|
15
|
-
|
16
|
-
# Merge this Tracker with another Tracker for the same model ( multi-process / cluster aggregation )
|
17
|
-
#
|
18
|
-
def merge( other_model )
|
19
|
-
return unless other_model
|
20
|
-
attributes.merge( other_model.attributes )
|
21
|
-
end
|
22
|
-
|
23
|
-
# Has any Attributes been tracked ?
|
24
|
-
#
|
25
|
-
def any?
|
26
|
-
GUARD.synchronize do
|
27
|
-
!@attributes.empty?
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
# Add a Model attribute to this tracker.
|
32
|
-
#
|
33
|
-
def <<( attribute )
|
34
|
-
GUARD.synchronize do
|
35
|
-
Array( attribute ).each do |attr|
|
36
|
-
attributes << attr
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def marshal_dump #:nodoc:
|
42
|
-
GUARD.synchronize do
|
43
|
-
{ name() => @attributes.to_a }
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
def marshal_load( data ) #:nodoc:
|
48
|
-
GUARD.synchronize do
|
49
|
-
@model = data.keys.first
|
50
|
-
@attributes = Set.new( data[@model] )
|
51
|
-
self
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
# Return a valid Rack middleware instance for this model.
|
56
|
-
#
|
57
|
-
def middleware( resource )
|
58
|
-
profile.orm.scope_resource_to_model( resource, self )
|
59
|
-
klass = Class.new
|
60
|
-
klass.class_eval(<<-EOS, __FILE__, __LINE__)
|
61
|
-
|
62
|
-
class << self
|
63
|
-
|
64
|
-
def inspect
|
65
|
-
"#<Scrooge::Middleware #{inspect}>"
|
66
|
-
end
|
67
|
-
|
68
|
-
# Around Filter compatible implementation for Rails as Dispatcher is
|
69
|
-
# the root Rack application and as such don't provide access to the Rails
|
70
|
-
# Routing internals from other middleware.
|
71
|
-
#
|
72
|
-
def filter( controller )
|
73
|
-
#{model.to_s}.#{profile.orm.resource_scope_method( resource ).to_s} do
|
74
|
-
yield
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
end
|
79
|
-
|
80
|
-
def initialize(app)
|
81
|
-
@app = app
|
82
|
-
end
|
83
|
-
|
84
|
-
def call(env)
|
85
|
-
if scope?( env )
|
86
|
-
#{model.to_s}.#{profile.orm.resource_scope_method( resource ).to_s} do
|
87
|
-
@app.call(env)
|
88
|
-
end
|
89
|
-
else
|
90
|
-
@app.call(env)
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
private
|
95
|
-
|
96
|
-
def scope?( env )
|
97
|
-
Scrooge::Base.profile.orm.resource_scope_method( resource( env ) ) == :#{profile.orm.resource_scope_method( resource ).to_s}
|
98
|
-
end
|
99
|
-
|
100
|
-
def resource( env )
|
101
|
-
Scrooge::Base.profile.framework.resource( env )
|
102
|
-
end
|
103
|
-
|
104
|
-
EOS
|
105
|
-
klass
|
106
|
-
end
|
107
|
-
|
108
|
-
# Memoize the name lookup.
|
109
|
-
#
|
110
|
-
def name
|
111
|
-
@name ||= profile.orm.name( @model )
|
112
|
-
end
|
113
|
-
|
114
|
-
# Memoize the table name lookup.
|
115
|
-
#
|
116
|
-
def table_name
|
117
|
-
@table_name ||= profile.orm.table_name( @model )
|
118
|
-
end
|
119
|
-
|
120
|
-
# Memoize the primary key lookup.
|
121
|
-
#
|
122
|
-
def primary_key
|
123
|
-
@primary_key ||= profile.orm.primary_key( @model )
|
124
|
-
end
|
125
|
-
|
126
|
-
# Dump to a SQL SELECT snippet.
|
127
|
-
#
|
128
|
-
def to_sql
|
129
|
-
GUARD.synchronize do
|
130
|
-
attributes_with_primary_key().map{|a| "#{table_name}.#{a.to_s}" }.join(', ')
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
def inspect #:nodoc:
|
135
|
-
"#<#{name()} #{attributes_for_inspect}>"
|
136
|
-
end
|
137
|
-
|
138
|
-
private
|
139
|
-
|
140
|
-
def attributes_for_inspect #:nodoc:
|
141
|
-
@attributes.map{|a| ":#{a}" }.join(', ')
|
142
|
-
end
|
143
|
-
|
144
|
-
def attributes_with_primary_key #:nodoc:
|
145
|
-
@attributes << primary_key
|
146
|
-
end
|
147
|
-
|
148
|
-
end
|
149
|
-
end
|
150
|
-
end
|
@@ -1,181 +0,0 @@
|
|
1
|
-
module Scrooge
|
2
|
-
module Tracker
|
3
|
-
class Resource < Base
|
4
|
-
|
5
|
-
# A Resource tracker is scoped to a
|
6
|
-
#
|
7
|
-
# * controller
|
8
|
-
# * action
|
9
|
-
# * request method
|
10
|
-
# * content type
|
11
|
-
#
|
12
|
-
# and is a container for any Models referenced during the active
|
13
|
-
# request / response cycle.
|
14
|
-
|
15
|
-
GET = /get/i
|
16
|
-
|
17
|
-
GUARD = Monitor.new
|
18
|
-
|
19
|
-
attr_accessor :controller,
|
20
|
-
:action,
|
21
|
-
:method,
|
22
|
-
:format,
|
23
|
-
:models,
|
24
|
-
:is_public
|
25
|
-
|
26
|
-
def initialize
|
27
|
-
super()
|
28
|
-
@models = Set.new
|
29
|
-
yield self if block_given?
|
30
|
-
end
|
31
|
-
|
32
|
-
# Merge this Tracker with another Tracker for the same resource ( multi-process / cluster aggregation )
|
33
|
-
#
|
34
|
-
def merge( other_resource )
|
35
|
-
return unless other_resource
|
36
|
-
models.merge( other_resource.models )
|
37
|
-
models.each do |model|
|
38
|
-
model.merge( other_resource.model( model ) )
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
# Has any Models been tracked ?
|
43
|
-
#
|
44
|
-
def any?
|
45
|
-
GUARD.synchronize do
|
46
|
-
!@models.empty?
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
# Is this a public ( not authenticated ) resource ?
|
51
|
-
#
|
52
|
-
def public?
|
53
|
-
@is_public == true
|
54
|
-
end
|
55
|
-
|
56
|
-
# Is this a private ( authenticated ) resource ?
|
57
|
-
#
|
58
|
-
def private?
|
59
|
-
!public?
|
60
|
-
end
|
61
|
-
|
62
|
-
# Search for a given model instance
|
63
|
-
#
|
64
|
-
def model( model )
|
65
|
-
models.detect{|m| m.name == model.name }
|
66
|
-
end
|
67
|
-
|
68
|
-
# Generates a signature / lookup key.
|
69
|
-
#
|
70
|
-
def signature
|
71
|
-
@signature ||= "#{controller.to_s}_#{action.to_s}_#{method.to_s}_#{private_or_public}"
|
72
|
-
end
|
73
|
-
|
74
|
-
# Only track GET requests
|
75
|
-
#
|
76
|
-
def trackable?
|
77
|
-
!( method || '' ).to_s.match( GET ).nil?
|
78
|
-
end
|
79
|
-
|
80
|
-
# Add a Model to this resource.
|
81
|
-
#
|
82
|
-
def <<( model )
|
83
|
-
GUARD.synchronize do
|
84
|
-
@models << track_model_from( model )
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
def marshal_dump #:nodoc:
|
89
|
-
GUARD.synchronize do
|
90
|
-
{ signature => { :controller => @controller,
|
91
|
-
:action => @action,
|
92
|
-
:method => @method,
|
93
|
-
:format => @format,
|
94
|
-
:models => dumped_models(),
|
95
|
-
:is_public => @is_public } }
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
def marshal_load( data ) #:nodoc:
|
100
|
-
GUARD.synchronize do
|
101
|
-
data = data.to_a.flatten.last
|
102
|
-
@controller = data[:controller]
|
103
|
-
@action = data[:action]
|
104
|
-
@method = data[:method]
|
105
|
-
@format = data[:format]
|
106
|
-
@models = restored_models( data[:models] )
|
107
|
-
@is_public = data[:is_public]
|
108
|
-
self
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
# Yields a collection of Rack middleware to scope Model attributes to the
|
113
|
-
# tracked dataset.
|
114
|
-
#
|
115
|
-
def middleware
|
116
|
-
@middleware ||= begin
|
117
|
-
GUARD.synchronize do
|
118
|
-
models.map do |model|
|
119
|
-
model.middleware( self )
|
120
|
-
end
|
121
|
-
end
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
def inspect #:nodoc:
|
126
|
-
"#<#{@method.to_s.upcase} #{private_or_public} :#{@controller}/#{@action} (#{@format})\n#{models_for_inspect()}"
|
127
|
-
end
|
128
|
-
|
129
|
-
private
|
130
|
-
|
131
|
-
def private_or_public #:nodoc:
|
132
|
-
@is_public ? 'public' : 'private'
|
133
|
-
end
|
134
|
-
|
135
|
-
def track_model_from( model ) #:nodoc:
|
136
|
-
model.is_a?( Array ) ? model_from_enumerable( model ) : setup_model( model )
|
137
|
-
end
|
138
|
-
|
139
|
-
def model_from_enumerable( model ) #:nodoc:
|
140
|
-
model, attribute = model
|
141
|
-
model = setup_model( model )
|
142
|
-
model << attribute
|
143
|
-
model
|
144
|
-
end
|
145
|
-
|
146
|
-
def models_for_inspect #:nodoc:
|
147
|
-
models.map{|m| " - #{m.inspect}" }.join( "\n" )
|
148
|
-
end
|
149
|
-
|
150
|
-
def dumped_models #:nodoc:
|
151
|
-
GUARD.synchronize do
|
152
|
-
@models.to_a.map{|m| m.marshal_dump }
|
153
|
-
end
|
154
|
-
end
|
155
|
-
|
156
|
-
def restored_models( models ) #:nodoc:
|
157
|
-
GUARD.synchronize do
|
158
|
-
models.map do |model|
|
159
|
-
m = model.keys.first # TODO: cleanup
|
160
|
-
Model.new( m ).marshal_load( model )
|
161
|
-
end.to_set
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
def setup_model( model ) #:nodoc:
|
166
|
-
GUARD.synchronize do
|
167
|
-
if model.is_a?( Scrooge::Tracker::Model )
|
168
|
-
model
|
169
|
-
else
|
170
|
-
model_for( model ) || Scrooge::Tracker::Model.new( model )
|
171
|
-
end
|
172
|
-
end
|
173
|
-
end
|
174
|
-
|
175
|
-
def model_for( model ) #:nodoc:
|
176
|
-
@models.detect{|m| m.model.name == model.name }
|
177
|
-
end
|
178
|
-
|
179
|
-
end
|
180
|
-
end
|
181
|
-
end
|