ruby-trello 0.4.0 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
data/lib/trello/net.rb CHANGED
@@ -12,8 +12,10 @@ module Trello
12
12
 
13
13
  def try_execute(request)
14
14
  begin
15
- result = execute_core request
16
- Response.new(200, {}, result)
15
+ if request
16
+ result = execute_core request
17
+ Response.new(200, {}, result)
18
+ end
17
19
  rescue Exception => e
18
20
  Response.new(e.http_code, {}, e.http_body)
19
21
  end
@@ -1,6 +1,7 @@
1
1
  module Trello
2
2
  class Notification < BasicData
3
- register_attributes :id, :unread, :type, :date, :data, :member_creator_id
3
+ register_attributes :id, :unread, :type, :date, :data, :member_creator_id,
4
+ :read_only => [ :id, :unread, :type, :date, :member_creator_id ]
4
5
  validates_presence_of :id, :type, :date, :member_creator_id
5
6
 
6
7
  class << self
@@ -22,9 +23,7 @@ module Trello
22
23
 
23
24
  alias :unread? :unread
24
25
 
25
- def member_creator
26
- Member.find(member_creator_id)
27
- end
26
+ one :member_creator, :via => Member, :using => :member_creator_id
28
27
 
29
28
  def board
30
29
  Client.get("/notifications/#{id}/board").json_into(Board)
@@ -1,7 +1,8 @@
1
1
  module Trello
2
2
  # Organizations are useful for linking members together.
3
3
  class Organization < BasicData
4
- register_attributes :id, :name, :display_name, :description, :url
4
+ register_attributes :id, :name, :display_name, :description, :url,
5
+ :readonly => [ :id, :name, :display_name, :description, :url ]
5
6
  validates_presence_of :id, :name
6
7
 
7
8
  include HasActions
@@ -28,12 +29,14 @@ module Trello
28
29
 
29
30
  # Returns a list of boards under this organization.
30
31
  def boards
31
- Client.get("/organizations/#{id}/boards/all").json_into(Board)
32
+ boards = Client.get("/organizations/#{id}/boards/all").json_into(Board)
33
+ MultiAssociation.new(self, boards).proxy
32
34
  end
33
35
 
34
36
  # Returns an array of members associated with the organization.
35
37
  def members
36
- Client.get("/organizations/#{id}/members/all").json_into(Member)
38
+ members = Client.get("/organizations/#{id}/members/all").json_into(Member)
39
+ MultiAssociation.new(self, members).proxy
37
40
  end
38
41
 
39
42
  # :nodoc:
data/lib/trello/string.rb CHANGED
@@ -25,10 +25,11 @@ class String
25
25
  end
26
26
  rescue JSON::ParserError => json_error
27
27
  if json_error.message =~ /model not found/
28
- logger.error "Could not find that record."
28
+ Trello.logger.error "Could not find that record."
29
29
  raise Trello::Error, "Request could not be found."
30
+ elsif json_error.message =~ /A JSON text must at least contain two octets/
30
31
  else
31
- logger.error "Unknown error."
32
+ Trello.logger.error "Unknown error."
32
33
  raise
33
34
  end
34
35
  end
@@ -0,0 +1,24 @@
1
+ module Trello
2
+ class Token < BasicData
3
+ register_attributes :id, :member_id, :created_at, :permissions,
4
+ :readonly => [ :id, :member_id, :created_at, :permissions ]
5
+
6
+ class << self
7
+ # Finds a token
8
+ def find(token)
9
+ super(:tokens, token)
10
+ end
11
+ end
12
+
13
+ # :nodoc:
14
+ def update_fields(fields)
15
+ attributes[:id] = fields['id']
16
+ attributes[:member_id] = fields['idMember']
17
+ attributes[:created_at] = Time.iso8601(fields['dateCreated'])
18
+ attributes[:permissions] = fields['permissions'] || {}
19
+ end
20
+
21
+ # Returns a reference to the user who authorized the token.
22
+ one :member, :using => :member_id
23
+ end
24
+ end
data/lib/trello.rb CHANGED
@@ -26,21 +26,25 @@ require 'active_model'
26
26
  #
