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.
Files changed (84) hide show
  1. checksums.yaml +5 -5
  2. data/lib/contentful_model.rb +17 -13
  3. data/lib/contentful_model/asset.rb +30 -0
  4. data/lib/contentful_model/asset_dimension_query.rb +70 -0
  5. data/lib/contentful_model/asset_dimensions.rb +54 -0
  6. data/lib/contentful_model/associations/associations.rb +10 -4
  7. data/lib/contentful_model/associations/belongs_to.rb +9 -4
  8. data/lib/contentful_model/associations/belongs_to_many.rb +22 -45
  9. data/lib/contentful_model/associations/has_many.rb +15 -13
  10. data/lib/contentful_model/associations/has_many_nested.rb +39 -37
  11. data/lib/contentful_model/associations/has_one.rb +22 -14
  12. data/lib/contentful_model/base.rb +115 -74
  13. data/lib/contentful_model/client.rb +14 -3
  14. data/lib/contentful_model/errors.rb +0 -1
  15. data/lib/contentful_model/manageable.rb +49 -21
  16. data/lib/contentful_model/management.rb +1 -0
  17. data/lib/contentful_model/migrations/content_type.rb +24 -24
  18. data/lib/contentful_model/migrations/content_type_factory.rb +9 -6
  19. data/lib/contentful_model/migrations/migration.rb +9 -4
  20. data/lib/contentful_model/queries.rb +60 -9
  21. data/lib/contentful_model/query.rb +148 -5
  22. data/lib/contentful_model/validations/lambda_validation.rb +17 -0
  23. data/lib/contentful_model/validations/validates_presence_of.rb +4 -1
  24. data/lib/contentful_model/validations/validations.rb +56 -8
  25. data/lib/contentful_model/version.rb +1 -1
  26. data/spec/asset_spec.rb +141 -0
  27. data/spec/associations/belongs_to_many_spec.rb +38 -0
  28. data/spec/associations/belongs_to_spec.rb +22 -0
  29. data/spec/associations/has_many_nested_spec.rb +321 -0
  30. data/spec/associations/has_many_spec.rb +33 -0
  31. data/spec/associations/has_one_spec.rb +32 -0
  32. data/spec/base_spec.rb +199 -0
  33. data/spec/chainable_queries_spec.rb +199 -0
  34. data/spec/client_spec.rb +11 -0
  35. data/spec/contentful_model_spec.rb +25 -0
  36. data/spec/fixtures/vcr_cassettes/asset/all.yml +161 -0
  37. data/spec/fixtures/vcr_cassettes/asset/find.yml +118 -0
  38. data/spec/fixtures/vcr_cassettes/association/belongs_to_many.yml +439 -0
  39. data/spec/fixtures/vcr_cassettes/association/has_many.yml +161 -0
  40. data/spec/fixtures/vcr_cassettes/association/has_one.yml +161 -0
  41. data/spec/fixtures/vcr_cassettes/association/nested_with_root_root.yml +240 -0
  42. data/spec/fixtures/vcr_cassettes/association/nested_without_root_child_higher_include.yml +123 -0
  43. data/spec/fixtures/vcr_cassettes/association/nested_without_root_child_parent.yml +609 -0
  44. data/spec/fixtures/vcr_cassettes/association/nested_without_root_childless.yml +688 -0
  45. data/spec/fixtures/vcr_cassettes/association/nested_without_root_middle.yml +319 -0
  46. data/spec/fixtures/vcr_cassettes/association/nested_without_root_middle_higher_include.yml +161 -0
  47. data/spec/fixtures/vcr_cassettes/association/nested_without_root_middle_parent.yml +489 -0
  48. data/spec/fixtures/vcr_cassettes/association/nested_without_root_parentless.yml +331 -0
  49. data/spec/fixtures/vcr_cassettes/association/nested_without_root_parentless_higher_include.yml +82 -0
  50. data/spec/fixtures/vcr_cassettes/associations/nested_without_root_middle.yml +161 -0
  51. data/spec/fixtures/vcr_cassettes/associations/nested_without_root_middle_higher_include.yml +82 -0
  52. data/spec/fixtures/vcr_cassettes/base/content_type.yml +185 -0
  53. data/spec/fixtures/vcr_cassettes/base/return_nil_for_empty.yml +202 -0
  54. data/spec/fixtures/vcr_cassettes/base/return_nil_for_empty_with_value.yml +124 -0
  55. data/spec/fixtures/vcr_cassettes/client.yml +98 -0
  56. data/spec/fixtures/vcr_cassettes/dog.yml +161 -0
  57. data/spec/fixtures/vcr_cassettes/human.yml +199 -0
  58. data/spec/fixtures/vcr_cassettes/management/client.yml +1362 -0
  59. data/spec/fixtures/vcr_cassettes/management/nyancat.yml +1449 -0
  60. data/spec/fixtures/vcr_cassettes/management/nyancat_2.yml +1449 -0
  61. data/spec/fixtures/vcr_cassettes/management/nyancat_publish.yml +481 -0
  62. data/spec/fixtures/vcr_cassettes/management/nyancat_refetch_and_fail.yml +558 -0
  63. data/spec/fixtures/vcr_cassettes/management/nyancat_refetch_and_save.yml +620 -0
  64. data/spec/fixtures/vcr_cassettes/management/nyancat_save.yml +479 -0
  65. data/spec/fixtures/vcr_cassettes/management/nyancat_save_2.yml +479 -0
  66. data/spec/fixtures/vcr_cassettes/nyancat.yml +196 -0
  67. data/spec/fixtures/vcr_cassettes/playground/nyancat.yml +177 -0
  68. data/spec/fixtures/vcr_cassettes/query/each_entry.yml +319 -0
  69. data/spec/fixtures/vcr_cassettes/query/each_page.yml +319 -0
  70. data/spec/fixtures/vcr_cassettes/query/empty.yml +180 -0
  71. data/spec/fixtures/vcr_cassettes/query/load.yml +197 -0
  72. data/spec/fixtures/vcr_cassettes/query/manual_pagination.yml +161 -0
  73. data/spec/fixtures/vcr_cassettes/query/nyancat_invalid_elements.yml +247 -0
  74. data/spec/manageable_spec.rb +186 -0
  75. data/spec/management_spec.rb +17 -0
  76. data/spec/migrations/content_type_factory_spec.rb +41 -0
  77. data/spec/migrations/content_type_spec.rb +176 -0
  78. data/spec/migrations/migration_spec.rb +75 -0
  79. data/spec/queries_spec.rb +85 -0
  80. data/spec/query_spec.rb +126 -0
  81. data/spec/spec_helper.rb +58 -0
  82. data/spec/validations/validations_spec.rb +182 -0
  83. metadata +213 -19
  84. data/lib/contentful_model/chainable_queries.rb +0 -104
@@ -1,14 +1,25 @@
1
+ require_relative 'asset'
2
+
1
3
  module ContentfulModel
4
+ # Wrapper for the CDA Client
2
5
  class Client < Contentful::Client
3
-
4
- PREVIEW_API_URL = "preview.contentful.com"
6
+ PREVIEW_API_URL = 'preview.contentful.com'.freeze
5
7
 
6
8
  def initialize(configuration)
9
+ configuration[:resource_mapping] = configuration.fetch(:resource_mapping, {}).merge(
10
+ 'Asset' => ContentfulModel::Asset
11
+ )
12
+
7
13
  if ContentfulModel.use_preview_api
8
14
  configuration[:api_url] = PREVIEW_API_URL
9
15
  configuration[:access_token] = configuration[:preview_access_token]
10
16
  end
11
- super({ raise_errors: true, dynamic_entries: :auto }.merge(configuration))
17
+ super({
18
+ raise_errors: true,
19
+ dynamic_entries: :auto,
20
+ integration_name: 'contentful_model',
21
+ integration_version: ::ContentfulModel::VERSION
22
+ }.merge(configuration))
12
23
  end
13
24
  end
14
25
  end
@@ -1,5 +1,4 @@
1
1
  module ContentfulModel
2
2
  class AssociationError < StandardError; end
3
3
  class VersionMismatchError < StandardError; end
4
- class AttributeNotFoundError < NoMethodError; end
5
4
  end
@@ -1,9 +1,18 @@
1
+ require_relative 'errors'
2
+ require_relative 'management'
3
+
1
4
  module ContentfulModel
5
+ # Adds CMA functionality to Base
2
6
  module Manageable
3
7
  attr_reader :dirty
4
8
 
5
- def initialize(*args)
9
+ def self.included(base)
10
+ base.extend(ClassMethods)
11
+ end
12
+
13
+ def initialize(_item, _configuration = {}, localized = false, *)
6
14
  super
15
+ @localized = localized
7
16
  @dirty = false
8
17
  @changed_fields = []
9
18
  define_setters
@@ -27,7 +36,9 @@ module ContentfulModel
27
36
  @management_entry = fetch_management_entry
28
37
  end
29
38
 
30
- def save
39
+ def save(skip_validations = false)
40
+ return false if !skip_validations && invalid?(true)
41
+
31
42
  begin
32
43
  to_management.save
33
44
  rescue Contentful::Management::Conflict
@@ -40,7 +51,14 @@ module ContentfulModel
40
51
 
41
52
  self
42
53
  rescue Contentful::Management::Conflict
43
- fail ContentfulModel::VersionMismatchError, "Version Mismatch persisting after refetch attempt, use :refetch_management_entry and try again later."
54
+ raise(
55
+ ContentfulModel::VersionMismatchError,
56
+ 'Version Mismatch persisting after refetch attempt, use :refetch_management_entry and try again later.'
57
+ )
58
+ end
59
+
60
+ def save!
61
+ save(true)
44
62
  end
45
63
 
46
64
  def publish
@@ -52,17 +70,25 @@ module ContentfulModel
52
70
 
53
71
  self
54
72
  rescue Contentful::Management::Conflict
55
- fail ContentfulModel::VersionMismatchError, "Version Mismatch persisting after refetch attempt, use :refetch_management_entry and try again later."
73
+ raise(
74
+ ContentfulModel::VersionMismatchError,
75
+ 'Version Mismatch persisting after refetch attempt, use :refetch_management_entry and try again later.'
76
+ )
56
77
  end
57
78
 
58
79
  private
59
80
 
60
- def management_space
61
- @management_space ||= self.class.management(default_locale: locale).spaces.find(space.id)
81
+ def management_proxy
82
+ @management_proxy ||= self.class.management(
83
+ default_locale: locale
84
+ ).entries(
85
+ space.id,
86
+ ContentfulModel.configuration.environment
87
+ )
62
88
  end
63
89
 
64
90
  def fetch_management_entry
65
- management_space.entries.find(id)
91
+ management_proxy.find(id)
66
92
  end
67
93
 
68
94
  def management_entry
@@ -72,7 +98,7 @@ module ContentfulModel
72
98
 
73
99
  def define_setters
74
100
  fields.each do |k, v|
75
- if Contentful::Constants::KNOWN_LOCALES.include?(k.to_s)
101
+ if @localized
76
102
  v.keys.each do |name|
77
103
  define_setter(name)
78
104
  end
@@ -86,7 +112,7 @@ module ContentfulModel
86
112
  define_singleton_method "#{name.to_s.underscore}=" do |value|
87
113
  @dirty = true
88
114
  @changed_fields << name
89
- fields(default_locale)[name] = value
115
+ fields[name] = value
90
116
  end
91
117
  end
92
118
 
@@ -97,39 +123,41 @@ module ContentfulModel
97
123
  when Contentful::Asset
98
124
  Contentful::Management::Entry.hash_with_link_object('Asset', entry_value)
99
125
  when Contentful::Link
100
- Contentful::Management::Entry.hash_with_link_object(entry_value.sys[:contentType], entry_value)
126
+ Contentful::Management::Entry.hash_with_link_object(entry_value.sys[:link_type], entry_value)
101
127
  else
102
128
  entry_value
103
129
  end
104
130
  end
