ruby-trello 3.1.0 → 3.2.0

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
  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