27
27
  # Feel free to {peruse and participate in our Trello board}[https://trello.com/board/ruby-trello/4f092b2ee23cb6fe6d1aaabd]. It's completely open to the public.
28
28
  module Trello
29
- autoload :Action, 'trello/action'
30
- autoload :BasicData, 'trello/basic_data'
31
- autoload :Board, 'trello/board'
32
- autoload :Card, 'trello/card'
33
- autoload :Checklist, 'trello/checklist'
34
- autoload :Client, 'trello/client'
35
- autoload :HasActions, 'trello/has_actions'
36
- autoload :Item, 'trello/item'
37
- autoload :ItemState, 'trello/item_state'
38
- autoload :List, 'trello/list'
39
- autoload :Member, 'trello/member'
40
- autoload :Notification, 'trello/notification'
41
- autoload :Organization, 'trello/organization'
42
- autoload :Request, 'trello/net'
43
- autoload :TInternet, 'trello/net'
29
+ autoload :Action, 'trello/action'
30
+ autoload :Association, 'trello/association'
31
+ autoload :AssociationProxy, 'trello/association_proxy'
32
+ autoload :BasicData, 'trello/basic_data'
33
+ autoload :Board, 'trello/board'
34
+ autoload :Card, 'trello/card'
35
+ autoload :Checklist, 'trello/checklist'
36
+ autoload :Client, 'trello/client'
37
+ autoload :HasActions, 'trello/has_actions'
38
+ autoload :Item, 'trello/item'
39
+ autoload :ItemState, 'trello/item_state'
40
+ autoload :List, 'trello/list'
41
+ autoload :Member, 'trello/member'
42
+ autoload :MultiAssociation, 'trello/multi_association'
43
+ autoload :Notification, 'trello/notification'
44
+ autoload :Organization, 'trello/organization'
45
+ autoload :Request, 'trello/net'
46
+ autoload :TInternet, 'trello/net'
47
+ autoload :Token, 'trello/token'
44
48
 
45
49
  module Authorization
46
50
  autoload :AuthPolicy, 'trello/authorization'
data/spec/action_spec.rb CHANGED
@@ -29,7 +29,7 @@ module Trello
29
29
  end
30
30
 
31
31
  it "gets the date" do
32
- @action.date.should == @detail['date']
32
+ @action.date.utc.iso8601.should == @detail['date']
33
33
  end
34
34
  end
35
35
 
data/spec/board_spec.rb CHANGED
@@ -44,7 +44,7 @@ module Trello
44
44
 
45
45
  context "cards" do
46
46
  it "gets its list of cards" do
47
- Client.stub(:get).with("/boards/abcdef123456789123456789/cards").
47
+ Client.stub(:get).with("/boards/abcdef123456789123456789/cards", { :filter => :open }).
48
48
  and_return cards_payload
49
49
 
50
50
  @board.cards.count.should be > 0
data/spec/card_spec.rb CHANGED
@@ -40,18 +40,29 @@ module Trello
40
40
  Client.should_receive(:post).with("/cards", expected_payload).and_return result
41
41
 
42
42
  card = Card.create(cards_details.first.merge(payload.merge(:list_id => lists_details.first['id'])))
43
-
43
+
44
44
  card.class.should be Card
45
45
  end
46
46
  end
47
47
 
48
48
  context "updating" do
49
- it "updating name does a put on the correct resource with the correct value", :broken => true do
49
+ it "updating name does a put on the correct resource with the correct value" do
50
50
  expected_new_name = "xxx"
51
51
  expected_resource = "/card/#{@card.id}/name"
