middleman-dato 0.0.1.rc12 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/.gitlab-ci.yml +7 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +9 -1070
  5. data/Gemfile +8 -8
  6. data/Rakefile +14 -5
  7. data/foo.rb +12 -0
  8. data/lib/dato/client.rb +14 -9
  9. data/lib/dato/entities_repo.rb +43 -0
  10. data/lib/dato/field_type/boolean.rb +9 -0
  11. data/lib/dato/field_type/date.rb +9 -0
  12. data/lib/dato/field_type/date_time.rb +9 -0
  13. data/lib/dato/field_type/file.rb +30 -0
  14. data/lib/dato/field_type/float.rb +9 -0
  15. data/lib/dato/field_type/image.rb +23 -0
  16. data/lib/dato/field_type/integer.rb +9 -0
  17. data/lib/dato/field_type/lat_lon.rb +16 -0
  18. data/lib/dato/field_type/link.rb +9 -0
  19. data/lib/dato/field_type/links.rb +9 -0
  20. data/lib/dato/field_type/seo.rb +21 -0
  21. data/lib/dato/field_type/string.rb +9 -0
  22. data/lib/dato/field_type/text.rb +9 -0
  23. data/lib/dato/field_type/video.rb +48 -0
  24. data/lib/dato/json_api_entity.rb +75 -0
  25. data/lib/dato/meta_tags/article_modified_time.rb +3 -3
  26. data/lib/dato/meta_tags/article_publisher.rb +3 -3
  27. data/lib/dato/meta_tags/base.rb +12 -19
  28. data/lib/dato/meta_tags/description.rb +4 -4
  29. data/lib/dato/meta_tags/image.rb +5 -8
  30. data/lib/dato/meta_tags/og_locale.rb +2 -2
  31. data/lib/dato/meta_tags/og_meta_tag.rb +2 -4
  32. data/lib/dato/meta_tags/og_site_name.rb +2 -2
  33. data/lib/dato/meta_tags/og_type.rb +5 -5
  34. data/lib/dato/meta_tags/robots.rb +2 -4
  35. data/lib/dato/meta_tags/title.rb +5 -4
  36. data/lib/dato/meta_tags/twitter_card.rb +3 -3
  37. data/lib/dato/meta_tags/twitter_meta_tag.rb +2 -4
  38. data/lib/dato/meta_tags/twitter_site.rb +2 -2
  39. data/lib/dato/meta_tags/url.rb +4 -4
  40. data/lib/dato/meta_tags_builder.rb +13 -13
  41. data/lib/dato/middleman_extension.rb +15 -23
  42. data/lib/dato/record.rb +77 -46
  43. data/lib/dato/records_repo.rb +106 -0
  44. data/lib/dato/space.rb +36 -0
  45. data/lib/middleman-dato.rb +5 -2
  46. data/middleman-dato.gemspec +14 -13
  47. data/spec/dato/entities_repo_spec.rb +41 -0
  48. data/spec/dato/field_type/file_spec.rb +20 -0
  49. data/spec/dato/field_type/image_spec.rb +24 -0
  50. data/spec/dato/field_type/lat_lon_spec.rb +18 -0
  51. data/spec/dato/field_type/seo_spec.rb +31 -0
  52. data/spec/dato/field_type/video_spec.rb +32 -0
  53. data/spec/dato/json_api_entity_spec.rb +123 -0
  54. data/spec/dato/meta_tags/article_modified_time_spec.rb +16 -14
  55. data/spec/dato/meta_tags/image_spec.rb +39 -0
  56. data/spec/dato/meta_tags/og_locale_spec.rb +14 -12
  57. data/spec/dato/record_spec.rb +137 -78
  58. data/spec/dato/records_repo_spec.rb +125 -0
  59. data/spec/spec_helper.rb +14 -12
  60. metadata +58 -13
  61. data/lib/dato/field.rb +0 -43
  62. data/lib/dato/fields/belongs_to.rb +0 -21
  63. data/lib/dato/fields/file.rb +0 -22
  64. data/lib/dato/fields/seo.rb +0 -37
  65. data/lib/dato/repo.rb +0 -111
  66. data/lib/middleman_extension.rb +0 -1
  67. data/spec/dato/field_spec.rb +0 -110
data/lib/dato/record.rb CHANGED
@@ -1,77 +1,108 @@
1
- require "active_support/core_ext/hash/indifferent_access"
2
- require "dato/field"
1
+ require 'forwardable'
2
+ require 'active_support/inflector/transliterate'
3
3
 
