locomotivecms_mounter 1.0.0.alpha4 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
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: