typekit-client 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +5 -3
- data/.travis.yml +4 -0
- data/.yardopts +6 -0
- data/CHANGELOG.md +12 -0
- data/Guardfile +21 -3
- data/README.md +253 -248
- data/bin/typekit-client +16 -16
- data/bin/typekit-publisher +6 -5
- data/lib/typekit.rb +6 -2
- data/lib/typekit/client.rb +66 -24
- data/lib/typekit/collection.rb +6 -11
- data/lib/typekit/collection/base.rb +40 -0
- data/lib/typekit/collection/serialization.rb +17 -0
- data/lib/typekit/converter.rb +26 -0
- data/lib/typekit/converter/boolean.rb +12 -0
- data/lib/typekit/converter/collection.rb +13 -0
- data/lib/typekit/converter/datetime.rb +12 -0
- data/lib/typekit/converter/element.rb +13 -0
- data/lib/typekit/converter/errors.rb +12 -0
- data/lib/typekit/converter/unknown.rb +13 -0
- data/lib/typekit/core.rb +8 -10
- data/lib/typekit/element.rb +27 -0
- data/lib/typekit/element/association.rb +63 -0
- data/lib/typekit/element/base.rb +61 -0
- data/lib/typekit/element/persistence.rb +61 -0
- data/lib/typekit/element/query.rb +25 -0
- data/lib/typekit/element/serialization.rb +17 -0
- data/lib/typekit/error.rb +23 -0
- data/lib/typekit/helper.rb +59 -10
- data/lib/typekit/record.rb +18 -22
- data/lib/typekit/record/family.rb +24 -1
- data/lib/typekit/record/kit.rb +29 -1
- data/lib/typekit/record/library.rb +4 -1
- data/lib/typekit/record/variation.rb +13 -1
- data/lib/typekit/version.rb +1 -1
- data/spec/feature/create_kit_spec.rb +52 -0
- data/spec/feature/delete_kit_spec.rb +33 -0
- data/spec/feature/index_kits_spec.rb +55 -0
- data/spec/feature/publish_kit_spec.rb +15 -0
- data/spec/feature/show_family_spec.rb +75 -0
- data/spec/feature/show_kit_spec.rb +56 -0
- data/spec/feature/show_library_spec.rb +29 -0
- data/spec/feature/show_variation_spec.rb +18 -0
- data/spec/feature/update_kit_spec.rb +88 -0
- data/spec/fixture/cassette/create_kits_bad.yml +16 -0
- data/spec/fixture/cassette/create_kits_ok.yml +16 -0
- data/spec/fixture/cassette/delete_kits_xxx_not_found.yml +13 -0
- data/spec/{cassettes → fixture/cassette}/delete_kits_xxx_ok.yml +0 -3
- data/spec/fixture/cassette/index_kits_show_kit_xxx_ok.yml +25 -0
- data/spec/{cassettes → fixture/cassette}/index_kits_unauthorized.yml +0 -3
- data/spec/{cassettes → fixture/cassette}/show_families_xxx_found.yml +0 -3
- data/spec/{cassettes → fixture/cassette}/show_families_xxx_ok.yml +0 -3
- data/spec/{cassettes → fixture/cassette}/show_families_xxx_yyy_ok.yml +0 -3
- data/spec/fixture/cassette/show_families_yyy_update_kits_xxx_families_ok.yml +35 -0
- data/spec/fixture/cassette/show_kits_xxx_families_yyy_show_family_yyy_ok.yml +45 -0
- data/spec/fixture/cassette/show_kits_xxx_not_found.yml +13 -0
- data/spec/fixture/cassette/show_kits_xxx_show_family_yyy_ok.yml +46 -0
- data/spec/{cassettes → fixture/cassette}/show_libraries_xxx_ok.yml +0 -3
- data/spec/fixture/cassette/update_kits_xxx_empty_families_ok.yml +16 -0
- data/spec/fixture/cassette/update_kits_xxx_families_ok.yml +18 -0
- data/spec/fixture/cassette/update_kits_xxx_families_variations_ok.yml +18 -0
- data/spec/fixture/cassette/update_kits_xxx_name_ok.yml +17 -0
- data/spec/fixture/cassette/update_kits_xxx_publish_ok.yml +16 -0
- data/spec/fixture/record/article.rb +11 -0
- data/spec/fixture/record/section.rb +10 -0
- data/spec/lib/typekit/collection_spec.rb +22 -0
- data/spec/{typekit/processing → lib/typekit}/converter_spec.rb +13 -13
- data/spec/lib/typekit/element/association_spec.rb +96 -0
- data/spec/lib/typekit/element/base_spec.rb +70 -0
- data/spec/lib/typekit/element/persistence_spec.rb +97 -0
- data/spec/lib/typekit/element/serialization_spec.rb +28 -0
- data/spec/lib/typekit/element_spec.rb +58 -0
- data/spec/{typekit → lib/typekit}/helper_spec.rb +6 -8
- data/spec/lib/typekit/record_spec.rb +57 -0
- data/spec/spec_helper.rb +10 -3
- data/spec/support/common_helper.rb +5 -0
- data/spec/support/record_helper.rb +38 -0
- data/typekit-client.gemspec +11 -4
- metadata +164 -58
- data/lib/typekit/processing.rb +0 -8
- data/lib/typekit/processing/converter.rb +0 -28
- data/lib/typekit/processing/converter/boolean.rb +0 -14
- data/lib/typekit/processing/converter/collection.rb +0 -18
- data/lib/typekit/processing/converter/datetime.rb +0 -14
- data/lib/typekit/processing/converter/errors.rb +0 -24
- data/lib/typekit/processing/converter/record.rb +0 -16
- data/lib/typekit/processing/converter/unknown.rb +0 -15
- data/lib/typekit/processing/translator.rb +0 -13
- data/lib/typekit/record/base.rb +0 -52
- data/spec/cassettes/index_kits_ok.yml +0 -16
- data/spec/cassettes/show_kits_xxx_families_yyy_ok.yml +0 -16
- data/spec/cassettes/show_kits_xxx_ok.yml +0 -17
- data/spec/features/client/delete_kit_spec.rb +0 -13
- data/spec/features/client/index_kits_spec.rb +0 -25
- data/spec/features/client/show_family_spec.rb +0 -47
- data/spec/features/client/show_kit_spec.rb +0 -18
- data/spec/features/client/show_library_spec.rb +0 -18
- data/spec/features/client/show_variation_spec.rb +0 -22
- data/spec/support/resource_helper.rb +0 -34
- data/spec/typekit/record/base_spec.rb +0 -85
- data/spec/typekit/record_spec.rb +0 -80
@@ -0,0 +1,27 @@
|
|
1
|
+
require_relative 'element/association'
|
2
|
+
require_relative 'element/persistence'
|
3
|
+
require_relative 'element/query'
|
4
|
+
require_relative 'element/serialization'
|
5
|
+
require_relative 'element/base'
|
6
|
+
|
7
|
+
module Typekit
|
8
|
+
module Element
|
9
|
+
def self.dictionary
|
10
|
+
@dictionary ||= Hash[
|
11
|
+
ObjectSpace.each_object(Class).select do |klass|
|
12
|
+
klass < Base && klass.name
|
13
|
+
end.map do |klass|
|
14
|
+
[Helper.tokenize(klass), klass]
|
15
|
+
end
|
16
|
+
]
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.classify(name)
|
20
|
+
dictionary[Helper.tokenize(name)]
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.build(name, *arguments)
|
24
|
+
classify(name).new(*arguments)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Typekit
|
2
|
+
module Element
|
3
|
+
module Association
|
4
|
+
def self.included(base)
|
5
|
+
base.extend(ClassMethods)
|
6
|
+
end
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
def possessions
|
10
|
+
@possessions ||= []
|
11
|
+
end
|
12
|
+
|
13
|
+
def owners
|
14
|
+
@owners ||= []
|
15
|
+
end
|
16
|
+
|
17
|
+
def has_many(name)
|
18
|
+
possessions << name
|
19
|
+
|
20
|
+
define_method(name) do
|
21
|
+
value = attributes[name]
|
22
|
+
return value if value.is_a?(Collection::Base)
|
23
|
+
|
24
|
+
unless value.nil?
|
25
|
+
attributes[name] = Collection.build(name, self, value)
|
26
|
+
return attributes[name]
|
27
|
+
end
|
28
|
+
|
29
|
+
if feature?(:persistence) && new?
|
30
|
+
attributes[name] = Collection.build(name, self, [])
|
31
|
+
return attributes[name]
|
32
|
+
end
|
33
|
+
|
34
|
+
load!
|
35
|
+
|
36
|
+
value = attributes[name]
|
37
|
+
raise Error, 'Cannot load the association' if value.nil?
|
38
|
+
|
39
|
+
attributes[name] = Collection.build(name, self, value)
|
40
|
+
end
|
41
|
+
|
42
|
+
define_method("#{name}=") do |value|
|
43
|
+
if value.is_a?(Collection::Base)
|
44
|
+
attributes[name] = value
|
45
|
+
else
|
46
|
+
attributes[name] = Collection.build(name, self, value)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def belongs_to(name)
|
52
|
+
owners << name
|
53
|
+
|
54
|
+
define_method(name) do
|
55
|
+
value = attributes[name]
|
56
|
+
return value if value.nil? || value.is_a?(Element::Base)
|
57
|
+
attributes[name] = Element.build(name, self, attributes[name])
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Typekit
|
2
|
+
module Element
|
3
|
+
class Base
|
4
|
+
extend Forwardable
|
5
|
+
|
6
|
+
include Client::Proxy
|
7
|
+
|
8
|
+
attr_reader :attributes
|
9
|
+
def_delegators :attributes, :to_hash, :to_h, :to_json
|
10
|
+
|
11
|
+
def initialize(*arguments)
|
12
|
+
@attributes = prepare_attributes(Helper.extract_hash!(arguments))
|
13
|
+
@attributes[:id] = nil unless @attributes.key?(:id)
|
14
|
+
connect(arguments.first)
|
15
|
+
end
|
16
|
+
|
17
|
+
def become(another)
|
18
|
+
raise ArgumentError, 'Invalid class' unless self.class == another.class
|
19
|
+
@attributes = another.attributes
|
20
|
+
true
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.feature?(name)
|
24
|
+
name = Helper.constantize(name)
|
25
|
+
@features ||= {}
|
26
|
+
return @features[name] if @features.key?(name)
|
27
|
+
@features[name] = include?(Element.const_get(name))
|
28
|
+
end
|
29
|
+
|
30
|
+
def feature?(name)
|
31
|
+
self.class.feature?(name)
|
32
|
+
end
|
33
|
+
|
34
|
+
def attribute?(name)
|
35
|
+
attributes.key?(name)
|
36
|
+
end
|
37
|
+
|
38
|
+
def assign_attributes(*arguments)
|
39
|
+
prepare_attributes(*arguments).each do |name, value|
|
40
|
+
attributes[name] = value
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def prepare_attributes(attributes)
|
47
|
+
Helper.symbolize_keys(attributes)
|
48
|
+
end
|
49
|
+
|
50
|
+
def method_missing(name, *arguments)
|
51
|
+
if name.to_s =~ /^(?<name>.*)=$/
|
52
|
+
name = Regexp.last_match(:name).to_sym
|
53
|
+
attributes.send(:[]=, name, *arguments)
|
54
|
+
else
|
55
|
+
return super unless attributes.key?(name)
|
56
|
+
attributes[name]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Typekit
|
2
|
+
module Element
|
3
|
+
module Persistence
|
4
|
+
def self.included(base)
|
5
|
+
base.extend(ClassMethods)
|
6
|
+
end
|
7
|
+
|
8
|
+
def new?
|
9
|
+
id.to_s.empty?
|
10
|
+
end
|
11
|
+
|
12
|
+
def persistent?
|
13
|
+
!(new? || deleted?)
|
14
|
+
end
|
15
|
+
|
16
|
+
def deleted?
|
17
|
+
!!@deleted
|
18
|
+
end
|
19
|
+
|
20
|
+
def save!
|
21
|
+
if new?
|
22
|
+
element = process(:create, serialize)
|
23
|
+
else
|
24
|
+
element = process(:update, id, serialize)
|
25
|
+
end
|
26
|
+
become(element)
|
27
|
+
true
|
28
|
+
end
|
29
|
+
|
30
|
+
def update!(*arguments)
|
31
|
+
assign_attributes(*arguments)
|
32
|
+
become(process(:update, id, serialize))
|
33
|
+
true
|
34
|
+
end
|
35
|
+
|
36
|
+
def delete!
|
37
|
+
process(:delete, id) if persistent?
|
38
|
+
@deleted = true
|
39
|
+
true
|
40
|
+
end
|
41
|
+
|
42
|
+
[:save, :update, :delete].each do |method|
|
43
|
+
class_eval <<-CODE, __FILE__, __LINE__ + 1
|
44
|
+
def #{method}(*arguments)
|
45
|
+
#{method}!(*arguments)
|
46
|
+
rescue ServerError
|
47
|
+
false
|
48
|
+
end
|
49
|
+
CODE
|
50
|
+
end
|
51
|
+
|
52
|
+
module ClassMethods
|
53
|
+
def create(*arguments)
|
54
|
+
element = new(*arguments)
|
55
|
+
element.save
|
56
|
+
element
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Typekit
|
2
|
+
module Element
|
3
|
+
module Query
|
4
|
+
def self.included(base)
|
5
|
+
base.extend(ClassMethods)
|
6
|
+
end
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
def all
|
10
|
+
process(:index)
|
11
|
+
end
|
12
|
+
|
13
|
+
def find!(id)
|
14
|
+
process(:show, id)
|
15
|
+
end
|
16
|
+
|
17
|
+
def find(id)
|
18
|
+
find!(id)
|
19
|
+
rescue ServerError
|
20
|
+
nil
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Typekit
|
2
|
+
module Element
|
3
|
+
module Serialization
|
4
|
+
def serialize(options = {})
|
5
|
+
keys = attributes.keys
|
6
|
+
keys = keys & Array(options[:only]) if options.key?(:only)
|
7
|
+
Hash[
|
8
|
+
keys.map do |key|
|
9
|
+
value = attributes[key]
|
10
|
+
value = value.serialize if value.respond_to?(:serialize)
|
11
|
+
[key, value]
|
12
|
+
end
|
13
|
+
]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Typekit
|
2
|
+
class Error < StandardError
|
3
|
+
end
|
4
|
+
|
5
|
+
class ServerError < Error
|
6
|
+
ERRORS = {
|
7
|
+
400 => 'There are errors in the data provided by your application',
|
8
|
+
401 => 'Authentication is needed to access the requested endpoint',
|
9
|
+
403 => 'Your application has been rate limited',
|
10
|
+
404 => 'You are requesting a resource that does not exist',
|
11
|
+
500 => 'The servers of Typekit are unable to process the request',
|
12
|
+
503 => 'The Typekit API is offline for maintenance'
|
13
|
+
}
|
14
|
+
ERRORS.default = 'Unknown server error'
|
15
|
+
|
16
|
+
attr_reader :code
|
17
|
+
|
18
|
+
def initialize(code, message = '')
|
19
|
+
@code = code
|
20
|
+
super(message.empty? ? ERRORS[code] : message)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/typekit/helper.rb
CHANGED
@@ -1,29 +1,78 @@
|
|
1
1
|
module Typekit
|
2
2
|
module Helper
|
3
|
-
|
4
|
-
|
3
|
+
# Returns the plural form of the given word.
|
4
|
+
#
|
5
|
+
# @param word [String]
|
6
|
+
# @return [String]
|
7
|
+
def self.pluralize(word)
|
8
|
+
case word
|
5
9
|
when /^.*s$/
|
6
|
-
|
10
|
+
word
|
7
11
|
when /^(?<root>.*)y$/
|
8
|
-
"#{
|
12
|
+
"#{Regexp.last_match(:root)}ies"
|
9
13
|
else
|
10
|
-
"#{
|
14
|
+
"#{word}s"
|
11
15
|
end
|
12
16
|
end
|
13
17
|
|
14
|
-
|
15
|
-
|
18
|
+
# Returns the singular form of the given word.
|
19
|
+
#
|
20
|
+
# @param word [String]
|
21
|
+
# @return [String]
|
22
|
+
def self.singularize(word)
|
23
|
+
case word
|
16
24
|
when /^(?<root>.*)ies$/
|
17
|
-
"#{
|
25
|
+
"#{Regexp.last_match(:root)}y"
|
18
26
|
when /^(?<root>.*)s$/
|
19
27
|
Regexp.last_match(:root)
|
20
28
|
else
|
21
|
-
|
29
|
+
word
|
22
30
|
end
|
23
31
|
end
|
24
32
|
|
33
|
+
# Constructs a symbol suitable for looking up modules among the constants
|
34
|
+
# defined in a module.
|
35
|
+
#
|
36
|
+
# @param object [String, Symbol]
|
37
|
+
# @return [Symbol]
|
38
|
+
def self.constantize(object)
|
39
|
+
object.to_s.sub(/^.*::/, '').capitalize.to_sym
|
40
|
+
end
|
41
|
+
|
42
|
+
# Constructs a symbolic representation of the given object.
|
43
|
+
#
|
44
|
+
# @param object
|
45
|
+
# @option options [Boolean] :pluralize (true) indicates if the result
|
46
|
+
# should be plural
|
47
|
+
def self.tokenize(object, options = {})
|
48
|
+
name = object.to_s.sub(/^.*::/, '').downcase
|
49
|
+
(options.fetch(:pluralize, true) ? pluralize(name) : name).to_sym
|
50
|
+
end
|
51
|
+
|
52
|
+
# Copies the given hash while converting its keys into symbols.
|
53
|
+
#
|
54
|
+
# @param hash [Hash]
|
55
|
+
# @return [Hash]
|
25
56
|
def self.symbolize_keys(hash)
|
26
|
-
Hash[hash.map { |k, v| [
|
57
|
+
Hash[hash.map { |k, v| [k.to_sym, v] }]
|
58
|
+
end
|
59
|
+
|
60
|
+
# Removes and returns the last element of the given array if that element
|
61
|
+
# is a hash; otherwise, a new hash is returned.
|
62
|
+
#
|
63
|
+
# @param array [Array]
|
64
|
+
# @return [Hash]
|
65
|
+
def self.extract_hash!(array)
|
66
|
+
array.last.is_a?(Hash) ? array.pop : {}
|
67
|
+
end
|
68
|
+
|
69
|
+
# Removes and returns the last element of the given array if that element
|
70
|
+
# is an array; otherwise, a new array is returned.
|
71
|
+
#
|
72
|
+
# @param array [Array]
|
73
|
+
# @return [Array]
|
74
|
+
def self.extract_array!(array)
|
75
|
+
array.last.is_a?(Array) ? array.pop : {}
|
27
76
|
end
|
28
77
|
end
|
29
78
|
end
|
data/lib/typekit/record.rb
CHANGED
@@ -1,35 +1,31 @@
|
|
1
|
-
require_relative 'record/base'
|
2
|
-
require_relative 'record/family'
|
3
|
-
require_relative 'record/variation'
|
4
1
|
require_relative 'record/kit'
|
2
|
+
require_relative 'record/family'
|
5
3
|
require_relative 'record/library'
|
4
|
+
require_relative 'record/variation'
|
6
5
|
|
7
6
|
module Typekit
|
8
7
|
module Record
|
9
|
-
def self.mapping
|
10
|
-
@mapping ||= Hash[
|
11
|
-
ObjectSpace.each_object(Class).select do |klass|
|
12
|
-
klass < Base && klass.name
|
13
|
-
end.map do |klass|
|
14
|
-
[ klass.name.downcase.sub(/^.*::/, '').to_sym, klass ]
|
15
|
-
end
|
16
|
-
]
|
17
|
-
end
|
18
|
-
|
19
|
-
def self.classify(name)
|
20
|
-
mapping[Helper.singularize(name.to_s).to_sym]
|
21
|
-
end
|
22
|
-
|
23
8
|
def self.identify(name)
|
24
|
-
if
|
25
|
-
:record
|
26
|
-
elsif mapping.include?(Helper.singularize(name.to_s).to_sym)
|
9
|
+
if Element.dictionary.key?(Helper.tokenize(name, pluralize: false))
|
27
10
|
:collection
|
11
|
+
elsif Element.dictionary.key?(Helper.tokenize(name))
|
12
|
+
:element
|
28
13
|
end
|
29
14
|
end
|
30
15
|
|
31
|
-
def self.build(name,
|
32
|
-
classify(name)
|
16
|
+
def self.build(name, client)
|
17
|
+
klass = Element.classify(name)
|
18
|
+
Class.new(klass) do
|
19
|
+
extend Client::Proxy
|
20
|
+
|
21
|
+
connect(client, Helper.tokenize(name))
|
22
|
+
|
23
|
+
singleton_class.instance_eval do
|
24
|
+
define_method(:new) do |*arguments|
|
25
|
+
klass.new(client, *arguments)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
33
29
|
end
|
34
30
|
end
|
35
31
|
end
|
@@ -1,8 +1,31 @@
|
|
1
1
|
module Typekit
|
2
2
|
module Record
|
3
|
-
class Family < Base
|
3
|
+
class Family < Element::Base
|
4
|
+
include Element::Association
|
5
|
+
include Element::Query
|
6
|
+
include Element::Serialization
|
7
|
+
|
4
8
|
has_many :libraries
|
5
9
|
has_many :variations
|
10
|
+
|
11
|
+
def complete?
|
12
|
+
attribute?(:libraries) && attribute?(:variations)
|
13
|
+
end
|
14
|
+
|
15
|
+
def load!
|
16
|
+
become(process(:show, id))
|
17
|
+
true
|
18
|
+
end
|
19
|
+
|
20
|
+
def load
|
21
|
+
load!
|
22
|
+
rescue ServerError
|
23
|
+
false
|
24
|
+
end
|
25
|
+
|
26
|
+
def serialize
|
27
|
+
super(only: [:id, :subset, :variations])
|
28
|
+
end
|
6
29
|
end
|
7
30
|
end
|
8
31
|
end
|