4
- module Slugify
5
- refine String do
6
- def to_slug
7
- downcase.strip.gsub(" ", "-").gsub(/[^\w-]/, "")
8
- end
9
- end
4
+ Dir[File.dirname(__FILE__) + '/field_type/*.rb'].each do |file|
5
+ require file
10
6
  end
11
7
 
12
8
  module Dato
13
9
  class Record
14
- using Slugify
15
- attr_reader :attributes, :fields, :content_type
16
-
17
- def initialize(attributes, content_type)
18
- @attributes = attributes.with_indifferent_access
19
- @content_type = content_type
20
- @fields = content_type[:fields].with_indifferent_access
21
- @values = {}
10
+ extend Forwardable
11
+
12
+ attr_reader :entity
13
+ def_delegators :entity, :id, :type
14
+
15
+ def initialize(entity, records_repo)
16
+ @entity = entity
17
+ @records_repo = records_repo
18
+ end
19
+
20
+ def slug
21
+ if singleton?
22
+ content_type.api_key.humanize.parameterize
23
+ elsif title_attribute
24
+ "#{id}-#{send(title_attribute).parameterize}"
25
+ else
26
+ id.to_s
27
+ end
22
28
  end
23
29
 
24
30
  def singleton?
25
- @singleton = content_type[:singleton]
31
+ content_type.singleton
26
32
  end
27
33
 
28
- def respond_to?(method, include_private = false)
29
- if @attributes.has_key?(method)
30
- true
31
- else
32
- super
34
+ def content_type
35
+ entity.content_type
36
+ end
37
+
38
+ def fields
39
+ content_type.fields.sort_by(&:position)
40
+ end
41
+
42
+ def attributes
43
+ fields.each_with_object({}) do |field, acc|
44
+ acc[field.api_key.to_sym] = send(field.api_key)
33
45
  end
34
46
  end
35
47
 
36
- def id
37
- @attributes[:id]
48
+ def position
49
+ entity.position
38
50
  end
39
51
 
40
52
  def updated_at
41
- Time.parse(@attributes[:updated_at])
53
+ Time.parse(entity.updated_at)
42
54
  end
43
55
 
44
- def method_missing(method, *arguments, &block)
45
- if @attributes.has_key?(method) && arguments.size == 0
46
- read_attribute(method.to_sym)
47
- else
48
- super
49
- end
56
+ def to_s
57
+ api_key = content_type.api_key
58
+ "#<Record id=#{id} content_type=#{api_key} attributes=#{attributes}>"
50
59
  end
60
+ alias inspect to_s
51
61
 
52
- def slug
53
- field_name = content_type[:fields].select do |_name, data|
54
- data[:field_type] == "title"
55
- end.shift.first
56
-
57
- "#{id}-#{send(field_name).to_slug}"
58
- rescue NoMethodError
59
- # there is no title
60
- return nil
62
+ def title_attribute
63
+ title_field = fields.find do |field|
64
+ field.field_type == 'string' &&
65
+ field.appeareance[:type] == 'title'
66
+ end
67
+ title_field && title_field.api_key
61
68
  end
62
69
 
63
- def ==(other)
64
- if other.is_a? Record
65
- id == other.id
70
+ def respond_to?(method, include_private = false)
71
+ field = fields.find { |f| f.api_key.to_sym == method }
72
+ if field
73
+ true
66
74
  else
67
- false
75
+ super
68
76
  end
69
77
  end
70
78
 
71
79
  private
72
80
 
73
- def read_attribute(name)
74
- Field.value(attributes[name], fields[name])
81
+ def read_attribute(method, field)
82
+ field_type = field.field_type
83
+ type_klass_name = "::Dato::FieldType::#{field_type.camelize}"
84
+ type_klass = type_klass_name.safe_constantize
85
+
86
+ if type_klass
87
+ value = if field.localized
88
+ (entity.send(method) || {})[I18n.locale]
89
+ else
90
+ entity.send(method)
91
+ end
92
+
93
+ value && type_klass.parse(value, @records_repo)
94
+ else
95
+ raise "Cannot convert field `#{method}` of type `#{field_type}`"
96
+ end
97
+ end
98
+
99
+ def method_missing(method, *arguments, &block)
100
+ field = fields.find { |f| f.api_key.to_sym == method }
101
+ if field && arguments.empty?
102
+ read_attribute(method, field)
103
+ else
104
+ super
105
+ end
75
106
  end
76
107
  end
77
108
  end
@@ -0,0 +1,106 @@
1
+ require 'active_support/core_ext/string'
2
+ require 'dato/record'
3
+
4
+ module Dato
5
+ class RecordsRepo
6
+ attr_reader :entities_repo, :collections_by_type
7
+
8
+ def initialize(entities_repo)
9
+ @entities_repo = entities_repo
10
+ @collections_by_type = {}
11
+
12
+ build_collections_by_type!
13
+ end
14
+
15
+ def find(id)
16
+ collections_by_type.values.flatten.find do |record|
17
+ record && record.id == id
18
+ end
19
+ end
20
+
21
+ def respond_to?(method, include_private = false)
22
+ if collections_by_type.key?(method)
23
+ true
24
+ else
25
+ super
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ def content_type_key(content_type)
32
+ api_key = content_type.api_key
33
+ if content_type.singleton
34
+ [api_key.to_sym, true]
35
+ else
36
+ [api_key.pluralize.to_sym, false]
37
+ end
38
+ end
39
+
40
+ def build_collections_by_type!
41
+ content_type_entities.each do |content_type|
42
+ key, singleton = content_type_key(content_type)
43
+ @collections_by_type[key] = if singleton
44
+ nil
45
+ else
46
+ RecordCollection.new
47
+ end
48
+ end
49
+
50
+ record_entities.each do |record_entity|
51
+ record = Record.new(record_entity, self)
52
+
53
+ key, singleton = content_type_key(record_entity.content_type)
54
+ if singleton
55
+ @collections_by_type[key] = record
56
+ else
57
+ @collections_by_type[key].push record
58
+ end
59
+ end
60
+ end
61
+
62
+ def content_type_entities
63
+ entities_repo.find_entities_of_type('content_type')
64
+ end
65
+
66
+ def record_entities
67
+ entities_repo.find_entities_of_type('record')
68
+ end
69
+
70
+ def method_missing(method, *arguments, &block)
71
+ if collections_by_type.key?(method) && arguments.empty?
72
+ collections_by_type[method]
73
+ else
74
+ super
75
+ end
76
+ end
77
+
78
+ class RecordCollection < Array
79
+ def each(&block)
80
+ if block && block.arity == 2
81
+ each_with_object({}) do |record, acc|
82
+ acc[record.id] = record
83
+ end.each(&block)
84
+ else
85
+ super(&block)
86
+ end
87
+ end
88
+
89
+ def [](id)
90
+ if id.is_a? String
91
+ find { |record| record.id == id }
92
+ else
93
+ super(id)
94
+ end
95
+ end
96
+
97
+ def keys
98
+ map(&:id)
99
+ end
100
+
101
+ def values
102
+ to_a
103
+ end
104
+ end
105
+ end
106
+ end
data/lib/dato/space.rb ADDED
@@ -0,0 +1,36 @@
1
+ require 'dato/client'
2
+ require 'dato/entities_repo'
3
+ require 'dato/records_repo'
4
+
5
+ module Dato
6
+ class Space
7
+ attr_reader :options
8
+ attr_reader :entities_repo
9
+ attr_reader :records_repo
10
+
11
+ def initialize(options)
12
+ @options = options
13
+ @entities_repo = EntitiesRepo.new
14
+ @records_repo = RecordsRepo.new(@entities_repo)
15
+ end
16
+
17
+ def refresh!
18
+ @entities_repo = EntitiesRepo.new(client.space, client.records)
19
+ @records_repo = RecordsRepo.new(@entities_repo)
20
+ end
21
+
22
+ def entity
23
+ @entities_repo.find_entities_of_type('space').first
24
+ end
25
+
26
+ private
27
+
28
+ def client
29
+ @client ||= Client.new(
30
+ options[:api_host],
31
+ options[:domain],
32
+ options[:token]
33
+ )
34
+ end
35
+ end
36
+ end
@@ -1,3 +1,6 @@
1
- require "dato/middleman_extension"
1
+ require "middleman-core"
2
2
 
3
- Dato::MiddlemanExtension.register(:dato)
3
+ Middleman::Extensions.register(:dato) do
4
+ require "dato/middleman_extension"
5
+ Dato::MiddlemanExtension
6
+ end
@@ -1,25 +1,26 @@
1
1
  # -*- encoding: utf-8 -*-
2
- $:.push File.expand_path("../lib", __FILE__)
2
+ $LOAD_PATH.push File.expand_path('../lib', __FILE__)
3
3
 
4
4
  Gem::Specification.new do |s|
5
- s.name = "middleman-dato"
6
- s.version = "0.0.1.rc12"
5
+ s.name = 'middleman-dato'
6
+ s.version = '0.5.0'
7
7
  s.platform = Gem::Platform::RUBY
8
- s.authors = ["Stefano Verna"]
9
- s.email = ["s.verna@cantierecreativo.net"]
10
- s.homepage = "http://cantierecreativo.net"
11
- s.summary = "Fetches data from a Dato space"
12
- s.description = "Fetches data from a Dato space"
8
+ s.authors = ['Stefano Verna']
9
+ s.email = ['s.verna@cantierecreativo.net']
10
+ s.homepage = 'http://cantierecreativo.net'
11
+ s.summary = 'Fetches data from a Dato space'
12
+ s.description = 'Fetches data from a Dato space'
13
13
 
14
14
  s.files = `git ls-files`.split("\n")
15
15
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
16
  s.executables = `git ls-files -- bin/*`.split("\n").map do |f|
17
17
  File.basename(f)
18
18
  end
19
- s.require_paths = ["lib"]
19
+ s.require_paths = ['lib']
20
20
 
21
- s.add_runtime_dependency("middleman-core", [">= 3.3.12"])
22
- s.add_runtime_dependency("faraday", [">= 0.9.0"])
23
- s.add_runtime_dependency("faraday_middleware", [">= 0.9.0"])
24
- s.add_runtime_dependency("imgix", [">= 0.3.1"])
21
+ s.add_runtime_dependency('middleman-core', ['>= 3.3.12'])
22
+ s.add_runtime_dependency('faraday', ['>= 0.9.0'])
23
+ s.add_runtime_dependency('faraday_middleware', ['>= 0.9.0'])
24
+ s.add_runtime_dependency('imgix', ['>= 0.3.1'])
25
+ s.add_runtime_dependency('video_embed')
25
26
  end
@@ -0,0 +1,41 @@
1
+ require 'dato/json_api_entity'
2
+
3
+ module Dato
4
+ RSpec.describe EntitiesRepo do
5
+ subject(:source) { described_class.new(payload) }
6
+
7
+ describe '#entities' do
8
+ context 'a payload with a data key' do
9
+ context 'object' do
10
+ let(:payload) do
11
+ { data: { id: 'bar', type: 'record' } }
12
+ end
13
+
14
+ it 'inserts the object into entities' do
15
+ expect(source.entities['record']['bar']).to be_a JsonApiEntity
16
+ end
17
+ end
18
+
19
+ context 'array' do
20
+ let(:payload) do
21
+ { data: [{ id: 'bar', type: 'record' }] }
22
+ end
23
+
24
+ it 'inserts the objects into entities' do
25
+ expect(source.entities['record']['bar']).to be_a JsonApiEntity
26
+ end
27
+ end
28
+ end
29
+
30
+ context 'a payload with an included key' do
31
+ let(:payload) do
32
+ { included: [{ id: 'bar', type: 'record' }] }
33
+ end
34
+
35
+ it 'inserts the objects into entities' do
36
+ expect(source.entities['record']['bar']).to be_a JsonApiEntity
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,20 @@
1
+ module Dato
2
+ module FieldType
3
+ RSpec.describe Dato::FieldType::File do
4
+ subject(:file) { described_class.parse(attributes, nil) }
5
+ let(:attributes) do
6
+ {
7
+ path: '/foo.png',
8
+ format: 'jpg',
9
+ size: 4000
10
+ }
11
+ end
12
+
13
+ it 'responds to path, format and size methods' do
14
+ expect(file.path).to eq '/foo.png'
15
+ expect(file.format).to eq 'jpg'
16
+ expect(file.size).to eq 4000
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,24 @@
1
+ module Dato
2
+ module FieldType
3
+ RSpec.describe Image do
4
+ subject(:image) { described_class.parse(attributes, nil) }
5
+ let(:attributes) do
6
+ {
7
+ path: '/foo.png',
8
+ format: 'jpg',
9
+ size: 4000,
10
+ width: 20,
11
+ height: 20
12
+ }
13
+ end
14
+
15
+ it 'responds to path, format, size, width and height' do
16
+ expect(image.path).to eq '/foo.png'
17
+ expect(image.format).to eq 'jpg'
18
+ expect(image.size).to eq 4000
19
+ expect(image.width).to eq 20
20
+ expect(image.height).to eq 20
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,18 @@
1
+ module Dato
2
+ module FieldType
3
+ RSpec.describe LatLon do
4
+ subject(:latlon) { described_class.parse(attributes, nil) }
5
+ let(:attributes) do
6
+ {
7
+ latitude: 12,
8
+ longitude: 10
9
+ }
10
+ end
11
+
12
+ it 'responds to latitude and longitude methods' do
13
+ expect(latlon.latitude).to eq 12
14
+ expect(latlon.longitude).to eq 10
15
+ end
16
+ end
17
+ end
18
+ end