ruby-trello 0.4.4.3 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/trello/board.rb CHANGED
@@ -11,17 +11,18 @@ module Trello
11
11
  class << self
12
12
  # Finds a board.
13
13
  def find(id)
14
- super(:boards, id)
14
+ client.find(:board, id)
15
15
  end
16
16
 
17
17
  def create(fields)
18
- new('name' => fields[:name],
19
- 'desc' => fields[:description],
20
- 'closed' => fields[:closed] || false).save
18
+ client.create(:board,
19
+ 'name' => fields[:name],
20
+ 'desc' => fields[:description],
21
+ 'closed' => fields[:closed] || false)
21
22
  end
22
23
 
23
24
  def all
24
- Client.get("/members/#{Member.find(:me).username}/boards").json_into(self)
25
+ client.get("/members/#{Member.find(:me).username}/boards").json_into(self)
25
26
  end
26
27
  end
27
28
 
@@ -32,7 +33,7 @@ module Trello
32
33
  fields.merge!(:desc => description) if description
33
34
  fields.merge!(:idOrganization => organization_id) if organization_id
34
35
 
35
- Client.post("/boards", fields).json_into(self)
36
+ client.post("/boards", fields).json_into(self)
36
37
  end
37
38
 
38
39
  def update!
@@ -41,7 +42,7 @@ module Trello
41
42
  @previously_changed = changes
42
43
  @changed_attributes.clear
43
44
 
