locomotivecms_steam 1.0.0.rc6 → 1.0.0.rc8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +21 -19
  3. data/lib/locomotive/steam/adapters/filesystem/sanitizers/content_entry.rb +1 -1
  4. data/lib/locomotive/steam/adapters/filesystem/yaml_loaders/content_type.rb +3 -2
  5. data/lib/locomotive/steam/adapters/filesystem/yaml_loaders/page.rb +12 -4
  6. data/lib/locomotive/steam/adapters/memory/condition.rb +2 -2
  7. data/lib/locomotive/steam/adapters/memory/order.rb +5 -0
  8. data/lib/locomotive/steam/entities/content_entry.rb +1 -1
  9. data/lib/locomotive/steam/entities/editable_element.rb +1 -4
  10. data/lib/locomotive/steam/liquid/drops/page.rb +36 -16
  11. data/lib/locomotive/steam/liquid/tags/editable/base.rb +25 -1
  12. data/lib/locomotive/steam/liquid/tags/editable/model.rb +4 -0
  13. data/lib/locomotive/steam/liquid/tags/editable/text.rb +5 -1
  14. data/lib/locomotive/steam/liquid/tags/extends.rb +11 -0
  15. data/lib/locomotive/steam/liquid/tags/with_scope.rb +11 -9
  16. data/lib/locomotive/steam/liquid/template.rb +33 -0
  17. data/lib/locomotive/steam/middlewares/templatized_page.rb +11 -6
  18. data/lib/locomotive/steam/models/mapper.rb +4 -0
  19. data/lib/locomotive/steam/models/repository.rb +1 -0
  20. data/lib/locomotive/steam/repositories/content_entry_repository.rb +37 -29
  21. data/lib/locomotive/steam/repositories/content_type_field_repository.rb +4 -0
  22. data/lib/locomotive/steam/repositories/page_repository.rb +2 -2
  23. data/lib/locomotive/steam/services/liquid_parser_service.rb +6 -5
  24. data/lib/locomotive/steam/version.rb +1 -1
  25. data/locomotivecms_steam.gemspec +1 -0
  26. data/spec/integration/liquid/drops/page_spec.rb +43 -0
  27. data/spec/support/liquid.rb +1 -1
  28. data/spec/unit/adapters/filesystem/yaml_loaders/content_type_spec.rb +21 -0
  29. data/spec/unit/adapters/memory/condition_spec.rb +9 -1
  30. data/spec/unit/adapters/memory/order_spec.rb +9 -0
  31. data/spec/unit/entities/content_entry_spec.rb +3 -3
  32. data/spec/unit/liquid/drops/page_spec.rb +1 -1
  33. data/spec/unit/liquid/tags/editable/text_spec.rb +23 -4
  34. data/spec/unit/liquid/tags/extends_spec.rb +19 -1
  35. data/spec/unit/liquid/tags/inherited_block_spec.rb +1 -1
  36. data/spec/unit/liquid/tags/with_scope_spec.rb +21 -0
  37. data/spec/unit/repositories/content_entry_repository_spec.rb +74 -4
  38. data/spec/unit/repositories/page_repository_spec.rb +6 -0
  39. metadata +19 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 73dc9ea0190083dd20c33f5e820da421b36d11b4
4
- data.tar.gz: 5e74931081e00c151d857c449f0c14c3219e0f67
3
+ metadata.gz: 193721014cf846cba6f95200c9d8f4d9d40e82fb
4
+ data.tar.gz: 1a0121ad4705b29db57e30535fb15c7725904805
5
5
  SHA512:
6
- metadata.gz: b4e2759d7ab8798c17f8a4a40b0779228410c8b0f0fb96b4aad83dd7589a2059e1baae8dae58be3f448ccd07ca2933e1ddd2a8a1e918924f3fb44a730825a4f9
7
- data.tar.gz: 7b443e9021b581bd62cee286dd74bb02ee966086064313866f1379055069d23a30f5b198de07aa9da308772eb89003f0e5ae6f6eef07b317c4e2bcbed6d728c8
6
+ metadata.gz: e3930c146bea95ec4aa7c60802020e0ea2d6e485693bbd417b25cb6d80dc21fa0ec54c64e59974de0f0529a089e6d1da7ccb2ba96f6cef869c4e33c856753b53
7
+ data.tar.gz: 0b4f8ff10324d481564b9807fb02c2b6188b25d25049ec4eb592315398dd00184aea9003c01181a4b625804a9b3f6a50c1bd4a3458f4a43a9cb327596d67038f
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- locomotivecms_steam (1.0.0.rc6)
4
+ locomotivecms_steam (1.0.0.rc8)
5
5
  RedCloth (~> 4.2.9)
6
6
  chronic (~> 0.10.2)
7
7
  coffee-script (~> 2.4.1)
@@ -17,6 +17,7 @@ PATH
17
17
  moneta (~> 0.8.0)
18
18
  mongo (~> 2.1.2)
19
19
  morphine (~> 0.1.1)
20
+ nokogiri (~> 1.6.6.4)
20
21
  origin (~> 2.1.1)
21
22
  rack-cache (~> 1.2)
22
23
  rack-rewrite (~> 1.5.1)
@@ -43,7 +44,7 @@ GEM
43
44
  columnize (= 0.9.0)
44
45
  chronic (0.10.2)
45
46
  chunky_png (1.3.5)
46
- codeclimate-test-reporter (0.4.7)
47
+ codeclimate-test-reporter (0.4.8)
47
48
  simplecov (>= 0.7.1, < 1.0.0)
48
49
  coderay (1.1.0)
49
50
  coffee-script (2.4.1)
@@ -65,16 +66,17 @@ GEM
65
66
  sass (>= 3.3.0, < 3.5)
66
67
  compass-import-once (1.0.5)
67
68
  sass (>= 3.2, < 3.5)
68
- coveralls (0.8.1)
69
+ coveralls (0.8.10)
69
70
  json (~> 1.8)
70
71
  rest-client (>= 1.6.8, < 2)
71
- simplecov (~> 0.10.0)
72
+ simplecov (~> 0.11.0)
72
73
  term-ansicolor (~> 1.3)
73
74
  thor (~> 0.19.1)
75
+ tins (~> 1.6.0)
74
76
  crass (1.0.2)
75
77
  diff-lcs (1.2.5)
76
78
  docile (1.1.5)
77
- domain_name (0.5.24)
79
+ domain_name (0.5.25)
78
80
  unf (>= 0.0.5, < 1.0.0)
79
81
  dragonfly (1.0.12)
80
82
  addressable (~> 2.3)
@@ -115,9 +117,9 @@ GEM
115
117
  attr_extras (~> 4.4.0)
116
118
  colorize
117
119
  stringex (~> 2.5.2)
118
- memory_profiler (0.9.4)
120
+ memory_profiler (0.9.6)
119
121
  method_source (0.8.2)
120
- mime-types (2.6.1)
122
+ mime-types (2.6.2)
121
123
  mimetype-fu (0.1.2)