52
+ payload = {
53
+ :name => expected_new_name,
54
+ :desc => "Awesome things are awesome.",
55
+ :due => nil,
56
+ :closed => false,
57
+ :idList => "abcdef123456789123456789",
58
+ :idBoard => "abcdef123456789123456789",
59
+ :idMembers => ["abcdef123456789123456789"]
60
+ }
52
61
 
53
- Client.should_receive(:put).once.with expected_resource, :value => expected_new_name
54
- @card.name = expected_new_name
62
+ Client.should_receive(:put).once.with("/cards/abcdef123456789123456789", payload)
63
+ card = @card.dup
64
+ card.name = expected_new_name
65
+ card.save
55
66
  end
56
67
  end
57
68
 
@@ -133,5 +144,35 @@ module Trello
133
144
  @card.add_comment "testing"
134
145
  end
135
146
  end
147
+
148
+ context "labels" do
149
+ it "can add a label" do
150
+ Client.stub(:post).with("/cards/abcdef123456789123456789/labels", { :value => 'green' }).
151
+ and_return "not important"
152
+ @card.add_label('green')
153
+ @card.errors.should be_empty
154
+ end
155
+
156
+ it "can remove a label" do
157
+ Client.stub(:delete).with("/cards/abcdef123456789123456789/labels/green").
158
+ and_return "not important"
159
+ @card.remove_label('green')
160
+ @card.errors.should be_empty
161
+ end
162
+
163
+ it "throws an error when trying to add a label with an unknown colour" do
164
+ Client.stub(:post).with("/cards/abcdef123456789123456789/labels", { :value => 'green' }).
165
+ and_return "not important"
166
+ @card.add_label('mauve')
167
+ @card.errors.full_messages.to_sentence.should == "Label colour 'mauve' does not exist"
168
+ end
169
+
170
+ it "throws an error when trying to remove a label with an unknown colour" do
171
+ Client.stub(:delete).with("/cards/abcdef123456789123456789/labels/mauve").
172
+ and_return "not important"
173
+ @card.remove_label('mauve')
174
+ @card.errors.full_messages.to_sentence.should == "Label colour 'mauve' does not exist"
175
+ end
176
+ end
136
177
  end
137
178
  end
data/spec/member_spec.rb CHANGED
@@ -7,21 +7,21 @@ module Trello
7
7
  include Helpers
8
8
 
9
9
  before(:each) do
10
- Client.stub(:get).with("/members/me").and_return user_payload
10
+ Client.stub(:get).with("/members/abcdef123456789012345678").and_return user_payload
11
11
 
12
- @member = Member.find('me')
12
+ @member = Member.find('abcdef123456789012345678')
13
13
  end
14
14
 
15
15
  context "actions" do
16
16
  it "retrieves a list of actions", :refactor => true do
17
- Client.stub(:get).with("/members/me/actions", { :filter => :all }).and_return actions_payload
17
+ Client.stub(:get).with("/members/abcdef123456789012345678/actions", { :filter => :all }).and_return actions_payload
18
18
  @member.actions.count.should be > 0
19
19
  end
20
20
  end
21
21
 
22
22
  context "boards" do
23
23
  it "has a list of boards" do
24
- Client.stub(:get).with("/members/me/boards", { :filter => :all }).and_return boards_payload
24
+ Client.stub(:get).with("/members/abcdef123456789012345678/boards", { :filter => :all }).and_return boards_payload
25
25
  boards = @member.boards
26
26
  boards.count.should be > 0
27
27
  end
@@ -29,7 +29,7 @@ module Trello
29
29
 
30
30
  context "cards" do
31
31
  it "has a list of cards" do
32
- Client.stub(:get).with("/members/me/cards", { :filter => :open }).and_return cards_payload
32
+ Client.stub(:get).with("/members/abcdef123456789012345678/cards", { :filter => :open }).and_return cards_payload
33
33
  cards = @member.cards
34
34
  cards.count.should be > 0
35
35
  end
@@ -37,7 +37,7 @@ module Trello
37
37
 
38
38
  context "organizations" do
39
39
  it "has a list of organizations" do
