ruby-trello 2.0.1 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/trello.rb +3 -0
- data/lib/trello/basic_data.rb +9 -1
- data/lib/trello/board.rb +3 -0
- data/lib/trello/card.rb +3 -0
- data/lib/trello/custom_field.rb +113 -0
- data/lib/trello/custom_field_item.rb +77 -0
- data/lib/trello/custom_field_option.rb +22 -0
- data/lib/trello/label.rb +2 -2
- data/spec/basic_data_spec.rb +58 -0
- data/spec/board_spec.rb +13 -0
- data/spec/card_spec.rb +36 -2
- data/spec/custom_field_item_spec.rb +118 -0
- data/spec/custom_field_option_spec.rb +49 -0
- data/spec/custom_field_spec.rb +185 -0
- data/spec/spec_helper.rb +48 -0
- metadata +14 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2971d7fb189328ae318b068c480ccb94824c8c85dbefed703a1837d839790144
|
4
|
+
data.tar.gz: ffdf9a6dac2e3adc9d69306d70c7a8b784cd1809e0ebab2a3bb4dd394d25a732
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4c7b7da985552a94069f359ea7e80200305e60ae1642f50541d28a412e8fe83b9dd8ca77594556435b0b7aac827eecf83d6ee5b8da378cbdfac635a42146694e
|
7
|
+
data.tar.gz: 230297498d5a1847802cc5a1a0a273222e75b2204554f2caed1b41549bf2942cedda5633156f414d108c384dfaaac8fa865d8520a7f16545105c6ee9adcc8aa9
|
data/lib/trello.rb
CHANGED
@@ -50,6 +50,9 @@ module Trello
|
|
50
50
|
autoload :Checklist, 'trello/checklist'
|
51
51
|
autoload :Client, 'trello/client'
|
52
52
|
autoload :Configuration, 'trello/configuration'
|
53
|
+
autoload :CustomField, 'trello/custom_field'
|
54
|
+
autoload :CustomFieldItem, 'trello/custom_field_item'
|
55
|
+
autoload :CustomFieldOption, 'trello/custom_field_option'
|
53
56
|
autoload :HasActions, 'trello/has_actions'
|
54
57
|
autoload :Item, 'trello/item'
|
55
58
|
autoload :CheckItemState, 'trello/item_state'
|
data/lib/trello/basic_data.rb
CHANGED
@@ -122,7 +122,15 @@ module Trello
|
|
122
122
|
|
123
123
|
# Two objects are equal if their _id_ methods are equal.
|
124
124
|
def ==(other)
|
125
|
-
id == other.id
|
125
|
+
self.class == other.class && id == other.id
|
126
|
+
end
|
127
|
+
|
128
|
+
# Alias hash equality to equality
|
129
|
+
alias eql? ==
|
130
|
+
|
131
|
+
# Delegate hash key computation to class and id pair
|
132
|
+
def hash
|
133
|
+
[self.class, id].hash
|
126
134
|
end
|
127
135
|
|
128
136
|
def client
|
data/lib/trello/board.rb
CHANGED
@@ -167,6 +167,9 @@ module Trello
|
|
167
167
|
# Returns a list of plugins associated with the board
|
168
168
|
many :plugin_data, path: "pluginData"
|
169
169
|
|
170
|
+
# Returns custom fields activated on this board
|
171
|
+
many :custom_fields, path: "customFields"
|
172
|
+
|
170
173
|
def labels(params = {})
|
171
174
|
# Set the limit to as high as possible given there is no pagination in this API.
|
172
175
|
params[:limit] = 1000 unless params[:limit]
|
data/lib/trello/card.rb
CHANGED
@@ -210,6 +210,9 @@ module Trello
|
|
210
210
|
# Returns a list of plugins associated with the card
|
211
211
|
many :plugin_data, path: "pluginData"
|
212
212
|
|
213
|
+
# List of custom field values on the card, only the ones that have been set
|
214
|
+
many :custom_field_items, path: 'customFieldItems'
|
215
|
+
|
213
216
|
def check_item_states
|
214
217
|
states = CheckItemState.from_response client.get("/cards/#{self.id}/checkItemStates")
|
215
218
|
MultiAssociation.new(self, states).proxy
|
@@ -0,0 +1,113 @@
|
|
1
|
+
module Trello
|
2
|
+
# A Custom Field can be activated on a board. Values are stored at the card level.
|
3
|
+
#
|
4
|
+
# @!attribute id
|
5
|
+
# @return [String]
|
6
|
+
# @!attribute model_id
|
7
|
+
# @return [String]
|
8
|
+
# @!attribute model_type
|
9
|
+
# @return [String]
|
10
|
+
# @!attribute field_group
|
11
|
+
# @return [String]
|
12
|
+
# @!attribute name
|
13
|
+
# @return [String]
|
14
|
+
# @!attribute pos
|
15
|
+
# @return [Float]
|
16
|
+
# @!attribute type
|
17
|
+
# @return [String]
|
18
|
+
# @!attribute options
|
19
|
+
# @return [Array<Hash>]
|
20
|
+
class CustomField < BasicData
|
21
|
+
register_attributes :id, :model_id, :model_type, :field_group, :name, :pos, :type
|
22
|
+
validates_presence_of :id, :model_id, :model_type, :name, :type, :pos
|
23
|
+
|
24
|
+
SYMBOL_TO_STRING = {
|
25
|
+
id: 'id',
|
26
|
+
name: 'name',
|
27
|
+
model_id: 'idModel',
|
28
|
+
model_type: 'modelType',
|
29
|
+
field_group: 'fieldGroup',
|
30
|
+
type: 'type',
|
31
|
+
pos: 'pos'
|
32
|
+
}
|
33
|
+
|
34
|
+
class << self
|
35
|
+
# Find a custom field by its id.
|
36
|
+
def find(id, params = {})
|
37
|
+
client.find('customFields', id, params)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Create a new custom field and save it on Trello.
|
41
|
+
def create(options)
|
42
|
+
client.create('customFields',
|
43
|
+
'name' => options[:name],
|
44
|
+
'idModel' => options[:model_id],
|
45
|
+
'modelType' => options[:model_type],
|
46
|
+
'fieldGroup' => options[:field_group],
|
47
|
+
'type' => options[:type],
|
48
|
+
'pos' => options[:pos]
|
49
|
+
)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# References Board where this custom field is located
|
54
|
+
# Currently, model_type will always be "board" at the customFields endpoint
|
55
|
+
one :board, path: :boards, using: :model_id
|
56
|
+
|
57
|
+
# If type == 'list'
|
58
|
+
many :custom_field_options, path: 'options'
|
59
|
+
|
60
|
+
def update_fields(fields)
|
61
|
+
attributes[:id] = fields[SYMBOL_TO_STRING[:id]] || fields[:id] || attributes[:id]
|
62
|
+
attributes[:name] = fields[SYMBOL_TO_STRING[:name]] || fields[:name] || attributes[:name]
|
63
|
+
attributes[:model_id] = fields[SYMBOL_TO_STRING[:model_id]] || fields[:model_id] || attributes[:model_id]
|
64
|
+
attributes[:model_type] = fields[SYMBOL_TO_STRING[:model_type]] || fields[:model_type] || attributes[:model_type]
|
65
|
+
attributes[:field_group] = fields[SYMBOL_TO_STRING[:field_group]] || fields[:field_group] || attributes[:field_group]
|
66
|
+
attributes[:type] = fields[SYMBOL_TO_STRING[:type]] || fields[:type] || attributes[:type]
|
67
|
+
attributes[:pos] = fields[SYMBOL_TO_STRING[:pos]] || fields[:pos] || attributes[:pos]
|
68
|
+
self
|
69
|
+
end
|
70
|
+
|
71
|
+
# Saves a record.
|
72
|
+
def save
|
73
|
+
# If we have an id, just update our fields.
|
74
|
+
return update! if id
|
75
|
+
|
76
|
+
from_response client.post("/customFields", {
|
77
|
+
name: name,
|
78
|
+
idModel: model_id,
|
79
|
+
modelType: model_type,
|
80
|
+
type: type,
|
81
|
+
pos: pos,
|
82
|
+
fieldGroup: field_group
|
83
|
+
})
|
84
|
+
end
|
85
|
+
|
86
|
+
# Update an existing custom field.
|
87
|
+
def update!
|
88
|
+
@previously_changed = changes
|
89
|
+
# extract only new values to build payload
|
90
|
+
payload = Hash[changes.map { |key, values| [SYMBOL_TO_STRING[key.to_sym].to_sym, values[1]] }]
|
91
|
+
@changed_attributes.clear
|
92
|
+
|
93
|
+
client.put("/customFields/#{id}", payload)
|
94
|
+
end
|
95
|
+
|
96
|
+
# Delete this custom field
|
97
|
+
# Also deletes all associated values across all cards
|
98
|
+
def delete
|
99
|
+
client.delete("/customFields/#{id}")
|
100
|
+
end
|
101
|
+
|
102
|
+
# If type == 'list', create a new option and add to this Custom Field
|
103
|
+
def create_new_option(value)
|
104
|
+
payload = { value: value }
|
105
|
+
client.post("/customFields/#{id}/options", payload)
|
106
|
+
end
|
107
|
+
|
108
|
+
# Will also clear it from individual cards that have this option selected
|
109
|
+
def delete_option(option_id)
|
110
|
+
client.delete("/customFields/#{id}/options/#{option_id}")
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module Trello
|
2
|
+
# A custom field item contains the value for a custom field on a particular card.
|
3
|
+
#
|
4
|
+
class CustomFieldItem < BasicData
|
5
|
+
register_attributes :id, :model_id, :model_type, :custom_field_id, :value, :option_id,
|
6
|
+
readonly: [ :id, :custom_field_id, :model_id, :model_type, :option_id ]
|
7
|
+
validates_presence_of :id, :model_id, :custom_field_id
|
8
|
+
|
9
|
+
# References the card with this custom field value
|
10
|
+
one :card, path: :cards, using: :model_id
|
11
|
+
|
12
|
+
# References the parent custom field that this item is an instance of
|
13
|
+
one :custom_field, path: 'customFields', using: :custom_field_id
|
14
|
+
|
15
|
+
# Update the fields of a custom field item.
|
16
|
+
#
|
17
|
+
# Supply a hash of string keyed data retrieved from the Trello API representing
|
18
|
+
# an item state.
|
19
|
+
def update_fields(fields)
|
20
|
+
attributes[:id] = fields['id'] || fields[:id] || attributes[:id]
|
21
|
+
attributes[:model_id] = fields['idModel'] || fields[:model_id] || attributes[:model_id]
|
22
|
+
attributes[:custom_field_id] = fields['idCustomField'] || fields[:custom_field_id] || attributes[:custom_field_id]
|
23
|
+
attributes[:model_type] = fields['modelType'] || fields[:model_type] || attributes[:model_type]
|
24
|
+
# Dropdown custom field items do not have a value, they have an ID that maps to
|
25
|
+
# a different endpoint to get the value
|
26
|
+
attributes[:option_id] = fields['idValue'] if fields.has_key?('idValue')
|
27
|
+
# value format: { "text": "hello world" }
|
28
|
+
attributes[:value] = fields['value'] if fields.has_key?('value')
|
29
|
+
self
|
30
|
+
end
|
31
|
+
|
32
|
+
def update!
|
33
|
+
@previously_changed = changes
|
34
|
+
# extract only new values to build payload
|
35
|
+
payload = Hash[changes.map { |key, values| [key.to_sym, values[1]] }]
|
36
|
+
@changed_attributes.clear
|
37
|
+
|
38
|
+
client.put("/card/#{model_id}/customField/#{custom_field_id}/item", payload)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Saves a record.
|
42
|
+
#
|
43
|
+
# @raise [Trello::Error] if the card could not be saved
|
44
|
+
#
|
45
|
+
# @return [String] The JSON representation of the saved custom field item returned by
|
46
|
+
# the Trello API.
|
47
|
+
def save
|
48
|
+
# If we have an id, just update our fields.
|
49
|
+
return update! if id
|
50
|
+
|
51
|
+
from_response client.post("/card/#{model_id}/customField/#{custom_field_id}/item", {
|
52
|
+
value: value
|
53
|
+
})
|
54
|
+
end
|
55
|
+
|
56
|
+
# You can't "delete" a custom field item, you can only clear the value
|
57
|
+
def remove
|
58
|
+
params = { value: {} }
|
59
|
+
client.put("/card/#{model_id}/customField/#{custom_field_id}/item", params)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Type is saved at the CustomField level
|
63
|
+
# Can equally be derived from :value, with a little parsing work: {"number": 42}
|
64
|
+
def type
|
65
|
+
custom_field.type
|
66
|
+
end
|
67
|
+
|
68
|
+
# Need to make another call to get the actual value if the custom field type == 'list'
|
69
|
+
def option_value
|
70
|
+
if option_id
|
71
|
+
option_endpoint = "/customFields/#{custom_field_id}/options/#{option_id}"
|
72
|
+
option = CustomFieldOption.from_response client.get(option_endpoint)
|
73
|
+
option.value
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Trello
|
2
|
+
# A custom field option contains the individual items in a custom field dropdown menu.
|
3
|
+
#
|
4
|
+
class CustomFieldOption < BasicData
|
5
|
+
register_attributes :id, :value, :pos, :color,
|
6
|
+
readonly: [:id]
|
7
|
+
validates_presence_of :id, :value
|
8
|
+
|
9
|
+
# Update the fields of a custom field option.
|
10
|
+
#
|
11
|
+
# Supply a hash of string keyed data retrieved from the Trello API representing
|
12
|
+
# an item state.
|
13
|
+
def update_fields(fields)
|
14
|
+
attributes[:id] = fields['_id'] || fields[:id] || attributes[:id]
|
15
|
+
attributes[:color] = fields['color'] || fields[:color] || attributes[:color]
|
16
|
+
attributes[:pos] = fields['pos'] || fields[:pos] || attributes[:pos]
|
17
|
+
# value format: { "text": "hello world" }
|
18
|
+
attributes[:value] = fields['value'] || fields[:value] || attributes[:value]
|
19
|
+
self
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/trello/label.rb
CHANGED
@@ -9,7 +9,7 @@ module Trello
|
|
9
9
|
class Label < BasicData
|
10
10
|
register_attributes :id, :name, :board_id, :uses,
|
11
11
|
readonly: [ :id, :uses, :board_id ]
|
12
|
-
validates_presence_of :id, :
|
12
|
+
validates_presence_of :id, :board_id, :name
|
13
13
|
validates_length_of :name, in: 1..16384
|
14
14
|
|
15
15
|
SYMBOL_TO_STRING = {
|
@@ -23,7 +23,7 @@ module Trello
|
|
23
23
|
class << self
|
24
24
|
VALID_LABEL_COLOURS = %w{green yellow orange red purple blue sky lime pink black} << ''
|
25
25
|
|
26
|
-
# Find a specific
|
26
|
+
# Find a specific label by its id.
|
27
27
|
def find(id, params = {})
|
28
28
|
client.find(:label, id, params)
|
29
29
|
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Trello
|
4
|
+
describe BasicData do
|
5
|
+
describe "equality" do
|
6
|
+
specify "two objects of the same type are equal if their id values are equal" do
|
7
|
+
data_object = Card.new('id' => 'abc123')
|
8
|
+
other_data_object = Card.new('id' => 'abc123')
|
9
|
+
|
10
|
+
expect(data_object).to eq(other_data_object)
|
11
|
+
end
|
12
|
+
|
13
|
+
specify "two object of the samy type are not equal if their id values are different" do
|
14
|
+
data_object = Card.new('id' => 'abc123')
|
15
|
+
other_data_object = Card.new('id' => 'def456')
|
16
|
+
|
17
|
+
expect(data_object).not_to eq(other_data_object)
|
18
|
+
end
|
19
|
+
|
20
|
+
specify "two object of different types are not equal even if their id values are equal" do
|
21
|
+
card = Card.new('id' => 'abc123')
|
22
|
+
list = List.new('id' => 'abc123')
|
23
|
+
|
24
|
+
expect(card.id).to eq(list.id)
|
25
|
+
expect(card).to_not eq(list)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "hash equality" do
|
30
|
+
specify "two objects of the same type point to the same hash key" do
|
31
|
+
data_object = Card.new('id' => 'abc123')
|
32
|
+
other_data_object = Card.new('id' => 'abc123')
|
33
|
+
|
34
|
+
hash = {data_object => 'one'}
|
35
|
+
|
36
|
+
expect(hash[other_data_object]).to eq('one')
|
37
|
+
end
|
38
|
+
|
39
|
+
specify "two object of the same type with different ids do not point to the same hash key" do
|
40
|
+
data_object = Card.new('id' => 'abc123')
|
41
|
+
other_data_object = Card.new('id' => 'def456')
|
42
|
+
|
43
|
+
hash = {data_object => 'one'}
|
44
|
+
|
45
|
+
expect(hash[other_data_object]).to be_nil
|
46
|
+
end
|
47
|
+
|
48
|
+
specify "two object of different types with same ids do not point to the same hash key" do
|
49
|
+
card = Card.new('id' => 'abc123')
|
50
|
+
list = List.new('id' => 'abc123')
|
51
|
+
|
52
|
+
hash = {card => 'one'}
|
53
|
+
|
54
|
+
expect(hash[list]).to be_nil
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
data/spec/board_spec.rb
CHANGED
@@ -251,6 +251,19 @@ module Trello
|
|
251
251
|
end
|
252
252
|
end
|
253
253
|
|
254
|
+
context "custom fields" do
|
255
|
+
before do
|
256
|
+
allow(client)
|
257
|
+
.to receive(:get)
|
258
|
+
.with("/boards/abcdef123456789123456789/customFields", {})
|
259
|
+
.and_return JSON.generate([custom_fields_details.first])
|
260
|
+
end
|
261
|
+
|
262
|
+
it "has custom fields" do
|
263
|
+
expect(board.custom_fields.count).to be > 0
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
254
267
|
it "is not closed" do
|
255
268
|
expect(board).not_to be_closed
|
256
269
|
end
|
data/spec/card_spec.rb
CHANGED
@@ -257,7 +257,6 @@ module Trello
|
|
257
257
|
expect(card.pos).to_not be_nil
|
258
258
|
end
|
259
259
|
|
260
|
-
|
261
260
|
it 'gets its creation time' do
|
262
261
|
expect(card.created_at).to be_kind_of Time
|
263
262
|
end
|
@@ -338,6 +337,41 @@ module Trello
|
|
338
337
|
end
|
339
338
|
end
|
340
339
|
|
340
|
+
context "custom field items" do
|
341
|
+
before do
|
342
|
+
allow(client)
|
343
|
+
.to receive(:get)
|
344
|
+
.with("/cards/abcdef123456789123456789/customFieldItems", {})
|
345
|
+
.and_return JSON.generate([custom_field_item_details])
|
346
|
+
end
|
347
|
+
|
348
|
+
it "has a list of custom field items" do
|
349
|
+
expect(card.custom_field_items.count).to be > 0
|
350
|
+
end
|
351
|
+
|
352
|
+
it "clears the custom field value on a card" do
|
353
|
+
params = { value: {} }
|
354
|
+
|
355
|
+
expect(client)
|
356
|
+
.to receive(:put)
|
357
|
+
.with("/card/abcdef123456789123456789/customField/abcdef123456789123456789/item", params)
|
358
|
+
|
359
|
+
card.custom_field_items.last.remove
|
360
|
+
end
|
361
|
+
|
362
|
+
it "updates a custom field value" do
|
363
|
+
payload = { value: { text: 'Test Text' } }
|
364
|
+
|
365
|
+
expect(client)
|
366
|
+
.to receive(:put)
|
367
|
+
.with("/card/abcdef123456789123456789/customField/abcdef123456789123456789/item", payload)
|
368
|
+
|
369
|
+
text_custom_field = card.custom_field_items.last
|
370
|
+
text_custom_field.value = { text: 'Test Text' }
|
371
|
+
text_custom_field.save
|
372
|
+
end
|
373
|
+
end
|
374
|
+
|
341
375
|
context "list" do
|
342
376
|
before do
|
343
377
|
allow(client)
|
@@ -345,6 +379,7 @@ module Trello
|
|
345
379
|
.with("/lists/abcdef123456789123456789", {})
|
346
380
|
.and_return JSON.generate(lists_details.first)
|
347
381
|
end
|
382
|
+
|
348
383
|
it 'has a list' do
|
349
384
|
expect(card.list).to_not be_nil
|
350
385
|
end
|
@@ -556,7 +591,6 @@ module Trello
|
|
556
591
|
end
|
557
592
|
end
|
558
593
|
|
559
|
-
|
560
594
|
context "comments" do
|
561
595
|
it "posts a comment" do
|
562
596
|
expect(client)
|
@@ -0,0 +1,118 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Trello
|
4
|
+
describe CustomFieldItem do
|
5
|
+
include Helpers
|
6
|
+
|
7
|
+
let(:text_field_details) {
|
8
|
+
{
|
9
|
+
'id' => 'abcdefgh12345678',
|
10
|
+
'value' => {"text" => "Low Priority"},
|
11
|
+
'idValue' => nil,
|
12
|
+
'idModel' => 'abc123',
|
13
|
+
'idCustomField' => 'abcd1234',
|
14
|
+
'modelType' => 'card'
|
15
|
+
}
|
16
|
+
}
|
17
|
+
|
18
|
+
let(:list_item_details) {
|
19
|
+
{
|
20
|
+
'id' => 'abcdefgh12345678',
|
21
|
+
'value' => nil,
|
22
|
+
'idValue' => 'abcde12345',
|
23
|
+
'idModel' => 'abc123',
|
24
|
+
'idCustomField' => 'abcd1234',
|
25
|
+
'modelType' => 'card'
|
26
|
+
}
|
27
|
+
}
|
28
|
+
|
29
|
+
let(:client) { Client.new }
|
30
|
+
let(:text_item) { CustomFieldItem.new(text_field_details) }
|
31
|
+
let(:list_item) { CustomFieldItem.new(list_item_details) }
|
32
|
+
|
33
|
+
it 'validates presence of id, model ID and custom field ID' do
|
34
|
+
invalid_item = CustomFieldItem.new
|
35
|
+
|
36
|
+
expect(invalid_item).to be_invalid
|
37
|
+
expect(invalid_item.errors).to include(:id)
|
38
|
+
expect(invalid_item.errors).to include(:model_id)
|
39
|
+
expect(invalid_item.errors).to include(:custom_field_id)
|
40
|
+
end
|
41
|
+
|
42
|
+
describe 'retrieve item fields' do
|
43
|
+
it 'gets its id' do
|
44
|
+
expect(text_item.id).to eq text_field_details['id']
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'gets its value' do
|
48
|
+
expect(text_item.value).to eq text_field_details['value']
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'gets its model type' do
|
52
|
+
expect(text_item.model_type).to eq text_field_details['modelType']
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'gets its model ID' do
|
56
|
+
expect(text_item.model_id).to eq text_field_details['idModel']
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'gets its custom field ID' do
|
60
|
+
expect(text_item.custom_field_id).to eq text_field_details['idCustomField']
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'has a value ID for list option' do
|
64
|
+
expect(list_item.option_id).to eq list_item_details['idValue']
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe 'list option' do
|
69
|
+
let(:client) { Trello.client }
|
70
|
+
|
71
|
+
before do
|
72
|
+
allow(client)
|
73
|
+
.to receive(:get)
|
74
|
+
.with("/customFields/#{list_item.custom_field_id}/options/#{list_item.option_id}")
|
75
|
+
.and_return JSON.generate(custom_field_option_details)
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'gets the value' do
|
79
|
+
expect(list_item.option_value).to_not be_nil
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe 'custom field' do
|
84
|
+
let(:client) { Trello.client }
|
85
|
+
|
86
|
+
before do
|
87
|
+
allow(client)
|
88
|
+
.to receive(:get)
|
89
|
+
.with("/customFields/abcd1234", {})
|
90
|
+
.and_return JSON.generate(custom_fields_details.first)
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'has a custom field' do
|
94
|
+
expect(text_item.custom_field).to be_a CustomField
|
95
|
+
expect(text_item.custom_field.name).to eq('Priority')
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'returns the custom field type' do
|
99
|
+
expect(text_item.type).to eq 'checkbox'
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
describe 'card' do
|
104
|
+
let(:client) { Trello.client }
|
105
|
+
|
106
|
+
before do
|
107
|
+
allow(client)
|
108
|
+
.to receive(:get)
|
109
|
+
.with("/cards/abc123", {})
|
110
|
+
.and_return JSON.generate(cards_details.first)
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'has a card' do
|
114
|
+
expect(text_item.card).to be_a Card
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Trello
|
4
|
+
describe CustomFieldOption do
|
5
|
+
include Helpers
|
6
|
+
|
7
|
+
let(:option) { CustomFieldOption.new(custom_field_option_details) }
|
8
|
+
|
9
|
+
it 'validates presence of value and id' do
|
10
|
+
invalid_option = CustomFieldOption.new
|
11
|
+
|
12
|
+
expect(invalid_option).to be_invalid
|
13
|
+
expect(invalid_option.errors).to include(:value)
|
14
|
+
expect(invalid_option.errors).to include(:id)
|
15
|
+
end
|
16
|
+
|
17
|
+
describe 'retrieve option fields' do
|
18
|
+
it 'gets its id' do
|
19
|
+
expect(option.id).to eq custom_field_option_details['_id']
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'gets its color' do
|
23
|
+
expect(option.color).to eq custom_field_option_details['color']
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'knows its value' do
|
27
|
+
expect(option.value).to eq custom_field_option_details['value']
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'gets its pos' do
|
31
|
+
expect(option.pos).to eq custom_field_option_details['pos']
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe 'update fields' do
|
36
|
+
it 'allows fields to be updated' do
|
37
|
+
updated = {
|
38
|
+
color: "purple",
|
39
|
+
value: { "text" => "Medium Priority" }
|
40
|
+
}
|
41
|
+
|
42
|
+
option.update_fields(updated)
|
43
|
+
|
44
|
+
expect(option.color).to eq "purple"
|
45
|
+
expect(option.value).to eq({"text" => "Medium Priority"})
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,185 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Trello
|
4
|
+
describe CustomField do
|
5
|
+
include Helpers
|
6
|
+
|
7
|
+
let(:custom_field) { client.find('customFields', 'abcdef123456789123456789') }
|
8
|
+
let(:client) { Client.new }
|
9
|
+
|
10
|
+
before do
|
11
|
+
allow(client)
|
12
|
+
.to receive(:get)
|
13
|
+
.with('/customFields/abcdef123456789123456789', {})
|
14
|
+
.and_return custom_fields_payload
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'creating' do
|
18
|
+
let(:client) { Trello.client }
|
19
|
+
|
20
|
+
it 'creates a new CustomField record' do
|
21
|
+
custom_fields_details.each do |details|
|
22
|
+
custom_field = CustomField.new(details)
|
23
|
+
expect(custom_field).to be_valid
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'properly initializes all fields from response-like formatted hash' do
|
28
|
+
custom_field_details = custom_fields_details.first
|
29
|
+
custom_field = CustomField.new(custom_field_details)
|
30
|
+
expect(custom_field.id).to eq(custom_field_details['id'])
|
31
|
+
expect(custom_field.name).to eq(custom_field_details['name'])
|
32
|
+
expect(custom_field.type).to eq(custom_field_details['type'])
|
33
|
+
expect(custom_field.pos).to eq(custom_field_details['pos'])
|
34
|
+
expect(custom_field.model_id).to eq(custom_field_details['idModel'])
|
35
|
+
expect(custom_field.model_type).to eq(custom_field_details['modelType'])
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'properly initializes all fields from options-like formatted hash' do
|
39
|
+
custom_field_details = custom_fields_details[1]
|
40
|
+
custom_field = CustomField.new(custom_field_details)
|
41
|
+
expect(custom_field.id).to eq(custom_field_details[:id])
|
42
|
+
expect(custom_field.name).to eq(custom_field_details[:name])
|
43
|
+
expect(custom_field.type).to eq(custom_field_details[:type])
|
44
|
+
expect(custom_field.pos).to eq(custom_field_details[:pos])
|
45
|
+
expect(custom_field.model_id).to eq(custom_field_details[:model_id])
|
46
|
+
expect(custom_field.model_type).to eq(custom_field_details[:model_type])
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'validates presence of id, name, model id, model type, type, and position' do
|
50
|
+
custom_field = CustomField.new
|
51
|
+
expect(custom_field).to_not be_valid
|
52
|
+
expect(custom_field.errors.count).to eq(6)
|
53
|
+
expect(custom_field.errors).to include(:name)
|
54
|
+
expect(custom_field.errors).to include(:id)
|
55
|
+
expect(custom_field.errors).to include(:model_id)
|
56
|
+
expect(custom_field.errors).to include(:model_type)
|
57
|
+
expect(custom_field.errors).to include(:pos)
|
58
|
+
expect(custom_field.errors).to include(:type)
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'creates a new record and saves it on Trello', refactor: true do
|
62
|
+
test_payload = {
|
63
|
+
name: 'Test Custom Field'
|
64
|
+
}
|
65
|
+
|
66
|
+
result = JSON.generate(custom_fields_details.first.merge(test_payload))
|
67
|
+
expected_payload = {name: 'Test Custom Field', type: 'checkbox', idModel: 'abc123',
|
68
|
+
modelType: 'board', pos: 123, fieldGroup: nil}
|
69
|
+
|
70
|
+
expect(client)
|
71
|
+
.to receive(:post)
|
72
|
+
.with('/customFields', expected_payload)
|
73
|
+
.and_return result
|
74
|
+
|
75
|
+
custom_field = CustomField.create(custom_fields_details[1].merge(test_payload))
|
76
|
+
expect(custom_field).to be_a CustomField
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
context 'finding' do
|
81
|
+
let(:client) { Trello.client }
|
82
|
+
|
83
|
+
before do
|
84
|
+
allow(client)
|
85
|
+
.to receive(:find)
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'delegates to Trello.client#find' do
|
89
|
+
expect(client)
|
90
|
+
.to receive(:find)
|
91
|
+
.with('customFields', 'abcdef123456789123456789', {})
|
92
|
+
|
93
|
+
CustomField.find('abcdef123456789123456789')
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'is equivalent to client#find' do
|
97
|
+
expect(CustomField.find('abcdef123456789123456789')).to eq(custom_field)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
context 'updating' do
|
102
|
+
it 'correctly updates custom field name' do
|
103
|
+
expected_new_name = 'Test Name'
|
104
|
+
|
105
|
+
payload = { name: expected_new_name }
|
106
|
+
|
107
|
+
expect(client)
|
108
|
+
.to receive(:put).once
|
109
|
+
.with('/customFields/abcdef123456789123456789', payload)
|
110
|
+
|
111
|
+
custom_field.name = expected_new_name
|
112
|
+
custom_field.save
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
context 'fields' do
|
117
|
+
it 'gets its id' do
|
118
|
+
expect(custom_field.id).to_not be_nil
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'gets its name' do
|
122
|
+
expect(custom_field.name).to_not be_nil
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'gets the model id' do
|
126
|
+
expect(custom_field.model_id).to_not be_nil
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'gets the model type' do
|
130
|
+
expect(custom_field.model_type).to_not be_nil
|
131
|
+
end
|
132
|
+
|
133
|
+
it 'gets its type' do
|
134
|
+
expect(custom_field.type).to_not be_nil
|
135
|
+
end
|
136
|
+
|
137
|
+
it 'gets its position' do
|
138
|
+
expect(custom_field.pos).to_not be_nil
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
context 'boards' do
|
143
|
+
before do
|
144
|
+
allow(client)
|
145
|
+
.to receive(:get)
|
146
|
+
.with('/boards/abc123', {})
|
147
|
+
.and_return JSON.generate(boards_details.first)
|
148
|
+
end
|
149
|
+
|
150
|
+
it 'has a board' do
|
151
|
+
expect(custom_field.board).to_not be_nil
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
context 'options' do
|
156
|
+
it 'creates a new option' do
|
157
|
+
payload = { :value => { "text" => "High Priority" } }
|
158
|
+
|
159
|
+
expect(client)
|
160
|
+
.to receive(:post)
|
161
|
+
.with('/customFields/abcdef123456789123456789/options', payload)
|
162
|
+
|
163
|
+
custom_field.create_new_option({"text" => "High Priority"})
|
164
|
+
end
|
165
|
+
|
166
|
+
it 'deletes option' do
|
167
|
+
expect(client)
|
168
|
+
.to receive(:delete)
|
169
|
+
.with('/customFields/abcdef123456789123456789/options/abc123')
|
170
|
+
|
171
|
+
custom_field.delete_option('abc123')
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
context 'deleting' do
|
176
|
+
it 'deletes the custom field' do
|
177
|
+
expect(client)
|
178
|
+
.to receive(:delete)
|
179
|
+
.with("/customFields/#{custom_field.id}")
|
180
|
+
|
181
|
+
custom_field.delete
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -425,6 +425,54 @@ module Helpers
|
|
425
425
|
JSON.generate(label_name_details)
|
426
426
|
end
|
427
427
|
|
428
|
+
def custom_fields_details
|
429
|
+
[
|
430
|
+
{
|
431
|
+
'id' => 'abcdef123456789123456789',
|
432
|
+
'name' => 'Priority',
|
433
|
+
'idModel' => 'abc123',
|
434
|
+
'type' => 'checkbox',
|
435
|
+
'pos' => 123,
|
436
|
+
'modelType' => 'board'
|
437
|
+
},
|
438
|
+
{
|
439
|
+
id: 'abcdef123456789123456789',
|
440
|
+
name: 'Priority',
|
441
|
+
model_id: 'abc123',
|
442
|
+
type: 'checkbox',
|
443
|
+
pos: 123,
|
444
|
+
model_type: 'board'
|
445
|
+
}
|
446
|
+
]
|
447
|
+
end
|
448
|
+
|
449
|
+
def custom_fields_payload
|
450
|
+
JSON.generate(custom_fields_details.first)
|
451
|
+
end
|
452
|
+
|
453
|
+
def custom_field_option_details
|
454
|
+
{
|
455
|
+
'_id' => 'abcdefgh12345678',
|
456
|
+
'value' => {'text' => 'Low Priority'},
|
457
|
+
'color' => 'green',
|
458
|
+
'pos' => 1
|
459
|
+
}
|
460
|
+
end
|
461
|
+
|
462
|
+
def custom_field_item_details
|
463
|
+
{
|
464
|
+
'id' => 'abcdefg1234567',
|
465
|
+
'value' => { 'text' => 'hello world' },
|
466
|
+
'idModel' => 'abcdef123456789123456789',
|
467
|
+
'idCustomField' => 'abcdef123456789123456789',
|
468
|
+
'modelType' => 'card'
|
469
|
+
}
|
470
|
+
end
|
471
|
+
|
472
|
+
def custom_field_items_payload
|
473
|
+
JSON.generate(custom_field_item_details)
|
474
|
+
end
|
475
|
+
|
428
476
|
def webhooks_payload
|
429
477
|
JSON.generate(webhooks_details)
|
430
478
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-trello
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeremy Tregunna
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-08-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|
@@ -105,6 +105,9 @@ files:
|
|
105
105
|
- lib/trello/core_ext/hash.rb
|
106
106
|
- lib/trello/core_ext/string.rb
|
107
107
|
- lib/trello/cover_image.rb
|
108
|
+
- lib/trello/custom_field.rb
|
109
|
+
- lib/trello/custom_field_item.rb
|
110
|
+
- lib/trello/custom_field_option.rb
|
108
111
|
- lib/trello/error.rb
|
109
112
|
- lib/trello/has_actions.rb
|
110
113
|
- lib/trello/item.rb
|
@@ -125,11 +128,15 @@ files:
|
|
125
128
|
- spec/array_spec.rb
|
126
129
|
- spec/association_spec.rb
|
127
130
|
- spec/basic_auth_policy_spec.rb
|
131
|
+
- spec/basic_data_spec.rb
|
128
132
|
- spec/board_spec.rb
|
129
133
|
- spec/card_spec.rb
|
130
134
|
- spec/checklist_spec.rb
|
131
135
|
- spec/client_spec.rb
|
132
136
|
- spec/configuration_spec.rb
|
137
|
+
- spec/custom_field_item_spec.rb
|
138
|
+
- spec/custom_field_option_spec.rb
|
139
|
+
- spec/custom_field_spec.rb
|
133
140
|
- spec/hash_spec.rb
|
134
141
|
- spec/integration/how_to_authorize_spec.rb
|
135
142
|
- spec/integration/how_to_use_boards_spec.rb
|
@@ -168,7 +175,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
168
175
|
version: '0'
|
169
176
|
requirements: []
|
170
177
|
rubyforge_project: ruby-trello
|
171
|
-
rubygems_version: 2.7.
|
178
|
+
rubygems_version: 2.7.7
|
172
179
|
signing_key:
|
173
180
|
specification_version: 4
|
174
181
|
summary: A wrapper around the trello.com API.
|
@@ -179,11 +186,13 @@ test_files:
|
|
179
186
|
- spec/integration/how_to_use_boards_spec.rb
|
180
187
|
- spec/integration/how_to_authorize_spec.rb
|
181
188
|
- spec/integration/integration_test.rb
|
189
|
+
- spec/custom_field_spec.rb
|
182
190
|
- spec/card_spec.rb
|
183
191
|
- spec/hash_spec.rb
|
184
192
|
- spec/trello_spec.rb
|
185
193
|
- spec/board_spec.rb
|
186
194
|
- spec/member_spec.rb
|
195
|
+
- spec/custom_field_option_spec.rb
|
187
196
|
- spec/oauth_policy_spec.rb
|
188
197
|
- spec/configuration_spec.rb
|
189
198
|
- spec/json_utils_spec.rb
|
@@ -191,10 +200,12 @@ test_files:
|
|
191
200
|
- spec/list_spec.rb
|
192
201
|
- spec/webhook_spec.rb
|
193
202
|
- spec/organization_spec.rb
|
203
|
+
- spec/custom_field_item_spec.rb
|
194
204
|
- spec/basic_auth_policy_spec.rb
|
195
205
|
- spec/token_spec.rb
|
196
206
|
- spec/string_spec.rb
|
197
207
|
- spec/action_spec.rb
|
208
|
+
- spec/basic_data_spec.rb
|
198
209
|
- spec/array_spec.rb
|
199
210
|
- spec/client_spec.rb
|
200
211
|
- spec/item_spec.rb
|