fetch 0.0.4 → 0.0.5

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a10520fb3d8cc9508aef80fe19c88dd4b5b72a71
4
- data.tar.gz: cc19fba644b2236f5833f312bf002b495258caf7
3
+ metadata.gz: 538eaf280947e75a0999edfea670488a353d6c0d
4
+ data.tar.gz: 39ebdb1b870ef7afd28d278ada14f84bb338f859
5
5
  SHA512:
6
- metadata.gz: 4b23e3bb9c6e49e85d07e37791d46343d5f36467dc279498a9da855ff8580ce3e0df3515bbf58b17222b7b013ee1be5619ec6af746fc7607c573ced140abc07b
7
- data.tar.gz: 3239bdfb8eb3ce1855efcad29227fa59ff0c23893781da47b85cae867440edc1e99d35188777e482b3764ec5853b81313b0d604a61e0324d0dae52dc2b192111
6
+ metadata.gz: dd5d3fe051dcdf0582ac359c3865e40a048bca131e1479070491c2a93b28f23aa18be31a126fca6a4d94c340a82a2b6ea14f3596b93bb66c870d4d2151b3510e
7
+ data.tar.gz: e75ed279223063297541ef88f4feedd8cb805c4ec50c7c2f6fba9bc59157d5366cd73b674369299717e8833016367202a078c9d0fde6efd3238c4ffe0f6f605f
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## Version 0.0.5
4
+
5
+ * The `after_fetch` callbacks are run in the reverse order of which they were
6
+ defined.
7
+
3
8
  ## Version 0.0.4
4
9
 
5
10
  * Exceptions are raised after the general `Fetch::Base` `error` callback is
data/README.md CHANGED
@@ -107,6 +107,52 @@ repos.
107
107
 
108
108
  ## Good to know
109
109
 
110
+ ### Doing something before a fetch
111
+
112
+ If you need to run something before a fetch is started, you can do it using the
113
+ `before_fetch` callback.
114
+
115
+ ```ruby
116
+ class UserFetcher < Fetch::Module
117
+ modules Facebook::UserInfoFetch,
118
+ Github::UserInfoFetch
119
+
120
+ before_fetch do
121
+ # Do something before the fetch.
122
+ end
123
+ end
124
+
125
+ user = User.find(123)
126
+ UserFetcher.new(user).fetch
127
+ # => `before_fetch` is run before fetching
128
+ ```
129
+
130
+ **Note:** If you define more than one `before_fetch` callback, they are run in the order
131
+ in which they were defined.
132
+
133
+ ### Doing something after a fetch
134
+
135
+ If you need to run something after a fetch is completed, you can do it using
136
+ the `after_fetch` callback.
137
+
138
+ ```ruby
139
+ class UserFetcher < Fetch::Module
140
+ modules Facebook::UserInfoFetch,
141
+ Github::UserInfoFetch
142
+
143
+ after_fetch do
144
+ # Do something after the fetch has completed.
145
+ end
146
+ end
147
+
148
+ user = User.find(123)
149
+ UserFetcher.new(user).fetch
150
+ # => `after_fetch` is run after fetching
151
+ ```
152
+
153
+ **Note:** If you define more than one `after_fetch` callback, they are run in
154
+ the *reverse* order of which they were defined.
155
+
110
156
  ### Adding defaults to your requests
111
157
 
112
158
  Each fetch module has a `defaults` callback that you can use to set up defaults
@@ -20,10 +20,11 @@ module Fetch
20
20
  :load,
21
21
  :init,
22
22
  :before_fetch,
23
- :after_fetch,
24
23
  :progress,
25
24
  :error
26
25
 
26
+ define_callback :after_fetch, reverse: true
27
+
27
28
  def initialize(fetchable = nil)
28
29
  @fetchable = fetchable
29
30
  end
@@ -15,19 +15,25 @@ module Fetch
15
15
  #
16
16
  # run_callbacks_for(:before_fetch)
17
17
  # run_callbacks_for(:progress, 12) # 12 percent done
18
- def run_callbacks_for(name, *args)
19
- self.class.callbacks[name].map do |block|
20
- run_callback(*args, &block)
18
+ def run_callbacks_for(name, args, reverse)
19
+ callbacks_for(name, reverse).map do |block|
20
+ run_callback(block, args)
21
21
  end
