ab_admin 0.8.3 → 0.9.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 (114) hide show
  1. checksums.yaml +4 -4
  2. data/MIT-LICENSE +1 -1
  3. data/README.md +11 -5
  4. data/app/assets/javascripts/ab_admin/components/admin_assets.js.coffee +0 -25
  5. data/app/assets/javascripts/ab_admin/components/google_translate.js.coffee +3 -5
  6. data/app/assets/javascripts/ab_admin/components/in_place_edit.js.coffee +5 -1
  7. data/app/assets/javascripts/ab_admin/core/columns_hider.js.coffee +24 -23
  8. data/app/assets/javascripts/ab_admin/core/init.js.coffee +6 -2
  9. data/app/assets/javascripts/ab_admin/core/search_form.js.coffee +1 -7
  10. data/app/assets/javascripts/ab_admin/core/ui_utils.js.coffee +2 -6
  11. data/app/assets/javascripts/ab_admin/core/utils.js.coffee +8 -2
  12. data/app/assets/javascripts/ab_admin/main.js +2 -2
  13. data/app/assets/stylesheets/ab_admin/bootstrap_and_overrides.scss +35 -10
  14. data/app/assets/stylesheets/ab_admin/components/_base.scss +21 -1
  15. data/app/assets/stylesheets/ab_admin/components/_form.scss +13 -17
  16. data/app/assets/stylesheets/ab_admin/components/_grid_view.scss +2 -2
  17. data/app/assets/stylesheets/ab_admin/components/_locale_tabs.scss +11 -23
  18. data/app/assets/stylesheets/ab_admin/components/_navigation.scss +0 -9
  19. data/app/assets/stylesheets/ab_admin/components/_table_view.scss +10 -2
  20. data/app/assets/stylesheets/ab_admin/components/_tooltip.scss +80 -0
  21. data/app/assets/stylesheets/ab_admin/components/_tree_view.scss +1 -1
  22. data/app/assets/stylesheets/ab_admin/devise.scss +2 -2
  23. data/app/assets/stylesheets/ab_admin/fileupload.scss +2 -9
  24. data/app/assets/stylesheets/ab_admin/main.scss +0 -1
  25. data/app/controllers/admin/base_controller.rb +67 -63
  26. data/app/controllers/admin/dashboards_controller.rb +2 -2
  27. data/app/controllers/admin/locators_controller.rb +8 -6
  28. data/app/controllers/admin/manager_controller.rb +2 -2
  29. data/app/controllers/admin/static_pages_controller.rb +0 -4
  30. data/app/controllers/admin/structures_controller.rb +2 -2
  31. data/app/views/admin/assets/batch_edit.html.slim +1 -1
  32. data/app/views/admin/base/_search_layout.html.slim +6 -5
  33. data/app/views/admin/base/create.js.erb +5 -2
  34. data/app/views/admin/base/index.html.slim +4 -4
  35. data/app/views/admin/base/update.js.erb +5 -0
  36. data/app/views/admin/fileupload/_asset_templates.html.slim +1 -2
  37. data/app/views/admin/fileupload/_image.html.slim +1 -2
  38. data/app/views/admin/locators/edit.html.slim +7 -6
  39. data/app/views/admin/manager/_map.html.slim +4 -0
  40. data/app/views/admin/manager/_table.html.slim +1 -1
  41. data/app/views/admin/shared/_content_actions.html.slim +19 -21
  42. data/app/views/admin/shared/_flash.html.slim +5 -4
  43. data/app/views/admin/shared/_locale_tabs.html.slim +2 -2
  44. data/app/views/admin/shared/_main_menu.html.slim +1 -1
  45. data/app/views/admin/structures/_form.html.slim +1 -1
  46. data/app/views/admin/users/_form.html.slim +1 -1
  47. data/app/views/admin/users/_search_form.html.slim +1 -1
  48. data/app/views/layouts/admin/_footer.html.slim +0 -1
  49. data/app/views/layouts/admin/_navigation.html.slim +1 -1
  50. data/app/views/layouts/admin/application.html.slim +2 -2
  51. data/config/locales/de.yml +1 -2
  52. data/config/locales/en.yml +1 -2
  53. data/config/locales/ru.yml +0 -1
  54. data/config/locales/uk.yml +0 -1
  55. data/lib/ab_admin.rb +34 -33
  56. data/lib/ab_admin/abstract_resource.rb +1 -1
  57. data/lib/ab_admin/carrierwave/base_uploader.rb +1 -2
  58. data/lib/ab_admin/concerns/admin_addition.rb +0 -30
  59. data/lib/ab_admin/concerns/translations_macro.rb +97 -0
  60. data/lib/ab_admin/concerns/utilities.rb +1 -1
  61. data/lib/ab_admin/config/base.rb +7 -0
  62. data/lib/ab_admin/controllers/callbacks.rb +3 -26
  63. data/lib/ab_admin/core_ext/array.rb +4 -48
  64. data/lib/ab_admin/core_ext/hash.rb +2 -31
  65. data/lib/ab_admin/core_ext/other.rb +0 -6
  66. data/lib/ab_admin/core_ext/string.rb +0 -80
  67. data/lib/ab_admin/engine.rb +1 -0
  68. data/lib/ab_admin/hooks/will_paginate_id_prefetch.rb +8 -6
  69. data/lib/ab_admin/hooks/will_paginate_no_uri.rb +1 -1
  70. data/lib/ab_admin/i18n_tools/google_translate.rb +3 -1
  71. data/lib/ab_admin/i18n_tools/model_translator.rb +1 -1
  72. data/lib/ab_admin/models/header.rb +2 -2
  73. data/lib/ab_admin/models/locator.rb +28 -2
  74. data/lib/ab_admin/models/user.rb +12 -48
  75. data/lib/ab_admin/utils/csv_document.rb +5 -3
  76. data/lib/ab_admin/utils/eval_helpers.rb +6 -3
  77. data/lib/ab_admin/utils/xls_document.rb +18 -16
  78. data/lib/ab_admin/version.rb +1 -1
  79. data/lib/ab_admin/views/admin_helpers.rb +10 -12
  80. data/lib/ab_admin/views/admin_navigation_helpers.rb +7 -8
  81. data/lib/ab_admin/views/form_builder.rb +7 -5
  82. data/lib/ab_admin/views/helpers.rb +0 -9
  83. data/lib/ab_admin/views/inputs/ckeditor_input.rb +4 -4
  84. data/lib/ab_admin/views/manager_helpers.rb +8 -5
  85. data/lib/ab_admin/views/search_form_builder.rb +2 -2
  86. data/lib/ab_admin/views/will_paginate_bootstrap_renderer.rb +60 -0
  87. data/lib/generators/ab_admin/glob/glob_generator.rb +4 -5
  88. data/lib/generators/ab_admin/glob/templates/migration.erb +10 -7
  89. data/lib/generators/ab_admin/install/templates/config/ab_admin.rb.erb +1 -1
  90. data/lib/generators/ab_admin/install/templates/models/user.rb +0 -11
  91. data/lib/generators/ab_admin/install/templates/spec/spec_helper.rb +0 -1
  92. data/lib/generators/ab_admin/install/templates/spec/support/database_cleaner.rb +8 -11
  93. data/lib/generators/ab_admin/model/model_generator.rb +3 -4
  94. data/lib/generators/ab_admin/model/templates/resource.erb +5 -2
  95. data/lib/generators/ab_admin/resource/templates/controller.erb +2 -2
  96. metadata +37 -79
  97. data/app/assets/images/admin/Jcrop.gif +0 -0
  98. data/app/assets/images/admin/flags/de.png +0 -0
  99. data/app/assets/images/admin/flags/en.png +0 -0
  100. data/app/assets/images/admin/flags/es.png +0 -0
  101. data/app/assets/images/admin/flags/fr.png +0 -0
  102. data/app/assets/images/admin/flags/it.png +0 -0
  103. data/app/assets/images/admin/flags/ja.png +0 -0
  104. data/app/assets/images/admin/flags/pl.png +0 -0
  105. data/app/assets/images/admin/flags/ru.png +0 -0
  106. data/app/assets/images/admin/flags/uk.png +0 -0
  107. data/app/assets/javascripts/ab_admin/components/croppable_image.js.coffee +0 -33
  108. data/app/assets/stylesheets/ab_admin/components/_columns_hider.scss +0 -5
  109. data/app/assets/stylesheets/ab_admin/components/_perms.scss +0 -39
  110. data/app/views/admin/shared/_columns_hider.html.slim +0 -9
  111. data/lib/ab_admin/hooks/globalize_locale_suffix_accessors.rb +0 -25
  112. data/lib/ab_admin/hooks/globalize_valid_locale.rb +0 -9
  113. data/lib/generators/ab_admin/ckeditor_assets/ckeditor_assets_generator.rb +0 -19
  114. data/lib/generators/template.rb +0 -96