40
- Client.stub(:get).with("/members/me/organizations", { :filter => :all }).and_return orgs_payload
40
+ Client.stub(:get).with("/members/abcdef123456789012345678/organizations", { :filter => :all }).and_return orgs_payload
41
41
  orgs = @member.organizations
42
42
  orgs.count.should be > 0
43
43
  end
@@ -45,7 +45,7 @@ module Trello
45
45
 
46
46
  context "notifications" do
47
47
  it "has a list of notifications" do
48
- Client.stub(:get).with("/members/me/notifications").and_return "[" << notification_payload << "]"
48
+ Client.stub(:get).with("/members/abcdef123456789012345678/notifications", {}).and_return "[" << notification_payload << "]"
49
49
  @member.notifications.count.should be 1
50
50
  end
51
51
  end
@@ -83,6 +83,10 @@ module Trello
83
83
  @member.bio = "New and amazing"
84
84
  @member.changed?.should be_true
85
85
  end
86
+
87
+ it "doesn't understand the #id= method" do
88
+ lambda { @member.id = "42" }.should raise_error NoMethodError
89
+ end
86
90
  end
87
91
  end
88
92
  end
@@ -5,9 +5,10 @@ module Trello
5
5
  include Helpers
6
6
 
7
7
  before(:each) do
8
- Client.stub(:get).with("/members/me").and_return user_payload
9
- Client.stub(:get).with("/members/me/notifications").and_return "[" << notification_payload << "]"
10
- @notification = Member.find("me").notifications.first
8
+ Client.stub(:get).with("/members/abcdef123456789012345678").and_return user_payload
9
+ member = Member.find("abcdef123456789012345678")
10
+ Client.stub(:get).with("/members/abcdef123456789012345678/notifications", {}).and_return "[" << notification_payload << "]"
11
+ @notification = member.notifications.first
11
12
  end
12
13
 
13
14
  context "finding" do
@@ -9,74 +9,85 @@ describe OAuthPolicy do
9
9
  OAuthPolicy.token = nil
10
10
  end
11
11
 
12
- it "adds an authorization header" do
13
- uri = Addressable::URI.parse("https://xxx/")
12
+ context "2-legged" do
13
+ it "adds an authorization header" do
14
+ uri = Addressable::URI.parse("https://xxx/")
14
15
 
15
- request = Request.new :get, uri
16
+ request = Request.new :get, uri
16
17
 
17
- authorized_request = OAuthPolicy.authorize request
18
-
19
- authorized_request.headers.keys.should include "Authorization"
20
- end
21
-
22
- it "preserves query parameters" do
23
- uri = Addressable::URI.parse("https://xxx/?name=Riccardo")
24
- request = Request.new :get, uri
18
+ OAuthPolicy.token = OAuthCredential.new "token", nil
25
19
 
26
- authorized_request = OAuthPolicy.authorize request
20
+ authorized_request = OAuthPolicy.authorize request
21
+
22
+ authorized_request.headers.keys.should include "Authorization"
23
+ end
27
24
 
28
- the_query_parameters = Addressable::URI.parse(authorized_request.uri).query_values
29
- the_query_parameters.should == {"name" => "Riccardo"}
30
- end
25
+ it "preserves query parameters" do
26
+ uri = Addressable::URI.parse("https://xxx/?name=Riccardo")
27
+ request = Request.new :get, uri
31
28
 
32
- it "adds the correct signature as part of authorization header" do
33
- Clock.stub(:timestamp).and_return "1327048592"
34
- Nonce.stub(:next).and_return "b94ff2bf7f0a5e87a326064ae1dbb18f"
29
+ Clock.stub(:timestamp).and_return "1327048592"
30
+ Nonce.stub(:next).and_return "b94ff2bf7f0a5e87a326064ae1dbb18f"
31
+ OAuthPolicy.consumer_credential = OAuthCredential.new "consumer_key", "consumer_secret"
32
+ OAuthPolicy.token = OAuthCredential.new "token", nil
35
33
 