122
124
  mini_portile (0.6.2)
123
125
  minitest (5.8.3)
@@ -125,26 +127,26 @@ GEM
125
127
  mongo (2.1.2)
126
128
  bson (~> 3.0)
127
129
  morphine (0.1.1)
128
- multi_json (1.11.1)
130
+ multi_json (1.11.2)
129
131
  multi_xml (0.5.5)
130
- netrc (0.10.3)
132
+ netrc (0.11.0)
131
133
  nokogiri (1.6.6.4)
132
134
  mini_portile (~> 0.6.0)
133
135
  nokogumbo (1.4.1)
134
136
  nokogiri
135
137
  origin (2.1.1)
136
- pry (0.10.1)
138
+ pry (0.10.3)
137
139
  coderay (~> 1.1.0)
138
140
  method_source (~> 0.8.1)
139
141
  slop (~> 3.4)
140
142
  pry-byebug (3.1.0)
141
143
  byebug (~> 4.0)
142
144
  pry (~> 0.10)
143
- puma (2.12.3)
144
- rack (1.6.1)
145
+ puma (2.15.3)
146
+ rack (1.6.4)
145
147
  rack-cache (1.5.1)
146
148
  rack (>= 0.4)
147
- rack-mini-profiler (0.9.7)
149
+ rack-mini-profiler (0.9.8)
148
150
  rack (>= 1.1.3)
149
151
  rack-rewrite (1.5.1)
150
152
  rack-test (0.6.3)
@@ -165,12 +167,12 @@ GEM
165
167
  rspec-core (~> 3.3.0)
166
168
  rspec-expectations (~> 3.3.0)
167
169
  rspec-mocks (~> 3.3.0)
168
- rspec-core (3.3.0)
170
+ rspec-core (3.3.2)
169
171
  rspec-support (~> 3.3.0)
170
- rspec-expectations (3.3.0)
172
+ rspec-expectations (3.3.1)
171
173
  diff-lcs (>= 1.2.0, < 2.0)
172
174
  rspec-support (~> 3.3.0)
173
- rspec-mocks (3.3.0)
175
+ rspec-mocks (3.3.2)
174
176
  diff-lcs (>= 1.2.0, < 2.0)
175
177
  rspec-support (~> 3.3.0)
176
178
  rspec-support (3.3.0)
@@ -179,7 +181,7 @@ GEM
179
181
  nokogiri (>= 1.4.4)
180
182
  nokogumbo (= 1.4.1)
181
183
  sass (3.4.19)
182
- simplecov (0.10.0)
184
+ simplecov (0.11.1)
183
185
  docile (~> 1.1.0)
184
186
  json (~> 1.8)
185
187
  simplecov-html (~> 0.10.0)
@@ -198,13 +200,13 @@ GEM
198
200
  tilt (~> 1.1)
199
201
  stackprof (0.2.7)
200
202
  stringex (2.5.2)
201
- term-ansicolor (1.3.0)
203
+ term-ansicolor (1.3.2)
202
204
  tins (~> 1.0)
203
205
  thor (0.19.1)
204
206
  thread_safe (0.3.5)
205
207
  tilt (1.4.1)
206
208
  timecop (0.7.4)
207
- tins (1.5.2)
209
+ tins (1.6.0)
208
210
  tzinfo (1.2.2)
209
211
  thread_safe (~> 0.1)
210
212
  unf (0.1.4)
@@ -57,7 +57,7 @@ module Locomotive::Steam
57
57
  entity._label.each do |locale, label|
58
58
  entity[:_slug][locale] ||= slugify(entity._id, label, dataset, locale)
59
59
  end
60
- else
60
+ elsif entity[:_slug] && entity[:_slug][:anylocale].nil?
61
61
  # Note: replace the translations of the I18nField by a string
62
62
  entity[:_slug].translations = slugify(entity._id, entity._label, dataset)
63
63
  end
@@ -66,7 +66,7 @@ module Locomotive
66
66
  if (option = list.at(position)).nil?
67
67
  list << { _id: name, name: { locale => name }, position: position }
68
68
  else
69
- option[name][locale] = name
69
+ option[:name][locale] = name
70
70
  end
71
71
  end
72
72
  end
@@ -76,7 +76,8 @@ module Locomotive
76
76
  def build_select_options_from_array(options)
77
77
  [].tap do |list|
78
78
  options.each_with_index do |name, position|
79
- list << { _id: name, name: name, position: position }
79
+ _id = name.is_a?(Hash) ? name.values.first : name
80
+ list << { _id: _id, name: name, position: position }
80
81
  end
81
82
  end
82
83
  end
@@ -42,14 +42,19 @@ module Locomotive
42
42
  slug = fullpath.split('/').last
43
43
  attributes = get_attributes(filepath, fullpath)
44
44
 
45
- {
45
+ _attributes = {
46
46
  title: { locale => attributes.delete(:title) || (default_locale == locale ? slug.humanize : nil) },
47
47
  slug: { locale => attributes.delete(:slug) || slug.dasherize },
48
48
  template_path: { locale => template_path(filepath, attributes, locale) },
49
- redirect_url: { locale => attributes.delete(:redirect_url) },
50
49
  editable_elements: build_editable_elements(attributes.delete(:editable_elements), locale),
51
50
  _fullpath: fullpath
52
- }.merge(attributes)
51
+ }
52
+
53
+ [:redirect_url, :seo_title, :meta_description, :meta_keywords].each do |name|
54
+ _attributes[name] = { locale => attributes.delete(name) }
55
+ end
56
+
57
+ _attributes.merge!(attributes)
53
58
  end
54
59
 
55
60
  def update(leaf, filepath, fullpath, locale)
@@ -59,7 +64,10 @@ module Locomotive
59
64
  leaf[:title][locale] = attributes.delete(:title) || slug.humanize
60
65
  leaf[:slug][locale] = attributes.delete(:slug) || slug.dasherize
61
66
  leaf[:template_path][locale] = template_path(filepath, attributes, locale)
62
- leaf[:redirect_url][locale] = attributes.delete(:redirect_url)
67
+
68
+ [:redirect_url, :seo_title, :meta_description, :meta_keywords].each do |name|
69
+ leaf[name][locale] = attributes.delete(name)
70
+ end
63
71
 
64
72
  update_editable_elements(leaf, attributes.delete(:editable_elements), locale)
65
73
 
@@ -41,7 +41,7 @@ module Locomotive::Steam
41
41
  end
42
42
 
43
43
  def inspect
44
- "#{field}.#{operator} #{value}"
44
+ "#{field}#{operator != :== ? '.' : ' '}#{operator} #{value}"
45
45
  end
46
46
 
47
47
  protected
@@ -92,7 +92,7 @@ module Locomotive::Steam
92
92
  if target.size == 0
93
93
  source.size == 0
94
94
  else
95
- source & target == target
95
+ (source & target).size != 0
96
96
  end
97
97
  end
98
98
 
@@ -25,6 +25,11 @@ module Locomotive::Steam
25
25
  def apply_to(entry, locale)
