ruby-trello 0.3.2 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/trello.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'oauth'
2
2
  require 'json'
3
3
  require 'logger'
4
+ require 'active_model'
4
5
 
5
6
  # Ruby wrapper around the Trello[http://trello.com] API
6
7
  #
@@ -31,6 +32,7 @@ module Trello
31
32
  autoload :Card, 'trello/card'
32
33
  autoload :Checklist, 'trello/checklist'
33
34
  autoload :Client, 'trello/client'
35
+ autoload :HasActions, 'trello/has_actions'
34
36
  autoload :Item, 'trello/item'
35
37
  autoload :ItemState, 'trello/item_state'
36
38
  autoload :List, 'trello/list'
@@ -61,4 +63,4 @@ module Trello
61
63
  def self.logger=(logger)
62
64
  @logger = logger
63
65
  end
64
- end
66
+ end
data/lib/trello/action.rb CHANGED
@@ -1,7 +1,8 @@
1
1
  module Trello
2
2
  # Action represents some event that occurred. For instance, when a card is created.
3
3
  class Action < BasicData
4
- attr_reader :id, :type, :data, :member_creator_id
4
+ register_attributes :id, :type, :data, :date, :member_creator_id
5
+ validates_presence_of :id, :type, :date, :member_creator_id
5
6
 
6
7
  class << self
7
8
  # Locate a specific action and return a new Action object.
@@ -15,35 +16,32 @@ module Trello
15
16
  # Supply a hash of string keyed data retrieved from the Trello API representing
16
17
  # an Action.
17
18
  def update_fields(fields)
18
- @id = fields['id']
19
- @type = fields['type']
20
- @data = fields['data']
21
- @member_creator_id = fields['idMemberCreator']
19
+ attributes[:id] = fields['id']
20
+ attributes[:type] = fields['type']
21
+ attributes[:data] = fields['data']
22
+ attributes[:date] = fields['date']
23
+ attributes[:member_creator_id] = fields['idMemberCreator']
22
24
  self
23
25
  end
24
26
 
25
27
  # Returns the board this action occurred on.
26
28
  def board
27
- return @board if @board
28
- @board = Client.get("/actions/#{id}/board").json_into(Board)
29
+ Client.get("/actions/#{id}/board").json_into(Board)
29
30
  end
30
31
 
31
32
  # Returns the card the action occurred on.
32
33
  def card
33
- return @card if @card
34
- @card = Client.get("/actions/#{id}/card").json_into(Card)
34
+ Client.get("/actions/#{id}/card").json_into(Card)
35
35
  end
36
36
 
37
37
  # Returns the list the action occurred on.
38
38
  def list
39
- return @list if @list
40
- @list = Client.get("/actions/#{id}/list").json_into(List)
39
+ Client.get("/actions/#{id}/list").json_into(List)
41
40
  end
42
41
 
43
42
  # Returns the member who created the action.
44
43
  def member_creator
45
- return @member_creator if @member_creator
46
- @member_creator = Member.find(member_creator_id)
44
+ Member.find(member_creator_id)
47
45
  end
48
46
  end
49
47
  end
@@ -2,7 +2,9 @@ require 'trello/string'
2
2
 
3
3
  module Trello
4
4
  class BasicData
5
- attr_reader :id
5
+ include ActiveModel::Validations
6
+ include ActiveModel::Dirty
7
+ include ActiveModel::Serializers::JSON
6
8
 
7
9
  class << self
8
10
  def find(path, id)
@@ -10,6 +12,27 @@ module Trello
10
12
  end
11
13
  end
12
14
 
15
+ def self.register_attributes(*names)
16
+ # Defines the attribute getter and setters.
17
+ class_eval do
18
+ define_method :attributes do
19
+ @attributes ||= names.inject({}) { |hash,k| hash.merge(k.to_sym => nil) }
20
+ end
21
+
22
+ names.each do |key|
23
+ define_method(:"#{key}") { @attributes[key] }
24
+
25
+ define_method :"#{key}=" do |val|
26
+ send(:"#{key}_will_change!") unless val == @attributes[key]
27
+ @attributes[key] = val
28
+ end
29
+ end
30
+ define_attribute_methods names
31
+ end
32
+ end
33
+
34
+ register_attributes :id
35
+
13
36
  def initialize(fields = {})
14
37
  update_fields(fields)
15
38
  end
data/lib/trello/board.rb CHANGED
@@ -1,34 +1,40 @@
1
1
  module Trello
2
2
 
3
3
  class Board < BasicData
4
- attr_reader :id, :name, :description, :url, :organization_id
4
+ register_attributes :id, :name, :description, :url, :organization_id
5
+ validates_presence_of :id, :name
5
6
 
6
- class << self
7
+ include HasActions
7
8
 
9
+ class << self
10
+ # Finds a board.
8
11
  def find(id)
9
12
  super(:boards, id)
10
13
  end
11
14
 
12
- def create(attributes)
13
- new('name' => attributes[:name],
14
- 'desc' => attributes[:description],
15
- 'closed' => attributes[:closed] || false).save!
15
+ def create(fields)
16
+ new('name' => fields[:name],
17
+ 'desc' => fields[:description],
18
+ 'closed' => fields[:closed] || false).save
16
19
  end
17
20
  end
18
21
 
19
- def save!
22
+ def save
20
23
  return update! if id
21
24
 
