ruby-trello 0.4.0 → 0.4.1

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