locomotivecms_mounter 1.0.0.alpha4 → 1.0.1

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 (26) hide show
  1. data/lib/locomotive/mounter/engine_api.rb +5 -0
  2. data/lib/locomotive/mounter/fields.rb +5 -5
  3. data/lib/locomotive/mounter/models/base.rb +2 -1
  4. data/lib/locomotive/mounter/models/content_entry.rb +34 -6
  5. data/lib/locomotive/mounter/models/content_field.rb +2 -0
  6. data/lib/locomotive/mounter/models/content_type.rb +3 -0
  7. data/lib/locomotive/mounter/models/page.rb +12 -1
  8. data/lib/locomotive/mounter/reader/api/content_assets_reader.rb +1 -1
  9. data/lib/locomotive/mounter/reader/api/content_entries_reader.rb +4 -3
  10. data/lib/locomotive/mounter/reader/api/content_types_reader.rb +4 -4
  11. data/lib/locomotive/mounter/reader/api/pages_reader.rb +4 -3
  12. data/lib/locomotive/mounter/reader/api/site_reader.rb +1 -1
  13. data/lib/locomotive/mounter/reader/api/snippets_reader.rb +1 -1
  14. data/lib/locomotive/mounter/reader/api/theme_assets_reader.rb +1 -1
  15. data/lib/locomotive/mounter/reader/api/translations_reader.rb +2 -2
  16. data/lib/locomotive/mounter/reader/api.rb +4 -0
  17. data/lib/locomotive/mounter/reader/file_system/pages_reader.rb +4 -1
  18. data/lib/locomotive/mounter/version.rb +1 -1
  19. data/lib/locomotive/mounter/writer/api/base.rb +3 -10
  20. data/lib/locomotive/mounter/writer/api/pages_writer.rb +1 -0
  21. data/lib/locomotive/mounter/writer/api/theme_assets_writer.rb +20 -11
  22. data/lib/locomotive/mounter/writer/api/translations_writer.rb +1 -1
  23. data/lib/locomotive/mounter/writer/api.rb +4 -0
  24. data/lib/locomotive/mounter/writer/file_system/translations_writer.rb +2 -2
  25. data/lib/locomotive/mounter/writer/runner.rb +18 -8
  26. metadata +36 -4
@@ -33,6 +33,11 @@ module Locomotive
33
33
  raise WrongCredentials.new("#{response['message']} (#{response.code})")
34
34
  end
35
35
  end
36
+
37
+ def self.teardown
38
+ Locomotive::Mounter::EngineApi.default_options[:base_uri] = nil
39
+ Locomotive::Mounter::EngineApi.default_options[:default_params] = {}
40
+ end
36
41
 
37
42
  end
38
43
 
@@ -48,10 +48,11 @@ module Locomotive
48
48
 
49
49
  attributes.each do |name, value|
50
50
  unless self.class._fields.key?(name.to_sym) || self.respond_to?(:"#{name}=")
51
+ next if name.to_s == 'id'
51
52
  raise FieldDoesNotExistException.new "[#{self.class.inspect}] setting an unknown attribute '#{name}' with the value '#{value.inspect}'"
52
53
  end
53
54
 
54
- if self.localized?(name) && value.is_a?(Hash)
55
+ if self.localized_field?(name) && value.is_a?(Hash)
55
56
  self.send(:"#{name}_translations=", value)
56
57
  else
57
58
  self.send(:"#{name}=", value)
@@ -103,7 +104,7 @@ module Locomotive
103
104
  #
104
105
  # @return [ Boolean ] True if the field is localized
105
106
  #
106
- def localized?(name)
107
+ def localized_field?(name)
107
108
  method_name = :"#{name}_localized?"
108
109
  self.respond_to?(method_name) && self.send(method_name)
109
110
  end
@@ -171,10 +172,9 @@ module Locomotive
171
172
  def getter(name, options = {})
172
173
  value = self.instance_variable_get(:"@#{name}")
173
174
  if options[:localized]
