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 +4 -4
- data/README.md +16 -4
- data/lib/trello/client.rb +1 -1
- data/lib/trello/configuration.rb +8 -0
- data/lib/trello/json_utils.rb +10 -4
- data/lib/trello/net/faraday.rb +46 -0
- data/lib/trello/net/rest_client.rb +41 -0
- data/lib/trello/net.rb +1 -28
- data/lib/trello.rb +49 -0
- data/spec/client_spec.rb +57 -3
- data/spec/configuration_spec.rb +13 -0
- data/spec/integration/board/add_member_spec.rb +1 -2
- data/spec/integration/card/delete_spec.rb +2 -2
- data/spec/integration/integration_test.rb +3 -3
- data/spec/spec_helper.rb +9 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 46d6d62edf1eb8973cfea687f157402b32ab4741b4f5cf3c638dd3b2704d5ad8
|
4
|
+
data.tar.gz: a31459e8d18d04b759be5ec6385b9fa75e55250fb691b37c484a639a799f8ee6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
####
|
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
data/lib/trello/configuration.rb
CHANGED
@@ -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
|
data/lib/trello/json_utils.rb
CHANGED
@@ -32,8 +32,8 @@ module Trello
|
|
32
32
|
# thing.a == 42
|
33
33
|
# thing.b == "foo"
|
34
34
|
#
|
35
|
-
def from_response(
|
36
|
-
from_json(parse_json(
|
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(
|
51
|
-
|
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
|
-
|
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
|
|
data/spec/configuration_spec.rb
CHANGED
@@ -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
|
-
|
12
|
-
expect(
|
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 "
|
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.
|
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-
|
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
|