rails_admin_cms 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +36 -0
  4. data/Rakefile +26 -0
  5. data/app/assets/javascripts/rails_admin_cms/all.js.coffee +2 -0
  6. data/app/assets/javascripts/rails_admin_cms/cms.js.coffee +18 -0
  7. data/app/assets/javascripts/rails_admin_cms/cms/flashes.js.coffee +2 -0
  8. data/app/assets/javascripts/rails_admin_cms/cms/with_scope/forms.js.coffee +4 -0
  9. data/app/assets/javascripts/rails_admin_cms/cms/with_scope/viewables.js.coffee +14 -0
  10. data/app/assets/stylesheets/rails_admin_cms/all.css.sass +0 -0
  11. data/app/controllers/cms/attachments_controller.rb +20 -0
  12. data/app/controllers/cms/files_controller.rb +19 -0
  13. data/app/controllers/cms/forms_controller.rb +89 -0
  14. data/app/controllers/cms/pages_controller.rb +13 -0
  15. data/app/controllers/cms/viewables_controller.rb +49 -0
  16. data/app/controllers/concerns/cms/editing.rb +21 -0
  17. data/app/controllers/concerns/cms/localize.rb +15 -0
  18. data/app/helpers/cms/cache_helper.rb +26 -0
  19. data/app/helpers/cms/form_helper.rb +67 -0
  20. data/app/helpers/cms/locale_helper.rb +34 -0
  21. data/app/helpers/cms/view_helper.rb +37 -0
  22. data/app/helpers/cms/viewable_helper.rb +155 -0
  23. data/app/helpers/rails_admin/form_builder_decorator.rb +11 -0
  24. data/app/helpers/rails_admin/navigation_helper.rb +77 -0
  25. data/app/mailers/cms/forms_mailer.rb +48 -0
  26. data/app/models/admin/form/email.rb +41 -0
  27. data/app/models/admin/form/field.rb +25 -0
  28. data/app/models/admin/form/row.rb +36 -0
  29. data/app/models/admin/form/static/object.rb +15 -0
  30. data/app/models/admin/form/structure.rb +18 -0
  31. data/app/models/admin/setting.rb +21 -0
  32. data/app/models/admin/unique_key.rb +15 -0
  33. data/app/models/admin/viewable/block.rb +25 -0
  34. data/app/models/admin/viewable/form.rb +36 -0
  35. data/app/models/admin/viewable/image.rb +18 -0
  36. data/app/models/admin/viewable/link.rb +21 -0
  37. data/app/models/admin/viewable/page.rb +27 -0
  38. data/app/models/admin/viewable/select.rb +15 -0
  39. data/app/models/admin/viewable/text.rb +16 -0
  40. data/app/models/callbacks/form/field_after_create.rb +16 -0
  41. data/app/models/callbacks/form/field_after_destroy.rb +16 -0
  42. data/app/models/callbacks/form/field_before_update.rb +29 -0
  43. data/app/models/callbacks/restrictor.rb +30 -0
  44. data/app/models/callbacks/unique_key_before_update.rb +46 -0
  45. data/app/models/callbacks/viewable_after_destroy.rb +27 -0
  46. data/app/models/callbacks/viewable_before_update.rb +15 -0
  47. data/app/models/form.rb +43 -0
  48. data/app/models/form/email.rb +21 -0
  49. data/app/models/form/field.rb +75 -0
  50. data/app/models/form/row.rb +30 -0
  51. data/app/models/form/static.rb +17 -0
  52. data/app/models/form/static/attachment.rb +62 -0
  53. data/app/models/form/static/base.rb +10 -0
  54. data/app/models/form/static/email.rb +23 -0
  55. data/app/models/form/static/object.rb +12 -0
  56. data/app/models/form/structure.rb +90 -0
  57. data/app/models/setting.rb +85 -0
  58. data/app/models/unique_key.rb +62 -0
  59. data/app/models/viewable.rb +93 -0
  60. data/app/models/viewable/block.rb +39 -0
  61. data/app/models/viewable/field/url.rb +45 -0
  62. data/app/models/viewable/field/uuid.rb +61 -0
  63. data/app/models/viewable/form.rb +67 -0
  64. data/app/models/viewable/image.rb +6 -0
  65. data/app/models/viewable/link.rb +10 -0
  66. data/app/models/viewable/page.rb +24 -0
  67. data/app/models/viewable/select.rb +6 -0
  68. data/app/models/viewable/text.rb +6 -0
  69. data/app/presenters/base_list_presenter.rb +42 -0
  70. data/app/presenters/base_presenter.rb +17 -0
  71. data/app/presenters/viewable/block_presenter.rb +10 -0
  72. data/app/presenters/viewable/form_presenter.rb +15 -0
  73. data/app/presenters/viewable/image_presenter.rb +11 -0
  74. data/app/presenters/viewable/link_list_presenter.rb +44 -0
  75. data/app/presenters/viewable/link_presenter.rb +64 -0
  76. data/app/presenters/viewable/page_presenter.rb +4 -0
  77. data/app/presenters/viewable/select_list_presenter.rb +7 -0
  78. data/app/presenters/viewable/select_presenter.rb +15 -0
  79. data/app/presenters/viewable/text_presenter.rb +11 -0
  80. data/app/presenters/viewable/view_presenter.rb +38 -0
  81. data/app/presenters/viewable_list_presenter.rb +54 -0
  82. data/app/presenters/viewable_presenter.rb +27 -0
  83. data/app/views/cms/forms/create.js.erb +3 -0
  84. data/app/views/cms/shared/_flash_messages.js.erb +2 -0
  85. data/app/views/cms/viewables/update.js.erb +1 -0
  86. data/app/views/layouts/rails_admin/_secondary_navigation.html.haml +10 -0
  87. data/config/initializers/assets.rb +6 -0
  88. data/config/initializers/route_translator.rb +3 -0
  89. data/config/locales/cms.en.yml +32 -0
  90. data/config/locales/cms.fr.yml +32 -0
  91. data/config/locales/flash.en.yml +43 -0
  92. data/config/locales/flash.fr.yml +43 -0
  93. data/config/locales/routes.en.yml +3 -0
  94. data/config/locales/routes.fr.yml +3 -0
  95. data/config/routes.rb +36 -0
  96. data/config/spring.rb +1 -0
  97. data/db/migrate/20151226023652_create_unique_key.rb +19 -0
  98. data/db/migrate/20151226054335_create_viewable_link.rb +14 -0
  99. data/db/migrate/20151227064933_create_viewable_text.rb +10 -0
  100. data/db/migrate/20151227072412_create_rich_rich_images.rich.rb +18 -0
  101. data/db/migrate/20151227072413_add_uri_cache_to_rich_image.rich.rb +6 -0
  102. data/db/migrate/20151227072414_refactor_image_to_file.rich.rb +13 -0
  103. data/db/migrate/20151228231201_create_viewable_image.rb +10 -0
  104. data/db/migrate/20151230050603_create_setting.rb +13 -0
  105. data/db/migrate/20151230072904_add_cms_mail_from_and_bcc_settings.rb +14 -0
  106. data/db/migrate/20151230085947_create_viewable_select.rb +10 -0
  107. data/db/migrate/20151231054310_create_viewable_block.rb +9 -0
  108. data/db/migrate/20151231102148_create_viewable_page.rb +13 -0
  109. data/db/migrate/20160101124428_create_viewable_form.rb +15 -0
  110. data/db/migrate/20160101140244_create_form_structure.rb +9 -0
  111. data/db/migrate/20160101141844_create_form_row.rb +13 -0
  112. data/db/migrate/20160102010317_create_form_field.rb +17 -0
  113. data/db/migrate/20160103120544_create_form_email.rb +18 -0
  114. data/lib/generators/cms/install/USAGE +8 -0
  115. data/lib/generators/cms/install/install_generator.rb +14 -0
  116. data/lib/generators/cms/install/templates/Gemfile +47 -0
  117. data/lib/generators/cms/install/templates/app/assets/javascripts/application.js +19 -0
  118. data/lib/generators/cms/install/templates/app/assets/stylesheets/application.css +17 -0
  119. data/lib/generators/cms/install/templates/app/controllers/application_controller.rb +9 -0
  120. data/lib/generators/cms/install/templates/app/controllers/cms/authenticate.rb +34 -0
  121. data/lib/generators/cms/install/templates/app/models/form/contact.rb +20 -0
  122. data/lib/generators/cms/install/templates/app/views/cms/blocks/_example.html.erb +13 -0
  123. data/lib/generators/cms/install/templates/app/views/cms/forms/contact/_form.html.erb +30 -0
  124. data/lib/generators/cms/install/templates/app/views/cms/forms/contact/new.html.erb +19 -0
  125. data/lib/generators/cms/install/templates/app/views/cms/forms_mailer/contact.html.erb +6 -0
  126. data/lib/generators/cms/install/templates/app/views/cms/forms_mailer/contact.text.erb +6 -0
  127. data/lib/generators/cms/install/templates/app/views/cms/pages/page.html.erb +29 -0
  128. data/lib/generators/cms/install/templates/app/views/layouts/application.html.erb +23 -0
  129. data/lib/generators/cms/install/templates/config/application.rb +36 -0
  130. data/lib/generators/cms/install/templates/config/initializers/rails_admin.rb +97 -0
  131. data/lib/generators/cms/install/templates/config/initializers/rich.rb +142 -0
  132. data/lib/generators/cms/install/templates/config/initializers/simple_form.rb +165 -0
  133. data/lib/generators/cms/install/templates/config/initializers/simple_form_bootstrap.rb +149 -0
  134. data/lib/generators/cms/install/templates/config/locales/routes.en.yml +4 -0
  135. data/lib/generators/cms/install/templates/config/locales/simple_form.en.yml +31 -0
  136. data/lib/generators/cms/install/templates/config/routes.rb +61 -0
  137. data/lib/generators/cms/install/templates/vendor/assets/javascripts/rails_admin/custom/ui.js.coffee +1 -0
  138. data/lib/generators/cms/install/templates/vendor/assets/stylesheets/rails_admin/custom/mixins.sass +0 -0
  139. data/lib/generators/cms/install/templates/vendor/assets/stylesheets/rails_admin/custom/theming.sass +1 -0
  140. data/lib/generators/cms/install/templates/vendor/assets/stylesheets/rails_admin/custom/variables.sass +0 -0
  141. data/lib/generators/cms/install/templates/vendor/assets/stylesheets/rich/editor.css +20 -0
  142. data/lib/rails_admin_cms.rb +28 -0
  143. data/lib/rails_admin_cms/config.rb +45 -0
  144. data/lib/rails_admin_cms/core_ext/boolean.rb +29 -0
  145. data/lib/rails_admin_cms/engine.rb +11 -0
  146. data/lib/rails_admin_cms/inflections.rb +4 -0
  147. data/lib/rails_admin_cms/utils.rb +30 -0
  148. data/lib/rails_admin_cms/version.rb +3 -0
  149. data/lib/tasks/rails_admin_cms_tasks.rake +4 -0
  150. metadata +669 -0
