Class: Trello::Card

Inherits:
BasicData show all
Includes:
HasActions
Defined in:
lib/trello/card.rb

Overview

A Card is a container that can house checklists and comments; it resides inside a List.

Constant Summary collapse

SYMBOL_TO_STRING =
{
  id: 'id',
  short_id: 'idShort',
  name: 'name',
  desc: 'desc',
  due: 'due',
  closed: 'closed',
  url: 'url',
  short_url: 'shortUrl',
  board_id: 'idBoard',
  member_ids: 'idMembers',
  cover_image_id: 'idAttachmentCover',
  list_id: 'idList',
  pos: 'pos',
  last_activity_date: 'dateLastActivity',
  card_labels: 'labels',
  badges: 'badges',
  card_members: 'members'
}

Instance Attribute Summary collapse

Attributes inherited from BasicData

#client

Class Method Summary collapse

Instance Method Summary collapse

Methods included from HasActions

#actions

Methods inherited from BasicData

#==, client, #initialize, many, one, parse, parse_many, path_name, #refresh!, register_attributes, save

Constructor Details

This class inherits a constructor from Trello::BasicData

Instance Attribute Details

#badgesHash (readonly)

Returns:



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
# File 'lib/trello/card.rb', line 38

class Card < BasicData
  register_attributes :id, :short_id, :name, :desc, :due, :closed, :url, :short_url,
    :board_id, :member_ids, :list_id, :pos, :last_activity_date, :card_labels,
    :cover_image_id, :badges, :card_members,
    readonly: [ :id, :short_id, :url, :short_url, :last_activity_date, :badges, :card_members ]
  validates_presence_of :id, :name, :list_id
  validates_length_of   :name,        in: 1..16384
  validates_length_of   :desc, in: 0..16384

  include HasActions

  SYMBOL_TO_STRING = {
    id: 'id',
    short_id: 'idShort',
    name: 'name',
    desc: 'desc',
    due: 'due',
    closed: 'closed',
    url: 'url',
    short_url: 'shortUrl',
    board_id: 'idBoard',
    member_ids: 'idMembers',
    cover_image_id: 'idAttachmentCover',
    list_id: 'idList',
    pos: 'pos',
    last_activity_date: 'dateLastActivity',
    card_labels: 'labels',
    badges: 'badges',
    card_members: 'members'
  }

  class << self
    # Find a specific card by its id.
    #
    # @raise [Trello::Error] if the card could not be found.
    #
    # @return [Trello::Card]
    def find(id, params = {})
      client.find(:card, id, params)
    end

    # Create a new card and save it on Trello.
    #
    # @param [Hash] options # @option options [String] :name The name of the new card.
    # @option options [String] :list_id ID of the list that the card should
    #     be added to.
    # @option options [String] :desc A string with a
    #     length from 0 to 16384.
    # @option options [String] :member_ids A comma-separated list of
    #     objectIds (24-character hex strings).
    # @option options [String] :card_labels A comma-separated list of
    #     objectIds (24-character hex strings).
    # @option options [Date] :due A date, or `nil`.
    # @option options [String] :pos A position. `"top"`, `"bottom"`, or a
    #     positive number. Defaults to `"bottom"`.
    #
    # @raise [Trello::Error] if the card could not be created.
    #
    # @return [Trello::Card]
    def create(options)
      client.create(:card,
        'name' => options[:name],
        'idList' => options[:list_id],
        'desc'   => options[:desc],
        'idMembers' => options[:member_ids],
        'labels' => options[:card_labels],
        'due' => options[:due],
        'pos' => options[:pos]
      )
    end
  end

  # Update the fields of a card.
  #
  # Supply a hash of string keyed data retrieved from the Trello API representing
  # a card.
  #
  # Note that this this method does not save anything new to the Trello API,
  # it just assigns the input attributes to your local object. If you use
  # this method to assign attributes, call `save` or `update!` afterwards if
  # you want to persist your changes to Trello.
  #
  # @param [Hash] fields
  # @option fields [String] :id
  # @option fields [String] :short_id
  # @option fields [String] :name The new name of the card.
  # @option fields [String] :desc A string with a length from 0 to
  #     16384.
  # @option fields [Date] :due A date, or `nil`.
  # @option fields [Boolean] :closed
  # @option fields [String] :url
  # @option fields [String] :short_url
  # @option fields [String] :board_id
  # @option fields [String] :member_ids A comma-separated list of objectIds
  #     (24-character hex strings).
  # @option fields [String] :pos A position. `"top"`, `"bottom"`, or a
  #     positive number. Defaults to `"bottom"`.
  # @option fields [String] :card_labels A comma-separated list of
  #     objectIds (24-character hex strings).
  # @option fields [Object] :cover_image_id
  # @option fields [Object] :badges
  # @option fields [Object] :card_members
  #
  # @return [Trello::Card] self
  def update_fields(fields)
    attributes[:id]                 = fields[SYMBOL_TO_STRING[:id]]
    attributes[:short_id]           = fields[SYMBOL_TO_STRING[:short_id]]
    attributes[:name]               = fields[SYMBOL_TO_STRING[:name]]
    attributes[:desc]               = fields[SYMBOL_TO_STRING[:desc]]
    attributes[:due]                = Time.iso8601(fields[SYMBOL_TO_STRING[:due]]) rescue nil
    attributes[:closed]             = fields[SYMBOL_TO_STRING[:closed]]
    attributes[:url]                = fields[SYMBOL_TO_STRING[:url]]
    attributes[:short_url]          = fields[SYMBOL_TO_STRING[:short_url]]
    attributes[:board_id]           = fields[SYMBOL_TO_STRING[:board_id]]
    attributes[:member_ids]         = fields[SYMBOL_TO_STRING[:member_ids]]
    attributes[:list_id]            = fields[SYMBOL_TO_STRING[:list_id]]
    attributes[:pos]                = fields[SYMBOL_TO_STRING[:pos]]
    attributes[:card_labels]        = fields[SYMBOL_TO_STRING[:card_labels]]
    attributes[:last_activity_date] = Time.iso8601(fields[SYMBOL_TO_STRING[:last_activity_date]]) rescue nil
    attributes[:cover_image_id]     = fields[SYMBOL_TO_STRING[:cover_image_id]]
    attributes[:badges]             = fields[SYMBOL_TO_STRING[:badges]]
    attributes[:card_members]       = fields[SYMBOL_TO_STRING[:card_members]]
    self
  end

  # Returns a reference to the board this card is part of.
  one :board, path: :boards, using: :board_id
  # Returns a reference to the cover image attachment
  one :cover_image, path: :attachments, using: :cover_image_id

  # Returns a list of checklists associated with the card.
  #
  # The options hash may have a filter key which can have its value set as any
  # of the following values:
  #    :filter => [ :none, :all ] # default :all
  many :checklists, filter: :all

  def check_item_states
    states = client.get("/cards/#{self.id}/checkItemStates").json_into(CheckItemState)
    MultiAssociation.new(self, states).proxy
  end

  many :labels
  
  # Returns a reference to the list this card is currently in.
  one :list, path: :lists, using: :list_id

  # Returns a list of members who are assigned to this card.
  #
  # @return [Array<Trello::Member>]
  def members
    members = member_ids.map do |member_id|
      client.get("/members/#{member_id}").json_into(Member)
    end
    MultiAssociation.new(self, members).proxy
  end

  # Saves a record.
  #
  # @raise [Trello::Error] if the card could not be saved
  #
  # @return [String] The JSON representation of the saved card returned by
  #     the Trello API.
  def save
    # If we have an id, just update our fields.
    return update! if id

    client.post("/cards", {
      name:   name,
      desc:   desc,
      idList: list_id,
      idMembers: member_ids,
      labels: card_labels,
      pos: pos,
      due: due
    }).json_into(self)
  end

  # Update an existing record.
  #
  # Warning: this updates all fields using values already in memory. If
  # an external resource has updated these fields, you should refresh!
  # this object before making your changes, and before updating the record.
  #
  # @raise [Trello::Error] if the card could not be updated.
  #
  # @return [String] The JSON representation of the updated card returned by
  #     the Trello API.
  def update!
    @previously_changed = changes
    # extract only new values to build payload
    payload = Hash[changes.map { |key, values| [SYMBOL_TO_STRING[key.to_sym].to_sym, values[1]] }]
    @changed_attributes.clear

    client.put("/cards/#{id}", payload)
  end


  # Delete this card
  #
  # @return [String] the JSON response from the Trello API
  def delete
    client.delete("/cards/#{id}")
  end

  # Check if the card is not active anymore.
  def closed?
    closed
  end

  # Close the card.
  #
  # This only marks your local copy card as closed. Use `close!` if you
  # want to close the card and persist the change to the Trello API.
  #
  # @return [Boolean] always returns true
  #
  # @return [String] The JSON representation of the closed card returned by
  #     the Trello API.
  def close
    self.closed = true
  end

  def close!
    close
    save
  end

  # Is the record valid?
  def valid?
    name && list_id
  end

  # Add a comment with the supplied text.
  def add_comment(text)
    client.post("/cards/#{id}/actions/comments", text: text)
  end

  # Add a checklist to this card
  def add_checklist(checklist)
    client.post("/cards/#{id}/checklists", {
      value: checklist.id
    })
  end

  # create a new checklist and add it to this card
  def create_new_checklist(name)
    client.post("/cards/#{id}/checklists", { name: name })
  end

  # Move this card to the given list
  def move_to_list(list)
    list_number = list.is_a?(String) ? list : list.id
    unless list_id == list_number
      client.put("/cards/#{id}/idList", {
        value: list_number
      })
    end
  end

  # Move this card to the given board (and optional list on this board)
  def move_to_board(new_board, new_list = nil)
    unless board_id == new_board.id
      payload = { value: new_board.id }
      payload[:idList] = new_list.id if new_list
      client.put("/cards/#{id}/idBoard", payload)
    end
  end

  # Add a member to this card
  def add_member(member)
    client.post("/cards/#{id}/members", {
      value: member.id
    })
  end

  # Remove a member from this card
  def remove_member(member)
    client.delete("/cards/#{id}/members/#{member.id}")
  end
  
  # Add a label
  def add_label(label)
    unless label.valid?
      errors.add(:label, "is not valid.")
      return Trello.logger.warn "Label is not valid." unless label.valid?
    end
    client.post("/cards/#{id}/idLabels", {value: label.id})
  end

  # Remove a label
  def remove_label(label)
      unless label.valid?
        errors.add(:label, "is not valid.")
        return Trello.logger.warn "Label is not valid." unless label.valid?
      end
      client.delete("/cards/#{id}/idLabels/#{label.id}")
  end

  # Add an attachment to this card
  def add_attachment(attachment, name='')
    if attachment.is_a? File
      client.post("/cards/#{id}/attachments", {
          file: attachment,
          name: name
        })
    else
      client.post("/cards/#{id}/attachments", {
          url: attachment,
          name: name
        })
    end
  end

  # Retrieve a list of attachments
  def attachments
    attachments = client.get("/cards/#{id}/attachments").json_into(Attachment)
    MultiAssociation.new(self, attachments).proxy
  end

  # Remove an attachment from this card
  def remove_attachment(attachment)
    client.delete("/cards/#{id}/attachments/#{attachment.id}")
  end

  # :nodoc:
  def request_prefix
    "/cards/#{id}"
  end
end

#board_idString

Returns A 24-character hex string.

Returns:

  • (String)

    A 24-character hex string



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
# File 'lib/trello/card.rb', line 38

class Card < BasicData
  register_attributes :id, :short_id, :name, :desc, :due, :closed, :url, :short_url,
    :board_id, :member_ids, :list_id, :pos, :last_activity_date, :card_labels,
    :cover_image_id, :badges, :card_members,
    readonly: [ :id, :short_id, :url, :short_url, :last_activity_date, :badges, :card_members ]
  validates_presence_of :id, :name, :list_id
  validates_length_of   :name,        in: 1..16384
  validates_length_of   :desc, in: 0..16384

  include HasActions

  SYMBOL_TO_STRING = {
    id: 'id',
    short_id: 'idShort',
    name: 'name',
    desc: 'desc',
    due: 'due',
    closed: 'closed',
    url: 'url',
    short_url: 'shortUrl',
    board_id: 'idBoard',
    member_ids: 'idMembers',
    cover_image_id: 'idAttachmentCover',
    list_id: 'idList',
    pos: 'pos',
    last_activity_date: 'dateLastActivity',
    card_labels: 'labels',
    badges: 'badges',
    card_members: 'members'
  }

  class << self
    # Find a specific card by its id.
    #
    # @raise [Trello::Error] if the card could not be found.
    #
    # @return [Trello::Card]
    def find(id, params = {})
      client.find(:card, id, params)
    end

    # Create a new card and save it on Trello.
    #
    # @param [Hash] options # @option options [String] :name The name of the new card.
    # @option options [String] :list_id ID of the list that the card should
    #     be added to.
    # @option options [String] :desc A string with a
    #     length from 0 to 16384.
    # @option options [String] :member_ids A comma-separated list of
    #     objectIds (24-character hex strings).
    # @option options [String] :card_labels A comma-separated list of
    #     objectIds (24-character hex strings).
    # @option options [Date] :due A date, or `nil`.
    # @option options [String] :pos A position. `"top"`, `"bottom"`, or a
    #     positive number. Defaults to `"bottom"`.
    #
    # @raise [Trello::Error] if the card could not be created.
    #
    # @return [Trello::Card]
    def create(options)
      client.create(:card,
        'name' => options[:name],
        'idList' => options[:list_id],
        'desc'   => options[:desc],
        'idMembers' => options[:member_ids],
        'labels' => options[:card_labels],
        'due' => options[:due],
        'pos' => options[:pos]
      )
    end
  end

  # Update the fields of a card.
  #
  # Supply a hash of string keyed data retrieved from the Trello API representing
  # a card.
  #
  # Note that this this method does not save anything new to the Trello API,
  # it just assigns the input attributes to your local object. If you use
  # this method to assign attributes, call `save` or `update!` afterwards if
  # you want to persist your changes to Trello.
  #
  # @param [Hash] fields
  # @option fields [String] :id
  # @option fields [String] :short_id
  # @option fields [String] :name The new name of the card.
  # @option fields [String] :desc A string with a length from 0 to
  #     16384.
  # @option fields [Date] :due A date, or `nil`.
  # @option fields [Boolean] :closed
  # @option fields [String] :url
  # @option fields [String] :short_url
  # @option fields [String] :board_id
  # @option fields [String] :member_ids A comma-separated list of objectIds
  #     (24-character hex strings).
  # @option fields [String] :pos A position. `"top"`, `"bottom"`, or a
  #     positive number. Defaults to `"bottom"`.
  # @option fields [String] :card_labels A comma-separated list of
  #     objectIds (24-character hex strings).
  # @option fields [Object] :cover_image_id
  # @option fields [Object] :badges
  # @option fields [Object] :card_members
  #
  # @return [Trello::Card] self
  def update_fields(fields)
    attributes[:id]                 = fields[SYMBOL_TO_STRING[:id]]
    attributes[:short_id]           = fields[SYMBOL_TO_STRING[:short_id]]
    attributes[:name]               = fields[SYMBOL_TO_STRING[:name]]
    attributes[:desc]               = fields[SYMBOL_TO_STRING[:desc]]
    attributes[:due]                = Time.iso8601(fields[SYMBOL_TO_STRING[:due]]) rescue nil
    attributes[:closed]             = fields[SYMBOL_TO_STRING[:closed]]
    attributes[:url]                = fields[SYMBOL_TO_STRING[:url]]
    attributes[:short_url]          = fields[SYMBOL_TO_STRING[:short_url]]
    attributes[:board_id]           = fields[SYMBOL_TO_STRING[:board_id]]
    attributes[:member_ids]         = fields[SYMBOL_TO_STRING[:member_ids]]
    attributes[:list_id]            = fields[SYMBOL_TO_STRING[:list_id]]
    attributes[:pos]                = fields[SYMBOL_TO_STRING[:pos]]
    attributes[:card_labels]        = fields[SYMBOL_TO_STRING[:card_labels]]
    attributes[:last_activity_date] = Time.iso8601(fields[SYMBOL_TO_STRING[:last_activity_date]]) rescue nil
    attributes[:cover_image_id]     = fields[SYMBOL_TO_STRING[:cover_image_id]]
    attributes[:badges]             = fields[SYMBOL_TO_STRING[:badges]]
    attributes[:card_members]       = fields[SYMBOL_TO_STRING[:card_members]]
    self
  end

  # Returns a reference to the board this card is part of.
  one :board, path: :boards, using: :board_id
  # Returns a reference to the cover image attachment
  one :cover_image, path: :attachments, using: :cover_image_id

  # Returns a list of checklists associated with the card.
  #
  # The options hash may have a filter key which can have its value set as any
  # of the following values:
  #    :filter => [ :none, :all ] # default :all
  many :checklists, filter: :all

  def check_item_states
    states = client.get("/cards/#{self.id}/checkItemStates").json_into(CheckItemState)
    MultiAssociation.new(self, states).proxy
  end

  many :labels
  
  # Returns a reference to the list this card is currently in.
  one :list, path: :lists, using: :list_id

  # Returns a list of members who are assigned to this card.
  #
  # @return [Array<Trello::Member>]
  def members
    members = member_ids.map do |member_id|
      client.get("/members/#{member_id}").json_into(Member)
    end
    MultiAssociation.new(self, members).proxy
  end

  # Saves a record.
  #
  # @raise [Trello::Error] if the card could not be saved
  #
  # @return [String] The JSON representation of the saved card returned by
  #     the Trello API.
  def save
    # If we have an id, just update our fields.
    return update! if id

    client.post("/cards", {
      name:   name,
      desc:   desc,
      idList: list_id,
      idMembers: member_ids,
      labels: card_labels,
      pos: pos,
      due: due
    }).json_into(self)
  end

  # Update an existing record.
  #
  # Warning: this updates all fields using values already in memory. If
  # an external resource has updated these fields, you should refresh!
  # this object before making your changes, and before updating the record.
  #
  # @raise [Trello::Error] if the card could not be updated.
  #
  # @return [String] The JSON representation of the updated card returned by
  #     the Trello API.
  def update!
    @previously_changed = changes
    # extract only new values to build payload
    payload = Hash[changes.map { |key, values| [SYMBOL_TO_STRING[key.to_sym].to_sym, values[1]] }]
    @changed_attributes.clear

    client.put("/cards/#{id}", payload)
  end


  # Delete this card
  #
  # @return [String] the JSON response from the Trello API
  def delete
    client.delete("/cards/#{id}")
  end

  # Check if the card is not active anymore.
  def closed?
    closed
  end

  # Close the card.
  #
  # This only marks your local copy card as closed. Use `close!` if you
  # want to close the card and persist the change to the Trello API.
  #
  # @return [Boolean] always returns true
  #
  # @return [String] The JSON representation of the closed card returned by
  #     the Trello API.
  def close
    self.closed = true
  end

  def close!
    close
    save
  end

  # Is the record valid?
  def valid?
    name && list_id
  end

  # Add a comment with the supplied text.
  def add_comment(text)
    client.post("/cards/#{id}/actions/comments", text: text)
  end

  # Add a checklist to this card
  def add_checklist(checklist)
    client.post("/cards/#{id}/checklists", {
      value: checklist.id
    })
  end

  # create a new checklist and add it to this card
  def create_new_checklist(name)
    client.post("/cards/#{id}/checklists", { name: name })
  end

  # Move this card to the given list
  def move_to_list(list)
    list_number = list.is_a?(String) ? list : list.id
    unless list_id == list_number
      client.put("/cards/#{id}/idList", {
        value: list_number
      })
    end
  end

  # Move this card to the given board (and optional list on this board)
  def move_to_board(new_board, new_list = nil)
    unless board_id == new_board.id
      payload = { value: new_board.id }
      payload[:idList] = new_list.id if new_list
      client.put("/cards/#{id}/idBoard", payload)
    end
  end

  # Add a member to this card
  def add_member(member)
    client.post("/cards/#{id}/members", {
      value: member.id
    })
  end

  # Remove a member from this card
  def remove_member(member)
    client.delete("/cards/#{id}/members/#{member.id}")
  end
  
  # Add a label
  def add_label(label)
    unless label.valid?
      errors.add(:label, "is not valid.")
      return Trello.logger.warn "Label is not valid." unless label.valid?
    end
    client.post("/cards/#{id}/idLabels", {value: label.id})
  end

  # Remove a label
  def remove_label(label)
      unless label.valid?
        errors.add(:label, "is not valid.")
        return Trello.logger.warn "Label is not valid." unless label.valid?
      end
      client.delete("/cards/#{id}/idLabels/#{label.id}")
  end

  # Add an attachment to this card
  def add_attachment(attachment, name='')
    if attachment.is_a? File
      client.post("/cards/#{id}/attachments", {
          file: attachment,
          name: name
        })
    else
      client.post("/cards/#{id}/attachments", {
          url: attachment,
          name: name
        })
    end
  end

  # Retrieve a list of attachments
  def attachments
    attachments = client.get("/cards/#{id}/attachments").json_into(Attachment)
    MultiAssociation.new(self, attachments).proxy
  end

  # Remove an attachment from this card
  def remove_attachment(attachment)
    client.delete("/cards/#{id}/attachments/#{attachment.id}")
  end

  # :nodoc:
  def request_prefix
    "/cards/#{id}"
  end
end

#card_labelsArray<Hash>

Returns:



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
# File 'lib/trello/card.rb', line 38

