weeler 0.0.4 → 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 (152) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -1
  3. data/.rspec +1 -1
  4. data/.travis.yml +7 -2
  5. data/CHANGELOG.md +149 -1
  6. data/LICENSE.txt +2 -2
  7. data/README.md +83 -1
  8. data/app/.DS_Store +0 -0
  9. data/app/assets/javascripts/weeler/init.js.coffee +13 -2
  10. data/app/assets/javascripts/weeler/lib/notify.js +18 -0
  11. data/app/assets/javascripts/weeler/lib/sortable.js +9 -0
  12. data/app/assets/stylesheets/weeler/init.css.erb +2 -1
  13. data/app/assets/stylesheets/weeler/style.css.scss +22 -0
  14. data/app/controllers/concerns/weeler/section_seo.rb +16 -0
  15. data/app/controllers/weeler/administration_controller.rb +11 -0
  16. data/app/controllers/weeler/application_controller.rb +5 -0
  17. data/app/controllers/weeler/base_controller.rb +16 -12
  18. data/app/controllers/weeler/configuration_controller.rb +9 -0
  19. data/app/controllers/weeler/content_controller.rb +12 -0
  20. data/app/controllers/weeler/home_controller.rb +5 -2
  21. data/app/controllers/weeler/seo_items_controller.rb +24 -0
  22. data/app/controllers/weeler/settings_controller.rb +21 -0
  23. data/app/controllers/weeler/static_sections_controller.rb +19 -0
  24. data/app/controllers/weeler/translations_controller.rb +36 -18
  25. data/app/models/concerns/weeler/seoable.rb +61 -0
  26. data/app/models/concerns/weeler/sluger.rb +32 -0
  27. data/app/models/settings.rb +2 -0
  28. data/app/models/weeler/seo.rb +9 -0
  29. data/app/views/kaminari/{_first_page.html.erb → weeler/_first_page.html.erb} +1 -1
  30. data/app/views/kaminari/{_gap.html.erb → weeler/_gap.html.erb} +1 -1
  31. data/app/views/kaminari/{_last_page.html.erb → weeler/_last_page.html.erb} +1 -1
  32. data/app/views/kaminari/{_next_page.html.erb → weeler/_next_page.html.erb} +1 -1
  33. data/app/views/kaminari/{_page.html.erb → weeler/_page.html.erb} +0 -0
  34. data/app/views/kaminari/{_paginator.html.erb → weeler/_paginator.html.erb} +1 -1
  35. data/app/views/kaminari/{_prev_page.html.erb → weeler/_prev_page.html.erb} +1 -1
  36. data/app/views/layouts/weeler/base.html.haml +22 -0
  37. data/{lib/generators/weeler/templates/views/weeler/example/index.html.erb → app/views/weeler/administration/_filter.html.haml} +0 -0
  38. data/app/views/weeler/administration/_header_row.html.haml +5 -0
  39. data/app/views/weeler/administration/_row.html.haml +5 -0
  40. data/app/views/weeler/administration/_side_navbar.html.haml +8 -0
  41. data/app/views/weeler/administration/index.html.haml +17 -0
  42. data/app/views/weeler/administration/welcome.html.haml +5 -0
  43. data/app/views/weeler/base/_flash.html.haml +3 -0
  44. data/app/views/weeler/base/_footer.html.haml +2 -0
  45. data/app/views/weeler/base/_header_navbar.html.haml +19 -0
  46. data/app/views/weeler/base/_side_navbar.html.haml +2 -0
  47. data/app/views/weeler/configuration/_side_navbar.html.haml +12 -0
  48. data/app/views/weeler/configuration/index.html.haml +3 -0
  49. data/app/views/weeler/content/_error_messages.html.haml +5 -0
  50. data/app/views/weeler/content/_form.html.haml +6 -0
  51. data/app/views/weeler/content/_list.html.haml +23 -0
  52. data/app/views/weeler/content/_object_seo.html.haml +31 -0
  53. data/app/views/weeler/content/_side_navbar.html.haml +17 -0
  54. data/app/views/weeler/content/_sortable_list.html.haml +24 -0
  55. data/app/views/weeler/content/edit.html.haml +2 -0
  56. data/app/views/weeler/content/index.html.haml +10 -0
  57. data/app/views/weeler/content/new.html.haml +2 -0
  58. data/app/views/weeler/content/welcome.html.haml +3 -0
  59. data/app/views/weeler/home/_side_navbar.html.haml +8 -0
  60. data/app/views/weeler/home/about.html.haml +15 -0
  61. data/app/views/weeler/home/index.html.haml +3 -0
  62. data/app/views/weeler/seo_items/edit.html.haml +28 -0
  63. data/app/views/weeler/seo_items/index.html.haml +15 -0
  64. data/app/views/weeler/settings/index.html.haml +19 -0
  65. data/app/views/weeler/static_sections/show.html.haml +26 -0
  66. data/app/views/weeler/translations/_form.html.haml +27 -0
  67. data/app/views/weeler/translations/_translation.html.haml +11 -0
  68. data/app/views/weeler/translations/edit.html.haml +14 -0
  69. data/app/views/weeler/translations/index.html.haml +76 -0
  70. data/app/views/weeler/translations/new.html.haml +13 -0
  71. data/lib/.DS_Store +0 -0
  72. data/lib/generators/weeler/.DS_Store +0 -0
  73. data/lib/generators/weeler/install_generator.rb +30 -26
  74. data/lib/generators/weeler/templates/assets/javascripts/weeler/app/index.js +2 -0
  75. data/lib/generators/weeler/templates/assets/stylesheets/weeler/app/index.css +4 -0
  76. data/lib/generators/weeler/templates/controllers/weeler/application_controller.rb +6 -0
  77. data/lib/generators/weeler/templates/initializers/weeler.rb +30 -2
  78. data/lib/generators/weeler/templates/migrations/create_weeler_seos.rb +14 -0
  79. data/lib/generators/weeler/templates/migrations/create_weeler_settings.rb +17 -0
  80. data/lib/generators/weeler/templates/migrations/translate_weeler_seos.rb +15 -0
  81. data/lib/generators/weeler/templates/views/weeler/.keep +0 -0
  82. data/lib/i18n/backend/weeler.rb +102 -22
  83. data/lib/i18n/backend/weeler/dedupe.rb +31 -0
  84. data/lib/i18n/backend/weeler/exporter.rb +67 -5
  85. data/lib/i18n/backend/weeler/html_checker.rb +41 -0
  86. data/lib/i18n/backend/weeler/importer.rb +30 -13
  87. data/lib/i18n/backend/weeler/translation.rb +12 -7
  88. data/lib/i18n/humanize_missing_translations.rb +1 -0
  89. data/lib/i18n/weeler.rb +8 -2
  90. data/lib/tasks/weeler.rake +8 -0
  91. data/lib/weeler.rb +80 -7
  92. data/lib/weeler/.DS_Store +0 -0
  93. data/lib/weeler/action_controller/acts/restful.rb +185 -0
  94. data/lib/weeler/action_dispatch/routing/mapper.rb +87 -0
  95. data/lib/weeler/action_view/helpers/form_helper.rb +13 -0
  96. data/lib/weeler/action_view/helpers/image_form_helper.rb +84 -0
  97. data/lib/weeler/action_view/helpers/translation_helper.rb +15 -0
  98. data/lib/weeler/deprecator.rb +9 -0
  99. data/lib/weeler/engine.rb +18 -4
  100. data/lib/weeler/version.rb +7 -1
  101. data/rspec.html +426 -147
  102. data/spec/.DS_Store +0 -0
  103. data/spec/controllers/translations_controller_spec.rb +76 -5
  104. data/spec/dummy/app/controllers/weeler/posts_controller.rb +3 -7
  105. data/spec/dummy/app/models/post.rb +17 -0
  106. data/spec/dummy/app/models/translation.rb +2 -0
  107. data/spec/dummy/config/locales/en.yml +4 -1
  108. data/spec/dummy/config/routes.rb +3 -3
  109. data/spec/dummy/db/development.sqlite3 +0 -0
  110. data/spec/dummy/db/migrate/20140123083704_create_weeler_seos.rb +14 -0
  111. data/spec/dummy/db/migrate/20140123083705_create_weeler_settings.rb +17 -0
  112. data/spec/dummy/db/migrate/{20131015144900_create_weeler_translations.rb → 20140123083706_create_weeler_translations.rb} +0 -0
  113. data/spec/dummy/db/migrate/20140123083707_translate_weeler_seos.rb +15 -0
  114. data/spec/dummy/db/migrate/20140718103237_create_posts.rb +12 -0
  115. data/spec/dummy/db/migrate/20140726151210_create_translations.rb +12 -0
  116. data/spec/dummy/db/schema.rb +59 -1
  117. data/spec/dummy/db/test.sqlite3 +0 -0
  118. data/spec/dummy/log/development.log +221 -0
  119. data/spec/factories/dummy_posts.rb +6 -0
  120. data/spec/fixtures/.DS_Store +0 -0
  121. data/spec/routing/routes_spec.rb +4 -4
  122. data/spec/spec_helper.rb +14 -3
  123. data/spec/weeler/action_controller/acts/restful_spec.rb +155 -0
  124. data/spec/weeler/action_view/helpers/form_helper_spec.rb +26 -0
  125. data/spec/weeler/action_view/helpers/translation_helper_spec.rb +16 -0
  126. data/spec/weeler/i18n/backend/weeler/dedupe_spec.rb +21 -0
  127. data/spec/weeler/i18n/backend/weeler/exporter_spec.rb +2 -4
  128. data/spec/weeler/i18n/backend/weeler/importer_spec.rb +5 -2
  129. data/spec/weeler/i18n/backend/weeler_spec.rb +121 -23
  130. data/weeler.gemspec +15 -7
  131. metadata +207 -85
  132. data/.DS_Store +0 -0
  133. data/app/assets/stylesheets/weeler/vendor/bootstrap.css +0 -6086
  134. data/app/views/layouts/weeler/base.html.erb +0 -40
  135. data/app/views/weeler/home/about.html.erb +0 -16
  136. data/app/views/weeler/home/index.html.erb +0 -4
  137. data/app/views/weeler/shared/_flash.html.erb +0 -17
  138. data/app/views/weeler/shared/_footer.html.erb +0 -3
  139. data/app/views/weeler/shared/_header_navbar.html.erb +0 -18
  140. data/app/views/weeler/shared/_side_navbar.html.erb +0 -14
  141. data/app/views/weeler/translations/_form.html.erb +0 -43
  142. data/app/views/weeler/translations/_translation.html.erb +0 -11
  143. data/app/views/weeler/translations/edit.html.erb +0 -19
  144. data/app/views/weeler/translations/index.html.erb +0 -103
  145. data/app/views/weeler/translations/new.html.erb +0 -19
  146. data/lib/generators/weeler/templates/controllers/weeler/example_controller.rb.example +0 -7
  147. data/lib/i18n/backend/weeler/exporter/active_record.rb +0 -37
  148. data/lib/i18n/backend/weeler/exporter/active_record_relation.rb +0 -38
  149. data/lib/i18n/backend/weeler/store_procs.rb +0 -39
  150. data/lib/weeler/route_mapper.rb +0 -41
  151. data/spec/dummy/db/production.sqlite3 +0 -0
  152. data/spec/dummy/log/test.log +0 -88454