22
22
  end
23
23
 
24
- def run_last_callback_for(name, *args)
25
- if callback = self.class.callbacks[name].last
26
- run_callback(*args, &callback)
24
+ def run_last_callback_for(name, args, reverse)
25
+ if block = callbacks_for(name, reverse).last
26
+ run_callback(block, args)
27
27
  end
28
28
  end
29
29
 
30
- def run_callback(*args, &block)
30
+ def callbacks_for(name, reverse)
31
+ callbacks = self.class.callbacks[name]
32
+ callbacks = callbacks.reverse if reverse
33
+ callbacks
34
+ end
35
+
36
+ def run_callback(block, args)
31
37
  instance_exec(*args, &block)
32
38
  end
33
39
 
@@ -39,17 +45,20 @@ module Fetch
39
45
 
40
46
  # Defines callback methods on the class level.
41
47
  def define_callback(*names)
48
+ options = names.last.is_a?(Hash) ? names.pop : {}
49
+ reverse = !!options[:reverse]
50
+
42
51
  names.each do |name|
43
52
  define_singleton_method name do |*values, &block|
44
- create_callback_for(name, *values, &block)
53
+ create_callback_for(name, values, block)
45
54
  end
46
55
 
47
56
  define_method name do |*args|
48
- run_callbacks_for(name, *args).last
57
+ run_callbacks_for(name, args, reverse).last
49
58
  end
50
59
 
51
60
  define_method "#{name}!" do |*args|
52
- run_last_callback_for(name, *args)
61
+ run_last_callback_for(name, args, reverse)
53
62
  end
54
63
  end
55
64
  end
@@ -63,12 +72,12 @@ module Fetch
63
72
 
64
73
  private
65
74
 
66
- def create_callback_for(name, *values, &block)
67
- add_callback(name) { values } if values.any?
68
- add_callback(name, &block) if block
75
+ def create_callback_for(name, values, block)
76
+ add_callback(name, ->{ values }) if values.any?
77
+ add_callback(name, block) if block
69
78
  end
70
79
 
71
- def add_callback(name, &block)
80
+ def add_callback(name, block)
72
81
  callbacks[name] << block
73
82
  end
74
83
  end
@@ -1,3 +1,3 @@
1
1
  module Fetch
2
- VERSION = "0.0.4"
2
+ VERSION = "0.0.5"
3
3
  end