@@ -1,5 +1,4 @@
1
1
  class Hash
2
-
3
2
  def reverse_deep_merge!(other_hash)
4
3
  other_hash.each_pair do |k, v|
5
4
  tv = self[k]
@@ -68,29 +67,13 @@ class Hash
68
67
  end
69
68
  end
70
69
 
71
- def val(*array)
72
- if array.empty?
73
- self
74
- else
75
- key = array.shift
76
- value = self[key]
77
- if array.empty?
78
- value
79
- elsif value.is_a? Hash
80
- value.val(*array)
81
- else
82
- nil
83
- end
84
- end
85
- end
86
-
87
- def store_multi(value, *keys)
70
+ def dig_store(value, *keys)
88
71
  key = keys.shift
89
72
  self[key] ||= {}
90
73
  if keys.empty?
91
74
  self[key] = value
92
75
  else
93
- self[key] = self[key].store_multi(value, *keys)
76
+ self[key] = self[key].dig_store(value, *keys)
94
77
  end
95
78
  self
96
79
  end
@@ -107,18 +90,6 @@ class Hash
107
90
  reject { |_, v| v.blank? }
108
91
  end
109
92
 
110
- def no_blank
111
- ActiveSupport::Deprecation.warn('`no_blank` is deprecated, use `reject_blank` instead')
112
- reject_blank
113
- end
114
-
115
- def try_keys(*try_keys)
116
- try_keys.each do |k|
117
- return self[k] if self.has_key?(k)
118
- end
119
- default
120
- end
121
-
122
93
  def deep_stringify_keys