26
26
  @list.collect do |(name, direction)|
27
27
  value = entry.send(name)
28
+
29
+ if value.respond_to?(:translations) # localized
30
+ value = value[locale]
31
+ end
32
+
28
33
  asc?(direction) ? Asc.new(value) : Desc.new(value)
29
34
  end
30
35
  end
@@ -139,7 +139,7 @@ module Locomotive::Steam
139
139
  end
140
140
 
141
141
  def _cast_date_time(field)
142
- _cast_time(field, :to_date)
142
+ _cast_time(field, :to_datetime)
143
143
  end
144
144
 
145
145
  def _cast_time(field, end_method)
@@ -8,6 +8,7 @@ module Locomotive::Steam
8
8
 
9
9
  def initialize(attributes = {})
10
10
  super({
11
+ label: nil,
11
12
  block: nil,
12
13
  content: nil,
13
14
  source: nil,
@@ -23,10 +24,6 @@ module Locomotive::Steam
23
24
  self[:format] || 'html' # only editable_text elements
24
25
  end
25
26
 
26
- def default_content?
27
- self.content.blank?
28
- end
29
-
30
27
  end
31
28
 
32
29
  end
@@ -62,32 +62,52 @@ module Locomotive
62
62
  end
63
63
 
64
64
  def build_editable_elements_hash
65
- {}.tap do |hash|
66
- repository.editable_elements_of(@_source).each do |el|
67
- safe_slug = el.slug.parameterize.underscore
68
- keys = el.block.try(:split, '/').try(:compact) || []
65
+ {}.tap do |hash|
66
+ # default content from the template itself
67
+ _build_default_editable_elements_hash(hash)
69
68
 
70
- _hash = _build_editable_elements_hashes(hash, keys)
69
+ # content updated by the users
70
+ _build_editable_elements_hash(hash)
71
+ end
72
+ end
71
73
 
72
- _hash[safe_slug] = el.content
73
- end
74
- end
74
+ def _build_default_editable_elements_hash(hash)
75
+ (@context.registers[:default_editable_content] || []).each do |key, content|
76
+ keys = key.split('/')
77
+ _build_editable_elements_hashes(hash, keys, keys.pop, content)
75
78
  end
79
+ end
76
80
 
77
- def _build_editable_elements_hashes(hash, keys)
78
- _hash = hash
81
+ def _build_editable_elements_hash(hash)
82
+ (repository.editable_elements_of(@_source) || []).each do |el|
83
+ keys = el.block.try(:split, '/').try(:compact) || []
79
84
 
80
- keys.each do |key|
81
- safe_key = key.parameterize.underscore
85
+ # decorate the el instance which is localized because
86
+ # el.content returns a I18nField.
87
+ content = editable_element_content(el)
82
88
 
83
- _hash[safe_key] = {} if _hash[safe_key].nil?
89
+ _build_editable_elements_hashes(hash, keys, el.slug, content)
90
+ end
91
+ end
84
92
 
85
- _hash = _hash[safe_key]
86
- end
93
+ def editable_element_content(element)
94
+ Locomotive::Steam::Decorators::I18nDecorator.new(element,
95
+ @_source.__locale__,
96
+ @_source.__default_locale__).content
97
+ end
98
+
99
+ def _build_editable_elements_hashes(hash, keys, slug, content)
100
+ last_hash = hash
87
101
 
88
- _hash
102
+ # go the last hash
103
+ keys.each do |key|
104
+ safe_key = key.parameterize.underscore
105
+ last_hash = (last_hash[safe_key] ||= {})
89
106
  end
90
107
 
108
+ last_hash[slug.parameterize.underscore] = content
109
+ end
110
+
91
111
  end
92
112
  end
93
113
  end
@@ -12,9 +12,11 @@ module Locomotive
12
12
  def initialize(tag_name, markup, options)
13
13
  if markup =~ Syntax
14
14
  @page_fullpath = options[:page].fullpath
15
- @slug = $1.gsub(/[\"\']/, '')
15
+ @label_or_slug = $1.gsub(/[\"\']/, '')
16
16
  @element_options = { fixed: false, inline_editing: true }
17
17
  markup.scan(::Liquid::TagAttributes) { |key, value| @element_options[key.to_sym] = value.gsub(/^[\"\']/, '').gsub(/[\"\']$/, '') }
18
+
19
+ self.set_label_and_slug
18
20
  else
19
21
  raise ::Liquid::SyntaxError.new("Valid syntax: #{tag_name} <slug>(, <options>)")
20
22
  end
@@ -25,6 +27,8 @@ module Locomotive
25
27
  def parse(tokens)
26
28
  super.tap do
27
29
  ActiveSupport::Notifications.instrument("steam.parse.editable.#{@tag_name}", page: options[:page], attributes: default_element_attributes)
30
+
31
+ register_default_content
28
32
  end
29
33
  end
30
34
 
@@ -56,9 +60,29 @@ module Locomotive
56
60
  pages[@page_fullpath] ||= service.find(@page_fullpath)
57
61
  end
58
62
 
63
+ def register_default_content
64
+ return if options[:default_editable_content].nil?
65
+
66
+ hash = options[:default_editable_content]
67
+ key = [current_inherited_block_name, @slug].compact.join('/')
68
+
69
+ hash[key] = render_default_content
70
+ end
71
+
72
+ def set_label_and_slug
73
+ @slug = @label_or_slug
74
+ @label = @element_options[:label]
75
+
76
+ if @element_options[:slug].present?
77
+ @slug = @element_options[:slug]
78
+ @label ||= @label_or_slug
79
+ end
80
+ end
81
+
59
82
  def default_element_attributes
60
83
  {
61
84
  block: self.current_inherited_block_name,
85
+ label: @label,
62
86
  slug: @slug,
63
87
  hint: @element_options[:hint],
64
88
  priority: @element_options[:priority] || 0,
@@ -9,6 +9,10 @@ module Locomotive
9
9
  default_render(context)
10
10
  end
11
11
 
12
+ def render_default_content
13
+ nil
14
+ end
15
+
12
16
  end
13
17
 
14
18
  ::Liquid::Template.register_tag('editable_model'.freeze, Model)
@@ -9,7 +9,7 @@ module Locomotive
9
9
 
10
10
  def render_element(context, element)
11
11
  with_inline_editing(context, element) do
12
- content = if element.default_content?
12
+ content = if default_content?(element)
13
13
  render_default_content
14
14
  else
15
15
  element.content
@@ -39,6 +39,10 @@ module Locomotive
39
39
  !!context.registers[:live_editing] && element.inline_editing
40
40
  end
41
41
 
42
+ def default_content?(element)
43
+ element.content.blank?
44
+ end
45
+
42
46
  def default_element_attributes
43
47
  super.merge(
44
48
  content_from_default: self.render_default_content,
@@ -4,6 +4,13 @@ module Locomotive
4
4
  module Tags
5
5
  class Extends < ::Liquid::Extends
6
6
 
7
+ def render(context)
8
+ context.stack do
9
+ context['layout_name'] = @layout_name
10
+ super
11
+ end
12
+ end
13
+
7
14
  private
8
15
 
9
16
  def parse_parent_template
@@ -14,6 +21,10 @@ module Locomotive
14
21
 
15
22
  ActiveSupport::Notifications.instrument('steam.parse.extends', page: options[:page], parent: parent)
16
23
 
24
+ # define the layout name which is basically the handle of the parent page
25
+ # if there is no handle, we take the slug which might or might not be localized.
26
+ @layout_name = parent.handle || parent.slug
27
+
17
28
  # the source has already been parsed before
18
29
  options[:parser]._parse(parent, options.merge(page: parent))
19
30
  end
@@ -45,18 +45,20 @@ module Locomotive
45
45
  # _slug instead of _permalink
46
46
  _key = key.to_s == '_permalink' ? '_slug' : key.to_s
47
47
 
48
- hash[_key] = (case value
49
- # regexp inside a string
50
- when /^\/[^\/]*\/$/ then Regexp.new(value[1..-2])
51
- # content entry drop? Use the source (entity) instead
52
- when Locomotive::Steam::Liquid::Drops::ContentEntry
53
- value.send(:_source)
54
- else
55
- value
56
- end)
48
+ hash[_key] = cast_value(value)
57
49
  end
58
50
  end
59
51
  end
52
+
53
+ def cast_value(value)
54
+ case value
55
+ when Array then value.map { |_value| cast_value(_value) }
56
+ when /^\/[^\/]*\/$/ then Regexp.new(value[1..-2])
57
+ else
58
+ value.respond_to?(:_id) ? value.send(:_source) : value
59
+ end
60
+ end
61
+
60
62
  end
61
63
 
62
64
  end
@@ -0,0 +1,33 @@
1
+ module Locomotive
2
+ module Steam
3
+ module Liquid
4
+
5
+ class Template < ::Liquid::Template
6
+
7
+ # When we render a Locomotive template, we need to know what are
8
+ # the default content of all the editable elements.
9
+ # Without this, developers are unable to use statements like
10
+ # the following: {{ page.editable_elements.content.header.title }}
11
+ def render(*args)
12
+ if args.first && args.first.is_a?(::Liquid::Context)
13
+ content = @options[:default_editable_content]
14
+ args.first.registers[:default_editable_content] = content
15
+ end
16
+
17
+ super
18
+ end
19
+
20
+ class << self
21
+
22
+ def parse(source, options = {})
23
+ template = new
24
+ template.parse(source, options)
25
+ end
26
+
27
+ end
28
+
29
+ end
30
+
31
+ end
32
+ end
33
+ end
@@ -28,7 +28,8 @@ module Locomotive::Steam
28
28
  # log it
29
29
  log "Found content entry: #{entry._label}"
30
30
  else
31
- redirect_to '/404', 302
31
+ url = services.url_builder.url_for(page_not_found, locale)
32
+ redirect_to url, 302
32
33
  end
33
34
  end
34
35
 
@@ -40,11 +41,6 @@ module Locomotive::Steam
40
41
  end
41
42
  end
42
43
 
43
- def decorate(entry)
44
- return nil if entry.nil?
45
- Locomotive::Steam::Decorators::I18nDecorator.new(entry, locale, default_locale)
46
- end
47
-
48
44
  def content_type_repository
49
45
  services.repositories.content_type
50
46
  end
@@ -53,6 +49,15 @@ module Locomotive::Steam
53
49
  services.repositories.content_entry
54
50
  end
55
51
 
52
+ def page_not_found
53
+ services.page_finder.find('404')
54
+ end
55
+
56
+ def decorate(entry)
57
+ return nil if entry.nil?
58
+ Locomotive::Steam::Decorators::I18nDecorator.new(entry, locale, default_locale)
59
+ end
60
+
56
61
  end
57
62
  end
58
63
  end
@@ -95,6 +95,10 @@ module Locomotive::Steam
95
95
  value.respond_to?(:translations) ? value[locale] : value
96
96
  end
97
97
 
98
+ def reset_entity_map
99
+ @entity_map = {}
100
+ end
101
+
98
102
  private
99
103
 
100
104
  # create a proxy class for each localized attribute
@@ -11,6 +11,7 @@ module Locomotive::Steam
11
11
  attr_accessor :adapter, :scope, :local_conditions
12
12
 
13
13
  def_delegators :@scope, :site, :site=, :locale, :locale=
14
+ def_delegators :all, :each
14
15
 
15
16
  def initialize(adapter, site = nil, locale = nil)
16
17
  @adapter = adapter
@@ -130,33 +130,11 @@ module Locomotive
130
130
  end
131
131
 
132
132
  def prepare_conditions(*conditions)
133
- # _conditions = conditions.first.try(:with_indifferent_access)
134
-
135
133
  _conditions = Conditions.new(conditions.first, self.content_type.fields).prepare
136
134
 
137
135
  super({ _visible: true }, _conditions)
138
136
  end
139
137
 
140
- # # belongs_to fields? if so, make sure we use the _id and we deal with the ID, not the object itself
141
- # def prepare_conditions_for_belongs_to_fields(conditions)
142
- # self.content_type.fields.belongs_to.each do |field|
143
- # if value = conditions[name = field.name.to_s]
144
- # conditions.delete(name)
145
- # conditions[name + '_id'] = value.try(:_id)
146
- # end
147
- # end
148
- # end
149
-
150
- # # select fields? if so, use the _id of the option instead of the option name
151
- # def prepare_conditions_for_select_fields(conditions)
152
- # self.content_type.fields.selects.each do |field|
153
- # if value = conditions[name = field.name.to_s]
154
- # conditions.delete(name)
155
- # conditions[name + '_id'] = field.select_options.by_name(value).try(:_id)
156
- # end
157
- # end
158
- # end
159
-
160
138
  def add_localized_fields_to_mapper(mapper)
161
139
  unless self.content_type.localized_names.blank?
162
140
  mapper.localized_attributes(*self.content_type.localized_names)
@@ -207,17 +185,25 @@ module Locomotive
207
185
  class Conditions
208
186
 
209
187
  def initialize(conditions = {}, fields)
210
- @conditions, @fields = conditions.try(:with_indifferent_access) || {}, fields
188
+ @conditions, @fields, @operators = conditions.try(:with_indifferent_access) || {}, fields, {}
189
+
190
+ @conditions.each do |name, value|
191
+ _name, operator = name.to_s.split('.')
192
+ @operators[_name] = operator if operator
193
+ end
211
194
  end
212
195
 
213
196
  def prepare
214
- return {} if @conditions.blank?
215
-
197
+ # selects
216
198
  _prepare(@fields.selects) do |field, value|
217
199
  field.select_options.by_name(value).try(:_id)
218
200
  end
219
201
 
220
- _prepare(@fields.belongs_to) { |field, value| value.try(:_id) }
202
+ # belongs_to
203
+ _prepare(@fields.belongs_to) { |field, value| value_to_id(value) }
204
+
205
+ # many_to_many
206
+ _prepare(@fields.many_to_many) { |field, value| values_to_ids(value) }
221
207
 
222
208
  @conditions
223
209
  end
@@ -226,13 +212,35 @@ module Locomotive
226
212
 
227
213
  def _prepare(fields, &block)
228
214
  fields.each do |field|
229
- if value = @conditions[name = field.name.to_s]
230
- @conditions.delete(name)
231
- @conditions[name + '_id'] = yield(field, value)
215
+ name = field.name.to_s
216
+ operator = @operators[name]
217
+ _name = operator ? "#{name}.#{operator}" : name
218
+
219
+ if value = @conditions[_name]
220
+ # delete old name
221
+ @conditions.delete(_name)
222
+
223
+ # build the new name with the prefix and the operator if there is one
224
+ _name = field.persisted_name + (operator ? ".#{operator}" : '')
225
+
226
+ # store the new name
227
+ @conditions[_name] = yield(field, value)
232
228
  end
233
229
  end
234
230
  end
235
231
 
232
+ def value_to_id(value)
233
+ if value.respond_to?(:each) # array
234
+ values_to_ids(value)
235
+ else
236
+ value.respond_to?(:_id) ? value._id : value
237
+ end
238
+ end
239
+
240
+ def values_to_ids(value)
241
+ [*value].map { |_value| value_to_id(_value) }
242
+ end
243
+
236
244
  end
237
245
 
238
246
  end
@@ -26,6 +26,10 @@ module Locomotive
26
26
  query { where(type: :belongs_to) }.all
27
27
  end
28
28
 
29
+ def many_to_many
30
+ query { where(type: :many_to_many) }.all
31
+ end
32
+
29
33
  def associations
30
34
  query { where(k(:type, :in) => %i(belongs_to has_many many_to_many)) }.all
31
35
  end
@@ -30,7 +30,7 @@ module Locomotive
30
30
  query do
31
31
  where(k(:handle, :ne) => nil).
32
32
  only(:_id, :title, :handle, :fullpath)
33
- end.all
33
+ end.all.tap { mapper.reset_entity_map }
34
34
  end
35
35
 
36
36
  def by_handle(handle)
@@ -81,7 +81,7 @@ module Locomotive
81
81
  end
82
82
 
83
83
  def editable_element_for(page, block, slug)
84
- return nil if page.nil?
84
+ return nil if page.nil? || page.editable_elements.nil?
85
85
  page.editable_elements.first do
86
86
  where(block: block, slug: slug)
87
87
  end
@@ -7,15 +7,16 @@ module Locomotive
7
7
 
8
8
  def parse(page)
9
9
  _parse(page,
10
- page: page,
11
- parent_finder: parent_finder,
12
- snippet_finder: snippet_finder,
13
- parser: self)
10
+ page: page,
11
+ parent_finder: parent_finder,
12
+ snippet_finder: snippet_finder,
13
+ parser: self,
14
+ default_editable_content: {})
14
15
  end
15
16
 
16
17
  def _parse(object, options = {})
17
18
  # Note: the template must not be parsed here
18
- ::Liquid::Template.parse(object.liquid_source, options)
19
+ Locomotive::Steam::Liquid::Template.parse(object.liquid_source, options)
19
20
  end
20
21
 
21
22
  end
@@ -3,6 +3,6 @@
3
3
  # 1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-alpha.beta < 1.0.0-beta < 1.0.0-beta.2 < 1.0.0-beta.11 < 1.0.0-rc.1 < 1.0.0
4
4
  module Locomotive
5
5
  module Steam
6
- VERSION = '1.0.0.rc6'
6
+ VERSION = '1.0.0.rc8'
7
7
  end
8
8
  end
@@ -21,6 +21,7 @@ Gem::Specification.new do |spec|
21
21
  spec.add_dependency 'mongo', '~> 2.1.2'
22
22
  spec.add_dependency 'origin', '~> 2.1.1'
23
23
 
24
+ spec.add_dependency 'nokogiri', '~> 1.6.6.4'
24
25
  spec.add_dependency 'sanitize', '~> 4.0.0'
25
26
  spec.add_dependency 'morphine', '~> 0.1.1'
26
27
  spec.add_dependency 'httparty', '~> 0.13.6'
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+
3
+ describe Locomotive::Steam::Liquid::Drops::Page do
4
+
5
+ describe '#editable_elements' do
6
+
7
+ let(:source) { <<-EOF
8
+ <h1>{{ page.editable_elements.content.header.title }}</h1>
9
+ {% block content %}
10
+ {% block header %}
11
+ {% editable_text title %}Hello world{% endeditable_text %}
12
+ {% endblock %}
13
+ {% endblock %}
14
+ EOF
15
+ }
16
+
17
+ let(:elements) { nil }
18
+ let(:page) { instance_double('Page', localized_attributes: [], fullpath: 'index', editable_elements: elements) }
19
+ let(:drop) { described_class.new(page) }
20
+ let(:services) { Locomotive::Steam::Services.build_instance }
21
+ let(:context) { ::Liquid::Context.new({ 'page' => drop }, {}, { page: page, services: services }, true) }
22
+
23
+ subject { render_template(source, context, { page: page, default_editable_content: {} }) }
24
+
25
+ it { is_expected.to match /<h1>Hello world<\/h1>/ }
26
+
27
+ context 'content updated by an user' do
28
+
29
+ let(:elements) { [instance_double('EditableText', block: 'content/header', slug: 'title', content: 'Bonjour le monde', :base_url= => nil, localized_attributes: [], format: 'raw')] }
30
+
31
+ before do
32
+ services.locale = :en
33
+ services.repositories.current_site = instance_double('Site', default_locale: :en)
34
+ allow(services.repositories.page).to receive(:editable_elements_of).and_return(elements)
35
+ end
36
+
37
+ it { is_expected.to match /<h1>Bonjour le monde<\/h1>/ }
38
+
39
+ end
40
+
41
+ end
42
+
43
+ end
@@ -1,7 +1,7 @@
1
1
  def render_template(source, context = nil, options = {})
2
2
  context ||= ::Liquid::Context.new
3
3
  context.exception_handler = ->(e) { true }
4
- ::Liquid::Template.parse(source, options).render(context)
4
+ Locomotive::Steam::Liquid::Template.parse(source, options).render(context)
5
5
  end
6
6
 
7
7
  def parse_template(source, options = nil)
@@ -23,4 +23,25 @@ describe Locomotive::Steam::Adapters::Filesystem::YAMLLoaders::ContentType do
23
23
 
24
24
  end
25
25
 
26
+ describe '#build_select_options_from_hash' do
27
+
28
+ let(:options) { { en: ['General', 'Gigs', 'Bands'], fr: ['Général', 'Concerts', 'Groupes'] } }
29
+
30
+ subject { loader.send(:build_select_options_from_hash, options) }
31
+
32
+ it { is_expected.to eq [{ _id: 'General', name: { en: 'General', fr: 'Général' }, position: 0 }, { _id: 'Gigs', name: { en: 'Gigs', fr: 'Concerts' }, position: 1 }, { _id: 'Bands', name: { en: 'Bands', fr: 'Groupes' }, position: 2 }] }
33
+
34
+ end
35
+
36
+ describe '#build_select_options_from_array' do
37
+
38
+ # let(:options) { { en: ['General', 'Gigs', 'Bands'], fr: ['Général', 'Concerts', 'Groupes'] } }
39
+ let(:options) { [{ en: 'General', fr: 'Général' }, { en: 'Gigs', fr: 'Concerts'}, { en: 'Bands', fr: 'Groupes' }] }
40
+
41
+ subject { loader.send(:build_select_options_from_array, options) }
42
+
43
+ it { is_expected.to eq [{ _id: 'General', name: { en: 'General', fr: 'Général' }, position: 0 }, { _id: 'Gigs', name: { en: 'Gigs', fr: 'Concerts' }, position: 1 }, { _id: 'Bands', name: { en: 'Bands', fr: 'Groupes' }, position: 2 }] }
44
+
45
+ end
46
+
26
47
  end
@@ -90,7 +90,15 @@ describe Locomotive::Steam::Adapters::Memory::Condition do
90
90
  describe '#array_contains?' do
91
91
  let(:source) { [1, 2, 3, 4] }
92
92
  let(:target) { [1, 2, 3] }
93
- context 'with target contains in source' do
93
+ context 'target contains the source' do
94
+ specify('should be true') do
95
+ expect(subject.send(:array_contains?, source, target)).to eq true
96
+ end
97
+ end
98
+
99
+ context 'target contains at least one element' do
100
+ let(:source) { [1] }
101
+ let(:target) { [1, 2, 3] }
94
102
  specify('should be true') do
95
103
  expect(subject.send(:array_contains?, source, target)).to eq true
96
104
  end
@@ -44,6 +44,15 @@ describe Locomotive::Steam::Adapters::Memory::Order do
44
44
  let(:entry) { instance_double('Entry', title: 'foo', date: Time.zone.now) }
45
45
  it { expect(subject.map(&:class)).to eq([Locomotive::Steam::Adapters::Memory::Order::Asc, Locomotive::Steam::Adapters::Memory::Order::Desc]) }
46
46
 
47
+ context 'localized field' do
48
+
49
+ let(:now) { Time.zone.now }
50
+ let(:field) { instance_double('TitleI18nField', :[] => 'Hello world', translations: true) }
51
+ let(:entry) { instance_double('Entry', title: field, date: now) }
52
+ it { expect(subject.map(&:obj)).to eq(['Hello world', now]) }
53
+
54
+ end
55
+
47
56
  end
48
57
 
49
58
  describe 'sort' do
@@ -151,11 +151,11 @@ describe Locomotive::Steam::ContentEntry do
151
151
 
152
152
  context 'a date time' do
153
153
  let(:field_type) { :date_time }
154
- let(:value) { '2007/06/29 00:00:00' }
155
- let(:datetime) { DateTime.parse('2007/06/29 00:00:00') }
154
+ let(:value) { '2007/06/29 10:00:00' }
155
+ let(:datetime) { DateTime.parse('2007/06/29 10:00:00') }
156
156
  it { is_expected.to eq datetime }
157
157
  context 'localized' do
158
- let(:value) { build_i18n_field(en: '2007/06/29 00:00:00', fr: datetime) }
158
+ let(:value) { build_i18n_field(en: '2007/06/29 10:00:00', fr: datetime) }
159
159
  it { expect(subject.translations).to eq('en' => datetime, 'fr' => datetime) }
160
160
  end
161
161
  end
@@ -70,7 +70,7 @@ describe Locomotive::Steam::Liquid::Drops::Page do
70
70
 
71
71
  describe '#editable_elements' do
72
72
 
73
- let(:elements) { [instance_double('EditableElement', block: 'top/left', slug: 'banner', content: 'Hello world')] }
73
+ let(:elements) { [instance_double('EditableElement', block: 'top/left', slug: 'banner', content: 'Hello world', localized_attributes: [])] }
74
74
 
75
75
  before do
76
76
  allow(services.repositories.page).to receive(:editable_elements_of).with(page).and_return(elements)
@@ -57,12 +57,31 @@ describe Locomotive::Steam::Liquid::Tags::Editable::Text do
57
57
  it { is_expected.to include(block: nil) }
58
58
  it { is_expected.to include(type: :editable_text) }
59
59
  it { is_expected.to include(slug: 'title') }
60
+ it { is_expected.to include(label: nil) }
60
61
  it { is_expected.to include(hint: 'Simple short text') }
61
62
  it { is_expected.to include(format: 'html') }
62
63
  it { is_expected.to include(rows: 10) }
63
64
  it { is_expected.to include(line_break: true) }
64
65
  it { is_expected.to include(content_from_default: 'Hello world') }
65
66
 
67
+ context 'with a defined slug' do
68
+
69
+ let(:source) { "{% editable_text 'First column', slug: 'column_1' %}{% endeditable_text %}" }
70
+
71
+ it { is_expected.to include(slug: 'column_1') }
72
+ it { is_expected.to include(label: 'First column') }
73
+
74
+ end
75
+
76
+ context 'with a defined label' do
77
+
78
+ let(:source) { "{% editable_text 'first_column', label: 'Column #1' %}{% endeditable_text %}" }
79
+
80
+ it { is_expected.to include(slug: 'first_column') }
81
+ it { is_expected.to include(label: 'Column #1') }
82
+
83
+ end
84
+
66
85
  end
67
86
 
68
87
  end
@@ -75,7 +94,7 @@ describe Locomotive::Steam::Liquid::Tags::Editable::Text do
75
94
  let(:element_editing) { true }
76
95
 
77
96
  let(:child_page) { instance_double('Page', fullpath: 'child-page') }
78
- let(:element) { instance_double('EditableText', _id: 42, id: 42, default_content?: true, inline_editing?: element_editing, inline_editing: element_editing, format: 'html') }
97
+ let(:element) { instance_double('EditableText', _id: 42, id: 42, content: nil, inline_editing?: element_editing, inline_editing: element_editing, format: 'html') }
79
98
  let(:services) { Locomotive::Steam::Services.build_instance(nil) }
80
99
  let(:context) { ::Liquid::Context.new({}, {}, { page: child_page, services: services, live_editing: live_editing }) }
81
100
 
@@ -102,7 +121,7 @@ describe Locomotive::Steam::Liquid::Tags::Editable::Text do
102
121
  let(:layout) { instance_double('Page', fullpath: 'layout') }
103
122
  let(:source) { "{% editable_text title, hint: 'Simple short text', fixed: true %}Hello world{% endeditable_text %}" }
104
123
  let(:options) { { page: layout } }
105
- let(:element) { instance_double('EditableText', _id: 42, id: 42, default_content?: true, inline_editing?: element_editing, inline_editing: element_editing, format: 'html', fixed: true) }
124
+ let(:element) { instance_double('EditableText', _id: 42, id: 42, content: nil, inline_editing?: element_editing, inline_editing: element_editing, format: 'html', fixed: true) }
106
125
 
107
126
  it 'fetches the related page in order to get the element' do
108
127
  expect(services.page_finder).to receive(:find).with('layout').and_return(layout)
@@ -113,7 +132,7 @@ describe Locomotive::Steam::Liquid::Tags::Editable::Text do
113
132
 
114
133
  context 'modified content' do
115
134
 
116
- let(:element) { instance_double('EditableText', content: 'Hello world!', default_content?: false, format: 'html') }
135
+ let(:element) { instance_double('EditableText', content: 'Hello world!', format: 'html') }
117
136
  it { is_expected.to eq 'Hello world!' }
118
137
 
119
138
  end
@@ -129,7 +148,7 @@ describe Locomotive::Steam::Liquid::Tags::Editable::Text do
129
148
 
130
149
  context 'markdown format' do
131
150
 
132
- let(:element) { instance_double('EditableText', content: "#Hello world!\nLorem ipsum", default_content?: false, format: 'markdown') }
151
+ let(:element) { instance_double('EditableText', content: "#Hello world!\nLorem ipsum", format: 'markdown') }
133
152
  it { is_expected.to eq "<h1>Hello world!</h1>\n<p>Lorem ipsum</p>\n" }
134
153
 
135
154
  end
@@ -27,12 +27,30 @@ describe Locomotive::Steam::Liquid::Tags::Extends do
27
27
 
28
28
  let!(:template) { parse_template(source, options) }
29
29
 
30
- let(:parent) { instance_double('Index', localized_attributes: { source: true, template: true }, source: { en: 'Hello world!' }, template: { en: nil }) }
30
+ let(:parent) { instance_double('Index', handle: nil, slug: nil, localized_attributes: { source: true, template: true }, source: { en: 'Hello world!' }, template: { en: nil }) }
31
31
 
32
32
  it { expect(listener.event_names.first).to eq 'steam.parse.extends' }
33
33
  it { expect(template.render).to eq 'Hello world!' }
34
34
  it { expect(options[:page]).to eq page }
35
35
 
36
+ describe 'set the layout name' do
37
+
38
+ let(:source) { '{% extends parent %}{% block message %}My layout: {{ layout_name }}{% endblock %}' }
39
+
40
+ let(:parent) { instance_double('Index', handle: nil, slug: 'index', localized_attributes: { source: true, template: true }, source: { en: 'Hello world! {% block message %}{% endblock %}' }, template: { en: nil }) }
41
+
42
+ it { expect(template.render).to eq 'Hello world! My layout: index' }
43
+
44
+ context 'the handle of the parent page exists' do
45
+
46
+ let(:parent) { instance_double('Index', handle: 'home', slug: 'index', localized_attributes: { source: true, template: true }, source: { en: 'Hello world! {% block message %}{% endblock %}' }, template: { en: nil }) }
47
+
48
+ it { expect(template.render).to eq 'Hello world! My layout: home' }
49
+
50
+ end
51
+
52
+ end
53
+
36
54
  end
37
55
 
38
56
  end
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  describe Locomotive::Steam::Liquid::Tags::InheritedBlock do
4
4
 
5
5
  let(:parent_source) { 'My product: {% block product %}Random{% endblock %}' }
6
- let(:parent) { instance_double('Index', liquid_source: parent_source, template: nil, :template= => nil) }
6
+ let(:parent) { instance_double('Index', liquid_source: parent_source, template: nil, :template= => nil, slug: nil, handle: nil) }
7
7
  let(:source) { '{% extends parent %}{% block product %}Skis{% endblock %}' }
8
8
  let(:page) { instance_double('Page') }
9
9
 
@@ -25,6 +25,27 @@ describe Locomotive::Steam::Liquid::Tags::WithScope do
25
25
 
26
26
  end
27
27
 
28
+ describe 'decode content entry' do
29
+
30
+ let(:entry) {
31
+ instance_double('ContentEntry', _id: 1, _source: 'entity').tap do |_entry|
32
+ allow(_entry).to receive(:to_liquid).and_return(_entry)
33
+ end }
34
+ let(:assigns) { { 'my_project' => entry } }
35
+ let(:source) { "{% with_scope project: my_project %}{% assign conditions = with_scope %}{% endwith_scope %}" }
36
+
37
+ it { expect(conditions['project']).to eq 'entity' }
38
+
39
+ context 'an array of content entries' do
40
+
41
+ let(:source) { "{% with_scope project: [my_project, my_project, my_project] %}{% assign conditions = with_scope %}{% endwith_scope %}" }
42
+
43
+ it { expect(conditions['project']).to eq ['entity', 'entity', 'entity'] }
44
+
45
+ end
46
+
47
+ end
48
+
28
49
  describe 'decode context variable' do
29
50
 
30
51
  let(:assigns) { { 'params' => { 'type' => 'posts' } } }
@@ -4,7 +4,7 @@ require_relative '../../../lib/locomotive/steam/adapters/filesystem.rb'
4
4
 
5
5
  describe Locomotive::Steam::ContentEntryRepository do
6
6
 
7
- let(:_fields) { instance_double('Fields', selects: [], belongs_to: []) }
7
+ let(:_fields) { instance_double('Fields', selects: [], belongs_to: [], many_to_many: []) }
8
8
  let(:type) { build_content_type('Articles', label_field_name: :title, localized_names: [:title], fields: _fields, fields_by_name: { title: instance_double('Field', name: :title, type: :string) }) }
9
9
  let(:entries) { [{ content_type_id: 1, _position: 0, _label: 'Update #1', title: { fr: 'Mise a jour #1' }, text: { en: 'added some free stuff', fr: 'phrase FR' }, date: '2009/05/12', category: 'General' }] }
10
10
  let(:locale) { :en }
@@ -248,7 +248,7 @@ describe Locomotive::Steam::ContentEntryRepository do
248
248
  let(:other_type) { build_content_type('Authors', _id: 2, label_field_name: :name, fields: _fields, fields_by_name: { name: instance_double('Field', name: :name, type: :string) }) }
249
249
  let(:other_entries) { [{ content_type_id: 2, _id: 'john-doe', name: 'John Doe' }] }
250
250
 
251
- let(:type_repository) { instance_double('ArticleBelongsToRepository', selects: [], belongs_to: []) }
251
+ let(:type_repository) { instance_double('ArticleBelongsToRepository', selects: [], belongs_to: [], many_to_many: []) }
252
252
 
253
253
  before do
254
254
  allow(type).to receive(:fields).and_return(type_repository)
@@ -281,7 +281,7 @@ describe Locomotive::Steam::ContentEntryRepository do
281
281
  ]
282
282
  }
283
283
 
284
- let(:type_repository) { instance_double('AuthorRepository', selects: [], belongs_to: []) }
284
+ let(:type_repository) { instance_double('AuthorRepository', selects: [], belongs_to: [], many_to_many: []) }
285
285
 
286
286
  before do
287
287
  allow(type).to receive(:fields).and_return(type_repository)
@@ -314,7 +314,7 @@ describe Locomotive::Steam::ContentEntryRepository do
314
314
  ]
315
315
  }
316
316
 
317
- let(:type_repository) { instance_double('AuthorRepository', selects: [], belongs_to: []) }
317
+ let(:type_repository) { instance_double('AuthorRepository', selects: [], belongs_to: [], many_to_many: []) }
318
318
 
319
319
  before do
320
320
  allow(type).to receive(:fields).and_return(type_repository)
@@ -333,6 +333,76 @@ describe Locomotive::Steam::ContentEntryRepository do
333
333
 
334
334
  end
335
335
 
336
+ describe '#conditions_without_order_by' do
337
+
338
+ let(:conditions) { {} }
339
+
340
+ subject { repository.with(type).send(:conditions_without_order_by, conditions) }
341
+
342
+ it { is_expected.to eq([{ _visible: true, content_type_id: 1 }, nil]) }
343
+
344
+ context 'select fields' do
345
+
346
+ let(:value) { 'CMS' }
347
+ let(:option) { instance_double('Option', _id: 42)}
348
+ let(:options) { instance_double('OptionRepository', by_name: option) }
349
+ let(:field) { instance_double('SelectField', name: 'category', persisted_name: 'category_id', select_options: options) }
350
+ let(:_fields) { instance_double('Fields', selects: [field], belongs_to: [], many_to_many: []) }
351
+ let(:conditions) { { 'category' => value } }
352
+
353
+ it { is_expected.to eq([{ _visible: true, content_type_id: 1, 'category_id' => 42 }, nil]) }
354
+
355
+ end
356
+
357
+ context 'belongs_to fields' do
358
+
359
+ let(:value) { 42 }
360
+ let(:field) { instance_double('BelongsToField', name: 'person', persisted_name: 'person_id') }
361
+ let(:_fields) { instance_double('Fields', selects: [], belongs_to: [field], many_to_many: []) }
362
+ let(:conditions) { { 'person' => value } }
363
+
364
+ it { is_expected.to eq([{ _visible: true, content_type_id: 1, 'person_id' => 42 }, nil]) }
365
+
366
+ context 'the target value is a content entry' do
367
+
368
+ let(:value) { instance_double('TargetContentEntry', _id: 1) }
369
+
370
+ it { is_expected.to eq([{ _visible: true, content_type_id: 1, 'person_id' => 1 }, nil]) }
371
+
372
+ end
373
+
374
+ context 'the target value is an arry of content entry' do
375
+
376
+ let(:value) { [instance_double('TargetContentEntry', _id: 1), instance_double('TargetContentEntry', _id: 2)] }
377
+ let(:conditions) { { 'person.in' => value } }
378
+
379
+ it { is_expected.to eq([{ _visible: true, content_type_id: 1, 'person_id.in' => [1, 2] }, nil]) }
380
+
381
+ end
382
+
383
+ end
384
+
385
+ context 'many_to_many fields' do
386
+
387
+ let(:value) { 42 }
388
+ let(:field) { instance_double('ManyToManyField', name: 'tags', persisted_name: 'tag_ids') }
389
+ let(:_fields) { instance_double('Fields', selects: [], belongs_to: [], many_to_many: [field]) }
390
+ let(:conditions) { { 'tags.in' => value } }
391
+
392
+ it { is_expected.to eq([{ _visible: true, content_type_id: 1, 'tag_ids.in' => [42] }, nil]) }
393
+
394
+ context 'the target value is a content entry' do
395
+
396
+ let(:value) { [instance_double('TargetContentEntry', _id: 1), 42] }
397
+
398
+ it { is_expected.to eq([{ _visible: true, content_type_id: 1, 'tag_ids.in' => [1, 42] }, nil]) }
399
+
400
+ end
401
+
402
+ end
403
+
404
+ end
405
+
336
406
  def build_content_type(name, attributes = {})
337
407
  instance_double(name,
338
408
  {
@@ -331,6 +331,12 @@ describe Locomotive::Steam::PageRepository do
331
331
 
332
332
  end
333
333
 
334
+ context 'looping over' do
335
+
336
+ it { i = 0; subject.each { |el| i += 1 }; expect(i).to eq 1 }
337
+
338
+ end
339
+
334
340
  end
335
341
 
336
342
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: locomotivecms_steam
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.rc6
4
+ version: 1.0.0.rc8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Didier Lafforgue
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2015-11-22 00:00:00.000000000 Z
14
+ date: 2015-12-05 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: bundler
@@ -69,6 +69,20 @@ dependencies:
69
69
  - - "~>"
70
70
  - !ruby/object:Gem::Version
71
71
  version: 2.1.1
72
+ - !ruby/object:Gem::Dependency
73
+ name: nokogiri
74
+ requirement: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - "~>"
77
+ - !ruby/object:Gem::Version
78
+ version: 1.6.6.4
79
+ type: :runtime
80
+ prerelease: false
81
+ version_requirements: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - "~>"
84
+ - !ruby/object:Gem::Version
85
+ version: 1.6.6.4
72
86
  - !ruby/object:Gem::Dependency
73
87
  name: sanitize
74
88
  requirement: !ruby/object:Gem::Requirement
@@ -489,6 +503,7 @@ files:
489
503
  - lib/locomotive/steam/liquid/tags/session_assign.rb
490
504
  - lib/locomotive/steam/liquid/tags/snippet.rb
491
505
  - lib/locomotive/steam/liquid/tags/with_scope.rb
506
+ - lib/locomotive/steam/liquid/template.rb
492
507
  - lib/locomotive/steam/middlewares.rb
493
508
  - lib/locomotive/steam/middlewares/default_env.rb
494
509
  - lib/locomotive/steam/middlewares/dynamic_assets.rb
@@ -649,6 +664,7 @@ files:
649
664
  - spec/fixtures/mongodb/locomotive_translations.metadata.json
650
665
  - spec/fixtures/mongodb/system.indexes.bson
651
666
  - spec/integration/integration_helper.rb
667
+ - spec/integration/liquid/drops/page_spec.rb
652
668
  - spec/integration/liquid/tags/paginate_spec.rb
653
669
  - spec/integration/repositories/content_entry_repository_spec.rb
654
670
  - spec/integration/repositories/content_type_repository_spec.rb
@@ -890,6 +906,7 @@ test_files:
890
906
  - spec/fixtures/mongodb/locomotive_translations.metadata.json
891
907
  - spec/fixtures/mongodb/system.indexes.bson
892
908
  - spec/integration/integration_helper.rb
909
+ - spec/integration/liquid/drops/page_spec.rb
893
910
  - spec/integration/liquid/tags/paginate_spec.rb
894
911
  - spec/integration/repositories/content_entry_repository_spec.rb
895
912
  - spec/integration/repositories/content_type_repository_spec.rb