contentful_model 0.2.0 → 1.0.0
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.
- checksums.yaml +5 -5
- data/lib/contentful_model.rb +17 -13
- data/lib/contentful_model/asset.rb +30 -0
- data/lib/contentful_model/asset_dimension_query.rb +70 -0
- data/lib/contentful_model/asset_dimensions.rb +54 -0
- data/lib/contentful_model/associations/associations.rb +10 -4
- data/lib/contentful_model/associations/belongs_to.rb +9 -4
- data/lib/contentful_model/associations/belongs_to_many.rb +22 -45
- data/lib/contentful_model/associations/has_many.rb +15 -13
- data/lib/contentful_model/associations/has_many_nested.rb +39 -37
- data/lib/contentful_model/associations/has_one.rb +22 -14
- data/lib/contentful_model/base.rb +115 -74
- data/lib/contentful_model/client.rb +14 -3
- data/lib/contentful_model/errors.rb +0 -1
- data/lib/contentful_model/manageable.rb +49 -21
- data/lib/contentful_model/management.rb +1 -0
- data/lib/contentful_model/migrations/content_type.rb +24 -24
- data/lib/contentful_model/migrations/content_type_factory.rb +9 -6
- data/lib/contentful_model/migrations/migration.rb +9 -4
- data/lib/contentful_model/queries.rb +60 -9
- data/lib/contentful_model/query.rb +148 -5
- data/lib/contentful_model/validations/lambda_validation.rb +17 -0
- data/lib/contentful_model/validations/validates_presence_of.rb +4 -1
- data/lib/contentful_model/validations/validations.rb +56 -8
- data/lib/contentful_model/version.rb +1 -1
- data/spec/asset_spec.rb +141 -0
- data/spec/associations/belongs_to_many_spec.rb +38 -0
- data/spec/associations/belongs_to_spec.rb +22 -0
- data/spec/associations/has_many_nested_spec.rb +321 -0
- data/spec/associations/has_many_spec.rb +33 -0
- data/spec/associations/has_one_spec.rb +32 -0
- data/spec/base_spec.rb +199 -0
- data/spec/chainable_queries_spec.rb +199 -0
- data/spec/client_spec.rb +11 -0
- data/spec/contentful_model_spec.rb +25 -0
- data/spec/fixtures/vcr_cassettes/asset/all.yml +161 -0
- data/spec/fixtures/vcr_cassettes/asset/find.yml +118 -0
- data/spec/fixtures/vcr_cassettes/association/belongs_to_many.yml +439 -0
- data/spec/fixtures/vcr_cassettes/association/has_many.yml +161 -0
- data/spec/fixtures/vcr_cassettes/association/has_one.yml +161 -0
- data/spec/fixtures/vcr_cassettes/association/nested_with_root_root.yml +240 -0
- data/spec/fixtures/vcr_cassettes/association/nested_without_root_child_higher_include.yml +123 -0
- data/spec/fixtures/vcr_cassettes/association/nested_without_root_child_parent.yml +609 -0
- data/spec/fixtures/vcr_cassettes/association/nested_without_root_childless.yml +688 -0
- data/spec/fixtures/vcr_cassettes/association/nested_without_root_middle.yml +319 -0
- data/spec/fixtures/vcr_cassettes/association/nested_without_root_middle_higher_include.yml +161 -0
- data/spec/fixtures/vcr_cassettes/association/nested_without_root_middle_parent.yml +489 -0
- data/spec/fixtures/vcr_cassettes/association/nested_without_root_parentless.yml +331 -0
- data/spec/fixtures/vcr_cassettes/association/nested_without_root_parentless_higher_include.yml +82 -0
- data/spec/fixtures/vcr_cassettes/associations/nested_without_root_middle.yml +161 -0
- data/spec/fixtures/vcr_cassettes/associations/nested_without_root_middle_higher_include.yml +82 -0
- data/spec/fixtures/vcr_cassettes/base/content_type.yml +185 -0
- data/spec/fixtures/vcr_cassettes/base/return_nil_for_empty.yml +202 -0
- data/spec/fixtures/vcr_cassettes/base/return_nil_for_empty_with_value.yml +124 -0
- data/spec/fixtures/vcr_cassettes/client.yml +98 -0
- data/spec/fixtures/vcr_cassettes/dog.yml +161 -0
- data/spec/fixtures/vcr_cassettes/human.yml +199 -0
- data/spec/fixtures/vcr_cassettes/management/client.yml +1362 -0
- data/spec/fixtures/vcr_cassettes/management/nyancat.yml +1449 -0
- data/spec/fixtures/vcr_cassettes/management/nyancat_2.yml +1449 -0
- data/spec/fixtures/vcr_cassettes/management/nyancat_publish.yml +481 -0
- data/spec/fixtures/vcr_cassettes/management/nyancat_refetch_and_fail.yml +558 -0
- data/spec/fixtures/vcr_cassettes/management/nyancat_refetch_and_save.yml +620 -0
- data/spec/fixtures/vcr_cassettes/management/nyancat_save.yml +479 -0
- data/spec/fixtures/vcr_cassettes/management/nyancat_save_2.yml +479 -0
- data/spec/fixtures/vcr_cassettes/nyancat.yml +196 -0
- data/spec/fixtures/vcr_cassettes/playground/nyancat.yml +177 -0
- data/spec/fixtures/vcr_cassettes/query/each_entry.yml +319 -0
- data/spec/fixtures/vcr_cassettes/query/each_page.yml +319 -0
- data/spec/fixtures/vcr_cassettes/query/empty.yml +180 -0
- data/spec/fixtures/vcr_cassettes/query/load.yml +197 -0
- data/spec/fixtures/vcr_cassettes/query/manual_pagination.yml +161 -0
- data/spec/fixtures/vcr_cassettes/query/nyancat_invalid_elements.yml +247 -0
- data/spec/manageable_spec.rb +186 -0
- data/spec/management_spec.rb +17 -0
- data/spec/migrations/content_type_factory_spec.rb +41 -0
- data/spec/migrations/content_type_spec.rb +176 -0
- data/spec/migrations/migration_spec.rb +75 -0
- data/spec/queries_spec.rb +85 -0
- data/spec/query_spec.rb +126 -0
- data/spec/spec_helper.rb +58 -0
- data/spec/validations/validations_spec.rb +182 -0
- metadata +213 -19
- data/lib/contentful_model/chainable_queries.rb +0 -104
@@ -1,10 +1,12 @@
|
|
1
1
|
module ContentfulModel
|
2
2
|
module Associations
|
3
|
+
# Module for Has Many Nested association
|
3
4
|
module HasManyNested
|
4
5
|
def self.included(base)
|
5
6
|
base.extend ClassMethods
|
6
7
|
end
|
7
8
|
|
9
|
+
# Class method
|
8
10
|
module ClassMethods
|
9
11
|
# has_many_nested allows you to set up a tree relationship
|
10
12
|
# it calls has_many and belongs_to_many on the class, and sets up
|
@@ -13,7 +15,7 @@ module ContentfulModel
|
|
13
15
|
# To set this up in contentful, add a multi-entry field validated to the same model
|
14
16
|
# as the parent, and give it a name. For example, Page might have a field called childPages:
|
15
17
|
#
|
16
|
-
# has_many_nested :child_pages, root: -> { Page.find("some_id")}
|
18
|
+
# has_many_nested :child_pages, root: -> { Page.find("some_id") }
|
17
19
|
#
|
18
20
|
# would setup up an instance attribute called parent_pages which lists all the direct
|
19
21
|
# parents of this page. It would also create methods to find a page based on an array
|
@@ -21,26 +23,26 @@ module ContentfulModel
|
|
21
23
|
# ancestors which called the object; because 'many' associations in Contentful are actually
|
22
24
|
# 'belongs_to_many' from the child end, we might have several ancestors to a page. You will need
|
23
25
|
# to write your own recursion for this, because it's probably an implementation-specific problem.
|
26
|
+
# rubocop:disable Style/PredicateName
|
24
27
|
def has_many_nested(association_name, options = {})
|
25
|
-
has_many association_name, inverse_of: :"parent_#{
|
26
|
-
belongs_to_many :"parent_#{
|
27
|
-
if options[:root].is_a?(Proc)
|
28
|
-
@root_method = options[:root]
|
29
|
-
end
|
28
|
+
has_many association_name, class_name: to_s, inverse_of: :"parent_#{to_s.underscore}"
|
29
|
+
belongs_to_many :"parent_#{to_s.underscore.pluralize}", class_name: to_s
|
30
|
+
root_method = options[:root] if options[:root].is_a?(Proc)
|
30
31
|
|
31
32
|
# If there's a root method defined, set up a class method called root_[class name]. In our example this would be
|
32
33
|
# Page.root_page.
|
33
34
|
# @return [Object] the root entity returned from the proc defined in has_many_nested
|
34
|
-
if defined?(
|
35
|
+
if defined?(root_method) && root_method.is_a?(Proc)
|
35
36
|
# @return [Object] the root entity
|
36
|
-
|
37
|
-
|
37
|
+
define_method :"root_#{to_s.underscore}" do
|
38
|
+
root_method.call
|
38
39
|
end
|
39
40
|
end
|
40
41
|
|
41
42
|
# A utility method which returns the parent object; saves passing around interpolated strings
|
42
43
|
define_method :parent do
|
43
|
-
|
44
|
+
parents = send(:"parent_#{self.class.to_s.underscore.pluralize}")
|
45
|
+
parents.first unless parents.nil?
|
44
46
|
end
|
45
47
|
|
46
48
|
# Determine if the object has any parents. If it doesn't, it's considered a root.
|
@@ -55,43 +57,44 @@ module ContentfulModel
|
|
55
57
|
define_method :find_ancestors do |&block|
|
56
58
|
return enum_for(:find_ancestors) unless block
|
57
59
|
if parent.nil?
|
58
|
-
#this *is* the parent
|
60
|
+
# this *is* the parent
|
59
61
|
return self
|
60
62
|
end
|
61
|
-
block
|
62
|
-
|
63
|
-
|
64
|
-
end
|
63
|
+
block[parent]
|
64
|
+
|
65
|
+
parent.find_ancestors { |a| block[a] } if parent && !parent.root?
|
65
66
|
end
|
66
67
|
|
67
68
|
# A utility method to return the results of `find_ancestors` as an array
|
68
69
|
# @return [Array] of ancestors in reverse order (root last)
|
69
70
|
define_method :ancestors do
|
70
|
-
|
71
|
+
find_ancestors.to_a
|
71
72
|
end
|
72
73
|
|
73
|
-
#
|
74
|
+
# If this entry is the root, return self.
|
75
|
+
# Otherwise, return the last member of the ancestors, which is the root
|
74
76
|
# @return the root instance of this object
|
75
77
|
define_method :root do
|
78
|
+
return self if root?
|
79
|
+
|
76
80
|
find_ancestors.to_a.last
|
77
81
|
end
|
78
82
|
|
79
83
|
# @return [Boolean] whether or not this instance has children
|
80
|
-
define_method :
|
81
|
-
!
|
84
|
+
define_method :children? do
|
85
|
+
!send(association_name).empty?
|
82
86
|
end
|
83
87
|
|
84
88
|
# @return [Array] a collection of child objects, based on the association name
|
85
89
|
define_method :children do
|
86
|
-
|
90
|
+
send(association_name)
|
87
91
|
end
|
88
92
|
|
89
93
|
# @return [Hash] a hash of nested child objects
|
90
94
|
define_method :nested_children do
|
91
|
-
|
92
|
-
children =
|
93
|
-
|
94
|
-
h
|
95
|
+
children.each_with_object({}) do |e, a|
|
96
|
+
children = e.children? ? e.nested_children : nil
|
97
|
+
a[e] = children
|
95
98
|
end
|
96
99
|
end
|
97
100
|
|
@@ -99,38 +102,37 @@ module ContentfulModel
|
|
99
102
|
# @param field [Symbol] the field you want to return, nested for each child
|
100
103
|
# @return [Hash] of nested children, by that field
|
101
104
|
define_method :nested_children_by do |field|
|
102
|
-
|
103
|
-
children =
|
104
|
-
|
105
|
-
h
|
105
|
+
children.each_with_object({}) do |e, a|
|
106
|
+
children = e.children? ? e.nested_children_by(field) : nil
|
107
|
+
a[e.send(field)] = children
|
106
108
|
end
|
107
109
|
end
|
108
110
|
|
109
111
|
# Return a flattened hash of children by the specified field
|
110
112
|
define_method :all_child_paths_by do |field, opts = {}|
|
111
|
-
options = {prefix: nil}.merge!(opts)
|
113
|
+
options = { prefix: nil }.merge!(opts)
|
112
114
|
flatten_hash(nested_children_by(field)).keys.collect do |path|
|
113
115
|
options[:prefix] ? path.unshift(options[:prefix]) : path
|
114
116
|
end
|
115
117
|
end
|
116
118
|
|
117
119
|
# Search for a child by a certain field. This is called on the parent(s).
|
118
|
-
#
|
120
|
+
# e.g. Page.root.find_child_path_by(:slug, "some-slug"). Accepts a prefix if you want to
|
119
121
|
# prefix the children with the parent
|
120
122
|
define_method :find_child_path_by do |field, value, opts = {}|
|
121
|
-
all_child_paths_by(field,opts).select {|child| child.include?(value)}
|
123
|
+
all_child_paths_by(field, opts).select { |child| child.include?(value) }
|
122
124
|
end
|
123
125
|
|
124
126
|
# Private method to flatten a hash. Courtesy Cary Swoveland http://stackoverflow.com/a/23861946
|
125
|
-
define_method :flatten_hash do |h,f=[],g={}|
|
126
|
-
return g.update(
|
127
|
-
h.each { |k,r| flatten_hash(r,f+[k],g) }
|
127
|
+
define_method :flatten_hash do |h, f = [], g = {}|
|
128
|
+
return g.update(f => h) unless h.is_a? Hash
|
129
|
+
h.each { |k, r| flatten_hash(r, f + [k], g) }
|
128
130
|
g
|
129
131
|
end
|
130
|
-
|
131
|
-
|
132
|
+
send(:private, :flatten_hash)
|
132
133
|
end
|
134
|
+
# rubocop:enable Style/PredicateName
|
133
135
|
end
|
134
136
|
end
|
135
137
|
end
|
136
|
-
end
|
138
|
+
end
|
@@ -1,45 +1,53 @@
|
|
1
1
|
module ContentfulModel
|
2
2
|
module Associations
|
3
|
+
# Module for Has One association
|
3
4
|
module HasOne
|
4
5
|
def self.included(base)
|
5
6
|
base.extend ClassMethods
|
6
7
|
end
|
7
8
|
|
9
|
+
# Class method
|
8
10
|
module ClassMethods
|
9
|
-
#has_one defines a method on the parent which wraps around the superclass's implementation. In most cases this
|
10
|
-
#will end up at ContentfulModel::Base#method_missing and look at the fields on a content object.
|
11
|
-
#We wrap around it like this so we can specify a class_name option to call a different method from the association
|
12
|
-
#name.
|
11
|
+
# has_one defines a method on the parent which wraps around the superclass's implementation. In most cases this
|
12
|
+
# will end up at ContentfulModel::Base#method_missing and look at the fields on a content object.
|
13
|
+
# We wrap around it like this so we can specify a class_name option to call a different method from the association
|
14
|
+
# name.
|
15
|
+
#
|
13
16
|
# class Foo
|
14
17
|
# has_one :special_bar, class_name: "Bar"
|
15
18
|
# end
|
19
|
+
#
|
16
20
|
# @param association_name [Symbol] the name of the association. In this case Foo.special_bar.
|
17
21
|
# @param options [Hash] a hash, the only key of which is important is class_name.
|
22
|
+
# rubocop:disable Style/PredicateName
|
18
23
|
def has_one(association_name, options = {})
|
19
24
|
default_options = {
|
20
25
|
class_name: association_name.to_s.classify,
|
21
|
-
inverse_of:
|
26
|
+
inverse_of: to_s.underscore.to_sym
|
22
27
|
}
|
23
28
|
options = default_options.merge(options)
|
29
|
+
|
30
|
+
include_discovered(options[:class_name])
|
31
|
+
|
24
32
|
# Define a method which matches the association name
|
25
33
|
define_method association_name do
|
26
34
|
begin
|
27
35
|
# Start by calling the association name as a method on the superclass.
|
28
36
|
# this will end up in ContentfulModel::Base#method_missing and return the value from Contentful.
|
29
37
|
# We set the singular of the association name on this object to allow easy recursing.
|
30
|
-
super().
|
31
|
-
|
32
|
-
# If method_missing returns an error, the field doesn't exist. If a class is specified, try that.
|
33
|
-
if options[:class_name].underscore.to_sym != association_name
|
34
|
-
self.send(options[:class_name].underscore.to_sym)
|
35
|
-
else
|
36
|
-
#otherwise give up and return nil
|
37
|
-
nil
|
38
|
+
super().tap do |child|
|
39
|
+
child.send(:"#{options[:inverse_of]}=", self) if child.respond_to?(:"#{options[:inverse_of]}=")
|
38
40
|
end
|
41
|
+
rescue NoMethodError
|
42
|
+
# If method_missing returns an error, the field doesn't exist. If a class is specified, try that.
|
43
|
+
possible_field_name = options[:class_name].underscore.to_sym
|
44
|
+
return send(possible_field_name) if possible_field_name != association_name && respond_to?(possible_field_name)
|
45
|
+
nil
|
39
46
|
end
|
40
47
|
end
|
41
48
|
end
|
49
|
+
# rubocop:enable Style/PredicateName
|
42
50
|
end
|
43
51
|
end
|
44
52
|
end
|
45
|
-
end
|
53
|
+
end
|
@@ -1,109 +1,133 @@
|
|
1
|
+
require_relative 'associations/associations'
|
2
|
+
require_relative 'validations/validations'
|
3
|
+
require_relative 'manageable'
|
4
|
+
require_relative 'queries'
|
5
|
+
require_relative 'errors'
|
6
|
+
require_relative 'client'
|
7
|
+
|
1
8
|
module ContentfulModel
|
2
|
-
|
3
|
-
|
9
|
+
# Wrapper for Contentful::Entry which provides ActiveModel-like syntax
|
10
|
+
class Base < Contentful::Entry
|
4
11
|
include ContentfulModel::Associations
|
5
12
|
include ContentfulModel::Validations
|
6
13
|
include ContentfulModel::Manageable
|
14
|
+
include ContentfulModel::Queries
|
7
15
|
|
8
|
-
def initialize(*
|
16
|
+
def initialize(*)
|
9
17
|
super
|
10
|
-
|
11
|
-
|
18
|
+
override_getters
|
19
|
+
end
|
20
|
+
|
21
|
+
def cache_key(*timestamp_names)
|
22
|
+
fail ArgumentError, "ContentfulModel::Base models don't support named timestamps." if timestamp_names.present?
|
23
|
+
|
24
|
+
"#{self.class.to_s.underscore}/#{id}-#{updated_at.utc.to_s(:usec)}"
|
25
|
+
end
|
26
|
+
|
27
|
+
def hash
|
28
|
+
"#{sys[:content_type].id}-#{sys[:id]}".hash
|
29
|
+
end
|
30
|
+
|
31
|
+
def eql?(other)
|
32
|
+
super || other.instance_of?(self.class) && sys[:id].present? && other.sys[:id] == sys[:id]
|
12
33
|
end
|
13
34
|
|
14
35
|
private
|
15
36
|
|
16
|
-
def
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
define_getter(name)
|
21
|
-
end
|
22
|
-
else
|
23
|
-
define_getter(k)
|
37
|
+
def define_sys_methods
|
38
|
+
sys.keys.each do |name|
|
39
|
+
define_singleton_method name do
|
40
|
+
self.class.coerce_value(name, sys[name])
|
24
41
|
end
|
25
42
|
end
|
26
43
|
end
|
27
44
|
|
28
|
-
def
|
29
|
-
|
30
|
-
|
31
|
-
|
45
|
+
def filter_invalids(value)
|
46
|
+
return value.reject { |v| v.is_a?(Contentful::Link) || (v.respond_to?(:invalid?) && v.invalid?) } if value.is_a?(Array)
|
47
|
+
return nil if value.is_a?(Contentful::Link) || value.respond_to?(:fields) && value.fields.empty?
|
48
|
+
|
49
|
+
value
|
32
50
|
end
|
33
51
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
if result.is_a?(Array)
|
40
|
-
result.reject! {|r| r.is_a?(Contentful::Link) || (r.respond_to?(:invalid) && r.invalid?)}
|
41
|
-
elsif result.is_a?(Contentful::Link)
|
42
|
-
result = nil
|
43
|
-
elsif result.respond_to?(:fields) && result.send(:fields).empty?
|
44
|
-
result = nil
|
45
|
-
elsif result.respond_to?(:invalid?) && result.invalid?
|
46
|
-
result = nil
|
47
|
-
end
|
52
|
+
def nillable?(name, value)
|
53
|
+
value.nil? &&
|
54
|
+
self.class.return_nil_for_empty_attribute_fields &&
|
55
|
+
self.class.return_nil_for_empty_attribute_fields.include?(name)
|
56
|
+
end
|
48
57
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
if self.class.coercions[method].nil?
|
60
|
-
return result
|
61
|
-
#if there's a coercion specified for the field and it's a proc, pass the result
|
62
|
-
#to the proc
|
63
|
-
elsif self.class.coercions[method].is_a?(Proc)
|
64
|
-
return self.class.coercions[method].call(result)
|
65
|
-
#provided the coercion is in the COERCIONS constant, call the proc on that
|
66
|
-
elsif !self.class::COERCIONS[self.class.coercions[method]].nil?
|
67
|
-
return self.class::COERCIONS[self.class.coercions[method]].call(result)
|
68
|
-
else
|
69
|
-
#... or just return the result
|
70
|
-
return result
|
58
|
+
def define_fields_methods
|
59
|
+
fields.keys.each do |name|
|
60
|
+
define_singleton_method name do
|
61
|
+
result = filter_invalids(
|
62
|
+
self.class.coerce_value(name, fields[name])
|
63
|
+
)
|
64
|
+
|
65
|
+
return nil if nillable?(name, result)
|
66
|
+
|
67
|
+
result
|
71
68
|
end
|
72
69
|
end
|
73
70
|
end
|
74
71
|
|
75
|
-
def
|
76
|
-
|
77
|
-
|
78
|
-
else
|
79
|
-
true
|
80
|
-
end
|
72
|
+
def override_getters
|
73
|
+
define_sys_methods
|
74
|
+
define_fields_methods
|
81
75
|
end
|
82
76
|
|
83
|
-
def
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
"#{self.class.to_s.underscore}/#{self.id}-#{self.updated_at.utc.to_s(:number)}"
|
77
|
+
def respond_to_missing?(method, private = false)
|
78
|
+
key = fields.keys.detect { |k| k.to_s.underscore == method.to_s.underscore }
|
79
|
+
return super if key.nil?
|
80
|
+
true
|
89
81
|
end
|
90
82
|
|
91
83
|
class << self
|
92
|
-
attr_accessor :content_type_id, :coercions, :return_nil_for_empty_attribute_fields
|
84
|
+
attr_accessor :content_type_id, :coercions, :return_nil_for_empty_attribute_fields, :client
|
93
85
|
|
94
86
|
def descendents
|
95
87
|
ObjectSpace.each_object(Class).select { |klass| klass < self }
|
96
88
|
end
|
97
89
|
|
98
|
-
def
|
99
|
-
|
100
|
-
|
90
|
+
def discovered_includes
|
91
|
+
@discovered_includes ||= []
|
92
|
+
end
|
93
|
+
|
94
|
+
def discovered_include_level
|
95
|
+
@discovered_include_level ||= nil
|
96
|
+
return @discovered_include_level unless @discovered_include_level.nil?
|
97
|
+
|
98
|
+
# Recreate content type tree
|
99
|
+
includes = {}
|
100
|
+
discovered_includes.each do |klass|
|
101
|
+
# Recursively find includes - remove self from reference lists
|
102
|
+
includes[klass] = klass.constantize.discovered_includes.reject { |i| i == to_s } + [klass]
|
101
103
|
end
|
104
|
+
|
105
|
+
include_level = includes.values.map(&:size).max # Longest include chain
|
106
|
+
return @discovered_include_level = 1 if include_level.nil? || include_level.zero?
|
107
|
+
return @discovered_include_level = 10 if include_level >= 10
|
108
|
+
@discovered_include_level = include_level + 1
|
109
|
+
end
|
110
|
+
|
111
|
+
# Add a class to the known referenced classes
|
112
|
+
def include_discovered(klass)
|
113
|
+
# This should be nil already in most cases,
|
114
|
+
# but if another class is defined in Runtime after a query was already run, we want to make sure this is reset
|
115
|
+
@discovered_include_level = nil
|
116
|
+
|
117
|
+
discovered_includes << klass unless discovered_includes.include?(klass)
|
118
|
+
end
|
119
|
+
|
120
|
+
def mapping?
|
121
|
+
ContentfulModel.configuration.entry_mapping.key?(@content_type_id)
|
122
|
+
end
|
123
|
+
|
124
|
+
def add_entry_mapping
|
125
|
+
ContentfulModel.configuration.entry_mapping[@content_type_id] = to_s.constantize unless mapping?
|
102
126
|
end
|
103
127
|
|
104
128
|
def client
|
105
129
|
# add an entry mapping for this content type
|
106
|
-
|
130
|
+
add_entry_mapping
|
107
131
|
if ContentfulModel.use_preview_api
|
108
132
|
@preview_client ||= ContentfulModel::Client.new(ContentfulModel.configuration.to_hash)
|
109
133
|
else
|
@@ -123,14 +147,31 @@ module ContentfulModel
|
|
123
147
|
@coercions
|
124
148
|
end
|
125
149
|
|
126
|
-
def
|
150
|
+
def coerce_value(field_name, value)
|
151
|
+
return value if coercions.nil?
|
152
|
+
|
153
|
+
coercion = coercions[field_name]
|
154
|
+
|
155
|
+
case coercion
|
156
|
+
when Symbol, String
|
157
|
+
coercion = Contentful::Field::KNOWN_TYPES[coercion.to_s]
|
158
|
+
return coercion.new(value).coerce unless coercion.nil?
|
159
|
+
when Proc
|
160
|
+
coercion[value]
|
161
|
+
else
|
162
|
+
value
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def return_nil_for_empty(*nillable_fields)
|
127
167
|
@return_nil_for_empty_attribute_fields ||= []
|
128
168
|
|
129
|
-
|
169
|
+
nillable_fields.each do |field|
|
130
170
|
define_method field do
|
131
171
|
begin
|
132
|
-
super()
|
133
|
-
|
172
|
+
result = super()
|
173
|
+
result.present? ? result : nil
|
174
|
+
rescue NoMethodError
|
134
175
|
nil
|
135
176
|
end
|
136
177
|
end
|