slices 1.0.0

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 (215) hide show
  1. data/CHANGELOG.md +3 -0
  2. data/README.md +51 -0
  3. data/Rakefile +9 -0
  4. data/app/assets/images/slices/ajax-loader.gif +0 -0
  5. data/app/assets/images/slices/asset-background.png +0 -0
  6. data/app/assets/images/slices/asset-spinner.gif +0 -0
  7. data/app/assets/images/slices/bg_header.gif +0 -0
  8. data/app/assets/images/slices/black-Linen.png +0 -0
  9. data/app/assets/images/slices/calendar.svg +68 -0
  10. data/app/assets/images/slices/chosen-sprite.png +0 -0
  11. data/app/assets/images/slices/drag-handle.svg +9 -0
  12. data/app/assets/images/slices/icon_admins.png +0 -0
  13. data/app/assets/images/slices/icon_app.png +0 -0
  14. data/app/assets/images/slices/icon_assets.png +0 -0
  15. data/app/assets/images/slices/icon_collapse.png +0 -0
  16. data/app/assets/images/slices/icon_drag.png +0 -0
  17. data/app/assets/images/slices/icon_files.png +0 -0
  18. data/app/assets/images/slices/icon_generic_file.png +0 -0
  19. data/app/assets/images/slices/icon_images.png +0 -0
  20. data/app/assets/images/slices/icon_padlock.png +0 -0
  21. data/app/assets/images/slices/icon_page.png +0 -0
  22. data/app/assets/images/slices/icon_search.png +0 -0
  23. data/app/assets/images/slices/icon_set-link.png +0 -0
  24. data/app/assets/images/slices/icon_set.png +0 -0
  25. data/app/assets/images/slices/icon_sitemap.png +0 -0
  26. data/app/assets/images/slices/icon_snippets.png +0 -0
  27. data/app/assets/images/slices/icon_template.jpg +0 -0
  28. data/app/assets/images/slices/icon_upload_happy.png +0 -0
  29. data/app/assets/images/slices/icon_upload_sad.png +0 -0
  30. data/app/assets/images/slices/icon_upload_thinking.png +0 -0
  31. data/app/assets/images/slices/noise.png +0 -0
  32. data/app/assets/images/slices/sitemap_icon_ghost.png +0 -0
  33. data/app/assets/images/slices/sitemap_icon_home.png +0 -0
  34. data/app/assets/images/slices/sitemap_icon_page.png +0 -0
  35. data/app/assets/images/slices/sitemap_icon_set_page.png +0 -0
  36. data/app/assets/images/slices/sitemap_icon_virtual_page.png +0 -0
  37. data/app/assets/images/slices/sitemap_overlay.png +0 -0
  38. data/app/assets/images/slices/spinner.gif +0 -0
  39. data/app/assets/images/slices/trash.png +0 -0
  40. data/app/assets/javascripts/admin.js.erb +18 -0
  41. data/app/assets/javascripts/slices/app/backbones/admins.js +114 -0
  42. data/app/assets/javascripts/slices/app/backbones/entries.js +172 -0
  43. data/app/assets/javascripts/slices/app/backbones/generic.js +101 -0
  44. data/app/assets/javascripts/slices/app/backbones/snippets.js +113 -0
  45. data/app/assets/javascripts/slices/app/helpers/assets.js +61 -0
  46. data/app/assets/javascripts/slices/app/helpers/breadcrumbs.js +30 -0
  47. data/app/assets/javascripts/slices/app/helpers/composer.js +26 -0
  48. data/app/assets/javascripts/slices/app/helpers/date_field.js +16 -0
  49. data/app/assets/javascripts/slices/app/helpers/get_value.js +31 -0
  50. data/app/assets/javascripts/slices/app/helpers/icon_upload_names.js.erb +5 -0
  51. data/app/assets/javascripts/slices/app/helpers/layout.js +20 -0
  52. data/app/assets/javascripts/slices/app/helpers/sitemap.js +150 -0
  53. data/app/assets/javascripts/slices/app/helpers/slice_preview.js +48 -0
  54. data/app/assets/javascripts/slices/app/helpers/tagging.js +73 -0
  55. data/app/assets/javascripts/slices/app/helpers/token_field.js +17 -0
  56. data/app/assets/javascripts/slices/app/helpers/upload_icons.js.erb +5 -0
  57. data/app/assets/javascripts/slices/app/helpers/uploader.js +127 -0
  58. data/app/assets/javascripts/slices/app/models/asset.js +29 -0
  59. data/app/assets/javascripts/slices/app/models/asset_collection.js +41 -0
  60. data/app/assets/javascripts/slices/app/models/attachment.js +29 -0
  61. data/app/assets/javascripts/slices/app/models/attachment_collection.js +7 -0
  62. data/app/assets/javascripts/slices/app/models/composer_item.js +1 -0
  63. data/app/assets/javascripts/slices/app/models/composer_item_collection.js +3 -0
  64. data/app/assets/javascripts/slices/app/models/file.js +103 -0
  65. data/app/assets/javascripts/slices/app/models/page.js +186 -0
  66. data/app/assets/javascripts/slices/app/models/s3_file.js +64 -0
  67. data/app/assets/javascripts/slices/app/slices.js +661 -0
  68. data/app/assets/javascripts/slices/app/views/asset_editor_view.js.erb +209 -0
  69. data/app/assets/javascripts/slices/app/views/asset_library_view.js +720 -0
  70. data/app/assets/javascripts/slices/app/views/asset_thumb_view.js.erb +191 -0
  71. data/app/assets/javascripts/slices/app/views/attachment_composer_view.js +350 -0
  72. data/app/assets/javascripts/slices/app/views/attachment_view.js +101 -0
  73. data/app/assets/javascripts/slices/app/views/calendar_view.js +198 -0
  74. data/app/assets/javascripts/slices/app/views/composer_item_view.js +54 -0
  75. data/app/assets/javascripts/slices/app/views/composer_view.js +130 -0
  76. data/app/assets/javascripts/slices/app/views/date_field_view.js +177 -0
  77. data/app/assets/javascripts/slices/app/views/file_view.js +142 -0
  78. data/app/assets/javascripts/slices/app/views/token_field_view.js +253 -0
  79. data/app/assets/javascripts/slices/lib/freeze.js +14 -0
  80. data/app/assets/javascripts/slices/lib/human_file_size.js +16 -0
  81. data/app/assets/javascripts/slices/lib/json_patch.js +9 -0
  82. data/app/assets/javascripts/slices/lib/moment.js +47 -0
  83. data/app/assets/javascripts/slices/lib/plugins.js +101 -0
  84. data/app/assets/javascripts/slices/lib/sortable.js +14 -0
  85. data/app/assets/javascripts/slices/slices.js +27 -0
  86. data/app/assets/javascripts/slices/vendor/autoscroll.js +188 -0
  87. data/app/assets/javascripts/slices/vendor/backbone.js +38 -0
  88. data/app/assets/javascripts/slices/vendor/handlebars.js +1920 -0
  89. data/app/assets/javascripts/slices/vendor/jqmodal.js +69 -0
  90. data/app/assets/javascripts/slices/vendor/jquery-ui.js +274 -0
  91. data/app/assets/javascripts/slices/vendor/jquery-ui_nested-sortable.js +357 -0
  92. data/app/assets/javascripts/slices/vendor/jquery.ajaxprogress.js +76 -0
  93. data/app/assets/javascripts/slices/vendor/jquery.js +2 -0
  94. data/app/assets/javascripts/slices/vendor/livefield.js +459 -0
  95. data/app/assets/javascripts/slices/vendor/moment.js +6 -0
  96. data/app/assets/javascripts/slices/vendor/rails.js +315 -0
  97. data/app/assets/javascripts/slices/vendor/underscore-string.js +1 -0
  98. data/app/assets/javascripts/slices/vendor/underscore.js +5 -0
  99. data/app/assets/stylesheets/admin.css +1 -0
  100. data/app/assets/stylesheets/slices/admin.css.erb +2237 -0
  101. data/app/assets/stylesheets/slices/reset_html5.css +106 -0
  102. data/app/assets/stylesheets/slices/slices.css +7 -0
  103. data/app/controllers/admin/admin_controller.rb +10 -0
  104. data/app/controllers/admin/admins_controller.rb +76 -0
  105. data/app/controllers/admin/assets_controller.rb +53 -0
  106. data/app/controllers/admin/auth/omniauth_callbacks_controller.rb +15 -0
  107. data/app/controllers/admin/auth/passwords_controller.rb +4 -0
  108. data/app/controllers/admin/auth/sessions_controller.rb +4 -0
  109. data/app/controllers/admin/entries_controller.rb +88 -0
  110. data/app/controllers/admin/page_search_controller.rb +12 -0
  111. data/app/controllers/admin/pages_controller.rb +103 -0
  112. data/app/controllers/admin/site_maps_controller.rb +15 -0
  113. data/app/controllers/admin/snippets_controller.rb +33 -0
  114. data/app/controllers/application_controller.rb +4 -0
  115. data/app/controllers/pages_controller.rb +45 -0
  116. data/app/controllers/slices_controller.rb +63 -0
  117. data/app/controllers/static_assets_controller.rb +52 -0
  118. data/app/helpers/admin/admin_helper.rb +63 -0
  119. data/app/helpers/admin/assets_helper.rb +36 -0
  120. data/app/helpers/admin/entries_helper.rb +13 -0
  121. data/app/helpers/admin/site_maps_helper.rb +104 -0
  122. data/app/helpers/assets_helper.rb +64 -0
  123. data/app/helpers/navigation_helper.rb +195 -0
  124. data/app/helpers/pages_helper.rb +119 -0
  125. data/app/models/admin.rb +34 -0
  126. data/app/models/asset.rb +211 -0
  127. data/app/models/attachment.rb +11 -0
  128. data/app/models/layout.rb +44 -0
  129. data/app/models/page.rb +214 -0
  130. data/app/models/placeholder_slice.rb +8 -0
  131. data/app/models/set_page.rb +12 -0
  132. data/app/models/set_slice.rb +57 -0
  133. data/app/models/site_map.rb +24 -0
  134. data/app/models/slice.rb +80 -0
  135. data/app/models/snippet.rb +21 -0
  136. data/app/observers/asset_observer.rb +6 -0
  137. data/app/observers/page_observer.rb +37 -0
  138. data/app/presenters/entry_presenter.rb +17 -0
  139. data/app/presenters/page_presenter.rb +67 -0
  140. data/app/presenters/presenter.rb +9 -0
  141. data/app/presenters/set_page_presenter.rb +2 -0
  142. data/app/views/admin/admins/index.html.erb +26 -0
  143. data/app/views/admin/admins/show.html.erb +27 -0
  144. data/app/views/admin/assets/index.html.erb +1 -0
  145. data/app/views/admin/auth/passwords/edit.html.erb +20 -0
  146. data/app/views/admin/auth/passwords/new.html.erb +14 -0
  147. data/app/views/admin/auth/sessions/_form.html.erb +35 -0
  148. data/app/views/admin/auth/sessions/new.html.erb +14 -0
  149. data/app/views/admin/entries/index.html.erb +32 -0
  150. data/app/views/admin/pages/_breadcrumbs.html.erb +32 -0
  151. data/app/views/admin/pages/_slices.html.erb +27 -0
  152. data/app/views/admin/pages/new.html.erb +14 -0
  153. data/app/views/admin/pages/show.html.erb +50 -0
  154. data/app/views/admin/shared/_asset_storage.html.erb +17 -0
  155. data/app/views/admin/shared/_custom_links.html.erb +1 -0
  156. data/app/views/admin/shared/_custom_navigation.html.erb +1 -0
  157. data/app/views/admin/shared/_navigation.html.erb +5 -0
  158. data/app/views/admin/site_maps/_page_li.html.erb +20 -0
  159. data/app/views/admin/site_maps/_set_page_li.html.erb +23 -0
  160. data/app/views/admin/site_maps/index.html.erb +29 -0
  161. data/app/views/admin/snippets/form.html.erb +12 -0
  162. data/app/views/admin/snippets/index.html.erb +20 -0
  163. data/app/views/admin/snippets/update.html.erb +0 -0
  164. data/app/views/layouts/admin.html.erb +72 -0
  165. data/lib/ext/file_store_cache.rb +18 -0
  166. data/lib/generators/humans/USAGE +8 -0
  167. data/lib/generators/humans/humans_generator.rb +10 -0
  168. data/lib/generators/humans/templates/humans.txt +6 -0
  169. data/lib/generators/slice/USAGE +28 -0
  170. data/lib/generators/slice/slice_generator.rb +123 -0
  171. data/lib/generators/slice/templates/main_fields.hbs +11 -0
  172. data/lib/generators/slice/templates/meta_fields.hbs +11 -0
  173. data/lib/generators/slice/templates/page.rb +19 -0
  174. data/lib/generators/slice/templates/presenter.rb +53 -0
  175. data/lib/generators/slice/templates/set.html.erb +8 -0
  176. data/lib/generators/slice/templates/set_slice.rb +14 -0
  177. data/lib/generators/slice/templates/set_slice_fields.hbs +5 -0
  178. data/lib/generators/slice/templates/show.html.erb +48 -0
  179. data/lib/generators/slice/templates/show_slice.rb +20 -0
  180. data/lib/generators/slice/templates/slice.rb +58 -0
  181. data/lib/generators/slice/templates/slice_fields.hbs +74 -0
  182. data/lib/generators/templates/slices.rb +211 -0
  183. data/lib/mongo_search.rb +84 -0
  184. data/lib/paperclip_validator.rb +5 -0
  185. data/lib/rack_utf8_fix.rb +10 -0
  186. data/lib/sRGB.icc +0 -0
  187. data/lib/set_link_renderer.rb +31 -0
  188. data/lib/slices.rb +68 -0
  189. data/lib/slices/asset/maker.rb +55 -0
  190. data/lib/slices/asset/rename.rb +67 -0
  191. data/lib/slices/available_slices.rb +43 -0
  192. data/lib/slices/cms_form_builder.rb +42 -0
  193. data/lib/slices/config.rb +93 -0
  194. data/lib/slices/container_parser.rb +70 -0
  195. data/lib/slices/generator_macros.rb +36 -0
  196. data/lib/slices/has_attachments.rb +111 -0
  197. data/lib/slices/has_slices.rb +88 -0
  198. data/lib/slices/i18n.rb +6 -0
  199. data/lib/slices/i18n/backend.rb +32 -0
  200. data/lib/slices/i18n_backend.rb +24 -0
  201. data/lib/slices/paperclip.rb +13 -0
  202. data/lib/slices/position_helper.rb +98 -0
  203. data/lib/slices/renderer.rb +52 -0
  204. data/lib/slices/slices_engine.rb +51 -0
  205. data/lib/slices/split_date_time_field.rb +14 -0
  206. data/lib/slices/tasks/assets.rake +35 -0
  207. data/lib/slices/tasks/db.rake +50 -0
  208. data/lib/slices/tasks/seeds.rake +93 -0
  209. data/lib/slices/tasks/validate.rake +62 -0
  210. data/lib/slices/tree.rb +306 -0
  211. data/lib/slices/version.rb +4 -0
  212. data/lib/slices/will_paginate.rb +12 -0
  213. data/lib/slices/will_paginate_mongoid.rb +45 -0
  214. data/lib/standard_tree.rb +193 -0
  215. metadata +483 -0