class Card < BasicData
  register_attributes :id, :short_id, :name, :desc, :due, :closed, :url, :short_url,
    :board_id, :member_ids, :list_id, :pos, :last_activity_date, :card_labels,
    :cover_image_id, :badges, :card_members,
    readonly: [ :id, :short_id, :url, :short_url, :last_activity_date, :badges, :card_members ]
  validates_presence_of :id, :name, :list_id
  validates_length_of   :name,        in: 1..16384
  validates_length_of   :desc, in: 0..16384

  include HasActions

  SYMBOL_TO_STRING = {
    id: 'id',
    short_id: 'idShort',
    name: 'name',
    desc: 'desc',
    due: 'due',
    closed: 'closed',
    url: 'url',
    short_url: 'shortUrl',
    board_id: 'idBoard',
    member_ids: 'idMembers',
    cover_image_id: 'idAttachmentCover',
    list_id: 'idList',
    pos: 'pos',
    last_activity_date: 'dateLastActivity',
    card_labels: 'labels',
    badges: 'badges',
    card_members: 'members'
  }

  class << self
    # Find a specific card by its id.
    #
    # @raise [Trello::Error] if the card could not be found.
    #
    # @return [Trello::Card]
    def find(id, params = {})
      client.find(:card, id, params)
    end

    # Create a new card and save it on Trello.
    #
    # @param [Hash] options # @option options [String] :name The name of the new card.
    # @option options [String] :list_id ID of the list that the card should
    #     be added to.
    # @option options [String] :desc A string with a
    #     length from 0 to 16384.
    # @option options [String] :member_ids A comma-separated list of
    #     objectIds (24-character hex strings).
    # @option options [String] :card_labels A comma-separated list of
    #     objectIds (24-character hex strings).
    # @option options [Date] :due A date, or `nil`.
    # @option options [String] :pos A position. `"top"`, `"bottom"`, or a
    #     positive number. Defaults to `"bottom"`.
    #
    # @raise [Trello::Error] if the card could not be created.
    #
    # @return [Trello::Card]
    def create(options)
      client.create(:card,
        'name' => options[:name],
        'idList' => options[:list_id],
        'desc'   => options[:desc],
        'idMembers' => options[:member_ids],
        'labels' => options[:card_labels],
        'due' => options[:due],
        'pos' => options[:pos]
      )
    end
  end

  # Update the fields of a card.
  #
  # Supply a hash of string keyed data retrieved from the Trello API representing
  # a card.
  #
  # Note that this this method does not save anything new to the Trello API,
  # it just assigns the input attributes to your local object. If you use
  # this method to assign attributes, call `save` or `update!` afterwards if
  # you want to persist your changes to Trello.
  #
  # @param [Hash] fields
  # @option fields [String] :id
  # @option fields [String] :short_id
  # @option fields [String] :name The new name of the card.
  # @option fields [String] :desc A string with a length from 0 to
  #     16384.
  # @option fields [Date] :due A date, or `nil`.
  # @option fields [Boolean] :closed
  # @option fields [String] :url
  # @option fields [String] :short_url
  # @option fields [String] :board_id
  # @option fields [String] :member_ids A comma-separated list of objectIds
  #     (24-character hex strings).
  # @option fields [String] :pos A position. `"top"`, `"bottom"`, or a
  #     positive number. Defaults to `"bottom"`.
  # @option fields [String] :card_labels A comma-separated list of
  #     objectIds (24-character hex strings).
  # @option fields [Object] :cover_image_id
  # @option fields [Object] :badges
  # @option fields [Object] :card_members
  #
  # @return [Trello::Card] self
  def update_fields(fields)
    attributes[:id]                 = fields[SYMBOL_TO_STRING[:id]]
    attributes[:short_id]           = fields[SYMBOL_TO_STRING[:short_id]]
    attributes[:name]               = fields[SYMBOL_TO_STRING[:name]]
    attributes[:desc]               = fields[SYMBOL_TO_STRING[:desc]]
    attributes[:due]                = Time.iso8601(fields[SYMBOL_TO_STRING[:due]]) rescue nil
    attributes[:closed]             = fields[SYMBOL_TO_STRING[:closed]]
    attributes[:url]                = fields[SYMBOL_TO_STRING[:url]]
    attributes[:short_url]          = fields[SYMBOL_TO_STRING[:short_url]]
    attributes[:board_id]           = fields[SYMBOL_TO_STRING[:board_id]]
    attributes[:member_ids]         = fields[SYMBOL_TO_STRING[:member_ids]]
    attributes[:list_id]            = fields[SYMBOL_TO_STRING[:list_id]]
    attributes[:pos]                = fields[SYMBOL_TO_STRING[:pos]]
    attributes[:card_labels]        = fields[SYMBOL_TO_STRING[:card_labels]]
    attributes[:last_activity_date] = Time.iso8601(fields[SYMBOL_TO_STRING[:last_activity_date]]) rescue nil
    attributes[:cover_image_id]     = fields[SYMBOL_TO_STRING[:cover_image_id]]
    attributes[:badges]             = fields[SYMBOL_TO_STRING[:badges]]
    attributes[:card_members]       = fields[SYMBOL_TO_STRING[:card_members]]
    self
  end

  # Returns a reference to the board this card is part of.
  one :board, path: :boards, using: :board_id
  # Returns a reference to the cover image attachment
  one :cover_image, path: :attachments, using: :cover_image_id

  # Returns a list of checklists associated with the card.
  #
  # The options hash may have a filter key which can have its value set as any
  # of the following values:
  #    :filter => [ :none, :all ] # default :all
  many :checklists, filter: :all

  def check_item_states
    states = client.get("/cards/#{self.id}/checkItemStates").json_into(CheckItemState)
    MultiAssociation.new(self, states).proxy
  end

  many :labels
  
  # Returns a reference to the list this card is currently in.
  one :list, path: :lists, using: :list_id

  # Returns a list of members who are assigned to this card.
  #
  # @return [Array<Trello::Member>]
  def members
    members = member_ids.map do |member_id|
      client.get("/members/#{member_id}").json_into(Member)
    end
    MultiAssociation.new(self, members).proxy
  end

  # Saves a record.
  #
  # @raise [Trello::Error] if the card could not be saved
  #
  # @return [String] The JSON representation of the saved card returned by
  #     the Trello API.
  def save
    # If we have an id, just update our fields.
    return update! if id

    client.post("/cards", {
      name:   name,
      desc:   desc,
      idList: list_id,
      idMembers: member_ids,
      labels: card_labels,
      pos: pos,
      due: due
    }).json_into(self)
  end

  # Update an existing record.
  #
  # Warning: this updates all fields using values already in memory. If
  # an external resource has updated these fields, you should refresh!
  # this object before making your changes, and before updating the record.
  #
  # @raise [Trello::Error] if the card could not be updated.
  #
  # @return [String] The JSON representation of the updated card returned by
  #     the Trello API.
  def update!
    @previously_changed = changes
    # extract only new values to build payload
    payload = Hash[changes.map { |key, values| [SYMBOL_TO_STRING[key.to_sym].to_sym, values[1]] }]
    @changed_attributes.clear

    client.put("/cards/#{id}", payload)
  end


  # Delete this card
  #
  # @return [String] the JSON response from the Trello API
  def delete
    client.delete("/cards/#{id}")
  end

  # Check if the card is not active anymore.
  def closed?
    closed
  end

  # Close the card.
  #
  # This only marks your local copy card as closed. Use `close!` if you
  # want to close the card and persist the change to the Trello API.
  #
  # @return [Boolean] always returns true
  #
  # @return [String] The JSON representation of the closed card returned by
  #     the Trello API.
  def close
    self.closed = true
  end

  def close!
    close
    save
  end

  # Is the record valid?
  def valid?
    name && list_id
  end

  # Add a comment with the supplied text.
  def add_comment(text)
    client.post("/cards/#{id}/actions/comments", text: text)
  end

  # Add a checklist to this card
  def add_checklist(checklist)
    client.post("/cards/#{id}/checklists", {
      value: checklist.id
    })
  end

  # create a new checklist and add it to this card
  def create_new_checklist(name)
    client.post("/cards/#{id}/checklists", { name: name })
  end

  # Move this card to the given list
  def move_to_list(list)
    list_number = list.is_a?(String) ? list : list.id
    unless list_id == list_number
      client.put("/cards/#{id}/idList", {
        value: list_number
      })
    end
  end

  # Move this card to the given board (and optional list on this board)
  def move_to_board(new_board, new_list = nil)
    unless board_id == new_board.id
      payload = { value: new_board.id }
      payload[:idList] = new_list.id if new_list
      client.put("/cards/#{id}/idBoard", payload)
    end
  end

  # Add a member to this card
  def add_member(member)
    client.post("/cards/#{id}/members", {
      value: member.id
    })
  end

  # Remove a member from this card
  def remove_member(member)
    client.delete("/cards/#{id}/members/#{member.id}")
  end
  
  # Add a label
  def add_label(label)
    unless label.valid?
      errors.add(:label, "is not valid.")
      return Trello.logger.warn "Label is not valid." unless label.valid?
    end
    client.post("/cards/#{id}/idLabels", {value: label.id})
  end

  # Remove a label
  def remove_label(label)
      unless label.valid?
        errors.add(:label, "is not valid.")
        return Trello.logger.warn "Label is not valid." unless label.valid?
      end
      client.delete("/cards/#{id}/idLabels/#{label.id}")
  end

  # Add an attachment to this card
  def add_attachment(attachment, name='')
    if attachment.is_a? File
      client.post("/cards/#{id}/attachments", {
          file: attachment,
          name: name
        })
    else
      client.post("/cards/#{id}/attachments", {
          url: attachment,
          name: name
        })
    end
  end

  # Retrieve a list of attachments
  def attachments
    attachments = client.get("/cards/#{id}/attachments").json_into(Attachment)
    MultiAssociation.new(self, attachments).proxy
  end

  # Remove an attachment from this card
  def remove_attachment(attachment)
    client.delete("/cards/#{id}/attachments/#{attachment.id}")
  end

  # :nodoc:
  def request_prefix
    "/cards/#{id}"
  end
end

#card_membersObject (readonly)

Returns:

  • (Object)


38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
# File 'lib/trello/card.rb', line 38

class Card < BasicData
  register_attributes :id, :short_id, :name, :desc, :due, :closed, :url, :short_url,
    :board_id, :member_ids, :list_id, :pos, :last_activity_date, :card_labels,
    :cover_image_id, :badges, :card_members,
    readonly: [ :id, :short_id, :url, :short_url, :last_activity_date, :badges, :card_members ]
  validates_presence_of :id, :name, :list_id
  validates_length_of   :name,        in: 1..16384
  validates_length_of   :desc, in: 0..16384

  include HasActions

  SYMBOL_TO_STRING = {
    id: 'id',
    short_id: 'idShort',
    name: 'name',
    desc: 'desc',
    due: 'due',
    closed: 'closed',
    url: 'url',
    short_url: 'shortUrl',
    board_id: 'idBoard',
    member_ids: 'idMembers',
    cover_image_id: 'idAttachmentCover',
    list_id: 'idList',
    pos: 'pos',
    last_activity_date: 'dateLastActivity',
    card_labels: 'labels',
    badges: 'badges',
    card_members: 'members'
  }

  class << self
    # Find a specific card by its id.
    #
    # @raise [Trello::Error] if the card could not be found.
    #
    # @return [Trello::Card]
    def find(id, params = {})
      client.find(:card, id, params)
    end

    # Create a new card and save it on Trello.
    #
    # @param [Hash] options # @option options [String] :name The name of the new card.
    # @option options [String] :list_id ID of the list that the card should
    #     be added to.
    # @option options [String] :desc A string with a
    #     length from 0 to 16384.
    # @option options [String] :member_ids A comma-separated list of
    #     objectIds (24-character hex strings).
    # @option options [String] :card_labels A comma-separated list of
    #     objectIds (24-character hex strings).
    # @option options [Date] :due A date, or `nil`.
    # @option options [String] :pos A position. `"top"`, `"bottom"`, or a
    #     positive number. Defaults to `"bottom"`.
    #
    # @raise [Trello::Error] if the card could not be created.
    #
    # @return [Trello::Card]
    def create(options)
      client.create(:card,
        'name' => options[:name],
        'idList' => options[:list_id],
        'desc'   => options[:desc],
        'idMembers' => options[:member_ids],
        'labels' => options[:card_labels],
        'due' => options[:due],
        'pos' => options[:pos]
      )
    end
  end

  # Update the fields of a card.
  #
  # Supply a hash of string keyed data retrieved from the Trello API representing
  # a card.
  #
  # Note that this this method does not save anything new to the Trello API,
  # it just assigns the input attributes to your local object. If you use
  # this method to assign attributes, call `save` or `update!` afterwards if
  # you want to persist your changes to Trello.
  #
  # @param [Hash] fields
  # @option fields [String] :id
  # @option fields [String] :short_id
  # @option fields [String] :name The new name of the card.
  # @option fields [String] :desc A string with a length from 0 to
  #     16384.
  # @option fields [Date] :due A date, or `nil`.
  # @option fields [Boolean] :closed
  # @option fields [String] :url
  # @option fields [String] :short_url
  # @option fields [String] :board_id
  # @option fields [String] :member_ids A comma-separated list of objectIds
  #     (24-character hex strings).
  # @option fields [String] :pos A position. `"top"`, `"bottom"`, or a
  #     positive number. Defaults to `"bottom"`.
  # @option fields [String] :card_labels A comma-separated list of
  #     objectIds (24-character hex strings).
  # @option fields [Object] :cover_image_id
  # @option fields [Object] :badges
  # @option fields [Object] :card_members
  #
  # @return [Trello::Card] self
  def update_fields(fields)
    attributes[:id]                 = fields[SYMBOL_TO_STRING[:id]]
    attributes[:short_id]           = fields[SYMBOL_TO_STRING[:short_id]]
    attributes[:name]               = fields[SYMBOL_TO_STRING[:name]]
    attributes[:desc]               = fields[SYMBOL_TO_STRING[:desc]]
    attributes[:due]                = Time.iso8601(fields[SYMBOL_TO_STRING[:due]]) rescue nil
    attributes[:closed]             = fields[SYMBOL_TO_STRING[:closed]]
    attributes[:url]                = fields[SYMBOL_TO_STRING[:url]]
    attributes[:short_url]          = fields[SYMBOL_TO_STRING[:short_url]]
    attributes[:board_id]           = fields[SYMBOL_TO_STRING[:board_id]]
    attributes[:member_ids]         = fields[SYMBOL_TO_STRING[:member_ids]]
    attributes[:list_id]            = fields[SYMBOL_TO_STRING[:list_id]]
    attributes[:pos]                = fields[SYMBOL_TO_STRING[:pos]]
    attributes[:card_labels]        = fields[SYMBOL_TO_STRING[:card_labels]]
    attributes[:last_activity_date] = Time.iso8601(fields[SYMBOL_TO_STRING[:last_activity_date]]) rescue nil
    attributes[:cover_image_id]     = fields[SYMBOL_TO_STRING[:cover_image_id]]
    attributes[:badges]             = fields[SYMBOL_TO_STRING[:badges]]
    attributes[:card_members]       = fields[SYMBOL_TO_STRING[:card_members]]
    self
  end

  # Returns a reference to the board this card is part of.
  one :board, path: :boards, using: :board_id
  # Returns a reference to the cover image attachment
  one :cover_image, path: :attachments, using: :cover_image_id

  # Returns a list of checklists associated with the card.
  #
  # The options hash may have a filter key which can have its value set as any
  # of the following values:
  #    :filter => [ :none, :all ] # default :all
  many :checklists, filter: :all

  def check_item_states
    states = client.get("/cards/#{self.id}/checkItemStates").json_into(CheckItemState)
    MultiAssociation.new(self, states).proxy
  end

  many :labels
  
  # Returns a reference to the list this card is currently in.
  one :list, path: :lists, using: :list_id

  # Returns a list of members who are assigned to this card.
  #
  # @return [Array<Trello::Member>]
  def members
    members = member_ids.map do |member_id|
      client.get("/members/#{member_id}").json_into(Member)
    end
    MultiAssociation.new(self, members).proxy
  end

  # Saves a record.
  #
  # @raise [Trello::Error] if the card could not be saved
  #
  # @return [String] The JSON representation of the saved card returned by
  #     the Trello API.
  def save
    # If we have an id, just update our fields.
    return update! if id

    client.post("/cards", {
      name:   name,
      desc:   desc,
      idList: list_id,
      idMembers: member_ids,
      labels: card_labels,
      pos: pos,
      due: due
    }).json_into(self)
  end

  # Update an existing record.
  #
  # Warning: this updates all fields using values already in memory. If
  # an external resource has updated these fields, you should refresh!
  # this object before making your changes, and before updating the record.
  #
  # @raise [Trello::Error] if the card could not be updated.
  #
  # @return [String] The JSON representation of the updated card returned by
  #     the Trello API.
  def update!
    @previously_changed = changes
    # extract only new values to build payload
    payload = Hash[changes.map { |key, values| [SYMBOL_TO_STRING[key.to_sym].to_sym, values[1]] }]
    @changed_attributes.clear

    client.put("/cards/#{id}", payload)
  end


  # Delete this card
  #
  # @return [String] the JSON response from the Trello API
  def delete
    client.delete("/cards/#{id}")
  end

  # Check if the card is not active anymore.
  def closed?
    closed
  end

  # Close the card.
  #
  # This only marks your local copy card as closed. Use `close!` if you
  # want to close the card and persist the change to the Trello API.
  #
  # @return [Boolean] always returns true
  #
  # @return [String] The JSON representation of the closed card returned by
  #     the Trello API.
  def close
    self.closed = true
  end

  def close!
    close
    save
  end

  # Is the record valid?
  def valid?
    name && list_id
  end

  # Add a comment with the supplied text.
  def add_comment(text)
    client.post("/cards/#{id}/actions/comments", text: text)
  end

  # Add a checklist to this card
  def add_checklist(checklist)
    client.post("/cards/#{id}/checklists", {
      value: checklist.id
    })
  end

  # create a new checklist and add it to this card
  def create_new_checklist(name)
    client.post("/cards/#{id}/checklists", { name: name })
  end

  # Move this card to the given list
  def move_to_list(list)
    list_number = list.is_a?(String) ? list : list.id
    unless list_id == list_number
      client.put("/cards/#{id}/idList", {
        value: list_number
      })
    end
  end

  # Move this card to the given board (and optional list on this board)
  def move_to_board(new_board, new_list = nil)
    unless board_id == new_board.id
      payload = { value: new_board.id }
      payload[:idList] = new_list.id if new_list
      client.put("/cards/#{id}/idBoard", payload)
    end
  end

  # Add a member to this card
  def add_member(member)
    client.post("/cards/#{id}/members", {
      value: member.id
    })
  end

  # Remove a member from this card
  def remove_member(member)
    client.delete("/cards/#{id}/members/#{member.id}")
  end
  
  # Add a label
  def add_label(label)
    unless label.valid?
      errors.add(:label, "is not valid.")
      return Trello.logger.warn "Label is not valid." unless label.valid?
    end
    client.post("/cards/#{id}/idLabels", {value: label.id})
  end

  # Remove a label
  def remove_label(label)
      unless label.valid?
        errors.add(:label, "is not valid.")
        return Trello.logger.warn "Label is not valid." unless label.valid?
      end
      client.delete("/cards/#{id}/idLabels/#{label.id}")
  end

  # Add an attachment to this card
  def add_attachment(attachment, name='')
    if attachment.is_a? File
      client.post("/cards/#{id}/attachments", {
          file: attachment,
          name: name
        })
    else
      client.post("/cards/#{id}/attachments", {
          url: attachment,
          name: name
        })
    end
  end

  # Retrieve a list of attachments
  def attachments
    attachments = client.get("/cards/#{id}/attachments").json_into(Attachment)
    MultiAssociation.new(self, attachments).proxy
  end

  # Remove an attachment from this card
  def remove_attachment(attachment)
    client.delete("/cards/#{id}/attachments/#{attachment.id}")
  end

  # :nodoc:
  def request_prefix
    "/cards/#{id}"
  end
end

#closedBoolean

Returns:

  • (Boolean)


38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
# File 'lib/trello/card.rb', line 38

