ruby-trello 2.0.1 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|