105
131
 
132
+ # Management Class methods
106
133
  module ClassMethods
107
134
  def management(options = {})
108
135
  @management ||= ContentfulModel::Management.new(
109
- options.merge(default_locale: ContentfulModel.configuration.default_locale)
136
+ options.merge(
137
+ default_locale: ContentfulModel.configuration.default_locale,
138
+ raise_errors: true,
139
+ integration_name: 'contentful_model',
140
+ integration_version: ::ContentfulModel::VERSION
141
+ )
110
142
  )
111
143
  end
112
144
 
113
145
  def create(values = {}, publish = false)
114
- entry = management.entries.create(
115
- management.content_types.find(
116
- ContentfulModel.configuration.space,
117
- content_type_id
118
- ),
146
+ space = ContentfulModel.configuration.space
147
+ environment = ContentfulModel.configuration.environment
148
+
149
+ entry = management.entries(space, environment).create(
150
+ management.content_types(space, environment).find(content_type_id),
119
151
  values
120
152
  )
121
153
 
122
154
  if publish
123
155
  entry.publish
124
- entry = self.find(entry.id)
156
+ entry = find(entry.id)
125
157
  end
126
158
 
127
159
  entry
128
160
  end
129
161
  end
130
-
131
- def self.included(base)
132
- base.extend(ClassMethods)
133
- end
134
162
  end
135
163
  end
@@ -1,4 +1,5 @@
1
1
  module ContentfulModel
2
+ # Wrapper for the CMA Client
2
3
  class Management < Contentful::Management::Client
3
4
  def initialize(options = {})
4
5
  super(ContentfulModel.configuration.management_token, options)
@@ -1,6 +1,11 @@
1
+ require_relative 'errors'
2
+
1
3
  module ContentfulModel
2
4
  module Migrations
5
+ # Class for defining Content Type transformations
3
6
  class ContentType
7
+ attr_accessor :id, :name
8
+
4
9
  def initialize(name = nil, management_content_type = nil)
5
10
  @name = name
6
11
  @management_content_type = management_content_type
@@ -8,8 +13,11 @@ module ContentfulModel
8
13
 
9
14
  def save
10
15
  if new?
11
- @management_content_type = management.content_types.create(
16
+ @management_content_type = management.content_types(
12
17
  ContentfulModel.configuration.space,
18
+ ContentfulModel.configuration.environment
19
+ ).create(
20
+ id: id || camel_case(@name),
13
21
  name: @name,
14
22
  fields: fields
15
23
  )
@@ -54,53 +62,46 @@ module ContentfulModel
54
62
  end
55
63
 
56
64
  def fields
57
- if new?
58
- return @fields ||= []
59
- else
60
- return @fields ||= fields_from_management_type
61
- end
65
+ @fields ||= new? ? [] : fields_from_management_type
62
66
  end
63
67
 
64
68
  private
65
69
 
70
+ def camel_case(a_string)
71
+ a_string.split(/\s|_|-/).inject([]) { |a, e| a.push(a.empty? ? e.downcase : e.capitalize) }.join
72
+ end
73
+
66
74
  def fields_from_management_type
67
75
  @management_content_type.fields
68
76
  end
69
77
 
70
78
  def management_type(type)
71
- if [
72
- :text, :symbol,
73
- :integer, :number,
74
- :date, :boolean,
75
- :location, :object
76
- ].include?(type.to_sym)
77
- return type.capitalize
79
+ if %i[text symbol integer number date boolean location object].include?(type.to_sym)
80
+ type.capitalize
78
81
  elsif type == 'string'
79
- return 'Symbol'
82
+ 'Symbol'
80
83
  elsif link?(type)
81
- return 'Link'
84
+ 'Link'
82
85
  elsif array?(type)
83
- return 'Array'
86
+ 'Array'
84
87
  else
85
88
  raise_field_type_error(type)
86
89
  end
87
90
  end
88
91
 
89
92
  def management_link_type(type)
90
- if [:entry_link, :asset_link].include?(type.to_sym)
91
- return type.split('_').first.capitalize
92
- else
93
- raise_field_type_error(type)
94
- end
93
+ raise_field_type_error(type) unless %i[entry_link asset_link].include?(type.to_sym)
94
+
95
+ type.split('_').first.capitalize
95
96
  end
96
97
 
97
98
  def management_items(type)
98
- if [:entry_array, :asset_array].include?(type.to_sym)
99
+ if %i[entry_array asset_array].include?(type.to_sym)
99
100
  items = Contentful::Management::Field.new
100
101
  items.type = 'Link'
101
102
  items.link_type = type.split('_').first.capitalize
102
103
 
103
- return items
104
+ items
104
105
  else
105
106
  raise_field_type_error(type)
106
107
  end
@@ -124,4 +125,3 @@ module ContentfulModel
124
125
  end
125
126
  end
126
127
  end
127
-
@@ -1,13 +1,16 @@
1
+ require_relative 'content_type'
2
+
1
3
  module ContentfulModel
2
4
  module Migrations
5
+ # Content Type Factory class
3
6
  module ContentTypeFactory
4
- def self.create(name, fields = {}, &block)
7
+ def self.create(name, fields = {}, &_block)
5
8
  content_type = ContentfulModel::Migrations::ContentType.new(name)
6
9
 
7
10
  yield(content_type) if block_given?
8
11
 
9
- fields.each do |name, type|
10
- content_type.field(name, type)
12
+ fields.each do |field_name, type|
13
+ content_type.field(field_name, type)
11
14
  end
12
15
 
13
16
  content_type.save
@@ -16,10 +19,10 @@ module ContentfulModel
16
19
  def self.find(content_type_id)
17
20
  ContentfulModel::Migrations::ContentType.new(
18
21
  nil,
19
- ContentfulModel::Management.new.content_types.find(
22
+ ContentfulModel::Management.new.content_types(
20
23
  ContentfulModel.configuration.space,
21
- content_type_id
22
- )
24
+ ContentfulModel.configuration.environment
25
+ ).find(content_type_id)
23
26
  )
24
27
  end
25
28
  end
@@ -1,16 +1,21 @@
1
+ require_relative 'content_type_factory'
2
+
1
3
  module ContentfulModel
4
+ # Migrations module
2
5
  module Migrations
6
+ # Content Type Migration methods
3
7
  module Migration
4
8
  def create_content_type(name, fields = {}, &block)
5
9
  ContentfulModel::Migrations::ContentTypeFactory.create(name, fields, &block)
6
10
  end
7
11
 
8
- def add_content_type_field(content_type_id, name, type)
12
+ def add_content_type_field(content_type_id, name, type, &_block)
9
13
  content_type = ContentfulModel::Migrations::ContentTypeFactory.find(content_type_id)
14
+ field = content_type.field(name, type)
10
15
 
11
- content_type.field(name, type)
16
+ yield(field) if block_given?
12
17
 
13
- content_type.save
18
+ content_type.save.publish
14
19
  end
15
20
 
16
21
  def remove_content_type_field(content_type_id, field_id)
@@ -18,7 +23,7 @@ module ContentfulModel
18
23
 
19
24
  content_type.remove_field(field_id)
20
25
 
21
- content_type.save
26
+ content_type.save.publish
22
27
  end
23
28
  end
24
29
  end
@@ -1,27 +1,78 @@
1
+ require_relative 'query'
2
+
1
3
  module ContentfulModel
4
+ # Module to extend Base with querying capabilities
2
5
  module Queries
3
6
  def self.included(base)
4
7
  base.extend ClassMethods
5
8
  end
6
9
 
10
+ # Class methods for Queries
7
11
  module ClassMethods
8
- def inherited(subclass)
9
- instantiate_query(subclass)
12
+ def query
13
+ ContentfulModel::Query.new(self)
10
14
  end
11
15
 
12
- def instantiate_query(klass)
13
- klass.instance_variable_set(:"@query", ContentfulModel::Query.new(klass))
16
+ def all
17
+ fail ArgumentError, 'You need to set self.content_type in your model class' if @content_type_id.nil?
18
+ query
14
19
  end
15
20
 
16
21
  def load
17
- old_query = @query.dup
18
- @query.reset
19
- return old_query.execute
22
+ all.load
23
+ end
24
+
25
+ def first
26
+ query.first
27
+ end
28
+
29
+ def params(options)
30
+ query.params(options)
31
+ end
32
+
33
+ def offset(n)
34
+ query.offset(n)
35
+ end
36
+ alias skip offset
37
+
38
+ def limit(n)
39
+ query.limit(n)
40
+ end
41
+
42
+ def locale(locale_code)
43
+ query.locale(locale_code)
44
+ end
45
+
46
+ def paginate(page = 1, per_page = 100, order_field = 'sys.updatedAt', additional_options = {})
47
+ query.paginate(page, per_page, order_field, additional_options)
48
+ end
49
+
50
+ def each_page(per_page = 100, order_field = 'sys.updatedAt', additional_options = {}, &block)
51
+ query.each_page(per_page, order_field, additional_options, &block)
52
+ end
53
+
54
+ def each_entry(per_page = 100, order_field = 'sys.updatedAt', additional_options = {}, &block)
55
+ query.each_entry(per_page, order_field, additional_options, &block)
56
+ end
57
+
58
+ def load_children(n)
59
+ query.load_children(n)
60
+ end
61
+
62
+ def order(args)
63
+ query.order(args)
20
64
  end
21
65
 
22
66
  def find(id)
23
- @query << {'sys.id' => id}
24
- load.first
67
+ query.find(id)
68
+ end
69
+
70
+ def find_by(find_query = {})
71
+ query.find_by(find_query)
72
+ end
73
+
74
+ def search(parameters)
75
+ query.search(parameters)
25
76
  end
26
77
  end
27
78
  end
@@ -1,7 +1,10 @@
1
1
  module ContentfulModel
2
+ # Class to wrap query parameters
2
3
  class Query
4
+ SYS_PROPERTIES = %w[type id space contentType linkType revision createdAt updatedAt locale]
5
+
3
6
  attr_accessor :parameters
4
- def initialize(referenced_class, parameters=nil)
7
+ def initialize(referenced_class, parameters = nil)
5
8
  @parameters = parameters || {}
6
9
  @referenced_class = referenced_class
7
10
  end
@@ -10,22 +13,162 @@ module ContentfulModel
10
13
  @parameters.merge!(parameters)
11
14
  end
12
15
 
16
+ def params(options)
17
+ self << options
18
+ self
19
+ end
20
+
21
+ def first
22
+ self << { 'limit' => 1 }
23
+ load.first
24
+ end
25
+
26
+ def offset(n)
27
+ self << { 'skip' => n }
28
+ self
29
+ end
30
+ alias skip offset
31
+
32
+ def limit(n)
33
+ self << { 'limit' => n }
34
+ self
35
+ end
36
+
37
+ def locale(locale_code)
38
+ self << { 'locale' => locale_code }
39
+ self
40
+ end
41
+
42
+ def paginate(page = 1, per_page = 100, order_field = 'sys.updatedAt', additional_options = {})
43
+ page = 1 if page.nil? || !page.is_a?(Numeric) || page <= 0
44
+ per_page = 100 if per_page.nil? || !per_page.is_a?(Numeric) || per_page <= 0
45
+
46
+ skip_records_count = (page - 1) * per_page
47
+ self << { 'limit' => per_page, 'skip' => skip_records_count, 'order' => order_field }
48
+ self << additional_options
49
+ self
50
+ end
51
+
52
+ def each_page(per_page = 100, order_field = 'sys.updatedAt', additional_options = {}, &block)
53
+ total = self.class.new(@referenced_class).limit(1).load_children(0).params(additional_options).execute.total
54
+
55
+ ((total / per_page) + 1).times do |i|
56
+ page = self.class.new(@referenced_class).paginate(i, per_page, order_field, additional_options).execute
57
+ block[page]
58
+ end
59
+ end
60
+
61
+ def each_entry(per_page = 100, order_field = 'sys.updatedAt', additional_options = {}, &block)
62
+ each_page(per_page, order_field, additional_options) do |page|
63
+ page.each do |entry|
64
+ block[entry]
65
+ end
66
+ end
67
+ end
68
+
69
+ def load_children(n)
70
+ self << { 'include' => n }
71
+ self
72
+ end
73
+
74
+ def order(args)
75
+ prefix = ''
76
+ if args.is_a?(Hash)
77
+ column = args.first.first.to_s
78
+ prefix = '-' if args.first.last == :desc
79
+ elsif args.is_a?(Symbol)
80
+ column = args.to_s
81
+ prefix = ''
82
+ else
83
+ column = args.to_s
84
+ end
85
+ property_name = column.camelize(:lower).to_sym
86
+ property_type = SYS_PROPERTIES.include?(property_name.to_s) ? 'sys' : 'fields'
87
+
88
+ self << { 'order' => "#{prefix}#{property_type}.#{property_name}" }
89
+ self
90
+ end
91
+
92
+ def find(id)
93
+ self << { 'sys.id' => id }
94
+ load.first
95
+ end
96
+
97
+ def find_by(find_query = {})
98
+ find_query.each do |field, value|
99
+ key = if field.to_s.include?('sys.') || field.to_s.include?('fields.')
100
+ field
101
+ elsif SYS_PROPERTIES.include?(field.to_s)
102
+ "sys.#{field}"
103
+ else
104
+ "fields.#{field}"
105
+ end
106
+
107
+ case value
108
+ when Array # we need to do an 'in' query
109
+ self << { "#{key}[in]" => value.join(',') }
110
+ when String, Numeric, true, false
111
+ self << { key.to_s => value }
112
+ when Hash
113
+ # if the search is a hash, use the key to specify the search field operator
114
+ # For example
115
+ # Model.search(start_date: {gte: DateTime.now}) => "fields.start_date[gte]" => DateTime.now
116
+ value.each do |search_predicate, search_value|
117
+ self << { "#{key}[#{search_predicate}]" => search_value }
118
+ end
119
+ end
120
+ end
121
+
122
+ self
123
+ end
124
+ alias where find_by
125
+
126
+ def search(parameters)
127
+ if parameters.is_a?(Hash)
128
+ parameters.each do |field, search|
129
+ # if the search is a hash, use the key to specify the search field operator
130
+ # For example
131
+ # Model.search(start_date: {gte: DateTime.now}) => "fields.start_date[gte]" => DateTime.now
132
+ if search.is_a?(Hash)
133
+ search_key, search_value = *search.flatten
134
+ self << { "fields.#{field.to_s.camelize(:lower)}[#{search_key}]" => search_value }
135
+ else
136
+ self << { "fields.#{field.to_s.camelize(:lower)}[match]" => search }
137
+ end
138
+ end
139
+ elsif parameters.is_a?(String)
140
+ self << { 'query' => parameters }
141
+ end
142
+
143
+ self
144
+ end
145
+
13
146
  def default_parameters
14
- { 'content_type' => @referenced_class.send(:content_type_id) }
147
+ { 'content_type' => @referenced_class.content_type_id }
15
148
  end
16
149
 
17
150
  def execute
18
151
  query = @parameters.merge(default_parameters)
19
- result = client.send(:entries,query)
20
- return result.to_a.reject {|entity| entity.is_a?(Contentful::Link) || entity.invalid?}
152
+
153
+ discovered_includes = discover_includes
154
+ query['include'] = discovered_includes unless query.key?('include') || discovered_includes == 1
155
+
156
+ result = client.entries(query)
157
+ result.items.reject!(&:invalid?)
158
+ result
21
159
  end
160
+ alias load execute
22
161
 
23
162
  def client
24
- @client ||= @referenced_class.send(:client)
163
+ @client ||= @referenced_class.client
25
164
  end
26
165
 
27
166
  def reset
28
167
  @parameters = default_parameters
29
168
  end
169
+
170
+ def discover_includes
171
+ @referenced_class.discovered_include_level
172
+ end
30
173
  end
31
174
  end