dato 0.1.5 → 0.1.6

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.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +24 -0
  3. data/Gemfile +1 -0
  4. data/Rakefile +25 -9
  5. data/bin/console +4 -3
  6. data/dato.gemspec +28 -23
  7. data/lib/dato.rb +5 -3
  8. data/lib/dato/account/client.rb +6 -5
  9. data/lib/dato/account/repo/account.rb +9 -10
  10. data/lib/dato/account/repo/base.rb +3 -3
  11. data/lib/dato/account/repo/site.rb +7 -8
  12. data/lib/dato/api_error.rb +3 -2
  13. data/lib/dato/json_api_deserializer.rb +7 -9
  14. data/lib/dato/json_api_serializer.rb +4 -5
  15. data/lib/dato/local/entities_repo.rb +46 -0
  16. data/lib/dato/local/field_type/boolean.rb +12 -0
  17. data/lib/dato/local/field_type/date.rb +12 -0
  18. data/lib/dato/local/field_type/date_time.rb +12 -0
  19. data/lib/dato/local/field_type/file.rb +33 -0
  20. data/lib/dato/local/field_type/float.rb +12 -0
  21. data/lib/dato/local/field_type/image.rb +32 -0
  22. data/lib/dato/local/field_type/integer.rb +12 -0
  23. data/lib/dato/local/field_type/lat_lon.rb +23 -0
  24. data/lib/dato/local/field_type/link.rb +12 -0
  25. data/lib/dato/local/field_type/links.rb +12 -0
  26. data/lib/dato/local/field_type/seo.rb +24 -0
  27. data/lib/dato/local/field_type/string.rb +12 -0
  28. data/lib/dato/local/field_type/text.rb +12 -0
  29. data/lib/dato/local/field_type/video.rb +55 -0
  30. data/lib/dato/local/item.rb +121 -0
  31. data/lib/dato/local/items_repo.rb +110 -0
  32. data/lib/dato/local/json_api_entity.rb +78 -0
  33. data/lib/dato/local/site.rb +57 -0
  34. data/lib/dato/site/client.rb +6 -5
  35. data/lib/dato/site/repo/base.rb +3 -2
  36. data/lib/dato/site/repo/field.rb +3 -4
  37. data/lib/dato/site/repo/item.rb +6 -7
  38. data/lib/dato/site/repo/item_type.rb +6 -7
  39. data/lib/dato/site/repo/menu_item.rb +8 -9
  40. data/lib/dato/site/repo/site.rb +5 -6
  41. data/lib/dato/site/repo/upload_request.rb +3 -4
  42. data/lib/dato/site/repo/user.rb +8 -9
  43. data/lib/dato/upload/file.rb +6 -5
  44. data/lib/dato/upload/image.rb +3 -3
  45. data/lib/dato/version.rb +2 -1
  46. metadata +77 -1
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+ module Dato
3
+ module Local
4
+ module FieldType
5
+ class Boolean
6
+ def self.parse(value, _repo)
7
+ value
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+ module Dato
3
+ module Local
4
+ module FieldType
5
+ class Date
6
+ def self.parse(value, _repo)
7
+ ::Date.parse(value)
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+ module Dato
3
+ module Local
4
+ module FieldType
5
+ class DateTime
6
+ def self.parse(value, _repo)
7
+ ::Time.parse(value)
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+ require 'imgix'
3
+
4
+ module Dato
5
+ module Local
6
+ module FieldType
7
+ class File
8
+ attr_reader :path, :format, :size
9
+
10
+ def self.parse(value, _repo)
11
+ new(
12
+ value[:path],
13
+ value[:format],
14
+ value[:size]
15
+ )
16
+ end
17
+
18
+ def initialize(path, format, size)
19
+ @path = path
20
+ @format = format
21
+ @size = size
22
+ end
23
+
24
+ def file
25
+ Imgix::Client.new(
26
+ host: 'dato-images.imgix.net',
27
+ secure: true
28
+ ).path(path)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+ module Dato
3
+ module Local
4
+ module FieldType
5
+ class Float
6
+ def self.parse(value, _repo)
7
+ value
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+ require 'dato/local/field_type/file'
3
+
4
+ module Dato
5
+ module Local
6
+ module FieldType
7
+ class Image < Dato::Local::FieldType::File
8
+ attr_reader :width, :height
9
+
10
+ def self.parse(value, _repo)
11
+ new(
12
+ value[:path],
13
+ value[:format],
14
+ value[:size],
15
+ value[:width],
16
+ value[:height]
17
+ )
18
+ end
19
+
20
+ def initialize(path, format, size, width, height)
21
+ super(path, format, size)
22
+ @width = width
23
+ @height = height
24
+ end
25
+
26
+ def file
27
+ super.ch('DPR', 'Width').auto('compress', 'format')
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+ module Dato
3
+ module Local
4
+ module FieldType
5
+ class Integer
6
+ def self.parse(value, _repo)
7
+ value
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+ module Dato
3
+ module Local
4
+ module FieldType
5
+ class LatLon
6
+ attr_reader :latitude, :longitude
7
+
8
+ def self.parse(value, _repo)
9
+ new(value[:latitude], value[:longitude])
10
+ end
11
+
12
+ def initialize(latitude, longitude)
13
+ @latitude = latitude
14
+ @longitude = longitude
15
+ end
16
+
17
+ def values
18
+ [latitude, longitude]
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+ module Dato
3
+ module Local
4
+ module FieldType
5
+ class Link
6
+ def self.parse(value, repo)
7
+ repo.find(value)
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+ module Dato
3
+ module Local
4
+ module FieldType
5
+ class Links
6
+ def self.parse(ids, repo)
7
+ ids.map { |id| repo.find(id) }
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+ module Dato
3
+ module Local
4
+ module FieldType
5
+ class Seo
6
+ attr_reader :title, :description
7
+
8
+ def self.parse(value, _repo)
9
+ new(value[:title], value[:description], value[:image])
10
+ end
11
+
12
+ def initialize(title, description, image)
13
+ @title = title
14
+ @description = description
15
+ @image = image
16
+ end
17
+
18
+ def image
19
+ @image && Image.parse(@image, nil)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+ module Dato
3
+ module Local
4
+ module FieldType
5
+ class String
6
+ def self.parse(value, _repo)
7
+ value
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+ module Dato
3
+ module Local
4
+ module FieldType
5
+ class Text
6
+ def self.parse(value, _repo)
7
+ value
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+ require 'active_support/core_ext/hash/compact'
3
+ require 'video_embed'
4
+
5
+ module Dato
6
+ module Local
7
+ module FieldType
8
+ class Video
9
+ def self.parse(value, _repo)
10
+ new(value)
11
+ end
12
+
13
+ def initialize(attributes)
14
+ @attributes = attributes
15
+ end
16
+
17
+ def url
18
+ @attributes[:url]
19
+ end
20
+
21
+ def thumbnail_url
22
+ @attributes[:thumbnail_url]
23
+ end
24
+
25
+ def title
26
+ @attributes[:title]
27
+ end
28
+
29
+ def width
30
+ @attributes[:width]
31
+ end
32
+
33
+ def height
34
+ @attributes[:height]
35
+ end
36
+
37
+ def provider
38
+ @attributes[:provider]
39
+ end
40
+
41
+ def provider_url
42
+ @attributes[:provider_url]
43
+ end
44
+
45
+ def provider_uid
46
+ @attributes[:provider_uid]
47
+ end
48
+
49
+ def iframe_embed(width = nil, height = nil)
50
+ VideoEmbed.embed(url, { width: width, height: height }.compact)
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,121 @@
1
+ # frozen_string_literal: true
2
+ require 'forwardable'
3
+ require 'active_support/inflector/transliterate'
4
+ require 'active_support/hash_with_indifferent_access'
5
+
6
+ Dir[File.dirname(__FILE__) + '/field_type/*.rb'].each do |file|
7
+ require file
8
+ end
9
+
10
+ module Dato
11
+ module Local
12
+ class Item
13
+ extend Forwardable
14
+
15
+ attr_reader :entity
16
+ def_delegators :entity, :id, :type, :item_type
17
+
18
+ def initialize(entity, items_repo)
19
+ @entity = entity
20
+ @items_repo = items_repo
21
+ end
22
+
23
+ def ==(other)
24
+ other.is_a?(Item) && other.id == id
25
+ end
26
+
27
+ def slug
28
+ return item_type.api_key.humanize.parameterize if singleton?
29
+ return id.to_s unless title_attribute
30
+
31
+ title = send(title_attribute)
32
+ if title
33
+ "#{id}-#{title.parameterize[0..50]}"
34
+ else
35
+ id.to_s
36
+ end
37
+ end
38
+
39
+ def singleton?
40
+ item_type.singleton
41
+ end
42
+
43
+ def item_type
44
+ @item_type ||= entity.item_type
45
+ end
46
+ alias content_type item_type
47
+
48
+ def fields
49
+ @fields ||= item_type.fields.sort_by(&:position)
50
+ end
51
+
52
+ def attributes
53
+ @attributes ||= fields.each_with_object(
54
+ ActiveSupport::HashWithIndifferentAccess.new
55
+ ) do |field, acc|
56
+ acc[field.api_key.to_sym] = send(field.api_key)
57
+ end
58
+ end
59
+
60
+ def position
61
+ entity.position
62
+ end
63
+
64
+ def updated_at
65
+ Time.parse(entity.updated_at)
66
+ end
67
+
68
+ def to_s
69
+ api_key = item_type.api_key
70
+ "#<Item id=#{id} item_type=#{api_key} attributes=#{attributes}>"
71
+ end
72
+ alias inspect to_s
73
+
74
+ def title_attribute
75
+ title_field = fields.find do |field|
76
+ field.field_type == 'string' &&
77
+ field.appeareance[:type] == 'title'
78
+ end
79
+ title_field && title_field.api_key
80
+ end
81
+
82
+ def respond_to_missing?(method, include_private = false)
83
+ field = fields.find { |f| f.api_key.to_sym == method }
84
+ if field
85
+ true
86
+ else
87
+ super
88
+ end
89
+ end
90
+
91
+ private
92
+
93
+ def read_attribute(method, field)
94
+ field_type = field.field_type
95
+ type_klass_name = "::Dato::Local::FieldType::#{field_type.camelize}"
96
+ type_klass = type_klass_name.safe_constantize
97
+
98
+ if type_klass
99
+ value = if field.localized
100
+ (entity.send(method) || {})[I18n.locale]
101
+ else
102
+ entity.send(method)
103
+ end
104
+
105
+ value && type_klass.parse(value, @items_repo)
106
+ else
107
+ raise "Cannot convert field `#{method}` of type `#{field_type}`"
108
+ end
109
+ end
110
+
111
+ def method_missing(method, *arguments, &block)
112
+ field = fields.find { |f| f.api_key.to_sym == method }
113
+ if field && arguments.empty?
114
+ read_attribute(method, field)
115
+ else
116
+ super
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,110 @@
1
+ # frozen_string_literal: true
2
+ require 'active_support/core_ext/string'
3
+ require 'dato/local/item'
4
+
5
+ module Dato
6
+ module Local
7
+ class ItemsRepo
8
+ attr_reader :entities_repo, :collections_by_type
9
+
10
+ def initialize(entities_repo)
11
+ @entities_repo = entities_repo
12
+ @collections_by_type = {}
13
+ @items_by_id = {}
14
+
15
+ build_cache!
16
+ end
17
+
18
+ def find(id)
19
+ @items_by_id[id]
20
+ end
21
+
22
+ def respond_to_missing?(method, include_private = false)
23
+ if collections_by_type.key?(method)
24
+ true
25
+ else
26
+ super
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ def item_type_key(item_type)
33
+ api_key = item_type.api_key
34
+ if item_type.singleton
35
+ [api_key.to_sym, true]
36
+ else
37
+ [api_key.pluralize.to_sym, false]
38
+ end
39
+ end
40
+
41
+ def build_cache!
42
+ item_type_entities.each do |item_type|
43
+ key, singleton = item_type_key(item_type)
44
+ @collections_by_type[key] = if singleton
45
+ nil
46
+ else
47
+ ItemCollection.new
48
+ end
49
+ end
50
+
51
+ item_entities.each do |item_entity|
52
+ item = Item.new(item_entity, self)
53
+
54
+ key, singleton = item_type_key(item_entity.item_type)
55
+ if singleton
56
+ @collections_by_type[key] = item
57
+ else
58
+ @collections_by_type[key].push item
59
+ end
60
+
61
+ @items_by_id[item.id] = item
62
+ end
63
+ end
64
+
65
+ def item_type_entities
66
+ entities_repo.find_entities_of_type('item_type')
67
+ end
68
+
69
+ def item_entities
70
+ entities_repo.find_entities_of_type('item')
71
+ end
72
+
73
+ def method_missing(method, *arguments, &block)
74
+ if collections_by_type.key?(method) && arguments.empty?
75
+ collections_by_type[method]
76
+ else
77
+ super
78
+ end
79
+ end
80
+
81
+ class ItemCollection < Array
82
+ def each(&block)
83
+ if block && block.arity == 2
84
+ each_with_object({}) do |item, acc|
85
+ acc[item.id] = item
86
+ end.each(&block)
87
+ else
88
+ super(&block)
89
+ end
90
+ end
91
+
92
+ def [](id)
93
+ if id.is_a? String
94
+ find { |item| item.id == id }
95
+ else
96
+ super(id)
97
+ end
98
+ end
99
+
100
+ def keys
101
+ map(&:id)
102
+ end
103
+
104
+ def values
105
+ to_a
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end