174
- (value || {})[Locomotive::Mounter.locale]
175
- else
176
- value
175
+ value = (value || {})[Locomotive::Mounter.locale]
177
176
  end
177
+ value
178
178
  end
179
179
 
180
180
  def setter(name, value, options = {})
@@ -6,11 +6,12 @@ module Locomotive
6
6
 
7
7
  include Locomotive::Mounter::Fields
8
8
 
9
- attr_accessor :_id, :mounting_point
9
+ attr_accessor :_id, :mounting_point, :created_at, :updated_at
10
10
 
11
11
  ## methods ##
12
12
 
13
13
  def initialize(attributes = {})
14
+ self.created_at = self.updated_at = Time.now
14
15
  self.mounting_point = attributes.delete(:mounting_point)
15
16
  super
16
17
  end
@@ -20,11 +20,20 @@ module Locomotive
20
20
  alias :_permalink= :_slug=
21
21
 
22
22
  ## callbacks ##
23
- # set_callback :initialize, :after, :set_slug
24
23
  set_callback :initialize, :after, :set_default_main_locale
25
24
 
26
25
  ## methods ##
27
26
 
27
+ # By definition, if the label field defined in the content type is
28
+ # localized, then the content entry will be considered as localized.
29
+ #
30
+ # @return [ Boolean ] True if the label field is localized.
31
+ #
32
+ def localized?
33
+ field = self.content_type.label_field
34
+ !!field.try(:localized)
35
+ end
36
+
28
37
  # Return the internal label used to identify a content entry
29
38
  # in a YAML file for instance. It is based on the first field
30
39
  # of the related content type.
@@ -80,10 +89,6 @@ module Locomotive
80
89
 
81
90
  self.dynamic_fields.each do |field|
82
91
  value = self.localized_dynamic_attribute_value(field)
83
-
84
- # value = (self.dynamic_attributes || {})[field.name.to_sym]
85
- # value = value.try(:[], Locomotive::Mounter.locale) unless field.is_relationship? || !field.localized
86
-
87
92
  block.call(field, value)
88
93
  end
89
94
  end
@@ -231,12 +236,35 @@ module Locomotive
231
236
  self._slug = self.next_unique_slug if self.slug_already_taken?
232
237
  end
233
238
  end
239
+
240
+ self.fill_with_default_slug
241
+ end
242
+
243
+ # In case the content entry is not localized, we need to make sure
244
+ # it has an non empty slug for each locale of the site.
245
+ #
246
+ def fill_with_default_slug
247
+ return if self.localized?
248
+
249
+ # we do not want to add a new translation because the content entry
250
+ # is not truly "localized".
251
+ __locales = self._locales.dup
252
+
253
+ default_slug = self._slug_translations[self.mounting_point.default_locale]
254
+
255
+ self.mounting_point.locales.each do |locale|
256
+ Locomotive::Mounter.with_locale(locale) do
257
+ self._slug = default_slug if self._slug.blank?
258
+ end
259
+ end
260
+
261
+ self._locales = __locales
234
262
  end
235
263
 
236
264
  # Once the entry has been initialized, we keep track of the current locale
237
265
  #
238
266
  def set_default_main_locale
239
- self.main_locale = Locomotive::Mounter.locale
267
+ self.main_locale = self.content_type.mounting_point.default_locale
240
268
  end
241
269
 
242
270
  # Return the next available unique slug as a string
@@ -12,6 +12,7 @@ module Locomotive
12
12
  field :position, default: 0
13
13
  field :required, default: false
14
14
  field :localized, default: false
15
+ field :class_slug
15
16
 
16
17
  # text
17
18
  field :text_formatting
@@ -27,6 +28,7 @@ module Locomotive
27
28
 
28
29
  alias :target :class_name
29
30
  alias :target= :class_name=
31
+ alias :raw_select_options= :select_options=
30
32
 
31
33
  ## callbacks ##
32
34
  set_callback :initialize, :after, :prepare_attributes
@@ -58,6 +58,9 @@ module Locomotive
58
58
  #
59
59
  def build_entry(attributes)