36
- OAuthPolicy.consumer_credential = OAuthCredential.new "consumer_key", "consumer_secret"
34
+ authorized_request = OAuthPolicy.authorize request
35
+
36
+ the_query_parameters = Addressable::URI.parse(authorized_request.uri).query_values
37
+ the_query_parameters.should == {"name" => "Riccardo"}
38
+ end
37
39
 
38
- request = Request.new :get, Addressable::URI.parse("http://xxx/")
40
+ it "adds the correct signature as part of authorization header" do
41
+ Clock.stub(:timestamp).and_return "1327048592"
42
+ Nonce.stub(:next).and_return "b94ff2bf7f0a5e87a326064ae1dbb18f"
39
43
 
40
- authorized_request = OAuthPolicy.authorize request
41
-
42
- authorized_request.headers["Authorization"].should =~ /oauth_signature="u7CmId4WEDUqPdHnWVf1JVChFmg%3D"/
43
- end
44
+ OAuthPolicy.consumer_credential = OAuthCredential.new "consumer_key", "consumer_secret"
45
+ OAuthPolicy.token = OAuthCredential.new "token", nil
44
46
 
45
- it "adds correct signature for uri with parameters" do
46
- Clock.stub(:timestamp).and_return "1327351010"
47
- Nonce.stub(:next).and_return "f5474aaf44ca84df0b09870044f91c69"
47
+ request = Request.new :get, Addressable::URI.parse("http://xxx/")
48
48
 
49
- OAuthPolicy.consumer_credential = OAuthCredential.new "consumer_key", "consumer_secret"
49
+ authorized_request = OAuthPolicy.authorize request
50
+
51
+ authorized_request.headers["Authorization"].should =~ /oauth_signature="kLcSxrCTd4ATHcLmTp8q%2Foa%2BFMA%3D"/
52
+ end
50
53
 
51
- request = Request.new :get, Addressable::URI.parse("http://xxx/?a=b")
54
+ it "adds correct signature for uri with parameters" do
55
+ Clock.stub(:timestamp).and_return "1327351010"
56
+ Nonce.stub(:next).and_return "f5474aaf44ca84df0b09870044f91c69"
52
57
 
53
- authorized_request = OAuthPolicy.authorize request
54
-
55
- authorized_request.headers["Authorization"].should =~ /oauth_signature="ABL%2FcOSGJSbvvLt1gW2nV9i%2FDyA%3D"/
56
- end
58
+ OAuthPolicy.consumer_credential = OAuthCredential.new "consumer_key", "consumer_secret"
59
+ OAuthPolicy.token = OAuthCredential.new "token", nil
57
60
 
58
- it "fails if consumer_credential is unset" do
59
- OAuthPolicy.consumer_credential = nil
61
+ request = Request.new :get, Addressable::URI.parse("http://xxx/?a=b")
60
62
 
61
- request = Request.new :get, Addressable::URI.parse("http://xxx/")
63
+ authorized_request = OAuthPolicy.authorize request
64
+
65
+ authorized_request.headers["Authorization"].should =~ /oauth_signature="xm%2FJ1swxxPb6mnuR1Q1ucJMdGRk%3D"/
66
+ end
62
67
 
63
- lambda{OAuthPolicy.authorize request}.should raise_error "The consumer_credential has not been supplied."
64
- end
68
+ it "fails if consumer_credential is unset" do
69
+ OAuthPolicy.consumer_credential = nil
65
70
 
66
- it "can sign with token" do
67
- Clock.stub(:timestamp).and_return "1327360530"
68
- Nonce.stub(:next).and_return "4f610cb28e7aa8711558de5234af1f0e"
71
+ request = Request.new :get, Addressable::URI.parse("http://xxx/")
69
72
 
70
- OAuthPolicy.consumer_credential = OAuthCredential.new "consumer_key", "consumer_secret"
71
- OAuthPolicy.token = OAuthCredential.new "token_key", "token_secret"
73
+ lambda{OAuthPolicy.authorize request}.should raise_error "The consumer_credential has not been supplied."
74
+ end
72
75
 