class Card < BasicData
  register_attributes :id, :short_id, :name, :desc, :due, :closed, :url, :short_url,
    :board_id, :member_ids, :list_id, :pos, :last_activity_date, :card_labels,
    :cover_image_id, :badges, :card_members,
    readonly: [ :id, :short_id, :url, :short_url, :last_activity_date, :badges, :card_members ]
  validates_presence_of :id, :name, :list_id
  validates_length_of   :name,        in: 1..16384
  validates_length_of   :desc, in: 0..16384

  include HasActions

  SYMBOL_TO_STRING = {
    id: 'id',
    short_id: 'idShort',
    name: 'name',
    desc: 'desc',
    due: 'due',
    closed: 'closed',
    url: 'url',
    short_url: 'shortUrl',
    board_id: 'idBoard',
    member_ids: 'idMembers',
    cover_image_id: 'idAttachmentCover',
    list_id: 'idList',
    pos: 'pos',
    last_activity_date: 'dateLastActivity',
    card_labels: 'labels',
    badges: 'badges',
    card_members: 'members'
  }

  class << self
    # Find a specific card by its id.
    #
    # @raise [Trello::Error] if the card could not be found.
    #
    # @return [Trello::Card]
    def find(id, params = {})
      client.find(:card, id, params)
    end

    # Create a new card and save it on Trello.
    #
    # @param [Hash] options # @option options [String] :name The name of the new card.
    # @option options [String] :list_id ID of the list that the card should
    #     be added to.
    # @option options [String] :desc A string with a
    #     length from 0 to 16384.
    # @option options [String] :member_ids A comma-separated list of
    #     objectIds (24-character hex strings).
    # @option options [String] :card_labels A comma-separated list of
    #     objectIds (24-character hex strings).
    # @option options [Date] :due A date, or `nil`.
    # @option options [String] :pos A position. `"top"`, `"bottom"`, or a
    #     positive number. Defaults to `"bottom"`.
    #
    # @raise [Trello::Error] if the card could not be created.
    #
    # @return [Trello::Card]
    def create(options)
      client.create(:card,
        'name' => options[:name],
        'idList' => options[:list_id],
        'desc'   => options[:desc],
        'idMembers' => options[:member_ids],
        'labels' => options[:card_labels],
        'due' => options[:due],
        'pos' => options[:pos]
      )
    end
  end

  # Update the fields of a card.
  #
  # Supply a hash of string keyed data retrieved from the Trello API representing
  # a card.
  #
  # Note that this this method does not save anything new to the Trello API,
  # it just assigns the input attributes to your local object. If you use
  # this method to assign attributes, call `save` or `update!` afterwards if
  # you want to persist your changes to Trello.
  #
  # @param [Hash] fields
  # @option fields [String] :id
  # @option fields [String] :short_id
  # @option fields [String] :name The new name of the card.
  # @option fields [String] :desc A string with a length from 0 to
  #     16384.
  # @option fields [Date] :due A date, or `nil`.
  # @option fields [Boolean] :closed
  # @option fields [String] :url
  # @option fields [String] :short_url
  # @option fields [String] :board_id
  # @option fields [String] :member_ids A comma-separated list of objectIds
  #     (24-character hex strings).
  # @option fields [String] :pos A position. `"top"`, `"bottom"`, or a
  #     positive number. Defaults to `"bottom"`.
  # @option fields [String] :card_labels A comma-separated list of
  #     objectIds (24-character hex strings).
  # @option fields [Object] :cover_image_id
  # @option fields [Object] :badges
  # @option fields [Object] :card_members
  #
  # @return [Trello::Card] self
  def update_fields(fields)
    attributes[:id]                 = fields[SYMBOL_TO_STRING[:id]]
    attributes[:short_id]           = fields[SYMBOL_TO_STRING[:short_id]]
    attributes[:name]               = fields[SYMBOL_TO_STRING[:name]]
    attributes[:desc]               = fields[SYMBOL_TO_STRING[:desc]]
    attributes[:due]                = Time.iso8601(fields[SYMBOL_TO_STRING[:due]]) rescue nil
    attributes[:closed]             = fields[SYMBOL_TO_STRING[:closed]]
    attributes[:url]                = fields[SYMBOL_TO_STRING[:url]]
    attributes[:short_url]          = fields[SYMBOL_TO_STRING[:short_url]]
    attributes[:board_id]           = fields[SYMBOL_TO_STRING[:board_id]]
    attributes[:member_ids]         = fields[SYMBOL_TO_STRING[:member_ids]]
    attributes[:list_id]            = fields[SYMBOL_TO_STRING[:list_id]]
    attributes[:pos]                = fields[SYMBOL_TO_STRING[:pos]]
    attributes[:card_labels]        = fields[SYMBOL_TO_STRING[:card_labels]]
    attributes[:last_activity_date] = Time.iso8601(fields[SYMBOL_TO_STRING[:last_activity_date]]) rescue nil
    attributes[:cover_image_id]     = fields[SYMBOL_TO_STRING[:cover_image_id]]
    attributes[:badges]             = fields[SYMBOL_TO_STRING[:badges]]
    attributes[:card_members]       = fields[SYMBOL_TO_STRING[:card_members]]
    self
  end

  # Returns a reference to the board this card is part of.
  one :board, path: :boards, using: :board_id
  # Returns a reference to the cover image attachment
  one :cover_image, path: :attachments, using: :cover_image_id

  # Returns a list of checklists associated with the card.
  #
  # The options hash may have a filter key which can have its value set as any
  # of the following values:
  #    :filter => [ :none, :all ] # default :all
  many :checklists, filter: :all

  def check_item_states
    states = client.get("/cards/#{self.id}/checkItemStates").json_into(CheckItemState)
    MultiAssociation.new(self, states).proxy
  end

  many :labels
  
  # Returns a reference to the list this card is currently in.
  one :list, path: :lists, using: :list_id

  # Returns a list of members who are assigned to this card.
  #
  # @return [Array<Trello::Member>]
  def members
    members = member_ids.map do |member_id|
      client.get("/members/#{member_id}").json_into(Member)
    end
    MultiAssociation.new(self, members).proxy
  end

  # Saves a record.
  #
  # @raise [Trello::Error] if the card could not be saved
  #
  # @return [String] The JSON representation of the saved card returned by
  #     the Trello API.
  def save
    # If we have an id, just update our fields.
    return update! if id

    client.post("/cards", {
      name:   name,
      desc:   desc,
      idList: list_id,
      idMembers: member_ids,
      labels: card_labels,
      pos: pos,
      due: due
    }).json_into(self)
  end

  # Update an existing record.
  #
  # Warning: this updates all fields using values already in memory. If
  # an external resource has updated these fields, you should refresh!
  # this object before making your changes, and before updating the record.
  #
  # @raise [Trello::Error] if the card could not be updated.
  #
  # @return [String] The JSON representation of the updated card returned by
  #     the Trello API.
  def update!
    @previously_changed = changes
    # extract only new values to build payload
    payload = Hash[changes.map { |key, values| [SYMBOL_TO_STRING[key.to_sym].to_sym, values[1]] }]
    @changed_attributes.clear

    client.put("/cards/#{id}", payload)
  end


  # Delete this card
  #
  # @return [String] the JSON response from the Trello API
  def delete
    client.delete("/cards/#{id}")
  end

  # Check if the card is not active anymore.
  def closed?
    closed
  end

  # Close the card.
  #
  # This only marks your local copy card as closed. Use `close!` if you
  # want to close the card and persist the change to the Trello API.
  #
  # @return [Boolean] always returns true
  #
  # @return [String] The JSON representation of the closed card returned by
  #     the Trello API.
  def close
    self.closed = true
  end

  def close!
    close
    save
  end

  # Is the record valid?
  def valid?
    name && list_id
  end

  # Add a comment with the supplied text.
  def add_comment(text)
    client.post("/cards/#{id}/actions/comments", text: text)
  end

  # Add a checklist to this card
  def add_checklist(checklist)
    client.post("/cards/#{id}/checklists", {
      value: checklist.id
    })
  end

  # create a new checklist and add it to this card
  def create_new_checklist(name)
    client.post("/cards/#{id}/checklists", { name: name })
  end

  # Move this card to the given list
  def move_to_list(list)
    list_number = list.is_a?(String) ? list : list.id
    unless list_id == list_number
      client.put("/cards/#{id}/idList", {
        value: list_number
      })
    end
  end

  # Move this card to the given board (and optional list on this board)
  def move_to_board(new_board, new_list = nil)
    unless board_id == new_board.id
      payload = { value: new_board.id }
      payload[:idList] = new_list.id if new_list
      client.put("/cards/#{id}/idBoard", payload)
    end
  end

  # Add a member to this card
  def add_member(member)
    client.post("/cards/#{id}/members", {
      value: member.id
    })
  end

  # Remove a member from this card
  def remove_member(member)
    client.delete("/cards/#{id}/members/#{member.id}")
  end
  
  # Add a label
  def add_label(label)
    unless label.valid?
      errors.add(:label, "is not valid.")
      return Trello.logger.warn "Label is not valid." unless label.valid?
    end
    client.post("/cards/#{id}/idLabels", {value: label.id})
  end

  # Remove a label
  def remove_label(label)
      unless label.valid?
        errors.add(:label, "is not valid.")
        return Trello.logger.warn "Label is not valid." unless label.valid?
      end
      client.delete("/cards/#{id}/idLabels/#{label.id}")
  end

  # Add an attachment to this card
  def add_attachment(attachment, name='')
    if attachment.is_a? File
      client.post("/cards/#{id}/attachments", {
          file: attachment,
          name: name
        })
    else
      client.post("/cards/#{id}/attachments", {
          url: attachment,
          name: name
        })
    end
  end

  # Retrieve a list of attachments
  def attachments
    attachments = client.get("/cards/#{id}/attachments").json_into(Attachment)
    MultiAssociation.new(self, attachments).proxy
  end

  # Remove an attachment from this card
  def remove_attachment(attachment)
    client.delete("/cards/#{id}/attachments/#{attachment.id}")
  end

  # :nodoc:
  def request_prefix
    "/cards/#{id}"
  end
end

#cover_image_idString

Returns A 24-character hex string.

Returns:

  • (String)

    A 24-character hex string



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
# File 'lib/trello/card.rb', line 38

class Card < BasicData
  register_attributes :id, :short_id, :name, :desc, :due, :closed, :url, :short_url,
    :board_id, :member_ids, :list_id, :pos, :last_activity_date, :card_labels,
    :cover_image_id, :badges, :card_members,
    readonly: [ :id, :short_id, :url, :short_url, :last_activity_date, :badges, :card_members ]
  validates_presence_of :id, :name, :list_id
  validates_length_of   :name,        in: 1..16384
  validates_length_of   :desc, in: 0..16384

  include HasActions

  SYMBOL_TO_STRING = {
    id: 'id',
    short_id: 'idShort',
    name: 'name',
    desc: 'desc',
    due: 'due',
    closed: 'closed',
    url: 'url',
    short_url: 'shortUrl',
    board_id: 'idBoard',
    member_ids: 'idMembers',
    cover_image_id: 'idAttachmentCover',
    list_id: 'idList',
    pos: 'pos',
    last_activity_date: 'dateLastActivity',
    card_labels: 'labels',
    badges: 'badges',
    card_members: 'members'
  }

  class << self
    # Find a specific card by its id.
    #
    # @raise [Trello::Error] if the card could not be found.
    #
    # @return [Trello::Card]
    def find(id, params = {})
      client.find(:card, id, params)
    end

    # Create a new card and save it on Trello.
    #
    # @param [Hash] options # @option options [String] :name The name of the new card.
    # @option options [String] :list_id ID of the list that the card should
    #     be added to.
    # @option options [String] :desc A string with a
    #     length from 0 to 16384.
    # @option options [String] :member_ids A comma-separated list of
    #     objectIds (24-character hex strings).
    # @option options [String] :card_labels A comma-separated list of
    #     objectIds (24-character hex strings).
    # @option options [Date] :due A date, or `nil`.
    # @option options [String] :pos A position. `"top"`, `"bottom"`, or a
    #     positive number. Defaults to `"bottom"`.
    #
    # @raise [Trello::Error] if the card could not be created.
    #
    # @return [Trello::Card]
    def create(options)
      client.create(:card,
        'name' => options[:name],
        'idList' => options[:list_id],
        'desc'   => options[:desc],
        'idMembers' => options[:member_ids],
        'labels' => options[:card_labels],
        'due' => options[:due],
        'pos' => options[:pos]
      )
    end
  end

  # Update the fields of a card.
  #
  # Supply a hash of string keyed data retrieved from the Trello API representing
  # a card.
  #
  # Note that this this method does not save anything new to the Trello API,
  # it just assigns the input attributes to your local object. If you use
  # this method to assign attributes, call `save` or `update!` afterwards if
  # you want to persist your changes to Trello.
  #
  # @param [Hash] fields
  # @option fields [String] :id
  # @option fields [String] :short_id
  # @option fields [String] :name The new name of the card.
  # @option fields [String] :desc A string with a length from 0 to
  #     16384.
  # @option fields [Date] :due A date, or `nil`.
  # @option fields [Boolean] :closed
  # @option fields [String] :url
  # @option fields [String] :short_url
  # @option fields [String] :board_id
  # @option fields [String] :member_ids A comma-separated list of objectIds
  #     (24-character hex strings).
  # @option fields [String] :pos A position. `"top"`, `"bottom"`, or a
  #     positive number. Defaults to `"bottom"`.
  # @option fields [String] :card_labels A comma-separated list of
  #     objectIds (24-character hex strings).
  # @option fields [Object] :cover_image_id
  # @option fields [Object] :badges
  # @option fields [Object] :card_members
  #
  # @return [Trello::Card] self
  def update_fields(fields)
    attributes[:id]                 = fields[SYMBOL_TO_STRING[:id]]
    attributes[:short_id]           = fields[SYMBOL_TO_STRING[:short_id]]
    attributes[:name]               = fields[SYMBOL_TO_STRING[:name]]
    attributes[:desc]               = fields[SYMBOL_TO_STRING[:desc]]
    attributes[:due]                = Time.iso8601(fields[SYMBOL_TO_STRING[:due]]) rescue nil
    attributes[:closed]             = fields[SYMBOL_TO_STRING[:closed]]
    attributes[:url]                = fields[SYMBOL_TO_STRING[:url]]
    attributes[:short_url]          = fields[SYMBOL_TO_STRING[:short_url]]
    attributes[:board_id]           = fields[SYMBOL_TO_STRING[:board_id]]
    attributes[:member_ids]         = fields[SYMBOL_TO_STRING[:member_ids]]
    attributes[:list_id]            = fields[SYMBOL_TO_STRING[:list_id]]
    attributes[:pos]                = fields[SYMBOL_TO_STRING[:pos]]
    attributes[:card_labels]        = fields[SYMBOL_TO_STRING[:card_labels]]
    attributes[:last_activity_date] = Time.iso8601(fields[SYMBOL_TO_STRING[:last_activity_date]]) rescue nil
    attributes[:cover_image_id]     = fields[SYMBOL_TO_STRING[:cover_image_id]]
    attributes[:badges]             = fields[SYMBOL_TO_STRING[:badges]]
    attributes[:card_members]       = fields[SYMBOL_TO_STRING[:card_members]]
    self
  end

  # Returns a reference to the board this card is part of.
  one :board, path: :boards, using: :board_id
  # Returns a reference to the cover image attachment
  one :cover_image, path: :attachments, using: :cover_image_id

  # Returns a list of checklists associated with the card.
  #
  # The options hash may have a filter key which can have its value set as any
  # of the following values:
  #    :filter => [ :none, :all ] # default :all
  many :checklists, filter: :all

  def check_item_states
    states = client.get("/cards/#{self.id}/checkItemStates").json_into(CheckItemState)
    MultiAssociation.new(self, states).proxy
  end

  many :labels
  
  # Returns a reference to the list this card is currently in.
  one :list, path: :lists, using: :list_id

  # Returns a list of members who are assigned to this card.
  #
  # @return [Array<Trello::Member>]
  def members
    members = member_ids.map do |member_id|
      client.get("/members/#{member_id}").json_into(Member)
    end
    MultiAssociation.new(self, members).proxy
  end

  # Saves a record.
  #
  # @raise [Trello::Error] if the card could not be saved
  #
  # @return [String] The JSON representation of the saved card returned by
  #     the Trello API.
  def save
    # If we have an id, just update our fields.
    return update! if id

    client.post("/cards", {
      name:   name,
      desc:   desc,
      idList: list_id,
      idMembers: member_ids,
      labels: card_labels,
      pos: pos,
      due: due
    }).json_into(self)
  end

  # Update an existing record.
  #
  # Warning: this updates all fields using values already in memory. If
  # an external resource has updated these fields, you should refresh!
  # this object before making your changes, and before updating the record.
  #
  # @raise [Trello::Error] if the card could not be updated.
  #
  # @return [String] The JSON representation of the updated card returned by
  #     the Trello API.
  def update!
    @previously_changed = changes
    # extract only new values to build payload
    payload = Hash[changes.map { |key, values| [SYMBOL_TO_STRING[key.to_sym].to_sym, values[1]] }]
    @changed_attributes.clear

    client.put("/cards/#{id}", payload)
  end


  # Delete this card
  #
  # @return [String] the JSON response from the Trello API
  def delete
    client.delete("/cards/#{id}")
  end

  # Check if the card is not active anymore.
  def closed?
    closed
  end

  # Close the card.
  #
  # This only marks your local copy card as closed. Use `close!` if you
  # want to close the card and persist the change to the Trello API.
  #
  # @return [Boolean] always returns true
  #
  # @return [String] The JSON representation of the closed card returned by
  #     the Trello API.
  def close
    self.closed = true
  end

  def close!
    close
    save
  end

  # Is the record valid?
  def valid?
    name && list_id
  end

  # Add a comment with the supplied text.
  def add_comment(text)
    client.post("/cards/#{id}/actions/comments", text: text)
  end

  # Add a checklist to this card
  def add_checklist(checklist)
    client.post("/cards/#{id}/checklists", {
      value: checklist.id
    })
  end

  # create a new checklist and add it to this card
  def create_new_checklist(name)
    client.post("/cards/#{id}/checklists", { name: name })
  end

  # Move this card to the given list
  def move_to_list(list)
    list_number = list.is_a?(String) ? list : list.id
    unless list_id == list_number
      client.put("/cards/#{id}/idList", {
        value: list_number
      })
    end
  end

  # Move this card to the given board (and optional list on this board)
  def move_to_board(new_board, new_list = nil)
    unless board_id == new_board.id
      payload = { value: new_board.id }
      payload[:idList] = new_list.id if new_list
      client.put("/cards/#{id}/idBoard", payload)
    end
  end

  # Add a member to this card
  def add_member(member)
    client.post("/cards/#{id}/members", {
      value: member.id
    })
  end

  # Remove a member from this card
  def remove_member(member)
    client.delete("/cards/#{id}/members/#{member.id}")
  end
  
  # Add a label
  def add_label(label)
    unless label.valid?
      errors.add(:label, "is not valid.")
      return Trello.logger.warn "Label is not valid." unless label.valid?
    end
    client.post("/cards/#{id}/idLabels", {value: label.id})
  end

  # Remove a label
  def remove_label(label)
      unless label.valid?
        errors.add(:label, "is not valid.")
        return Trello.logger.warn "Label is not valid." unless label.valid?
      end
      client.delete("/cards/#{id}/idLabels/#{label.id}")
  end

  # Add an attachment to this card
  def add_attachment(attachment, name='')
    if attachment.is_a? File
      client.post("/cards/#{id}/attachments", {
          file: attachment,
          name: name
        })
    else
      client.post("/cards/#{id}/attachments", {
          url: attachment,
          name: name
        })
    end
  end

  # Retrieve a list of attachments
  def attachments
    attachments = client.get("/cards/#{id}/attachments").json_into(Attachment)
    MultiAssociation.new(self, attachments).proxy
  end

  # Remove an attachment from this card
  def remove_attachment(attachment)
    client.delete("/cards/#{id}/attachments/#{attachment.id}")
  end

  # :nodoc:
  def request_prefix
    "/cards/#{id}"
  end
end

#descString

Returns:



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
# File 'lib/trello/card.rb', line 38

class Card < BasicData
  register_attributes :id, :short_id, :name, :desc, :due, :closed, :url, :short_url,
    :board_id, :member_ids, :list_id, :pos, :last_activity_date, :card_labels,
    :cover_image_id, :badges, :card_members,
    readonly: [ :id, :short_id, :url, :short_url, :last_activity_date, :badges, :card_members ]
  validates_presence_of :id, :name, :list_id
  validates_length_of   :name,        in: 1..16384
  validates_length_of   :desc, in: 0..16384

  include HasActions

  SYMBOL_TO_STRING = {
    id: 'id',
    short_id: 'idShort',
    name: 'name',
    desc: 'desc',
    due: 'due',
    closed: 'closed',
    url: 'url',
    short_url: 'shortUrl',
    board_id: 'idBoard',
    member_ids: 'idMembers',
    cover_image_id: 'idAttachmentCover',
    list_id: 'idList',
    pos: 'pos',
    last_activity_date: 'dateLastActivity',
    card_labels: 'labels',
    badges: 'badges',
    card_members: 'members'
  }

  class << self
    # Find a specific card by its id.
    #
    # @raise [Trello::Error] if the card could not be found.
    #
    # @return [Trello::Card]
    def find(id, params = {})
      client.find(:card, id, params)
    end

    # Create a new card and save it on Trello.
    #
    # @param [Hash] options # @option options [String] :name The name of the new card.
    # @option options [String] :list_id ID of the list that the card should
    #     be added to.
    # @option options [String] :desc A string with a
    #     length from 0 to 16384.
    # @option options [String] :member_ids A comma-separated list of
    #     objectIds (24-character hex strings).
    # @option options [String] :card_labels A comma-separated list of
    #     objectIds (24-character hex strings).
    # @option options [Date] :due A date, or `nil`.
    # @option options [String] :pos A position. `"top"`, `"bottom"`, or a
    #     positive number. Defaults to `"bottom"`.
    #
    # @raise [Trello::Error] if the card could not be created.
    #
    # @return [Trello::Card]
    def create(options)
      client.create(:card,
        'name' => options[:name],
        'idList' => options[:list_id],
        'desc'   => options[:desc],
        'idMembers' => options[:member_ids],
        'labels' => options[:card_labels],
        'due' => options[:due],
        'pos' => options[:pos]
      )
    end
  end

  # Update the fields of a card.
  #
  # Supply a hash of string keyed data retrieved from the Trello API representing
  # a card.
  #
  # Note that this this method does not save anything new to the Trello API,
  # it just assigns the input attributes to your local object. If you use
  # this method to assign attributes, call `save` or `update!` afterwards if
  # you want to persist your changes to Trello.
  #
  # @param [Hash] fields
  # @option fields [String] :id
  # @option fields [String] :short_id
  # @option fields [String] :name The new name of the card.
  # @option fields [String] :desc A string with a length from 0 to
  #     16384.
  # @option fields [Date] :due A date, or `nil`.
  # @option fields [Boolean] :closed
  # @option fields [String] :url
  # @option fields [String] :short_url
  # @option fields [String] :board_id
  # @option fields [String] :member_ids A comma-separated list of objectIds
  #     (24-character hex strings).
  # @option fields [String] :pos A position. `"top"`, `"bottom"`, or a
  #     positive number. Defaults to `"bottom"`.
  # @option fields [String] :card_labels A comma-separated list of
  #     objectIds (24-character hex strings).
  # @option fields [Object] :cover_image_id
  # @option fields [Object] :badges
  # @option fields [Object] :card_members
  #
  # @return [Trello::Card] self
  def update_fields(fields)
    attributes[:id]                 = fields[SYMBOL_TO_STRING[:id]]
    attributes[:short_id]           = fields[SYMBOL_TO_STRING[:short_id]]
    attributes[:name]               = fields[SYMBOL_TO_STRING[:name]]
    attributes[:desc]               = fields[SYMBOL_TO_STRING[:desc]]
    attributes[:due]                = Time.iso8601(fields[SYMBOL_TO_STRING[:due]]) rescue nil
    attributes[:closed]             = fields[SYMBOL_TO_STRING[:closed]]
    attributes[:url]                = fields[SYMBOL_TO_STRING[:url]]
    attributes[:short_url]          = fields[SYMBOL_TO_STRING[:short_url]]
    attributes[:board_id]           = fields[SYMBOL_TO_STRING[:board_id]]
    attributes[:member_ids]         = fields[SYMBOL_TO_STRING[:member_ids]]
    attributes[:list_id]            = fields[SYMBOL_TO_STRING[:list_id]]
    attributes[:pos]                = fields[SYMBOL_TO_STRING[:pos]]
    attributes[:card_labels]        = fields[SYMBOL_TO_STRING[:card_labels]]
    attributes[:last_activity_date] = Time.iso8601(fields[SYMBOL_TO_STRING[:last_activity_date]]) rescue nil
    attributes[:cover_image_id]     = fields[SYMBOL_TO_STRING[:cover_image_id]]
    attributes[:badges]             = fields[SYMBOL_TO_STRING[:badges]]
    attributes[:card_members]       = fields[SYMBOL_TO_STRING[:card_members]]
    self
  end

  # Returns a reference to the board this card is part of.
  one :board, path: :boards, using: :board_id
  # Returns a reference to the cover image attachment
  one :cover_image, path: :attachments, using: :cover_image_id

  # Returns a list of checklists associated with the card.
  #
  # The options hash may have a filter key which can have its value set as any
  # of the following values:
  #    :filter => [ :none, :all ] # default :all
  many :checklists, filter: :all

  def check_item_states
    states = client.get("/cards/#{self.id}/checkItemStates").json_into(CheckItemState)
    MultiAssociation.new(self, states).proxy
  end

  many :labels
  
  # Returns a reference to the list this card is currently in.
  one :list, path: :lists, using: :list_id

  # Returns a list of members who are assigned to this card.
  #
  # @return [Array<Trello::Member>]
  def members
    members = member_ids.map do |member_id|
      client.get("/members/#{member_id}").json_into(Member)
    end
    MultiAssociation.new(self, members).proxy
  end

  # Saves a record.
  #
  # @raise [Trello::Error] if the card could not be saved
  #
  # @return [String] The JSON representation of the saved card returned by
  #     the Trello API.
  def save
    # If we have an id, just update our fields.
    return update! if id

    client.post("/cards", {
      name:   name,
      desc:   desc,
      idList: list_id,
      idMembers: member_ids,
      labels: card_labels,
      pos: pos,
      due: due
    }).json_into(self)
  end

  # Update an existing record.
  #
  # Warning: this updates all fields using values already in memory. If
  # an external resource has updated these fields, you should refresh!
  # this object before making your changes, and before updating the record.
  #
  # @raise [Trello::Error] if the card could not be updated.
  #
  # @return [String] The JSON representation of the updated card returned by
  #     the Trello API.
  def update!
    @previously_changed = changes
    # extract only new values to build payload
    payload = Hash[changes.map { |key, values| [SYMBOL_TO_STRING[key.to_sym].to_sym, values[1]] }]
    @changed_attributes.clear

    client.put("/cards/#{id}", payload)
  end


  # Delete this card
  #
  # @return [String] the JSON response from the Trello API
  def delete
    client.delete("/cards/#{id}")
  end

  # Check if the card is not active anymore.
  def closed?
    closed
  end

  # Close the card.
  #
  # This only marks your local copy card as closed. Use `close!` if you
  # want to close the card and persist the change to the Trello API.
  #
  # @return [Boolean] always returns true
  #
  # @return [String] The JSON representation of the closed card returned by
  #     the Trello API.
  def close
    self.closed = true
  end

  def close!
    close
    save
  end

  # Is the record valid?
  def valid?
    name && list_id
  end

  # Add a comment with the supplied text.
  def add_comment(text)
    client.post("/cards/#{id}/actions/comments", text: text)
  end

  # Add a checklist to this card
  def add_checklist(checklist)
    client.post("/cards/#{id}/checklists", {
      value: checklist.id
    })
  end

  # create a new checklist and add it to this card
  def create_new_checklist(name)
    client.post("/cards/#{id}/checklists", { name: name })
  end

  # Move this card to the given list
  def move_to_list(list)
    list_number = list.is_a?(String) ? list : list.id
    unless list_id == list_number
      client.put("/cards/#{id}/idList", {
        value: list_number
      })
    end
  end

  # Move this card to the given board (and optional list on this board)
  def move_to_board(new_board, new_list = nil)
    unless board_id == new_board.id
      payload = { value: new_board.id }
      payload[:idList] = new_list.id if new_list
      client.put("/cards/#{id}/idBoard", payload)
    end
  end

  # Add a member to this card
  def add_member(member)
    client.post("/cards/#{id}/members", {
      value: member.id
    })
  end

  # Remove a member from this card
  def remove_member(member)
    client.delete("/cards/#{id}/members/#{member.id}")
  end
  
  # Add a label
  def add_label(label)
    unless label.valid?
      errors.add(:label, "is not valid.")
      return Trello.logger.warn "Label is not valid." unless label.valid?
    end
    client.post("/cards/#{id}/idLabels", {value: label.id})
  end

  # Remove a label
  def remove_label(label)
      unless label.valid?
        errors.add(:label, "is not valid.")
        return Trello.logger.warn "Label is not valid." unless label.valid?
      end
      client.delete("/cards/#{id}/idLabels/#{label.id}")
  end

  # Add an attachment to this card
  def add_attachment(attachment, name='')
    if attachment.is_a? File
      client.post("/cards/#{id}/attachments", {
          file: attachment,
          name: name
        })
    else
      client.post("/cards/#{id}/attachments", {
          url: attachment,
          name: name
        })
    end
  end

  # Retrieve a list of attachments
  def attachments
    attachments = client.get("/cards/#{id}/attachments").json_into(Attachment)
    MultiAssociation.new(self, attachments).proxy
  end

  # Remove an attachment from this card
  def remove_attachment(attachment)
    client.delete("/cards/#{id}/attachments/#{attachment.id}")
  end

  # :nodoc:
  def request_prefix
    "/cards/#{id}"
  end