@@ -0,0 +1,41 @@
1
+ # This module is intended to be mixed into the Weeler backend to allow
2
+ # checks if translation is html
3
+ #
4
+ # I18n.backend = I18n::Backend::Weeler.new
5
+ # I18n::Backend::Weeler::Translation.send(:include, I18n::Backend::Weeler::HtmlChecker)
6
+ #
7
+ # The HtmlChecker module requires html-scanner
8
+ # was extracted from the original backend.
9
+
10
+ begin
11
+ require 'action_view/vendor/html-scanner'
12
+ rescue LoadError => e
13
+ puts "can't use Html because: #{e.message}"
14
+ end
15
+
16
+ module I18n
17
+ module Backend
18
+ class Weeler
19
+ module HtmlChecker
20
+
21
+ def html?
22
+ if html_safe_translation_key?(self.key) ||
23
+ (self.value.present? && HTML::FullSanitizer.new.sanitize(self.value.to_s).length != self.value.to_s.length)
24
+ return true
25
+ else
26
+ return false
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ def html_safe_translation_key?(key)
33
+ key.to_s =~ /(\b|_|\.)html$/
34
+ end
35
+
36
+ Translation.send(:include, HtmlChecker)
37
+ end
38
+ end
39
+ end
40
+ end
41
+
@@ -1,3 +1,13 @@
1
+ # Weeler I18n backend import helper module.
2
+ #
3
+ # Loads file translations into datebase.
4
+ # Supports: csv, xls, xlsx or ods
5
+ #
6
+ # if params[:file].present?
7
+ # I18n::Backend::Weeler::Translation.import params[:file]
8
+ # Settings.i18n_updated_at = Time.now
9
+ # end
10
+
1
11
  begin
2
12
  require 'roo'
3
13
  rescue LoadError => e
@@ -9,27 +19,21 @@ module I18n
9
19
  class Weeler
10
20
 
11
21
  module Importer
12
-
13
22
  extend ActiveSupport::Concern
14
23
 
15
24
  module ClassMethods
16
25
 
17
-
18
-
19
- def import path
20
-
21
- xls = Roo::Excelx.new(path, file_warning: :ignore)
22
-
26
+ # Loads file and iterates each sheet and row.
27
+ def import file
28
+ xls = open_spreadsheet file
23
29
  xls.each_with_pagename do |name, sheet|
24
-
30
+
25
31
  # Lookup locales
26
32
  locales = locales_from_xlsx_sheet_row(sheet.row(1))
27
33
 
28
34
  # Lookup values
29
35
  (2..sheet.last_row).each do |row_no|
30
-
31
36
  store_translations_from_xlsx_row(sheet.row(row_no), locales)
32
-
33
37
  end # rows
34
38
 
35
39
  end # sheets
@@ -38,6 +42,18 @@ module I18n
38
42
 
39
43
  private
40
44
 
45
+ # Open csv, xls, xlsx or ods file and read content
46
+ def open_spreadsheet(file)
47
+ case File.extname(file.original_filename)
48
+ when ".csv" then Roo::Csv.new(file.path, file_warning: :ignore)
49
+ when ".xls" then Roo::Excel.new(file.path, file_warning: :ignore)
50
+ when ".xlsx" then Roo::Excelx.new(file.path, file_warning: :ignore)
51
+ when ".ods" then Roo::OpenOffice.new(file.path, file_warning: :ignore)
52
+ else raise "Unknown file type: #{file.original_filename}"
53
+ end
54
+ end
55
+
56
+ # Lookup locales and sequence for loading
41
57
  def locales_from_xlsx_sheet_row row
