typekit-client 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +6 -0
  3. data/Guardfile +18 -4
  4. data/README.md +62 -39
  5. data/bin/{typekit → typekit-client} +14 -1
  6. data/bin/typekit-publisher +89 -0
  7. data/lib/typekit/client.rb +6 -10
  8. data/lib/typekit/collection.rb +15 -0
  9. data/lib/typekit/core.rb +3 -3
  10. data/lib/typekit/helper.rb +4 -0
  11. data/lib/typekit/processing/converter/boolean.rb +3 -0
  12. data/lib/typekit/processing/converter/collection.rb +18 -0
  13. data/lib/typekit/processing/converter/datetime.rb +3 -0
  14. data/lib/typekit/processing/converter/errors.rb +3 -1
  15. data/lib/typekit/processing/converter/record.rb +2 -1
  16. data/lib/typekit/processing/converter.rb +8 -13
  17. data/lib/typekit/record/base.rb +30 -8
  18. data/lib/typekit/record/family.rb +2 -1
  19. data/lib/typekit/record/kit.rb +1 -1
  20. data/lib/typekit/record/library.rb +1 -1
  21. data/lib/typekit/record/variation.rb +2 -2
  22. data/lib/typekit/record.rb +18 -18
  23. data/lib/typekit/version.rb +1 -1
  24. data/lib/typekit.rb +2 -0
  25. data/spec/cassettes/{show_families_calluna_found.yml → show_families_xxx_found.yml} +1 -1
  26. data/spec/cassettes/show_families_xxx_ok.yml +31 -0
  27. data/spec/cassettes/show_families_xxx_yyy_ok.yml +20 -0
  28. data/spec/cassettes/show_kits_xxx_families_yyy_ok.yml +16 -0
  29. data/spec/cassettes/show_kits_xxx_ok.yml +17 -0
  30. data/spec/cassettes/show_libraries_xxx_ok.yml +31 -0
  31. data/spec/features/client/delete_kit_spec.rb +13 -0
  32. data/spec/features/client/index_kits_spec.rb +25 -0
  33. data/spec/features/client/show_family_spec.rb +47 -0
  34. data/spec/features/client/show_kit_spec.rb +18 -0
  35. data/spec/features/client/show_library_spec.rb +18 -0
  36. data/spec/features/client/show_variation_spec.rb +22 -0
  37. data/spec/spec_helper.rb +3 -5
  38. data/spec/support/resource_helper.rb +34 -0
  39. data/spec/typekit/helper_spec.rb +12 -5
  40. data/spec/typekit/processing/converter_spec.rb +1 -1
  41. data/spec/typekit/record/base_spec.rb +56 -3
  42. data/spec/typekit/record_spec.rb +57 -24
  43. data/typekit-client.gemspec +1 -1
  44. metadata +36 -13
  45. data/lib/typekit/processing/converter/records.rb +0 -18
  46. data/spec/support/rest_helper.rb +0 -22
  47. data/spec/typekit/client_spec.rb +0 -42
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2bc086a0bb50bb480f485bbef88d7bebdcc25356
4
- data.tar.gz: f8d01ce2b825b203f8df1ec09607549800987c64
3
+ metadata.gz: b2d0603ce4ff30ecb04ccf846ba94cf71b0e8d54
4
+ data.tar.gz: a85ce05a15a5aa3b0cea5b1e0122ccd0b8db6eb8
5
5
  SHA512:
6
- metadata.gz: 632b2218c382aac4717d5aebbb612ccf670c83f36ca0b12ac7b1d1a83018f4d2714893638d39dc10f6c032b6ec473a06a683e7a70e50227cb9ae512c5f2b9997
7
- data.tar.gz: 6a55fc36b622cb55a54512abbe3b8648efcae9b4f207928e40191b094781a50c18d225dedc7db5fdc48e3f7d961ed60c0952528acde0824fdc7d3844babdc736
6
+ metadata.gz: a661e632bae645066c291a078fdd60ce727d137e3bd5edf4778dbe5dad1554f18e1f88d99c4dbbea0bc92e09d042c7486c64c30fa77e3984ac3b0145e40d6f38
7
+ data.tar.gz: 60bfc3980c3128be77545fb6be4e8d88edd436b773f30a09cc930868f666b001ea1227e2c6e5bcbb17e7790273fa48f0df0e3c644b8426b8f140ca469e890404
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## Typekit Client 0.0.5 (June 10, 2014)
2
+ * New name for the general CLI: `typekit-client` instead of `typekit`.
3
+ * New CLI for the sole purpose of publishing kits: `typekit-publisher`.
4
+ * Relations between resources (a kit has families, a family has variations,
5
+ a variation belongs to a family, etc.).
6
+
1
7
  ## Typekit Client 0.0.4 (June 1, 2014)
