ruby-trello 0.3.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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