42
58
  locales = []
43
59
  row.each_with_index do |cell, i|
@@ -48,11 +64,12 @@ module I18n
48
64
  locales
49
65
  end
50
66
 
67
+ # Iterate each cell in row and store translation by locale
51
68
  def store_translations_from_xlsx_row row, locales
52
69
  locale = nil
53
70
  key = nil
54
71
  value = nil
55
-
72
+
56
73
  row.each_with_index do |cell, i|
57
74
  if i == 0
58
75
  key = cell
@@ -63,9 +80,9 @@ module I18n
63
80
  end
64
81
  end
65
82
 
83
+ # Store locale if locale and key present
66
84
  def store_translation_from_xlsx_cell locale, key, cell
67
85
  value = cell.nil? ? '' : cell
68
- # value = cell
69
86
 
70
87
  if locale.present? && key.present?
71
88
  translation = Translation.find_or_initialize_by locale: locale, key: key
@@ -82,4 +99,4 @@ module I18n
82
99
  Translation.send(:include, Importer)
83
100
  end
84
101
  end
85
- end
102
+ end
@@ -54,6 +54,11 @@ module I18n
54
54
  serialize :value
55
55
  serialize :interpolations, Array
56
56
 
57
+ scope :except_key, -> (key) { where("key NOT LIKE ?", "#{key}%") }
58
+
59
+ validates :key, :uniqueness => { :scope => :locale }
60
+ validates :key, presence: true
61
+
57
62
  class << self
58
63
 
59
64
  def locale(locale)
@@ -73,15 +78,15 @@ module I18n
73
78
  where("#{column_name} IN (?) OR #{column_name} LIKE ?", keys, namespace)
74
79
  end
75
80
 
76
- def available_locales
77
- Translation.select("DISTINCT locale").map { |t| t.locale.to_sym }
78
- end
79
81
 
80
- # This problably works only with PG
81
82
  def groups
82
- # Translation.select("DISTINCT split_part(key, '.', 1), split_part(key, '.', 1) AS key_group").order("key_group").map { |t| t.key_group.to_sym }
83
- groups_records = Translation.select("key").order("key").map{ |t| t.key.split(".")[0] }.uniq{ |t| t}
84
- groups_records.uniq{ |t| t }
83
+ groups_records = Translation.select("key")
84
+
85
+ ::Weeler.excluded_i18n_groups.each do |key|
86
+ groups_records = groups_records.except_key(key)
87
+ end
88
+ groups_records = groups_records.order("key")
89
+ groups_records.map{ |t| t.key.split(".")[0] }.uniq{ |t| t}
85
90
  end
86
91
  end
87
92
 
@@ -1,4 +1,5 @@
1
1
  module I18n
2
+ # Show only last part from key in humanize mode
2
3
  module HumanizeMissingTranslations
3
4
  def call(exception, locale, key, options)
4
5
  if exception.is_a?(I18n::MissingTranslation)
data/lib/i18n/weeler.rb CHANGED
@@ -1,6 +1,12 @@
1
1
  require 'i18n'
2
+
2
3
  require 'i18n/humanize_missing_translations'
4
+ I18n.exception_handler.extend I18n::HumanizeMissingTranslations
5
+
3
6
  require 'i18n/backend/weeler'
7
+ weeler_i18n_backend = I18n::Backend::Weeler.new
8
+ weeler_i18n_backend.i18n_cache = Weeler.i18n_cache
9
+ I18n.backend = I18n::Backend::Chain.new(weeler_i18n_backend, I18n::Backend::Simple.new)
4
10
 
5
- I18n.exception_handler.extend I18n::HumanizeMissingTranslations
6
- I18n.backend = I18n::Backend::Chain.new(I18n::Backend::Weeler.new, I18n::Backend::Simple.new)
11
+ logger = Logger.new(STDOUT)
12
+ logger.info "Weeler i18n backend loaded"
@@ -0,0 +1,8 @@
1
+ namespace :weeler do
2
+ namespace :translations do
3
+ desc "Remove all weeler i18n translation dublicates"
4
+ task dedupe: :environment do
5
+ I18n::Backend::Weeler::Translation.dedupe
6
+ end
7
+ end
8
+ end
data/lib/weeler.rb CHANGED
@@ -1,10 +1,25 @@
1
1
  require "weeler/version"
2
+ require "weeler/deprecator"
3
+
4
+ require 'logger'
2
5
  require "rails"
3
- require "weeler/route_mapper"
6
+
4
7
  require "weeler/engine"
8
+
9
+ # 3rd party
10
+ require "haml"
5
11
  require "kaminari"
12
+ require "globalize"
13
+ require "jquery-ui-rails"
14
+ require "rails-settings-cached"
6
15
 
7
16
  module Weeler
17
+ #
18
+ # => Static sections in content menu bottom
19
+ # => [{about: [{title: :text_field, content: :text_area}]}]
20
+ #
21
+ mattr_accessor :static_sections
22
+ @@static_sections = {}
8
23
 
9
24
  mattr_accessor :create_missing_translations
10
25
  @@create_missing_translations = true
@@ -12,18 +27,76 @@ module Weeler
12
27
  mattr_accessor :use_weeler_i18n
13
28
  @@use_weeler_i18n = true
14
29
 
15
- mattr_accessor :menu_items
16
- @@menu_items = []
17
-
18
30
  mattr_accessor :required_user_method
19
31
  @@required_user_method = nil
20
32
 
33
+ mattr_accessor :logout_path
34
+ @@logout_path = nil
35
+
36
+ # Rafacture this to one menu module
37
+ mattr_accessor :content_menu_items
38
+ @@content_menu_items = []
39
+
40
+ # Rafacture this to one menu module
41
+ mattr_accessor :static_menu_items
42
+ @@static_menu_items = []
43
+
44
+ # Rafacture this to one menu module
45
+ mattr_accessor :administration_menu_items
46
+ @@administration_menu_items = []
47
+
48
+ # Rafacture this to one menu module
49
+ mattr_accessor :configuration_menu_items
50
+ @@configuration_menu_items = []
51
+
52
+ # Rafacture this to one menu module
53
+ mattr_accessor :main_menu_items
54
+ @@main_menu_items = []
55
+
56
+ mattr_accessor :excluded_i18n_groups
57
+ @@excluded_i18n_groups = [:activerecord, :attributes, :helpers, :views, :i18n, :weeler]
58
+
59
+ mattr_accessor :i18n_cache
60
+ @@i18n_cache = ActiveSupport::Cache::MemoryStore.new
61
+
62
+ mattr_accessor :mount_location_namespace
63
+ @@mount_location_namespace = "weeler"
64
+
21
65
  def self.setup
22
- if Weeler.use_weeler_i18n
66
+ yield self
67
+ if Weeler.use_weeler_i18n == true && ActiveRecord::Base.connection.table_exists?('weeler_translations')
23
68
  require "i18n/weeler"
69
+ Weeler.static_sections.each do |key, section|
70
+ Weeler.static_menu_items << {name: key.to_s.capitalize, weeler_path: "static_sections/#{key}"}
71
+ end
24
72
  end
73
+ build_main_menu
74
+ end
25
75
 
26
- yield self
76
+ def self.build_main_menu
77
+ home_menu_item = {name: "Home", weeler_path: ""}
78
+ content_menu_item = {name: "Content", weeler_path: "content"}
79
+ administration_menu_item = {name: "Administration", weeler_path: "administration"}
80
+ configuration_menu_item = {name: "Configuration", weeler_path: "configuration"}
81
+
82
+ Weeler.main_menu_items.delete(home_menu_item)
83
+ Weeler.main_menu_items.delete(content_menu_item)
84
+ Weeler.main_menu_items.delete(administration_menu_item)
85
+ Weeler.main_menu_items.delete(configuration_menu_item)
86
+
87
+
88
+ Weeler.main_menu_items.insert(0, {name: "Home", weeler_path: ""}) unless Weeler.main_menu_items.include?(home_menu_item)
89
+
90
+ if (Weeler.content_menu_items.size > 0 || Weeler.static_menu_items.size > 0) && !Weeler.main_menu_items.include?(content_menu_item)
91
+ Weeler.main_menu_items.insert(1, {name: "Content", weeler_path: "content"})
92
+ end
93
+
94
+ Weeler.main_menu_items.insert(2, administration_menu_item) if Weeler.administration_menu_items.size > 0 && !Weeler.main_menu_items.include?(administration_menu_item)
95
+ Weeler.main_menu_items.push(configuration_menu_item) unless Weeler.main_menu_items.include?(configuration_menu_item)
96
+ Weeler.main_menu_items = Weeler.main_menu_items.compact
27
97
  end
28
- end
29
98
 
99
+ def self.translations
100
+ I18n::Backend::Weeler::Translation if Weeler.use_weeler_i18n == true
101
+ end
102
+ end
data/lib/weeler/.DS_Store CHANGED
Binary file
@@ -0,0 +1,185 @@
1
+ module Weeler
2
+ module ActionController
3
+ module Acts
4
+ module Restful
5
+ extend ActiveSupport::Concern
6
+
7
+ module ClassMethods
8
+ # Weeler action controller method.
9
+ # It creates all restful actions for action controller. Create a controller for your
10
+ # model (e.g. Post) what you want to administrate in weeler. Add method <tt>acts_as_restful Post</tt>
11
+ # and permit params for your resource - option <tt>permit_params</tt>. Also you can paginate - add
12
+ # option <tt>paginate</tt>
13
+ # e.g.
14
+ #
15
+ # class Weeler::PostController < Weeler::ContentController
16
+ # acts_as_restful Post, permit_params: [:title, :body], paginate: 50
17
+ # end
18
+ #
19
+ # It will handle <tt>:index</tt>, <tt>:new</tt>, <tt>:edit</tt>, <tt>:update</tt>,
20
+ # <tt>:destroy</tt>, <tt>:order</tt>, <tt>:activation</tt> and <tt>:remove_image</tt> actions
21
+ #
22
+ # For permiting custom by role or permiting all params (permit!),
23
+ # you must add block <tt>permit_params: -> (params) { params.require(:post).permit! }</tt>
24
+ #
25
+ # You should implement form file with your own active record attributes.
26
+ # To do that, create <tt>_form.html.haml</tt> in <tt>views/weeler/_YOUR_RESOURCE_/_form.html.haml</tt>
27
+ # where <tt>_YOUR_RESOURCE_</tt> is name of your resource.
28
+ #
29
+ # Also you can override all standart restful action view and implement, if you need,
30
+ # <tt>_filter.html.haml</tt>
31
+ #
32
+ def acts_as_restful(active_record_model, options = {})
33
+ before_filter(:load_record, only: [:show, :edit, :update, :destroy, :remove_image])
34
+
35
+ include InstanceMethodsOnActivation
36
+ helper_method :item_humanized_name
37
+
38
+ cattr_accessor :model do
39
+ active_record_model
40
+ end
41
+
42
+ cattr_accessor :permited_params do
43
+ options[:permit_params] if options.include? :permit_params
44
+ end
45
+
46
+ cattr_accessor :paginate do
47
+ options[:paginate] if options.include? :paginate
48
+ end
49
+
50
+ cattr_accessor :order_by do
51
+ options[:order_by] if options.include? :order_by
52
+ end
53
+ end
54
+ end
55
+
56
+ # These methods only activate if 'acts_as_restful' is called
57
+ #
58
+ module InstanceMethodsOnActivation
59
+
60
+ def index
61
+ @paginate = paginate
62
+ @items = load_collection
63
+ @items = @items.page(params[:page]).per(@paginate) if @paginate.present? && @paginate > 0
64
+ end
65
+
66
+ def new
67
+ @item = model.new
68
+ load_translations
69
+ end
70
+
71
+ def show
72
+ render :edit
73
+ end
74
+
75
+ def edit
76
+ load_translations
77
+ end
78
+
79
+ def order
80
+ sort
81
+ end
82
+
83
+ def create
84
+ @item = model.new(items_params)
85
+ if @item.save
86
+ redirect_to({ action: :edit, id: @item.id }, {:notice => "Successfully created item"})
87
+ else
88
+ render :action => 'new'
89
+ end
90
+ end
91
+
92
+ def update
93
+ if @item.update_attributes(items_params)
94
+ redirect_to({ action: :edit, id: @item.id }, {:notice => "Successfully updated item"})
95
+ else
96
+ render :action => 'edit'
97
+ end
98
+ end
99
+
100
+ def destroy
101
+ @item.destroy
102
+ redirect_to({ action: :index}, {:notice => "Successfully destroyed item"})
103
+ end
104
+
105
+ def remove_image
106
+ if @item.image.present?
107
+ @item.image.destroy
108
+ @item.image_file_name = nil
109
+ @item.save
110
+ end
111
+ redirect_to({ action: :edit, id: @item.id}, {:notice => "Image successfully removed"})
112
+ end
113
+
114
+ protected
115
+
116
+ def items_params
117
+ if permited_params.is_a? Proc
118
+ permited_params.call(params)
119
+ elsif permited_params.blank?
120
+ warning_suggestion = params[parameterized_name.to_sym].is_a?(Hash) ? params[parameterized_name.to_sym].keys.map{ |k| k.to_sym } : "permit_params:"
121
+ warn "[UNPERMITED PARAMS] To permiting #{params[parameterized_name.to_sym].inspect} params, add 'permit_params: #{warning_suggestion}' option to 'acts_as_restful'"
122
+ else
123
+ params.require(parameterized_name.to_sym).permit(permited_params)
124
+ end
125
+ end
126
+
127
+ def collection; end
128
+
129
+ def parameterized_name
130
+ "#{model.to_s.underscore.downcase}"
131
+ end
132
+
133
+ def item_humanized_name
134
+ "#{parameterized_name.humanize}"
135
+ end
136
+
137
+ def load_translations
138
+ if @item.respond_to? :translations
139
+ I18n.available_locales.each { |locale| @item.translations.find_or_initialize_by(locale: locale) }
140
+ end
141
+ end
142
+
143
+ private
144
+
145
+ def model
146
+ model
147
+ end
148
+
149
+ def load_collection
150
+ return @load_collection if @load_collection.present?
151
+ if model
152
+ if collection
153
+ @load_collection = collection
154
+ else
155
+ @load_collection = model.all
156
+ if order_by.present?
157
+ @load_collection.order(order_by)
158
+ elsif model.new.has_attribute?(:sequence)
159
+ @load_collection.order(:sequence)
160
+ else
161
+ @load_collection.order(created_at: :desc)
162
+ end
163
+ end
164
+ end
165
+ end
166
+
167
+ def load_record
168
+ @item = model.find(params[:id])
169
+ end
170
+
171
+ def sort
172
+ items_sequence = URI.decode_www_form(params[:orders]).map{ |i| i[1] }
173
+ items_sequence.each_with_index do |sequence_item_id, index|
174
+ item = model.find_by id: sequence_item_id
175
+ item.sequence = index
176
+ item.save!
177
+ end
178
+ render :text => 'all ok'
179
+ end
180
+
181
+ end # Instance methods
182
+ end
183
+ end
184
+ end
185
+ end