2
8
  * Extraction of the RESTful API logic into a separate gem called
3
9
  [Apitizer](https://github.com/IvanUkhov/apitizer).
data/Guardfile CHANGED
@@ -1,7 +1,21 @@
1
1
  guard :rspec do
2
2
  watch(%r{^spec/.+_spec\.rb$})
3
- watch('spec/spec_helper.rb') { 'spec' }
4
- watch(%r{^spec/support/(.+)\.rb$}) { 'spec' }
5
- watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{ m[1] }_spec.rb" }
6
- watch(%r{^lib/(.*\.rb)$}) { |m| "spec/#{ File.dirname(m[1]) }" }
3
+ watch(%r{^spec/.+_helper\.rb$}) { 'spec' }
4
+ watch(%r{^lib/(.+)\.rb$}) do |match|
5
+ result = "spec/#{ match[1] }_spec.rb"
6
+ begin
7
+ break if File.exist?(result)
8
+ result = File.dirname(result)
9
+ end until result.empty?
10
+ result
11
+ end
12
+ watch(%r{^lib/[^/]+/(.+)\.rb$}) do |match|
13
+ result = "spec/features/#{ match[1] }"
14
+ begin
15
+ break if File.exist?(result)
16
+ result = File.dirname(result)
17
+ end until result.empty?
18
+ result
19
+ end
7
20
  end
21
+ # vim: ft=ruby
data/README.md CHANGED
@@ -2,24 +2,24 @@
2
2
  A Ruby library for accessing the [Typekit API](https://typekit.com/docs/api).
3
3
 
4
4
  ## Installation
5
- `Ruby >= 2.1` is required. Make sure you have it installed:
5
+ The minimal supported version of Ruby is `2.1`. The simplest way to install
6
+ Ruby is via [rvm](https://rvm.io/):
6
7
  ```bash
7
- $ ruby -v
8
- ruby 2.1.2p95 (2014-05-08 revision 45877) [x86_64-darwin13.0]
8
+ $ curl -sSL https://get.rvm.io | bash -s stable --ruby=2.1
9
9
  ```
10
10
 
11
- In case you don’t:
11
+ Now you can install the library itself:
12
12
  ```bash
13
- $ curl -sSL https://get.rvm.io | bash
14
- $ rvm install 2.1
13
+ $ gem install typekit-client
15
14
  ```
16
15
 
17
- Add the gem into your `Gemfile`:
16
+ If you are planning to use the gem as a part of your project, add the
17
+ following line into your `Gemfile`:
18
18
  ```ruby
19
19
  gem 'typekit-client', require: 'typekit'
20
20
  ```
21
21
 
22
- Then run `bundler`:
22
+ Then execute:
23
23
  ```bash
24
24
  $ bundle
25
25
  ```
@@ -39,26 +39,17 @@ require 'typekit'
39
39
  client = Typekit::Client.new(token: ENV['tk_token'])
40
40
  ```
41
41
 
42
- And here is how to run it, assuming you name your script `app.rb`:
43
- ```bash
44
- $ bundle exec ruby app.rb
45
- ```
46
-
47
- The main method of `client` is `perform(action, *path, parameters = {})`.
48
- The arguments are as follows:
49
- * `action` is the action that you would like to perform on a resource, and
50
- it can be one of `:index`, `:show`, `:create`, `:update`, or `:delete`;
42
+ `client` has five methods: `index`, `show`, `create`, `update`, and `delete`.
43
+ The signature of each method is `action(*path, parameters = {})`. The
44
+ arguments are as follows:
51
45
  * `*path` refers to an arbitrary number of arguments needed to identify
52
- the desired resource (a plenty of examples are given below), and it
53
- always begins with one of `:families`, `:kits`, or `:libraries`;
54
- * `parameters` is a hash of parameters needed to perform the action.
46
+ the endpoint of interest (a plenty of examples are given below);
47
+ * `parameters` is a hash of parameters (optional).
55
48
 
56
- `perform` has an alias for each of the actions: `index(*path, parameters = {})`,
57
- `show(*path, parameters = {})`, `create(*path, parameters = {})`, and so on.
58
- Before sending the actual request to the Typekit API, `perform` checks
59
- whether the resource given by `*path` makes sense and, if it does, whether
60
- `action` can be performed on that resource. So, if you receive an exception,
61
- check the [API reference](https://typekit.com/docs/api/).
49
+ Before sending the actual request to the Typekit API, the library checks
50
+ whether the endpoint given by `*path` exists and, if it does, whether
51
+ the desired action (`index`, `show`, _etc._) is permitted. So, if you
52
+ receive an exception, check the [API reference](https://typekit.com/docs/api/).
62
53
 
63
54
  Now, let us have a look at some typical use cases. For clarity, the code
64
55
  below makes use of the following auxiliary function:
@@ -70,7 +61,7 @@ rescue JSON::GeneratorError
70
61
  end
71
62
  ```
72
63
 
73
- ### Show all kits
64
+ ### List all kits
74
65
  Code:
75
66
  ```ruby
76
67
  p kits = client.index(:kits)
@@ -107,7 +98,7 @@ Output:
107
98
  "/api/v1/json/kits/bas4cfe"
108
99
  ```
109
100
 
110
- ### Show the description of a variant of a font family
101
+ ### Show the description of a variation of a font family
111
102
  Code:
112
103
  ```ruby
113
104
  p client.show(:families, 'vcsm', 'i9')
@@ -299,14 +290,14 @@ Output:
299
290
  true
300
291
  ```
301
292
 
302
- ## Command-line Interface (CLI)
303
- There is a simple CLI provided in order to demonstrate the usage of the
293
+ ## General Command-line Interface
294
+ There is a simple tool provided in order to demonstrate the usage of the
304
295
  library and to give the ability to perform basic operations without writing
305
- any code. The tool is called `typekit`, and it should get installed along
306
- with the gem. Try running:
296
+ any code. The tool is called `typekit-client`, and it should get installed
297
+ along with the gem. Try running:
307
298
  ```
308
- $ typekit -h
309
- Usage: typekit [options] [command]
299
+ $ typekit-client -h
300
+ Usage: typekit-client [options] [command]
310
301
 
311
302
  Required options:
312
303
  -t, --token TOKEN Set the API token
@@ -315,16 +306,16 @@ Other options:
315
306
  -h, --help Show this message
316
307
  ```
317
308
 
318
- Alternatively, you can install `typekit` in the `bin` directory of your
319
- project using the following command:
309
+ Alternatively, you can install `typekit-client` in the `bin` directory of
310
+ your project using the following command:
320
311
  ```bash
321
- $ bundle binstubs typekit
312
+ $ bundle binstubs typekit-client
322
313
  ```
323
314
 
324
315
  The tool has two modes: normal and interactive. If `command` is provided,
325
316
  the tool executes only that particular command and terminates:
326
317
  ```
327
- $ typekit -t $tk_token index kits
318
+ $ typekit-client -t $tk_token index kits
328
319
  [
329
320
  {
330
321
  "id": "bas4cfe",
@@ -338,7 +329,7 @@ $
338
329
  If `command` is not provided, the tool gives a command prompt wherein one
339
330
  can enter multiple commands:
340
331
  ```
341
- $ typekit -t $tk_token
332
+ $ typekit-client -t $tk_token
342
333
  Type 'help' for help and 'exit' to exit.
343
334
  > help
344
335
  Usage: <action> <resource> [parameters]
@@ -368,6 +359,38 @@ Bye.
368
359
  $
369
360
  ```
370
361
 
362
+ ## Publishing Command-line Interface
363
+ There is another utility with the sole purpose of publishing kits. The tool
364
+ is called `typekit-publisher`:
365
+
366
+ ```
367
+ $ typekit-publisher -h
368
+ Usage: typekit-publisher [options]
369
+
370
+ Required options:
371
+ -t, --token TOKEN Set the API token
372
+
373
+ Other options:
374
+ -h, --help Show this message
375
+ ```
376
+
377
+ Using `typekit-publisher`, you can publish all your kits at once. Here is
378
+ an example:
379
+
380
+ ```
381
+ $ typekit-publisher -t $tk_token
382
+ Which kit would you like to publish?
383
+ 1. bas4cfe
384
+ 2. sfh6bkj
385
+ 3. kof8zcn
386
+ 4. all
387
+ > 4
388
+ Publishing bas4cfe... Done.
389
+ Publishing sfh6bkj... Done.
390
+ Publishing kof8zcn... Done.
391
+ Bye.
392
+ ```
393
+
371
394
  ## Contributing
372
395
  1. Fork it ( https://github.com/IvanUkhov/typekit-client/fork )
373
396
  2. Create your feature branch (`git checkout -b my-new-feature`)
@@ -79,7 +79,7 @@ end
79
79
  options = {}
80
80
 
81
81
  parser = OptionParser.new do |o|
82
- o.banner = 'Usage: typekit [options] [command]'
82
+ o.banner = 'Usage: typekit-client [options] [command]'
83
83
 
84
84
  o.separator ''
85
85
  o.separator 'Required options:'
@@ -103,6 +103,19 @@ rescue
103
103
  exit
104
104
  end
105
105
 
106
+ unless options[:token]
107
+ puts <<-MESSAGE
108
+ You have not specified your API token. Try generating one here:
109
+
110
+ https://typekit.com/account/tokens
111
+
112
+ Then run:
113
+
114
+ $ typekit-client -t YOUR_TOKEN_GOES_HERE
115
+ MESSAGE
116
+ exit
117
+ end
118
+
106
119
  begin
107
120
  controller = Controller.new(options)
108
121
  rescue Exception => e
@@ -0,0 +1,89 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift(File.expand_path('../lib', __dir__))
4
+
5
+ require 'typekit'
6
+ require 'readline'
7
+ require 'optparse'
8
+
9
+ options = {}
10
+
11
+ parser = OptionParser.new do |o|
12
+ o.banner = 'Usage: typekit-publisher [options]'
13
+
14
+ o.separator ''
15
+ o.separator 'Required options:'
16
+
17
+ o.on('-t', '--token TOKEN', 'Set the API token') do |value|
18
+ options[:token] = value
19
+ end
20
+
21
+ o.separator ''
22
+ o.separator 'Other options:'
23
+
24
+ o.on_tail('-h', '--help', 'Show this message') do
25
+ raise
26
+ end
27
+ end
28
+
29
+ begin
30
+ parser.parse!
31
+ rescue
32
+ puts parser
33
+ exit
34
+ end
35
+
36
+ unless options[:token]
37
+ puts <<-MESSAGE
38
+ You have not specified your API token. Try generating one here:
39
+
40
+ https://typekit.com/account/tokens
41
+
42
+ Then run:
43
+
44
+ $ typekit-publisher -t YOUR_TOKEN_GOES_HERE
45
+ MESSAGE
46
+ exit
47
+ end
48
+
49
+ $client = Typekit::Client.new(token: options[:token])
50
+
51
+ def process(*arguments)
52
+ $client.process(*arguments)
53
+ rescue Typekit::Error => e
54
+ puts e
55
+ exit
56
+ end
57
+
58
+ kits = process(:index, :kits)
59
+
60
+ puts 'Which kit would you like to publish?'
61
+ kits.each_with_index do |kit, i|
62
+ puts "%4d. %s" % [ i + 1, kit.id ]
63
+ end
64
+ puts "%4d. all" % [ kits.length + 1 ]
65
+
66
+ k = Readline.readline('> ')
67
+ if k.nil? || k.empty?
68
+ puts 'None? OK.'
69
+ exit
70
+ end
71
+
72
+ k = k.to_i
73
+
74
+ if k < 1 || k > kits.length + 1
75
+ puts 'Invalid option. Try again.'
76
+ exit
77
+ end
78
+
79
+ range = k == kits.length + 1 ? 0...kits.length : [ k - 1 ]
80
+
81
+ range.each do |i|
82
+ print "Publishing #{ kits[i].id }..."
83
+ process(:update, :kits, kits[i].id, :publish)
84
+ puts ' Done.'
85
+ end
86
+
87
+ puts 'Bye.'
88
+
89
+ # vim: set ft=ruby
@@ -18,12 +18,12 @@ module Typekit
18
18
 
19
19
  private
20
20
 
21
- [ :engine, :translator ].each do |component|
22
- class_eval <<-METHOD, __FILE__, __LINE__ + 1
23
- def #{ component }
24
- @#{ component } ||= build_#{ component }
25
- end
26
- METHOD
21
+ def engine
22
+ @engine ||= build_engine
23
+ end
24
+
25
+ def translator
26
+ @translator ||= Processing::Translator.new
27
27
  end
28
28
 
29
29
  def build_engine
@@ -37,9 +37,5 @@ module Typekit
37
37
  instance_exec(version, format, &Typekit.schema)
38
38
  end
39
39
  end
40
-
41
- def build_translator
42
- Processing::Translator.new
43
- end
44
40
  end
45
41
  end
@@ -0,0 +1,15 @@
1
+ module Typekit
2
+ class Collection
3
+ extend Forwardable
4
+
5
+ def_delegator :@records, :to_json
6
+ def_delegators :@records, :each, :map, :[], :size, :length
7
+
8
+ def initialize(name, collection_attributes = nil)
9
+ @klass = Record.classify(name)
10
+ @records = collection_attributes.map do |attributes|
11
+ @klass.new(attributes)
12
+ end
13
+ end
14
+ end
15
+ end
data/lib/typekit/core.rb CHANGED
@@ -1,13 +1,13 @@
1
1
  module Typekit
2
2
  Error = Class.new(StandardError)
3
3
 
4
- @defaults = { version: 1, format: :json }.freeze
4
+ @defaults = { version: 1, format: :json }
5
5
 
6
6
  @schema = Proc.new do |version, format|
7
7
  address "https://typekit.com/api/v#{ version }/#{ format }"
8
8
 
9
9
  resources :families, only: :show do
10
- show ':variant', on: :member
10
+ show ':variation', on: :member
11
11
  end
12
12
 
13
13
  resources :kits do
@@ -19,7 +19,7 @@ module Typekit
19
19
  resources :libraries, only: [ :index, :show ]
20
20
  end
21
21
 
22
- @dictionary = { :update => :post }.freeze # not PUT, Typekit’s exception
22
+ @dictionary = { :update => :post } # not PUT
23
23
 
24
24
  @headers = Proc.new do |token|
25
25
  { 'X-Typekit-Token' => token }
@@ -21,5 +21,9 @@ module Typekit
21
21
  name
22
22
  end
23
23
  end
24
+
25
+ def self.symbolize_keys(hash)
26
+ Hash[hash.map { |k, v| [ k.to_sym, v ] }]
27
+ end
24
28
  end
25
29
  end
@@ -2,6 +2,9 @@ module Typekit
2
2
  module Processing
3
3
  module Converter
4
4
  class Boolean
5
+ def initialize(*_)
6
+ end
7
+
5
8
  def process(response, object)
6
9
  object # already boolean
7
10
  end
@@ -0,0 +1,18 @@
1
+ module Typekit
2
+ module Processing
3
+ module Converter
4
+ class Collection
5
+ def initialize(name)
6
+ @klass = Typekit::Record.classify(name)
7
+ raise Error, 'Unknown class' unless @klass
8
+ end
9
+
10
+ def process(response, collection_attributes)
11
+ collection_attributes.map do |attributes|
12
+ @klass.new(attributes)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -2,6 +2,9 @@ module Typekit
2
2
  module Processing
3
3
  module Converter
4
4
  class DateTime
5
+ def initialize(*_)
6
+ end
7
+
5
8
  def process(response, object)
6
9
  ::DateTime.parse(object)
7
10
  end
@@ -11,7 +11,9 @@ module Typekit
11
11
  503 => 'The Typekit API is offline for maintenance'
12
12
  }
13
13
  ERRORS.default = 'Unknown server error'
14
- ERRORS.freeze
14
+
15
+ def initialize(*_)
16
+ end
15
17
 
16
18
  def process(response, errors)
17
19
  raise Error, Array(errors || ERRORS[response.code]).join(', ')
@@ -3,7 +3,8 @@ module Typekit
3
3
  module Converter
4
4
  class Record
5
5
  def initialize(name)
6
- @klass = Typekit::Record.const_get(name.to_s.capitalize)
6
+ @klass = Typekit::Record.classify(name)
7
+ raise Error, 'Unknown class' unless @klass
7
8
  end
8
9
 
9
10
  def process(response, attributes)
@@ -1,5 +1,5 @@
1
1
  require_relative 'converter/record'
2
- require_relative 'converter/records'
2
+ require_relative 'converter/collection'
3
3
  require_relative 'converter/boolean'
4
4
  require_relative 'converter/datetime'
5
5
  require_relative 'converter/errors'
@@ -9,24 +9,19 @@ module Typekit
9
9
  module Processing
10
10
  module Converter
11
11
  MAPPING = {
12
+ :record => Record,
13
+ :collection => Collection,
14
+
12
15
  'ok' => Boolean,
13
16
  'errors' => Errors,
14
17
  'published' => DateTime,
18
+
15
19
  nil => Errors
16
- }.freeze
20
+ }
21
+ MAPPING.default = Unknown
17
22
 
18
23
  def self.build(name)
19
- if MAPPING.key?(name)
20
- MAPPING[name].new
21
- elsif Typekit::Record.collection?(name)
22
- Records.new(name)
23
- elsif Typekit::Record.member?(name)
24
- Record.new(name)
25
- else
26
- Unknown.new(name)
27
- end
28
- rescue NameError
29
- raise Error, 'Unknown converter'
24
+ MAPPING[Typekit::Record.identify(name) || name].new(name)
30
25
  end
31
26
  end
32
27
  end
@@ -1,5 +1,3 @@
1
- require 'forwardable'
2
-
3
1
  module Typekit
4
2
  module Record
5
3
  class Base
@@ -8,23 +6,47 @@ module Typekit
8
6
  attr_reader :attributes
9
7
  def_delegator :attributes, :to_json
10
8
 
9
+ def self.has_many(name)
10
+ possessions << name
11
+ end
12
+
13
+ def self.possessions
14
+ @possessions ||= []
15
+ end
16
+
17
+ def self.belongs_to(name)
18
+ owners << name
19
+ end
20
+
21
+ def self.owners
22
+ @owners ||= []
23
+ end
24
+
11
25
  def initialize(attributes = {})
12
- @attributes = Hash[attributes.map { |k, v| [ k.to_sym, v ] }]
26
+ attributes = { id: attributes } unless attributes.is_a?(Hash)
27
+ @attributes = Helper.symbolize_keys(attributes)
28
+
29
+ self.class.possessions.each do |name|
30
+ next unless @attributes.key?(name)
31
+ @attributes[name] = Collection.new(name, @attributes[name])
32
+ end
33
+
34
+ self.class.owners.each do |name|
35
+ next unless @attributes.key?(name)
36
+ @attributes[name] = Record.build(name, @attributes[name])
37
+ end
13
38
  end
14
39
 
15
40
  def method_missing(name, *arguments)
16
41
  if name.to_s =~ /^(?<name>.*)=$/
17
42
  name = Regexp.last_match(:name).to_sym
18
- return super unless arguments.length == 1
19
43
  return super unless @attributes.key?(name)
20
- @attributes[name] = arguments.first
44
+ @attributes.send(:[]=, name, *arguments)
21
45
  else
22
- return super unless arguments.length.zero?
23
46
  return super unless @attributes.key?(name)
24
- @attributes[name]
47
+ @attributes.send(:[], name, *arguments)
25
48
  end
26
49
  end
27
50
  end
28
51
  end
29
52
  end
30
-
@@ -1,7 +1,8 @@
1
1
  module Typekit
2
2
  module Record
3
3
  class Family < Base
4
- # has_many :libraries, :variations
4
+ has_many :libraries
5
+ has_many :variations
5
6
  end
6
7
  end
7
8
  end
@@ -1,7 +1,7 @@
1
1
  module Typekit
2
2
  module Record
3
3
  class Kit < Base
4
- # has_many :families
4
+ has_many :families
5
5
  end
6
6
  end
7
7
  end
@@ -1,7 +1,7 @@
1
1
  module Typekit
2
2
  module Record
3
3
  class Library < Base
4
- # has_many :families
4
+ has_many :families
5
5
  end
6
6
  end
7
7
  end
@@ -1,8 +1,8 @@
1
1
  module Typekit
2
2
  module Record
3
3
  class Variation < Base
4
- # belongs_to :family
5
- # has_many :libraries
4
+ has_many :libraries
5
+ belongs_to :family
6
6
  end
7
7
  end
8
8
  end