end

#dueDatetime

Returns:

  • (Datetime)


38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
# File 'lib/trello/card.rb', line 38

class Card < BasicData
  register_attributes :id, :short_id, :name, :desc, :due, :closed, :url, :short_url,
    :board_id, :member_ids, :list_id, :pos, :last_activity_date, :card_labels,
    :cover_image_id, :badges, :card_members,
    readonly: [ :id, :short_id, :url, :short_url, :last_activity_date, :badges, :card_members ]
  validates_presence_of :id, :name, :list_id
  validates_length_of   :name,        in: 1..16384
  validates_length_of   :desc, in: 0..16384

  include HasActions

  SYMBOL_TO_STRING = {
    id: 'id',
    short_id: 'idShort',
    name: 'name',
    desc: 'desc',
    due: 'due',
    closed: 'closed',
    url: 'url',
    short_url: 'shortUrl',
    board_id: 'idBoard',
    member_ids: 'idMembers',
    cover_image_id: 'idAttachmentCover',
    list_id: 'idList',
    pos: 'pos',
    last_activity_date: 'dateLastActivity',
    card_labels: 'labels',
    badges: 'badges',
    card_members: 'members'
  }

  class << self
    # Find a specific card by its id.
    #
    # @raise [Trello::Error] if the card could not be found.
    #
    # @return [Trello::Card]
    def find(id, params = {})
      client.find(:card, id, params)
    end

    # Create a new card and save it on Trello.
    #
    # @param [Hash] options # @option options [String] :name The name of the new card.
    # @option options [String] :list_id ID of the list that the card should
    #     be added to.
    # @option options [String] :desc A string with a
    #     length from 0 to 16384.
    # @option options [String] :member_ids A comma-separated list of
    #     objectIds (24-character hex strings).
    # @option options [String] :card_labels A comma-separated list of
    #     objectIds (24-character hex strings).
    # @option options [Date] :due A date, or `nil`.
    # @option options [String] :pos A position. `"top"`, `"bottom"`, or a
    #     positive number. Defaults to `"bottom"`.
    #
    # @raise [Trello::Error] if the card could not be created.
    #
    # @return [Trello::Card]
    def create(options)
      client.create(:card,
        'name' => options[:name],
        'idList' => options[:list_id],
        'desc'   => options[:desc],
        'idMembers' => options[:member_ids],
        'labels' => options[:card_labels],
        'due' => options[:due],
        'pos' => options[:pos]
      )
    end
  end

  # Update the fields of a card.
  #
  # Supply a hash of string keyed data retrieved from the Trello API representing
  # a card.
  #
  # Note that this this method does not save anything new to the Trello API,
  # it just assigns the input attributes to your local object. If you use
  # this method to assign attributes, call `save` or `update!` afterwards if
  # you want to persist your changes to Trello.
  #
  # @param [Hash] fields
  # @option fields [String] :id
  # @option fields [String] :short_id
  # @option fields [String] :name The new name of the card.
  # @option fields [String] :desc A string with a length from 0 to
  #     16384.
  # @option fields [Date] :due A date, or `nil`.
  # @option fields [Boolean] :closed
  # @option fields [String] :url
  # @option fields [String] :short_url
  # @option fields [String] :board_id
  # @option fields [String] :member_ids A comma-separated list of objectIds
  #     (24-character hex strings).
  # @option fields [String] :pos A position. `"top"`, `"bottom"`, or a
  #     positive number. Defaults to `"bottom"`.
  # @option fields [String] :card_labels A comma-separated list of
  #     objectIds (24-character hex strings).
  # @option fields [Object] :cover_image_id
  # @option fields [Object] :badges
  # @option fields [Object] :card_members
  #
  # @return [Trello::Card] self
  def update_fields(fields)
    attributes[:id]                 = fields[SYMBOL_TO_STRING[:id]]
    attributes[:short_id]           = fields[SYMBOL_TO_STRING[:short_id]]
    attributes[:name]               = fields[SYMBOL_TO_STRING[:name]]
    attributes[:desc]               = fields[SYMBOL_TO_STRING[:desc]]
    attributes[:due]                = Time.iso8601(fields[SYMBOL_TO_STRING[:due]]) rescue nil
    attributes[:closed]             = fields[SYMBOL_TO_STRING[:closed]]
    attributes[:url]                = fields[SYMBOL_TO_STRING[:url]]
    attributes[:short_url]          = fields[SYMBOL_TO_STRING[:short_url]]
    attributes[:board_id]           = fields[SYMBOL_TO_STRING[:board_id]]
    attributes[:member_ids]         = fields[SYMBOL_TO_STRING[:member_ids]]
    attributes[:list_id]            = fields[SYMBOL_TO_STRING[:list_id]]
    attributes[:pos]                = fields[SYMBOL_TO_STRING[:pos]]
    attributes[:card_labels]        = fields[SYMBOL_TO_STRING[:card_labels]]
    attributes[:last_activity_date] = Time.iso8601(fields[SYMBOL_TO_STRING[:last_activity_date]]) rescue nil
    attributes[:cover_image_id]     = fields[SYMBOL_TO_STRING[:cover_image_id]]
    attributes[:badges]             = fields[SYMBOL_TO_STRING[:badges]]
    attributes[:card_members]       = fields[SYMBOL_TO_STRING[:card_members]]
    self
  end

  # Returns a reference to the board this card is part of.
  one :board, path: :boards, using: :board_id
  # Returns a reference to the cover image attachment
  one :cover_image, path: :attachments, using: :cover_image_id

  # Returns a list of checklists associated with the card.
  #
  # The options hash may have a filter key which can have its value set as any
  # of the following values:
  #    :filter => [ :none, :all ] # default :all
  many :checklists, filter: :all

  def check_item_states
    states = client.get("/cards/#{self.id}/checkItemStates").json_into(CheckItemState)
    MultiAssociation.new(self, states).proxy
  end

  many :labels
  
  # Returns a reference to the list this card is currently in.
  one :list, path: :lists, using: :list_id

  # Returns a list of members who are assigned to this card.
  #
  # @return [Array<Trello::Member>]
  def members
    members = member_ids.map do |member_id|
      client.get("/members/#{member_id}").json_into(Member)
    end
    MultiAssociation.new(self, members).proxy
  end

  # Saves a record.
  #
  # @raise [Trello::Error] if the card could not be saved
  #
  # @return [String] The JSON representation of the saved card returned by
  #     the Trello API.
  def save
    # If we have an id, just update our fields.
    return update! if id

    client.post("/cards", {
      name:   name,
      desc:   desc,
      idList: list_id,
      idMembers: member_ids,
      labels: card_labels,
      pos: pos,
      due: due
    }).json_into(self)
  end

  # Update an existing record.
  #
  # Warning: this updates all fields using values already in memory. If
  # an external resource has updated these fields, you should refresh!
  # this object before making your changes, and before updating the record.
  #
  # @raise [Trello::Error] if the card could not be updated.
  #
  # @return [String] The JSON representation of the updated card returned by
  #     the Trello API.
  def update!
    @previously_changed = changes
    # extract only new values to build payload
    payload = Hash[changes.map { |key, values| [SYMBOL_TO_STRING[key.to_sym].to_sym, values[1]] }]
    @changed_attributes.clear

    client.put("/cards/#{id}", payload)
  end


  # Delete this card
  #
  # @return [String] the JSON response from the Trello API
  def delete
    client.delete("/cards/#{id}")
  end

  # Check if the card is not active anymore.
  def closed?
    closed
  end

  # Close the card.
  #
  # This only marks your local copy card as closed. Use `close!` if you
  # want to close the card and persist the change to the Trello API.
  #
  # @return [Boolean] always returns true
  #
  # @return [String] The JSON representation of the closed card returned by
  #     the Trello API.
  def close
    self.closed = true
  end

  def close!
    close
    save
  end

  # Is the record valid?
  def valid?
    name && list_id
  end

  # Add a comment with the supplied text.
  def add_comment(text)
    client.post("/cards/#{id}/actions/comments", text: text)
  end

  # Add a checklist to this card
  def add_checklist(checklist)
    client.post("/cards/#{id}/checklists", {
      value: checklist.id
    })
  end

  # create a new checklist and add it to this card
  def create_new_checklist(name)
    client.post("/cards/#{id}/checklists", { name: name })
  end

  # Move this card to the given list
  def move_to_list(list)
    list_number = list.is_a?(String) ? list : list.id
    unless list_id == list_number
      client.put("/cards/#{id}/idList", {
        value: list_number
      })
    end
  end

  # Move this card to the given board (and optional list on this board)
  def move_to_board(new_board, new_list = nil)
    unless board_id == new_board.id
      payload = { value: new_board.id }
      payload[:idList] = new_list.id if new_list
      client.put("/cards/#{id}/idBoard", payload)
    end
  end

  # Add a member to this card
  def add_member(member)
    client.post("/cards/#{id}/members", {
      value: member.id
    })
  end

  # Remove a member from this card
  def remove_member(member)
    client.delete("/cards/#{id}/members/#{member.id}")
  end
  
  # Add a label
  def add_label(label)
    unless label.valid?
      errors.add(:label, "is not valid.")
      return Trello.logger.warn "Label is not valid." unless label.valid?
    end
    client.post("/cards/#{id}/idLabels", {value: label.id})
  end

  # Remove a label
  def remove_label(label)
      unless label.valid?
        errors.add(:label, "is not valid.")
        return Trello.logger.warn "Label is not valid." unless label.valid?
      end
      client.delete("/cards/#{id}/idLabels/#{label.id}")
  end

  # Add an attachment to this card
  def add_attachment(attachment, name='')
    if attachment.is_a? File
      client.post("/cards/#{id}/attachments", {
          file: attachment,
          name: name
        })
    else
      client.post("/cards/#{id}/attachments", {
          url: attachment,
          name: name
        })
    end
  end

  # Retrieve a list of attachments
  def attachments
    attachments = client.get("/cards/#{id}/attachments").json_into(Attachment)
    MultiAssociation.new(self, attachments).proxy
  end

  # Remove an attachment from this card
  def remove_attachment(attachment)
    client.delete("/cards/#{id}/attachments/#{attachment.id}")
  end

  # :nodoc:
  def request_prefix
    "/cards/#{id}"
  end
end

#idString (readonly)

Returns:



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
# File 'lib/trello/card.rb', line 38

class Card < BasicData
  register_attributes :id, :short_id, :name, :desc, :due, :closed, :url, :short_url,
    :board_id, :member_ids, :list_id, :pos, :last_activity_date, :card_labels,
    :cover_image_id, :badges, :card_members,
    readonly: [ :id, :short_id, :url, :short_url, :last_activity_date, :badges, :card_members ]
  validates_presence_of :id, :name, :list_id
  validates_length_of   :name,        in: 1..16384
  validates_length_of   :desc, in: 0..16384

  include HasActions

  SYMBOL_TO_STRING = {
    id: 'id',
    short_id: 'idShort',
    name: 'name',
    desc: 'desc',
    due: 'due',
    closed: 'closed',
    url: 'url',
    short_url: 'shortUrl',
    board_id: 'idBoard',
    member_ids: 'idMembers',
    cover_image_id: 'idAttachmentCover',
    list_id: 'idList',
    pos: 'pos',
    last_activity_date: 'dateLastActivity',
    card_labels: 'labels',
    badges: 'badges',
    card_members: 'members'
  }

  class << self
    # Find a specific card by its id.
    #
    # @raise [Trello::Error] if the card could not be found.
    #
    # @return [Trello::Card]
    def find(id, params = {})
      client.find(:card, id, params)
    end

    # Create a new card and save it on Trello.
    #
    # @param [Hash] options # @option options [String] :name The name of the new card.
    # @option options [String] :list_id ID of the list that the card should
    #     be added to.
    # @option options [String] :desc A string with a
    #     length from 0 to 16384.
    # @option options [String] :member_ids A comma-separated list of
    #     objectIds (24-character hex strings).
    # @option options [String] :card_labels A comma-separated list of
    #     objectIds (24-character hex strings).
    # @option options [Date] :due A date, or `nil`.
    # @option options [String] :pos A position. `"top"`, `"bottom"`, or a
    #     positive number. Defaults to `"bottom"`.
    #
    # @raise [Trello::Error] if the card could not be created.
    #
    # @return [Trello::Card]
    def create(options)
      client.create(:card,
        'name' => options[:name],
        'idList' => options[:list_id],
        'desc'   => options[:desc],
        'idMembers' => options[:member_ids],
        'labels' => options[:card_labels],
        'due' => options[:due],
        'pos' => options[:pos]
      )
    end
  end

  # Update the fields of a card.
  #
  # Supply a hash of string keyed data retrieved from the Trello API representing
  # a card.
  #
  # Note that this this method does not save anything new to the Trello API,
  # it just assigns the input attributes to your local object. If you use
  # this method to assign attributes, call `save` or `update!` afterwards if
  # you want to persist your changes to Trello.
  #
  # @param [Hash] fields
  # @option fields [String] :id
  # @option fields [String] :short_id
  # @option fields [String] :name The new name of the card.
  # @option fields [String] :desc A string with a length from 0 to
  #     16384.
  # @option fields [Date] :due A date, or `nil`.
  # @option fields [Boolean] :closed
  # @option fields [String] :url
  # @option fields [String] :short_url
  # @option fields [String] :board_id
  # @option fields [String] :member_ids A comma-separated list of objectIds
  #     (24-character hex strings).
  # @option fields [String] :pos A position. `"top"`, `"bottom"`, or a
  #     positive number. Defaults to `"bottom"`.
  # @option fields [String] :card_labels A comma-separated list of
  #     objectIds (24-character hex strings).
  # @option fields [Object] :cover_image_id
  # @option fields [Object] :badges
  # @option fields [Object] :card_members
  #
  # @return [Trello::Card] self
  def update_fields(fields)
    attributes[:id]                 = fields[SYMBOL_TO_STRING[:id]]
    attributes[:short_id]           = fields[SYMBOL_TO_STRING[:short_id]]
    attributes[:name]               = fields[SYMBOL_TO_STRING[:name]]
    attributes[:desc]               = fields[SYMBOL_TO_STRING[:desc]]
    attributes[:due]                = Time.iso8601(fields[SYMBOL_TO_STRING[:due]]) rescue nil
    attributes[:closed]             = fields[SYMBOL_TO_STRING[:closed]]
    attributes[:url]                = fields[SYMBOL_TO_STRING[:url]]
    attributes[:short_url]          = fields[SYMBOL_TO_STRING[:short_url]]
    attributes[:board_id]           = fields[SYMBOL_TO_STRING[:board_id]]
    attributes[:member_ids]         = fields[SYMBOL_TO_STRING[:member_ids]]
    attributes[:list_id]            = fields[SYMBOL_TO_STRING[:list_id]]
    attributes[:pos]                = fields[SYMBOL_TO_STRING[:pos]]
    attributes[:card_labels]        = fields[SYMBOL_TO_STRING[:card_labels]]
    attributes[:last_activity_date] = Time.iso8601(fields[SYMBOL_TO_STRING[:last_activity_date]]) rescue nil
    attributes[:cover_image_id]     = fields[SYMBOL_TO_STRING[:cover_image_id]]
    attributes[:badges]             = fields[SYMBOL_TO_STRING[:badges]]
    attributes[:card_members]       = fields[SYMBOL_TO_STRING[:card_members]]
    self
  end

  # Returns a reference to the board this card is part of.
  one :board, path: :boards, using: :board_id
  # Returns a reference to the cover image attachment
  one :cover_image, path: :attachments, using: :cover_image_id

  # Returns a list of checklists associated with the card.
  #
  # The options hash may have a filter key which can have its value set as any
  # of the following values:
  #    :filter => [ :none, :all ] # default :all
  many :checklists, filter: :all

  def check_item_states
    states = client.get("/cards/#{self.id}/checkItemStates").json_into(CheckItemState)
    MultiAssociation.new(self, states).proxy
  end

  many :labels
  
  # Returns a reference to the list this card is currently in.
  one :list, path: :lists, using: :list_id

  # Returns a list of members who are assigned to this card.
  #
  # @return [Array<Trello::Member>]
  def members
    members = member_ids.map do |member_id|
      client.get("/members/#{member_id}").json_into(Member)
    end
    MultiAssociation.new(self, members).proxy
  end

  # Saves a record.
  #
  # @raise [Trello::Error] if the card could not be saved
  #
  # @return [String] The JSON representation of the saved card returned by
  #     the Trello API.
  def save
    # If we have an id, just update our fields.
    return update! if id

    client.post("/cards", {
      name:   name,
      desc:   desc,
      idList: list_id,
      idMembers: member_ids,
      labels: card_labels,
      pos: pos,
      due: due
    }).json_into(self)
  end

  # Update an existing record.
  #
  # Warning: this updates all fields using values already in memory. If
  # an external resource has updated these fields, you should refresh!
  # this object before making your changes, and before updating the record.
  #
  # @raise [Trello::Error] if the card could not be updated.
  #
  # @return [String] The JSON representation of the updated card returned by
  #     the Trello API.
  def update!
    @previously_changed = changes
    # extract only new values to build payload
    payload = Hash[changes.map { |key, values| [SYMBOL_TO_STRING[key.to_sym].to_sym, values[1]] }]
    @changed_attributes.clear

    client.put("/cards/#{id}", payload)
  end


  # Delete this card
  #
  # @return [String] the JSON response from the Trello API
  def delete
    client.delete("/cards/#{id}")
  end

  # Check if the card is not active anymore.
  def closed?
    closed
  end

  # Close the card.
  #
  # This only marks your local copy card as closed. Use `close!` if you
  # want to close the card and persist the change to the Trello API.
  #
  # @return [Boolean] always returns true
  #
  # @return [String] The JSON representation of the closed card returned by
  #     the Trello API.
  def close
    self.closed = true
  end

  def close!
    close
    save
  end

  # Is the record valid?
  def valid?
    name && list_id
  end

  # Add a comment with the supplied text.
  def add_comment(text)
    client.post("/cards/#{id}/actions/comments", text: text)
  end

  # Add a checklist to this card
  def add_checklist(checklist)
    client.post("/cards/#{id}/checklists", {
      value: checklist.id
    })
  end

  # create a new checklist and add it to this card
  def create_new_checklist(name)
    client.post("/cards/#{id}/checklists", { name: name })
  end

  # Move this card to the given list
  def move_to_list(list)
    list_number = list.is_a?(String) ? list : list.id
    unless list_id == list_number
      client.put("/cards/#{id}/idList", {
        value: list_number
      })
    end
  end

  # Move this card to the given board (and optional list on this board)
  def move_to_board(new_board, new_list = nil)
    unless board_id == new_board.id
      payload = { value: new_board.id }
      payload[:idList] = new_list.id if new_list
      client.put("/cards/#{id}/idBoard", payload)
    end
  end

  # Add a member to this card
  def add_member(member)
    client.post("/cards/#{id}/members", {
      value: member.id
    })
  end

  # Remove a member from this card
  def remove_member(member)
    client.delete("/cards/#{id}/members/#{member.id}")
  end
  
  # Add a label
  def add_label(label)
    unless label.valid?
      errors.add(:label, "is not valid.")
      return Trello.logger.warn "Label is not valid." unless label.valid?
    end
    client.post("/cards/#{id}/idLabels", {value: label.id})
  end

  # Remove a label
  def remove_label(label)
      unless label.valid?
        errors.add(:label, "is not valid.")
        return Trello.logger.warn "Label is not valid." unless label.valid?
      end
      client.delete("/cards/#{id}/idLabels/#{label.id}")
  end

  # Add an attachment to this card
  def add_attachment(attachment, name='')
    if attachment.is_a? File
      client.post("/cards/#{id}/attachments", {
          file: attachment,
          name: name
        })
    else
      client.post("/cards/#{id}/attachments", {
          url: attachment,
          name: name
        })
    end
  end

  # Retrieve a list of attachments
  def attachments
    attachments = client.get("/cards/#{id}/attachments").json_into(Attachment)
    MultiAssociation.new(self, attachments).proxy
  end

  # Remove an attachment from this card
  def remove_attachment(attachment)
    client.delete("/cards/#{id}/attachments/#{attachment.id}")
  end

  # :nodoc:
  def request_prefix
    "/cards/#{id}"
  end
