crabfarm 0.4.2 → 0.5.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.
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