60
60
  ContentEntry.new(content_type: self).tap do |entry|
61
+ # set the link to the mounting point
62
+ entry.mounting_point = self.mounting_point
63
+
61
64
  # do not forget that we are manipulating dynamic fields
62
65
  attributes.each do |k, v|
63
66
  begin
@@ -98,6 +98,17 @@ module Locomotive
98
98
  self._locales = locales.map(&:to_sym)
99
99
  end
100
100
 
101
+ # Set the content type, attribute required for templatized page.
102
+ # @deprecated. Use content_type= instead.
103
+ #
104
+ # @param [ Object ] content_type The content type
105
+ #
106
+ def model=(content_type)
107
+ Locomotive::Mounter.logger.warn 'The model attribute is deprecated. Use content_type instead.'
108
+ self.content_type = content_type
109
+ end
110
+
111
+
101
112
  # Modified setter in order to set correctly the slug
102
113
  #
103
114
  # @param [ String ] fullpath The fullpath
@@ -354,7 +365,7 @@ module Locomotive
354
365
  # @return [ Hash ] The safe params
355
366
  #
356
367
  def to_safe_params
357
- fields = %w(listed published handle cache_strategy redirect_url response_type templatized content_type_id position)
368
+ fields = %w(title slug listed published handle cache_strategy redirect_url response_type templatized content_type_id position)
358
369
 
359
370
  params = self.attributes.delete_if do |k, v|
360
371
  !fields.include?(k.to_s) || (!v.is_a?(FalseClass) && v.blank?)
@@ -28,7 +28,7 @@ module Locomotive
28
28
  protected
29
29
 
30
30
  def safe_attributes
31
- %w(_id url)
31
+ %w(_id url created_at updated_at)
32
32
  end
33
33
 
34
34
  end
@@ -76,7 +76,7 @@ module Locomotive
76
76
  # @return [ Object] The attributes understandable by the content entry
77
77
  #
78
78
  def filter_attributes(content_type, original_attributes)
79
- attributes = original_attributes.clone.keep_if { |k, v| %w(_id _slug seo_title meta_keywords meta_description _position).include?(k) }
79
+ attributes = original_attributes.clone.keep_if { |k, v| %w(_id _slug seo_title meta_keywords meta_description _position created_at updated_at).include?(k) }
80
80
 
81
81
  content_type.fields.each do |field|
