crabfarm 0.4.2 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/assets/live-tools/instructions.html +17 -0
  3. data/assets/live-tools/tools.css +16 -0
  4. data/assets/live-tools/tools.js +41 -47
  5. data/assets/live-tools/welcome.html +18 -0
  6. data/lib/crabfarm/adapters/browser/abstract_webdriver.rb +19 -16
  7. data/lib/crabfarm/adapters/browser/phantom_js.rb +11 -11
  8. data/lib/crabfarm/assertion/fields.rb +8 -0
  9. data/lib/crabfarm/base_navigator.rb +4 -11
  10. data/lib/crabfarm/base_reducer.rb +5 -1
  11. data/lib/crabfarm/cli.rb +13 -13
  12. data/lib/crabfarm/context.rb +15 -3
  13. data/lib/crabfarm/factories/context.rb +24 -0
  14. data/lib/crabfarm/factories/decorable.rb +71 -0
  15. data/lib/crabfarm/factories/navigator.rb +14 -0
  16. data/lib/crabfarm/factories/reducer.rb +14 -0
  17. data/lib/crabfarm/factories/snapshot_reducer.rb +14 -0
  18. data/lib/crabfarm/http_client.rb +2 -5
  19. data/lib/crabfarm/live/context.rb +21 -0
  20. data/lib/crabfarm/live/controller.rb +20 -72
  21. data/lib/crabfarm/live/interactable.rb +6 -2
  22. data/lib/crabfarm/live/manager.rb +90 -18
  23. data/lib/crabfarm/live/navigator_runner.rb +43 -13
  24. data/lib/crabfarm/live/navigator_runner_direct.rb +39 -0
  25. data/lib/crabfarm/live/navigator_runner_rspec.rb +111 -0
  26. data/lib/crabfarm/live/reducer_runner.rb +61 -10
  27. data/lib/crabfarm/live/reducer_runner_direct.rb +41 -0
  28. data/lib/crabfarm/live/reducer_runner_rspec.rb +23 -0
  29. data/lib/crabfarm/live/watcher.rb +21 -7
  30. data/lib/crabfarm/modes/console.rb +1 -1
  31. data/lib/crabfarm/modes/live.rb +7 -4
  32. data/lib/crabfarm/modes/recorder/memento.rb +1 -5
  33. data/lib/crabfarm/modes/recorder/snapshot.rb +2 -2
  34. data/lib/crabfarm/modes/shared/interactive_decorator.rb +0 -1
  35. data/lib/crabfarm/modes/shared/snapshot_decorator.rb +17 -22
  36. data/lib/crabfarm/rspec/navigator_spec_helpers.rb +56 -0
  37. data/lib/crabfarm/rspec/reducer_spec_helpers.rb +29 -0
  38. data/lib/crabfarm/rspec/reducer_spy.rb +36 -0
  39. data/lib/crabfarm/rspec/reducer_spy_manager.rb +38 -0
  40. data/lib/crabfarm/rspec.rb +22 -66
  41. data/lib/crabfarm/support/phantom_runner.rb +77 -0
  42. data/lib/crabfarm/templates/Gemfile.erb +1 -0
  43. data/lib/crabfarm/transition_service.rb +3 -48
  44. data/lib/crabfarm/utils/console.rb +77 -0
  45. data/lib/crabfarm/utils/naming.rb +4 -3
  46. data/lib/crabfarm/utils/resolve.rb +39 -0
  47. data/lib/crabfarm/utils/rspec_runner.rb +54 -0
  48. data/lib/crabfarm/{live/helpers.rb → utils/webdriver.rb} +3 -3
  49. data/lib/crabfarm/version.rb +1 -1
  50. data/lib/crabfarm.rb +24 -3
  51. metadata +23 -6
  52. data/lib/crabfarm/context_factory.rb +0 -32
  53. data/lib/crabfarm/global_state.rb +0 -22
  54. data/lib/crabfarm/phantom_runner.rb +0 -75
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bf6e7d6f8659f3c1bac2e007a467766e23c6edc8
4
- data.tar.gz: 9831fc872ce20aa5f78fff598d774c32363da716
3
+ metadata.gz: 8098614afb567bcfdca40bf7744e9c4e3e90bd32
4
+ data.tar.gz: 80f04f4467eb0165e9a3c3f7170604115bf0bbcb
5
5
  SHA512:
6
- metadata.gz: 5fdfdc33011d754a0effb063b3cd37c4c02f4cf5ea19da217de68290db4f450bb2740b109ab7202f7491ea24055475f1dc6ce22ced7af0e691b9200154a38674
7
- data.tar.gz: e4f6d82029a3a5a9476c2c496681c2ab96f6489c83745c0726c78134c48a3a3d9c4a1af6d77594962c17323541a0f83cd555fb39d3c4d41dd28fe69b8303822d
6
+ metadata.gz: 6c64f0918a254b6db190b8efb22636ab3df15f0c127cb121822d3b408321281307885fd6710d8b268589bb02af9eb2ca31c4be9cd9a2bec158b426aab5e4e2a2
7
+ data.tar.gz: 37e09a7aa5428bf17be7fcd6149a5f1a4a960d168b7b3c1d8f54d119fcb68adca751b25fed8dc112396daec9811ed01066fbaa2ab9b0400483cc149cb821bdc4
@@ -0,0 +1,17 @@
1
+ <!doctype html>
2
+
3
+ <html lang="en">
4
+ <head>
5
+ <meta charset="utf-8">
6
+ <title>Crabfarm Live Reload</title>
7
+
8
+ <style>
9
+ </style>
10
+ </head>
11
+
12
+ <body>
13
+ <h1>Live reload mode</h1>
14
+
15
+ <p>This is a dummy page that marks the start of a new execution</p>
16
+ </body>
17
+ </html>
@@ -30,11 +30,27 @@ div.crabfarm_dialog.crabfarm_dialog_success {
30
30
  background: #009000 !important;
31
31
  }
32
32
 
33
+ div.crabfarm_dialog.crabfarm_dialog_warning {
34
+ border: 6px solid #DD5500;
35
+ background: #DD5500 !important;
36
+ }
37
+
33
38
  div.crabfarm_dialog.crabfarm_dialog_error {
34
39
  border: 6px solid #DD0000;
35
40
  background: #DD0000 !important;
36
41
  }
37
42
 
43
+ div.crabfarm_dialog.crabfarm_dialog_neutral {
44
+ border: 6px solid #BBBBBB;
45
+ background: #EEEEEE !important;
46
+ }
47
+
48
+ div.crabfarm_dialog.crabfarm_dialog_neutral h1,
49
+ div.crabfarm_dialog.crabfarm_dialog_neutral h3,
50
+ div.crabfarm_dialog.crabfarm_dialog_neutral a {
51
+ color: black;
52
+ }
53
+
38
54
  div.crabfarm_dialog .crabfarm_dialog_container {
39
55
  padding: 10px !important;
40
56
  }
@@ -23,64 +23,58 @@ if(!window.crabfarm) {
23
23
  });
24
24
  };
25
25
 
26
- var buildResultDialog = function(_styleClass, _title, _subtitle, _content) {
27
- var overlay = jQuerySG('<div>')
28
- .addClass('selectorgadget_ignore')
29
- .addClass('crabfarm_overlay');
26
+ var formatDialogContent = function(_content, _contentType) {
27
+ if(_contentType == 'json') {
28
+ _content = JSON.parse(_content);
29
+ return jQuerySG('<pre>').html(syntaxHighlight(_content));
30
+ } else {
31
+ return jQuerySG('<pre>').text(_content);
32
+ }
33
+ };
30
34
 
31
- var dialog = jQuerySG('<div>')
32
- .addClass('crabfarm_dialog')
33
- .addClass(_styleClass);
35
+ window.crabfarm = {
36
+ showDialog: function(_type, _title, _subtitle, _content, _contentType) {
34
37
 
35
- var container = jQuerySG('<div>')
36
- .addClass('crabfarm_dialog_container');
38
+ var overlay = jQuerySG('<div>')
39
+ .addClass('selectorgadget_ignore')
40
+ .addClass('crabfarm_overlay');
37
41
 
38
- var button = jQuerySG('<a href="javascript:void(0);">')
39
- .addClass('crabfarm_dialog_close')
40
- .text('x');
42
+ var dialog = jQuerySG('<div>')
43
+ .addClass('crabfarm_dialog')
44
+ .addClass('crabfarm_dialog_' + _type);
41
45
 
42
- var removeOverlay = function() {
43
- overlay.remove();
44
- window.crabfarm.showSelectorGadget();
45
- };
46
+ var container = jQuerySG('<div>')
47
+ .addClass('crabfarm_dialog_container');
46
48
 
47
- overlay.bind("click", removeOverlay);
48
- button.bind("click", removeOverlay);
49
+ var button = jQuerySG('<a href="javascript:void(0);">')
50
+ .addClass('crabfarm_dialog_close')
51
+ .text('x');
49
52
 
50
- var content = jQuerySG('<div>')
51
- .addClass('crabfarm_dialog_content')
52
- .append(_content);
53
+ var removeOverlay = function() {
54
+ overlay.remove();
55
+ window.crabfarm.showSelectorGadget();
56
+ };
53
57
 
54
- container.append(jQuerySG('<h1>').text(_title));
55
- container.append(jQuerySG('<h3>').text(_subtitle));
56
- container.append(content);
58
+ overlay.bind("click", removeOverlay);
59
+ button.bind("click", removeOverlay);
57
60
 
58
- dialog.append(button);
59
- dialog.append(container);
60
- overlay.append(dialog);
61
+ container.append(jQuerySG('<h1>').text(_title));
62
+ if(_subtitle) container.append(jQuerySG('<h3>').text(_subtitle));
63
+ if(_content) {
64
+ var inner = formatDialogContent(_content, _contentType);
61
65
 
62
- jQuerySG('body').append(overlay);
63
- };
66
+ var content = jQuerySG('<div>')
67
+ .addClass('crabfarm_dialog_content')
68
+ .append(inner);
64
69
 
65
- window.crabfarm = {
66
- showResults: function(_data, _elapsed) {
67
- _data = JSON.parse(_data);
68
-
69
- buildResultDialog(
70
- 'crabfarm_dialog_success',
71
- 'Navigation completed!',
72
- 'The page was scrapped in ' + _elapsed + ' seconds',
73
- jQuerySG('<pre>').html(syntaxHighlight(_data))
74
- );
75
- },
70
+ container.append(content);
71
+ }
72
+
73
+ dialog.append(button);
74
+ dialog.append(container);
75
+ overlay.append(dialog);
76
76
 
77
- showError: function(_error, _trace) {
78
- buildResultDialog(
79
- 'crabfarm_dialog_error',
80
- 'Navigation error!',
81
- _error,
82
- jQuerySG('<pre>').text(_trace)
83
- );
77
+ jQuerySG('body').append(overlay);
84
78
  },
85
79
 
86
80
  showSelectorGadget: function() {
@@ -0,0 +1,18 @@
1
+ <!doctype html>
2
+
3
+ <html lang="en">
4
+ <head>
5
+ <meta charset="utf-8">
6
+ <title>Crabfarm Live Reload</title>
7
+
8
+ <style>
9
+ </style>
10
+ </head>
11
+
12
+ <body>
13
+ <h1>Live reload mode</h1>
14
+
15
+ <p>Just edit a tracked file to trigger navigation.</p>
16
+ </body>
17
+
18
+ </html>
@@ -3,32 +3,35 @@ module Crabfarm
3
3
  module Browser
4
4
  class AbstractWebdriver
5
5
 
6
- attr_accessor :config
6
+ attr_accessor :config, :viewer
7
7
 
8
- def initialize(_proxy=nil)
8
+ def initialize(_proxy=nil, _viewer=nil)
9
9
  @config = load_driver_config
10
10
  @config[:proxy] = _proxy
11
+ @viewer = _viewer
11
12
  end
12
13
 
13
14
  def prepare_driver_services
14
- # Nothing by default
15
+ start_server if viewer.nil?
15
16
  end
16
17
 
17
18
  def cleanup_driver_services
18
- # Nothing by default
19
+ stop_server if viewer.nil?
19
20
  end
20
21
 
21
22
  def build_driver(_session_id)
22
- wrap_driver(if Crabfarm.live?
23
- build_live_instance _session_id
24
- else
23
+ wrap_driver(if viewer.nil?
25
24
  build_webdriver_instance
25
+ else
26
+ viewer.attach _session_id == :default_driver
26
27
  end)
27
28
  end
28
29
 
29
- def release_driver(_session_id, _driver)
30
- unless Crabfarm.live? and _session_id == :default_driver
31
- _driver.driver.quit rescue nil
30
+ def release_driver(_session_id, _wrapped)
31
+ if viewer.nil?
32
+ _wrapped.driver.quit rescue nil
33
+ else
34
+ viewer.detach _wrapped.driver
32
35
  end
33
36
  end
34
37
 
@@ -44,12 +47,12 @@ module Crabfarm
44
47
  raise NotImplementedError.new
45
48
  end
46
49
 
47
- def build_live_instance(_session_id)
48
- if _session_id == :default_driver
49
- Crabfarm.live.primary_driver
50
- else
51
- Crabfarm.live.generate_support_driver
52
- end
50
+ def start_server
51
+ # Nothing by default
52
+ end
53
+
54
+ def stop_server
55
+ # Nothing by default
53
56
  end
54
57
 
55
58
  def load_driver_config
@@ -1,29 +1,29 @@
1
1
  require 'crabfarm/support/webdriver_factory'
2
+ require 'crabfarm/support/phantom_runner'
2
3
  require 'crabfarm/adapters/browser/abstract_webdriver'
3
- require 'crabfarm/phantom_runner'
4
4
 
5
5
  module Crabfarm
6
6
  module Adapters
7
7
  module Browser
8
8
  class PhantomJs < AbstractWebdriver
9
9
 
10
- def prepare_driver_services
11
- @phantom = load_and_start_phantom if @phantom.nil? and not Crabfarm.live?
12
- end
13
-
14
- def cleanup_driver_services
15
- @phantom.stop unless @phantom.nil?
16
- @phantom = nil
17
- end
18
-
19
10
  private
20
11
 
21
12
  def build_webdriver_instance
22
13
  Support::WebdriverFactory.build_remote_driver driver_config
23
14
  end
24
15
 
16
+ def start_server
17
+ @phantom = load_and_start_phantom if @phantom.nil?
18
+ end
19
+
20
+ def stop_server
21
+ @phantom.stop unless @phantom.nil?
22
+ @phantom = nil
23
+ end
24
+
25
25
  def load_and_start_phantom
26
- new_phantom = PhantomRunner.new phantom_config
26
+ new_phantom = Support::PhantomRunner.new phantom_config
27
27
  new_phantom.start
28
28
  return new_phantom
29
29
  end
@@ -76,6 +76,14 @@ module Crabfarm
76
76
  end
77
77
  end
78
78
 
79
+ def attributes=(_hash)
80
+ _hash.each { |k,v| send(k.to_s+'=', v) }
81
+ end
82
+
83
+ def mock(_hash)
84
+ @field_hash = _hash
85
+ end
86
+
79
87
  def field_hash
80
88
  @field_hash
81
89
  end
@@ -58,20 +58,13 @@ module Crabfarm
58
58
 
59
59
  private
60
60
 
61
- def reduce_using(_reducer_class, _target, _options={})
62
- if _reducer_class.is_a? String or _reducer_class.is_a? Symbol
63
- _reducer_class = (Utils::Naming.decode_crabfarm_uri(_reducer_class.to_s) + 'Reducer').constantize
64
- end
65
-
66
- reducer = _reducer_class.new _target, @params.merge(_options)
67
- execute_reducer reducer
61
+ def reduce_using(_name_or_class, _target, _options={})
62
+ reducer_class = Utils::Resolve.reducer_class _name_or_class
63
+ reducer = Factories::Reducer.build reducer_class, _target, @params.merge(_options)
64
+ reducer.run
68
65
  reducer
69
66
  end
70
67
 
71
- def execute_reducer(_reducer)
72
- _reducer.run
73
- end
74
-
75
68
  def start_forked_navigation(_name, _value, _block, _mutex)
76
69
  Thread.new {
77
70
  fork = ForkedNavigator.new @context, self, _name, _mutex
@@ -20,7 +20,7 @@ module Crabfarm
20
20
 
21
21
  def self.snapshot_path(_name=nil)
22
22
  _name = self.to_s.underscore if _name.nil?
23
- File.join(GlobalState.snapshots_path, _name + '.' + parser.format)
23
+ Utils::Resolve.snapshot_path _name, parser.format
24
24
  end
25
25
 
26
26
  def parser
@@ -45,6 +45,10 @@ module Crabfarm
45
45
  field_hash
46
46
  end
47
47
 
48
+ def to_json(_options=nil)
49
+ field_hash.to_json _options
50
+ end
51
+
48
52
  def __getobj__
49
53
  @document
50
54
  end
data/lib/crabfarm/cli.rb CHANGED
@@ -16,11 +16,11 @@ module Crabfarm
16
16
  Support::GLI.generate_options c
17
17
 
18
18
  c.action do |global_options,options,args|
19
- next puts "This command can only be ran inside a crabfarm application" unless GlobalState.inside_crawler_app?
19
+ next puts "This command can only be ran inside a crabfarm application" unless Crabfarm.inside_crawler_app?
20
20
 
21
21
  Crabfarm.config.set Support::GLI.parse_options options
22
22
 
23
- ContextFactory.with_context options[:memento] do |context|
23
+ Crabfarm.with_context options[:memento] do |context|
24
24
  require "crabfarm/modes/console"
25
25
  Crabfarm::Modes::Console.process_input context
26
26
  end
@@ -30,7 +30,7 @@ module Crabfarm
30
30
  desc "Starts the crawler in live mode"
31
31
  command [:live, :l] do |c|
32
32
  c.action do |global_options,options,args|
33
- next puts "This command can only be ran inside a crabfarm application" unless GlobalState.inside_crawler_app?
33
+ next puts "This command can only be ran inside a crabfarm application" unless Crabfarm.inside_crawler_app?
34
34
 
35
35
  require "crabfarm/modes/live"
36
36
  Crabfarm::Modes::Live.start_watch
@@ -60,7 +60,7 @@ module Crabfarm
60
60
  Support::GLI.generate_options c
61
61
 
62
62
  c.action do |global_options,options,args|
63
- next puts "This command can only be ran inside a crabfarm application" unless GlobalState.inside_crawler_app?
63
+ next puts "This command can only be ran inside a crabfarm application" unless Crabfarm.inside_crawler_app?
64
64
 
65
65
  Crabfarm.config.set Support::GLI.parse_options options
66
66
 
@@ -72,7 +72,7 @@ module Crabfarm
72
72
  server_options[:Threads] = options[:threads] unless options[:threads].nil?
73
73
  server_options[:Verbose] = options[:verbose]
74
74
 
75
- ContextFactory.with_context options[:memento] do |context|
75
+ Crabfarm.with_context options[:memento] do |context|
76
76
  require "crabfarm/modes/server"
77
77
  Crabfarm::Modes::Server.serve context, server_options
78
78
  end
@@ -88,7 +88,7 @@ module Crabfarm
88
88
  app.flag [:r, :remote]
89
89
 
90
90
  app.action do |global_options,options,args|
91
- next puts "This command cannot be ran inside a crabfarm application" if GlobalState.inside_crawler_app?
91
+ next puts "This command cannot be ran inside a crabfarm application" if Crabfarm.inside_crawler_app?
92
92
 
93
93
  require "crabfarm/modes/generator"
94
94
  Crabfarm::Modes::Generator.generate_app(Dir.pwd, args[0], options[:remote])
@@ -105,7 +105,7 @@ module Crabfarm
105
105
  sub.switch :reducer, :default_value => true
106
106
 
107
107
  sub.action do |global_options,options,args|
108
- next puts "This command can only be ran inside a crabfarm application" unless GlobalState.inside_crawler_app?
108
+ next puts "This command can only be ran inside a crabfarm application" unless Crabfarm.inside_crawler_app?
109
109
 
110
110
  require "crabfarm/modes/generator"
111
111
  Crabfarm::Modes::Generator.generate_navigator(GlobalState.app_path, args[0], options)
@@ -116,7 +116,7 @@ module Crabfarm
116
116
  c.desc "Generates a new crabfarm reducer and reducer spec"
117
117
  c.command :reducer do |sub|
118
118
  sub.action do |global_options,options,args|
119
- next puts "This command can only be ran inside a crabfarm application" unless GlobalState.inside_crawler_app?
119
+ next puts "This command can only be ran inside a crabfarm application" unless Crabfarm.inside_crawler_app?
120
120
 
121
121
  require "crabfarm/modes/generator"
122
122
  Crabfarm::Modes::Generator.generate_reducer(GlobalState.app_path, args[0])
@@ -126,7 +126,7 @@ module Crabfarm
126
126
  c.desc "Generates a new crabfarm struct"
127
127
  c.command :struct do |sub|
128
128
  sub.action do |global_options,options,args|
129
- next puts "This command can only be ran inside a crabfarm application" unless GlobalState.inside_crawler_app?
129
+ next puts "This command can only be ran inside a crabfarm application" unless Crabfarm.inside_crawler_app?
130
130
 
131
131
  require "crabfarm/modes/generator"
132
132
  Crabfarm::Modes::Generator.generate_struct(GlobalState.app_path, args[0])
@@ -144,7 +144,7 @@ module Crabfarm
144
144
  memento.switch [:p, :playback], :default_value => false
145
145
 
146
146
  memento.action do |global_options, options, args|
147
- next puts "This command can only be ran inside a crabfarm application" unless GlobalState.inside_crawler_app?
147
+ next puts "This command can only be ran inside a crabfarm application" unless Crabfarm.inside_crawler_app?
148
148
 
149
149
  require "crabfarm/modes/recorder/memento"
150
150
  Crabfarm::Modes::Recorder::Memento.start args[0], options[:playback]
@@ -162,9 +162,9 @@ module Crabfarm
162
162
  snap.flag [:q, :query]
163
163
 
164
164
  snap.action do |global_options, options, args|
165
- next puts "This command can only be ran inside a crabfarm application" unless GlobalState.inside_crawler_app?
165
+ next puts "This command can only be ran inside a crabfarm application" unless Crabfarm.inside_crawler_app?
166
166
 
167
- ContextFactory.with_context options[:memento] do |context|
167
+ Crabfarm.with_context options[:memento] do |context|
168
168
  require "crabfarm/modes/recorder/snapshot"
169
169
  Crabfarm::Modes::Recorder::Snapshot.start context, args[0], options[:query]
170
170
  end
@@ -182,7 +182,7 @@ module Crabfarm
182
182
  c.switch :unsafe, :default_value => false
183
183
 
184
184
  c.action do |global_options,options,args|
185
- next puts "This command can only be ran inside a crabfarm application" unless GlobalState.inside_crawler_app?
185
+ next puts "This command can only be ran inside a crabfarm application" unless Crabfarm.inside_crawler_app?
186
186
 
187
187
  options[:remote] = args[0]
188
188
 
@@ -50,11 +50,15 @@ module Crabfarm
50
50
 
51
51
  def init_driver_factory
52
52
  if @factory.nil?
53
- @factory = Strategies.load(:browser, config.browser).new proxy
53
+ @factory = build_driver_factory
54
54
  @factory.prepare_driver_services
55
55
  end
56
56
  end
57
57
 
58
+ def build_driver_factory
59
+ Strategies.load(:browser, config.browser).new proxy, viewer
60
+ end
61
+
58
62
  def release_driver_factory
59
63
  @factory.cleanup_driver_services unless @factory.nil?
60
64
  @factory.nil?
@@ -70,7 +74,11 @@ module Crabfarm
70
74
  end
71
75
 
72
76
  def init_http_client
73
- @http = HttpClient.new proxy if @http.nil?
77
+ @http = build_http_client if @http.nil?
78
+ end
79
+
80
+ def build_http_client
81
+ HttpClient.new proxy, viewer
74
82
  end
75
83
 
76
84
  def release_http_client
@@ -78,7 +86,11 @@ module Crabfarm
78
86
  end
79
87
 
80
88
  def proxy
81
- Crabfarm.config.proxy
89
+ config.proxy
90
+ end
91
+
92
+ def viewer
93
+ nil # no viewer provided by default
82
94
  end
83
95
 
84
96
  def config
@@ -0,0 +1,24 @@
1
+ require 'crabfarm/factories/decorable'
2
+
3
+ module Crabfarm
4
+ module Factories
5
+ module Context
6
+ include Decorable
7
+
8
+ def self.default_build(_memento)
9
+ if _memento.nil?
10
+ Crabfarm::Context.new
11
+ else
12
+ load_crabtrap_context _memento
13
+ end
14
+ end
15
+
16
+ def self.load_crabtrap_context(_memento)
17
+ require 'crabfarm/crabtrap_context'
18
+ m_path = Utils::Resolve.memento_path _memento
19
+ raise ResourceNotFoundError.new "Could not find memento '#{_memento}'" unless File.exists? m_path
20
+ Crabfarm::CrabtrapContext.new :replay, m_path
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,71 @@
1
+ module Crabfarm
2
+ module Factories
3
+ module Decorable
4
+
5
+ class DecoratorChain
6
+
7
+ attr_reader :base, :decorator
8
+
9
+ def initialize(_base, _decorator)
10
+ @base = _base # al
11
+ @decorator = _decorator
12
+ end
13
+
14
+ def prepare(_args)
15
+ obj = if @decorator.respond_to? :prepare
16
+ @decorator.prepare(*_args)
17
+ else nil end
18
+
19
+ return obj if @base.nil?
20
+ base_obj = @base.prepare _args
21
+ raise ConfigurationError.new 'Decorator race condition' if obj and base_obj
22
+ obj || base_obj
23
+ end
24
+
25
+ def decorate(_obj)
26
+ if @decorator.respond_to? :decorate
27
+ new_obj = @decorator.decorate _obj
28
+ _obj = new_obj if new_obj
29
+ end
30
+
31
+ return _obj if @base.nil?
32
+ @base.decorate _obj
33
+ end
34
+
35
+ end
36
+
37
+ def self.included(klass)
38
+ klass.extend ClassMethods
39
+ end
40
+
41
+ module ClassMethods
42
+
43
+ def with_decorator(_decorator)
44
+ @decorator = DecoratorChain.new @decorator, _decorator
45
+ begin
46
+ return yield
47
+ ensure
48
+ @decorator = @decorator.base
49
+ end
50
+ end
51
+
52
+ def build(*_args)
53
+ obj = if @decorator
54
+ @decorator.prepare _args
55
+ else nil end
56
+
57
+ if obj.nil?
58
+ obj = default_build(*_args)
59
+ end
60
+
61
+ if @decorator
62
+ @decorator.decorate obj
63
+ else obj end
64
+ end
65
+
66
+ end
67
+
68
+ end
69
+
70
+ end
71
+ end
@@ -0,0 +1,14 @@
1
+ require 'crabfarm/factories/decorable'
2
+
3
+ module Crabfarm
4
+ module Factories
5
+ module Navigator
6
+ include Decorable
7
+
8
+ def self.default_build(_class, _context, _params)
9
+ _class.new _context, _params
10
+ end
11
+
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ require 'crabfarm/factories/decorable'
2
+
3
+ module Crabfarm
4
+ module Factories
5
+ module Reducer
6
+ include Decorable
7
+
8
+ def self.default_build(_class, _target, _params)
9
+ _class.new _target, _params
10
+ end
11
+
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ require 'crabfarm/factories/decorable'
2
+
3
+ module Crabfarm
4
+ module Factories
5
+ module SnapshotReducer
6
+ include Decorable
7
+
8
+ def self.default_build(_class, _path, _params)
9
+ data = File.read _path
10
+ Reducer.build(_class, data, _params)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -24,11 +24,8 @@ module Crabfarm
24
24
 
25
25
  attr_reader :proxy_addr, :proxy_port
26
26
 
27
- def initialize(_proxy=nil)
28
- if Crabfarm.live?
29
- @proxy_addr = '127.0.0.1'
30
- @proxy_port = Crabfarm.live.proxy_port
31
- elsif _proxy.nil?
27
+ def initialize(_proxy=nil, _viewer=nil)
28
+ if _proxy.nil?
32
29
  @proxy_addr = nil
33
30
  @proxy_port = nil
34
31
  else