locomotivecms_mounter 1.0.0.alpha1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. data/lib/locomotive/mounter/config.rb +21 -0
  2. data/lib/locomotive/mounter/engine_api.rb +40 -0
  3. data/lib/locomotive/mounter/exceptions.rb +38 -0
  4. data/lib/locomotive/mounter/extensions/compass.rb +36 -0
  5. data/lib/locomotive/mounter/extensions/httmultiparty.rb +22 -0
  6. data/lib/locomotive/mounter/extensions/tilt/css.rb +31 -0
  7. data/lib/locomotive/mounter/extensions/tilt/haml.rb +27 -0
  8. data/lib/locomotive/mounter/extensions/tilt/liquid.rb +23 -0
  9. data/lib/locomotive/mounter/extensions/tilt/template.rb +11 -0
  10. data/lib/locomotive/mounter/fields.rb +250 -0
  11. data/lib/locomotive/mounter/models/base.rb +41 -0
  12. data/lib/locomotive/mounter/models/content_asset.rb +84 -0
  13. data/lib/locomotive/mounter/models/content_entry.rb +290 -0
  14. data/lib/locomotive/mounter/models/content_field.rb +128 -0
  15. data/lib/locomotive/mounter/models/content_select_option.rb +29 -0
  16. data/lib/locomotive/mounter/models/content_type.rb +217 -0
  17. data/lib/locomotive/mounter/models/editable_element.rb +27 -0
  18. data/lib/locomotive/mounter/models/page.rb +377 -0
  19. data/lib/locomotive/mounter/models/site.rb +27 -0
  20. data/lib/locomotive/mounter/models/snippet.rb +55 -0
  21. data/lib/locomotive/mounter/models/theme_asset.rb +135 -0
  22. data/lib/locomotive/mounter/models/translation.rb +28 -0
  23. data/lib/locomotive/mounter/mounting_point.rb +49 -0
  24. data/lib/locomotive/mounter/reader/api/base.rb +49 -0
  25. data/lib/locomotive/mounter/reader/api/content_assets_reader.rb +40 -0
  26. data/lib/locomotive/mounter/reader/api/content_entries_reader.rb +141 -0
  27. data/lib/locomotive/mounter/reader/api/content_types_reader.rb +74 -0
  28. data/lib/locomotive/mounter/reader/api/pages_reader.rb +174 -0
  29. data/lib/locomotive/mounter/reader/api/site_reader.rb +37 -0
  30. data/lib/locomotive/mounter/reader/api/snippets_reader.rb +59 -0
  31. data/lib/locomotive/mounter/reader/api/theme_assets_reader.rb +42 -0
  32. data/lib/locomotive/mounter/reader/api/translations_reader.rb +28 -0
  33. data/lib/locomotive/mounter/reader/api.rb +49 -0
  34. data/lib/locomotive/mounter/reader/file_system/base.rb +65 -0
  35. data/lib/locomotive/mounter/reader/file_system/content_assets_reader.rb +88 -0
  36. data/lib/locomotive/mounter/reader/file_system/content_entries_reader.rb +101 -0
  37. data/lib/locomotive/mounter/reader/file_system/content_types_reader.rb +88 -0
  38. data/lib/locomotive/mounter/reader/file_system/pages_reader.rb +206 -0
  39. data/lib/locomotive/mounter/reader/file_system/site_reader.rb +24 -0
  40. data/lib/locomotive/mounter/reader/file_system/snippets_reader.rb +78 -0
  41. data/lib/locomotive/mounter/reader/file_system/theme_assets_reader.rb +78 -0
  42. data/lib/locomotive/mounter/reader/file_system/translations_reader.rb +36 -0
  43. data/lib/locomotive/mounter/reader/file_system.rb +42 -0
  44. data/lib/locomotive/mounter/reader/runner.rb +89 -0
  45. data/lib/locomotive/mounter/utils/hash.rb +31 -0
  46. data/lib/locomotive/mounter/utils/string.rb +17 -0
  47. data/lib/locomotive/mounter/utils/yaml.rb +125 -0
  48. data/lib/locomotive/mounter/version.rb +8 -0
  49. data/lib/locomotive/mounter/writer/api/base.rb +323 -0
  50. data/lib/locomotive/mounter/writer/api/content_assets_writer.rb +74 -0
  51. data/lib/locomotive/mounter/writer/api/content_entries_writer.rb +223 -0
  52. data/lib/locomotive/mounter/writer/api/content_types_writer.rb +151 -0
  53. data/lib/locomotive/mounter/writer/api/pages_writer.rb +225 -0
  54. data/lib/locomotive/mounter/writer/api/site_writer.rb +164 -0
  55. data/lib/locomotive/mounter/writer/api/snippets_writer.rb +111 -0
  56. data/lib/locomotive/mounter/writer/api/theme_assets_writer.rb +152 -0
  57. data/lib/locomotive/mounter/writer/api/translations_writer.rb +83 -0
  58. data/lib/locomotive/mounter/writer/api.rb +62 -0
  59. data/lib/locomotive/mounter/writer/file_system/base.rb +61 -0
  60. data/lib/locomotive/mounter/writer/file_system/content_assets_writer.rb +33 -0
  61. data/lib/locomotive/mounter/writer/file_system/content_entries_writer.rb +29 -0
  62. data/lib/locomotive/mounter/writer/file_system/content_types_writer.rb +27 -0
  63. data/lib/locomotive/mounter/writer/file_system/pages_writer.rb +73 -0
  64. data/lib/locomotive/mounter/writer/file_system/site_writer.rb +25 -0
  65. data/lib/locomotive/mounter/writer/file_system/snippets_writer.rb +54 -0
  66. data/lib/locomotive/mounter/writer/file_system/theme_assets_writer.rb +35 -0
  67. data/lib/locomotive/mounter/writer/file_system/translations_writer.rb +22 -0
  68. data/lib/locomotive/mounter/writer/file_system.rb +69 -0
  69. data/lib/locomotive/mounter/writer/runner.rb +68 -0
  70. data/lib/locomotive/mounter.rb +97 -0
  71. metadata +487 -0
@@ -0,0 +1,323 @@
1
+ module Locomotive
2
+ module Mounter
3
+ module Writer
4
+ module Api
5
+
6
+ class Base
7
+
8
+ @@buffer_enabled = false
9
+ @@buffer_log = ''
10
+
11
+ attr_accessor :mounting_point, :runner
12
+
13
+ delegate :default_locale, :locales, :site, to: :mounting_point
14
+
15
+ def initialize(mounting_point, runner)
16
+ self.mounting_point = mounting_point
17
+ self.runner = runner
18
+ end
19
+
20
+ # A write may have to do some work before being launched.
21
+ # By default, it displays to the output the resource being pushed.
22
+ #
23
+ def prepare
24
+ self.output_title
25
+ end
26
+
27
+ # By setting the force option to true, some resources (site, content assets, ...etc)
28
+ # may overide the content of the remote engine during the push operation.
29
+ # By default, its value is false.
30
+ #
31
+ # @return [ Boolean ] True if the force option has been set to true
32
+ #
33
+ def force?
34
+ self.runner.parameters[:force] || false
35
+ end
36
+
37
+ # By setting the data option to true, user content (content entries and
38
+ # editable elements from page) can be pushed too.
39
+ # By default, its value is false.
40
+ #
41
+ # @return [ Boolean ] True if the data option has been set to true
42
+ #
43
+ def data?
44
+ self.runner.parameters[:data] || false
45
+ end
46
+
47
+ # Get remote resource(s) by the API
48
+ #
49
+ # @param [ String ] resource_name The path to the resource (usually, the resource name)
50
+ # @param [ String ] locale The locale for the request
51
+ # @param [ Boolean ] raw True if the result has to be converted into object.
52
+ #
53
+ # @return [ Object] The object or a collection of objects.
54
+ #
55
+ def get(resource_name, locale = nil, raw = false)
56
+ params = { query: {} }
57
+
58
+ params[:query][:locale] = locale if locale
59
+
60
+ response = Locomotive::Mounter::EngineApi.get("/#{resource_name}.json", params)
61
+ data = response.parsed_response
62
+
63
+ if response.success?
64
+ return data if raw
65
+ self.raw_data_to_object(data)
66
+ else
67
+ nil
68
+ end
69
+ end
70
+
71
+ # Create a resource by the API.
72
+ #
73
+ # @param [ String ] resource_name The path to the resource (usually, the resource name)
74
+ # @param [ Hash ] params The attributes of the resource
75
+ # @param [ String ] locale The locale for the request
76
+ # @param [ Boolean ] raw True if the result has to be converted into object.
77
+ #
78
+ # @return [ Object] The response of the API or nil if an error occurs
79
+ #
80
+ def post(resource_name, params, locale = nil, raw = false)
81
+ params_name = resource_name.to_s.split('/').last.singularize
82
+
83
+ query = { query: { params_name => params } }
84
+
85
+ query[:query][:locale] = locale if locale
86
+
87
+ response = Locomotive::Mounter::EngineApi.post("/#{resource_name}.json", query)
88
+ data = response.parsed_response
89
+
90
+ if response.success?
91
+ return data if raw
92
+ self.raw_data_to_object(data)
93
+ else
94
+ message = data
95
+
96
+ message = data.map do |attribute, errors|
97
+ " #{attribute} => #{[*errors].join(', ')}\n".colorize(color: :red)
98
+ end.join("\n") if data.respond_to?(:keys)
99
+
100
+ raise WriterException.new(message)
101
+
102
+ # self.log "\n"
103
+ # data.each do |attribute, errors|
104
+ # self.log " #{attribute} => #{[*errors].join(', ')}\n".colorize(color: :red)
105
+ # end if data.respond_to?(:keys)
106
+ # nil
107
+ end
108
+ end
109
+
110
+ # Update a resource by the API.
111
+ #
112
+ # @param [ String ] resource_name The path to the resource (usually, the resource name)
113
+ # @param [ String ] id The unique identifier of the resource
114
+ # @param [ Hash ] params The attributes of the resource
115
+ # @param [ String ] locale The locale for the request
116
+ #
117
+ # @return [ Object] The response of the API or nil if an error occurs
118
+ #
119
+ def put(resource_name, id, params, locale = nil)
120
+ params_name = resource_name.to_s.split('/').last.singularize
121
+
122
+ query = { query: { params_name => params } }
123
+
124
+ query[:query][:locale] = locale if locale
125
+
126
+ response = Locomotive::Mounter::EngineApi.put("/#{resource_name}/#{id}.json", query)
127
+ data = response.parsed_response
128
+
129
+ if response.success?
130
+ self.raw_data_to_object(data)
131
+ else
132
+ message = data
133
+
134
+ message = data.map do |attribute, errors|
135
+ " #{attribute} => #{[*errors].join(', ')}" #.colorize(color: :red)
136
+ end.join("\n") if data.respond_to?(:keys)
137
+
138
+ raise WriterException.new(message)
139
+
140
+ # data.each do |attribute, errors|
141
+ # self.log "\t\t #{attribute} => #{[*errors].join(', ')}".colorize(color: :red)
142
+ # end if data.respond_to?(:keys)
143
+ # nil
144
+ end
145
+ end
146
+
147
+ def safe_attributes
148
+ %w(_id)
149
+ end
150
+
151
+ # Loop on each locale of the mounting point and
152
+ # change the current locale at the same time.
153
+ def each_locale(&block)
154
+ self.mounting_point.locales.each do |locale|
155
+ Locomotive::Mounter.with_locale(locale) do
156
+ block.call(locale)
157
+ end
158
+ end
159
+ end
160
+
161
+ # Return the absolute path from a relative path
162
+ # pointing to an asset within the public folder
163
+ #
164
+ # @param [ String ] path The path to the file within the public folder
165
+ #
166
+ # @return [ String ] The absolute path
167
+ #
168
+ def absolute_path(path)
169
+ File.join(self.mounting_point.path, 'public', path)
170
+ end
171
+
172
+ # Take a path and convert it to a File object if possible
173
+ #
174
+ # @param [ String ] path The path to the file within the public folder
175
+ #
176
+ # @return [ Object ] The file
177
+ #
178
+ def path_to_file(path)
179
+ File.new(self.absolute_path(path))
180
+ end
181
+
182
+ # Take in the source the assets whose url begins by "/samples",
183
+ # upload them to the engine and replace them by their remote url.
184
+ #
185
+ # @param [ String ] source The source text
186
+ #
187
+ # @return [ String ] The source with remote urls
188
+ #
189
+ def replace_content_assets!(source)
190
+ return source if source.blank?
191
+
192
+ source.to_s.gsub(/\/samples\/.*\.[a-zA-Z0-9]+/) do |match|
193
+ url = self.runner.content_assets_writer.write(match)
194
+ url || match
195
+ end
196
+ end
197
+
198
+ protected
199
+
200
+ def response_to_status(response)
201
+ response ? :success : :error
202
+ end
203
+
204
+ # Convert raw data into the corresponding object (Page, Site, ...etc)
205
+ #
206
+ # @param [ Hash ] data The attributes of the object
207
+ #
208
+ # @return [ Object ] A new instance of the object
209
+ #
210
+ def raw_data_to_object(data)
211
+ case data
212
+ when Hash then data.to_hash.delete_if { |k, _| !self.safe_attributes.include?(k) }
213
+ when Array
214
+ data.map do |row|
215
+ # puts "#{row.inspect}\n---" # DEBUG
216
+ row.delete_if { |k, _| !self.safe_attributes.include?(k) }
217
+ end
218
+ else
219
+ data
220
+ end
221
+ end
222
+
223
+ # Print the the title for each kind of resource.
224
+ #
225
+ def output_title
226
+ msg = "* Pushing #{self.class.name.gsub(/Writer$/, '').demodulize}"
227
+ self.log msg.colorize(background: :white, color: :black) + "\n"
228
+ end
229
+
230
+ # Print the current locale.
231
+ #
232
+ def output_locale
233
+ locale = Locomotive::Mounter.locale.to_s
234
+ self.log " #{locale.colorize(background: :blue, color: :white)}\n"
235
+ end
236
+
237
+ # Print the message about the creation / update of a resource.
238
+ #
239
+ # @param [ Object ] resource The resource (Site, Page, ...etc).
240
+ #
241
+ def output_resource_op(resource)
242
+ self.log self.resource_message(resource)
243
+ end
244
+
245
+ # Print the message about the creation / update of a resource.
246
+ #
247
+ # @param [ Object ] resource The resource (Site, Page, ...etc).
248
+ # @param [ Symbol ] status :success, :error, :skipped
249
+ # @param [ String ] errors The error messages
250
+ #
251
+ def output_resource_op_status(resource, status = :success, errors = nil)
252
+ status_label = case status
253
+ when :success then 'done'.colorize(color: :green)
254
+ when :error then 'error'.colorize(color: :red)
255
+ when :skipped then 'skipped'.colorize(color: :magenta)
256
+ when :not_translated then 'not translated (itself or parent)'.colorize(color: :yellow)
257
+ end
258
+
259
+ spaces = '.' * (80 - self.resource_message(resource).size)
260
+ self.log "#{spaces}[#{status_label}]\n"
261
+
262
+ if errors && status == :error
263
+ self.log "#{errors.colorize(color: :red)}\n"
264
+ end
265
+ end
266
+
267
+ # Return the message about the creation / update of a resource.
268
+ #
269
+ # @param [ Object ] resource The resource (Site, Page, ...etc).
270
+ #
271
+ # @return [ String ] The message
272
+ #
273
+ def resource_message(resource)
274
+ op_label = resource.persisted? ? 'updating': 'creating'
275
+ " #{op_label} #{resource.to_s}"
276
+ end
277
+
278
+ # Log a message to the console or the logger depending on the options
279
+ # of the runner. Info is the log level if case the logger has been chosen.
280
+ #
281
+ # @param [ String ] message The message to log.
282
+ #
283
+ def log(message)
284
+ # puts "buffer ? #{@@buffer_enabled.inspect}"
285
+ if @@buffer_enabled
286
+ @@buffer_log << message
287
+ else
288
+ if self.runner.parameters[:console]
289
+ print message
290
+ else
291
+ Mounter.logger.info message #.gsub(/\n$/, '')
292
+ end
293
+ end
294
+ end
295
+
296
+ # Put in a buffer the logs generated when executing the block.
297
+ # It means that they will not output unless the flush_log_buffer
298
+ # method is called.
299
+ #
300
+ # @return [ Object ] Thee value returned by the call of the block
301
+ #
302
+ def buffer_log(&block)
303
+ @@buffer_log = ''
304
+ @@buffer_enabled = true
305
+ if block_given?
306
+ block.call.tap { @@buffer_enabled = false }
307
+ end
308
+ end
309
+
310
+ # Flush the logs put in a buffer.
311
+ #
312
+ def flush_log_buffer
313
+ @@buffer_enabled = false
314
+ self.log(@@buffer_log)
315
+ @@buffer_log = ''
316
+ end
317
+
318
+ end
319
+
320
+ end
321
+ end
322
+ end
323
+ end
@@ -0,0 +1,74 @@
1
+ module Locomotive
2
+ module Mounter
3
+ module Writer
4
+ module Api
5
+
6
+ # Push content assets to a remote LocomotiveCMS engine.
7
+ #
8
+ # The assets come from editable content blocks, for instance, in a
9
+ # the text fields of content entries or within editable_***_text.
10
+ # If an asset with the same filename already exists in the engine,
11
+ # the local version will not pushed unless the :force_assets option is passed
12
+ #
13
+ class ContentAssetsWriter < Base
14
+
15
+ attr_accessor :remote_assets
16
+
17
+ def prepare
18
+ self.remote_assets = {}
19
+
20
+ # assign an _id to a local content type if possible
21
+ self.get(:content_assets, nil, true).each do |attributes|
22
+ self.remote_assets[attributes['full_filename']] = attributes
23
+ end
24
+ end
25
+
26
+ def write(local_path)
27
+ status = :skipped
28
+ asset = self.build_asset(local_path)
29
+ response = self.remote_assets[asset.filename]
30
+
31
+ asset._id = response['_id'] if response
32
+
33
+ self.output_resource_op asset
34
+
35
+ if !asset.exists?
36
+ status = :error
37
+ elsif asset.persisted?
38
+ if asset.size != response['size'].to_i && self.force_assets?
39
+ # update it
40
+ response = self.put :content_assets, asset._id, asset.to_params
41
+ status = self.response_to_status(response)
42
+ end
43
+ else
44
+ # create it
45
+ response = self.post :content_assets, asset.to_params, nil, true
46
+ status = self.response_to_status(response)
47
+
48
+ self.remote_assets[response['full_filename']] = response
49
+ end
50
+
51
+ self.output_resource_op_status asset, status
52
+
53
+ [:success, :skipped].include?(status) ? response['url'] : nil
54
+ end
55
+
56
+ protected
57
+
58
+ def build_asset(local_path)
59
+ Locomotive::Mounter::Models::ContentAsset.new(filepath: self.absolute_path(local_path))
60
+ end
61
+
62
+ def force_assets?
63
+ self.runner.parameters[:force_assets] || false
64
+ end
65
+
66
+ def resource_message(resource)
67
+ " #{super}"
68
+ end
69
+
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,223 @@
1
+ module Locomotive
2
+ module Mounter
3
+ module Writer
4
+ module Api
5
+
6
+ # Push content entries to a remote LocomotiveCMS engine.
7
+ #
8
+ # TODO: They get created or changed only if the
9
+ # :data option has been passed.
10
+ #
11
+ class ContentEntriesWriter < Base
12
+
13
+ attr_accessor :with_relationships
14
+
15
+ def prepare
16
+ return unless self.data?
17
+
18
+ super
19
+
20
+ # initialize the list storing all the entries including relationships
21
+ self.with_relationships = []
22
+
23
+ # assign an _id to a local content entry if possible
24
+ self.content_types.each do |slug, content_type|
25
+ self.get("content_types/#{slug}/entries", nil, true).each do |attributes|
26
+ content_entry = content_type.find_entry(attributes['_slug'])
27
+
28
+ if content_entry
29
+ self.apply_response(content_entry, attributes)
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ def write
36
+ return unless self.data?
37
+
38
+ self.each_locale do |locale|
39
+ self.output_locale
40
+
41
+ self.content_types.each do |slug, content_type|
42
+ (content_type.entries || []).each do |entry|
43
+ next unless entry.translated_in?(locale)
44
+
45
+ if entry.persisted?
46
+ self.update_content_entry(slug, entry)
47
+ else
48
+ self.create_content_entry(slug, entry)
49
+ end
50
+
51
+ self.register_relationships(slug, entry)
52
+ end # content entries
53
+ end # content type
54
+ end # locale
55
+
56
+ self.persist_content_entries_with_relationships
57
+ end
58
+
59
+ protected
60
+
61
+ # Persist a content entry by calling the API. It is enhanced then
62
+ # by the response if no errors occured.
63
+ #
64
+ # @param [ String ] content_type The slug of the content type
65
+ # @param [ Object ] content_entry The content entry to create
66
+ #
67
+ def create_content_entry(content_type, content_entry)
68
+ # log before
69
+ self.output_resource_op content_entry
70
+
71
+ # get the params
72
+ params = self.buffer_log { self.content_entry_to_params(content_entry) }
73
+
74
+ # send the request
75
+ response = self.post "content_types/#{content_type}/entries", params, nil, true
76
+
77
+ self.apply_response(content_entry, response)
78
+
79
+ status = self.response_to_status(response)
80
+
81
+ # log after
82
+ self.output_resource_op_status content_entry, status
83
+ self.flush_log_buffer
84
+ end
85
+
86
+ # Update a content entry by calling the API.
87
+ #
88
+ # @param [ String ] content_type The slug of the content type
89
+ # @param [ Object ] content_entry The content entry to update
90
+ #
91
+ def update_content_entry(content_type, content_entry)
92
+ locale = Locomotive::Mounter.locale
93
+
94
+ # log before
95
+ self.output_resource_op content_entry
96
+
97
+ # get the params
98
+ params = self.buffer_log { self.content_entry_to_params(content_entry) }
99
+
100
+ # send the request
101
+ response = self.put "content_types/#{content_type}/entries", content_entry._id, params, locale
102
+
103
+ status = self.response_to_status(response)
104
+
105
+ # log after
106
+ self.output_resource_op_status content_entry, status
107
+ self.flush_log_buffer
108
+ end
109
+
110
+ # Save to the remote engine the content entries owning
111
+ # a relationship field. This can be done once ALL the
112
+ # the content entries have been first created.
113
+ #
114
+ def persist_content_entries_with_relationships
115
+ unless self.with_relationships.empty?
116
+ self.log "\n setting relationships for all the content entries\n"
117
+
118
+ updates = self.content_entries_with_relationships_to_hash
119
+
120
+ updates.each do |params|
121
+ _id, slug = params.delete(:_id), params.delete(:slug)
122
+ self.put "content_types/#{slug}/entries", _id, params
123
+ end
124
+ end
125
+ end
126
+
127
+ # Build hash storing the values of the relationships (belongs_to and has_many).
128
+ # The key is the id of the content entry
129
+ #
130
+ # @return [ Hash ] The updates to process
131
+ #
132
+ def content_entries_with_relationships_to_hash
133
+ [].tap do |updates|
134
+ self.with_relationships.each do |(slug, content_entry)|
135
+ changes = {}
136
+
137
+ content_entry.content_type.fields.each do |field|
138
+ case field.type.to_sym
139
+ when :belongs_to
140
+ if target_id = content_entry.dynamic_getter(field.name).try(:_id)
141
+ changes["#{field.name}_id"] = target_id
142
+ end
143
+ when :many_to_many
144
+ target_ids = content_entry.dynamic_getter(field.name).map(&:_id).compact
145
+ unless target_ids.empty?
146
+ changes["#{field.name}_ids"] = target_ids
147
+ end
148
+ end
149
+ end
150
+
151
+ updates << { _id: content_entry._id, slug: slug }.merge(changes)
152
+ end
153
+ end
154
+ end
155
+
156
+ # Return the list of content types
157
+ #
158
+ # @return [ Array ] List of content types
159
+ #
160
+ def content_types
161
+ self.mounting_point.content_types
162
+ end
163
+
164
+ # Take a content entry and get the params related to that content
165
+ #
166
+ # @param [ Object ] entry The content entry
167
+ #
168
+ # @return [ Hash ] The params
169
+ #
170
+ def content_entry_to_params(entry)
171
+ params = entry.to_params
172
+
173
+ entry.each_dynamic_field do |field, value|
174
+ case field.type.to_sym
175
+ when :string, :text
176
+ params[field.name] = self.replace_content_assets!(value)
177
+ when :date, :select, :boolean
178
+ params[field.name] = value
179
+ when :file
180
+ if value =~ %r($http://)
181
+ params[field.name] = value
182
+ elsif value && self.mounting_point.path
183
+ path = File.join(self.mounting_point.path, 'public', value)
184
+ params[field.name] = File.new(path)
185
+ end
186
+ end
187
+ end
188
+
189
+ params
190
+ end
191
+
192
+ # Keep track of both the content entries which
193
+ # includes a relationship field and also
194
+ # the selection options.
195
+ #
196
+ # @param [ String ] slug The slug of the content type
197
+ # @param [ Object ] entry The content entry
198
+ #
199
+ def register_relationships(slug, entry)
200
+ entry.each_dynamic_field do |field, value|
201
+ if %w(belongs_to many_to_many).include?(field.type.to_s)
202
+ self.with_relationships << [slug, entry]
203
+ return # no need to go further and avoid duplicate entries
204
+ end
205
+ end
206
+ end
207
+
208
+ # Enhance the content entry with the information returned by an API call.
209
+ #
210
+ # @param [ Object ] content_entry The content entry instance
211
+ # @param [ Hash ] response The API response
212
+ #
213
+ def apply_response(content_entry, response)
214
+ return if content_entry.nil? || response.nil?
215
+
216
+ content_entry._id = response['_id']
217
+ end
218
+
219
+ end
220
+ end
221
+ end
222
+ end
223
+ end