44
- Client.put("/boards/#{self.id}/", {
45
+ client.put("/boards/#{self.id}/", {
45
46
  :name => attributes[:name],
46
47
  :description => attributes[:description],
47
48
  :closed => attributes[:closed]
@@ -68,7 +69,7 @@ module Trello
68
69
  end
69
70
 
70
71
  def find_card(card_id)
71
- Client.get("/boards/#{self.id}/cards/#{card_id}").json_into(Card)
72
+ client.get("/boards/#{self.id}/cards/#{card_id}").json_into(Card)
72
73
  end
73
74
 
74
75
  # Return all the cards on this board.
@@ -93,7 +94,7 @@ module Trello
93
94
  many :members, :filter => :all
94
95
 
95
96
  # Returns a reference to the organization this board belongs to.
96
- one :organization, :using => :organization_id
97
+ one :organization, :path => :organizations, :using => :organization_id
97
98
 
98
99
  # :nodoc:
99
100
  def request_prefix
data/lib/trello/card.rb CHANGED
@@ -12,14 +12,15 @@ module Trello
12
12
  class << self
13
13
  # Find a specific card by its id.
14
14
  def find(id)
15
- super(:cards, id)
15
+ client.find(:card, id)
16
16
  end
17
17
 
18
18
  # Create a new card and save it on Trello.
19
19
  def create(options)
20
- new('name' => options[:name],
20
+ client.create(:card,
21
+ 'name' => options[:name],
21
22
  'idList' => options[:list_id],
22
- 'desc' => options[:description]).save
23
+ 'desc' => options[:description])
23
24
  end
24
25
  end
25
26
 
@@ -43,7 +44,7 @@ module Trello
43
44
  end
44
45
 
45
46
  # Returns a reference to the board this card is part of.
46
- one :board, :using => :board_id
47
+ one :board, :path => :boards, :using => :board_id
47
48
 
48
49
  # Returns a list of checklists associated with the card.
49
50
  #
@@ -53,18 +54,18 @@ module Trello
53
54
  many :checklists, :filter => :all
54
55
 
55
56
  def check_item_states
56
- states = Client.get("/cards/#{self.id}/checkItemStates").json_into(CheckItemState)
57
+ states = client.get("/cards/#{self.id}/checkItemStates").json_into(CheckItemState)
57
58
  MultiAssociation.new(self, states).proxy
58
59
  end
59
60
 
60
61
 
61
62
  # Returns a reference to the list this card is currently in.
62
- one :list, :using => :list_id
63
+ one :list, :path => :lists, :using => :list_id
63
64
 
64
65
  # Returns a list of members who are assigned to this card.
65
66
  def members
66
67
  members = member_ids.map do |member_id|
67
- Client.get("/members/#{member_id}").json_into(Member)
68
+ client.get("/members/#{member_id}").json_into(Member)
68
69
  end
69
70
  MultiAssociation.new(self, members).proxy
70
71
  end
@@ -74,7 +75,7 @@ module Trello
74
75
  # If we have an id, just update our fields.
75
76
  return update! if id
76
77
 
77
- Client.post("/cards", {
78
+ client.post("/cards", {
78
79
  :name => name,
79
80
  :desc => description,
80
81
  :idList => list_id
@@ -87,18 +88,16 @@ module Trello
87
88
  # this object before making your changes, and before updating the record.
88
89
  def update!
89
90
  @previously_changed = changes
91
+ # extract only new values to build payload
92
+ payload = Hash[changes.map { |key, values| [key.to_sym, values[1]] }]
90
93
  @changed_attributes.clear
91
94
 
92
- Client.put("/cards/#{id}", {
93
- :name => name,
94
- :desc => description,
95
- :due => due && due.utc.iso8601,
96
- :closed => closed,
97
- :idList => list_id,
98
- :idBoard => board_id,
99
- :idMembers => member_ids,
100
- :pos => pos
101
- })
95
+ client.put("/cards/#{id}", payload)
96
+ end
97
+
98
+ # Delete this card
99
+ def delete
100
+ client.delete("/cards/#{id}")
102
101
  end
103
102
 
104
103
  # Check if the card is not active anymore.
@@ -122,45 +121,49 @@ module Trello
122
121
 
123
122
  # Add a comment with the supplied text.
124
123
  def add_comment(text)
125
- Client.post("/cards/#{id}/actions/comments", :text => text)
124
+ client.post("/cards/#{id}/actions/comments", :text => text)
126
125
  end
127
126
 
128
127
  # Add a checklist to this card
129
128
  def add_checklist(checklist)
130
- Client.post("/cards/#{id}/checklists", {
129
+ client.post("/cards/#{id}/checklists", {
131
130
  :value => checklist.id
132
131
  })
133
132
  end
134
133
 
135
134
  # Move this card to the given list
136
135
  def move_to_list(list)
137
- Client.put("/cards/#{id}/idList", {
138
- :value => list.id
139
- })
136
+ unless list_id == list.id
137
+ client.put("/cards/#{id}/idList", {
138
+ :value => list.id
139
+ })
140
+ end
140
141
  end
141
142
 
142
143
  # Move this card to the given board (and optional list on this board)
143
144
  def move_to_board(new_board, new_list = nil)
144
- payload = { :value => new_board.id }
145
- payload[:idList] = new_list.id if new_list
146
- Client.put("/cards/#{id}/idBoard", payload)
145
+ unless board_id == new_board.id
146
+ payload = { :value => new_board.id }
147
+ payload[:idList] = new_list.id if new_list
148
+ client.put("/cards/#{id}/idBoard", payload)
149
+ end
147
150
  end
148
151
 
149
152
  # Add a member to this card
150
153
  def add_member(member)
151
- Client.post("/cards/#{id}/members", {
154
+ client.post("/cards/#{id}/members", {
152
155
  :value => member.id
153
156
  })
154
157
  end
155
158
 
156
159
  # Remove a member from this card
157
160
  def remove_member(member)
158
- Client.delete("/cards/#{id}/members/#{member.id}")
161
+ client.delete("/cards/#{id}/members/#{member.id}")
159
162
  end
160
163
 
161
164
  # Retrieve a list of labels
162
165
  def labels
163
- labels = Client.get("/cards/#{id}/labels").json_into(Label)
166
+ labels = client.get("/cards/#{id}/labels").json_into(Label)
164
167
  MultiAssociation.new(self, labels).proxy
165
168
  end
166
169
 
@@ -170,7 +173,7 @@ module Trello
170
173
  errors.add(:label, "colour '#{colour}' does not exist")
171
174
  return Trello.logger.warn "The label colour '#{colour}' does not exist."
172
175
  end
173
- Client.post("/cards/#{id}/labels", { :value => colour })
176
+ client.post("/cards/#{id}/labels", { :value => colour })
174
177
  end
175
178
 
176
179
  # Remove a label
@@ -179,18 +182,18 @@ module Trello
179
182
  errors.add(:label, "colour '#{colour}' does not exist")
180
183
  return Trello.logger.warn "The label colour '#{colour}' does not exist." unless %w{green yellow orange red purple blue}.include? colour
181
184
  end
182
- Client.delete("/cards/#{id}/labels/#{colour}")
185
+ client.delete("/cards/#{id}/labels/#{colour}")
183
186
  end
184
187
 
185
188
  # Add an attachment to this card
186
189
  def add_attachment(attachment, name='')
187
190
  if attachment.is_a? File
188
- Client.post("/cards/#{id}/attachments", {
191
+ client.post("/cards/#{id}/attachments", {
189
192
  :file => attachment,
190
193
  :name => name
191
194
  })
192
195
  else
193
- Client.post("/cards/#{id}/attachments", {
196
+ client.post("/cards/#{id}/attachments", {
194
197
  :url => attachment,
195
198
  :name => name
196
199
  })
@@ -199,13 +202,13 @@ module Trello
199
202
 
200
203
  # Retrieve a list of attachments
201
204
  def attachments
202
- attachments = Client.get("/cards/#{id}/attachments").json_into(Attachment)
205
+ attachments = client.get("/cards/#{id}/attachments").json_into(Attachment)
203
206
  MultiAssociation.new(self, attachments).proxy
204
207
  end
205
208
 
206
209
  # Remove an attachment from this card
207
210
  def remove_attachment(attachment)
208
- Client.delete("/cards/#{id}/attachments/#{attachment.id}")
211
+ client.delete("/cards/#{id}/attachments/#{attachment.id}")
209
212
  end
210
213
 
211
214
  # :nodoc:
@@ -9,12 +9,13 @@ module Trello
9
9
  class << self
10
10
  # Locate a specific checklist by its id.
11
11
  def find(id)
12
- super(:checklists, id)
12
+ client.find(:checklist, id)
13
13
  end
14
14
 
15
15
  def create(options)
16
- new('name' => options[:name],
17
- 'idBoard' => options[:board_id]).save
16
+ client.create(:checklist,
17
+ 'name' => options[:name],
18
+ 'idBoard' => options[:board_id])
18
19
  end
19
20
  end
20
21
 
@@ -30,6 +31,7 @@ module Trello
30
31
  attributes[:url] = fields['url']
31
32
  attributes[:check_items] = fields['checkItems']
32
33
  attributes[:board_id] = fields['idBoard']
34
+ attributes[:list_id] = fields['idList']
33
35
  attributes[:member_ids] = fields['idMembers']
34
36
  self
35
37
  end
@@ -43,14 +45,14 @@ module Trello
43
45
  def save
44
46
  return update! if id
45
47
 
46
- Client.post("/checklists", {
48
+ client.post("/checklists", {
47
49
  :name => name,
48
50
  :idBoard => board_id
49
51
  }).json_into(self)
50
52
  end
51
53
 
52
54
  def update!
53
- Client.put("/checklists/#{id}", { :name => name }).json_into(self)
55
+ client.put("/checklists/#{id}", { :name => name }).json_into(self)
54
56
  end
55
57
 
56
58
  # Return a list of items on the checklist.
@@ -61,10 +63,10 @@ module Trello
61
63
  end
62
64
 
63
65
  # Return a reference to the board the checklist is on.
64
- one :board, :using => :board_id
66
+ one :board, :path => :checklists, :using => :board_id
65
67
 
66
68
  # Return a reference to the list the checklist is on.
67
- one :list, :using => :list_id
69
+ one :list, :path => :lists, :using => :list_id
68
70
 
69
71
  # Return a list of members active in this checklist.
70
72
  def members
@@ -76,7 +78,7 @@ module Trello
76
78
 
77
79
  # Add an item to the checklist
78
80
  def add_item(name)
79
- Client.post("/checklists/#{id}/checkItems", { :name => name })
81
+ client.post("/checklists/#{id}/checkItems", { :name => name })
80
82
  end
81
83
  end
82
84
  end
data/lib/trello/client.rb CHANGED
@@ -2,48 +2,117 @@ require 'addressable/uri'
2
2
 
3
3
  module Trello
4
4
  class Client
5
- extend Authorization
5
+ extend Forwardable
6
+ include Authorization
6
7
 
7
- class << self
8
- def get(path, params = {})
9
- uri = Addressable::URI.parse("https://api.trello.com/#{API_VERSION}#{path}")
10
- uri.query_values = params unless params.empty?
11
- invoke_verb(:get, uri)
12
- end
8
+ def_delegators :configuration, :credentials, *Configuration.configurable_attributes
9
+
10
+ def initialize(attrs = {})
11
+ self.configuration.attributes = attrs
12
+ end
13
+
14
+ def get(path, params = {})
15
+ uri = Addressable::URI.parse("https://api.trello.com/#{API_VERSION}#{path}")
16
+ uri.query_values = params unless params.empty?
17
+ invoke_verb(:get, uri)
18
+ end
19
+
20
+ def post(path, body = {})
21
+ uri = Addressable::URI.parse("https://api.trello.com/#{API_VERSION}#{path}")
22
+ invoke_verb(:post, uri, body)
23
+ end
13
24
 
14
- def post(path, body = {})
15
- uri = Addressable::URI.parse("https://api.trello.com/#{API_VERSION}#{path}")
16
- invoke_verb(:post, uri, body)
25
+ def put(path, body = {})
26
+ uri = Addressable::URI.parse("https://api.trello.com/#{API_VERSION}#{path}")
27
+ invoke_verb(:put, uri, body)
28
+ end
29
+
30
+ def delete(path)
31
+ uri = Addressable::URI.parse("https://api.trello.com/#{API_VERSION}#{path}")
32
+ invoke_verb(:delete, uri)
33
+ end
34
+
35
+ # Finds given resource by id
36
+ #
37
+ # Examples:
38
+ # client.find(:board, "board1234")
39
+ # client.find(:member, "user1234")
40
+ #
41
+ def find(path, id)
42
+ response = get("/#{path.to_s.pluralize}/#{id}")
43
+ trello_class = class_from_path(path)
44
+ trello_class.parse response do |data|
45
+ data.client = self
17
46
  end
47
+ end
18
48
 
19
- def put(path, body = {})
20
- uri = Addressable::URI.parse("https://api.trello.com/#{API_VERSION}#{path}")
21
- invoke_verb(:put, uri, body)
49
+ # Finds given resource by path with params
50
+ def find_many(trello_class, path, params = {})
51
+ response = get(path, params)
52
+ trello_class.parse_many response do |data|
53
+ data.client = self
22
54
  end
55
+ end
23
56
 
24
- def delete(path)
25
- uri = Addressable::URI.parse("https://api.trello.com/#{API_VERSION}#{path}")
26
- invoke_verb(:delete, uri)
57
+ # Creates resource with given options (attributes)
58
+ #
59
+ # Examples:
60
+ # client.create(:member, options)
61
+ # client.create(:board, options)
62
+ #
63
+ def create(path, options)
64
+ trello_class = class_from_path(path)
65
+ trello_class.save options do |data|
66
+ data.client = self
27
67
  end
68
+ end
28
69
 
29
- def invoke_verb(name, uri, body = nil)
30
- request = Request.new name, uri, {}, body
31
- response = TInternet.execute AuthPolicy.authorize(request)
70
+ def configure
71
+ yield configuration if block_given?
72
+ end
73
+
74
+ def configuration
75
+ @configuration ||= Configuration.new
76
+ end
32
77
 
33
- return '' unless response
78
+ def auth_policy
79
+ @auth_policy ||= auth_policy_class.new(credentials)
80
+ end
34
81
 
35
- if response.code.to_i == 401 && response.body =~ /expired token/
36
- Trello.logger.error("[401 #{name.to_s.upcase} #{uri}]: Your access token has expired.")
37
- raise InvalidAccessToken, response.body
38
- end
82
+ private
39
83
 
40
- unless [200, 201].include? response.code
41
- Trello.logger.error("[#{response.code} #{name.to_s.upcase} #{uri}]: #{response.body}")
42
- raise Error, response.body
43
- end
84
+ def invoke_verb(name, uri, body = nil)
85
+ request = Request.new name, uri, {}, body
86
+ response = TInternet.execute auth_policy.authorize(request)
87
+
88
+ return '' unless response
89
+
90
+ if response.code.to_i == 401 && response.body =~ /expired token/
91
+ Trello.logger.error("[401 #{name.to_s.upcase} #{uri}]: Your access token has expired.")
92
+ raise InvalidAccessToken, response.body
93
+ end
44
94
 
45
- response.body
95
+ unless [200, 201].include? response.code
96
+ Trello.logger.error("[#{response.code} #{name.to_s.upcase} #{uri}]: #{response.body}")
97
+ raise Error, response.body
46
98
  end
99
+
100
+ response.body
101
+ end
102
+
103
+ def auth_policy_class
104
+ if configuration.oauth?
105
+ OAuthPolicy
106
+ elsif configuration.basic?
107
+ BasicAuthPolicy
108
+ else
109
+ AuthPolicy
110
+ end
111
+ end
112
+
113
+ def class_from_path(path_or_class)
114
+ return path_or_class if path_or_class.is_a?(Class)
115
+ Trello.const_get(path_or_class.to_s.singularize.camelize)
47
116
  end
48
117
  end
49
118
  end