123
94
  inject({}) { |result, (key, value)|
124
95
  value = value.deep_stringify_keys if value.is_a?(Hash)
@@ -1,9 +1,3 @@
1
- class NilClass
2
- def val(*args)
3
- self
4
- end
5
- end
6
-
7
1
  class TrueClass
8
2
  def to_i
9
3
  1
@@ -1,41 +1,4 @@
1
1
  class String
2
- # http://lucene.apache.org/core/old_versioned_docs/versions/2_9_1/queryparsersyntax.html
3
- #LUCENE_ESCAPE_REGEX = /(\+|-|&&|\|\||!|\(|\)|{|}|\[|\]|`|"|~|\?|:|\\|\/)/
4
- #LUCENE_ESCAPE_REGEX = /(\+|-|&&|\|\||!|\(|\)|{|}|\[|\]|`|"|~|\?|:|\\|\s)/
5
-
6
- KEYBOARDS = {
7
- en: 'qwertyuiop[]asdfghjkl;\'zxcvbnm,./',
8
- ru: 'йцукенгшщзхъфывапролджэячсмитьбю/'
9
- }
10
-
11
- unless defined? LUCENE_ESCAPE_REGEX
12
- LUCENE_ESCAPE_REGEX = /(\+|-|&&|\|\||!|\(|\)|{|}|\[|\]|\^|"|~|\*|\?|:|\\|\/)/
13
-
14
- def lucene_escape
15
- self.gsub(LUCENE_ESCAPE_REGEX, "\\\\\\1")
16
- end
17
- end
18
-
19
- def capitalize_first
20
- self.mb_chars[0].capitalize + self.mb_chars[1..-1]
21
- end
22
-
23
- def is_int?
24
- self =~ /^[-+]?[0-9]+$/
25
- end
26
-
27
- def is_number?
28
- self =~ /^[-+]?[0-9]+(\.[0-9]+)?$/
29
- end
30
-
31
- def to_utc
32
- begin
33
- Time.zone.parse(self).utc
34
- rescue
35
- Time.now.utc
36
- end
37
- end
38
-
39
2
  def no_html
40
3
  str = self.dup
41
4
  str.gsub!(/<br\/?>/, ' ')
@@ -44,49 +7,6 @@ class String
44
7
  str.gsub!('&nbsp;', ' ')
45
8
  str
46
9
  end
47
-
48
- def tr_lang(from=nil, to=nil)
49
- return '' if self.blank?
50
-
51
- unless from || to
52
- if KEYBOARDS[:en].index(self[0])
53
- from, to = :en, :ru
54
- elsif KEYBOARDS[:ru].index(self[0])
55
- from, to = :ru, :en
56
- else
57
- from, to = :en, :ru
58
- end
59
- end
60
-
61
- self.tr(KEYBOARDS[from], KEYBOARDS[to])
62
- end
63
-
64
- def count_words
65
- clean_text.scan(/(\p{Alnum}+([-'.]\p{Alnum}+)*)/u).size
66
- end
67
-
68
- def words_count
69
- frequencies = Hash.new(0)
70
- downcase.scan(/(\w+([-'.]\w+)*)/) { |word, ignore| frequencies[word] += 1 }
71
- frequencies
72
- end
73
-
74
- def self.randomize(length = 8)
75
- Array.new(length) { (rand(122-97) + 97).chr }.join
76
- end
77
-
78
- def clean_text
79
- coder = HTMLEntities.new
80
- coder.decode(self.no_html)
81
- end
82
-
83
- def mb_upcase
84
- mb_chars.upcase.to_s
85
- end
86
-
87
- def mb_downcase
88
- mb_chars.downcase.to_s
89
- end
90
10
  end
91
11
 
92
12
  unless ''.respond_to?(:each)
@@ -19,6 +19,7 @@ module AbAdmin
19
19
  ActiveRecord::Base.send :extend, AbAdmin::Concerns::Silencer
20
20
  ActiveRecord::Base.send :include, AbAdmin::Concerns::Validations
21
21
  ActiveRecord::Base.send :include, AbAdmin::Concerns::Fileuploads
22
+ ActiveRecord::Base.send :extend, AbAdmin::Concerns::TranslationsMacro
22
23
  ActiveRecord::Base.send :extend, EnumField::EnumeratedAttribute
23
24
  end
24
25
 
@@ -1,3 +1,5 @@
1
+ require 'will_paginate/active_record'
2
+
1
3
  # add `:large` option with make pagination on large tables easier, because `SELECT *` is slow with large `OFFSET`:
2
4
  # first it fetch ids of the records using `SELECT id`
3
5
  # and in the second query it fetch records
@@ -10,7 +12,7 @@ module WillPaginate
10
12
  if value.nil?
11
13
  paginate_limit || limit_value
12
14
  else
13
- limit(value)
15
+ limit(value.to_i)
14
16
  end
15
17
  end
16
18
 
@@ -18,7 +20,7 @@ module WillPaginate
18
20
  if value.nil?
19
21
  paginate_offset || offset_value
20
22
  else
21
- super(value)
23
+ super(value.to_i)
22
24
  end
23
25
  end
24
26
  end
@@ -26,8 +28,8 @@ module WillPaginate
26
28
  module Pagination
27
29
  def paginate(options)
28
30
  options = options.dup
29
- page_number = options.fetch(:page) { raise ArgumentError, ':page parameter required' }
30
- per_page = options.delete(:per_page) || self.per_page
31
+ page_number = [1, options[:page].to_i].max
32
+ per_page = (options.delete(:per_page) || self.per_page).to_i
31
33
  total = options.delete(:total_entries)
32
34
  large = options.delete(:large)
33
35
 
@@ -40,8 +42,8 @@ module WillPaginate
40
42
  rel.total_entries = total.to_i unless total.blank?
41
43
 
42
44
  if large
43
- ids = rel.except(:includes).pluck(Arel.sql("#{quoted_table_name}.id"))
44
- new_rel = rel.except(:limit, :offset, :where).where(id: ids)
45
+ ids = rel.except(:includes).pluck(Arel.sql("#{quoted_table_name}.#{primary_key}"))
46
+ new_rel = rel.except(:limit, :offset, :where).where(primary_key => ids)
45
47
  new_rel.paginate_limit = rel.limit_value.to_i
46
48
  new_rel.paginate_offset = rel.offset_value.to_i
47
49
  new_rel.total_entries = rel.total_entries
@@ -1,6 +1,6 @@
1
- # add `:no_uri` options to skip query params in pagination urls
2
1
  require 'will_paginate/view_helpers/action_view'
3
2
 
3
+ # add `:no_uri` options to skip query params in pagination urls
4
4
  WillPaginate::ViewHelpers.pagination_options[:no_uri] = false
5
5
  WillPaginate::ActionView::LinkRenderer.class_exec do
6
6
  def url(page)
@@ -19,7 +19,9 @@ module AbAdmin
19
19
 
20
20
  if response.code == 200
21
21
  json = MultiJson.decode(response)
22
- json['data']['translations'][0]['translatedText']
22
+ res = json['data']['translations'][0]['translatedText'].to_s.gsub(/%\s{/, ' %{')
23
+ res = "#{res[0].upcase}#{res[1..-1]}" if text.first[/[[:upper:]]/]
24
+ res
23
25
  else
24
26
  raise StandardError, response.inspect
25
27
  end
@@ -7,7 +7,7 @@ module AbAdmin
7
7
 
8
8
  def initialize(options: {})
9
9
  @options = options
10
- @locales = Globalize.available_locales
10
+ @locales = AbAdmin.translated_locales
11
11
  @models = AbAdmin.translate_models.map{|m| m.constantize }
12
12
  @models_i18n_hash = {}
13
13
  end
@@ -24,12 +24,12 @@ module AbAdmin
24
24
  end
25
25
 
26
26
  def normalize_html
27
- ::Globalize.available_locales.each do |loc|
27
+ AbAdmin.translated_locales.each do |loc|
28
28
  %w(title h1 keywords description).each do |attr|
29
29
  send("#{attr}_#{loc}=", send("#{attr}_#{loc}").to_s.no_html)
30
30
  end
31
31
  end
32
- ::Globalize.available_locales.each do |loc|
32
+ AbAdmin.translated_locales.each do |loc|
33
33
  send("seo_block_#{loc}=", sanitize(send("seo_block_#{loc}").to_s))
34
34
  end
35
35
  end
@@ -58,12 +58,38 @@ module AbAdmin
58
58
  csv_data.each do |d|
59
59
  key_parts = [l.to_s] + d[0].split('.')
60
60
  raise "Invalid key #{d[0]}" unless data.dig(*key_parts)
61
- data.store_multi(d[i], *key_parts)
61
+ data.dig_store(d[i], *key_parts)
62
62
  end
63
63
  save path, data
64
64
  end
65
65
  end
66
66
 
67
+ INTERPOLATION_REGEXP = /%{[^}]+}/
68
+ def csv_errors(csv)
69
+ return ['CSV blank'] if csv.blank?
70
+ csv_data = CSV.parse(csv)
71
+ errors = []
72
+ csv_data.shift.each_with_index do |l, i|
73
+ next if i.zero?
74
+ unless I18n.available_locales.include?(l.to_sym)
75
+ errors << "Unknown locale #{l}"
76
+ next
77
+ end
78
+ csv_data.each do |d|
79
+ key = d[0]
80
+ next if d[i].blank?
81
+ if translations.dig(I18n.default_locale, key)
82
+ unless translations.dig(I18n.default_locale, key).scan(INTERPOLATION_REGEXP).sort == d[i].scan(INTERPOLATION_REGEXP).sort
83
+ errors << "Wrong interpolations #{I18n.default_locale}:'#{translations.dig(I18n.default_locale, key)}' #{l}:#{d[i]}"
84
+ end
85
+ else
86
+ errors << "Extra interpolations #{l}:#{d[i]}" if d[i].scan(INTERPOLATION_REGEXP).present?
87
+ end
88
+ end
89
+ end
90
+ errors
91
+ end
92
+
67
93
  def translations
68
94
  @translations ||= I18n.backend.send(:translations).slice(*I18n.available_locales).transform_values{|v| v.flatten_hash.transform_keys{|k| k.join('.') } }
69
95
  end
@@ -93,7 +119,7 @@ module AbAdmin
93
119
  message = nil
94
120
  locale_replace_regexp = Regexp.new("(^#{I18n.default_locale}|(?<=\.)#{I18n.default_locale}(?=\.yml))")
95
121
 
96
- locale_files = @files.map { |path| self.class.prepare_data(path) }
122
+ locale_files = @files.find_all{|f| f =~ /\/\w+(\.readonly)?\.yml/ }.map { |path| self.class.prepare_data(path) }
97
123
  main_locale_files = locale_files.find_all { |file| file.locale == I18n.default_locale }
98
124
 
99
125
  main_locale_files.each do |main_file|
@@ -6,17 +6,14 @@ module AbAdmin
6
6
  included do
7
7
  has_one :avatar, as: :assetable, dependent: :destroy, autosave: true
8
8
 
9
- scope :managers, -> { where(user_role_id: [::UserRoleType.admin.id, ::UserRoleType.moderator.id]) }
10
9
  scope :active, -> { where(locked_at: nil) }
11
10
  scope :admin, proc { includes(:avatar) }
12
11
 
13
- after_initialize :init
14
- before_validation :generate_login
15
- before_validation :set_default_role, unless: :user_role_id?
16
-
17
- validate :check_role
18
-
19
12
  enumerated_attribute :user_role_type, id_attribute: :user_role_id, class: ::UserRoleType
13
+ delegate *UserRoleType.codes.map{|code| "#{code}?" }, to: :user_role_type
14
+ end
15
+
16
+ def admin_menu_builder
20
17
  end
21
18
 
22
19
  def name
@@ -40,6 +37,10 @@ module AbAdmin
40
37
  active_for_authentication?
41
38
  end
42
39
 
40
+ def admin_access?
41
+ admin? || moderator?
42
+ end
43
+
43
44
  def generate_password!
44
45
  raw_password = AbAdmin.test_env? ? '654321' : AbAdmin.friendly_token
45
46
  self.password = self.password_confirmation = raw_password
@@ -47,47 +48,10 @@ module AbAdmin
47
48
  raw_password
48
49
  end
49
50
 
50
- def admin_access?
51
- moderator?
52
- end
53
-
54
- def default?
55
- has_role?(:default)
56
- end
57
-
58
- def redactor?
59
- has_role?(:redactor)
60
- end
61
-
62
- def moderator?
63
- has_role?(:admin) || has_role?(:moderator)
64
- end
65
-
66
- def admin?
67
- has_role?(:admin)
68
- end
69
-
70
- def has_role?(role_name)
71
- user_role_type.code == role_name
72
- end
73
-
74
- def set_default_role
75
- self.user_role_id ||= ::UserRoleType.default.id
76
- end
77
-
78
- protected
79
-
80
- def generate_login
81
- self.login ||= begin
82
- unless email.blank?
83
- tmp_login = email.split('@').first
84
- tmp_login.parameterize.downcase.gsub(/[^A-Za-z0-9-]+/, '-').gsub(/-+/, '-')
85
- end
86
- end
87
- end
88
-
89
- def check_role
90
- errors.add(:user_role_id, :invalid) unless ::UserRoleType.valid?(user_role_id)
51
+ def password_required?
52
+ return true if password.present?
53
+ return false if persisted? && password.blank?
54
+ super
91
55
  end
92
56
  end
93
57
  end
@@ -27,12 +27,14 @@ module AbAdmin
27
27
  @filename ||= [@options[:filename] || "#{@klass.model_name.plural}-#{Time.now.strftime('%Y-%m-%d')}", '.csv'].join
28
28
  end
29
29
 
30
- def render
30
+ def render(context=nil, options={})
31
31
  ::CSV.generate(col_sep: @options[:column_separator] || ',') do |csv|
32
32
  csv << columns_names
33
33
 
34
- each_record do |item|
35
- csv << column_data.map { |column| AbAdmin.pretty_data call_method_or_proc_on(item, column, exec: false) }
34
+ I18n.with_locale options[:locale] do
35
+ each_record do |item|
36
+ csv << column_data.map { |column| AbAdmin.pretty_data call_method_or_proc_on(item, column, context: context) }
37
+ end
36
38
  end
37
39
  end
38
40
  end
@@ -85,15 +85,18 @@ module AbAdmin
85
85
  end
86
86
 
87
87
  def call_method_or_proc_on(obj, symbol_or_proc, options = {})
88
- exec = options[:exec].nil? ? true : options[:exec]
88
+ options.reverse_merge!(exec: true)
89
89
  case symbol_or_proc
90
90
  when String
91
- ActiveSupport::Deprecation.warn('`call_method_or_proc_on` don\'t accept method name as String, use Symbol instead') if symbol_or_proc =~ /\A\w+\z/
92
91
  symbol_or_proc
93
92
  when Symbol
94
93
  obj.public_send(symbol_or_proc.to_sym, *options[:attrs])
95
94
  when Proc
96
- exec ? obj.instance_exec(&symbol_or_proc) : symbol_or_proc.call(obj)
95
+ if options[:context]
96
+ options[:context].instance_exec(obj, &symbol_or_proc)
97
+ else
98
+ options[:exec] ? obj.instance_exec(&symbol_or_proc) : symbol_or_proc.call(obj)
99
+ end
97
100
  end
98
101
  end
99
102
  end
@@ -49,25 +49,27 @@ module AbAdmin
49
49
  @filename ||= [@options[:filename] || "#{@klass.model_name.plural}-#{Time.now.strftime('%Y-%m-%d')}", '.xlsx'].join
50
50
  end
51
51
 
52
- def render
52
+ def render(context, options={})
53
53
  date_format = workbook.add_format(num_format: 'dd.mm.yyyy')
54
54
  time_format = workbook.add_format(num_format: 'dd.mm.yyyy HH:MM')
55
55
 
56
- each_with_index do |item, index|
57
- row = index + 1
58
-
59
- column_data.each_with_index do |column, num|
60
- value = call_method_or_proc_on(item, column, exec: false)
61
-
62
- case value
63
- when Date
64
- worksheet.write_string(row, num, value.strftime('%Y-%m-%dT'), date_format)
65
- when DateTime, Time
66
- worksheet.write_date_time(row, num, value.strftime('%Y-%m-%dT%H:%M:%S.%L'), time_format)
67
- when String
68
- worksheet.write_string(row, num, value)
69
- else
70
- worksheet.write(row, num, AbAdmin.pretty_data(value))
56
+ I18n.with_locale options[:locale] do
57
+ each_with_index do |item, index|
58
+ row = index + 1
59
+
60
+ column_data.each_with_index do |column, num|
61
+ value = call_method_or_proc_on(item, column, context: context)
62
+
63
+ case value
64
+ when Date
65
+ worksheet.write_string(row, num, value.strftime('%Y-%m-%dT'), date_format)
66
+ when DateTime, Time
67
+ worksheet.write_date_time(row, num, value.strftime('%Y-%m-%dT%H:%M:%S.%L'), time_format)
68
+ when String
69
+ worksheet.write_string(row, num, value)
70
+ else
71
+ worksheet.write(row, num, AbAdmin.pretty_data(value))
72
+ end
71
73
  end
72
74
  end
73
75
  end