73
- request = Request.new :get, Addressable::URI.parse("http://xxx/")
76
+ it "can sign with token" do
77
+ Clock.stub(:timestamp).and_return "1327360530"
78
+ Nonce.stub(:next).and_return "4f610cb28e7aa8711558de5234af1f0e"
74
79
 
75
- authorized_request = OAuthPolicy.authorize request
80
+ OAuthPolicy.consumer_credential = OAuthCredential.new "consumer_key", "consumer_secret"
81
+ OAuthPolicy.token = OAuthCredential.new "token_key", "token_secret"
76
82
 
77
- authorized_request.headers["Authorization"].should =~ /oauth_signature="1Boj4fo6KiXA4xGD%2BKF5QOD36PI%3D"/
78
- end
83
+ request = Request.new :get, Addressable::URI.parse("http://xxx/")
79
84
 
80
- it "adds correct signature for https uri"
81
- it "adds correct signature for verbs other than get"
85
+ authorized_request = OAuthPolicy.authorize request
86
+
87
+ authorized_request.headers["Authorization"].should =~ /oauth_signature="3JeZSzsLCYnGNdVALZMgbzQKN44%3D"/
88
+ end
89
+
90
+ it "adds correct signature for https uri"
91
+ it "adds correct signature for verbs other than get"
92
+ end
82
93
  end
data/spec/spec_helper.rb CHANGED
@@ -140,7 +140,7 @@ module Helpers
140
140
  "name" => "Assembler"
141
141
  }
142
142
  },
143
- "date" => "2012-02-10T11:32:17.447Z",
143
+ "date" => "2012-02-10T11:32:17Z",
144
144
  "type" => "createCard"
145
145
  }]
146
146
  end
@@ -198,4 +198,36 @@ module Helpers
198
198
  def organization_payload
199
199
  JSON.generate(organization_details)
200
200
  end
201
+
202
+ def token_details
203
+ {
204
+ "id" => "4f2c10c7b3eb95a45b294cd5",
205
+ "idMember" => "abcdef123456789123456789",
206
+ "dateCreated" => "2012-02-03T16:52:23.661Z",
207
+ "permissions" => [
208
+ {
209
+ "idModel" => "me",
210
+ "modelType" => "Member",
211
+ "read" => true,
212
+ "write" => true
213
+ },
214
+ {
215
+ "idModel" => "*",
216
+ "modelType" => "Board",
217
+ "read" => true,
218
+ "write" => true
219
+ },
220
+ {
221
+ "idModel" => "*",
222
+ "modelType" => "Organization",
223
+ "read" => true,
224
+ "write" => true
225
+ }
226
+ ]
227
+ }
228
+ end
229
+
230
+ def token_payload
231
+ JSON.generate(token_details)
232
+ end
201
233
  end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ module Trello
4
+ describe Token do
5
+ include Helpers
6
+
7
+ before(:each) do
8
+ Client.stub(:get).with("/tokens/1234").and_return token_payload
9
+ @token = Token.find("1234")
10
+ end
11
+
12
+ context "attributes" do
13
+ it "has an id" do
14
+ @token.id.should == "4f2c10c7b3eb95a45b294cd5"
15
+ end
16
+
17
+ it "gets its created_at date" do
18
+ @token.created_at.should == Time.iso8601("2012-02-03T16:52:23.661Z")
19
+ end
20
+
21
+ it "has a permission grant" do
22
+ @token.permissions.count.should be 3
23
+ end
24
+ end
25
+
26
+ context "members" do
27
+ it "retrieves the member who authorized the token" do
28
+ Client.stub(:get).with("/members/abcdef123456789123456789").and_return user_payload
29
+ @token.member.should == Member.find("abcdef123456789123456789")
30
+ end
31
+ end
32
+ end
33
+ end