82
82
  value = (case field.type
@@ -85,7 +85,7 @@ module Locomotive
85
85
  when :text
86
86
  self.replace_urls_by_content_assets(original_attributes[field.name])
87
87
  when :select
88
- field.name_for_select_option(original_attributes[field.name])
88
+ field.find_select_option(original_attributes[field.name]).try(:name)
89
89
  when :date
90
90
  original_attributes["formatted_#{field.name}"]
91
91
  when :belongs_to, :many_to_many
@@ -101,7 +101,7 @@ module Locomotive
101
101
  end
102
102
 
103
103
  attributes
104
- end
104
+ end
105
105
 
106
106
  # Some entries have what it is called "relationships" field
107
107
  # which can be only resolved once all the entries have been fetched
@@ -127,6 +127,7 @@ module Locomotive
127
127
  # @return [ String ] The content with local urls
128
128
  #
129
129
  def replace_urls_by_content_assets(content)
130
+ return "" unless content
130
131
  self.mounting_point.content_assets.each do |path, asset|
131
132
  content.gsub!(path, asset.local_filepath)
132
133
  end
@@ -55,15 +55,15 @@ module Locomotive
55
55
  def enable_relationships
56
56
  self.items.each do |_, content_type|
57
57
  content_type.fields.find_all(&:is_relationship?).each do |field|
58
- # look for the target content type from its class name
59
- target = self.items.values.find { |_content_type| _content_type.klass_name == field.class_name }
60
- field.class_name = target.slug
58
+ # look for the target content type from its slug
59
+ target = self.items.keys.find { |k| k == field.class_slug }
60
+ field.class_name = target
61
61
  end
62
62
  end
63
63
  end
64
64
 
65
65
  def safe_attributes
66
- %w(name slug description order_by order_direction label_field_name group_by_field_id public_submission_accounts entries_custom_fields klass_name)
66
+ %w(name slug description order_by order_direction label_field_name group_by_field_id public_submission_accounts entries_custom_fields klass_name created_at updated_at)
67
67
  end
68
68
 
69
69
  end
@@ -98,7 +98,7 @@ module Locomotive
98
98
 
99
99
  # content type
100
100
  if content_type_slug = attributes.delete('target_klass_slug')
101
- attributes['content_type'] = self.mounting_point.content_types[content_type_slug] #.values.find { |ct| ct._id == content_type_id }
101
+ attributes['content_type'] = self.mounting_point.content_types[content_type_slug] #.values.find { |ct| ct._id == content_type_id }
102
102
  end
103
103
 
104
104
  self.pages[fullpath] = Locomotive::Mounter::Models::Page.new(attributes)
@@ -128,7 +128,7 @@ module Locomotive
128
128
  end
129
129
 
130
130
  # Only keep the minimal attributes from a list of
131
- # editable elements hashes. It also replaces the url to
131
+ # editable elements hashes. It also replaces the url to
132
132
  # content assets by their corresponding local ones.
133
133
  #
134
134
  # @param [ Array ] list The list of the editable elements with all the attributes
@@ -149,7 +149,8 @@ module Locomotive
149
149
  %w(_id title slug handle fullpath translated_in target_klass_slug
150
150
  published listed templatized editable_elements
151
151
  redirect_url cache_strategy response_type position
152
- seo_title meta_keywords meta_description raw_template)
152
+ seo_title meta_keywords meta_description raw_template
153
+ created_at updated_at)
153
154
  end
154
155
 
155
156
  # Output simply the tree structure of the pages.
@@ -26,7 +26,7 @@ module Locomotive
26
26
  end
27
27
 
28
28
  def safe_attributes
29
- %w(name locales seo_title meta_keywords meta_description domains subdomain)
29
+ %w(name locales seo_title meta_keywords meta_description domains subdomain created_at updated_at)
30
30
  end
31
31
 
32
32
  end
@@ -48,7 +48,7 @@ module Locomotive
48
48
  end
49
49
 
50
50
  def safe_attributes
51
- %w(_id name slug template)
51
+ %w(_id name slug template created_at updated_at)
52
52
  end
53
53
 
54
54
  end
@@ -30,7 +30,7 @@ module Locomotive
30
30
  protected
31
31
 
32
32
  def safe_attributes
33
- %w(_id folder url)
33
+ %w(_id folder url created_at updated_at)
34
34
  end
35
35
 
36
36
  end
@@ -14,10 +14,10 @@ module Locomotive
14
14
  Locomotive::Mounter::Models::Translation.new(attributes)
15
15
  end
16
16
  end
17
-
17
+
18
18
  protected
19
19
  def safe_attributes
20
- %w[_id key values]
20
+ %w[_id key values created_at updated_at]
21
21
  end
22
22
  end
23
23
 
@@ -10,6 +10,10 @@ module Locomotive
10
10
  def self.instance
11
11
  @@instance ||= Runner.new(:api)
12
12
  end
13
+
14
+ def self.teardown
15
+ @@instance = nil
16
+ end
13
17
 
14
18
  class Runner < Locomotive::Mounter::Reader::Runner
15
19
 
@@ -108,7 +108,10 @@ module Locomotive
108
108
  attributes[:title] = File.basename(fullpath).humanize
109
109
  attributes[:fullpath] = fullpath
110
110
 
111
- self.pages[fullpath] = Locomotive::Mounter::Models::Page.new(attributes)
111
+ page = Locomotive::Mounter::Models::Page.new(attributes)
112
+ page.mounting_point = self.mounting_point
113
+
114
+ self.pages[fullpath] = page
112
115
  end
113
116
 
114
117
  self.pages[fullpath]
@@ -2,7 +2,7 @@
2
2
  module Locomotive
3
3
  module Mounter #:nodoc
4
4
 
5
- VERSION = '1.0.0.alpha4'
5
+ VERSION = '1.0.1'
6
6
 
7
7
  end
8
8
  end
@@ -12,6 +12,8 @@ module Locomotive
12
12
 
13
13
  delegate :default_locale, :locales, :site, to: :mounting_point
14
14
 
15
+ delegate :force?, to: :runner
16
+
15
17
  def initialize(mounting_point, runner)
16
18
  self.mounting_point = mounting_point
17
19
  self.runner = runner
@@ -24,16 +26,6 @@ module Locomotive
24
26
  self.output_title
25
27
  end
26
28
 
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
29
  # By setting the data option to true, user content (content entries and
38
30
  # editable elements from page) can be pushed too.
39
31
  # By default, its value is false.
@@ -253,6 +245,7 @@ module Locomotive
253
245
  when :success then 'done'.colorize(color: :green)
254
246
  when :error then 'error'.colorize(color: :red)
255
247
  when :skipped then 'skipped'.colorize(color: :magenta)
248
+ when :same then 'same'.colorize(color: :magenta)
256
249
  when :not_translated then 'not translated (itself or parent)'.colorize(color: :yellow)
257
250
  end
258
251
 
@@ -63,6 +63,7 @@ module Locomotive
63
63
  success = page.persisted? ? self.update_page(page) : self.create_page(page)
64
64
 
65
65
  self.output_resource_op_status page, success ? :success : :error
66
+
66
67
  self.flush_log_buffer
67
68
  end
68
69
 
@@ -37,27 +37,36 @@ module Locomotive
37
37
  self.output_resource_op theme_asset
38
38
 
39
39
  status = :skipped
40
+ errors = []
40
41
  file = self.build_temp_file(theme_asset)
41
42
  params = theme_asset.to_params.merge(source: file, performing_plain_text: false)
42
43
 
43
- if theme_asset.persisted?
44
- # we only update it if the size has changed or if the force option has been set.
45
- if self.force? || self.theme_asset_changed?(theme_asset, file)
46
- response = self.put :theme_assets, theme_asset._id, params
47
-
48
- status = self.response_to_status(response)
44
+ begin
45
+ if theme_asset.persisted?
46
+ # we only update it if the size has changed or if the force option has been set.
47
+ if self.force? || self.theme_asset_changed?(theme_asset, file)
48
+ response = self.put :theme_assets, theme_asset._id, params
49
+ status = self.response_to_status(response)
50
+ else
51
+ status = :same
52
+ end
53
+ else
54
+ response = self.post :theme_assets, params, nil, true
55
+ status = self.response_to_status(response)
56
+ end
57
+ rescue Exception => e
58
+ if self.force?
59
+ status, errors = :error, e.message
60
+ else
61
+ raise e
49
62
  end
50
- else
51
- response = self.post :theme_assets, params, nil, true
52
-
53
- status = self.response_to_status(response)
54
63
  end
55
64
 
56
65
  # very important. we do not want a huge number of non-closed file descriptor.
57
66
  file.close
58
67
 
59
68
  # track the status
60
- self.output_resource_op_status theme_asset, status
69
+ self.output_resource_op_status theme_asset, status, errors
61
70
  end
62
71
 
63
72
  # make the stuff like they were before
@@ -13,7 +13,7 @@ module Locomotive
13
13
  super
14
14
 
15
15
  # set the unique identifier to each local translation
16
- self.get(:translations, nil, true).each do |attributes|
16
+ (self.get(:translations, nil, true) || []).each do |attributes|
17
17
  translation = self.translations[attributes['key']]
18
18
 
19
19
  translation._id = attributes['id'] if translation
@@ -11,6 +11,10 @@ module Locomotive
11
11
  @@instance ||= Runner.new(:api)
12
12
  end
13
13
 
14
+ def self.teardown
15
+ @@instance = nil
16
+ end
17
+
14
18
  class Runner < Locomotive::Mounter::Writer::Runner
