ruby-trello 3.1.0 → 3.2.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
  SHA256:
3
- metadata.gz: c36f88684585632f2f1fc785ea06cd651b6ba61105c1326e49cc9e4cbf1f5080
4
- data.tar.gz: 1aeafd0ed644ac395d71ea296feac980ebd013f1b915c1caa99845c86c24d2b3
3
+ metadata.gz: 46d6d62edf1eb8973cfea687f157402b32ab4741b4f5cf3c638dd3b2704d5ad8
4
+ data.tar.gz: a31459e8d18d04b759be5ec6385b9fa75e55250fb691b37c484a639a799f8ee6
5
5
  SHA512:
6
- metadata.gz: 4305a964e59f049220842e64dbd9df87dc4f94ff3a43825700178d2efeeae069dd607f718c6d1e027556921b20b6a2e187e92076d5debd85e314c916a61c5845
7
- data.tar.gz: ba6056ba114bfb48cae07fad2acc4742641c3ef9c0adecdfbf0ee7f6aa4e6e08375ebbff6978918e4f1979c9a2b6ed33d29c1a846b6e89446b848e0cfb84576d
6
+ metadata.gz: ca3cffbb4c3e0b3ce88ec21dade8b5a21bf0b2bedb2cdb259523fac0986632d521eb04f3c607273192cd4ce617b73005152507dedfa42c370b51cf75e4d1ec45
7
+ data.tar.gz: 7b13d2e420d26fde4cdd62e09f7f199dd170102272f17c630554c2156aaee2ddc2f2f76a62a67707df23d252ce2723edd5de1b6697b64ca7ef2b9f30c6f56c15
data/README.md CHANGED
@@ -87,7 +87,19 @@ end
87
87
 
88
88
  All the calls this library makes to Trello require authentication using these keys. Be sure to protect them.
89
89
 
90
- #### Usage
90
+ #### HTTP Client
91
+
92
+ By default, ruby-trello uses [rest-client](https://rubygems.org/gems/rest-client) for network calls. You can configure ruby-trello to use either rest-client or [faraday](https://rubygems.org/gems/faraday), depending on your project's needs. In the next major version, ruby-trello will not require either gem in the gemspec and will default to faraday if both are present.
93
+
94
+ ```ruby
95
+ Trello.configure do |config|
96
+ config.http_client = 'rest-client'
97
+ # OR
98
+ config.http_client = 'faraday'
99
+ end
100
+ ```
101
+
102
+ ## Usage
91
103
 
92
104
  So let's say you want to get information about the user *bobtester*. We can do something like this:
93
105
 
@@ -103,7 +115,7 @@ puts bob.bio # A wonderfully delightful test user
103
115
  # How about a list of his boards?
104
116
  bob.boards
105
117
 
106
- # And then to read the lists of the first board do :
118
+ # And then to read the lists of the first board do :
107
119
  bob.boards.first.lists
108
120
  ```
109
121
 
@@ -130,10 +142,10 @@ pp Trello::Card.find( card_id ).checklists
130
142
 
131
143
  ##### Changing a checkbox state
132
144
  ```ruby
133
- # First get your checklist id
145
+ # First get your checklist id
134
146
  checklist = Trello::Checklist.find( checklist_id )
135
147
 
136
- # At this point, there is no more ids. To get your checklist item,
148
+ # At this point, there is no more ids. To get your checklist item,
137
149
  # you have to know it's position (same as in the trello interface).
138
150
  # Let's take the first
139
151
  checklist_item = checklist.items.first
data/lib/trello/client.rb CHANGED
@@ -99,7 +99,7 @@ module Trello
99
99
  raise Error.new(response.body, response.code)
100
100
  end
101
101
 
102
- response.body
102
+ response
103
103
  end
104
104
 
105
105
  def auth_policy_class
@@ -44,6 +44,14 @@ module Trello
44
44
  developer_public_key && member_token
45
45
  end
46
46
 
47
+ def http_client=(http_client)
48
+ Trello.http_client = http_client.to_s
49
+ end
50
+
51
+ def http_client
52
+ Trello::HTTP_CLIENTS.find { |k, v| v == Trello.http_client }[0]
53
+ end
54
+
47
55
  private
48
56
 
49
57
  def oauth_credentials
@@ -32,8 +32,8 @@ module Trello
32
32
  # thing.a == 42
33
33
  # thing.b == "foo"
34
34
  #
35
- def from_response(data, encoding = 'UTF-8')
36
- from_json(parse_json(data, encoding))
35
+ def from_response(response, encoding = 'UTF-8')
36
+ from_json(parse_json(response, encoding))
37
37
  end
38
38
 
39
39
  def from_json(json)
@@ -47,8 +47,14 @@ module Trello
47
47
  end
48
48
  end
49
49
 
50
- def parse_json(string, encoding = 'UTF-8')
51
- JSON.parse(string.force_encoding(encoding))
50
+ def parse_json(data, encoding = 'UTF-8')
51
+ # Trello.http_client.parse_json(data, encoding)
52
+ case data
53
+ when Trello::Response
54
+ JSON.parse(data.body.force_encoding(encoding))
55
+ else
56
+ JSON.parse(data.force_encoding(encoding))
57
+ end
52
58
  rescue JSON::ParserError => json_error
53
59
  if json_error.message =~ /model not found/
54
60
  Trello.logger.error "Could not find that record."
@@ -0,0 +1,46 @@
1
+ module Trello
2
+ module TFaraday
3
+ class TInternet
4
+ class << self
5
+ begin
6
+ require 'faraday'
7
+ rescue LoadError
8
+ end
9
+
10
+ def execute(request)
11
+ try_execute request
12
+ end
13
+
14
+ private
15
+
16
+ def try_execute(request)
17
+ begin
18
+ if request
19
+ result = execute_core request
20
+ Response.new(200, {}, result.body)
21
+ end
22
+ rescue Faraday::Error => e
23
+ raise if !e.respond_to?(:response) || e.response.nil? || e.response[:status].nil?
24
+ Response.new(e.response[:status], {}, e.response[:body])
25
+ end
26
+ end
27
+
28
+ def execute_core(request)
29
+ conn = Faraday.new(
30
+ request.uri.to_s,
31
+ headers: request.headers,
32
+ proxy: ENV['HTTP_PROXY'],
33
+ request: { timeout: 10 }
34
+ ) do |faraday|
35
+ faraday.response :raise_error
36
+ faraday.request :json
37
+ end
38
+
39
+ conn.send(request.verb) do |req|
40
+ req.body = request.body
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,41 @@
1
+ module Trello
2
+ module TRestClient
3
+ class TInternet
4
+ class << self
5
+ begin
6
+ require 'rest-client'
7
+ rescue LoadError
8
+ end
9
+
10
+ def execute(request)
11
+ try_execute request
12
+ end
13
+
14
+ private
15
+
16
+ def try_execute(request)
17
+ begin
18
+ if request
19
+ result = execute_core request
20
+ Response.new(200, {}, result.body)
21
+ end
22
+ rescue RestClient::Exception => e
23
+ raise if !e.respond_to?(:http_code) || e.http_code.nil?
24
+ Response.new(e.http_code, {}, e.http_body)
25
+ end
26
+ end
27
+
28
+ def execute_core(request)
29
+ RestClient.proxy = ENV['HTTP_PROXY'] if ENV['HTTP_PROXY']
30
+ RestClient::Request.execute(
31
+ method: request.verb,
32
+ url: request.uri.to_s,
33
+ headers: request.headers,
34
+ payload: request.body,
35
+ timeout: 10
36
+ )
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
data/lib/trello/net.rb CHANGED
@@ -4,35 +4,8 @@ module Trello
4
4
 
5
5
  class TInternet
6
6
  class << self
7
- require "rest_client"
8
-
9
7
  def execute(request)
10
- try_execute request
11
- end
12
-
13
- private
14
-
15
- def try_execute(request)
16
- begin
17
- if request
18
- result = execute_core request
19
- Response.new(200, {}, result)
20
- end
21
- rescue RestClient::Exception => e
22
- raise if !e.respond_to?(:http_code) || e.http_code.nil?
23
- Response.new(e.http_code, {}, e.http_body)
24
- end
25
- end
26
-
27
- def execute_core(request)
28
- RestClient.proxy = ENV['HTTP_PROXY'] if ENV['HTTP_PROXY']
29
- RestClient::Request.execute(
30
- method: request.verb,
31
- url: request.uri.to_s,
32
- headers: request.headers,
33
- payload: request.body,
34
- timeout: 10
35
- )
8
+ Trello.http_client.execute(request)
36
9
  end
37
10
  end
38
11
  end
data/lib/trello.rb CHANGED
@@ -72,6 +72,7 @@ module Trello
72
72
  autoload :Organization, 'trello/organization'
73
73
  autoload :PluginDatum, 'trello/plugin_datum'
74
74
  autoload :Request, 'trello/net'
75
+ autoload :Response, 'trello/net'
75
76
  autoload :TInternet, 'trello/net'
76
77
  autoload :Token, 'trello/token'
77
78
  autoload :Webhook, 'trello/webhook'
@@ -79,6 +80,14 @@ module Trello
79
80
  autoload :AssociationInferTool, 'trello/association_infer_tool'
80
81
  autoload :Schema, 'trello/schema'
81
82
 
83
+ module TFaraday
84
+ autoload :TInternet, 'trello/net/faraday'
85
+ end
86
+
87
+ module TRestClient
88
+ autoload :TInternet, 'trello/net/rest_client'
89
+ end
90
+
82
91
  module Authorization
83
92
  autoload :AuthPolicy, 'trello/authorization'
84
93
  autoload :BasicAuthPolicy, 'trello/authorization'
@@ -112,6 +121,45 @@ module Trello
112
121
  @logger = logger
113
122
  end
114
123
 
124
+ # The order in which we will try the http clients
125
+ HTTP_CLIENT_PRIORITY = %w(rest-client faraday)
126
+ HTTP_CLIENTS = {
127
+ 'faraday' => Trello::TFaraday::TInternet,
128
+ 'rest-client' => Trello::TRestClient::TInternet
129
+ }
130
+
131
+ def self.http_client
132
+ @http_client ||= begin
133
+ # No client has been set explicitly. Try to load each supported client.
134
+ # The first one that loads successfully will be used.
135
+ client = HTTP_CLIENT_PRIORITY.each do |key|
136
+ begin
137
+ require key
138
+ break HTTP_CLIENTS[key]
139
+ rescue LoadError
140
+ next
141
+ end
142
+ end
143
+
144
+ raise ConfigurationError, 'Trello requires either rest-client or faraday installed' unless client
145
+
146
+ client
147
+ end
148
+ end
149
+
150
+ def self.http_client=(http_client)
151
+ if HTTP_CLIENTS.include?(http_client)
152
+ begin
153
+ require http_client
154
+ @http_client = HTTP_CLIENTS[http_client]
155
+ rescue LoadError
156
+ raise ConfigurationError, "Trello tried to use #{http_client}, but that gem is not installed"
157
+ end
158
+ else
159
+ raise ArgumentError, "Unsupported HTTP client: #{http_client}"
160
+ end
161
+ end
162
+
115
163
  def self.client
116
164
  @client ||= Client.new
117
165
  end
@@ -123,6 +171,7 @@ module Trello
123
171
 
124
172
  def self.reset!
125
173
  @client = nil
174
+ @http_client = nil
126
175
  end
127
176
 
128
177
  def self.auth_policy; client.auth_policy; end
data/spec/client_spec.rb CHANGED
@@ -1,4 +1,6 @@
1
1
  require "spec_helper"
2
+ require "rest-client"
3
+ require "faraday"
2
4
 
3
5
  include Trello
4
6
  include Trello::Authorization
@@ -18,11 +20,16 @@ describe Client do
18
20
  end
19
21
 
20
22
  describe "and how it handles RestClient exceptions" do
23
+
24
+ before do
25
+ Trello.http_client = 'rest-client'
26
+ end
27
+
21
28
  context "with RestClient::Exception sans HTTP code" do
22
29
  let(:rc_exception_without_http_code) { RestClient::Exception.new }
23
30
 
24
31
  before do
25
- allow(TInternet)
32
+ allow(Trello::TRestClient::TInternet)
26
33
  .to receive(:execute_core)
27
34
  .and_raise(rc_exception_without_http_code)
28
35
  end
@@ -39,14 +46,61 @@ describe Client do
39
46
  let(:rc_exception_with_http_code) { RestClient::Exception.new(double("404 error response", {:code => 404, :body => "404 error response"}))}
40
47
 
41
48
  before do
42
- allow(TInternet)
49
+ allow(Trello::TRestClient::TInternet)
43
50
  .to receive(:execute_core)
44
51
  .and_raise(rc_exception_with_http_code)
45
52
  end
46
53
 
47
54
  it "raises Error" do
48
55
 
49
- expect(TInternet)
56
+ expect(Trello::TRestClient::TInternet)
57
+ .to receive(:try_execute)
58
+ .and_return(response_with_non_200_status)
59
+
60
+ expect { client.get "/xxx" }.to raise_error do |error|
61
+ expect(error).to be_a(Error)
62
+ expect(error.message).to eq("404 error response")
63
+ expect(error.status_code).to eq(404)
64
+ end
65
+ end
66
+ end
67
+ end
68
+
69
+ describe "and how it handles Faraday errors" do
70
+
71
+ before do
72
+ Trello.http_client = 'faraday'
73
+ end
74
+
75
+ context "with Faraday::Error sans HTTP code" do
76
+ let(:faraday_error_without_http_code) { Faraday::Error.new("Test error") }
77
+
78
+ before do
79
+ allow(Trello::TFaraday::TInternet)
80
+ .to receive(:execute_core)
81
+ .and_raise(faraday_error_without_http_code)
82
+ end
83
+
84
+ it "bubbles up Faraday::Error errors that don't contain an HTTP code" do
85
+ expect { client.get "/xxx" }.to raise_error faraday_error_without_http_code
86
+ end
87
+ end
88
+
89
+ context "with Faraday::Error that contains HTTP code" do
90
+ let(:response_with_non_200_status) { double "A fake 404 response",
91
+ code: 404,
92
+ body: "404 error response"}
93
+ let(:faraday_error_with_http_code) { Faraday::Error.new(double("404 error response", {:code => 404, :body => "404 error response"}))}
94
+
95
+ before do
96
+ allow(Trello::TFaraday::TInternet)
97
+ .to receive(:execute_core)
98
+ .and_raise(faraday_error_with_http_code)
99
+ end
100
+
101
+ it "raises Error" do
102
+
103
+ expect(Trello::TFaraday::TInternet)
50
104
  .to receive(:try_execute)
51
105
  .and_return(response_with_non_200_status)
52
106
 
@@ -19,6 +19,19 @@ describe Trello::Configuration do
19
19
  end
20
20
  end
21
21
 
22
+ it "only allows http_client to be set to one of Trello::HTTP_CLIENTS" do
23
+ Trello::HTTP_CLIENTS.each do |key, _client|
24
+ configuration.http_client = key
25
+ expect(configuration.http_client).to eq key
26
+ end
27
+ end
28
+
29
+ it "raises an error if an invalid http_client is set" do
30
+ expect {
31
+ configuration.http_client = :invalid_http_client
32
+ }.to raise_error(ArgumentError)
33
+ end
34
+
22
35
  it 'has a callback (for oauth)' do
23
36
  callback = -> { 'foobar' }
24
37
  configuration.callback = callback
@@ -14,8 +14,7 @@ RSpec.describe 'Trello::Board#add_member' do
14
14
  expect(response.code).to eq(200)
15
15
  body = JSON.parse(response.body)
16
16
  expect(body['id']).to eq('5e93ba98614ac22d22f085c4')
17
- expect(body['members'][0]['username']).to eq('wokenqingtian')
17
+ expect(body['members'][0]['username']).to eq('wokenqingtian')
18
18
  end
19
19
  end
20
-
21
20
  end
@@ -8,8 +8,8 @@ RSpec.describe 'Trello::Card#delete' do
8
8
  it 'can success delete card' do
9
9
  VCR.use_cassette('can_success_delete_card') do
10
10
  card = Trello::Card.find('5e95b664ace3621af695aeb0')
11
- respone = card.delete
12
- expect(respone.code).to eq(200)
11
+ response = card.delete
12
+ expect(response.code).to eq(200)
13
13
  end
14
14
  end
15
15
 
@@ -25,16 +25,16 @@ module IntegrationTest
25
25
  @welcome_board = ENV["WELCOME_BOARD"]
26
26
  @access_token_key = ENV["ACCESS_TOKEN_KEY"]
27
27
  @access_token_secret = ENV["ACCESS_TOKEN_SECRET"]
28
-
28
+
29
29
  WebMock.disable!
30
- end
30
+ end
31
31
  end
32
32
  end
33
33
 
34
34
  protected
35
35
 
36
36
  def get(uri)
37
- require "rest_client"
37
+ require "rest-client"
38
38
  RestClient.get uri.to_s
39
39
  end
40
40
  end
data/spec/spec_helper.rb CHANGED
@@ -59,6 +59,14 @@ RSpec.configure do |rspec|
59
59
  rspec.color = true
60
60
  end
61
61
 
62
+ Trello::HTTP_CLIENTS.each do |key, _client|
63
+ RSpec.shared_context "using #{key}" do
64
+ before do
65
+ Trello.http_client = key
66
+ end
67
+ end
68
+ end
69
+
62
70
  RSpec::Expectations.configuration.on_potential_false_positives = :nothing
63
71
 
64
72
  module IntegrationHelpers
@@ -66,6 +74,7 @@ module IntegrationHelpers
66
74
  Trello.configure do |config|
67
75
  config.developer_public_key = ENV['TRELLO_DEVELOPER_PUBLIC_KEY'] || 'developerpublickey'
68
76
  config.member_token = ENV['TRELLO_MEMBER_TOKEN'] || 'membertoken'
77
+ config.http_client = ENV['HTTP_CLIENT_GEM'] || 'rest-client'
69
78
  end
70
79
  end
71
80
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-trello
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.0
4
+ version: 3.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeremy Tregunna
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-02-11 00:00:00.000000000 Z
11
+ date: 2022-05-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -128,6 +128,8 @@ files:
128
128
  - lib/trello/member.rb
129
129
  - lib/trello/multi_association.rb
130
130
  - lib/trello/net.rb
131
+ - lib/trello/net/faraday.rb
132
+ - lib/trello/net/rest_client.rb
131
133
  - lib/trello/notification.rb
132
134
  - lib/trello/organization.rb
133
135
  - lib/trello/plugin_datum.rb