@@ -0,0 +1,13 @@
1
+ require "test_helper"
2
+
3
+ class AfterFetchTest < Minitest::Test
4
+ def test_after_fetch_runs_when_fetching
5
+ actions = []
6
+ klass = Class.new(Fetch::Base) do
7
+ after_fetch { actions << "first after" }
8
+ after_fetch { actions << "second after" }
9
+ end
10
+ klass.new.fetch
11
+ assert_equal ["second after", "first after"], actions
12
+ end
13
+ end
@@ -0,0 +1,19 @@
1
+ require "test_helper"
2
+
3
+ class BaseTest < Minitest::Test
4
+ def test_sends_fetchable_to_modules
5
+ stub_request(:get, "https://api.github.com/users/lassebunk").to_return(body: "id: 1234")
6
+ actions = []
7
+ mod = Class.new(Fetch::Module) do
8
+ request do |req|
9
+ req.url = "https://api.github.com/users/#{fetchable.login}"
10
+ req.process do |body|
11
+ actions << "process: #{body}"
12
+ end
13
+ end
14
+ end
15
+ user = OpenStruct.new(login: "lassebunk")
16
+ MockFetcher(mod).new(user).fetch
17
+ assert_equal ["process: id: 1234"], actions
18
+ end
19
+ end
@@ -0,0 +1,13 @@
1
+ require "test_helper"
2
+
3
+ class BeforeFetchTest < Minitest::Test
4
+ def test_before_fetch_runs_when_fetching
5
+ actions = []
6
+ klass = Class.new(Fetch::Base) do
7
+ before_fetch { actions << "first before" }
8
+ before_fetch { actions << "second before" }
9
+ end
10
+ klass.new.fetch
11
+ assert_equal ["first before", "second before"], actions
12
+ end
13
+ end
File without changes
File without changes
@@ -0,0 +1,95 @@
1
+ require "test_helper"
2
+
3
+ class ProgressTest < Minitest::Test
4
+ def test_progress_with_single_module
5
+ stub_request(:get, "http://test.com/one").to_return(body: "got one")
6
+
7
+ mod = Class.new(Fetch::Module) do
8
+ 3.times do
9
+ request do |req|
10
+ req.url = "http://test.com/one"
11
+ end
12
+ end
13
+ end
14
+
15
+ updates = []
16
+
17
+ klass = Class.new(MockFetcher(mod)) do
18
+ progress do |percent|
19
+ updates << percent
20
+ end
21
+ end
22
+
23
+ klass.new.fetch
24
+ assert_equal [0, 33, 66, 100], updates
25
+ end
26
+
27
+ def test_progress_with_multiple_modules
28
+ stub_request(:get, "http://test.com/one").to_return(body: "got one")
29
+
30
+ mods = 3.times.map do
31
+ Class.new(Fetch::Module) do
32
+ 2.times do
33
+ request do |req|
34
+ req.url = "http://test.com/one"
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ updates = []
41
+
42
+ klass = Class.new(MockFetcher(mods)) do
43
+ progress do |percent|
44
+ updates << percent
45
+ end
46
+ end
47
+
48
+ klass.new.fetch
49
+ assert_equal [0, 16, 33, 50, 66, 83, 100], updates
50
+ end
51
+
52
+ def test_progress_with_http_failure
53
+ stub_request(:get, "http://test.com/one").to_return(body: "something went wrong", status: 500)
54
+ updates = []
55
+ mods = 3.times.map do
56
+ Class.new(Fetch::Module) do
57
+ request do |req|
58
+ req.url = "http://test.com/one"
59
+ end
60
+ end
61
+ end
62
+ klass = Class.new(MockFetcher(mods)) do
63
+ progress do |percent|
64
+ updates << percent
65
+ end
66
+ end
67
+
68
+ klass.new.fetch
69
+ assert_equal [0, 33, 66, 100], updates
70
+ end
71
+
72
+ def test_progress_with_handled_process_error
73
+ stub_request(:get, "http://test.com/one").to_return(body: "ok")
74
+ updates = []
75
+ mods = 3.times.map do
76
+ Class.new(Fetch::Module) do
77
+ request do |req|
78
+ req.url = "http://test.com/one"
79
+ req.process do |body|
80
+ wont_work
81
+ end
82
+ req.error { }
83
+ end
84
+ end
85
+ end
86
+ klass = Class.new(MockFetcher(mods)) do
87
+ progress do |percent|
88
+ updates << percent
89
+ end
90
+ end
91
+
92
+ klass.new.fetch
93
+ assert_equal [0, 33, 66, 100], updates
94
+ end
95
+ end
@@ -1,6 +1,6 @@
1
1
  require "test_helper"
2
2
 
3
- class CallbackTest < Minitest::Test
3
+ class Test < Minitest::Test
4
4
  def test_callbacks
5
5
  actions = []
6
6
  klass = Class.new do
@@ -42,6 +42,38 @@ class CallbackTest < Minitest::Test
42
42
  assert_equal "second", klass.new.before
43
43
  end
44
44
 
45
+ def test_bang_method_only_runs_last_callback
46
+ klass = Class.new do
47
+ include Fetch::Callbacks
48
+ define_callback :before
49
+ before { this_shouldnt_be_run! }
50
+ before { "ok" }
51
+ end
52
+ assert_equal "ok", klass.new.before!
53
+ end
54
+
55
+ def test_callbacks_can_run_in_reverse_order
56
+ actions = []
57
+ klass = Class.new do
58
+ include Fetch::Callbacks
59
+ define_callback :after, reverse: true
60
+ after { actions << "first after" }
61
+ after { actions << "second after" }
62
+ end
63
+ klass.new.after
64
+ assert_equal ["second after", "first after"], actions
65
+ end
66
+
67
+ def test_reversed_bang_method_runs_only_first_callback
68
+ klass = Class.new do
69
+ include Fetch::Callbacks
70
+ define_callback :after, reverse: true
71
+ after { "first one defined" }
72
+ after { this_cant_run! }
73
+ end
74
+ assert_equal "first one defined", klass.new.after!
75
+ end
76
+
45
77
  def test_callbacks_take_optional_arguments