22
- attributes = { :name => name }
23
- attributes.merge!(:desc => description) if description
24
- attributes.merge!(:idOrganization => organization_id) if organization_id
25
+ fields = { :name => name }
26
+ fields.merge!(:desc => description) if description
27
+ fields.merge!(:idOrganization => organization_id) if organization_id
25
28
 
26
- Client.post("/boards", attributes).json_into(self)
29
+ Client.post("/boards", fields).json_into(self)
27
30
  end
28
31
 
29
32
  def update!
30
33
  fail "Cannot save new instance." unless self.id
31
34
 
35
+ @previously_changed = changes
36
+ @changed_attributes.clear
37
+
32
38
  Client.put("/boards/#{self.id}/", {
33
39
  :name => @name,
34
40
  :description => @description,
@@ -37,24 +43,18 @@ module Trello
37
43
  end
38
44
 
39
45
  def update_fields(fields)
40
- @id = fields['id'] if fields['id']
41
- @name = fields['name'] if fields['name']
42
- @description = fields['desc'] if fields['desc']
43
- @closed = fields['closed'] if fields.has_key?('closed')
44
- @url = fields['url'] if fields['url']
45
- @organization_id = fields['idOrganization'] if fields['idOrganization']
46
+ attributes[:id] = fields['id'] if fields['id']
47
+ attributes[:name] = fields['name'] if fields['name']
48
+ attributes[:description] = fields['desc'] if fields['desc']
49
+ attributes[:closed] = fields['closed'] if fields.has_key?('closed')
50
+ attributes[:url] = fields['url'] if fields['url']
51
+ attributes[:organization_id] = fields['idOrganization'] if fields['idOrganization']
46
52
 
47
53
  self
48
54
  end
49
55
 
50
56
  def closed?
51
- @closed
52
- end
53
-
54
- # Return a timeline of actions related to this board.
55
- def actions
56
- return @actions if @actions
57
- @actions = Client.get("/boards/#{id}/actions").json_into(Action)
57
+ @attributes[:closed]
58
58
  end
59
59
 
60
60
  # Return all the cards on this board.
@@ -63,8 +63,7 @@ module Trello
63
63
  # of the following values:
64
64
  # :filter => [ :none, :open, :closed, :all ] # default :open
65
65
  def cards(options = { :filter => :open })
66
- return @cards if @cards
67
- @cards = Client.get("/boards/#{id}/cards").json_into(Card)
66
+ Client.get("/boards/#{id}/cards").json_into(Card)
68
67
  end
69
68
 
70
69
  def has_lists?
@@ -77,8 +76,7 @@ module Trello
77
76
  # of the following values:
78
77
  # :filter => [ :none, :open, :closed, :all ] # default :open
79
78
  def lists(options = { :filter => :open })
80
- return @lists if @lists
81
- @lists = Client.get("/boards/#{id}/lists", options).json_into(List)
79
+ Client.get("/boards/#{id}/lists", options).json_into(List)
82
80
  end
83
81
 
84
82
  # Returns an array of members who are associated with this board.
@@ -87,14 +85,17 @@ module Trello
87
85
  # of the following values:
88
86
  # :filter => [ :none, :normal, :owners, :all ] # default :all
89
87
  def members(options = { :filter => :all })
90
- return @members if @members
91
- @members = Client.get("/boards/#{id}/members", options).json_into(Member)
88
+ Client.get("/boards/#{id}/members", options).json_into(Member)
92
89
  end
93
90
 
94
91
  # Returns a reference to the organization this board belongs to.
95
92
  def organization
96
- return @organization if @organization
97
- @organization = Organization.find(organization_id)
93
+ Organization.find(organization_id)
94
+ end
95
+
96
+ # :nodoc:
97
+ def request_prefix
98
+ "/boards/#{id}"
98
99
  end
99
100
  end
100
101
  end
data/lib/trello/card.rb CHANGED
@@ -1,8 +1,10 @@
1
1
  module Trello
2
2
  # A Card is a container that can house checklists and comments; it resides inside a List.
3
3
  class Card < BasicData
4
- attr_reader :id
5
- attr_accessor :name, :description, :closed, :url, :board_id, :member_ids, :list_id
4
+ register_attributes :id, :short_id, :name, :description, :closed, :url, :board_id, :member_ids, :list_id
5
+ validates_presence_of :id, :name, :list_id
6
+
7
+ include HasActions
6
8
 
7
9
  class << self
8
10
  # Find a specific card by its id.
@@ -14,7 +16,7 @@ module Trello
14
16
  def create(options)
15
17
  new('name' => options[:name],
16
18
  'idList' => options[:list_id],
17
- 'desc' => options[:description]).save!
19
+ 'desc' => options[:description]).save
18
20
  end
19
21
  end
20
22
 
@@ -23,27 +25,21 @@ module Trello
23
25
  # Supply a hash of string keyed data retrieved from the Trello API representing
24
26
  # a card.
25
27
  def update_fields(fields)
26
- @id = fields['id']
27
- @name = fields['name']
28
- @description = fields['desc']
29
- @closed = fields['closed']
30
- @url = fields['url']
31
- @board_id = fields['idBoard']
32
- @member_ids = fields['idMembers']
33
- @list_id = fields['idList']
28
+ attributes[:id] = fields['id']
29
+ attributes[:short_id] = fields['idShort']
30
+ attributes[:name] = fields['name']
31
+ attributes[:description] = fields['desc']
32
+ attributes[:closed] = fields['closed']
33
+ attributes[:url] = fields['url']
34
+ attributes[:board_id] = fields['idBoard']
35
+ attributes[:member_ids] = fields['idMembers']
36
+ attributes[:list_id] = fields['idList']
34
37
  self
35
38
  end
36
39
 
37
- # Returns a list of the actions associated with this card.
38
- def actions
39
- return @actions if @actions
40
- @actions = Client.get("/cards/#{id}/actions").json_into(Action)
41
- end
42
-
43
40
  # Returns a reference to the board this card is part of.
44
41
  def board
45
- return @board if @board
46
- @board = Board.find(board_id)
42
+ Board.find(board_id)
47
43
  end
48
44
 
49
45
  # Returns a list of checklists associated with the card.
@@ -52,52 +48,30 @@ module Trello
52
48
  # of the following values:
53
49
  # :filter => [ :none, :all ] # default :all
54
50
  def checklists(options = { :filter => :all })
55
- return @checklists if @checklists
56
- @checklists = Client.get("/cards/#{id}/checklists", options).json_into(Checklist)
51
+ Client.get("/cards/#{id}/checklists", options).json_into(Checklist)
57
52
  end
58
53
 
59
54
  # Returns a reference to the list this card is currently in.
60
55
  def list
61
- return @list if @list
62
- @list = List.find(list_id)
56
+ List.find(list_id)
63
57
  end
64
58
 
65
59
  # Returns a list of members who are assigned to this card.
66
60
  def members
67
- return @members if @members
68
- @members = member_ids.map do |member_id|
61
+ member_ids.map do |member_id|
69
62
  Client.get("/members/#{member_id}").json_into(Member)
70
63
  end
71
64
  end
72
65
 
73
- # Change the name of the card
74
- def name=(val)
75
- Client.put("/card/#{id}/name", :value => val)
76
- @name = val
77
- end
78
-
79
- # Change the description of the card
80
- def description=(val)
81
- Client.put("/card/#{id}/desc", :value => val)
82
- @description = val
83
- end
84
-
85
- # Change the list this card is a part of
86
- def list=(other)
87
- Client.put("/card/#{id}/idList", :value => other.id)
88
- @list_id = other.id
89
- other
90
- end
91
-
92
66
  # Saves a record.
93
- def save!
67
+ def save
94
68
  # If we have an id, just update our fields.
95
69
  return update! if id
96
70
 
97
71
  Client.post("/cards", {
98
- :name => @name,
99
- :desc => @description,
100
- :idList => @list_id
72
+ :name => name,
73
+ :desc => description,
74
+ :idList => list_id
101
75
  }).json_into(self)
102
76
  end
103
77
 
@@ -106,19 +80,22 @@ module Trello
106
80
  # an external resource has updated these fields, you should refresh!
107
81
  # this object before making your changes, and before updating the record.
108
82
  def update!
83
+ @previously_changed = changes
84
+ @changed_attributes.clear
85
+
109
86
  Client.put("/cards/#{@id}", {
110
- :name => @name,
111
- :desc => @description,
112
- :closed => @closed,
113
- :idList => @list_id,
114
- :idBoard => @board_id,
115
- :idMembers => @member_ids
87
+ :name => name,
88
+ :desc => description,
89
+ :closed => closed,
90
+ :idList => list_id,
91
+ :idBoard => board_id,
92
+ :idMembers => member_ids
116
93
  }).json_into(self)
117
94
  end
118
95
 
119
96
  # Is the record valid?
120
97
  def valid?
121
- @name && @list_id
98
+ name && list_id
122
99
  end
123
100
 
124
101
  # Add a comment with the supplied text.
@@ -144,5 +121,11 @@ module Trello
144
121
  return logger.warn "The label colour '#{colour}' does not exist." unless %w{green yellow orange red purple blue}.include? colour
145
122
  Client.delete("/cards/#{id}/labels/#{colour}")
146
123
  end
124
+
125
+ # :nodoc:
126
+ def request_prefix
127
+ "/cards/#{id}"
128
+ end
129
+
147
130
  end
148
131
  end
@@ -1,7 +1,8 @@
1
1
  module Trello
2
2
  # A Checklist holds items which are like a "task" list. Checklists are linked to a card.
3
3
  class Checklist < BasicData
4
- attr_reader :id, :name, :description, :closed, :url, :check_items, :board_id, :list_id, :member_ids
4
+ register_attributes :id, :name, :description, :closed, :url, :check_items, :board_id, :list_id, :member_ids
5
+ validates_presence_of :id, :board_id, :list_id
5
6
 
6
7
  class << self
7
8
  # Locate a specific checklist by its id.
@@ -20,14 +21,14 @@ module Trello
20
21
  # Supply a hash of string keyed data retrieved from the Trello API representing
21
22
  # a checklist.
22
23
  def update_fields(fields)
23
- @id = fields['id']
24
- @name = fields['name']
25
- @description = fields['desc']
26
- @closed = fields['closed']
27
- @url = fields['url']
28
- @check_items = fields['checkItems']
29
- @board_id = fields['idBoard']
30
- @member_ids = fields['idMembers']
24
+ attributes[:id] = fields['id']
25
+ attributes[:name] = fields['name']
26
+ attributes[:description] = fields['desc']
27
+ attributes[:closed] = fields['closed']
28
+ attributes[:url] = fields['url']
29
+ attributes[:check_items] = fields['checkItems']
30
+ attributes[:board_id] = fields['idBoard']
31
+ attributes[:member_ids] = fields['idMembers']
31
32
  self
32
33
  end
33
34
 
@@ -37,7 +38,7 @@ module Trello
37
38
  end
38
39
 
39
40
  # Save a record.
40
- def save!
41
+ def save
41
42
  return update! if id
42
43
 
43
44
  Client.post("/checklists", {
@@ -52,30 +53,24 @@ module Trello
52
53
 
53
54
  # Return a list of items on the checklist.
54
55
  def items
55
- return @items if @items
56
-
57
- @items = check_items.map do |item_fields|
56
+ check_items.map do |item_fields|
58
57
  Item.new(item_fields)
59
58
  end
60
59
  end
61
60
 
62
61
  # Return a reference to the board the checklist is on.
63
62
  def board
64
- return @board if @board
65
- @board = Board.find(board_id)
63
+ Board.find(board_id)
66
64
  end
67
65
 
68
66
  # Return a reference to the list the checklist is on.
69
67
  def list
70
- return @list if @list
71
- @list = List.find(list_id)
68
+ List.find(list_id)
72
69
  end
73
70
 
74
71
  # Return a list of members active in this checklist.
75
72
  def members
76
- return @members if @members
77
-
78
- @members = member_ids.map do |member_id|
73
+ member_ids.map do |member_id|
79
74
  Member.find(member_id)
80
75
  end
81
76
  end
data/lib/trello/client.rb CHANGED
@@ -35,8 +35,8 @@ module Trello
35
35
  raise InvalidAccessToken, response.body
36
36
  end
37
37
 
38
- unless response.code.to_i == 200
39
- Trello.logger.error("[#{response.code.to_i} #{name.to_s.upcase} #{uri}]: #{response.body}")
38
+ unless [200, 201].include? response.code
39
+ Trello.logger.error("[#{response.code} #{name.to_s.upcase} #{uri}]: #{response.body}")
40
40
  raise Error, response.body
41
41
  end
42
42
 
@@ -0,0 +1,8 @@
1
+ module Trello
2
+ module HasActions
3
+ # Returns a list of the actions associated with this object.
4
+ def actions(options = {})
5
+ Client.get("#{request_prefix}/actions", { :filter => :all }.merge(options)).json_into(Action)
6
+ end
7
+ end
8
+ end
data/lib/trello/item.rb CHANGED
@@ -1,16 +1,17 @@
1
1
  module Trello
2
2
  # An Item is a basic task that can be checked off and marked as completed.
3
3
  class Item < BasicData
4
- attr_reader :id, :name, :type
4
+ register_attributes :id, :name, :type
5
+ validates_presence_of :id, :type
5
6
 
6
7
  # Updates the fields of an item.
7
8
  #
8
9
  # Supply a hash of string keyed data retrieved from the Trello API representing
9
10
  # an item.
10
11
  def update_fields(fields)
11
- @id = fields['id']
12
- @name = fields['name']
13
- @type = fields['type']
12
+ attributes[:id] = fields['id']
13
+ attributes[:name] = fields['name']
14
+ attributes[:type] = fields['type']
14
15
  self
15
16
  end
16
17
  end
@@ -1,22 +1,23 @@
1
1
  module Trello
2
2
  # Represents the state of an item.
3
3
  class ItemState < BasicData
4
- attr_reader :id, :state, :item_id
4
+ register_attributes :id, :state, :item_id
5
+ validates_presence_of :id, :item_id
5
6
 
6
7
  # Update the fields of an item state.
7
8
  #
8
9
  # Supply a hash of string keyed data retrieved from the Trello API representing
9
10
  # an item state.
10
11
  def update_fields(fields)
11
- @id = fields['id']
12
- @state = fields['state']
13
- @item_id = fields['idItem']
12
+ attributes[:id] = fields['id']
13
+ attributes[:state] = fields['state']
14
+ attributes[:item_id] = fields['idItem']
14
15
  self
15
16
  end
16
17
 
17
18
  # Return the item this state belongs to.
18
19
  def item
19
- Item.find(@item_id)
20
+ Item.find(item_id)
20
21
  end
21
22
  end
22
23
  end
data/lib/trello/list.rb CHANGED
@@ -1,7 +1,10 @@
1
1
  module Trello
2
2
  # A List is a container which holds cards. Lists are items on a board.
3
3
  class List < BasicData
4
- attr_reader :id, :name, :closed, :board_id
4
+ register_attributes :id, :name, :closed, :board_id
5
+ validates_presence_of :id, :name, :board_id
6
+
7
+ include HasActions
5
8
 
6
9
  class << self
7
10
  # Finds a specific list, given an id.
@@ -20,14 +23,14 @@ module Trello
20
23
  # Supply a hash of string keyed data retrieved from the Trello API representing
21
24
  # a List.
22
25
  def update_fields(fields)
23
- @id = fields['id']
24
- @name = fields['name']
25
- @closed = fields['closed']
26
- @board_id = fields['idBoard']
26
+ attributes[:id] = fields['id']
27
+ attributes[:name] = fields['name']
28
+ attributes[:closed] = fields['closed']
29
+ attributes[:board_id] = fields['idBoard']
27
30
  self
28
31
  end
29
32
 
30
- def save!
33
+ def save
31
34
  return update! if id
32
35
 
33
36
  Client.post("/lists", {
@@ -49,16 +52,9 @@ module Trello
49
52
  closed
50
53
  end
51
54
 
52
- # Return a timeline of events related to this list.
53
- def actions
54
- return @actions if @actions
55
- @actions = Client.get("/lists/#{id}/actions").json_into(Action)
56
- end
57
-
58
55
  # Return the board the list is connected to.
59
56
  def board
60
- return @board if @board
61
- @board = Board.find(board_id)
57
+ Board.find(board_id)
62
58
  end
63
59
 
64
60
  # Returns all the cards on this list.
@@ -67,8 +63,12 @@ module Trello
67
63
  # of the following values:
68
64
  # :filter => [ :none, :open, :closed, :all ] # default :open
69
65
  def cards(options = { :filter => :open })
70
- return @cards if @cards
71
- @cards = Client.get("/lists/#{id}/cards", options).json_into(Card)
66
+ Client.get("/lists/#{id}/cards", options).json_into(Card)
67
+ end
68
+
69
+ # :nodoc:
70
+ def request_prefix
71
+ "/lists/#{id}"
72
72
  end
73
73
  end
74
74
  end
data/lib/trello/member.rb CHANGED
@@ -1,8 +1,10 @@
1
1
  module Trello
2
2
  # A Member is a user of the Trello service.
3
3
  class Member < BasicData
4
- attr_reader :id
5
- attr_accessor :full_name, :username, :gravatar_id, :bio, :url
4
+ register_attributes :id, :username, :full_name, :avatar_id, :bio, :url
5
+ validates_presence_of :id, :username
6
+
7
+ include HasActions
6
8
 
7
9
  class << self
8
10
  # Finds a user
@@ -18,19 +20,23 @@ module Trello
18
20
  # Supply a hash of string keyed data retrieved from the Trello API representing
19
21
  # an Member.
20
22
  def update_fields(fields)
21
- @id = fields['id']
22
- @full_name = fields['fullName']
23
- @username = fields['username']
24
- @gravatar_id = fields['gravatar']
25
- @bio = fields['bio']
26
- @url = fields['url']
23
+ attributes[:id] = fields['id']
24
+ attributes[:full_name] = fields['fullName']
25
+ attributes[:username] = fields['username']
26
+ attributes[:avatar_id] = fields['avatarHash']
27
+ attributes[:bio] = fields['bio']
28
+ attributes[:url] = fields['url']
27
29
  self
28
30
  end
29
31
 
30
- # Returns a list of the users actions.
31
- def actions
32
- return @actions if @actions
33
- @actions = Client.get("/members/#{username}/actions").json_into(Action)
32
+ # Retrieve a URL to the avatar.
33
+ #
34
+ # Valid values for options are:
35
+ # :large (170x170)
36
+ # :small (30x30)
37
+ def avatar_url(options = { :size => :large })
38
+ size = options[:size] == :small ? 30 : 170
39
+ "https://trello-avatars.s3.amazonaws.com/#{avatar_id}/#{size}.png"
34
40
  end
35
41
 
36
42
  # Returns a list of the boards a member is a part of.
@@ -39,8 +45,7 @@ module Trello
39
45
  # of the following values:
40
46
  # :filter => [ :none, :members, :organization, :public, :open, :closed, :all ] # default: :all
41
47
  def boards(options = { :filter => :all })
42
- return @boards if @boards
43
- @boards = Client.get("/members/#{username}/boards", options).json_into(Board)
48
+ Client.get("/members/#{username}/boards", options).json_into(Board)
44
49
  end
45
50
 
46
51
  # Returns a list of cards the member is assigned to.
@@ -49,8 +54,7 @@ module Trello
49
54
  # of the following values:
50
55
  # :filter => [ :none, :open, :closed, :all ] # default :open
51
56
  def cards(options = { :filter => :open })
52
- return @cards if @cards
53
- @cards = Client.get("/members/#{username}/cards", options).json_into(Card)
57
+ Client.get("/members/#{username}/cards", options).json_into(Card)
54
58
  end
55
59
 
56
60
  # Returns a list of the organizations this member is a part of.
@@ -59,8 +63,7 @@ module Trello
59
63
  # of the following values:
60
64
  # :filter => [ :none, :members, :public, :all ] # default: all
61
65
  def organizations(options = { :filter => :all })
62
- return @organizations if @organizations
63
- @organizations = Client.get("/members/#{username}/organizations", options).json_into(Organization)
66
+ Client.get("/members/#{username}/organizations", options).json_into(Organization)
64
67
  end
65
68
 
66
69
  # Returns a list of notifications for the user
@@ -68,16 +71,16 @@ module Trello
68
71
  Client.get("/members/#{username}/notifications").json_into(Notification)
69
72
  end
70
73
 
71
- # Returns a hash of the items that would be returned by Trello.
72
- def to_hash
73
- {
74
- 'id' => id,
75
- 'fullName' => full_name,
76
- 'username' => username,
77
- 'gravatar' => gravatar_id,
78
- 'bio' => bio,
79
- 'url' => url
80
- }
74
+ def save
75
+ @previously_changed = changes
76
+ @changed_attributes.clear
77
+
78
+ # TODO: updating attributes.
79
+ end
80
+
81
+ # :nodoc:
82
+ def request_prefix
83
+ "/members/#{username}"
81
84
  end
82
85
  end
83
86
  end
@@ -1,6 +1,7 @@
1
1
  module Trello
2
2
  class Notification < BasicData
3
- attr_reader :id, :unread, :type, :date, :data, :member_creator_id
3
+ register_attributes :id, :unread, :type, :date, :data, :member_creator_id
4
+ validates_presence_of :id, :type, :date, :member_creator_id
4
5
 
5
6
  class << self
6
7
  # Locate a notification by its id
@@ -10,12 +11,12 @@ module Trello
10
11
  end
11
12
 
12
13
  def update_fields(fields)
13
- @id = fields['id']
14
- @unread = fields['unread']
15
- @type = fields['type']
16
- @date = fields['date']
17
- @data = fields['data']
18
- @member_creator_id = fields['idMemberCreator']
14
+ attributes[:id] = fields['id']
15
+ attributes[:unread] = fields['unread']
16
+ attributes[:type] = fields['type']
17
+ attributes[:date] = fields['date']
18
+ attributes[:data] = fields['data']
19
+ attributes[:member_creator_id] = fields['idMemberCreator']
19
20
  self
20
21
  end
21
22
 
@@ -1,7 +1,10 @@
1
1
  module Trello
2
2
  # Organizations are useful for linking members together.
3
3
  class Organization < BasicData
4
- attr_reader :id, :name, :display_name, :description, :url
4
+ register_attributes :id, :name, :display_name, :description, :url
5
+ validates_presence_of :id, :name
6
+
7
+ include HasActions
5
8
 
6
9
  class << self
7
10
  # Find an organization by its id.
@@ -15,30 +18,27 @@ module Trello
15
18
  # Supply a hash of string keyed data retrieved from the Trello API representing
16
19
  # an Organization.
17
20
  def update_fields(fields)
18
- @id = fields['id']
19
- @name = fields['name']
20
- @display_name = fields['displayName']
21
- @description = fields['description']
22
- @url = fields['url']
21
+ attributes[:id] = fields['id']
22
+ attributes[:name] = fields['name']
23
+ attributes[:display_name] = fields['displayName']
24
+ attributes[:description] = fields['description']
25
+ attributes[:url] = fields['url']
23
26
  self
24
27
  end
25
28
 
26
- # Returns a timeline of actions.
27
- def actions
28
- return @actions if @actions
29
- @actions = Client.get("/organizations/#{id}/actions").json_into(Action)
30
- end
31
-
32
29
  # Returns a list of boards under this organization.
33
30
  def boards
34
- return @boards if @boards
35
- @boards = Client.get("/organizations/#{id}/boards/all").json_into(Board)
31
+ Client.get("/organizations/#{id}/boards/all").json_into(Board)
36
32
  end
37
33
 
38
34
  # Returns an array of members associated with the organization.
39
35
  def members
40
- return @members if @members
41
- @members = Client.get("/organizations/#{id}/members/all").json_into(Member)
36
+ Client.get("/organizations/#{id}/members/all").json_into(Member)
37
+ end
38
+
39
+ # :nodoc:
40
+ def request_prefix
41
+ "/organizations/#{id}"
42
42
  end
43
43
  end
44
44
  end
data/spec/action_spec.rb CHANGED
@@ -27,6 +27,10 @@ module Trello
27
27
  it "has the same data" do
28
28
  @action.data.should == @detail['data']
29
29
  end
30
+
31
+ it "gets the date" do
32
+ @action.date.should == @detail['date']
33
+ end
30
34
  end
31
35
 
32
36
  context "boards" do
data/spec/board_spec.rb CHANGED
@@ -35,7 +35,7 @@ module Trello
35
35
 
36
36
  context "actions" do
37
37
  it "has a list of actions" do
38
- Client.stub(:get).with("/boards/abcdef123456789123456789/actions").
38
+ Client.stub(:get).with("/boards/abcdef123456789123456789/actions", {:filter => :all}).
39
39
  and_return actions_payload
40
40
 
41
41
  @board.actions.count.should be > 0
@@ -56,7 +56,7 @@ module Trello
56
56
  Client.stub(:get).with("/boards/abcdef123456789123456789/lists", hash_including(:filter => :open)).
57
57
  and_return lists_payload
58
58
 
59
- @board.lists.count.should be > 0
59
+ @board.has_lists?.should be true
60
60
  end
61
61
  end
62
62
 
@@ -111,7 +111,7 @@ module Trello
111
111
  it "sets any attributes supplied in the fields argument"
112
112
  end
113
113
 
114
- describe "#save!" do
114
+ describe "#save" do
115
115
  include Helpers
116
116
 
117
117
  let(:any_board_json) do
@@ -122,7 +122,7 @@ module Trello
122
122
  Client.should_not_receive :put
123
123
 
124
124
  the_new_board = Board.new
125
- lambda{the_new_board.save!}.should raise_error
125
+ lambda{the_new_board.save}.should raise_error
126
126
  end
127
127
 
128
128
  it "puts all fields except id" do
@@ -134,7 +134,7 @@ module Trello
134
134
  end
135
135
 
136
136
  the_new_board = Board.new 'id' => "xxx"
137
- the_new_board.save!
137
+ the_new_board.save
138
138
  end
139
139
 
140
140
  it "mutates the current instance" do
@@ -142,7 +142,7 @@ module Trello
142
142
 
143
143
  board = Board.new 'id' => "xxx"
144
144
 
145
- the_result_of_save = board.save!
145
+ the_result_of_save = board.save
146
146
 
147
147
  the_result_of_save.should equal board
148
148
  end
@@ -156,7 +156,7 @@ module Trello
156
156
  end
157
157
 
158
158
  the_new_board = Board.new 'id' => expected_resource_id
159
- the_new_board.save!
159
+ the_new_board.save
160
160
  end
161
161
 
162
162
  it "saves OR updates depending on whether or not it has an id set"
data/spec/card_spec.rb CHANGED
@@ -46,7 +46,7 @@ module Trello
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" do
49
+ it "updating name does a put on the correct resource with the correct value", :broken => true do
50
50
  expected_new_name = "xxx"
51
51
  expected_resource = "/card/#{@card.id}/name"
52
52
 
@@ -60,6 +60,10 @@ module Trello
60
60
  @card.id.should_not be_nil
61
61
  end
62
62
 
63
+ it "gets its short id" do
64
+ @card.short_id.should_not be_nil
65
+ end
66
+
63
67
  it "gets its name" do
64
68
  @card.name.should_not be_nil
65
69
  end
@@ -78,10 +82,15 @@ module Trello
78
82
  end
79
83
 
80
84
  context "actions" do
81
- it "has a list of actions" do
82
- Client.stub(:get).with("/cards/abcdef123456789123456789/actions").and_return actions_payload
85
+ it "asks for all actions by default" do
86
+ Client.stub(:get).with("/cards/abcdef123456789123456789/actions", { :filter => :all }).and_return actions_payload
83
87
  @card.actions.count.should be > 0
84
88
  end
89
+
90
+ it "allows overriding the filter" do
91
+ Client.stub(:get).with("/cards/abcdef123456789123456789/actions", { :filter => :updateCard }).and_return actions_payload
92
+ @card.actions(:filter => :updateCard).count.should be > 0
93
+ end
85
94
  end
86
95
 
87
96
  context "boards" do
data/spec/client_spec.rb CHANGED
@@ -45,7 +45,7 @@ describe Client, "and how it handles authorization" do
45
45
  it "raises an error when response has non-200 status" do
46
46
  expected_error_message = "An error response"
47
47
  response_with_non_200_status = stub "A fake OK response",
48
- :code => 201,
48
+ :code => 404,
49
49
  :body => expected_error_message
50
50
 
51
51
  TInternet.stub(:execute).and_return response_with_non_200_status
@@ -14,7 +14,7 @@ describe "how to use boards", :broken => true do
14
14
  after do
15
15
  if @new_board and false == @new_board.closed?
16
16
  @new_board.update_fields 'closed' => true
17
- @new_board.save!
17
+ @new_board.save
18
18
  end
19
19
  end
20
20
 
@@ -36,7 +36,7 @@ describe "how to use boards", :broken => true do
36
36
  @new_board = Board.create(:name => "[#{Time.now}, CLOSED] An example")
37
37
 
38
38
  @new_board.update_fields 'closed' => true
39
- @new_board.save!
39
+ @new_board.save
40
40
 
41
41
  Board.find(@new_board.id).should be_closed
42
42
  end
data/spec/list_spec.rb CHANGED
@@ -31,7 +31,7 @@ module Trello
31
31
 
32
32
  context "actions" do
33
33
  it "has a list of actions" do
34
- Client.stub(:get).with("/lists/abcdef123456789123456789/actions").and_return actions_payload
34
+ Client.stub(:get).with("/lists/abcdef123456789123456789/actions", { :filter => :all }).and_return actions_payload
35
35
  @list.actions.count.should be > 0
36
36
  end
37
37
  end
data/spec/member_spec.rb CHANGED
@@ -14,7 +14,7 @@ module Trello
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").and_return actions_payload
17
+ Client.stub(:get).with("/members/me/actions", { :filter => :all }).and_return actions_payload
18
18
  @member.actions.count.should be > 0
19
19
  end
20
20
  end
@@ -43,6 +43,13 @@ module Trello
43
43
  end
44
44
  end
45
45
 
46
+ context "notifications" do
47
+ it "has a list of notifications" do
48
+ Client.stub(:get).with("/members/me/notifications").and_return "[" << notification_payload << "]"
49
+ @member.notifications.count.should be 1
50
+ end
51
+ end
52
+
46
53
  context "personal" do
47
54
  it "gets the members bio" do
48
55
  @member.bio.should == user_details['bio']
@@ -52,8 +59,13 @@ module Trello
52
59
  @member.full_name.should == user_details['fullName']
53
60
  end
54
61
 
55
- it "gets the gravatar id" do
56
- @member.gravatar_id.should == user_details['gravatar']
62
+ it "gets the avatar id" do
63
+ @member.avatar_id.should == user_details['avatarHash']
64
+ end
65
+
66
+ it "returns a valid url for the avatar" do
67
+ @member.avatar_url(:size => :large).should == "https://trello-avatars.s3.amazonaws.com/abcdef1234567890abcdef1234567890/170.png"
68
+ @member.avatar_url(:size => :small).should == "https://trello-avatars.s3.amazonaws.com/abcdef1234567890abcdef1234567890/30.png"
57
69
  end
58
70
 
59
71
  it "gets the url" do
@@ -64,5 +76,13 @@ module Trello
64
76
  @member.username.should == user_details['username']
65
77
  end
66
78
  end
79
+
80
+ context "modification" do
81
+ it "lets us know a field has changed without committing it" do
82
+ @member.changed?.should be_false
83
+ @member.bio = "New and amazing"
84
+ @member.changed?.should be_true
85
+ end
86
+ end
67
87
  end
68
88
  end
@@ -0,0 +1,26 @@
1
+
2
+ require 'spec_helper'
3
+
4
+ module Trello
5
+ describe Organization do
6
+ include Helpers
7
+
8
+ before(:each) do
9
+ Client.stub(:get).with("/organizations/4ee7e59ae582acdec8000291").
10
+ and_return organization_payload
11
+
12
+ @organization = Organization.find('4ee7e59ae582acdec8000291')
13
+ end
14
+
15
+ context "actions" do
16
+ it "retrieves actions" do
17
+ Client.stub(:get).with("/organizations/4ee7e59ae582acdec8000291/actions", { :filter => :all }).and_return actions_payload
18
+ @organization.actions.count.should be > 0
19
+ end
20
+
21
+ end
22
+
23
+ end
24
+
25
+ end
26
+
data/spec/spec_helper.rb CHANGED
@@ -19,6 +19,10 @@ Bundler.require(:spec)
19
19
 
20
20
  require 'trello'
21
21
  require 'webmock/rspec'
22
+ require 'stringio'
23
+
24
+ $strio = StringIO.new
25
+ Trello.logger = Logger.new($strio)
22
26
 
23
27
  RSpec.configure do |c|
24
28
  c.filter_run_excluding :broken => true
@@ -27,12 +31,12 @@ end
27
31
  module Helpers
28
32
  def user_details
29
33
  {
30
- "id" => "abcdef123456789012345678",
31
- "fullName" => "Test User",
32
- "username" => "me",
33
- "gravatar" => "abcdef1234567890abcdef1234567890",
34
- "bio" => "a rather dumb user",
35
- "url" => "https://trello.com/me"
34
+ "id" => "abcdef123456789012345678",
35
+ "fullName" => "Test User",
36
+ "username" => "me",
37
+ "avatarHash" => "abcdef1234567890abcdef1234567890",
38
+ "bio" => "a rather dumb user",
39
+ "url" => "https://trello.com/me"
36
40
  }
37
41
  end
38
42
 
@@ -89,6 +93,7 @@ module Helpers
89
93
  def cards_details
90
94
  [{
91
95
  "id" => "abcdef123456789123456789",
96
+ "idShort" => "1",
92
97
  "name" => "Do something awesome",
93
98
  "desc" => "Awesome things are awesome.",
94
99
  "closed" => false,
@@ -135,6 +140,7 @@ module Helpers
135
140
  "name" => "Assembler"
136
141
  }
137
142
  },
143
+ "date" => "2012-02-10T11:32:17.447Z",
138
144
  "type" => "createCard"
139
145
  }]
140
146
  end
@@ -167,4 +173,29 @@ module Helpers
167
173
  def notification_payload
168
174
  JSON.generate(notification_details)
169
175
  end
176
+
177
+ def organization_details
178
+ {
179
+ "id" => "4ee7e59ae582acdec8000291",
180
+ "name" => "publicorg",
181
+ "desc" => "This is a test organization",
182
+ "members" => [{
183
+ "id" => "4ee7df3ce582acdec80000b2",
184
+ "username" => "alicetester",
185
+ "fullName" => "Alice Tester"
186
+ }, {
187
+ "id" => "4ee7df74e582acdec80000b6",
188
+ "username" => "davidtester",
189
+ "fullName" => "David Tester"
190
+ }, {
191
+ "id" => "4ee7e2e1e582acdec8000112",
192
+ "username" => "edtester",
193
+ "fullName" => "Ed Tester"
194
+ }]
195
+ }
196
+ end
197
+
198
+ def organization_payload
199
+ JSON.generate(organization_details)
200
+ end
170
201
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-trello
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.4.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2012-01-07 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: yajl-ruby
16
- requirement: &70172866550100 !ruby/object:Gem::Requirement
16
+ requirement: &70158442213940 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 1.1.0
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70172866550100
24
+ version_requirements: *70158442213940
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: oauth
27
- requirement: &70172866549140 !ruby/object:Gem::Requirement
27
+ requirement: &70158442213480 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 0.4.5
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70172866549140
35
+ version_requirements: *70158442213480
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: addressable
38
- requirement: &70172866548200 !ruby/object:Gem::Requirement
38
+ requirement: &70158442213020 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 2.2.6
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70172866548200
46
+ version_requirements: *70158442213020
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: rest-client
49
- requirement: &70172866546920 !ruby/object:Gem::Requirement
49
+ requirement: &70158442212560 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
@@ -54,10 +54,21 @@ dependencies:
54
54
  version: 1.6.7
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *70172866546920
57
+ version_requirements: *70158442212560
58
+ - !ruby/object:Gem::Dependency
59
+ name: activemodel
60
+ requirement: &70158442212180 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :runtime
67
+ prerelease: false
68
+ version_requirements: *70158442212180
58
69
  - !ruby/object:Gem::Dependency
59
70
  name: bundler
60
- requirement: &70172866545720 !ruby/object:Gem::Requirement
71
+ requirement: &70158442211640 !ruby/object:Gem::Requirement
61
72
  none: false
62
73
  requirements:
63
74
  - - ~>
@@ -65,7 +76,7 @@ dependencies:
65
76
  version: 1.0.0
66
77
  type: :development
67
78
  prerelease: false
68
- version_requirements: *70172866545720
79
+ version_requirements: *70158442211640
69
80
  description: A wrapper around the trello.com API.
70
81
  email: jeremy@tregunna.ca
71
82
  executables: []
@@ -80,6 +91,7 @@ files:
80
91
  - lib/trello/card.rb
81
92
  - lib/trello/checklist.rb
82
93
  - lib/trello/client.rb
94
+ - lib/trello/has_actions.rb
83
95
  - lib/trello/item.rb
84
96
  - lib/trello/item_state.rb
85
97
  - lib/trello/list.rb