@@ -0,0 +1,21 @@
1
+ module Form
2
+ class Email < ActiveRecord::Base
3
+ include Admin::Form::Email
4
+
5
+ self.table_name_prefix = 'form_'
6
+
7
+ has_one :structure
8
+
9
+ def subject
10
+ send("subject_#{I18n.locale}").presence || I18n.t('cms.form.email.default_subject')
11
+ end
12
+
13
+ def body
14
+ send("body_#{I18n.locale}").presence || I18n.t('cms.form.email.default_body')
15
+ end
16
+
17
+ def send_to
18
+ read_attribute(:send_to).presence || Setting[:cms_mail_bcc]
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,75 @@
1
+ module Form
2
+ class Field < ActiveRecord::Base
3
+ include Admin::Form::Field
4
+
5
+ TYPES ||= %w[ string text email ]
6
+
7
+ self.table_name_prefix = 'form_'
8
+ self.inheritance_column = nil
9
+
10
+ belongs_to :structure, touch: true
11
+ has_many :fields, through: :structure
12
+
13
+ delegate :count, to: :fields, prefix: true
14
+ delegate :header, to: :structure
15
+
16
+ after_create ::Callbacks::Form::FieldAfterCreate.new
17
+ after_destroy ::Callbacks::Form::FieldAfterDestroy.new
18
+ before_update ::Callbacks::Form::FieldBeforeUpdate.new, if: :position_changed?
19
+ after_update :update_column_header, if: :default_label_changed_but_not_position?
20
+
21
+ with_options presence: true do
22
+ validates :type, inclusion: { in: TYPES }
23
+ validates :structure
24
+ validates :position, numericality: { greater_than_or_equal_to: 0}
25
+ with_options on: :create do
26
+ validates :position, numericality: { less_than_or_equal_to: :fields_count }
27
+ end
28
+ with_options on: :update do
29
+ validates :position, numericality: { less_than: :fields_count }
30
+ end
31
+ end
32
+
33
+ def column_key
34
+ :"column_#{position}"
35
+ end
36
+
37
+ def label
38
+ send("label_#{I18n.locale}")
39
+ end
40
+
41
+ def default_label
42
+ send("label_#{I18n.default_locale}")
43
+ end
44
+
45
+ def input_type
46
+ type.demodulize.underscore.to_sym
47
+ end
48
+
49
+ def type_enum
50
+ TYPES
51
+ end
52
+
53
+ def update_header
54
+ attributes = RailsAdminCMS::Config.custom_form_max_size.times.map do |i|
55
+ [:"column_#{i}", '']
56
+ end.to_h
57
+
58
+ fields.map do |field|
59
+ attributes[field.column_key] = field.default_label
60
+ end
61
+
62
+ header.update! attributes
63
+ end
64
+
65
+ private
66
+
67
+ def default_label_changed_but_not_position?
68
+ send("label_#{I18n.default_locale}_changed?") && !position_changed?
69
+ end
70
+
71
+ def update_column_header
72
+ header.update! column_key => default_label
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,30 @@
1
+ module Form
2
+ class Row < ActiveRecord::Base
3
+ include Form
4
+ include Admin::Form::Row
5
+
6
+ self.table_name_prefix = 'form_'
7
+
8
+ belongs_to :structure
9
+ has_many :fields, through: :structure
10
+ has_one :viewable, through: :structure, class_name: 'Viewable::Form'
11
+
12
+ validates :structure, presence: true
13
+
14
+ delegate :with_email?, :send_to, :subject, :body, :email_column_key, :header, to: :structure
15
+ delegate :form_name, to: :viewable
16
+
17
+ def send_from
18
+ send(email_column_key) if email_column_key
19
+ end
20
+
21
+ def labelled_values
22
+ columns = fields.count.times.map{ |i| "column_#{i}" }
23
+ values = header.attributes.slice(*columns)
24
+ values.reduce({}) do |values, (column_key, label)|
25
+ values[label] = send(column_key)
26
+ values
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,17 @@
1
+ module Form
2
+ module Static
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ self.abstract_class = true
7
+ end
8
+
9
+ def with_email?
10
+ false
11
+ end
12
+
13
+ def form_name
14
+ model_name.element
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,62 @@
1
+ module Form
2
+ module Static
3
+ module Attachment
4
+ extend ActiveSupport::Concern
5
+
6
+ class_methods do
7
+ def has_attachments(*attachments)
8
+ define_singleton_method :attachments do
9
+ attachments
10
+ end
11
+
12
+ delegate :attachments, to: :class
13
+
14
+ if virtual?
15
+ attachments.each do |attachment|
16
+ attribute "#{attachment}_file_name", :string
17
+ attribute "#{attachment}_content_type", :string
18
+ attribute "#{attachment}_file_size", :integer
19
+ attribute "#{attachment}_updated_at", :datetime
20
+ end
21
+ end
22
+
23
+ attachments.each do |attachment|
24
+ has_attached_file attachment,
25
+ url: "/attachments/:class/:id_partition/:basename.:extension",
26
+ path: ":rails_root/private/attachments/:class/:id_partition/:basename.:extension"
27
+
28
+ validates_attachment_content_type attachment, { content_type: %w[
29
+ text/plain
30
+ application/pdf
31
+ application/msword
32
+ application/vnd.openxmlformats-officedocument.wordprocessingml.document
33
+ image/jpeg
34
+ image/png
35
+ image/gif
36
+ ] }
37
+ validates_attachment_file_name attachment, matches: [
38
+ /txt\Z/i,
39
+ /pdf\Z/i,
40
+ /doc\Z/i,
41
+ /docx\Z/i,
42
+ /jpe?g\Z/i,
43
+ /png\Z/i,
44
+ /gif\Z/i,
45
+ ]
46
+ validates_attachment_size attachment, less_than: 5.megabytes
47
+ end
48
+
49
+ before_post_process :normalize_attachment
50
+ end
51
+ end
52
+
53
+ private
54
+
55
+ def normalize_attachment
56
+ attachments.each do |attachment|
57
+ Rich::Backends::Paperclip.normalize_attachment(attachment)
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,10 @@
1
+ module Form
2
+ module Static
3
+ class Base < ActiveRecord::Base
4
+ include Form
5
+ include Static
6
+
7
+ self.table_name_prefix = 'form_static_'
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,23 @@
1
+ module Form
2
+ module Static
3
+ module Email
4
+ extend ActiveSupport::Concern
5
+
6
+ def subject
7
+ I18n.t('cms.form.email.default_subject')
8
+ end
9
+
10
+ def send_from
11
+ try(:email)
12
+ end
13
+
14
+ def send_to
15
+ Setting[:cms_mail_bcc]
16
+ end
17
+
18
+ def with_email?
19
+ true
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,12 @@
1
+ module Form
2
+ module Static
3
+ class Object < ActiveType::Object
4
+ include Form
5
+ include Static
6
+
7
+ def self.virtual?
8
+ true
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,90 @@
1
+ module Form
2
+ class Structure < ActiveRecord::Base
3
+ include Admin::Form::Structure
4
+
5
+ self.table_name_prefix = 'form_'
6
+
7
+ has_one :viewable, class_name: 'Viewable::Form'
8
+ has_many :fields, -> { order(:position) }, dependent: :destroy
9
+ has_many :rows, -> { order(:id) }, dependent: :destroy
10
+ belongs_to :email, dependent: :destroy
11
+
12
+ validates :fields, length: { maximum: RailsAdminCMS::Config.custom_form_max_size }
13
+
14
+ after_create :create_header
15
+ after_update :expire_cache
16
+ after_touch :expire_cache
17
+
18
+ accepts_nested_attributes_for :fields, allow_destroy: true
19
+ accepts_nested_attributes_for :email
20
+
21
+ delegate :form_name, to: :viewable
22
+ delegate :with_email?, :send_to, :subject, :body, to: :email
23
+
24
+ def name
25
+ @_name ||= "#{form_name}_#{id}".to_sym
26
+ end
27
+
28
+ def email_column_key
29
+ @email_column_key ||= fields.where(type: 'email').first.try(:column_key)
30
+ end
31
+
32
+ def header
33
+ rows.first
34
+ end
35
+
36
+ private
37
+
38
+ def create_header
39
+ rows.create!
40
+ end
41
+
42
+ def expire_cache
43
+ viewable.touch
44
+ end
45
+
46
+ module Splitter
47
+ extend ActiveSupport::Concern
48
+
49
+ included do
50
+ class << self
51
+ attr_accessor :scopes, :form_name
52
+ end
53
+ self.scopes = []
54
+ self.includes(:viewable).each do |structure|
55
+ current_id = structure.id
56
+ current_name = "#{structure.viewable.form_name}_#{current_id}".to_sym
57
+ ::Form::Row.define_singleton_method(current_name) do
58
+ where(structure_id: current_id)
59
+ end
60
+ self.scopes << current_name
61
+ end
62
+
63
+ after_create :add_to_scopes
64
+ before_destroy :remove_from_scopes
65
+ end
66
+
67
+ private
68
+
69
+ def add_to_scopes
70
+ current_id = self.id
71
+ ::Form::Row.define_singleton_method(name) do
72
+ where(structure_id: current_id)
73
+ end
74
+ self.class.scopes << name
75
+ end
76
+
77
+ def remove_from_scopes
78
+ if (current_name = self.class.form_name)
79
+ current_name = "#{current_name}_#{id}".to_sym
80
+ self.class.form_name = nil
81
+ else
82
+ current_name = name
83
+ end
84
+ self.class.scopes.delete(current_name)
85
+ end
86
+ end
87
+
88
+ include Splitter
89
+ end
90
+ end
@@ -0,0 +1,85 @@
1
+ class Setting < ActiveRecord::Base
2
+ include Admin::Setting
3
+
4
+ has_paper_trail if RailsAdminCMS::Config.with_paper_trail?
5
+
6
+ cattr_accessor :cache
7
+ self.cache = Rails.cache
8
+
9
+ after_commit :expire_cache
10
+
11
+ class << self
12
+ def []=(name, value)
13
+ write(name, value)
14
+
15
+ find_or_create_by!(name: name) do |setting|
16
+ setting.value = value
17
+ end
18
+
19
+ value
20
+ end
21
+
22
+ def [](name)
23
+ if has_key? name
24
+ return read(name)
25
+ end
26
+
27
+ if (setting = find_by(name: name))
28
+ value = setting.value
29
+ else
30
+ value = yield # default value passed as block
31
+ end
32
+
33
+ write(name, value)
34
+
35
+ value
36
+ end
37
+
38
+ def has_key?(name)
39
+ cache.exist? cache_key(name)
40
+ end
41
+
42
+ def expire(name)
43
+ cache.delete cache_key(name)
44
+ end
45
+
46
+ def apply_all(settings = {})
47
+ settings.each do |name, value|
48
+ find_or_create_by!(name: name) do |setting|
49
+ if value.is_a? Array
50
+ setting.value, setting.unit = value
51
+ else
52
+ setting.value = value
53
+ end
54
+ end
55
+ end
56
+ end
57
+
58
+ def remove_all(*settings)
59
+ settings.each do |name|
60
+ find_by(name: name).try(:destroy!)
61
+ expire(name)
62
+ end
63
+ end
64
+
65
+ private
66
+
67
+ def read(name)
68
+ cache.read cache_key(name)
69
+ end
70
+
71
+ def write(name, value)
72
+ cache.write cache_key(name), value
73
+ end
74
+
75
+ def cache_key(name)
76
+ "setting/#{name}"
77
+ end
78
+ end
79
+
80
+ private
81
+
82
+ def expire_cache
83
+ self.class.expire(name)
84
+ end
85
+ end
@@ -0,0 +1,62 @@
1
+ class UniqueKey < ActiveRecord::Base
2
+ include Admin::UniqueKey
3
+
4
+ has_paper_trail if RailsAdminCMS::Config.with_paper_trail?
5
+
6
+ belongs_to :viewable, polymorphic: true
7
+
8
+ before_update ::Callbacks::UniqueKeyBeforeUpdate.new
9
+
10
+ with_options on: :update do
11
+ validates :position, numericality: { greater_than: 0 }
12
+ validates :position, numericality: { less_than_or_equal_to: :list_count }
13
+ end
14
+
15
+ delegate :count, to: :list, prefix: true
16
+
17
+ class << self
18
+ def find_viewable(unique_key)
19
+ (unique_key = find_by(unique_key)) ? unique_key.viewable : nil
20
+ end
21
+
22
+ def find_or_create_viewable!(unique_key)
23
+ unless (viewable = find_viewable(unique_key))
24
+ viewable = create_localized_viewable!(unique_key)
25
+ end
26
+ viewable
27
+ end
28
+
29
+ def create_localized_viewable!(unique_key)
30
+ viewable = nil
31
+ I18n.available_locales.each do |locale|
32
+ attributes = unique_key.merge(locale: locale, viewable: unique_key[:viewable_type].constantize.new)
33
+ new_record = find_or_create_by! attributes
34
+ if I18n.locale == locale
35
+ viewable = new_record.viewable
36
+ end
37
+ end
38
+ viewable.try(:uuid) # forces uuid creation
39
+ viewable
40
+ end
41
+ end
42
+
43
+ def list(locale = nil)
44
+ self.class
45
+ .where(viewable_type: viewable_type, view_path: view_path, name: name)
46
+ .where(locale: locale || self.locale)
47
+ end
48
+
49
+ def other_locales(position = nil)
50
+ self.class
51
+ .where(viewable_type: viewable_type, view_path: view_path, name: name)
52
+ .where(position: position || self.position)
53
+ .where.not(locale: locale)
54
+ end
55
+
56
+ def with_buffered_position(new_position)
57
+ update_column(:position, 0)
58
+ yield
59
+ update_column(:position, new_position)
60
+ viewable.touch
61
+ end
62
+ end