46
78
  actions = []
47
79
  klass = Class.new do
@@ -0,0 +1,104 @@
1
+ require "test_helper"
2
+
3
+ class AfterProcessTest < Minitest::Test
4
+ def test_after_process_callback_set_in_request
5
+ words = %w{one two}
6
+ words.each { |w| stub_request(:get, "http://test.com/#{w}").to_return(body: "got #{w}") }
7
+
8
+ stub_request(:get, "http://test.com/two").to_return(body: "got two")
9
+ actions = []
10
+ mod = Class.new(Fetch::Module) do
11
+ words.each do |word|
12
+ request do |req|
13
+ req.url = "http://test.com/#{word}"
14
+ req.after_process do
15
+ actions << "after process #{word}"
16
+ end
17
+ req.process do |body|
18
+ actions << "process #{word}"
19
+ end
20
+ end
21
+ end
22
+ end
23
+ MockFetcher(mod).new.fetch
24
+ assert_equal ["process one", "after process one", "process two", "after process two"], actions
25
+ end
26
+
27
+ def test_after_process_callback_scope_set_in_request
28
+ words = %w{one two}
29
+ words.each { |w| stub_request(:get, "http://test.com/#{w}").to_return(body: "got #{w}") }
30
+
31
+ stub_request(:get, "http://test.com/two").to_return(body: "got two")
32
+ actions = []
33
+ mod = Class.new(Fetch::Module) do
34
+ words.each do |word|
35
+ request do |req|
36
+ req.url = "http://test.com/#{word}"
37
+ req.after_process do
38
+ actions << "after process #{word} (#{some_instance_method})"
39
+ end
40
+ req.process do |body|
41
+ actions << "process #{word}"
42
+ end
43
+ end
44
+ end
45
+ def some_instance_method
46
+ "ok"
47
+ end
48
+ end
49
+ MockFetcher(mod).new.fetch
50
+ assert_equal ["process one", "after process one (ok)", "process two", "after process two (ok)"], actions
51
+ end
52
+
53
+ def test_after_process_callback_set_in_module
54
+ words = %w{one two}
55
+ words.each { |w| stub_request(:get, "http://test.com/#{w}").to_return(body: "got #{w}") }
56
+
57
+ stub_request(:get, "http://test.com/two").to_return(body: "got two")
58
+ actions = []
59
+ mod = Class.new(Fetch::Module) do
60
+ words.each do |word|
61
+ request do |req|
62
+ req.url = "http://test.com/#{word}"
63
+ req.process do |body|
64
+ actions << "process #{word}"
65
+ end
66
+ end
67
+ end
68
+
69
+ after_process do
70
+ actions << "after process"
71
+ end
72
+ end
73
+ MockFetcher(mod).new.fetch
74
+ assert_equal ["process one", "after process", "process two", "after process"], actions
75
+ end
76
+
77
+ def test_after_process_callback_scope_set_in_module
78
+ words = %w{one two}
79
+ words.each { |w| stub_request(:get, "http://test.com/#{w}").to_return(body: "got #{w}") }
80
+
81
+ stub_request(:get, "http://test.com/two").to_return(body: "got two")
82
+ actions = []
83
+ mod = Class.new(Fetch::Module) do
84
+ words.each do |word|
85
+ request do |req|
86
+ req.url = "http://test.com/#{word}"
87
+ req.process do |body|
88
+ actions << "process #{word}"
89
+ end
90
+ end
91
+ end
92
+
93
+ after_process do
94
+ actions << "after process (#{some_instance_method})"
95
+ end
96
+
97
+ def some_instance_method
98
+ "ok"
99
+ end
100
+ end
101
+ MockFetcher(mod).new.fetch
102
+ assert_equal ["process one", "after process (ok)", "process two", "after process (ok)"], actions
103
+ end
104
+ end