@@ -0,0 +1,70 @@
1
+ module Slices
2
+ class ContainerParser
3
+ class MissingLayoutError < StandardError; end
4
+
5
+ def initialize(path)
6
+ raise MissingLayoutError if path.nil?
7
+ @path = path
8
+ @containers = {}
9
+ end
10
+
11
+ def parse
12
+ @page = Page.new
13
+ erb_template = File.read(@path)
14
+ @erb = ActionView::Template::Handlers::Erubis.new(erb_template)
15
+ parse_with_block {}
16
+ @containers
17
+ end
18
+
19
+ # Define a +container+ in a layout, a container holds slices on a page.
20
+ #
21
+ # This container is called Title and only allows title and You Tube slices
22
+ #
23
+ # container "title", :only => [TitleSlice, YouTubeSlice]
24
+ #
25
+ # Here's a container called body which is the primary and does not allow
26
+ # title slices.
27
+ #
28
+ # container "body", :primary => true, :except => TitleSlice
29
+ #
30
+ # @param [String] name Name of container
31
+ # @param [Hash] options
32
+ # @option options [Boolean] :primary (false) Is this container the primary
33
+ # @option options [Class,Array] :except Disallow these slice(s) from this container
34
+ # @option options [Class,Array] :only Only allow these slice(s) from this container
35
+ # @return [String]
36
+ #
37
+ def container(name, options = {})
38
+ [:except, :only].each do |type|
39
+ if options.has_key? type
40
+ options[type] = convert_slice_classes_to_symbols(options[type])
41
+ end
42
+ end
43
+
44
+ @containers[name] = options.reverse_merge name: name.titleize
45
+ end
46
+
47
+ def method_missing(meth, *args, &block)
48
+ yield if block_given?
49
+ end
50
+
51
+ private
52
+
53
+ def parse_with_block(&block)
54
+ @erb.result(binding)
55
+ end
56
+
57
+ def convert_slice_classes_to_symbols(options = [])
58
+ [options].flatten.select do |klass|
59
+ klass.is_a?(Class)
60
+ end.map do |klass|
61
+ convert_slice_class_to_symbol(klass)
62
+ end
63
+ end
64
+
65
+ def convert_slice_class_to_symbol(klass)
66
+ klass.name.underscore.split('_')[0 .. -2].join('_').to_sym
67
+ end
68
+ end
69
+ end
70
+
@@ -0,0 +1,36 @@
1
+ module Slices
2
+ module GeneratorMacros
3
+ # Defines a generator method.
4
+ #
5
+ # e.g.
6
+ #
7
+ # generator :home do
8
+ # Page.where(path: '/').first || Page.make(
9
+ # name: 'Home'
10
+ # )
11
+ # end
12
+ #
13
+ # Results in:
14
+ #
15
+ # MyStandardTree.home
16
+ #
17
+ #
18
+ # @param [Symbol] name
19
+ # @param [Proc] block macro body
20
+ #
21
+ def generator name, &block
22
+ define_singleton_method name, &block
23
+ generators << name
24
+ end
25
+
26
+ # Simple catalogue of generators.
27
+ def generators
28
+ @generators ||= []
29
+ end
30
+
31
+ # Invokes all generators.
32
+ def generate!
33
+ generators.map { |m| send m }
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,111 @@
1
+ module Slices
2
+ module HasAttachments
3
+ extend ActiveSupport::Concern
4
+
5
+ module ClassMethods
6
+
7
+ def has_attachments(embed_name = :attachments, options = {})
8
+ klass = if options.has_key?(:class_name)
9
+ options[:class_name].constantize
10
+ else
11
+ Attachment
12
+ end
13
+
14
+ default = options[:default] || options[:singular] ? nil : []
15
+ type = options[:singular] ? Hash : Array
16
+
17
+ if options[:singular]
18
+ define_method embed_name do
19
+ if embed = read_attribute(embed_name)
20
+ klass.new embed
21
+ end
22
+ end
23
+ else
24
+ define_method embed_name do
25
+ (read_attribute(embed_name) || []).collect do |embed|
26
+ klass.new embed
27
+ end
28
+ end
29
+ end
30
+
31
+ attachment_fields << embed_name
32
+
33
+ field embed_name, type: type, default: default
34
+ end
35
+
36
+ def attachment_fields
37
+ @attachment_fields ||= if superclass.respond_to?(:attachment_fields)
38
+ superclass.attachment_fields.dup
39
+ else
40
+ []
41
+ end
42
+ end
43
+
44
+ end
45
+
46
+ module PageInstanceMethods
47
+
48
+ def attachment_assets
49
+ attachment_asset_ids.inject([]) do |memo, asset_id|
50
+ begin
51
+ memo << ::Asset.find(asset_id)
52
+ rescue Mongoid::Errors::DocumentNotFound
53
+ end
54
+ memo
55
+ end
56
+ end
57
+
58
+ def slice_attachment_asset_ids
59
+ [].tap do |asset_ids|
60
+ self.class.slice_embeds.each do |slice_embed|
61
+ slices_for(slice_embed).each do |slice|
62
+ if slice.respond_to? :attachment_asset_ids
63
+ asset_ids.concat slice.attachment_asset_ids
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+ alias :attachment_asset_ids :slice_attachment_asset_ids
70
+
71
+ end
72
+
73
+ def as_json options = nil
74
+ super.merge(attachments_as_json)
75
+ end
76
+
77
+ def attachments_as_json
78
+ self.class.attachment_fields.inject({}) do |hash, name|
79
+ value = send name
80
+
81
+ hash[name] = if value.respond_to?(:map)
82
+ value.map &:as_json
83
+ else
84
+ value.as_json
85
+ end
86
+
87
+ hash
88
+ end
89
+ end
90
+
91
+ def attachment_asset_ids
92
+ _attachment_asset_ids.tap do |asset_ids|
93
+ if respond_to? :slice_attachment_asset_ids
94
+ asset_ids.concat slice_attachment_asset_ids
95
+ end
96
+ asset_ids.uniq!
97
+ end
98
+ end
99
+
100
+ def _attachment_asset_ids
101
+ attachment_asset_ids = self.class.attachment_fields.collect do |attachments|
102
+ [send(attachments)].flatten.collect do |attachment|
103
+ attachment.asset_id
104
+ end.reject {|i| i.nil? }
105
+ end.flat_map {|i| i }
106
+ end
107
+
108
+ end
109
+
110
+ end
111
+
@@ -0,0 +1,88 @@
1
+ module Slices
2
+ module HasSlices
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ validate :validate_slices
7
+ end
8
+
9
+ module ClassMethods
10
+ def has_slices(embed_name)
11
+ embeds_many embed_name, class_name: 'Slice', validate: false
12
+ accepts_nested_attributes_for embed_name, allow_destroy: true
13
+
14
+ class_attribute :slice_embeds if self == Page
15
+ if slice_embeds.nil?
16
+ self.slice_embeds = [embed_name]
17
+ else
18
+ self.slice_embeds = slice_embeds + [embed_name]
19
+ end
20
+
21
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
22
+ def ordered_#{embed_name} # def orderd_slices
23
+ #{embed_name}.ascending(:position) # slices.ascending(:position)
24
+ end # end
25
+ RUBY
26
+ end
27
+ end
28
+
29
+ def update_attributes(attributes)
30
+ [:slices, :set_slices].each do |type|
31
+ next if attributes[type].nil?
32
+
33
+ attributes[type] = attributes[type].map { |slice|
34
+ slice = slice.symbolize_keys
35
+ next if slice[:_destroy]
36
+ slice.delete :_new
37
+ klass = (slice[:type] + '_slice').camelize.constantize
38
+ klass.new(slice)
39
+ }.compact
40
+ end
41
+
42
+ super
43
+ end
44
+
45
+ def slices_for(embed_name)
46
+ send(embed_name)
47
+ end
48
+
49
+ def ordered_slices_for(embed_name=nil)
50
+ embed_name = self.class.slice_embeds.first if embed_name.nil?
51
+ send("ordered_#{embed_name}")
52
+ end
53
+
54
+ def validate_slices
55
+ embeded_slices do |embed_name|
56
+ _slice_errors = slice_errors_for(embed_name)
57
+ if _slice_errors.any?
58
+ errors.add(embed_name, _slice_errors)
59
+ end
60
+ end
61
+ end
62
+
63
+ def slice_errors_for(embed_name)
64
+ Hash.new.tap do |message|
65
+ slices_for(embed_name).each do |slice|
66
+ if ! slice.valid? && ! slice.to_delete?
67
+ message[slice.id_or_client_id] = messages_from_errors(slice.errors)
68
+ end
69
+ end
70
+ end
71
+ end
72
+
73
+ def embeded_slices(&block)
74
+ self.class.slice_embeds.each do |embed_name|
75
+ yield(embed_name)
76
+ end
77
+ end
78
+
79
+ def messages_from_errors(errors)
80
+ if errors.respond_to?(:messages)
81
+ errors.messages
82
+ else
83
+ errors
84
+ end
85
+ end
86
+
87
+ end
88
+ end
@@ -0,0 +1,6 @@
1
+ require 'slices/i18n/backend'
2
+
3
+ I18n.backend = I18n::Backend::Chain.new(
4
+ Slices::I18n::Backend.new,
5
+ I18n.backend
6
+ )
@@ -0,0 +1,32 @@
1
+ module Slices
2
+ module I18n
3
+
4
+ class Backend
5
+ module Implementation
6
+ include ::I18n::Backend::Base, ::I18n::Backend::Flatten
7
+
8
+ # This method receives a locale, a data hash and options for storing translations.
9
+ # Should be implemented
10
+ def store_translations(locale, data, options = {})
11
+ raise NotImplementedError
12
+ end
13
+
14
+ def available_locales
15
+ raise NotImplementedError
16
+ end
17
+
18
+ protected
19
+
20
+ def lookup(locale, key, scope = [], options = {})
21
+ key = normalize_flat_keys(locale, key, scope, options[:separator])
22
+ Snippet.find_value_by_key("#{locale}.#{key}")
23
+ end
24
+
25
+ end
26
+
27
+ include Implementation
28
+ end
29
+
30
+ end
31
+ end
32
+
@@ -0,0 +1,24 @@
1
+ saise 'aaaaa'
2
+ module Slices
3
+
4
+ class I18nBackend
5
+ include I18n::Backend::Simple::Implementation
6
+
7
+ # Translates the given local and key. See the I18n API documentation for details.
8
+ #
9
+ # @return [Object] the translated key (usually a String)
10
+ def translate(locale, key, options = {})
11
+ content = super(locale, key, options.merge(fallback: true))
12
+ if content.respond_to?(:html_safe)
13
+ content.html_safe
14
+ else
15
+ content
16
+ end
17
+ end
18
+ end
19
+ end
20
+
21
+ I18n.backend = I18n::Backend::Chain.new(
22
+ Slices::I18n::Backend.new,
23
+ I18n.backend
24
+ )
@@ -0,0 +1,13 @@
1
+ Paperclip.options[:log] = true
2
+ require 'paperclip_validator'
3
+
4
+ Paperclip.interpolates :mon_year do |attachment, style|
5
+ attachment.instance.id.generation_time.strftime("%m%Y")
6
+ end
7
+
8
+ #This is a hack used to access Paperclip's internal cache
9
+ #of attributes it reads from the attachment. Used as part
10
+ #of the file renaming code.
11
+ class Paperclip::Attachment
12
+ attr_accessor :_file_file_name
13
+ end
@@ -0,0 +1,98 @@
1
+ module Slices
2
+ module PositionHelper
3
+
4
+ # Returns an array of slices in the same container, including self.
5
+ #
6
+ # @return [Array]
7
+ #
8
+ def peers
9
+ @peers ||= normal_or_set_page.ordered_slices.select do |slice|
10
+ slice.container == self.container
11
+ end
12
+ end
13
+
14
+ # Returns the previous slice in the container, or +nil+ if this is the
15
+ # first slice.
16
+ #
17
+ # @return [Slice]
18
+ #
19
+ def previous_slice
20
+ index = peers.index(self) - 1
21
+ index < 0 ? nil : peers[index]
22
+ end
23
+
24
+ # Returns the next slice in the container, or +nil+ if this is the
25
+ # last slice.
26
+ #
27
+ # @return [Slice]
28
+ #
29
+ def next_slice
30
+ peers[peers.index(self) + 1]
31
+ end
32
+
33
+ # Is this the first slice in the container?
34
+ #
35
+ def first_in_container?
36
+ self == peers.first
37
+ end
38
+
39
+ # Is the previous slice of the same type?
40
+ #
41
+ def first_adjacent_of_type?
42
+ previous_slice.try(:class) != self.class
43
+ end
44
+
45
+ # Is this the last slice in the container?
46
+ #
47
+ def last_in_container?
48
+ self == peers.last
49
+ end
50
+
51
+ # Is the next slice the same type?
52
+ #
53
+ def last_adjacent_of_type?
54
+ next_slice.try(:class) != self.class
55
+ end
56
+
57
+ # Is this the only slice in the container?
58
+ #
59
+ def alone_in_container?
60
+ peers.size == 1
61
+ end
62
+
63
+ # Are both the next and previous slices different types?
64
+ #
65
+ def alone_in_adjacent_of_type?
66
+ first_adjacent_of_type? && last_adjacent_of_type?
67
+ end
68
+
69
+ # The position of the slice in the container, the first slice has a position
70
+ # of 1
71
+ #
72
+ # @return [Integer]
73
+ #
74
+ def position_in_container
75
+ peers.index(self) + 1
76
+ end
77
+
78
+ # The position of the slice in a group of the same slices
79
+ #
80
+ # For example, given the following slices
81
+ # [TitleSlice, CopySlice, CopySlice, CopySlice]
82
+ #
83
+ # The second +CopySlice+ would have a +position_in_adjacent_of_type+ of 2
84
+ #
85
+ # @return [Integer]
86
+ #
87
+ def position_in_adjacent_of_type
88
+ slices = []
89
+ reversed = peers.reverse
90
+ reversed[reversed.index(self)..-1].each do |slice|
91
+ break unless slice.class == self.class
92
+ slices << slice
93
+ end
94
+ slices.length
95
+ end
96
+ end
97
+
98
+ end