15
19
 
16
20
  attr_accessor :uri
@@ -11,8 +11,8 @@ module Locomotive
11
11
 
12
12
  def write
13
13
  self.open_file('config/translations.yml') do |file|
14
- file.write self.mounting_point.translations.inject({}) do |memo,translation|
15
- memo.merge!(translation.key => translation.values)
14
+ file.write self.mounting_point.translations.each_with_object({}) do |hash,translation|
15
+ hash[translation.key] = translation.values
16
16
  end.to_yaml
17
17
  end
18
18
  end
@@ -48,19 +48,29 @@ module Locomotive
48
48
  "#{name}_writer".camelize
49
49
  end.try(:insert, 0, 'SiteWriter')
50
50
 
51
- begin
52
- self.writers.each do |klass|
53
- next if only && !only.include?(klass.name.demodulize)
54
- writer = klass.new(self.mounting_point, self)
55
- writer.prepare
51
+ self.writers.each do |klass|
52
+ next if only && !only.include?(klass.name.demodulize)
53
+ writer = klass.new(self.mounting_point, self)
54
+ writer.prepare
55
+ begin
56
56
  writer.write
57
+ rescue Exception => e
58
+ Locomotive::Mounter.logger.error e.backtrace
59
+ puts "\n\nBlocking Error: #{e.message.colorize(:red)}"
57
60
  end
58
- rescue Exception => e
59
- Locomotive::Mounter.logger.error e.backtrace
60
- puts "\n\nBlocking Error: #{e.message.colorize(:red)}"
61
61
  end
62
62
  end
63
63
 
64
+ # By setting the force option to true, some resources (site, content assets, ...etc)
65
+ # may overide the content of the remote engine during the push operation.
66
+ # By default, its value is false.
67
+ #
68
+ # @return [ Boolean ] True if the force option has been set to true
69
+ #
70
+ def force?
71
+ self.parameters[:force] || false
72
+ end
73
+
64
74
  end
65
75
 
66
76
  end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: locomotivecms_mounter
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.alpha4
5
- prerelease: 6
4
+ version: 1.0.1
5
+ prerelease:
6
6
  platform: ruby
7
7
  authors:
8
8
  - Didier Lafforgue
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-02-01 00:00:00.000000000 Z
12
+ date: 2013-04-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: tilt
@@ -379,6 +379,38 @@ dependencies:
379
379
  - - ~>
380
380
  - !ruby/object:Gem::Version
381
381
  version: 0.0.1
382
+ - !ruby/object:Gem::Dependency
383
+ name: vcr
384
+ requirement: !ruby/object:Gem::Requirement
385
+ none: false
386
+ requirements:
387
+ - - '='
388
+ - !ruby/object:Gem::Version
389
+ version: 2.4.0
390
+ type: :development
391
+ prerelease: false
392
+ version_requirements: !ruby/object:Gem::Requirement
393
+ none: false
394
+ requirements:
395
+ - - '='
396
+ - !ruby/object:Gem::Version
397
+ version: 2.4.0
398
+ - !ruby/object:Gem::Dependency
399
+ name: webmock
400
+ requirement: !ruby/object:Gem::Requirement
401
+ none: false
402
+ requirements:
403
+ - - '='
404
+ - !ruby/object:Gem::Version
405
+ version: 1.9.3
406
+ type: :development
407
+ prerelease: false
408
+ version_requirements: !ruby/object:Gem::Requirement
409
+ none: false
410
+ requirements:
411
+ - - '='
412
+ - !ruby/object:Gem::Version
413
+ version: 1.9.3
382
414
  description: Mount any LocomotiveCMS site, from a template on the filesystem, a zip
383
415
  file or even an online engine
384
416
  email:
@@ -471,7 +503,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
471
503
  version: '0'
472
504
  segments:
473
505
  - 0
474
- hash: -4090664391938544491
506
+ hash: -3971524882032378901
475
507
  required_rubygems_version: !ruby/object:Gem::Requirement
476
508
  none: false
477
509
  requirements: