restify 1.0.1.beta1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3b00cff50046f420707ed6d6e8851d74e1392f5f
4
- data.tar.gz: fa5553ba030b9ec8bcd2457d4c24a866ad1db293
3
+ metadata.gz: 3acb2cc3581b8c3c47ad27c6ab1ea34406d7fa39
4
+ data.tar.gz: 91e4eb0b80116b6e13d8aca4cf8942de6ef064bc
5
5
  SHA512:
6
- metadata.gz: 76ad0f4229b26ba714763793a086ba2cffb62642fa1ebb329037e1b542a5802ace3f29acc1220100488f7010b2eae5963a729d812475d17fa7834e43079a1004
7
- data.tar.gz: 32908687b5e5b3234ccc5985cf1184a179d60f5589383482a4dff87abf168f7dbbefe101b4f7a4fcbe0d5ccb10b0b2d5e2c9a46dbae11dfd9cf54ddedb94baae
6
+ metadata.gz: e314678c3419674b6a709db0ba224bd46b704ba24455db084dba0f7e9dfccaf4c633243e384411d1fd7046a0c34480f19353a2313190c70ed62599eb50d04a3a
7
+ data.tar.gz: 8378f0c684c143cab5c92b4799a1424370f3b0db6395296d7b4bf38b3b8c48e08274035dfcd770f8ecc52308e9b80d74247628e125635f477f2fcec7436ba670
data/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.1.0
4
+
5
+ * Return response body if no processor matches (#7)
6
+ * Add shortcuts for creating fulfilled / rejected promises (#6)
7
+
3
8
  ## 1.0.0
4
9
 
5
10
  * Experimental cache API doing nothing for now
data/lib/restify.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'restify/version'
2
4
 
3
5
  require 'hashie'
@@ -30,7 +32,7 @@ module Restify
30
32
  require 'restify/processors/json'
31
33
  end
32
34
 
33
- PROCESSORS = [Processors::Json]
35
+ PROCESSORS = [Processors::Json].freeze
34
36
 
35
37
  extend Global
36
38
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Restify
2
4
  module Adapter
3
5
  class Base
@@ -7,8 +9,8 @@ module Restify
7
9
  end
8
10
  end
9
11
 
10
- def call_native(request, writer)
11
- throw NotImplementedError.new '#call_native not implemented. Subclass responsibility.'
12
+ def call_native(_request, _writer)
13
+ throw NotImplementedError.new 'Subclass responsibility'
12
14
  end
13
15
  end
14
16
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'eventmachine'
2
4
  require 'em-http-request'
3
5
 
@@ -26,6 +28,7 @@ module Restify
26
28
  @requests ||= []
27
29
  end
28
30
 
31
+ # rubocop:disable Style/IdenticalConditionalBranches
29
32
  def call(request, writer, retried = false)
30
33
  if requests.empty?
31
34
  requests << [request, writer, retried]
@@ -43,6 +46,10 @@ module Restify
43
46
  @pipeline
44
47
  end
45
48
 
49
+ # rubocop:disable Metrics/AbcSize
50
+ # rubocop:disable Metrics/CyclomaticComplexity
51
+ # rubocop:disable Metrics/MethodLength
52
+ # rubocop:disable Metrics/PerceivedComplexity
46
53
  def process_next
47
54
  return if requests.empty?
48
55
 
@@ -55,7 +62,7 @@ module Restify
55
62
  query: request.uri.normalized_query,
56
63
  body: request.body,
57
64
  head: request.headers
58
- rescue Exception => err
65
+ rescue Exception => err # rubocop:disable RescueException
59
66
  writer.reject err
60
67
  requests.shift unless pipeline?
61
68
  return
@@ -93,8 +100,7 @@ module Restify
93
100
  EventMachine.next_tick { call request, writer }
94
101
  else
95
102
  begin
96
- raise RuntimeError.new \
97
- "(#{req.response_header.status}) #{req.error}"
103
+ raise "(#{req.response_header.status}) #{req.error}"
98
104
  rescue => e
99
105
  writer.reject e
100
106
  end
@@ -117,6 +123,8 @@ module Restify
117
123
  end
118
124
 
119
125
  def ensure_running
126
+ return if EventMachine.reactor_running?
127
+
120
128
  Thread.new do
121
129
  begin
122
130
  EventMachine.run {}
@@ -124,7 +132,7 @@ module Restify
124
132
  puts "#{self.class} -> #{e}\n#{e.backtrace.join("\n")}"
125
133
  raise e
126
134
  end
127
- end unless EventMachine.reactor_running?
135
+ end
128
136
  end
129
137
  end
130
138
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'typhoeus'
2
4
 
3
5
  module Restify
@@ -51,7 +53,7 @@ module Restify
51
53
  def handle(native_response, writer, request)
52
54
  writer.fulfill convert_back(native_response, request)
53
55
 
54
- @hydra.queue convert(*@queue.pop(true)) while !@queue.empty?
56
+ @hydra.queue convert(*@queue.pop(true)) until @queue.empty?
55
57
  end
56
58
 
57
59
  def convert_back(response, request)
@@ -69,6 +71,7 @@ module Restify
69
71
  end
70
72
  end
71
73
 
74
+ # rubocop:disable Metrics/MethodLength
72
75
  def start
73
76
  Thread.new do
74
77
  loop do
data/lib/restify/cache.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Restify
2
4
  class Cache
3
5
  def initialize(store)
@@ -9,15 +11,15 @@ module Restify
9
11
  return response
10
12
  end
11
13
 
12
- yield(request).then do |response|
13
- cache(response)
14
- response
14
+ yield(request).then do |new_response|
15
+ cache(new_response)
16
+ new_response
15
17
  end
16
18
  end
17
19
 
18
20
  private
19
21
 
20
- def match(request)
22
+ def match(_request)
21
23
  false
22
24
  end
23
25
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Restify
2
4
  # A resource context.
3
5
  #
@@ -19,7 +21,12 @@ module Restify
19
21
  attr_reader :options
20
22
 
21
23
  def initialize(uri, **kwargs)
22
- @uri = uri.is_a?(Addressable::URI) ? uri : Addressable::URI.parse(uri.to_s)
24
+ @uri = if uri.is_a?(Addressable::URI)
25
+ uri
26
+ else
27
+ @uri = Addressable::URI.parse(uri.to_s)
28
+ end
29
+
23
30
  @options = kwargs
24
31
  end
25
32
 
@@ -34,20 +41,21 @@ module Restify
34
41
 
35
42
  def process(response)
36
43
  context = inherit response.uri
37
- processor = Restify::PROCESSORS.find { |p| p.accept? response }
44
+ processor = Restify::PROCESSORS.find {|p| p.accept? response }
38
45
  processor ||= Restify::Processors::Base
39
46
 
40
47
  processor.new(context, response).resource
41
48
  end
42
49
 
43
- def request(method, uri, data = nil, opts = {})
50
+ # rubocop:disable Metrics/MethodLength
51
+ def request(method, uri, data = nil, _opts = {})
44
52
  request = Request.new \
45
53
  method: method,
46
54
  uri: join(uri),
47
55
  data: data,
48
56
  headers: options.fetch(:headers, {})
49
57
 
50
- ret = cache.call(request) {|request| adapter.call(request) }
58
+ ret = cache.call(request) {|req| adapter.call(req) }
51
59
  ret.then do |response|
52
60
  if response.success?
53
61
  process response
@@ -75,7 +83,7 @@ module Restify
75
83
  when 500...600
76
84
  raise ServerError.new(response)
77
85
  else
78
- raise RuntimeError.new "Unknown response code: #{response.code}"
86
+ raise "Unknown response code: #{response.code}"
79
87
  end
80
88
  end
81
89
  end
data/lib/restify/error.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Restify
2
4
  #
3
5
  # A {ResponseError} is returned on a non-successful
@@ -36,7 +38,9 @@ module Restify
36
38
  #
37
39
  def errors
38
40
  if response.decoded_body
39
- response.decoded_body['errors'] || response.decoded_body[:errors] || response.decoded_body
41
+ response.decoded_body['errors'] ||
42
+ response.decoded_body[:errors] ||
43
+ response.decoded_body
40
44
  else
41
45
  response.body
42
46
  end
@@ -1,7 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Restify
2
4
  module Global
3
- extend self
4
-
5
5
  def new(uri, **opts)
6
6
  context = resolve_context uri, **opts
7
7
 
data/lib/restify/link.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Restify
2
4
  #
3
5
  # A {Link} represents a single entry from the Link header
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Restify
2
4
  #
3
5
  module Processors
@@ -36,7 +38,7 @@ module Restify
36
38
  # Should be overridden in subclass.
37
39
  #
38
40
  def load
39
-
41
+ body
40
42
  end
41
43
 
42
44
  # @!method body
@@ -50,18 +52,17 @@ module Restify
50
52
  name = link.metadata['rel']
51
53
  value = link.uri
52
54
 
53
- if !name.empty? && !relations.key?(name)
54
- relations[name] = value
55
- end
55
+ relations[name] = value if !name.empty? && !relations.key?(name)
56
56
  end
57
57
 
58
- if (location = @response.follow_location)
59
- relations[:_restify_follow] = location
60
- end
58
+ location = @response.follow_location
59
+ return unless location
60
+
61
+ relations[:_restify_follow] = location
61
62
  end
62
63
 
63
64
  class << self
64
- def accept?(response)
65
+ def accept?(_response)
65
66
  false
66
67
  end
67
68
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'json'
2
4
 
3
5
  module Restify
@@ -9,13 +11,13 @@ module Restify
9
11
  # JSON fields matching *_url will be parsed as relations.
10
12
  #
11
13
  class Json < Base
12
-
13
14
  def load
14
- parse ::JSON.load(body), root: true
15
+ parse ::JSON.parse(body), root: true
15
16
  end
16
17
 
17
18
  private
18
19
 
20
+ # rubocop:disable Metrics/MethodLength
19
21
  def parse(object, root: false)
20
22
  case object
21
23
  when Hash
@@ -27,9 +29,14 @@ module Restify
27
29
  end
28
30
 
29
31
  if root
30
- Resource.new context, response: response, data: data, relations: relations
32
+ Resource.new context,
33
+ data: data,
34
+ response: response,
35
+ relations: relations
31
36
  else
32
- Resource.new context, data: data, relations: relations
37
+ Resource.new context,
38
+ data: data,
39
+ relations: relations
33
40
  end
34
41
  when Array
35
42
  object.map(&method(:parse))
@@ -44,21 +51,23 @@ module Restify
44
51
 
45
52
  def parse_rels(pair, relations)
46
53
  name = case pair[0].to_s.downcase
47
- when /\A(\w+)_url\z/
48
- Regexp.last_match[1]
49
- when 'url'
50
- 'self'
51
- else
52
- return
54
+ when /\A(\w+)_url\z/
55
+ Regexp.last_match[1]
56
+ when 'url'
57
+ 'self'
58
+ else
59
+ return
60
+ end
61
+
62
+ if relations.key?(name) || pair[1].nil? || pair[1].to_s =~ /\A\w*\z/
63
+ return
53
64
  end
54
65
 
55
- return if relations.key?(name) || pair[1].nil? || pair[1].to_s =~ /\A\w*\z/
56
-
57
66
  relations[name] = pair[1].to_s
58
67
  end
59
68
 
60
69
  def json
61
- @json ||= JSON.load response.body
70
+ @json ||= JSON.parse(response.body)
62
71
  end
63
72
 
64
73
  def with_indifferent_access(data)
@@ -67,19 +76,17 @@ module Restify
67
76
 
68
77
  class << self
69
78
  def accept?(response)
70
- response.content_type =~ /\Aapplication\/json($|;)/
79
+ response.content_type =~ %r{\Aapplication/json($|;)}
71
80
  end
72
81
 
73
82
  def indifferent_access?
74
- @@indifferent_access
83
+ @indifferent_access
75
84
  end
76
85
 
77
- def indifferent_access=(value)
78
- @@indifferent_access = value
79
- end
80
-
81
- @@indifferent_access = true
86
+ attr_writer :indifferent_access
82
87
  end
88
+
89
+ self.indifferent_access = true
83
90
  end
84
91
  end
85
92
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Restify
2
4
  #
3
5
  class Promise < Concurrent::IVar
@@ -10,22 +12,7 @@ module Restify
10
12
 
11
13
  def wait(timeout = nil)
12
14
  execute if pending?
13
-
14
- # if defined?(EventMachine)
15
- # if incomplete?
16
- # fiber = Fiber.current
17
-
18
- # self.add_observer do
19
- # EventMachine.next_tick { fiber.resume }
20
- # end
21
-
22
- # Fiber.yield
23
- # else
24
- # self
25
- # end
26
- # else
27
- super
28
- # end
15
+ super
29
16
  end
30
17
 
31
18
  def then(&block)
@@ -39,17 +26,16 @@ module Restify
39
26
  protected
40
27
 
41
28
  # @!visibility private
42
- def ns_execute(timeout)
43
- if compare_and_set_state(:processing, :pending)
44
- return unless @task || @dependencies.any?
29
+ def ns_execute(_timeout)
30
+ return unless compare_and_set_state(:processing, :pending)
31
+ return unless @task || @dependencies.any?
45
32
 
46
- executor = Concurrent::SafeTaskExecutor.new \
47
- method(:ns_exec), rescue_exception: true
33
+ executor = Concurrent::SafeTaskExecutor.new \
34
+ method(:ns_exec), rescue_exception: true
48
35
 
49
- success, value, reason = executor.execute
36
+ success, value, reason = executor.execute
50
37
 
51
- complete success, value, reason
52
- end
38
+ complete success, value, reason
53
39
  end
54
40
 
55
41
  # @!visibility private
@@ -57,9 +43,7 @@ module Restify
57
43
  args = @dependencies.any? ? @dependencies.map(&:value!) : []
58
44
  value = @task ? @task.call(*args) : args
59
45
 
60
- while value.is_a? Restify::Promise
61
- value = value.value!
62
- end
46
+ value = value.value! while value.is_a? Restify::Promise
63
47
 
64
48
  value
65
49
  end
@@ -70,6 +54,18 @@ module Restify
70
54
  yield Writer.new(promise)
71
55
  promise
72
56
  end
57
+
58
+ def fulfilled(value)
59
+ create do |writer|
60
+ writer.fulfill value
61
+ end
62
+ end
63
+
64
+ def rejected(value)
65
+ create do |writer|
66
+ writer.reject value
67
+ end
68
+ end
73
69
  end
74
70
 
75
71
  class Writer
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Restify
2
4
  class Registry
3
5
  def initialize
@@ -1,7 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Restify
2
4
  #
3
5
  class Relation
4
-
5
6
  # Relation context
6
7
  #
7
8
  # @return [Restify::Context] Context
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Restify
2
4
  #
3
5
  class Request
@@ -1,9 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'delegate'
2
4
 
3
5
  module Restify
4
6
  #
5
7
  class Resource < SimpleDelegator
6
-
7
8
  # @api private
8
9
  #
9
10
  def initialize(context, response: nil, data: nil, relations: {})
@@ -23,9 +24,9 @@ module Restify
23
24
  @relations.key?(name) || @relations.key?(name.to_s)
24
25
  end
25
26
 
26
- alias_method :rel?, :relation?
27
- alias_method :has_rel?, :relation?
28
- alias_method :has_relation?, :relation?
27
+ alias rel? relation?
28
+ alias has_rel? relation?
29
+ alias has_relation? relation?
29
30
 
30
31
  # Return relation with given name.
31
32
  #
@@ -40,7 +41,7 @@ module Restify
40
41
  end
41
42
  end
42
43
 
43
- alias_method :rel, :relation
44
+ alias rel relation
44
45
 
45
46
  # @!method data
46
47
  #
@@ -64,11 +65,7 @@ module Restify
64
65
  # @return [Relation] Relation to follow resource or nil.
65
66
  #
66
67
  def follow
67
- if relation? :_restify_follow
68
- relation :_restify_follow
69
- else
70
- nil
71
- end
68
+ relation :_restify_follow if relation? :_restify_follow
72
69
  end
73
70
 
74
71
  # Follow a LOCATION or CONTEXT-LOCATION header.
@@ -76,11 +73,12 @@ module Restify
76
73
  # @return [Relation] Relation to follow resource.
77
74
  # @raise RuntimeError If nothing to follow.
78
75
  #
76
+ # rubocop:disable Style/GuardClause
79
77
  def follow!
80
78
  if (rel = follow)
81
79
  rel
82
80
  else
83
- raise RuntimeError.new 'Nothing to follow'
81
+ raise 'Nothing to follow'
84
82
  end
85
83
  end
86
84
 
@@ -97,9 +95,9 @@ module Restify
97
95
  # @api private
98
96
  def inspect
99
97
  text = {
100
- "@data" => data,
101
- "@relations" => @relations
102
- }.map {|k,v | k + '=' + v.inspect }.join(' ')
98
+ '@data' => data,
99
+ '@relations' => @relations
100
+ }.map {|k, v| k + '=' + v.inspect }.join(' ')
103
101
 
104
102
  "#<#{self.class} #{text}>"
105
103
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rack/utils'
2
4
  require 'json'
3
5
 
@@ -87,6 +89,7 @@ module Restify
87
89
  #
88
90
  # @return [Array<Link>] Links.
89
91
  #
92
+ # rubocop:disable Metrics/MethodLength
90
93
  def links
91
94
  @links ||= begin
92
95
  if headers['LINK']
@@ -116,15 +119,15 @@ module Restify
116
119
  # @return [Boolean] True if status code is 2XX otherwise false.
117
120
  #
118
121
  def success?
119
- (200...300).include? code
122
+ (200...300).cover? code
120
123
  end
121
124
 
122
125
  # @api private
123
126
  def decoded_body
124
127
  @decoded_body ||= begin
125
128
  case content_type
126
- when /\Aapplication\/json($|;)/
127
- JSON.load body
129
+ when %r{\Aapplication/json($|;)}
130
+ ::JSON.parse(body)
128
131
  end
129
132
  end
130
133
  end
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Restify
2
4
  module VERSION
3
5
  MAJOR = 1
4
- MINOR = 0
5
- PATCH = 1
6
- STAGE = :beta1
6
+ MINOR = 1
7
+ PATCH = 0
8
+ STAGE = nil
7
9
  STRING = [MAJOR, MINOR, PATCH, STAGE].reject(&:nil?).join('.').freeze
8
10
 
9
11
  def self.to_s
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Restify::Cache do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Restify::Global do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Restify::Link do
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Restify::Processors::Base do
6
+ let(:context) { Restify::Context.new('http://test.host/') }
7
+ let(:response) { double 'response' }
8
+
9
+ before do
10
+ allow(response).to receive(:links).and_return []
11
+ allow(response).to receive(:follow_location).and_return nil
12
+ end
13
+
14
+ describe 'class' do
15
+ describe '#accept?' do
16
+ subject { described_class.accept? response }
17
+
18
+ # If no other processor accepts the request, we have an explicit fallback
19
+ # to the base processor.
20
+ it 'does not accept any responses' do
21
+ expect(subject).to be_falsey
22
+ end
23
+ end
24
+ end
25
+
26
+ describe '#resource' do
27
+ subject { described_class.new(context, response).resource }
28
+ before { allow(response).to receive(:body).and_return(body) }
29
+
30
+ describe 'parsing' do
31
+ context 'string' do
32
+ let(:body) do
33
+ <<-BODY
34
+ binaryblob
35
+ BODY
36
+ end
37
+
38
+ it { is_expected.to be_a Restify::Resource }
39
+ it { expect(subject.response).to be response }
40
+ it { is_expected.to eq body }
41
+ end
42
+ end
43
+ end
44
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Restify::Processors::Json do
@@ -29,27 +31,29 @@ describe Restify::Processors::Json do
29
31
  subject { described_class.new(context, response).resource }
30
32
  before { allow(response).to receive(:body).and_return(body) }
31
33
 
32
- context 'parsing' do
34
+ describe 'parsing' do
33
35
  context 'single object' do
34
- let(:body) do <<-JSON
35
- {"key": "value"}
36
+ let(:body) do
37
+ <<-JSON
38
+ {"json": "value"}
36
39
  JSON
37
40
  end
38
41
 
39
42
  it { is_expected.to be_a Restify::Resource }
40
43
  it { expect(subject.response).to be response }
41
- it { is_expected.to eq 'key' => 'value' }
44
+ it { is_expected.to eq 'json' => 'value' }
42
45
  end
43
46
 
44
47
  context 'object with relation fields' do
45
- let(:body) do <<-JSON
46
- {"key": "value", "search_url": "https://google.com{?q}"}
48
+ let(:body) do
49
+ <<-JSON
50
+ {"json": "value", "search_url": "https://google.com{?q}"}
47
51
  JSON
48
52
  end
49
53
 
50
54
  it do
51
55
  is_expected.to eq \
52
- 'key' => 'value', 'search_url' => 'https://google.com{?q}'
56
+ 'json' => 'value', 'search_url' => 'https://google.com{?q}'
53
57
  end
54
58
 
55
59
  it { is_expected.to have_relation :search }
@@ -57,8 +61,9 @@ describe Restify::Processors::Json do
57
61
  end
58
62
 
59
63
  context 'object with implicit self relation' do
60
- let(:body) do <<-JSON
61
- {"key": "value", "url": "/self"}
64
+ let(:body) do
65
+ <<-JSON
66
+ {"json": "value", "url": "/self"}
62
67
  JSON
63
68
  end
64
69
 
@@ -66,18 +71,20 @@ describe Restify::Processors::Json do
66
71
  end
67
72
 
68
73
  context 'single array' do
69
- let(:body) do <<-JSON
74
+ let(:body) do
75
+ <<-JSON
70
76
  [1, 2, null, "STR"]
71
77
  JSON
72
78
  end
73
79
 
74
80
  it { is_expected.to be_a Restify::Resource }
75
81
  it { expect(subject.response).to be response }
76
- it { is_expected.to eq [1, 2, nil, "STR"] }
82
+ it { is_expected.to eq [1, 2, nil, 'STR'] }
77
83
  end
78
84
 
79
85
  context 'array with objects' do
80
- let(:body) do <<-JSON
86
+ let(:body) do
87
+ <<-JSON
81
88
  [{"a":0}, {"b":1}]
82
89
  JSON
83
90
  end
@@ -86,15 +93,15 @@ describe Restify::Processors::Json do
86
93
  end
87
94
 
88
95
  context 'array with resources' do
89
- let(:body) do <<-JSON
96
+ let(:body) do
97
+ <<-JSON
90
98
  [{"name": "John", "self_url": "/users/john"},
91
99
  {"name": "Jane", "self_url": "/users/jane"}]
92
100
  JSON
93
101
  end
94
102
 
95
103
  it 'parses objects as resources' do
96
- expect(subject.map(&:class)).to eq \
97
- [Restify::Resource, Restify::Resource]
104
+ expect(subject).to all(be_a(Restify::Resource))
98
105
  end
99
106
 
100
107
  it 'parses relations of resources' do
@@ -104,7 +111,8 @@ describe Restify::Processors::Json do
104
111
  end
105
112
 
106
113
  context 'nested objects' do
107
- let(:body) do <<-JSON
114
+ let(:body) do
115
+ <<-JSON
108
116
  {"john": {"name": "John"},
109
117
  "jane": {"name": "Jane"}}
110
118
  JSON
@@ -123,18 +131,20 @@ describe Restify::Processors::Json do
123
131
  end
124
132
 
125
133
  context 'single value' do
126
- let(:body) do <<-JSON
134
+ let(:body) do
135
+ <<-JSON
127
136
  "BLUB"
128
137
  JSON
129
138
  end
130
139
 
131
140
  it { is_expected.to be_a Restify::Resource }
132
141
  it { expect(subject.response).to be response }
133
- it { is_expected.to eq "BLUB" }
142
+ it { is_expected.to eq 'BLUB' }
134
143
  end
135
144
 
136
145
  context 'with indifferent access' do
137
- let(:body) do <<-JSON
146
+ let(:body) do
147
+ <<-JSON
138
148
  {"name": "John", "age": 24}
139
149
  JSON
140
150
  end
@@ -157,7 +167,8 @@ describe Restify::Processors::Json do
157
167
  end
158
168
 
159
169
  context 'with method getter access' do
160
- let(:body) do <<-JSON
170
+ let(:body) do
171
+ <<-JSON
161
172
  {"name": "John", "age": 24}
162
173
  JSON
163
174
  end
@@ -0,0 +1,165 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Restify::Promise do
6
+ describe 'factory methods' do
7
+ describe '#fulfilled' do
8
+ subject { described_class.fulfilled(fulfill_value) }
9
+ let(:fulfill_value) { 42 }
10
+
11
+ it 'returns a fulfilled promise' do
12
+ expect(subject.fulfilled?).to be true
13
+ expect(subject.rejected?).to be false
14
+ end
15
+
16
+ it 'wraps the given value' do
17
+ expect(subject.value!).to eq 42
18
+ end
19
+ end
20
+
21
+ describe '#rejected' do
22
+ subject { described_class.rejected(rejection_reason) }
23
+ let(:rejection_reason) { ArgumentError }
24
+
25
+ it 'returns a rejected promise' do
26
+ expect(subject.fulfilled?).to be false
27
+ expect(subject.rejected?).to be true
28
+ end
29
+
30
+ it 'bubbles up the caught exception on #value!' do
31
+ expect { subject.value! }.to raise_error(ArgumentError)
32
+ end
33
+
34
+ it 'swallows the exception on #value' do
35
+ expect(subject.value).to be nil
36
+ end
37
+ end
38
+
39
+ describe '#create' do
40
+ context 'when fulfilling the promise in the writer block' do
41
+ subject do
42
+ described_class.create do |writer|
43
+ # Calculate a value and fulfill the promise with it
44
+ writer.fulfill 42
45
+ end
46
+ end
47
+
48
+ it 'returns a fulfilled promise' do
49
+ expect(subject.fulfilled?).to be true
50
+ expect(subject.rejected?).to be false
51
+ end
52
+
53
+ it 'wraps the given value' do
54
+ expect(subject.value!).to eq 42
55
+ end
56
+ end
57
+
58
+ context 'when rejecting the promise in the writer block' do
59
+ subject do
60
+ described_class.create do |writer|
61
+ # Calculate a value and fulfill the promise with it
62
+ writer.reject ArgumentError
63
+ end
64
+ end
65
+
66
+ it 'returns a rejected promise' do
67
+ expect(subject.fulfilled?).to be false
68
+ expect(subject.rejected?).to be true
69
+ end
70
+
71
+ it 'bubbles up the caught exception on #value!' do
72
+ expect { subject.value! }.to raise_error(ArgumentError)
73
+ end
74
+
75
+ it 'swallows the exception on #value' do
76
+ expect(subject.value).to be nil
77
+ end
78
+ end
79
+
80
+ context 'when fulfilling the promise asynchronously' do
81
+ subject do
82
+ described_class.create do |writer|
83
+ Thread.new do
84
+ sleep 0.1
85
+ writer.fulfill 42
86
+ end
87
+ end
88
+ end
89
+
90
+ it 'returns a pending promise' do
91
+ expect(subject.fulfilled?).to be false
92
+ expect(subject.rejected?).to be false
93
+ expect(subject.pending?).to be true
94
+ end
95
+
96
+ it 'waits for the fulfillment value' do
97
+ expect(subject.value!).to eq 42
98
+ end
99
+ end
100
+ end
101
+ end
102
+
103
+ describe 'result' do
104
+ subject { described_class.new(*dependencies, &task).value! }
105
+ let(:dependencies) { [] }
106
+ let(:task) { nil }
107
+
108
+ context 'with a task' do
109
+ let(:task) do
110
+ proc {
111
+ # Calculate the resulting value
112
+ 38 + 4
113
+ }
114
+ end
115
+
116
+ it 'is calculated using the task block' do
117
+ expect(subject).to eq 42
118
+ end
119
+ end
120
+
121
+ context 'with dependencies, but no task' do
122
+ let(:dependencies) do
123
+ [
124
+ Restify::Promise.fulfilled(1),
125
+ Restify::Promise.fulfilled(2),
126
+ Restify::Promise.fulfilled(3)
127
+ ]
128
+ end
129
+
130
+ it 'is an array of the dependencies\' results' do
131
+ expect(subject).to eq [1, 2, 3]
132
+ end
133
+ end
134
+
135
+ context 'with dependencies passed as an array, but no task' do
136
+ let(:dependencies) do
137
+ [[
138
+ Restify::Promise.fulfilled(1),
139
+ Restify::Promise.fulfilled(2),
140
+ Restify::Promise.fulfilled(3)
141
+ ]]
142
+ end
143
+
144
+ it 'is an array of the dependencies\' results' do
145
+ expect(subject).to eq [1, 2, 3]
146
+ end
147
+ end
148
+
149
+ context 'with dependencies and a task' do
150
+ let(:dependencies) do
151
+ [
152
+ Restify::Promise.fulfilled(5),
153
+ Restify::Promise.fulfilled(12)
154
+ ]
155
+ end
156
+ let(:task) do
157
+ proc {|dep1, dep2| dep1 + dep2 }
158
+ end
159
+
160
+ it 'can use the dependencies to calculate the value' do
161
+ expect(subject).to eq 17
162
+ end
163
+ end
164
+ end
165
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Restify::Registry do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Restify::Relation do
@@ -26,7 +28,6 @@ describe Restify::Relation do
26
28
  end
27
29
 
28
30
  context 'with #to_param object' do
29
-
30
31
  let(:params) { {id: ParamObject.new} }
31
32
 
32
33
  it { expect(subject.to_s).to eq 'http://test.host/resource/42' }
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Restify::Resource do
data/spec/restify_spec.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Restify do
data/spec/spec_helper.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rspec'
2
4
  require 'webmock/rspec'
3
5
 
@@ -10,19 +12,21 @@ end
10
12
 
11
13
  require 'restify'
12
14
 
13
- case ENV['ADAPTER'].to_s.downcase
14
- when 'em-http-request'
15
- require 'restify/adapter/em'
16
- Restify.adapter = Restify::Adapter::EM.new
17
- when 'typhoeus'
18
- require 'restify/adapter/typhoeus'
19
- Restify.adapter = Restify::Adapter::Typhoeus.new
20
- when 'typhoeus-sync'
21
- require 'restify/adapter/typhoeus'
22
- Restify.adapter = Restify::Adapter::Typhoeus.new sync: true
23
- else
24
- raise "Invalid adapter: #{ENV['ADAPTER']}"
25
- end if ENV['ADAPTER']
15
+ if ENV['ADAPTER']
16
+ case ENV['ADAPTER'].to_s.downcase
17
+ when 'em-http-request'
18
+ require 'restify/adapter/em'
19
+ Restify.adapter = Restify::Adapter::EM.new
20
+ when 'typhoeus'
21
+ require 'restify/adapter/typhoeus'
22
+ Restify.adapter = Restify::Adapter::Typhoeus.new
23
+ when 'typhoeus-sync'
24
+ require 'restify/adapter/typhoeus'
25
+ Restify.adapter = Restify::Adapter::Typhoeus.new sync: true
26
+ else
27
+ raise "Invalid adapter: #{ENV['ADAPTER']}"
28
+ end
29
+ end
26
30
 
27
31
  require 'webmock/rspec'
28
32
  require 'rspec/collection_matchers'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: restify
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1.beta1
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jan Graichen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-01-20 00:00:00.000000000 Z
11
+ date: 2017-05-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -151,11 +151,12 @@ files:
151
151
  - lib/restify/resource.rb
152
152
  - lib/restify/response.rb
153
153
  - lib/restify/version.rb
154
- - restify.gemspec
155
154
  - spec/restify/cache_spec.rb
156
155
  - spec/restify/global_spec.rb
157
156
  - spec/restify/link_spec.rb
157
+ - spec/restify/processors/base_spec.rb
158
158
  - spec/restify/processors/json_spec.rb
159
+ - spec/restify/promise_spec.rb
159
160
  - spec/restify/registry_spec.rb
160
161
  - spec/restify/relation_spec.rb
161
162
  - spec/restify/resource_spec.rb
@@ -176,12 +177,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
176
177
  version: '0'
177
178
  required_rubygems_version: !ruby/object:Gem::Requirement
178
179
  requirements:
179
- - - ">"
180
+ - - ">="
180
181
  - !ruby/object:Gem::Version
181
- version: 1.3.1
182
+ version: '0'
182
183
  requirements: []
183
184
  rubyforge_project:
184
- rubygems_version: 2.5.1
185
+ rubygems_version: 2.6.11
185
186
  signing_key:
186
187
  specification_version: 4
187
188
  summary: An experimental hypermedia REST client.
@@ -189,7 +190,9 @@ test_files:
189
190
  - spec/restify/cache_spec.rb
190
191
  - spec/restify/global_spec.rb
191
192
  - spec/restify/link_spec.rb
193
+ - spec/restify/processors/base_spec.rb
192
194
  - spec/restify/processors/json_spec.rb
195
+ - spec/restify/promise_spec.rb
193
196
  - spec/restify/registry_spec.rb
194
197
  - spec/restify/relation_spec.rb
195
198
  - spec/restify/resource_spec.rb
data/restify.gemspec DELETED
@@ -1,35 +0,0 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
3
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'restify/version'
5
-
6
- Gem::Specification.new do |spec|
7
- spec.name = 'restify'
8
- spec.version = Restify::VERSION
9
- spec.authors = ['Jan Graichen']
10
- spec.email = ['jg@altimos.de']
11
- spec.summary = 'An experimental hypermedia REST client.'
12
- spec.description = 'An experimental hypermedia REST client that uses parallel, keep-alive and pipelined requests by default.'
13
- spec.homepage = 'https://github.com/jgraichen/restify'
14
- spec.license = 'LGPLv3'
15
-
16
- spec.files = Dir['**/*'].grep(%r{^((bin|lib|test|spec|features)/|.*\.gemspec|.*LICENSE.*|.*README.*|.*CHANGELOG.*)})
17
- spec.executables = spec.files.grep(%r{^bin/}) {|f| File.basename(f) }
18
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
- spec.require_paths = ['lib']
20
-
21
- spec.add_runtime_dependency 'concurrent-ruby', '~> 1.0'
22
- spec.add_runtime_dependency 'addressable', '~> 2.3'
23
- spec.add_runtime_dependency 'hashie', '~> 3.3'
24
- spec.add_runtime_dependency 'rack'
25
- spec.add_runtime_dependency 'eventmachine', '>= 1.2'
26
- spec.add_runtime_dependency 'em-http-request', '~> 1.1.3'
27
- spec.add_runtime_dependency 'activesupport'
28
-
29
- spec.add_development_dependency 'bundler', '~> 1.5'
30
-
31
- if ENV['TRAVIS_BUILD_NUMBER']
32
- # Append travis build number for auto-releases
33
- spec.version = "#{spec.version}.1.b#{ENV['TRAVIS_BUILD_NUMBER']}"
34
- end
35
- end