end

#last_activity_dateDateime (readonly)

Returns:

  • (Dateime)


38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
# File 'lib/trello/card.rb', line 38

class Card < BasicData
  register_attributes :id, :short_id, :name, :desc, :due, :closed, :url, :short_url,
    :board_id, :member_ids, :list_id, :pos, :last_activity_date, :card_labels,
    :cover_image_id, :badges, :card_members,
    readonly: [ :id, :short_id, :url, :short_url, :last_activity_date, :badges, :card_members ]
  validates_presence_of :id, :name, :list_id
  validates_length_of   :name,        in: 1..16384
  validates_length_of   :desc, in: 0..16384

  include HasActions

  SYMBOL_TO_STRING = {
    id: 'id',
    short_id: 'idShort',
    name: 'name',
    desc: 'desc',
    due: 'due',
    closed: 'closed',
    url: 'url',
    short_url: 'shortUrl',
    board_id: 'idBoard',
    member_ids: 'idMembers',
    cover_image_id: 'idAttachmentCover',
    list_id: 'idList',
    pos: 'pos',
    last_activity_date: 'dateLastActivity',
    card_labels: 'labels',
    badges: 'badges',
    card_members: 'members'
  }

  class << self
    # Find a specific card by its id.
    #
    # @raise [Trello::Error] if the card could not be found.
    #
    # @return [Trello::Card]
    def find(id, params = {})
      client.find(:card, id, params)
    end

    # Create a new card and save it on Trello.
    #
    # @param [Hash] options # @option options [String] :name The name of the new card.
    # @option options [String] :list_id ID of the list that the card should
    #     be added to.
    # @option options [String] :desc A string with a
    #     length from 0 to 16384.
    # @option options [String] :member_ids A comma-separated list of
    #     objectIds (24-character hex strings).
    # @option options [String] :card_labels A comma-separated list of
    #     objectIds (24-character hex strings).
    # @option options [Date] :due A date, or `nil`.
    # @option options [String] :pos A position. `"top"`, `"bottom"`, or a
    #     positive number. Defaults to `"bottom"`.
    #
    # @raise [Trello::Error] if the card could not be created.
    #
    # @return [Trello::Card]
    def create(options)
      client.create(:card,
        'name' => options[:name],
        'idList' => options[:list_id],
        'desc'   => options[:desc],
        'idMembers' => options[:member_ids],
        'labels' => options[:card_labels],
        'due' => options[:due],
        'pos' => options[:pos]
      )
    end
  end

  # Update the fields of a card.
  #
  # Supply a hash of string keyed data retrieved from the Trello API representing
  # a card.
  #
  # Note that this this method does not save anything new to the Trello API,
  # it just assigns the input attributes to your local object. If you use
  # this method to assign attributes, call `save` or `update!` afterwards if
  # you want to persist your changes to Trello.
  #
  # @param [Hash] fields
  # @option fields [String] :id
  # @option fields [String] :short_id
  # @option fields [String] :name The new name of the card.
  # @option fields [String] :desc A string with a length from 0 to
  #     16384.
  # @option fields [Date] :due A date, or `nil`.
  # @option fields [Boolean] :closed
  # @option fields [String] :url
  # @option fields [String] :short_url
  # @option fields [String] :board_id
  # @option fields [String] :member_ids A comma-separated list of objectIds
  #     (24-character hex strings).
  # @option fields [String] :pos A position. `"top"`, `"bottom"`, or a
  #     positive number. Defaults to `"bottom"`.
  # @option fields [String] :card_labels A comma-separated list of
  #     objectIds (24-character hex strings).
  # @option fields [Object] :cover_image_id
  # @option fields [Object] :badges
  # @option fields [Object] :card_members
  #
  # @return [Trello::Card] self
  def update_fields(fields)
    attributes[:id]                 = fields[SYMBOL_TO_STRING[:id]]
    attributes[:short_id]           = fields[SYMBOL_TO_STRING[:short_id]]
    attributes[:name]               = fields[SYMBOL_TO_STRING[:name]]
    attributes[:desc]               = fields[SYMBOL_TO_STRING[:desc]]
    attributes[:due]                = Time.iso8601(fields[SYMBOL_TO_STRING[:due]]) rescue nil
    attributes[:closed]             = fields[SYMBOL_TO_STRING[:closed]]
    attributes[:url]                = fields[SYMBOL_TO_STRING[:url]]
    attributes[:short_url]          = fields[SYMBOL_TO_STRING[:short_url]]
    attributes[:board_id]           = fields[SYMBOL_TO_STRING[:board_id]]
    attributes[:member_ids]         = fields[SYMBOL_TO_STRING[:member_ids]]
    attributes[:list_id]            = fields[SYMBOL_TO_STRING[:list_id]]
    attributes[:pos]                = fields[SYMBOL_TO_STRING[:pos]]
    attributes[:card_labels]        = fields[SYMBOL_TO_STRING[:card_labels]]
    attributes[:last_activity_date] = Time.iso8601(fields[SYMBOL_TO_STRING[:last_activity_date]]) rescue nil
    attributes[:cover_image_id]     = fields[SYMBOL_TO_STRING[:cover_image_id]]
    attributes[:badges]             = fields[SYMBOL_TO_STRING[:badges]]
    attributes[:card_members]       = fields[SYMBOL_TO_STRING[:card_members]]
    self
  end

  # Returns a reference to the board this card is part of.
  one :board, path: :boards, using: :board_id
  # Returns a reference to the cover image attachment
  one :cover_image, path: :attachments, using: :cover_image_id

  # Returns a list of checklists associated with the card.
  #
  # The options hash may have a filter key which can have its value set as any
  # of the following values:
  #    :filter => [ :none, :all ] # default :all
  many :checklists, filter: :all

  def check_item_states
    states = client.get("/cards/#{self.id}/checkItemStates").json_into(CheckItemState)
    MultiAssociation.new(self, states).proxy
  end

  many :labels
  
  # Returns a reference to the list this card is currently in.
  one :list, path: :lists, using: :list_id

  # Returns a list of members who are assigned to this card.
  #
  # @return [Array<Trello::Member>]
  def members
    members = member_ids.map do |member_id|
      client.get("/members/#{member_id}").json_into(Member)
    end
    MultiAssociation.new(self, members).proxy
  end

  # Saves a record.
  #
  # @raise [Trello::Error] if the card could not be saved
  #
  # @return [String] The JSON representation of the saved card returned by
  #     the Trello API.
  def save
    # If we have an id, just update our fields.
    return update! if id

    client.post("/cards", {
      name:   name,
      desc:   desc,
      idList: list_id,
      idMembers: member_ids,
      labels: card_labels,
      pos: pos,
      due: due
    }).json_into(self)
  end

  # Update an existing record.
  #
  # Warning: this updates all fields using values already in memory. If
  # an external resource has updated these fields, you should refresh!
  # this object before making your changes, and before updating the record.
  #
  # @raise [Trello::Error] if the card could not be updated.
  #
  # @return [String] The JSON representation of the updated card returned by
  #     the Trello API.
  def update!
    @previously_changed = changes
    # extract only new values to build payload
    payload = Hash[changes.map { |key, values| [SYMBOL_TO_STRING[key.to_sym].to_sym, values[1]] }]
    @changed_attributes.clear

    client.put("/cards/#{id}", payload)
  end


  # Delete this card
  #
  # @return [String] the JSON response from the Trello API
  def delete
    client.delete("/cards/#{id}")
  end

  # Check if the card is not active anymore.
  def closed?
    closed
  end

  # Close the card.
  #
  # This only marks your local copy card as closed. Use `close!` if you
  # want to close the card and persist the change to the Trello API.
  #
  # @return [Boolean] always returns true
  #
  # @return [String] The JSON representation of the closed card returned by
  #     the Trello API.
  def close
    self.closed = true
  end

  def close!
    close
    save
  end

  # Is the record valid?
  def valid?
    name && list_id
  end

  # Add a comment with the supplied text.
  def add_comment(text)
    client.post("/cards/#{id}/actions/comments", text: text)
  end

  # Add a checklist to this card
  def add_checklist(checklist)
    client.post("/cards/#{id}/checklists", {
      value: checklist.id
    })
  end

  # create a new checklist and add it to this card
  def create_new_checklist(name)
    client.post("/cards/#{id}/checklists", { name: name })
  end

  # Move this card to the given list
  def move_to_list(list)
    list_number = list.is_a?(String) ? list : list.id
    unless list_id == list_number
      client.put("/cards/#{id}/idList", {
        value: list_number
      })
    end
  end

  # Move this card to the given board (and optional list on this board)
  def move_to_board(new_board, new_list = nil)
    unless board_id == new_board.id
      payload = { value: new_board.id }
      payload[:idList] = new_list.id if new_list
      client.put("/cards/#{id}/idBoard", payload)
    end
  end

  # Add a member to this card
  def add_member(member)
    client.post("/cards/#{id}/members", {
      value: member.id
    })
  end

  # Remove a member from this card
  def remove_member(member)
    client.delete("/cards/#{id}/members/#{member.id}")
  end
  
  # Add a label
  def add_label(label)
    unless label.valid?
      errors.add(:label, "is not valid.")
      return Trello.logger.warn "Label is not valid." unless label.valid?
    end
    client.post("/cards/#{id}/idLabels", {value: label.id})
  end

  # Remove a label
  def remove_label(label)
      unless label.valid?
        errors.add(:label, "is not valid.")
        return Trello.logger.warn "Label is not valid." unless label.valid?
      end
      client.delete("/cards/#{id}/idLabels/#{label.id}")
  end

  # Add an attachment to this card
  def add_attachment(attachment, name='')
    if attachment.is_a? File
      client.post("/cards/#{id}/attachments", {
          file: attachment,
          name: name
        })
    else
      client.post("/cards/#{id}/attachments", {
          url: attachment,
          name: name
        })
    end
  end

  # Retrieve a list of attachments
  def attachments
    attachments = client.get("/cards/#{id}/attachments").json_into(Attachment)
    MultiAssociation.new(self, attachments).proxy
  end

  # Remove an attachment from this card
  def remove_attachment(attachment)
    client.delete("/cards/#{id}/attachments/#{attachment.id}")
  end

  # :nodoc:
  def request_prefix
    "/cards/#{id}"
  end
end

#list_idString

Returns A 24-character hex string.

Returns:

  • (String)

    A 24-character hex string



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
# File 'lib/trello/card.rb', line 38

class Card < BasicData
  register_attributes :id, :short_id, :name, :desc, :due, :closed, :url, :short_url,
    :board_id, :member_ids, :list_id, :pos, :last_activity_date, :card_labels,
    :cover_image_id, :badges, :card_members,
    readonly: [ :id, :short_id, :url, :short_url, :last_activity_date, :badges, :card_members ]
  validates_presence_of :id, :name, :list_id
  validates_length_of   :name,        in: 1..16384
  validates_length_of   :desc, in: 0..16384

  include HasActions

  SYMBOL_TO_STRING = {
    id: 'id',
    short_id: 'idShort',
    name: 'name',
    desc: 'desc',
    due: 'due',
    closed: 'closed',
    url: 'url',
    short_url: 'shortUrl',
    board_id: 'idBoard',
    member_ids: 'idMembers',
    cover_image_id: 'idAttachmentCover',
    list_id: 'idList',
    pos: 'pos',
    last_activity_date: 'dateLastActivity',
    card_labels: 'labels',
    badges: 'badges',
    card_members: 'members'
  }

  class << self
    # Find a specific card by its id.
    #
    # @raise [Trello::Error] if the card could not be found.
    #
    # @return [Trello::Card]
    def find(id, params = {})
      client.find(:card, id, params)
    end

    # Create a new card and save it on Trello.
    #
    # @param [Hash] options # @option options [String] :name The name of the new card.
    # @option options [String] :list_id ID of the list that the card should
    #     be added to.
    # @option options [String] :desc A string with a
    #     length from 0 to 16384.
    # @option options [String] :member_ids A comma-separated list of
    #     objectIds (24-character hex strings).
    # @option options [String] :card_labels A comma-separated list of
    #     objectIds (24-character hex strings).
    # @option options [Date] :due A date, or `nil`.
    # @option options [String] :pos A position. `"top"`, `"bottom"`, or a
    #     positive number. Defaults to `"bottom"`.
    #
    # @raise [Trello::Error] if the card could not be created.
    #
    # @return [Trello::Card]
    def create(options)
      client.create(:card,
        'name' => options[:name],
        'idList' => options[:list_id],
        'desc'   => options[:desc],
        'idMembers' => options[:member_ids],
        'labels' => options[:card_labels],
        'due' => options[:due],
        'pos' => options[:pos]
      )
    end
  end

  # Update the fields of a card.
  #
  # Supply a hash of string keyed data retrieved from the Trello API representing
  # a card.
  #
  # Note that this this method does not save anything new to the Trello API,
  # it just assigns the input attributes to your local object. If you use
  # this method to assign attributes, call `save` or `update!` afterwards if
  # you want to persist your changes to Trello.
  #
  # @param [Hash] fields
  # @option fields [String] :id
  # @option fields [String] :short_id
  # @option fields [String] :name The new name of the card.
  # @option fields [String] :desc A string with a length from 0 to
  #     16384.
  # @option fields [Date] :due A date, or `nil`.
  # @option fields [Boolean] :closed
  # @option fields [String] :url
  # @option fields [String] :short_url
  # @option fields [String] :board_id
  # @option fields [String] :member_ids A comma-separated list of objectIds
  #     (24-character hex strings).
  # @option fields [String] :pos A position. `"top"`, `"bottom"`, or a
  #     positive number. Defaults to `"bottom"`.
  # @option fields [String] :card_labels A comma-separated list of
  #     objectIds (24-character hex strings).
  # @option fields [Object] :cover_image_id
  # @option fields [Object] :badges
  # @option fields [Object] :card_members
  #
  # @return [Trello::Card] self
  def update_fields(fields)
    attributes[:id]                 = fields[SYMBOL_TO_STRING[:id]]
    attributes[:short_id]           = fields[SYMBOL_TO_STRING[:short_id]]
    attributes[:name]               = fields[SYMBOL_TO_STRING[:name]]
    attributes[:desc]               = fields[SYMBOL_TO_STRING[:desc]]
    attributes[:due]                = Time.iso8601(fields[SYMBOL_TO_STRING[:due]]) rescue nil
    attributes[:closed]             = fields[SYMBOL_TO_STRING[:closed]]
    attributes[:url]                = fields[SYMBOL_TO_STRING[:url]]
    attributes[:short_url]          = fields[SYMBOL_TO_STRING[:short_url]]
    attributes[:board_id]           = fields[SYMBOL_TO_STRING[:board_id]]
    attributes[:member_ids]         = fields[SYMBOL_TO_STRING[:member_ids]]
    attributes[:list_id]            = fields[SYMBOL_TO_STRING[:list_id]]
    attributes[:pos]                = fields[SYMBOL_TO_STRING[:pos]]
    attributes[:card_labels]        = fields[SYMBOL_TO_STRING[:card_labels]]
    attributes[:last_activity_date] = Time.iso8601(fields[SYMBOL_TO_STRING[:last_activity_date]]) rescue nil
    attributes[:cover_image_id]     = fields[SYMBOL_TO_STRING[:cover_image_id]]
    attributes[:badges]             = fields[SYMBOL_TO_STRING[:badges]]
    attributes[:card_members]       = fields[SYMBOL_TO_STRING[:card_members]]
    self
  end

  # Returns a reference to the board this card is part of.
  one :board, path: :boards, using: :board_id
  # Returns a reference to the cover image attachment
  one :cover_image, path: :attachments, using: :cover_image_id

  # Returns a list of checklists associated with the card.
  #
  # The options hash may have a filter key which can have its value set as any
  # of the following values:
  #    :filter => [ :none, :all ] # default :all
  many :checklists, filter: :all

  def check_item_states
    states = client.get("/cards/#{self.id}/checkItemStates").json_into(CheckItemState)
    MultiAssociation.new(self, states).proxy
  end

  many :labels
  
  # Returns a reference to the list this card is currently in.
  one :list, path: :lists, using: :list_id

  # Returns a list of members who are assigned to this card.
  #
  # @return [Array<Trello::Member>]
  def members
    members = member_ids.map do |member_id|
      client.get("/members/#{member_id}").json_into(Member)
    end
    MultiAssociation.new(self, members).proxy
  end

  # Saves a record.
  #
  # @raise [Trello::Error] if the card could not be saved
  #
  # @return [String] The JSON representation of the saved card returned by
  #     the Trello API.
  def save
    # If we have an id, just update our fields.
    return update! if id

    client.post("/cards", {
      name:   name,
      desc:   desc,
      idList: list_id,
      idMembers: member_ids,
      labels: card_labels,
      pos: pos,
      due: due
    }).json_into(self)
  end

  # Update an existing record.
  #
  # Warning: this updates all fields using values already in memory. If
  # an external resource has updated these fields, you should refresh!
  # this object before making your changes, and before updating the record.
  #
  # @raise [Trello::Error] if the card could not be updated.
  #
  # @return [String] The JSON representation of the updated card returned by
  #     the Trello API.
  def update!
    @previously_changed = changes
    # extract only new values to build payload
    payload = Hash[changes.map { |key, values| [SYMBOL_TO_STRING[key.to_sym].to_sym, values[1]] }]
    @changed_attributes.clear

    client.put("/cards/#{id}", payload)
  end


  # Delete this card
  #
  # @return [String] the JSON response from the Trello API
  def delete
    client.delete("/cards/#{id}")
  end

  # Check if the card is not active anymore.
  def closed?
    closed
  end

  # Close the card.
  #
  # This only marks your local copy card as closed. Use `close!` if you
  # want to close the card and persist the change to the Trello API.
  #
  # @return [Boolean] always returns true
  #
  # @return [String] The JSON representation of the closed card returned by
  #     the Trello API.
  def close
    self.closed = true
  end

  def close!
    close
    save
  end

  # Is the record valid?
  def valid?
    name && list_id
  end

  # Add a comment with the supplied text.
  def add_comment(text)
    client.post("/cards/#{id}/actions/comments", text: text)
  end

  # Add a checklist to this card
  def add_checklist(checklist)
    client.post("/cards/#{id}/checklists", {
      value: checklist.id
    })
  end

  # create a new checklist and add it to this card
  def create_new_checklist(name)
    client.post("/cards/#{id}/checklists", { name: name })
  end

  # Move this card to the given list
  def move_to_list(list)
    list_number = list.is_a?(String) ? list : list.id
    unless list_id == list_number
      client.put("/cards/#{id}/idList", {
        value: list_number
      })
    end
  end

  # Move this card to the given board (and optional list on this board)
  def move_to_board(new_board, new_list = nil)
    unless board_id == new_board.id
      payload = { value: new_board.id }
      payload[:idList] = new_list.id if new_list
      client.put("/cards/#{id}/idBoard", payload)
    end
  end

  # Add a member to this card
  def add_member(member)
    client.post("/cards/#{id}/members", {
      value: member.id
    })
  end

  # Remove a member from this card
  def remove_member(member)
    client.delete("/cards/#{id}/members/#{member.id}")
  end
  
  # Add a label
  def add_label(label)
    unless label.valid?
      errors.add(:label, "is not valid.")
      return Trello.logger.warn "Label is not valid." unless label.valid?
    end
    client.post("/cards/#{id}/idLabels", {value: label.id})
  end

  # Remove a label
  def remove_label(label)
      unless label.valid?
        errors.add(:label, "is not valid.")
        return Trello.logger.warn "Label is not valid." unless label.valid?
      end
      client.delete("/cards/#{id}/idLabels/#{label.id}")
  end

  # Add an attachment to this card
  def add_attachment(attachment, name='')
    if attachment.is_a? File
      client.post("/cards/#{id}/attachments", {
          file: attachment,
          name: name
        })
    else
      client.post("/cards/#{id}/attachments", {
          url: attachment,
          name: name
        })
    end
  end

  # Retrieve a list of attachments
  def attachments
    attachments = client.get("/cards/#{id}/attachments").json_into(Attachment)
    MultiAssociation.new(self, attachments).proxy
  end

  # Remove an attachment from this card
  def remove_attachment(attachment)
    client.delete("/cards/#{id}/attachments/#{attachment.id}")
  end

  # :nodoc:
  def request_prefix
    "/cards/#{id}"
  end
end

#member_idsArray<String>

Returns An Array of 24-character hex strings.

Returns:

  • (Array<String>)

    An Array of 24-character hex strings



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
# File 'lib/trello/card.rb', line 38

