thumbtack 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/thumbtack.rb +6 -0
- data/lib/thumbtack/client.rb +70 -24
- data/lib/thumbtack/note.rb +68 -8
- data/lib/thumbtack/note_summary.rb +66 -11
- data/lib/thumbtack/notes.rb +30 -6
- data/lib/thumbtack/post.rb +82 -8
- data/lib/thumbtack/posts.rb +143 -85
- data/lib/thumbtack/specification.rb +12 -8
- data/lib/thumbtack/suggestion.rb +59 -0
- data/lib/thumbtack/tags.rb +41 -11
- data/lib/thumbtack/types.rb +4 -3
- data/lib/thumbtack/types/boolean.rb +20 -12
- data/lib/thumbtack/types/date.rb +20 -13
- data/lib/thumbtack/types/date_time.rb +21 -14
- data/lib/thumbtack/types/identity.rb +11 -6
- data/lib/thumbtack/types/integer.rb +12 -8
- data/lib/thumbtack/types/md5.rb +12 -9
- data/lib/thumbtack/types/tags.rb +23 -18
- data/lib/thumbtack/types/text.rb +11 -7
- data/lib/thumbtack/types/title.rb +11 -7
- data/lib/thumbtack/types/url.rb +12 -7
- data/lib/thumbtack/user.rb +26 -5
- data/lib/thumbtack/version.rb +1 -1
- data/test/test_helper.rb +4 -10
- data/test/thumbtack/client_test.rb +1 -1
- data/test/thumbtack/integration/client_test.rb +5 -2
- data/test/thumbtack/note_summary_test.rb +1 -1
- data/test/thumbtack/notes_test.rb +1 -7
- data/test/thumbtack/posts_test.rb +6 -13
- data/test/thumbtack/suggestion_test.rb +16 -0
- data/test/thumbtack/tags_test.rb +0 -6
- data/test/thumbtack/user_test.rb +0 -6
- metadata +15 -11
data/lib/thumbtack/types.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
module Thumbtack
|
4
|
-
# Handlers for each of the data types in the Pinboard API
|
5
|
-
#
|
4
|
+
# Handlers for each of the data types in the Pinboard API
|
5
|
+
#
|
6
|
+
# @see https://pinboard.in/api/#data
|
6
7
|
module Types
|
7
|
-
#
|
8
|
+
# Raised when given an argument that does not satisfy the type constraints
|
8
9
|
class ValidationError < StandardError; end
|
9
10
|
end
|
10
11
|
end
|
@@ -2,15 +2,20 @@
|
|
2
2
|
|
3
3
|
module Thumbtack
|
4
4
|
module Types
|
5
|
-
#
|
6
|
-
# and 'no' parameters supported by
|
5
|
+
# Handles conversion and validation of Booleans to the 'yes'
|
6
|
+
# and 'no' parameters supported by Pinboard
|
7
|
+
#
|
8
|
+
# @api private
|
7
9
|
class Boolean
|
8
|
-
# Validate
|
10
|
+
# Validate a value is a boolean parameter
|
9
11
|
#
|
10
|
-
#
|
12
|
+
# @param [Boolean] value
|
13
|
+
# the value to validate
|
11
14
|
#
|
12
|
-
#
|
13
|
-
#
|
15
|
+
# @return [undefined]
|
16
|
+
#
|
17
|
+
# @raise [Types::ValidationError]
|
18
|
+
# if the value is not true or false
|
14
19
|
def self.validate(value)
|
15
20
|
case value
|
16
21
|
when TrueClass, FalseClass
|
@@ -20,11 +25,13 @@ module Thumbtack
|
|
20
25
|
end
|
21
26
|
end
|
22
27
|
|
23
|
-
# Convert a
|
28
|
+
# Convert a boolean value to a parameter acceptable to Pinboard
|
24
29
|
#
|
25
|
-
#
|
30
|
+
# @param [Boolean] value
|
31
|
+
# the value to convert
|
26
32
|
#
|
27
|
-
#
|
33
|
+
# @return [String]
|
34
|
+
# 'yes' if value is true, 'no' otherwise
|
28
35
|
def self.to_parameter(value)
|
29
36
|
case value
|
30
37
|
when TrueClass
|
@@ -34,11 +41,12 @@ module Thumbtack
|
|
34
41
|
end
|
35
42
|
end
|
36
43
|
|
37
|
-
# Convert a parameter from
|
44
|
+
# Convert a parameter from Pinboard to a boolean value
|
38
45
|
#
|
39
|
-
#
|
46
|
+
# @param [String] parameter
|
47
|
+
# Either 'yes' or 'no'
|
40
48
|
#
|
41
|
-
#
|
49
|
+
# @return [Boolean]
|
42
50
|
def self.from_parameter(parameter)
|
43
51
|
case parameter
|
44
52
|
when 'yes'
|
data/lib/thumbtack/types/date.rb
CHANGED
@@ -2,21 +2,25 @@
|
|
2
2
|
|
3
3
|
module Thumbtack
|
4
4
|
module Types
|
5
|
-
#
|
6
|
-
#
|
5
|
+
# Handles conversion and validation of Dates to parameters supported by
|
6
|
+
# Pinboard
|
7
|
+
#
|
8
|
+
# @api private
|
7
9
|
class Date
|
8
10
|
# The earliest allowable date
|
9
11
|
EARLIEST = ::Date.new(1, 1, 1)
|
10
12
|
# The latest allowable date
|
11
13
|
LATEST = ::Date.new(2100, 1, 1)
|
12
14
|
|
13
|
-
# Validate a
|
15
|
+
# Validate a date
|
14
16
|
#
|
15
|
-
#
|
17
|
+
# @param [Date] value
|
18
|
+
# the date to validate
|
16
19
|
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
20
|
+
# @return [undefined]
|
21
|
+
#
|
22
|
+
# @raise [Types::ValidationError]
|
23
|
+
# if the date is not between 0001-01-01 and 2100-01-01
|
20
24
|
def self.validate(value)
|
21
25
|
unless value > EARLIEST && value < LATEST
|
22
26
|
fail ValidationError,
|
@@ -25,20 +29,23 @@ module Thumbtack
|
|
25
29
|
self
|
26
30
|
end
|
27
31
|
|
28
|
-
# Convert a
|
32
|
+
# Convert a date to a parameter acceptable to Pinboard
|
29
33
|
#
|
30
|
-
#
|
34
|
+
# @param [Date] value
|
35
|
+
# the date to convert
|
31
36
|
#
|
32
|
-
#
|
37
|
+
# @return [String]
|
38
|
+
# the date with format yyyy-mm-dd
|
33
39
|
def self.to_parameter(value)
|
34
40
|
value.xmlschema
|
35
41
|
end
|
36
42
|
|
37
|
-
# Convert a parameter from
|
43
|
+
# Convert a parameter from Pinboard to a date
|
38
44
|
#
|
39
|
-
#
|
45
|
+
# @param [String] parameter
|
46
|
+
# the date with format yyyy-mm-dd
|
40
47
|
#
|
41
|
-
#
|
48
|
+
# @return [Date]
|
42
49
|
def self.from_parameter(parameter)
|
43
50
|
::Date.xmlschema(parameter)
|
44
51
|
end
|
@@ -2,23 +2,27 @@
|
|
2
2
|
|
3
3
|
module Thumbtack
|
4
4
|
module Types
|
5
|
-
# Handles conversion and validation of
|
6
|
-
#
|
5
|
+
# Handles conversion and validation of DateTimes to parameters supported by
|
6
|
+
# Pinboard
|
7
|
+
#
|
8
|
+
# @api private
|
7
9
|
class DateTime
|
8
10
|
# The earliest allowable time
|
9
11
|
EARLIEST = ::DateTime.new(1, 1, 1)
|
10
12
|
# The latest allowable time
|
11
13
|
LATEST = ::DateTime.new(2100, 1, 1)
|
12
|
-
#
|
14
|
+
# Pinboard's date format
|
13
15
|
FORMAT = '%Y-%m-%dT%H:%M:%SZ'.freeze
|
14
16
|
|
15
|
-
# Validate
|
17
|
+
# Validate a time
|
16
18
|
#
|
17
|
-
#
|
19
|
+
# @param [DateTime] value
|
20
|
+
# The time to validate
|
18
21
|
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
22
|
+
# @return [undefined]
|
23
|
+
#
|
24
|
+
# @raise [Types::ValidationError]
|
25
|
+
# if the time is not between 0001-01-01 00:00:00 and 2100-01-01 00:00:00
|
22
26
|
def self.validate(value)
|
23
27
|
unless value > EARLIEST && value < LATEST
|
24
28
|
fail ValidationError,
|
@@ -27,20 +31,23 @@ module Thumbtack
|
|
27
31
|
self
|
28
32
|
end
|
29
33
|
|
30
|
-
# Convert a
|
34
|
+
# Convert a time to a parameter acceptable to Pinboard
|
31
35
|
#
|
32
|
-
#
|
36
|
+
# @param [DateTime] value
|
37
|
+
# the time to convert
|
33
38
|
#
|
34
|
-
#
|
39
|
+
# @return [String]
|
40
|
+
# the time formatted yyyy-mm-ddTHH:MM:SSZ.
|
35
41
|
def self.to_parameter(value)
|
36
42
|
value.strftime(FORMAT)
|
37
43
|
end
|
38
44
|
|
39
|
-
# Convert a parameter from
|
45
|
+
# Convert a parameter from Pinboard to a datetime value
|
40
46
|
#
|
41
|
-
#
|
47
|
+
# @param [String] parameter
|
48
|
+
# the time formatted yyyy-mm-ddTHH:MM:SSZ
|
42
49
|
#
|
43
|
-
#
|
50
|
+
# @return [DateTime]
|
44
51
|
def self.from_parameter(parameter)
|
45
52
|
::DateTime.strptime(parameter)
|
46
53
|
end
|
@@ -2,22 +2,27 @@
|
|
2
2
|
|
3
3
|
module Thumbtack
|
4
4
|
module Types
|
5
|
-
#
|
5
|
+
# An abstract type handler with no conversion or validation
|
6
|
+
#
|
7
|
+
# @api private
|
6
8
|
class Identity
|
7
|
-
|
8
|
-
# Any value passed is valid.
|
9
|
+
# Any value passed is valid
|
9
10
|
#
|
10
|
-
#
|
11
|
+
# @return [undefined]
|
11
12
|
def self.validate(*)
|
12
13
|
self
|
13
14
|
end
|
14
15
|
|
15
|
-
#
|
16
|
+
# Value is returned unconverted
|
17
|
+
#
|
18
|
+
# @return [value]
|
16
19
|
def self.to_parameter(value)
|
17
20
|
value
|
18
21
|
end
|
19
22
|
|
20
|
-
#
|
23
|
+
# Parameter is returned unconverted
|
24
|
+
#
|
25
|
+
# @return [parameter]
|
21
26
|
def self.from_parameter(parameter)
|
22
27
|
parameter
|
23
28
|
end
|
@@ -2,20 +2,24 @@
|
|
2
2
|
|
3
3
|
module Thumbtack
|
4
4
|
module Types
|
5
|
-
#
|
6
|
-
#
|
5
|
+
# Handles validation of Integer types as the values supported by Pinboard
|
6
|
+
#
|
7
|
+
# @api private
|
7
8
|
class Integer < Identity
|
8
|
-
# The minimum allowable integer
|
9
|
+
# The minimum allowable integer
|
9
10
|
MIN = 0
|
10
|
-
# The maximum allowable integer
|
11
|
+
# The maximum allowable integer
|
11
12
|
MAX = 2**32
|
12
13
|
|
13
|
-
# Validate something is a valid integer parameter
|
14
|
+
# Validate something is a valid integer parameter
|
14
15
|
#
|
15
|
-
#
|
16
|
+
# @param [Integer] value
|
17
|
+
# the integer to validate
|
16
18
|
#
|
17
|
-
#
|
18
|
-
#
|
19
|
+
# @return [undefined]
|
20
|
+
#
|
21
|
+
# @raise [Types::ValidationError]
|
22
|
+
# if the value is not between 0 and 2^32
|
19
23
|
def self.validate(value)
|
20
24
|
unless value >= MIN && value <= MAX
|
21
25
|
fail ValidationError, "#{value} must be in range 0..2^32"
|
data/lib/thumbtack/types/md5.rb
CHANGED
@@ -2,21 +2,24 @@
|
|
2
2
|
|
3
3
|
module Thumbtack
|
4
4
|
module Types
|
5
|
-
#
|
6
|
-
#
|
5
|
+
# Handles validation of MD5 types as the values supported by Pinboard
|
6
|
+
#
|
7
|
+
# @api private
|
7
8
|
class MD5 < Identity
|
8
|
-
# The length of an MD5 value
|
9
|
+
# The length of an MD5 value
|
9
10
|
LENGTH = 32
|
10
|
-
# The valid characters in an MD5 value
|
11
|
+
# The valid characters in an MD5 value
|
11
12
|
CHARACTERS = '0123456789abcdf'.freeze
|
12
13
|
|
13
|
-
# Validate
|
14
|
+
# Validate a string is a valid MD5 parameter
|
14
15
|
#
|
15
|
-
#
|
16
|
+
# @param [String] value
|
17
|
+
# the MD5 to validate
|
16
18
|
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
19
|
+
# @return [undefined]
|
20
|
+
#
|
21
|
+
# @raise [Types::ValidationError]
|
22
|
+
# if the value is not a 32 character hexadecimal MD5 hash
|
20
23
|
def self.validate(value)
|
21
24
|
unless value.length == 32 &&
|
22
25
|
value.each_char.all? { |char| CHARACTERS.include?(char) }
|
data/lib/thumbtack/types/tags.rb
CHANGED
@@ -2,24 +2,27 @@
|
|
2
2
|
|
3
3
|
module Thumbtack
|
4
4
|
module Types
|
5
|
-
#
|
6
|
-
# Pinboard
|
5
|
+
# Handles conversion and validation of tag lists to values supported by
|
6
|
+
# Pinboard
|
7
|
+
#
|
8
|
+
# @api private
|
7
9
|
class Tags
|
8
|
-
# The maximum tag length
|
10
|
+
# The maximum tag length
|
9
11
|
MAXIMUM_LENGTH = 255
|
10
|
-
# Tags cannot have commas
|
12
|
+
# Tags cannot have commas
|
11
13
|
INVALID_CHARACTER = ','.freeze
|
12
|
-
# Tag parameters are separated by spaces
|
14
|
+
# Tag parameters are separated by spaces
|
13
15
|
SEPARATOR = ' '.freeze
|
14
16
|
|
15
|
-
# Validate a tags value
|
17
|
+
# Validate a tags value
|
16
18
|
#
|
17
|
-
#
|
18
|
-
#
|
19
|
+
# @param [String, Array<String>] value
|
20
|
+
# a single tag or an array of many tags
|
19
21
|
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
22
|
+
# @return [undefined]
|
23
|
+
#
|
24
|
+
# @raise [Types::ValidationError]
|
25
|
+
# if any tag contains commas or are longer than 255 characters
|
23
26
|
def self.validate(value)
|
24
27
|
Array(value).each do |tag|
|
25
28
|
unless tag.length < MAXIMUM_LENGTH && !tag.include?(INVALID_CHARACTER)
|
@@ -30,21 +33,23 @@ module Thumbtack
|
|
30
33
|
self
|
31
34
|
end
|
32
35
|
|
33
|
-
# Convert a tag value to a parameter acceptable to
|
36
|
+
# Convert a tag value to a parameter acceptable to Pinboard
|
34
37
|
#
|
35
|
-
#
|
36
|
-
#
|
38
|
+
# @param [String, Array<String>] value
|
39
|
+
# a single tag or an array of many tags
|
37
40
|
#
|
38
|
-
#
|
41
|
+
# @return [String]
|
42
|
+
# space-separated list of tags
|
39
43
|
def self.to_parameter(value)
|
40
44
|
Array(value).map(&:strip).join(SEPARATOR)
|
41
45
|
end
|
42
46
|
|
43
|
-
# Convert a parameter from
|
47
|
+
# Convert a parameter from Pinboard to a list of tags
|
44
48
|
#
|
45
|
-
#
|
49
|
+
# @param [String] parameter
|
50
|
+
# space-separated list of tags
|
46
51
|
#
|
47
|
-
#
|
52
|
+
# @return [Array<String>]
|
48
53
|
def self.from_parameter(parameter)
|
49
54
|
parameter.split(SEPARATOR)
|
50
55
|
end
|
data/lib/thumbtack/types/text.rb
CHANGED
@@ -2,18 +2,22 @@
|
|
2
2
|
|
3
3
|
module Thumbtack
|
4
4
|
module Types
|
5
|
-
#
|
5
|
+
# Handles validation of text values as supported by Pinboard
|
6
|
+
#
|
7
|
+
# @api private
|
6
8
|
class Text < Identity
|
7
|
-
# Maximum length of a text value
|
9
|
+
# Maximum length of a text value
|
8
10
|
MAXIMUM_LENGTH = 65_536
|
9
11
|
|
10
|
-
# Validate text
|
12
|
+
# Validate text
|
11
13
|
#
|
12
|
-
#
|
14
|
+
# @param [String] value
|
15
|
+
# text to validate
|
13
16
|
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
+
# @return [undefined]
|
18
|
+
#
|
19
|
+
# @raise [Types::ValidationError]
|
20
|
+
# if the value is longer than 65536 characters
|
17
21
|
def self.validate(value)
|
18
22
|
unless value.length <= MAXIMUM_LENGTH
|
19
23
|
fail ValidationError,
|
@@ -2,18 +2,22 @@
|
|
2
2
|
|
3
3
|
module Thumbtack
|
4
4
|
module Types
|
5
|
-
#
|
5
|
+
# Handles validation of title values as supported by Pinboard
|
6
|
+
#
|
7
|
+
# @api private
|
6
8
|
class Title < Identity
|
7
|
-
# Maximum length of a title value
|
9
|
+
# Maximum length of a title value
|
8
10
|
MAXIMUM_LENGTH = 255
|
9
11
|
|
10
|
-
# Validate a title
|
12
|
+
# Validate a title
|
11
13
|
#
|
12
|
-
#
|
14
|
+
# @param [String] value
|
15
|
+
# the title to validate
|
13
16
|
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
+
# @return [undefined]
|
18
|
+
#
|
19
|
+
# @raise [Types::ValidationError]
|
20
|
+
# if the value is longer than 255 characters
|
17
21
|
def self.validate(value)
|
18
22
|
unless value.length <= MAXIMUM_LENGTH
|
19
23
|
fail ValidationError,
|
data/lib/thumbtack/types/url.rb
CHANGED
@@ -2,18 +2,23 @@
|
|
2
2
|
|
3
3
|
module Thumbtack
|
4
4
|
module Types
|
5
|
-
#
|
5
|
+
# Handles validation of URL values as supported by Pinboard
|
6
|
+
#
|
7
|
+
# @api private
|
6
8
|
class URL < Identity
|
7
|
-
# Valid URL schemes
|
9
|
+
# Valid URL schemes
|
8
10
|
VALID_SCHEMES = %w(http https javascript mailto ftp file feed).freeze
|
9
11
|
|
10
|
-
# Validate a URL
|
12
|
+
# Validate a URL
|
11
13
|
#
|
12
|
-
#
|
14
|
+
# @param [String] value
|
15
|
+
# the URL to validate
|
13
16
|
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
+
# @return [undefined]
|
18
|
+
#
|
19
|
+
# @raise [Types::ValidationError]
|
20
|
+
# if the URL's scheme isn't one of http, https, javascript, mailto, ftp,
|
21
|
+
# file, or feed
|
17
22
|
def self.validate(value)
|
18
23
|
unless VALID_SCHEMES.include? URI(value).scheme
|
19
24
|
fail ValidationError,
|