dato 0.1.5 → 0.1.6

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