class Card < BasicData
  register_attributes :id, :short_id, :name, :desc, :due, :closed, :url, :short_url,
    :board_id, :member_ids, :list_id, :pos, :last_activity_date, :card_labels,
    :cover_image_id, :badges, :card_members,
    readonly: [ :id, :short_id, :url, :short_url, :last_activity_date, :badges, :card_members ]
  validates_presence_of :id, :name, :list_id
  validates_length_of   :name,        in: 1..16384
  validates_length_of   :desc, in: 0..16384

  include HasActions

  SYMBOL_TO_STRING = {
    id: 'id',
    short_id: 'idShort',
    name: 'name',
    desc: 'desc',
    due: 'due',
    closed: 'closed',
    url: 'url',
    short_url: 'shortUrl',
    board_id: 'idBoard',
    member_ids: 'idMembers',
    cover_image_id: 'idAttachmentCover',
    list_id: 'idList',
    pos: 'pos',
    last_activity_date: 'dateLastActivity',
    card_labels: 'labels',
    badges: 'badges',
    card_members: 'members'
  }

  class << self
    # Find a specific card by its id.
    #
    # @raise [Trello::Error] if the card could not be found.
    #
    # @return [Trello::Card]
    def find(id, params = {})
      client.find(:card, id, params)
    end

    # Create a new card and save it on Trello.
    #
    # @param [Hash] options # @option options [String] :name The name of the new card.
    # @option options [String] :list_id ID of the list that the card should
    #     be added to.
    # @option options [String] :desc A string with a
    #     length from 0 to 16384.
    # @option options [String] :member_ids A comma-separated list of
    #     objectIds (24-character hex strings).
    # @option options [String] :card_labels A comma-separated list of
    #     objectIds (24-character hex strings).
    # @option options [Date] :due A date, or `nil`.
    # @option options [String] :pos A position. `"top"`, `"bottom"`, or a
    #     positive number. Defaults to `"bottom"`.
    #
    # @raise [Trello::Error] if the card could not be created.
    #
    # @return [Trello::Card]
    def create(options)
      client.create(:card,
        'name' => options[:name],
        'idList' => options[:list_id],
        'desc'   => options[:desc],
        'idMembers' => options[:member_ids],
        'labels' => options[:card_labels],
        'due' => options[:due],
        'pos' => options[:pos]
      )
    end
  end

  # Update the fields of a card.
  #
  # Supply a hash of string keyed data retrieved from the Trello API representing
  # a card.
  #
  # Note that this this method does not save anything new to the Trello API,
  # it just assigns the input attributes to your local object. If you use
  # this method to assign attributes, call `save` or `update!` afterwards if
  # you want to persist your changes to Trello.
  #
  # @param [Hash] fields
  # @option fields [String] :id
  # @option fields [String] :short_id
  # @option fields [String] :name The new name of the card.
  # @option fields [String] :desc A string with a length from 0 to
  #     16384.
  # @option fields [Date] :due A date, or `nil`.
  # @option fields [Boolean] :closed
  # @option fields [String] :url
  # @option fields [String] :short_url
  # @option fields [String] :board_id
  # @option fields [String] :member_ids A comma-separated list of objectIds
  #     (24-character hex strings).
  # @option fields [String] :pos A position. `"top"`, `"bottom"`, or a
  #     positive number. Defaults to `"bottom"`.
  # @option fields [String] :card_labels A comma-separated list of
  #     objectIds (24-character hex strings).
  # @option fields [Object] :cover_image_id
  # @option fields [Object] :badges
  # @option fields [Object] :card_members
  #
  # @return [Trello::Card] self
  def update_fields(fields)
    attributes[:id]                 = fields[SYMBOL_TO_STRING[:id]]
    attributes[:short_id]           = fields[SYMBOL_TO_STRING[:short_id]]
    attributes[:name]               = fields[SYMBOL_TO_STRING[:name]]
    attributes[:desc]               = fields[SYMBOL_TO_STRING[:desc]]
    attributes[:due]                = Time.iso8601(fields[SYMBOL_TO_STRING[:due]]) rescue nil
    attributes[:closed]             = fields[SYMBOL_TO_STRING[:closed]]
    attributes[:url]                = fields[SYMBOL_TO_STRING[:url]]
    attributes[:short_url]          = fields[SYMBOL_TO_STRING[:short_url]]
    attributes[:board_id]           = fields[SYMBOL_TO_STRING[:board_id]]
    attributes[:member_ids]         = fields[SYMBOL_TO_STRING[:member_ids]]
    attributes[:list_id]            = fields[SYMBOL_TO_STRING[:list_id]]
    attributes[:pos]                = fields[SYMBOL_TO_STRING[:pos]]
    attributes[:card_labels]        = fields[SYMBOL_TO_STRING[:card_labels]]
    attributes[:last_activity_date] = Time.iso8601(fields[SYMBOL_TO_STRING[:last_activity_date]]) rescue nil
    attributes[:cover_image_id]     = fields[SYMBOL_TO_STRING[:cover_image_id]]
    attributes[:badges]             = fields[SYMBOL_TO_STRING[:badges]]
    attributes[:card_members]       = fields[SYMBOL_TO_STRING[:card_members]]
    self
  end

  # Returns a reference to the board this card is part of.
  one :board, path: :boards, using: :board_id
  # Returns a reference to the cover image attachment
  one :cover_image, path: :attachments, using: :cover_image_id

  # Returns a list of checklists associated with the card.
  #
  # The options hash may have a filter key which can have its value set as any
  # of the following values:
  #    :filter => [ :none, :all ] # default :all
  many :checklists, filter: :all

  def check_item_states
    states = client.get("/cards/#{self.id}/checkItemStates").json_into(CheckItemState)
    MultiAssociation.new(self, states).proxy
  end

  many :labels
  
  # Returns a reference to the list this card is currently in.
  one :list, path: :lists, using: :list_id

  # Returns a list of members who are assigned to this card.
  #
  # @return [Array<Trello::Member>]
  def members
    members = member_ids.map do |member_id|
      client.get("/members/#{member_id}").json_into(Member)
    end
    MultiAssociation.new(self, members).proxy
  end

  # Saves a record.
  #
  # @raise [Trello::Error] if the card could not be saved
  #
  # @return [String] The JSON representation of the saved card returned by
  #     the Trello API.
  def save
    # If we have an id, just update our fields.
    return update! if id

    client.post("/cards", {
      name:   name,
      desc:   desc,
      idList: list_id,
      idMembers: member_ids,
      labels: card_labels,
      pos: pos,
      due: due
    }).json_into(self)
  end

  # Update an existing record.
  #
  # Warning: this updates all fields using values already in memory. If
  # an external resource has updated these fields, you should refresh!
  # this object before making your changes, and before updating the record.
  #
  # @raise [Trello::Error] if the card could not be updated.
  #
  # @return [String] The JSON representation of the updated card returned by
  #     the Trello API.
  def update!
    @previously_changed = changes
    # extract only new values to build payload
    payload = Hash[changes.map { |key, values| [SYMBOL_TO_STRING[key.to_sym].to_sym, values[1]] }]
    @changed_attributes.clear

    client.put("/cards/#{id}", payload)
  end


  # Delete this card
  #
  # @return [String] the JSON response from the Trello API
  def delete
    client.delete("/cards/#{id}")
  end

  # Check if the card is not active anymore.
  def closed?
    closed
  end

  # Close the card.
  #
  # This only marks your local copy card as closed. Use `close!` if you
  # want to close the card and persist the change to the Trello API.
  #
  # @return [Boolean] always returns true
  #
  # @return [String] The JSON representation of the closed card returned by
  #     the Trello API.
  def close
    self.closed = true
  end

  def close!
    close
    save
  end

  # Is the record valid?
  def valid?
    name && list_id
  end

  # Add a comment with the supplied text.
  def add_comment(text)
    client.post("/cards/#{id}/actions/comments", text: text)
  end

  # Add a checklist to this card
  def add_checklist(checklist)
    client.post("/cards/#{id}/checklists", {
      value: checklist.id
    })
  end

  # create a new checklist and add it to this card
  def create_new_checklist(name)
    client.post("/cards/#{id}/checklists", { name: name })
  end

  # Move this card to the given list
  def move_to_list(list)
    list_number = list.is_a?(String) ? list : list.id
    unless list_id == list_number
      client.put("/cards/#{id}/idList", {
        value: list_number
      })
    end
  end

  # Move this card to the given board (and optional list on this board)
  def move_to_board(new_board, new_list = nil)
    unless board_id == new_board.id
      payload = { value: new_board.id }
      payload[:idList] = new_list.id if new_list
      client.put("/cards/#{id}/idBoard", payload)
    end
  end

  # Add a member to this card
  def add_member(member)
    client.post("/cards/#{id}/members", {
      value: member.id
    })
  end

  # Remove a member from this card
  def remove_member(member)
    client.delete("/cards/#{id}/members/#{member.id}")
  end
  
  # Add a label
  def add_label(label)
    unless label.valid?
      errors.add(:label, "is not valid.")
      return Trello.logger.warn "Label is not valid." unless label.valid?
    end
    client.post("/cards/#{id}/idLabels", {value: label.id})
  end

  # Remove a label
  def remove_label(label)
      unless label.valid?
        errors.add(:label, "is not valid.")
        return Trello.logger.warn "Label is not valid." unless label.valid?
      end
      client.delete("/cards/#{id}/idLabels/#{label.id}")
  end

  # Add an attachment to this card
  def add_attachment(attachment, name='')
    if attachment.is_a? File
      client.post("/cards/#{id}/attachments", {
          file: attachment,
          name: name
        })
    else
      client.post("/cards/#{id}/attachments", {
          url: attachment,
          name: name
        })
    end
  end

  # Retrieve a list of attachments
  def attachments
    attachments = client.get("/cards/#{id}/attachments").json_into(Attachment)
    MultiAssociation.new(self, attachments).proxy
  end

  # Remove an attachment from this card
  def remove_attachment(attachment)
    client.delete("/cards/#{id}/attachments/#{attachment.id}")
  end

  # :nodoc:
  def request_prefix
    "/cards/#{id}"
  end
end

#nameString

Returns:



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
# File 'lib/trello/card.rb', line 38

class Card < BasicData
  register_attributes :id, :short_id, :name, :desc, :due, :closed, :url, :short_url,
    :board_id, :member_ids, :list_id, :pos, :last_activity_date, :card_labels,
    :cover_image_id, :badges, :card_members,
    readonly: [ :id, :short_id, :url, :short_url, :last_activity_date, :badges, :card_members ]
  validates_presence_of :id, :name, :list_id
  validates_length_of   :name,        in: 1..16384
  validates_length_of   :desc, in: 0..16384

  include HasActions

  SYMBOL_TO_STRING = {
    id: 'id',
    short_id: 'idShort',
    name: 'name',
    desc: 'desc',
    due: 'due',
    closed: 'closed',
    url: 'url',
    short_url: 'shortUrl',
    board_id: 'idBoard',
    member_ids: 'idMembers',
    cover_image_id: 'idAttachmentCover',
    list_id: 'idList',
    pos: 'pos',
    last_activity_date: 'dateLastActivity',
    card_labels: 'labels',
    badges: 'badges',
    card_members: 'members'
  }

  class << self
    # Find a specific card by its id.
    #
    # @raise [Trello::Error] if the card could not be found.
    #
    # @return [Trello::Card]
    def find(id, params = {})
      client.find(:card, id, params)
    end

    # Create a new card and save it on Trello.
    #
    # @param [Hash] options # @option options [String] :name The name of the new card.
    # @option options [String] :list_id ID of the list that the card should
    #     be added to.
    # @option options [String] :desc A string with a
    #     length from 0 to 16384.
    # @option options [String] :member_ids A comma-separated list of
    #     objectIds (24-character hex strings).
    # @option options [String] :card_labels A comma-separated list of
    #     objectIds (24-character hex strings).
    # @option options [Date] :due A date, or `nil`.
    # @option options [String] :pos A position. `"top"`, `"bottom"`, or a
    #     positive number. Defaults to `"bottom"`.
    #
    # @raise [Trello::Error] if the card could not be created.
    #
    # @return [Trello::Card]
    def create(options)
      client.create(:card,
        'name' => options[:name],
        'idList' => options[:list_id],
        'desc'   => options[:desc],
        'idMembers' => options[:member_ids],
        'labels' => options[:card_labels],
        'due' => options[:due],
        'pos' => options[:pos]
      )
    end
  end

  # Update the fields of a card.
  #
  # Supply a hash of string keyed data retrieved from the Trello API representing
  # a card.
  #
  # Note that this this method does not save anything new to the Trello API,
  # it just assigns the input attributes to your local object. If you use
  # this method to assign attributes, call `save` or `update!` afterwards if
  # you want to persist your changes to Trello.
  #
  # @param [Hash] fields
  # @option fields [String] :id
  # @option fields [String] :short_id
  # @option fields [String] :name The new name of the card.
  # @option fields [String] :desc A string with a length from 0 to
  #     16384.
  # @option fields [Date] :due A date, or `nil`.
  # @option fields [Boolean] :closed
  # @option fields [String] :url
  # @option fields [String] :short_url
  # @option fields [String] :board_id
  # @option fields [String] :member_ids A comma-separated list of objectIds
  #     (24-character hex strings).
  # @option fields [String] :pos A position. `"top"`, `"bottom"`, or a
  #     positive number. Defaults to `"bottom"`.
  # @option fields [String] :card_labels A comma-separated list of
  #     objectIds (24-character hex strings).
  # @option fields [Object] :cover_image_id
  # @option fields [Object] :badges
  # @option fields [Object] :card_members
  #
  # @return [Trello::Card] self
  def update_fields(fields)
    attributes[:id]                 = fields[SYMBOL_TO_STRING[:id]]
    attributes[:short_id]           = fields[SYMBOL_TO_STRING[:short_id]]
    attributes[:name]               = fields[SYMBOL_TO_STRING[:name]]
    attributes[:desc]               = fields[SYMBOL_TO_STRING[:desc]]
    attributes[:due]                = Time.iso8601(fields[SYMBOL_TO_STRING[:due]]) rescue nil
    attributes[:closed]             = fields[SYMBOL_TO_STRING[:closed]]
    attributes[:url]                = fields[SYMBOL_TO_STRING[:url]]
    attributes[:short_url]          = fields[SYMBOL_TO_STRING[:short_url]]
    attributes[:board_id]           = fields[SYMBOL_TO_STRING[:board_id]]
    attributes[:member_ids]         = fields[SYMBOL_TO_STRING[:member_ids]]
    attributes[:list_id]            = fields[SYMBOL_TO_STRING[:list_id]]
    attributes[:pos]                = fields[SYMBOL_TO_STRING[:pos]]
    attributes[:card_labels]        = fields[SYMBOL_TO_STRING[:card_labels]]
    attributes[:last_activity_date] = Time.iso8601(fields[SYMBOL_TO_STRING[:last_activity_date]]) rescue nil
    attributes[:cover_image_id]     = fields[SYMBOL_TO_STRING[:cover_image_id]]
    attributes[:badges]             = fields[SYMBOL_TO_STRING[:badges]]
    attributes[:card_members]       = fields[SYMBOL_TO_STRING[:card_members]]
    self
  end

  # Returns a reference to the board this card is part of.
  one :board, path: :boards, using: :board_id
  # Returns a reference to the cover image attachment
  one :cover_image, path: :attachments, using: :cover_image_id

  # Returns a list of checklists associated with the card.
  #
  # The options hash may have a filter key which can have its value set as any
  # of the following values:
  #    :filter => [ :none, :all ] # default :all
  many :checklists, filter: :all

  def check_item_states
    states = client.get("/cards/#{self.id}/checkItemStates").json_into(CheckItemState)
    MultiAssociation.new(self, states).proxy
  end

  many :labels
  
  # Returns a reference to the list this card is currently in.
  one :list, path: :lists, using: :list_id

  # Returns a list of members who are assigned to this card.
  #
  # @return [Array<Trello::Member>]
  def members
    members = member_ids.map do |member_id|
      client.get("/members/#{member_id}").json_into(Member)
    end
    MultiAssociation.new(self, members).proxy
  end

  # Saves a record.
  #
  # @raise [Trello::Error] if the card could not be saved
  #
  # @return [String] The JSON representation of the saved card returned by
  #     the Trello API.
  def save
    # If we have an id, just update our fields.
    return update! if id

    client.post("/cards", {
      name:   name,
      desc:   desc,
      idList: list_id,
      idMembers: member_ids,
      labels: card_labels,
      pos: pos,
      due: due
    }).json_into(self)
  end

  # Update an existing record.
  #
  # Warning: this updates all fields using values already in memory. If
  # an external resource has updated these fields, you should refresh!
  # this object before making your changes, and before updating the record.
  #
  # @raise [Trello::Error] if the card could not be updated.
  #
  # @return [String] The JSON representation of the updated card returned by
  #     the Trello API.
  def update!
    @previously_changed = changes
    # extract only new values to build payload
    payload = Hash[changes.map { |key, values| [SYMBOL_TO_STRING[key.to_sym].to_sym, values[1]] }]
    @changed_attributes.clear

    client.put("/cards/#{id}", payload)
  end


  # Delete this card
  #
  # @return [String] the JSON response from the Trello API
  def delete
    client.delete("/cards/#{id}")
  end

  # Check if the card is not active anymore.
  def closed?
    closed
  end

  # Close the card.
  #
  # This only marks your local copy card as closed. Use `close!` if you
  # want to close the card and persist the change to the Trello API.
  #
  # @return [Boolean] always returns true
  #
  # @return [String] The JSON representation of the closed card returned by
  #     the Trello API.
  def close
    self.closed = true
  end

  def close!
    close
    save
  end

  # Is the record valid?
  def valid?
    name && list_id
  end

  # Add a comment with the supplied text.
  def add_comment(text)
    client.post("/cards/#{id}/actions/comments", text: text)
  end

  # Add a checklist to this card
  def add_checklist(checklist)
    client.post("/cards/#{id}/checklists", {
      value: checklist.id
    })
  end

  # create a new checklist and add it to this card
  def create_new_checklist(name)
    client.post("/cards/#{id}/checklists", { name: name })
  end

  # Move this card to the given list
  def move_to_list(list)
    list_number = list.is_a?(String) ? list : list.id
    unless list_id == list_number
      client.put("/cards/#{id}/idList", {
        value: list_number
      })
    end
  end

  # Move this card to the given board (and optional list on this board)
  def move_to_board(new_board, new_list = nil)
    unless board_id == new_board.id
      payload = { value: new_board.id }
      payload[:idList] = new_list.id if new_list
      client.put("/cards/#{id}/idBoard", payload)
    end
  end

  # Add a member to this card
  def add_member(member)
    client.post("/cards/#{id}/members", {
      value: member.id
    })
  end

  # Remove a member from this card
  def remove_member(member)
    client.delete("/cards/#{id}/members/#{member.id}")
  end
  
  # Add a label
  def add_label(label)
    unless label.valid?
      errors.add(:label, "is not valid.")
      return Trello.logger.warn "Label is not valid." unless label.valid?
    end
    client.post("/cards/#{id}/idLabels", {value: label.id})
  end

  # Remove a label
  def remove_label(label)
      unless label.valid?
        errors.add(:label, "is not valid.")
        return Trello.logger.warn "Label is not valid." unless label.valid?
      end
      client.delete("/cards/#{id}/idLabels/#{label.id}")
  end

  # Add an attachment to this card
  def add_attachment(attachment, name='')
    if attachment.is_a? File
      client.post("/cards/#{id}/attachments", {
          file: attachment,
          name: name
        })
    else
      client.post("/cards/#{id}/attachments", {
          url: attachment,
          name: name
        })
    end
  end

  # Retrieve a list of attachments
  def attachments
    attachments = client.get("/cards/#{id}/attachments").json_into(Attachment)
    MultiAssociation.new(self, attachments).proxy
  end

  # Remove an attachment from this card
  def remove_attachment(attachment)
    client.delete("/cards/#{id}/attachments/#{attachment.id}")
  end

  # :nodoc:
  def request_prefix
    "/cards/#{id}"
  end
end

#posFloat

Returns:

  • (Float)


38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
# File 'lib/trello/card.rb', line 38

