sunil 0.0.2

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 (49) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/gem-push.yml +33 -0
  3. data/.gitignore +12 -0
  4. data/.talismanrc +1 -0
  5. data/.yardopts +6 -0
  6. data/CHANGELOG.md +79 -0
  7. data/CODEOWNERS +1 -0
  8. data/CODE_OF_CONDUCT.md +73 -0
  9. data/Gemfile +3 -0
  10. data/Gemfile.lock +77 -0
  11. data/LICENSE.txt +21 -0
  12. data/README.md +197 -0
  13. data/SECURITY.md +27 -0
  14. data/lib/contentstack/api.rb +191 -0
  15. data/lib/contentstack/asset.rb +69 -0
  16. data/lib/contentstack/asset_collection.rb +28 -0
  17. data/lib/contentstack/client.rb +92 -0
  18. data/lib/contentstack/content_type.rb +54 -0
  19. data/lib/contentstack/entry.rb +222 -0
  20. data/lib/contentstack/entry_collection.rb +45 -0
  21. data/lib/contentstack/error.rb +7 -0
  22. data/lib/contentstack/query.rb +654 -0
  23. data/lib/contentstack/region.rb +6 -0
  24. data/lib/contentstack/sync_result.rb +30 -0
  25. data/lib/contentstack/version.rb +3 -0
  26. data/lib/contentstack.rb +32 -0
  27. data/lib/util.rb +111 -0
  28. data/rakefile.rb +4 -0
  29. data/spec/asset_collection_spec.rb +16 -0
  30. data/spec/asset_spec.rb +48 -0
  31. data/spec/content_type_spec.rb +81 -0
  32. data/spec/contentstack_spec.rb +39 -0
  33. data/spec/entry_collection_spec.rb +42 -0
  34. data/spec/entry_spec.rb +102 -0
  35. data/spec/fixtures/asset.json +1 -0
  36. data/spec/fixtures/asset_collection.json +1 -0
  37. data/spec/fixtures/category_content_type.json +1 -0
  38. data/spec/fixtures/category_entry.json +1 -0
  39. data/spec/fixtures/category_entry_collection.json +1 -0
  40. data/spec/fixtures/category_entry_collection_without_count.json +1 -0
  41. data/spec/fixtures/content_types.json +1 -0
  42. data/spec/fixtures/product_entry.json +1 -0
  43. data/spec/fixtures/product_entry_collection.json +1 -0
  44. data/spec/fixtures/sync_init.json +2975 -0
  45. data/spec/query_spec.rb +206 -0
  46. data/spec/spec_helper.rb +181 -0
  47. data/spec/sync_spec.rb +27 -0
  48. data/sunil.gemspec +30 -0
  49. metadata +186 -0
@@ -0,0 +1,191 @@
1
+ require 'uri'
2
+ require 'net/http'
3
+ require 'active_support'
4
+ require 'active_support/json'
5
+ require 'open-uri'
6
+ require 'util'
7
+ module Contentstack
8
+ class API
9
+ using Utility
10
+ def self.init_api(api_key, delivery_token, environment, host, branch, live_preview, proxy, retry_options)
11
+ @host = host
12
+ @api_version = '/v3'
13
+ @environment = environment
14
+ @api_key = api_key
15
+ @access_token = delivery_token
16
+ @branch = branch
17
+ @headers = {environment: @environment}
18
+ @live_preview = live_preview
19
+ @proxy_details = proxy
20
+ @timeout = retry_options["timeout"]
21
+ @retryDelay = retry_options["retryDelay"]
22
+ @retryLimit = retry_options["retryLimit"]
23
+ @errorRetry = retry_options["errorRetry"]
24
+ end
25
+
26
+ def self.live_preview_query(query= {})
27
+ @live_preview[:content_type_uid] = query[:content_type_uid] || query["content_type_uid"]
28
+ @live_preview[:live_preview] = query[:live_preview] || query["live_preview"]
29
+ @live_preview[:entry_uid] = query[:entry_uid] || query["entry_uid"]
30
+ if @live_preview[:content_type_uid].present? && @live_preview[:entry_uid].present?
31
+ path = "/content_types/#{@live_preview[:content_type_uid]}/entries/#{@live_preview[:entry_uid]}"
32
+ @live_preview_response = send_preview_request(path)
33
+ end
34
+ end
35
+
36
+ def self.fetch_content_types(uid="")
37
+ if !uid.nil? && !uid.empty?
38
+ path = "/content_types/#{uid}"
39
+ else
40
+ path = "/content_types"
41
+ end
42
+ fetch_retry(path, {})
43
+ end
44
+
45
+ def self.fetch_entries(content_type, query)
46
+ if @live_preview[:enable] && @live_preview[:content_type_uid] == content_type
47
+ path = "/content_types/#{content_type}/entries"
48
+ send_preview_request(path, query)
49
+ else
50
+ path = "/content_types/#{content_type}/entries"
51
+ fetch_retry(path, query)
52
+ end
53
+ end
54
+
55
+ def self.fetch_entry(content_type, entry_uid, query)
56
+ if @live_preview[:enable] && @live_preview[:content_type_uid] == content_type
57
+ path = "/content_types/#{content_type}/entries/#{entry_uid}"
58
+ send_preview_request(path, query)
59
+ else
60
+ path = "/content_types/#{content_type}/entries/#{entry_uid}"
61
+ fetch_retry(path, query)
62
+ end
63
+ end
64
+
65
+ def self.get_assets(asset_uid=nil)
66
+ path = "/assets"
67
+ path += "/#{asset_uid}" if !asset_uid.nil?
68
+ fetch_retry(path)
69
+ end
70
+
71
+ def self.get_sync_items(query)
72
+ path = "/stacks/sync"
73
+ fetch_retry(path, query)
74
+ end
75
+
76
+ private
77
+ def self.fetch_retry(path, query=nil, count=0)
78
+ response = send_request(path, query)
79
+ if @errorRetry.include?(response["status_code"].to_i)
80
+ if count < @retryLimit
81
+ retryDelay_in_seconds = @retryDelay / 1000 #converting retry_delay from milliseconds into seconds
82
+ sleep(retryDelay_in_seconds.to_i) #sleep method requires time in seconds as parameter
83
+ response = fetch_retry(path, query, (count + 1))
84
+ else
85
+ raise Contentstack::Error.new(response) #Retry Limit exceeded
86
+ end
87
+ else
88
+ to_render_content(response)
89
+ end
90
+ end
91
+
92
+ def self.send_request(path, q=nil)
93
+ q ||= {}
94
+
95
+ q.merge!(@headers)
96
+
97
+ query = "?" + q.to_query
98
+ # puts "Request URL:- #{@host}#{@api_version}#{path}#{query} \n\n"
99
+ params = {
100
+ "api_key" => @api_key,
101
+ "access_token"=> @access_token,
102
+ "user_agent"=> "ruby-sdk/#{Contentstack::VERSION}",
103
+ "x-user-agent" => "ruby-sdk/#{Contentstack::VERSION}",
104
+ "read_timeout" => @timeout
105
+ }
106
+ if !@branch.nil? && !@branch.empty?
107
+ params["branch"] = @branch
108
+ end
109
+
110
+ if @proxy_details.present? && @proxy_details[:url].present? && @proxy_details[:port].present? && @proxy_details[:username].empty? && @proxy_details[:password].empty?
111
+ params["proxy"] = URI.parse("http://#{@proxy_details[:url]}:#{@proxy_details[:port]}/").to_s
112
+ end
113
+
114
+ if @proxy_details.present? && @proxy_details[:url].present? && @proxy_details[:port].present? && @proxy_details[:username].present? && @proxy_details[:password].present?
115
+ proxy_uri = URI.parse("http://#{@proxy_details[:url]}:#{@proxy_details[:port]}/").to_s
116
+ params[:proxy_http_basic_authentication] = [proxy_uri, @proxy_details[:username], @proxy_details[:password]]
117
+ end
118
+
119
+ begin
120
+ ActiveSupport::JSON.decode(URI.open("#{@host}#{@api_version}#{path}#{query}", params).read)
121
+ rescue OpenURI::HTTPError => error
122
+ response = error.io
123
+ #response.status
124
+ # => ["503", "Service Unavailable"]
125
+ error_response = JSON.parse(response.string)
126
+ error_status = {"status_code" => response.status[0], "status_message" => response.status[1]}
127
+ error = error_response.merge(error_status)
128
+ raise Contentstack::Error.new(error.to_s)
129
+ end
130
+ end
131
+
132
+ def self.send_preview_request(path, q=nil)
133
+ q ||= {}
134
+
135
+ q.merge!({live_preview: (!@live_preview.key?(:live_preview) ? 'init' : @live_preview[:live_preview]),})
136
+
137
+ query = "?" + q.to_query
138
+ preview_host = @live_preview[:host]
139
+ params = {
140
+ "api_key" => @api_key,
141
+ "authorization" => @live_preview[:management_token],
142
+ "user_agent"=> "ruby-sdk/#{Contentstack::VERSION}",
143
+ "x-user-agent" => "ruby-sdk/#{Contentstack::VERSION}",
144
+ "read_timeout" => @timeout
145
+ }
146
+ if !@branch.nil? && !@branch.empty?
147
+ params["branch"] = @branch
148
+ end
149
+
150
+ if @proxy_details.present? && @proxy_details[:url].present? && @proxy_details[:port].present? && @proxy_details[:username].empty? && @proxy_details[:password].empty?
151
+ params["proxy"] = URI.parse("http://#{@proxy_details[:url]}:#{@proxy_details[:port]}/").to_s
152
+ end
153
+
154
+ if @proxy_details.present? && @proxy_details[:url].present? && @proxy_details[:port].present? && @proxy_details[:username].present? && @proxy_details[:password].present?
155
+ proxy_uri = URI.parse("http://#{@proxy_details[:url]}:#{@proxy_details[:port]}/").to_s
156
+ params[:proxy_http_basic_authentication] = [proxy_uri, @proxy_details[:username], @proxy_details[:password]]
157
+ end
158
+
159
+ begin
160
+ ActiveSupport::JSON.decode(URI.open("#{preview_host}#{@api_version}#{path}#{query}",params).read)
161
+ rescue OpenURI::HTTPError => error
162
+ response = error.io
163
+ #response.status
164
+ # => ["503", "Service Unavailable"]
165
+ error_response = JSON.parse(response.string)
166
+ error_status = {"status_code" => response.status[0], "status_message" => response.status[1]}
167
+ error = error_response.merge(error_status)
168
+ raise Contentstack::Error.new(error.to_s)
169
+ end
170
+ end
171
+
172
+ def self.to_render_content(resp)
173
+ if resp.class == Hash
174
+ if resp.key?('uid') && resp['uid'] == @live_preview[:entry_uid]
175
+ resp = resp.merge(@live_preview_response)
176
+ else
177
+ resp_keys = resp.keys
178
+ resp_keys.each {|key|
179
+ resp[key] = to_render_content(resp[key])
180
+ }
181
+ end
182
+ elsif resp.class == Array
183
+ resp.each_with_index {|value, index|
184
+ resp[index] = to_render_content(value)
185
+ }
186
+ end
187
+ resp
188
+ end
189
+
190
+ end
191
+ end
@@ -0,0 +1,69 @@
1
+ require 'util'
2
+ module Contentstack
3
+
4
+ # Asset class to fetch file details on Conentstack server.
5
+ class Asset
6
+ using Utility
7
+ attr_reader :uid, :content_type, :filename, :file_size, :tags, :url
8
+
9
+ # @!attribute [r] uid
10
+ # Contentstack Asset UID for this asset
11
+
12
+ # @!attribute [r] content_type
13
+ # Content Type for the asset. image/png, image/jpeg, application/pdf, video/mp4 etc.
14
+
15
+ # @!attribute [r] filename
16
+ # Name of the asset.
17
+
18
+ # @!attribute [r] file_size
19
+ # Size of the asset.
20
+
21
+ # @!attribute [r] tags
22
+ # Array of tags assigned to the asset.
23
+
24
+ # @!attribute [r] url
25
+ # URL to fetch/render the asset
26
+
27
+ # Create instance of an Asset. Accepts either a uid of asset (String) or a complete asset JSON
28
+ # @param [String/Hash] attrs
29
+ # Usage for String parameter
30
+ # @asset = @stack.asset("some_asset_uid")
31
+ # @asset.fetch
32
+ #
33
+ # Usage for Hash parameter
34
+ # @asset = @stack.asset({
35
+ # :uid => "some_asset_uid",
36
+ # :content_type => "file_type", # image/png, image/jpeg, application/pdf, video/mp4 etc.
37
+ # :filename => "some_file_name",
38
+ # :file_size => "some_file_size",
39
+ # :tags => ["tag1", "tag2", "tag3"],
40
+ # :url => "file_url"
41
+ # })
42
+ # @asset.fetch
43
+ def initialize(attrs)
44
+ if attrs.class == String
45
+ @uid = attrs
46
+ else
47
+ attrs = attrs.symbolize_keys
48
+ @uid = attrs[:uid]
49
+ @content_type = attrs[:content_type]
50
+ @filename = attrs[:filename]
51
+ @file_size = attrs[:file_size]
52
+ @tags = attrs[:tags]
53
+ @url = attrs[:url]
54
+ end
55
+
56
+ self
57
+ end
58
+
59
+ # Fetch a particular asset using uid.
60
+ # @asset = @stack.asset('some_asset_uid')
61
+ # @asset.fetch
62
+ # puts @asset.url
63
+ def fetch
64
+ json = API.get_assets(@uid)
65
+ # puts "json -- #{json}"
66
+ self.class.new(json["asset"])
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,28 @@
1
+ require 'contentstack/asset'
2
+ require 'util'
3
+
4
+ module Contentstack
5
+ # Asset class to fetch details of files on Conentstack server.
6
+ class AssetCollection
7
+ using Utility
8
+ attr_reader :assets
9
+
10
+ def initialize(assets_array=nil)
11
+ if assets_array.nil?
12
+ @assets = []
13
+ return self
14
+ else
15
+ @assets = assets_array.collect{|a| Asset.new(a)}
16
+ end
17
+ end
18
+
19
+ # Fetch assets uploaded to Contentstack
20
+ #
21
+ # Example:
22
+ # @assets = @stack.assets.fetch
23
+ def fetch
24
+ json = API.get_assets
25
+ self.class.new(json["assets"])
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,92 @@
1
+ require 'contentstack/api'
2
+ require 'contentstack/content_type'
3
+ require 'contentstack/asset_collection'
4
+ require 'contentstack/sync_result'
5
+ require 'util'
6
+ require 'contentstack/error'
7
+ module Contentstack
8
+ class Client
9
+ using Utility
10
+ attr_reader :region, :host
11
+ # Initialize "Contentstack" Client instance
12
+ def initialize(api_key, delivery_token, environment, options={})
13
+ raise Contentstack::Error.new("Api Key is not valid") if api_key.class != String
14
+ raise Contentstack::Error.new("Api Key Field Should not be Empty") if api_key.empty?
15
+ raise Contentstack::Error.new("Delivery Token is not valid") if delivery_token.class != String
16
+ raise Contentstack::Error.new("Delivery Token Field Should not be Empty") if delivery_token.empty?
17
+ raise Contentstack::Error.new("Envirnoment Field is not valid") if environment.class != String
18
+ raise Contentstack::Error.new("Envirnoment Field Should not be Empty") if environment.empty?
19
+ @region = options[:region].nil? ? Contentstack::Region::US : options[:region]
20
+ @host = options[:host].nil? ? get_default_region_hosts(@region) : options[:host]
21
+ @live_preview = !options.key?(:live_preview) ? {} : options[:live_preview]
22
+ @branch = options[:branch].nil? ? "" : options[:branch]
23
+ @proxy_details = options[:proxy].nil? ? "" : options[:proxy]
24
+ @timeout = options[:timeout].nil? ? 3000 : options[:timeout]
25
+ @retryDelay = options[:retryDelay].nil? ? 3000 : options[:retryDelay]
26
+ @retryLimit = options[:retryLimit].nil? ? 5 : options[:retryLimit]
27
+ @errorRetry = options[:errorRetry].nil? ? [408, 429] : options[:errorRetry]
28
+ retry_options = {
29
+ "timeout" => @timeout.to_s,
30
+ "retryDelay"=> @retryDelay,
31
+ "retryLimit"=> @retryLimit,
32
+ "errorRetry" => @errorRetry
33
+ }
34
+ raise Contentstack::Error.new("Proxy URL Should not be Empty") if @proxy_details.present? && @proxy_details[:url].empty?
35
+ raise Contentstack::Error.new("Proxy Port Should not be Empty") if @proxy_details.present? && @proxy_details[:port].empty?
36
+ API.init_api(api_key, delivery_token, environment, @host, @branch, @live_preview, @proxy_details, retry_options)
37
+ end
38
+
39
+ def content_types
40
+ ContentType.all
41
+ end
42
+
43
+ def content_type(uid)
44
+ ContentType.new({uid: uid})
45
+ end
46
+
47
+ def assets
48
+ AssetCollection.new
49
+ end
50
+
51
+ def asset(uid)
52
+ Asset.new(uid)
53
+ end
54
+
55
+ def live_preview_query(query={})
56
+ API.live_preview_query(query)
57
+ end
58
+
59
+ # Syncs your Contentstack data with your app and ensures that the data is always up-to-date by providing delta updates
60
+ #
61
+ # Stack.sync({'init': true}) // For initializing sync
62
+ #
63
+ # Stack.sync({'init': true, 'locale': 'en-us'}) //For initializing sync with entries of a specific locale
64
+ #
65
+ # Stack.sync({'init': true, 'start_date': '2018-10-22'}) //For initializing sync with entries published after a specific date
66
+ #
67
+ # Stack.sync({'init': true, 'content_type_uid': 'session'}) //For initializing sync with entries of a specific content type
68
+ #
69
+ # Stack.sync({'init': true, 'type': 'entry_published'}) // Use the type parameter to get a specific type of content.Supports 'asset_published', 'entry_published', 'asset_unpublished', 'entry_unpublished', 'asset_deleted', 'entry_deleted', 'content_type_deleted'.
70
+ #
71
+ # Stack.sync({'pagination_token': '<pagination>'}) // For fetching the next batch of entries using pagination token
72
+ #
73
+ # Stack.sync({'sync_token': '<sync>'}) // For performing subsequent sync after initial sync
74
+ #
75
+ # @param params [Hash] params is an object that supports ‘locale’, ‘start_date’, ‘content_type_uid’, and ‘type’ queries.
76
+ def sync(params)
77
+ sync_result = API.get_sync_items(params)
78
+ SyncResult.new(sync_result)
79
+ end
80
+
81
+ private
82
+ def get_default_region_hosts(region='us')
83
+ case region
84
+ when "us"
85
+ host = "https://cdn.contentstack.io"
86
+ when "eu"
87
+ host = "https://eu-cdn.contentstack.com"
88
+ end
89
+ host
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,54 @@
1
+ require 'contentstack/query'
2
+ require 'util'
3
+
4
+ module Contentstack
5
+ class ContentType
6
+ using Utility
7
+ [:title, :uid, :created_at, :updated_at, :attributes].each do |method_name|
8
+ if [:created_at, :updated_at].include?(method_name)
9
+ define_method method_name do
10
+ return Time.parse(@attributes[method_name]) if @attributes[method_name] && !@attributes[method_name].nil?
11
+ end
12
+ elsif :attributes == method_name
13
+ define_method :attributes do
14
+ {
15
+ title: self.title,
16
+ uid: self.uid,
17
+ created_at: self.created_at,
18
+ updated_at: self.updated_at,
19
+ schema: @attributes[:schema]
20
+ }
21
+ end
22
+ else
23
+ define_method method_name do
24
+ return @attributes[method_name]
25
+ end
26
+ end
27
+ end
28
+
29
+ def initialize(object)
30
+ @attributes = object.symbolize_keys
31
+ end
32
+
33
+ def query
34
+ Query.new(self.uid)
35
+ end
36
+
37
+ def entry(entry_uid)
38
+ Entry.new({uid: entry_uid}, self.uid)
39
+ end
40
+
41
+
42
+ def self.all
43
+ content_types = API.fetch_content_types["content_types"]
44
+ content_types.map do |content_type|
45
+ ContentType.new(content_type.inject({}){|clone,(k,v)| clone[k.to_sym] = v; clone})
46
+ end
47
+ end
48
+
49
+ def fetch
50
+ content_type = API.fetch_content_types(uid)["content_type"]
51
+ ContentType.new(content_type.inject({}){|clone,(k,v)| clone[k.to_sym] = v; clone})
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,222 @@
1
+ require 'active_support/core_ext'
2
+ require 'util'
3
+
4
+ module Contentstack
5
+ class Entry
6
+ using Utility
7
+ attr_reader :fields, :content_type, :uid, :owner, :query, :schema, :content_type
8
+ def initialize(attrs, content_type_uid=nil)
9
+ setup(attrs, content_type_uid)
10
+ end
11
+
12
+ # Get entries from the specified locale.
13
+ #
14
+ # @param [String] code The locale code of the entry
15
+ #
16
+ # Example
17
+ # @entry = @stack.content_type('category').entry(entry_uid)
18
+ # @entry.locale('en-us')
19
+ #
20
+ # @return [Contentstack::Entry]
21
+ def locale(code)
22
+ @query[:locale] = code
23
+ self
24
+ end
25
+
26
+ # Specifies an array of 'only' keys in BASE object that would be 'included' in the response.
27
+ #
28
+ # @param [Array] fields Array of the 'only' reference keys to be included in response.
29
+ # @param [Array] fields_with_base Can be used to denote 'only' fields of the reference class
30
+ #
31
+ # Example
32
+ # # Include only title and description field in response
33
+ # @entry = @stack.content_type('category').entry(entry_uid)
34
+ # @entry.only(['title', 'description'])
35
+ #
36
+ # # Query product and include only the title and description from category reference
37
+ # @entry = @stack.content_type('product').entry(entry_uid)
38
+ # @entry.include_reference('category')
39
+ # .only('category', ['title', 'description'])
40
+ #
41
+ # @return [Contentstack::Entry]
42
+ def only(fields, fields_with_base=nil)
43
+ q = {}
44
+ if [Array, String].include?(fields_with_base.class)
45
+ fields_with_base = [fields_with_base] if fields_with_base.class == String
46
+ q[fields.to_sym] = fields_with_base
47
+ else
48
+ fields = [fields] if fields.class == String
49
+ q = {BASE: fields}
50
+ end
51
+
52
+ @query[:only] = q
53
+ self
54
+ end
55
+
56
+ # Specifies list of field uids that would be 'excluded' from the response.
57
+ #
58
+ # @param [Array] fields Array of field uid which get 'excluded' from the response.
59
+ # @param [Array] fields_with_base Can be used to denote 'except' fields of the reference class
60
+ #
61
+ # Example
62
+ # # Exclude 'description' field in response
63
+ # @entry = @stack.content_type('category').entry(entry_uid)
64
+ # @entry.except(['description'])
65
+ #
66
+ # # Query product and exclude the 'description' from category reference
67
+ # @entry = @stack.content_type('product').entry(entry_uid)
68
+ # @entry.include_reference('category')
69
+ # .except('category', ['description'])
70
+ #
71
+ # @return [Contentstack::Entry]
72
+ def except(fields, fields_with_base=nil)
73
+ q = {}
74
+ if [Array, String].include?(fields_with_base.class)
75
+ fields_with_base = [fields_with_base] if fields_with_base.class == String
76
+ q[fields.to_sym] = fields_with_base
77
+ else
78
+ fields = [fields] if fields.class == String
79
+ q = {BASE: fields}
80
+ end
81
+
82
+ @query[:except] = q
83
+ self
84
+ end
85
+
86
+ # Add a constraint that requires a particular reference key details.
87
+ #
88
+ # @param [String/Array] reference_field_uids Pass string or array of reference fields that must be included in the response
89
+ #
90
+ # Example
91
+ #
92
+ # # Include reference of 'category'
93
+ # @entry = @stack.content_type('product').entry(entry_uid)
94
+ # @entry.include_reference('category')
95
+ #
96
+ # # Include reference of 'category' and 'reviews'
97
+ # @entry = @stack.content_type('product').entry(entry_uid)
98
+ # @entry.include_reference(['category', 'reviews'])
99
+ #
100
+ # @return [Contentstack::Entry]
101
+ def include_reference(reference_field_uids)
102
+ self.include(reference_field_uids)
103
+ end
104
+
105
+ # Include schemas of all returned objects along with objects themselves.
106
+ #
107
+ # Example
108
+ #
109
+ # @entry = @stack.content_type('product').entry(entry_uid)
110
+ # @entry.include_schema
111
+ #
112
+ # @return [Contentstack::Entry]
113
+ def include_schema(flag=true)
114
+ @query[:include_schema] = flag
115
+ self
116
+ end
117
+
118
+ # Include object owner's profile in the objects data.
119
+ #
120
+ # Example
121
+ #
122
+ # @entry = @stack.content_type('product').entry(entry_uid)
123
+ # @entry.include_owner
124
+ #
125
+ # @return [Contentstack::Entry]
126
+ def include_owner(flag=true)
127
+ @query[:include_owner] = flag
128
+ self
129
+ end
130
+
131
+ # Include object's content_type in response
132
+ #
133
+ # Example
134
+ #
135
+ # @entry = @stack.content_type('product').entry(entry_uid)
136
+ # @entry.include_content_type
137
+ #
138
+ # @return [Contentstack::Entry]
139
+ def include_content_type(flag=true)
140
+ @query[:include_content_type] = flag
141
+ self
142
+ end
143
+
144
+ # Include the fallback locale publish content, if specified locale content is not publish.
145
+ #
146
+ # Example
147
+ #
148
+ # @entry = @stack.content_type('product').entry(entry_uid)
149
+ # @entry.include_fallback
150
+ #
151
+ # @return [Contentstack::Entry]
152
+ def include_fallback(flag=true)
153
+ @query[:include_fallback] = flag
154
+ self
155
+ end
156
+
157
+ # Include the branch for publish content.
158
+ #
159
+ # Example
160
+ #
161
+ # @entry = @stack.content_type('product').entry(entry_uid)
162
+ # @entry.include_branch
163
+ #
164
+ # @return [Contentstack::Entry]
165
+ def include_branch(flag=true)
166
+ @query[:include_branch] = flag
167
+ self
168
+ end
169
+
170
+ # Include Embedded Objects (Entries and Assets) along with entry/entries details.
171
+ #
172
+ # Example
173
+ #
174
+ # @entry = @stack.content_type('product').entry(entry_uid)
175
+ # @entry.include_embedded_items
176
+ #
177
+ # @return [Contentstack::Query]
178
+ def include_embedded_items()
179
+ @query[:include_embedded_items] = ['BASE']
180
+ self
181
+ end
182
+
183
+ #
184
+ # @return [Contentstack::Query]
185
+ def include(field_uids)
186
+ field_uids = [field_uids] if field_uids.class == String
187
+ @query[:include] ||= []
188
+ @query[:include] = @query[:include] | field_uids
189
+ self
190
+ end
191
+
192
+ # Execute entry
193
+ #
194
+ # Example
195
+ #
196
+ # @entry = @stack.content_type('product').entry(entry_uid)
197
+ # @entry.fetch
198
+ #
199
+ # @return [Contentstack::EntryCollection]
200
+ def fetch
201
+ entry = API.fetch_entry(@content_type, self.fields[:uid], @query)
202
+ setup(entry["entry"])
203
+ @schema = entry["schema"].symbolize_keys if entry["schema"]
204
+ @content_type = entry["content_type"].symbolize_keys if entry["content_type"]
205
+ self
206
+ end
207
+
208
+ def get(field_uid)
209
+ raise Contentstack::Error("Please send a valid Field UID") if field_uid.class != String
210
+ @fields[field_uid.to_sym]
211
+ end
212
+
213
+ private
214
+ def setup(attrs, content_type_uid=nil)
215
+ @fields = attrs.symbolize_keys
216
+ @content_type = content_type_uid if !content_type_uid.blank?
217
+ @owner = attrs[:_owner] if attrs[:_owner]
218
+ @uid = attrs[:uid]
219
+ @query = {}
220
+ end
221
+ end
222
+ end