class Card < BasicData
  register_attributes :id, :short_id, :name, :desc, :due, :closed, :url, :short_url,
    :board_id, :member_ids, :list_id, :pos, :last_activity_date, :card_labels,
    :cover_image_id, :badges, :card_members,
    readonly: [ :id, :short_id, :url, :short_url, :last_activity_date, :badges, :card_members ]
  validates_presence_of :id, :name, :list_id
  validates_length_of   :name,        in: 1..16384
  validates_length_of   :desc, in: 0..16384

  include HasActions

  SYMBOL_TO_STRING = {
    id: 'id',
    short_id: 'idShort',
    name: 'name',
    desc: 'desc',
    due: 'due',
    closed: 'closed',
    url: 'url',
    short_url: 'shortUrl',
    board_id: 'idBoard',
    member_ids: 'idMembers',
    cover_image_id: 'idAttachmentCover',
    list_id: 'idList',
    pos: 'pos',
    last_activity_date: 'dateLastActivity',
    card_labels: 'labels',
    badges: 'badges',
    card_members: 'members'
  }

  class << self
    # Find a specific card by its id.
    #
    # @raise [Trello::Error] if the card could not be found.
    #
    # @return [Trello::Card]
    def find(id, params = {})
      client.find(:card, id, params)
    end

    # Create a new card and save it on Trello.
    #
    # @param [Hash] options # @option options [String] :name The name of the new card.
    # @option options [String] :list_id ID of the list that the card should
    #     be added to.
    # @option options [String] :desc A string with a
    #     length from 0 to 16384.
    # @option options [String] :member_ids A comma-separated list of
    #     objectIds (24-character hex strings).
    # @option options [String] :card_labels A comma-separated list of
    #     objectIds (24-character hex strings).
    # @option options [Date] :due A date, or `nil`.
    # @option options [String] :pos A position. `"top"`, `"bottom"`, or a
    #     positive number. Defaults to `"bottom"`.
    #
    # @raise [Trello::Error] if the card could not be created.
    #
    # @return [Trello::Card]
    def create(options)
      client.create(:card,
        'name' => options[:name],
        'idList' => options[:list_id],
        'desc'   => options[:desc],
        'idMembers' => options[:member_ids],
        'labels' => options[:card_labels],
        'due' => options[:due],
        'pos' => options[:pos]
      )
    end
  end

  # Update the fields of a card.
  #
  # Supply a hash of string keyed data retrieved from the Trello API representing
  # a card.
  #
  # Note that this this method does not save anything new to the Trello API,
  # it just assigns the input attributes to your local object. If you use
  # this method to assign attributes, call `save` or `update!` afterwards if
  # you want to persist your changes to Trello.
  #
  # @param [Hash] fields
  # @option fields [String] :id
  # @option fields [String] :short_id
  # @option fields [String] :name The new name of the card.
  # @option fields [String] :desc A string with a length from 0 to
  #     16384.
  # @option fields [Date] :due A date, or `nil`.
  # @option fields [Boolean] :closed
  # @option fields [String] :url
  # @option fields [String] :short_url
  # @option fields [String] :board_id
  # @option fields [String] :member_ids A comma-separated list of objectIds
  #     (24-character hex strings).
  # @option fields [String] :pos A position. `"top"`, `"bottom"`, or a
  #     positive number. Defaults to `"bottom"`.
  # @option fields [String] :card_labels A comma-separated list of
  #     objectIds (24-character hex strings).
  # @option fields [Object] :cover_image_id
  # @option fields [Object] :badges
  # @option fields [Object] :card_members
  #
  # @return [Trello::Card] self
  def update_fields(fields)
    attributes[:id]                 = fields[SYMBOL_TO_STRING[:id]]
    attributes[:short_id]           = fields[SYMBOL_TO_STRING[:short_id]]
    attributes[:name]               = fields[SYMBOL_TO_STRING[:name]]
    attributes[:desc]               = fields[SYMBOL_TO_STRING[:desc]]
    attributes[:due]                = Time.iso8601(fields[SYMBOL_TO_STRING[:due]]) rescue nil
    attributes[:closed]             = fields[SYMBOL_TO_STRING[:closed]]
    attributes[:url]                = fields[SYMBOL_TO_STRING[:url]]
    attributes[:short_url]          = fields[SYMBOL_TO_STRING[:short_url]]
    attributes[:board_id]           = fields[SYMBOL_TO_STRING[:board_id]]
    attributes[:member_ids]         = fields[SYMBOL_TO_STRING[:member_ids]]
    attributes[:list_id]            = fields[SYMBOL_TO_STRING[:list_id]]
    attributes[:pos]                = fields[SYMBOL_TO_STRING[:pos]]
    attributes[:card_labels]        = fields[SYMBOL_TO_STRING[:card_labels]]
    attributes[:last_activity_date] = Time.iso8601(fields[SYMBOL_TO_STRING[:last_activity_date]]) rescue nil
    attributes[:cover_image_id]     = fields[SYMBOL_TO_STRING[:cover_image_id]]
    attributes[:badges]             = fields[SYMBOL_TO_STRING[:badges]]
    attributes[:card_members]       = fields[SYMBOL_TO_STRING[:card_members]]
    self
  end

  # Returns a reference to the board this card is part of.
  one :board, path: :boards, using: :board_id
  # Returns a reference to the cover image attachment
  one :cover_image, path: :attachments, using: :cover_image_id

  # Returns a list of checklists associated with the card.
  #
  # The options hash may have a filter key which can have its value set as any
  # of the following values:
  #    :filter => [ :none, :all ] # default :all
  many :checklists, filter: :all

  def check_item_states
    states = client.get("/cards/#{self.id}/checkItemStates").json_into(CheckItemState)
    MultiAssociation.new(self, states).proxy
  end

  many :labels
  
  # Returns a reference to the list this card is currently in.
  one :list, path: :lists, using: :list_id

  # Returns a list of members who are assigned to this card.
  #
  # @return [Array<Trello::Member>]
  def members
    members = member_ids.map do |member_id|
      client.get("/members/#{member_id}").json_into(Member)
    end
    MultiAssociation.new(self, members).proxy
  end

  # Saves a record.
  #
  # @raise [Trello::Error] if the card could not be saved
  #
  # @return [String] The JSON representation of the saved card returned by
  #     the Trello API.
  def save
    # If we have an id, just update our fields.
    return update! if id

    client.post("/cards", {
      name:   name,
      desc:   desc,
      idList: list_id,
      idMembers: member_ids,
      labels: card_labels,
      pos: pos,
      due: due
    }).json_into(self)
  end

  # Update an existing record.
  #
  # Warning: this updates all fields using values already in memory. If
  # an external resource has updated these fields, you should refresh!
  # this object before making your changes, and before updating the record.
  #
  # @raise [Trello::Error] if the card could not be updated.
  #
  # @return [String] The JSON representation of the updated card returned by
  #     the Trello API.
  def update!
    @previously_changed = changes
    # extract only new values to build payload
    payload = Hash[changes.map { |key, values| [SYMBOL_TO_STRING[key.to_sym].to_sym, values[1]] }]
    @changed_attributes.clear

    client.put("/cards/#{id}", payload)
  end


  # Delete this card
  #
  # @return [String] the JSON response from the Trello API
  def delete
    client.delete("/cards/#{id}")
  end

  # Check if the card is not active anymore.
  def closed?
    closed
  end

  # Close the card.
  #
  # This only marks your local copy card as closed. Use `close!` if you
  # want to close the card and persist the change to the Trello API.
  #
  # @return [Boolean] always returns true
  #
  # @return [String] The JSON representation of the closed card returned by
  #     the Trello API.
  def close
    self.closed = true
  end

  def close!
    close
    save
  end

  # Is the record valid?
  def valid?
    name && list_id
  end

  # Add a comment with the supplied text.
  def add_comment(text)
    client.post("/cards/#{id}/actions/comments", text: text)
  end

  # Add a checklist to this card
  def add_checklist(checklist)
    client.post("/cards/#{id}/checklists", {
      value: checklist.id
    })
  end

  # create a new checklist and add it to this card
  def create_new_checklist(name)
    client.post("/cards/#{id}/checklists", { name: name })
  end

  # Move this card to the given list
  def move_to_list(list)
    list_number = list.is_a?(String) ? list : list.id
    unless list_id == list_number
      client.put("/cards/#{id}/idList", {
        value: list_number
      })
    end
  end

  # Move this card to the given board (and optional list on this board)
  def move_to_board(new_board, new_list = nil)
    unless board_id == new_board.id
      payload = { value: new_board.id }
      payload[:idList] = new_list.id if new_list
      client.put("/cards/#{id}/idBoard", payload)
    end
  end

  # Add a member to this card
  def add_member(member)
    client.post("/cards/#{id}/members", {
      value: member.id
    })
  end

  # Remove a member from this card
  def remove_member(member)
    client.delete("/cards/#{id}/members/#{member.id}")
  end
  
  # Add a label
  def add_label(label)
    unless label.valid?
      errors.add(:label, "is not valid.")
      return Trello.logger.warn "Label is not valid." unless label.valid?
    end
    client.post("/cards/#{id}/idLabels", {value: label.id})
  end

  # Remove a label
  def remove_label(label)
      unless label.valid?
        errors.add(:label, "is not valid.")
        return Trello.logger.warn "Label is not valid." unless label.valid?
      end
      client.delete("/cards/#{id}/idLabels/#{label.id}")
  end

  # Add an attachment to this card
  def add_attachment(attachment, name='')
    if attachment.is_a? File
      client.post("/cards/#{id}/attachments", {
          file: attachment,
          name: name
        })
    else
      client.post("/cards/#{id}/attachments", {
          url: attachment,
          name: name
        })
    end
  end

  # Retrieve a list of attachments
  def attachments
    attachments = client.get("/cards/#{id}/attachments").json_into(Attachment)
    MultiAssociation.new(self, attachments).proxy
  end

  # Remove an attachment from this card
  def remove_attachment(attachment)
    client.delete("/cards/#{id}/attachments/#{attachment.id}")
  end

  # :nodoc:
  def request_prefix
    "/cards/#{id}"
  end
end

#short_idFixnum (readonly)

Returns:

  • (Fixnum)


38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
# File 'lib/trello/card.rb', line 38

class Card < BasicData
  register_attributes :id, :short_id, :name, :desc, :due, :closed, :url, :short_url,
    :board_id, :member_ids, :list_id, :pos, :last_activity_date, :card_labels,
    :cover_image_id, :badges, :card_members,
    readonly: [ :id, :short_id, :url, :short_url, :last_activity_date, :badges, :card_members ]
  validates_presence_of :id, :name, :list_id
  validates_length_of   :name,        in: 1..16384
  validates_length_of   :desc, in: 0..16384

  include HasActions

  SYMBOL_TO_STRING = {
    id: 'id',
    short_id: 'idShort',
    name: 'name',
    desc: 'desc',
    due: 'due',
    closed: 'closed',
    url: 'url',
    short_url: 'shortUrl',
    board_id: 'idBoard',
    member_ids: 'idMembers',
    cover_image_id: 'idAttachmentCover',
    list_id: 'idList',
    pos: 'pos',
    last_activity_date: 'dateLastActivity',
    card_labels: 'labels',
    badges: 'badges',
    card_members: 'members'
  }

  class << self
    # Find a specific card by its id.
    #
    # @raise [Trello::Error] if the card could not be found.
    #
    # @return [Trello::Card]
    def find(id, params = {})
      client.find(:card, id, params)
    end

    # Create a new card and save it on Trello.
    #
    # @param [Hash] options # @option options [String] :name The name of the new card.
    # @option options [String] :list_id ID of the list that the card should
    #     be added to.
    # @option options [String] :desc A string with a
    #     length from 0 to 16384.
    # @option options [String] :member_ids A comma-separated list of
    #     objectIds (24-character hex strings).
    # @option options [String] :card_labels A comma-separated list of
    #     objectIds (24-character hex strings).
    # @option options [Date] :due A date, or `nil`.
    # @option options [String] :pos A position. `"top"`, `"bottom"`, or a
    #     positive number. Defaults to `"bottom"`.
    #
    # @raise [Trello::Error] if the card could not be created.
    #
    # @return [Trello::Card]
    def create(options)
      client.create(:card,
        'name' => options[:name],
        'idList' => options[:list_id],
        'desc'   => options[:desc],
        'idMembers' => options[:member_ids],
        'labels' => options[:card_labels],
        'due' => options[:due],
        'pos' => options[:pos]
      )
    end
  end

  # Update the fields of a card.
  #
  # Supply a hash of string keyed data retrieved from the Trello API representing
  # a card.
  #
  # Note that this this method does not save anything new to the Trello API,
  # it just assigns the input attributes to your local object. If you use
  # this method to assign attributes, call `save` or `update!` afterwards if
  # you want to persist your changes to Trello.
  #
  # @param [Hash] fields
  # @option fields [String] :id
  # @option fields [String] :short_id
  # @option fields [String] :name The new name of the card.
  # @option fields [String] :desc A string with a length from 0 to
  #     16384.
  # @option fields [Date] :due A date, or `nil`.
  # @option fields [Boolean] :closed
  # @option fields [String] :url
  # @option fields [String] :short_url
  # @option fields [String] :board_id
  # @option fields [String] :member_ids A comma-separated list of objectIds
  #     (24-character hex strings).
  # @option fields [String] :pos A position. `"top"`, `"bottom"`, or a
  #     positive number. Defaults to `"bottom"`.
  # @option fields [String] :card_labels A comma-separated list of
  #     objectIds (24-character hex strings).
  # @option fields [Object] :cover_image_id
  # @option fields [Object] :badges
  # @option fields [Object] :card_members
  #
  # @return [Trello::Card] self
  def update_fields(fields)
    attributes[:id]                 = fields[SYMBOL_TO_STRING[:id]]
    attributes[:short_id]           = fields[SYMBOL_TO_STRING[:short_id]]
    attributes[:name]               = fields[SYMBOL_TO_STRING[:name]]
    attributes[:desc]               = fields[SYMBOL_TO_STRING[:desc]]
    attributes[:due]                = Time.iso8601(fields[SYMBOL_TO_STRING[:due]]) rescue nil
    attributes[:closed]             = fields[SYMBOL_TO_STRING[:closed]]
    attributes[:url]                = fields[SYMBOL_TO_STRING[:url]]
    attributes[:short_url]          = fields[SYMBOL_TO_STRING[:short_url]]
    attributes[:board_id]           = fields[SYMBOL_TO_STRING[:board_id]]
    attributes[:member_ids]         = fields[SYMBOL_TO_STRING[:member_ids]]
    attributes[:list_id]            = fields[SYMBOL_TO_STRING[:list_id]]
    attributes[:pos]                = fields[SYMBOL_TO_STRING[:pos]]
    attributes[:card_labels]        = fields[SYMBOL_TO_STRING[:card_labels]]
    attributes[:last_activity_date] = Time.iso8601(fields[SYMBOL_TO_STRING[:last_activity_date]]) rescue nil
    attributes[:cover_image_id]     = fields[SYMBOL_TO_STRING[:cover_image_id]]
    attributes[:badges]             = fields[SYMBOL_TO_STRING[:badges]]
    attributes[:card_members]       = fields[SYMBOL_TO_STRING[:card_members]]
    self
  end

  # Returns a reference to the board this card is part of.
  one :board, path: :boards, using: :board_id
  # Returns a reference to the cover image attachment
  one :cover_image, path: :attachments, using: :cover_image_id

  # Returns a list of checklists associated with the card.
  #
  # The options hash may have a filter key which can have its value set as any
  # of the following values:
  #    :filter => [ :none, :all ] # default :all
  many :checklists, filter: :all

  def check_item_states
    states = client.get("/cards/#{self.id}/checkItemStates").json_into(CheckItemState)
    MultiAssociation.new(self, states).proxy
  end

  many :labels
  
  # Returns a reference to the list this card is currently in.
  one :list, path: :lists, using: :list_id

  # Returns a list of members who are assigned to this card.
  #
  # @return [Array<Trello::Member>]
  def members
    members = member_ids.map do |member_id|
      client.get("/members/#{member_id}").json_into(Member)
    end
    MultiAssociation.new(self, members).proxy
  end

  # Saves a record.
  #
  # @raise [Trello::Error] if the card could not be saved
  #
  # @return [String] The JSON representation of the saved card returned by
  #     the Trello API.
  def save
    # If we have an id, just update our fields.
    return update! if id

    client.post("/cards", {
      name:   name,
      desc:   desc,
      idList: list_id,
      idMembers: member_ids,
      labels: card_labels,
      pos: pos,
      due: due
    }).json_into(self)
  end

  # Update an existing record.
  #
  # Warning: this updates all fields using values already in memory. If
  # an external resource has updated these fields, you should refresh!
  # this object before making your changes, and before updating the record.
  #
  # @raise [Trello::Error] if the card could not be updated.
  #
  # @return [String] The JSON representation of the updated card returned by
  #     the Trello API.
  def update!
    @previously_changed = changes
    # extract only new values to build payload
    payload = Hash[changes.map { |key, values| [SYMBOL_TO_STRING[key.to_sym].to_sym, values[1]] }]
    @changed_attributes.clear

    client.put("/cards/#{id}", payload)
  end


  # Delete this card
  #
  # @return [String] the JSON response from the Trello API
  def delete
    client.delete("/cards/#{id}")
  end

  # Check if the card is not active anymore.
  def closed?
    closed
  end

  # Close the card.
  #
  # This only marks your local copy card as closed. Use `close!` if you
  # want to close the card and persist the change to the Trello API.
  #
  # @return [Boolean] always returns true
  #
  # @return [String] The JSON representation of the closed card returned by
  #     the Trello API.
  def close
    self.closed = true
  end

  def close!
    close
    save
  end

  # Is the record valid?
  def valid?
    name && list_id
  end

  # Add a comment with the supplied text.
  def add_comment(text)
    client.post("/cards/#{id}/actions/comments", text: text)
  end

  # Add a checklist to this card
  def add_checklist(checklist)
    client.post("/cards/#{id}/checklists", {
      value: checklist.id
    })
  end

  # create a new checklist and add it to this card
  def create_new_checklist(name)
    client.post("/cards/#{id}/checklists", { name: name })
  end

  # Move this card to the given list
  def move_to_list(list)
    list_number = list.is_a?(String) ? list : list.id
    unless list_id == list_number
      client.put("/cards/#{id}/idList", {
        value: list_number
      })
    end
  end

  # Move this card to the given board (and optional list on this board)
  def move_to_board(new_board, new_list = nil)
    unless board_id == new_board.id
      payload = { value: new_board.id }
      payload[:idList] = new_list.id if new_list
      client.put("/cards/#{id}/idBoard", payload)
    end
  end

  # Add a member to this card
  def add_member(member)
    client.post("/cards/#{id}/members", {
      value: member.id
    })
  end

  # Remove a member from this card
  def remove_member(member)
    client.delete("/cards/#{id}/members/#{member.id}")
  end
  
  # Add a label
  def add_label(label)
    unless label.valid?
      errors.add(:label, "is not valid.")
      return Trello.logger.warn "Label is not valid." unless label.valid?
    end
    client.post("/cards/#{id}/idLabels", {value: label.id})
  end

  # Remove a label
  def remove_label(label)
      unless label.valid?
        errors.add(:label, "is not valid.")
        return Trello.logger.warn "Label is not valid." unless label.valid?
      end
      client.delete("/cards/#{id}/idLabels/#{label.id}")
  end

  # Add an attachment to this card
  def add_attachment(attachment, name='')
    if attachment.is_a? File
      client.post("/cards/#{id}/attachments", {
          file: attachment,
          name: name
        })
    else
      client.post("/cards/#{id}/attachments", {
          url: attachment,
          name: name
        })
    end
  end

  # Retrieve a list of attachments
  def attachments
    attachments = client.get("/cards/#{id}/attachments").json_into(Attachment)
    MultiAssociation.new(self, attachments).proxy
  end

  # Remove an attachment from this card
  def remove_attachment(attachment)
    client.delete("/cards/#{id}/attachments/#{attachment.id}")
  end

  # :nodoc:
  def request_prefix
    "/cards/#{id}"
  end
end

#short_urlString (readonly)

Returns:



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
# File 'lib/trello/card.rb', line 38

class Card < BasicData
  register_attributes :id, :short_id, :name, :desc, :due, :closed, :url, :short_url,
    :board_id, :member_ids, :list_id, :pos, :last_activity_date, :card_labels,
    :cover_image_id, :badges, :card_members,
    readonly: [ :id, :short_id, :url, :short_url, :last_activity_date, :badges, :card_members ]
  validates_presence_of :id, :name, :list_id
  validates_length_of   :name,        in: 1..16384
  validates_length_of   :desc, in: 0..16384

  include HasActions

  SYMBOL_TO_STRING = {
    id: 'id',
    short_id: 'idShort',
    name: 'name',
    desc: 'desc',
    due: 'due',
    closed: 'closed',
    url: 'url',
    short_url: 'shortUrl',
    board_id: 'idBoard',
    member_ids: 'idMembers',
    cover_image_id: 'idAttachmentCover',
    list_id: 'idList',
    pos: 'pos',
    last_activity_date: 'dateLastActivity',
    card_labels: 'labels',
    badges: 'badges',
    card_members: 'members'
  }

  class << self
    # Find a specific card by its id.
    #
    # @raise [Trello::Error] if the card could not be found.
    #
    # @return [Trello::Card]
    def find(id, params = {})
      client.find(:card, id, params)
    end

    # Create a new card and save it on Trello.
    #
    # @param [Hash] options # @option options [String] :name The name of the new card.
    # @option options [String] :list_id ID of the list that the card should
    #     be added to.
    # @option options [String] :desc A string with a
    #     length from 0 to 16384.
    # @option options [String] :member_ids A comma-separated list of
    #     objectIds (24-character hex strings).
    # @option options [String] :card_labels A comma-separated list of
    #     objectIds (24-character hex strings).
    # @option options [Date] :due A date, or `nil`.
    # @option options [String] :pos A position. `"top"`, `"bottom"`, or a
    #     positive number. Defaults to `"bottom"`.
    #
    # @raise [Trello::Error] if the card could not be created.
    #
    # @return [Trello::Card]
    def create(options)
      client.create(:card,
        'name' => options[:name],
        'idList' => options[:list_id],
        'desc'   => options[:desc],
        'idMembers' => options[:member_ids],
        'labels' => options[:card_labels],
        'due' => options[:due],
        'pos' => options[:pos]
      )
    end
  end

  # Update the fields of a card.
  #
  # Supply a hash of string keyed data retrieved from the Trello API representing
  # a card.
  #
  # Note that this this method does not save anything new to the Trello API,
  # it just assigns the input attributes to your local object. If you use
  # this method to assign attributes, call `save` or `update!` afterwards if
  # you want to persist your changes to Trello.
  #
  # @param [Hash] fields
  # @option fields [String] :id
  # @option fields [String] :short_id
  # @option fields [String] :name The new name of the card.
  # @option fields [String] :desc A string with a length from 0 to
  #     16384.
  # @option fields [Date] :due A date, or `nil`.
  # @option fields [Boolean] :closed
  # @option fields [String] :url
  # @option fields [String] :short_url
  # @option fields [String] :board_id
  # @option fields [String] :member_ids A comma-separated list of objectIds
  #     (24-character hex strings).
  # @option fields [String] :pos A position. `"top"`, `"bottom"`, or a
  #     positive number. Defaults to `"bottom"`.
  # @option fields [String] :card_labels A comma-separated list of
  #     objectIds (24-character hex strings).
  # @option fields [Object] :cover_image_id
  # @option fields [Object] :badges
  # @option fields [Object] :card_members
  #
  # @return [Trello::Card] self
  def update_fields(fields)
    attributes[:id]                 = fields[SYMBOL_TO_STRING[:id]]
    attributes[:short_id]           = fields[SYMBOL_TO_STRING[:short_id]]
    attributes[:name]               = fields[SYMBOL_TO_STRING[:name]]
    attributes[:desc]               = fields[SYMBOL_TO_STRING[:desc]]
    attributes[:due]                = Time.iso8601(fields[SYMBOL_TO_STRING[:due]]) rescue nil
    attributes[:closed]             = fields[SYMBOL_TO_STRING[:closed]]
    attributes[:url]                = fields[SYMBOL_TO_STRING[:url]]
    attributes[:short_url]          = fields[SYMBOL_TO_STRING[:short_url]]
    attributes[:board_id]           = fields[SYMBOL_TO_STRING[:board_id]]
    attributes[:member_ids]         = fields[SYMBOL_TO_STRING[:member_ids]]
    attributes[:list_id]            = fields[SYMBOL_TO_STRING[:list_id]]
    attributes[:pos]                = fields[SYMBOL_TO_STRING[:pos]]
    attributes[:card_labels]        = fields[SYMBOL_TO_STRING[:card_labels]]
    attributes[:last_activity_date] = Time.iso8601(fields[SYMBOL_TO_STRING[:last_activity_date]]) rescue nil
    attributes[:cover_image_id]     = fields[SYMBOL_TO_STRING[:cover_image_id]]
    attributes[:badges]             = fields[SYMBOL_TO_STRING[:badges]]
    attributes[:card_members]       = fields[SYMBOL_TO_STRING[:card_members]]
    self
  end

  # Returns a reference to the board this card is part of.
  one :board, path: :boards, using: :board_id
  # Returns a reference to the cover image attachment
  one :cover_image, path: :attachments, using: :cover_image_id

  # Returns a list of checklists associated with the card.
  #
  # The options hash may have a filter key which can have its value set as any
  # of the following values:
  #    :filter => [ :none, :all ] # default :all
  many :checklists, filter: :all

  def check_item_states
    states = client.get("/cards/#{self.id}/checkItemStates").json_into(CheckItemState)
    MultiAssociation.new(self, states).proxy
  end

  many :labels
  
  # Returns a reference to the list this card is currently in.
  one :list, path: :lists, using: :list_id

  # Returns a list of members who are assigned to this card.
  #
  # @return [Array<Trello::Member>]
  def members
    members = member_ids.map do |member_id|
      client.get("/members/#{member_id}").json_into(Member)
    end
    MultiAssociation.new(self, members).proxy
  end

  # Saves a record.
  #
  # @raise [Trello::Error] if the card could not be saved
  #
  # @return [String] The JSON representation of the saved card returned by
  #     the Trello API.
  def save
    # If we have an id, just update our fields.
    return update! if id

    client.post("/cards", {
      name:   name,
      desc:   desc,
      idList: list_id,
      idMembers: member_ids,
      labels: card_labels,
      pos: pos,
      due: due
    }).json_into(self)
  end

  # Update an existing record.
  #
  # Warning: this updates all fields using values already in memory. If
  # an external resource has updated these fields, you should refresh!
  # this object before making your changes, and before updating the record.
  #
  # @raise [Trello::Error] if the card could not be updated.
  #
  # @return [String] The JSON representation of the updated card returned by
  #     the Trello API.
  def update!
    @previously_changed = changes
    # extract only new values to build payload
    payload = Hash[changes.map { |key, values| [SYMBOL_TO_STRING[key.to_sym].to_sym, values[1]] }]
    @changed_attributes.clear

    client.put("/cards/#{id}", payload)
  end


  # Delete this card
  #
  # @return [String] the JSON response from the Trello API
  def delete
    client.delete("/cards/#{id}")
  end

  # Check if the card is not active anymore.
  def closed?
    closed
  end

  # Close the card.
  #
  # This only marks your local copy card as closed. Use `close!` if you
  # want to close the card and persist the change to the Trello API.
  #
  # @return [Boolean] always returns true
  #
  # @return [String] The JSON representation of the closed card returned by
  #     the Trello API.
  def close
    self.closed = true
  end

  def close!
    close
    save
  end

  # Is the record valid?
  def valid?
    name && list_id
  end

  # Add a comment with the supplied text.
  def add_comment(text)
    client.post("/cards/#{id}/actions/comments", text: text)
  end

  # Add a checklist to this card
  def add_checklist(checklist)
    client.post("/cards/#{id}/checklists", {
      value: checklist.id
    })
  end

  # create a new checklist and add it to this card
  def create_new_checklist(name)
    client.post("/cards/#{id}/checklists", { name: name })
  end

  # Move this card to the given list
  def move_to_list(list)
    list_number = list.is_a?(String) ? list : list.id
    unless list_id == list_number
      client.put("/cards/#{id}/idList", {
        value: list_number
      })
    end
  end

  # Move this card to the given board (and optional list on this board)
  def move_to_board(new_board, new_list = nil)
    unless board_id == new_board.id
      payload = { value: new_board.id }
      payload[:idList] = new_list.id if new_list
      client.put("/cards/#{id}/idBoard", payload)
    end
  end

  # Add a member to this card
  def add_member(member)
    client.post("/cards/#{id}/members", {
      value: member.id
    })
  end

  # Remove a member from this card
  def remove_member(member)
    client.delete("/cards/#{id}/members/#{member.id}")
  end
  
  # Add a label
  def add_label(label)
    unless label.valid?
      errors.add(:label, "is not valid.")
      return Trello.logger.warn "Label is not valid." unless label.valid?
    end
    client.post("/cards/#{id}/idLabels", {value: label.id})
  end

  # Remove a label
  def remove_label(label)
      unless label.valid?
        errors.add(:label, "is not valid.")
        return Trello.logger.warn "Label is not valid." unless label.valid?
      end
      client.delete("/cards/#{id}/idLabels/#{label.id}")
  end

  # Add an attachment to this card
  def add_attachment(attachment, name='')
    if attachment.is_a? File
      client.post("/cards/#{id}/attachments", {
          file: attachment,
          name: name
        })
    else
      client.post("/cards/#{id}/attachments", {
          url: attachment,
          name: name
        })
    end
  end

  # Retrieve a list of attachments
  def attachments
    attachments = client.get("/cards/#{id}/attachments").json_into(Attachment)
    MultiAssociation.new(self, attachments).proxy
  end

  # Remove an attachment from this card
  def remove_attachment(attachment)
    client.delete("/cards/#{id}/attachments/#{attachment.id}")
  end

  # :nodoc:
  def request_prefix
    "/cards/#{id}"
  end
end

#urlString (readonly)

Returns:



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
# File 'lib/trello/card.rb', line 38

class Card < BasicData
  register_attributes :id, :short_id, :name, :desc, :due, :closed, :url, :short_url,
    :board_id, :member_ids, :list_id, :pos, :last_activity_date, :card_labels,
    :cover_image_id, :badges, :card_members,
    readonly: [ :id, :short_id, :url, :short_url, :last_activity_date, :badges, :card_members ]
  validates_presence_of :id, :name, :list_id
  validates_length_of   :name,        in: 1..16384
  validates_length_of   :desc, in: 0..16384

  include HasActions

  SYMBOL_TO_STRING = {
    id: 'id',
    short_id: 'idShort',
    name: 'name',
    desc: 'desc',
    due: 'due',
    closed: 'closed',
    url: 'url',
    short_url: 'shortUrl',
    board_id: 'idBoard',
    member_ids: 'idMembers',
    cover_image_id: 'idAttachmentCover',
    list_id: 'idList',
    pos: 'pos',
    last_activity_date: 'dateLastActivity',
    card_labels: 'labels',
    badges: 'badges',
    card_members: 'members'
  }

  class << self
    # Find a specific card by its id.
    #
    # @raise [Trello::Error] if the card could not be found.
    #
    # @return [Trello::Card]
    def find(id, params = {})
      client.find(:card, id, params)
    end

    # Create a new card and save it on Trello.
    #
    # @param [Hash] options # @option options [String] :name The name of the new card.
    # @option options [String] :list_id ID of the list that the card should
    #     be added to.
    # @option options [String] :desc A string with a
    #     length from 0 to 16384.
    # @option options [String] :member_ids A comma-separated list of
    #     objectIds (24-character hex strings).
    # @option options [String] :card_labels A comma-separated list of
    #     objectIds (24-character hex strings).
    # @option options [Date] :due A date, or `nil`.
    # @option options [String] :pos A position. `"top"`, `"bottom"`, or a
    #     positive number. Defaults to `"bottom"`.
    #
    # @raise [Trello::Error] if the card could not be created.
    #
    # @return [Trello::Card]
    def create(options)
      client.create(:card,
        'name' => options[:name],
        'idList' => options[:list_id],
        'desc'   => options[:desc],
        'idMembers' => options[:member_ids],
        'labels' => options[:card_labels],
        'due' => options[:due],
        'pos' => options[:pos]
      )
    end
  end

  # Update the fields of a card.
  #
  # Supply a hash of string keyed data retrieved from the Trello API representing
  # a card.
  #
  # Note that this this method does not save anything new to the Trello API,
  # it just assigns the input attributes to your local object. If you use
  # this method to assign attributes, call `save` or `update!` afterwards if
  # you want to persist your changes to Trello.
  #
  # @param [Hash] fields
  # @option fields [String] :id
  # @option fields [String] :short_id
  # @option fields [String] :name The new name of the card.
  # @option fields [String] :desc A string with a length from 0 to
  #     16384.
  # @option fields [Date] :due A date, or `nil`.
  # @option fields [Boolean] :closed
  # @option fields [String] :url
  # @option fields [String] :short_url
  # @option fields [String] :board_id
  # @option fields [String] :member_ids A comma-separated list of objectIds
  #     (24-character hex strings).
  # @option fields [String] :pos A position. `"top"`, `"bottom"`, or a
  #     positive number. Defaults to `"bottom"`.
  # @option fields [String] :card_labels A comma-separated list of
  #     objectIds (24-character hex strings).
  # @option fields [Object] :cover_image_id
  # @option fields [Object] :badges
  # @option fields [Object] :card_members
  #
  # @return [Trello::Card] self
  def update_fields(fields)
    attributes[:id]                 = fields[SYMBOL_TO_STRING[:id]]
    attributes[:short_id]           = fields[SYMBOL_TO_STRING[:short_id]]
    attributes[:name]               = fields[SYMBOL_TO_STRING[:name]]
    attributes[:desc]               = fields[SYMBOL_TO_STRING[:desc]]
    attributes[:due]                = Time.iso8601(fields[SYMBOL_TO_STRING[:due]]) rescue nil
    attributes[:closed]             = fields[SYMBOL_TO_STRING[:closed]]
    attributes[:url]                = fields[SYMBOL_TO_STRING[:url]]
    attributes[:short_url]          = fields[SYMBOL_TO_STRING[:short_url]]
    attributes[:board_id]           = fields[SYMBOL_TO_STRING[:board_id]]
    attributes[:member_ids]         = fields[SYMBOL_TO_STRING[:member_ids]]
    attributes[:list_id]            = fields[SYMBOL_TO_STRING[:list_id]]
    attributes[:pos]                = fields[SYMBOL_TO_STRING[:pos]]
    attributes[:card_labels]        = fields[SYMBOL_TO_STRING[:card_labels]]
    attributes[:last_activity_date] = Time.iso8601(fields[SYMBOL_TO_STRING[:last_activity_date]]) rescue nil
    attributes[:cover_image_id]     = fields[SYMBOL_TO_STRING[:cover_image_id]]
    attributes[:badges]             = fields[SYMBOL_TO_STRING[:badges]]
    attributes[:card_members]       = fields[SYMBOL_TO_STRING[:card_members]]
    self
  end

  # Returns a reference to the board this card is part of.
  one :board, path: :boards, using: :board_id
  # Returns a reference to the cover image attachment
  one :cover_image, path: :attachments, using: :cover_image_id

  # Returns a list of checklists associated with the card.
  #
  # The options hash may have a filter key which can have its value set as any
  # of the following values:
  #    :filter => [ :none, :all ] # default :all
  many :checklists, filter: :all

  def check_item_states
    states = client.get("/cards/#{self.id}/checkItemStates").json_into(CheckItemState)
    MultiAssociation.new(self, states).proxy
  end

  many :labels
  
  # Returns a reference to the list this card is currently in.
  one :list, path: :lists, using: :list_id

  # Returns a list of members who are assigned to this card.
  #
  # @return [Array<Trello::Member>]
  def members
    members = member_ids.map do |member_id|
      client.get("/members/#{member_id}").json_into(Member)
    end
    MultiAssociation.new(self, members).proxy
  end

  # Saves a record.
  #
  # @raise [Trello::Error] if the card could not be saved
  #
  # @return [String] The JSON representation of the saved card returned by
  #     the Trello API.
  def save
    # If we have an id, just update our fields.
    return update! if id

    client.post("/cards", {
      name:   name,
      desc:   desc,
      idList: list_id,
      idMembers: member_ids,
      labels: card_labels,
      pos: pos,
      due: due
    }).json_into(self)
  end

  # Update an existing record.
  #
  # Warning: this updates all fields using values already in memory. If
  # an external resource has updated these fields, you should refresh!
  # this object before making your changes, and before updating the record.
  #
  # @raise [Trello::Error] if the card could not be updated.
  #
  # @return [String] The JSON representation of the updated card returned by
  #     the Trello API.
  def update!
    @previously_changed = changes
    # extract only new values to build payload
    payload = Hash[changes.map { |key, values| [SYMBOL_TO_STRING[key.to_sym].to_sym, values[1]] }]
    @changed_attributes.clear

    client.put("/cards/#{id}", payload)
  end


  # Delete this card
  #
  # @return [String] the JSON response from the Trello API
  def delete
    client.delete("/cards/#{id}")
  end

  # Check if the card is not active anymore.
  def closed?
    closed
  end

  # Close the card.
  #
  # This only marks your local copy card as closed. Use `close!` if you
  # want to close the card and persist the change to the Trello API.
  #
  # @return [Boolean] always returns true
  #
  # @return [String] The JSON representation of the closed card returned by
  #     the Trello API.
  def close
    self.closed = true
  end

  def close!
    close
    save
  end

  # Is the record valid?
  def valid?
    name && list_id
  end

  # Add a comment with the supplied text.
  def add_comment(text)
    client.post("/cards/#{id}/actions/comments", text: text)
  end

  # Add a checklist to this card
  def add_checklist(checklist)
    client.post("/cards/#{id}/checklists", {
      value: checklist.id
    })
  end

  # create a new checklist and add it to this card
  def create_new_checklist(name)
    client.post("/cards/#{id}/checklists", { name: name })
  end

  # Move this card to the given list
  def move_to_list(list)
    list_number = list.is_a?(String) ? list : list.id
    unless list_id == list_number
      client.put("/cards/#{id}/idList", {
        value: list_number
      })
    end
  end

  # Move this card to the given board (and optional list on this board)
  def move_to_board(new_board, new_list = nil)
    unless board_id == new_board.id
      payload = { value: new_board.id }
      payload[:idList] = new_list.id if new_list
      client.put("/cards/#{id}/idBoard", payload)
    end
  end

  # Add a member to this card
  def add_member(member)
    client.post("/cards/#{id}/members", {
      value: member.id
    })
  end

  # Remove a member from this card
  def remove_member(member)
    client.delete("/cards/#{id}/members/#{member.id}")
  end
  
  # Add a label
  def add_label(label)
    unless label.valid?
      errors.add(:label, "is not valid.")
      return Trello.logger.warn "Label is not valid." unless label.valid?
    end
    client.post("/cards/#{id}/idLabels", {value: label.id})
  end

  # Remove a label
  def remove_label(label)
      unless label.valid?
        errors.add(:label, "is not valid.")
        return Trello.logger.warn "Label is not valid." unless label.valid?
      end
      client.delete("/cards/#{id}/idLabels/#{label.id}")
  end

  # Add an attachment to this card
  def add_attachment(attachment, name='')
    if attachment.is_a? File
      client.post("/cards/#{id}/attachments", {
          file: attachment,
          name: name
        })
    else
      client.post("/cards/#{id}/attachments", {
          url: attachment,
          name: name
        })
    end
  end

  # Retrieve a list of attachments
  def attachments
    attachments = client.get("/cards/#{id}/attachments").json_into(Attachment)
    MultiAssociation.new(self, attachments).proxy
  end

  # Remove an attachment from this card
  def remove_attachment(attachment)
    client.delete("/cards/#{id}/attachments/#{attachment.id}")
  end

  # :nodoc:
  def request_prefix
    "/cards/#{id}"
  end
end

Class Method Details

.create(options) ⇒ Trello::Card

Create a new card and save it on Trello.

Parameters:

  • options (Hash)

    # @option options [String] :name The name of the new card.

Options Hash (options):

  • :list_id (String)

    ID of the list that the card should be added to.

  • :desc (String)

    A string with a length from 0 to 16384.

  • :member_ids (String)

    A comma-separated list of objectIds (24-character hex strings).

  • :card_labels (String)

    A comma-separated list of objectIds (24-character hex strings).

  • :due (Date)

    A date, or ‘nil`.

  • :pos (String)

    A position. ‘“top”`, `“bottom”`, or a positive number. Defaults to `“bottom”`.

Returns:

Raises:



97
98
99
100
101
102
103
104
105
106
107
# File 'lib/trello/card.rb', line 97

def create(options)
  client.create(:card,
    'name' => options[:name],
    'idList' => options[:list_id],
    'desc'   => options[:desc],
    'idMembers' => options[:member_ids],
    'labels' => options[:card_labels],
    'due' => options[:due],
    'pos' => options[:pos]
  )
end

.find(id, params = {}) ⇒ Trello::Card

Find a specific card by its id.

Returns:

Raises:



75
76
77
# File 'lib/trello/card.rb', line 75

def find(id, params = {})
  client.find(:card, id, params)
end

Instance Method Details

#add_attachment(attachment, name = '') ⇒ Object

Add an attachment to this card



338
339
340
341
342
343
344
345
346
347
348
349
350
# File 'lib/trello/card.rb', line 338

def add_attachment(attachment, name='')
  if attachment.is_a? File
    client.post("/cards/#{id}/attachments", {
        file: attachment,
        name: name
      })
  else
    client.post("/cards/#{id}/attachments", {
        url: attachment,
        name: name
      })
  end
end

#add_checklist(checklist) ⇒ Object

Add a checklist to this card



277
278
279
280
281
# File 'lib/trello/card.rb', line 277

def add_checklist(checklist)
  client.post("/cards/#{id}/checklists", {
    value: checklist.id
  })
end

#add_comment(text) ⇒ Object

Add a comment with the supplied text.



272
273
274
# File 'lib/trello/card.rb', line 272

def add_comment(text)
  client.post("/cards/#{id}/actions/comments", text: text)
end

#add_label(label) ⇒ Object

Add a label



320
321
322
323
324
325
326
# File 'lib/trello/card.rb', line 320

def add_label(label)
  unless label.valid?
    errors.add(:label, "is not valid.")
    return Trello.logger.warn "Label is not valid." unless label.valid?
  end
  client.post("/cards/#{id}/idLabels", {value: label.id})
end

#add_member(member) ⇒ Object

Add a member to this card



308
309
310
311
312
# File 'lib/trello/card.rb', line 308

def add_member(member)
  client.post("/cards/#{id}/members", {
    value: member.id
  })
end

#attachmentsObject

Retrieve a list of attachments



353
354
355
356
# File 'lib/trello/card.rb', line 353

def attachments
  attachments = client.get("/cards/#{id}/attachments").json_into(Attachment)
  MultiAssociation.new(self, attachments).proxy
end

#check_item_statesObject



175
176
177
178
# File 'lib/trello/card.rb', line 175

def check_item_states
  states = client.get("/cards/#{self.id}/checkItemStates").json_into(CheckItemState)
  MultiAssociation.new(self, states).proxy
end

#closeBoolean, String

Close the card.

This only marks your local copy card as closed. Use ‘close!` if you want to close the card and persist the change to the Trello API.

Returns:

  • (Boolean)

    always returns true

  • (String)

    The JSON representation of the closed card returned by the Trello API.



257
258
259
# File 'lib/trello/card.rb', line 257

def close
  self.closed = true
end

#close!Object



261
262
263
264
# File 'lib/trello/card.rb', line 261

def close!
  close
  save
end

#closed?Boolean

Check if the card is not active anymore.

Returns:

  • (Boolean)


244
245
246
# File 'lib/trello/card.rb', line 244

def closed?
  closed
end

#create_new_checklist(name) ⇒ Object

create a new checklist and add it to this card



284
285
286
# File 'lib/trello/card.rb', line 284

def create_new_checklist(name)
  client.post("/cards/#{id}/checklists", { name: name })
end

#deleteString

Delete this card

Returns:

  • (String)

    the JSON response from the Trello API



239
240
241
# File 'lib/trello/card.rb', line 239

def delete
  client.delete("/cards/#{id}")
end

#membersArray<Trello::Member>

Returns a list of members who are assigned to this card.

Returns:



188
189
190
191
192
193
# File 'lib/trello/card.rb', line 188

def members
  members = member_ids.map do |member_id|
    client.get("/members/#{member_id}").json_into(Member)
  end
  MultiAssociation.new(self, members).proxy
end

#move_to_board(new_board, new_list = nil) ⇒ Object

Move this card to the given board (and optional list on this board)



299
300
301
302
303
304
305
# File 'lib/trello/card.rb', line 299

def move_to_board(new_board, new_list = nil)
  unless board_id == new_board.id
    payload = { value: new_board.id }
    payload[:idList] = new_list.id if new_list
    client.put("/cards/#{id}/idBoard", payload)
  end
end

#move_to_list(list) ⇒ Object

Move this card to the given list



289
290
291
292
293
294
295
296
# File 'lib/trello/card.rb', line 289

def move_to_list(list)
  list_number = list.is_a?(String) ? list : list.id
  unless list_id == list_number
    client.put("/cards/#{id}/idList", {
      value: list_number
    })
  end
end

#remove_attachment(attachment) ⇒ Object

Remove an attachment from this card



359
360
361
# File 'lib/trello/card.rb', line 359

def remove_attachment(attachment)
  client.delete("/cards/#{id}/attachments/#{attachment.id}")
end

#remove_label(label) ⇒ Object

Remove a label



329
330
331
332
333
334
335
# File 'lib/trello/card.rb', line 329

def remove_label(label)
    unless label.valid?
      errors.add(:label, "is not valid.")
      return Trello.logger.warn "Label is not valid." unless label.valid?
    end
    client.delete("/cards/#{id}/idLabels/#{label.id}")
end

#remove_member(member) ⇒ Object

Remove a member from this card



315
316
317
# File 'lib/trello/card.rb', line 315

def remove_member(member)
  client.delete("/cards/#{id}/members/#{member.id}")
end

#request_prefixObject

:nodoc:



364
365
366
# File 'lib/trello/card.rb', line 364

def request_prefix
  "/cards/#{id}"
end

#saveString

Saves a record.

Returns:

  • (String)

    The JSON representation of the saved card returned by the Trello API.

Raises:



201
202
203
204
205
206
207
208
209
210
211
212
213
214
# File 'lib/trello/card.rb', line 201

def save
  # If we have an id, just update our fields.
  return update! if id

  client.post("/cards", {
    name:   name,
    desc:   desc,
    idList: list_id,
    idMembers: member_ids,
    labels: card_labels,
    pos: pos,
    due: due
  }).json_into(self)
end

#update!String

Update an existing record.

Warning: this updates all fields using values already in memory. If an external resource has updated these fields, you should refresh! this object before making your changes, and before updating the record.

Returns:

  • (String)

    The JSON representation of the updated card returned by the Trello API.

Raises:



226
227
228
229
230
231
232
233
# File 'lib/trello/card.rb', line 226

def update!
  @previously_changed = changes
  # extract only new values to build payload
  payload = Hash[changes.map { |key, values| [SYMBOL_TO_STRING[key.to_sym].to_sym, values[1]] }]
  @changed_attributes.clear

  client.put("/cards/#{id}", payload)
end

#update_fields(fields) ⇒ Trello::Card

Update the fields of a card.

Supply a hash of string keyed data retrieved from the Trello API representing a card.

Note that this this method does not save anything new to the Trello API, it just assigns the input attributes to your local object. If you use this method to assign attributes, call ‘save` or `update!` afterwards if you want to persist your changes to Trello.

Parameters:

Options Hash (fields):

  • :id (String)
  • :short_id (String)
  • :name (String)

    The new name of the card.

  • :desc (String)

    A string with a length from 0 to 16384.

  • :due (Date)

    A date, or ‘nil`.

  • :closed (Boolean)
  • :url (String)
  • :short_url (String)
  • :board_id (String)
  • :member_ids (String)

    A comma-separated list of objectIds (24-character hex strings).

  • :pos (String)

    A position. ‘“top”`, `“bottom”`, or a positive number. Defaults to `“bottom”`.

  • :card_labels (String)

    A comma-separated list of objectIds (24-character hex strings).

  • :cover_image_id (Object)
  • :badges (Object)
  • :card_members (Object)

Returns:



142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/trello/card.rb', line 142

def update_fields(fields)
  attributes[:id]                 = fields[SYMBOL_TO_STRING[:id]]
  attributes[:short_id]           = fields[SYMBOL_TO_STRING[:short_id]]
  attributes[:name]               = fields[SYMBOL_TO_STRING[:name]]
  attributes[:desc]               = fields[SYMBOL_TO_STRING[:desc]]
  attributes[:due]                = Time.iso8601(fields[SYMBOL_TO_STRING[:due]]) rescue nil
  attributes[:closed]             = fields[SYMBOL_TO_STRING[:closed]]
  attributes[:url]                = fields[SYMBOL_TO_STRING[:url]]
  attributes[:short_url]          = fields[SYMBOL_TO_STRING[:short_url]]
  attributes[:board_id]           = fields[SYMBOL_TO_STRING[:board_id]]
  attributes[:member_ids]         = fields[SYMBOL_TO_STRING[:member_ids]]
  attributes[:list_id]            = fields[SYMBOL_TO_STRING[:list_id]]
  attributes[:pos]                = fields[SYMBOL_TO_STRING[:pos]]
  attributes[:card_labels]        = fields[SYMBOL_TO_STRING[:card_labels]]
  attributes[:last_activity_date] = Time.iso8601(fields[SYMBOL_TO_STRING[:last_activity_date]]) rescue nil
  attributes[:cover_image_id]     = fields[SYMBOL_TO_STRING[:cover_image_id]]
  attributes[:badges]             = fields[SYMBOL_TO_STRING[:badges]]
  attributes[:card_members]       = fields[SYMBOL_TO_STRING[:card_members]]
  self
end

#valid?Boolean

Is the record valid?

Returns:

  • (Boolean)


267
268
269
# File 'lib/trello/card.rb', line 267

def valid?
  name && list_id
end