hancock_cms_cache 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.ruby-gemset +1 -0
  4. data/.ruby-version +1 -0
  5. data/Gemfile +4 -0
  6. data/README.md +35 -0
  7. data/Rakefile +2 -0
  8. data/app/assets/javascripts/hancock/rails_admin/plugins/cache.coffee +4 -0
  9. data/app/assets/javascripts/hancock/rails_admin/plugins/cache/custom/ui.coffee +0 -0
  10. data/app/assets/stylesheets/hancock/rails_admin/plugins/cache.sass +3 -0
  11. data/app/assets/stylesheets/hancock/rails_admin/plugins/cache/custom/theming.sass +0 -0
  12. data/app/controllers/concerns/hancock/cache/action.rb +58 -0
  13. data/app/controllers/concerns/hancock/cache/ajax_csrf.rb +25 -0
  14. data/app/controllers/concerns/hancock/cache/fragments.rb +34 -0
  15. data/app/controllers/concerns/hancock/cache/no_cache.rb +12 -0
  16. data/app/helpers/hancock/cache/cache_helper.rb +167 -0
  17. data/app/models/concerns/hancock/cache/cacheable.rb +164 -0
  18. data/app/models/concerns/hancock/cache/cleared_stack.rb +43 -0
  19. data/app/models/concerns/hancock/cache/decorators/fragment.rb +41 -0
  20. data/app/models/concerns/hancock/cache/loadable.rb +44 -0
  21. data/app/models/concerns/hancock/cache/snapshotable.rb +49 -0
  22. data/app/models/hancock/cache/fragment.rb +11 -0
  23. data/app/views/hancock/_assets.html.slim +24 -0
  24. data/app/views/layouts/application.html.slim +33 -0
  25. data/app/views/rails_admin/main/hancock_cache_global_clear.html.slim +25 -0
  26. data/bin/console +14 -0
  27. data/bin/setup +8 -0
  28. data/config/initializers/cache_detector.rb +53 -0
  29. data/config/initializers/hancock_cache.rb +7 -0
  30. data/config/locales/hancock.cache.ru.yml +59 -0
  31. data/hancock_cms_cache.gemspec +34 -0
  32. data/lib/generators/hancock/cache/config/config_generator.rb +13 -0
  33. data/lib/generators/hancock/cache/config/templates/hancock_cache.erb +14 -0
  34. data/lib/generators/hancock/cache/models/decorators_generator.rb +24 -0
  35. data/lib/generators/hancock/cache/models/fragment_generator.rb +39 -0
  36. data/lib/generators/hancock/cache/models/templates/fragment.erb +38 -0
  37. data/lib/hancock/cache/admin.rb +37 -0
  38. data/lib/hancock/cache/admin/fragment.rb +140 -0
  39. data/lib/hancock/cache/configuration.rb +38 -0
  40. data/lib/hancock/cache/engine.rb +20 -0
  41. data/lib/hancock/cache/models/fragment.rb +310 -0
  42. data/lib/hancock/cache/models/mongoid/fragment.rb +259 -0
  43. data/lib/hancock/cache/rails_admin_ext/hancock_cache_clear.rb +95 -0
  44. data/lib/hancock/cache/rails_admin_ext/hancock_cache_dump_snapshot.rb +92 -0
  45. data/lib/hancock/cache/rails_admin_ext/hancock_cache_global_clear.rb +74 -0
  46. data/lib/hancock/cache/rails_admin_ext/hancock_cache_restore_snapshot.rb +92 -0
  47. data/lib/hancock/cache/rails_admin_ext/hancock_touch.rb +95 -0
  48. data/lib/hancock/cache/rails_admin_settings_patch.rb +185 -0
  49. data/lib/hancock/cache/version.rb +5 -0
  50. data/lib/hancock_cms_cache.rb +34 -0
  51. data/release.sh +6 -0
  52. metadata +141 -0
@@ -0,0 +1,259 @@
1
+ module Hancock::Cache
2
+ module Models::Mongoid
3
+ module Fragment
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+
8
+ include Hancock::Cache::Snapshotable
9
+
10
+ index({name: 1}, {unique: true, background: true})
11
+ index({last_clear_user_id: 1, last_clear_time: 1}, {background: true})
12
+
13
+ field :name, type: String, localize: false, default: ""
14
+ scope :by_name, -> (_name) {
15
+ if _name.is_a?(Array)
16
+ where(:name.in => _name.compact.map(&:strip))
17
+ else
18
+ if _name.is_a?(String)
19
+ where(name: (_name and _name.strip))
20
+ else
21
+ where(name: _name)
22
+ end
23
+ end
24
+ }
25
+ scope :by_name_from_view, -> (_name) {
26
+ by_name(self.name_from_view(_name))
27
+ }
28
+ scope :find_by_name, -> (_name) {
29
+ by_name(_name).first
30
+ }
31
+ scope :find_by_name_from_view, -> (_name) {
32
+ by_name_from_view(_name).first
33
+ }
34
+
35
+ field :desc, type: String, localize: Hancock::Cache.config.localize, default: ""
36
+ field :virtual_path, type: String, localize: false, default: ""
37
+ field :is_html, type: Boolean, default: true
38
+
39
+ field :is_action_cache, type: Boolean, default: false
40
+ scope :is_action_cache, -> {
41
+ where(is_action_cache: true)
42
+ }
43
+
44
+ field :on_ram, type: Boolean, default: false
45
+ scope :on_ram, -> {
46
+ where(on_ram: true)
47
+ }
48
+ attr_accessor :on_ram_data
49
+ def load_data_on_ram
50
+ if self.on_ram and !self.name.blank?
51
+ self.on_ram_data = Rails.cache.read(self.name)
52
+ end
53
+ end
54
+
55
+ field :last_clear_time, type: DateTime
56
+ if Hancock.rails4?
57
+ belongs_to :last_clear_user, class_name: Mongoid::Userstamp.config.user_model_name, autosave: false
58
+ else
59
+ belongs_to :last_clear_user, class_name: Mongoid::Userstamp.config.user_model_name, autosave: false, optional: true, required: false
60
+
61
+ if relations.has_key?("updater") and defined?(::Mongoid::History)
62
+ belongs_to :updater, class_name: ::Mongoid::History.modifier_class_name, optional: true, validate: false
63
+ _validators.delete(:updater)
64
+ _validate_callbacks.each do |callback|
65
+ if callback.raw_filter.respond_to?(:attributes) and callback.raw_filter.attributes.include?(:updater)
66
+ _validate_callbacks.delete(callback)
67
+ end
68
+ end
69
+ end
70
+ end
71
+
72
+ has_and_belongs_to_many :parents, class_name: "Hancock::Cache::Fragment", inverse_of: nil
73
+ field :parent_names, type: Array, default: []
74
+ def set_parent_names
75
+ self.parent_names = self.parents.distinct(:name)
76
+ end
77
+ def set_parent_names!
78
+ self.set_parent_names and self.save
79
+ end
80
+ def update_parent_names!
81
+ self.set_parent_names and self.class.where(id: self.id).update(parent_names: self.parent_names)
82
+ end
83
+ before_save do
84
+ if self.parent_ids_changed?
85
+ self.set_parent_names
86
+ end
87
+ self
88
+ end
89
+ def set_parent_ids
90
+ self.parent_ids = self.class.by_name(self.parent_names).distinct(:_id) unless self.parent_names.blank?
91
+ end
92
+ def set_parent_ids!
93
+ self.set_parent_ids and self.save
94
+ end
95
+ def update_parent_ids!
96
+ self.set_parent_ids and self.class.where(id: self.id).update(parent_ids: self.parent_ids, parent_names: self.parent_names)
97
+ end
98
+
99
+ def reset_parents
100
+ self.parent_ids = self.parents.distinct(:_id)
101
+ end
102
+ def reset_parents!
103
+ self.reset_parents and self.save
104
+ end
105
+ def self.reset_parents!
106
+ self.all.map(&:reset_parents!)
107
+ end
108
+
109
+ def name_n_desc
110
+ "#{self.name}<hr>#{self.desc}".html_safe
111
+ end
112
+ def parents_str
113
+ self.parents.map(&:name).join(", ")
114
+ end
115
+ def name_n_desc_n_parents
116
+ "#{self.name}<hr>#{self.desc}<hr>#{parents_str}".html_safe
117
+ end
118
+
119
+ def last_clear_data
120
+ "#{self.last_clear_time}<hr>#{self.last_clear_user}".html_safe
121
+ end
122
+ def snapshot_data
123
+ "#{self.last_dump_snapshot_time}<hr>#{self.last_restore_snapshot_time}<hr>#{self.get_snapshot(false)}".html_safe
124
+ end
125
+
126
+ def data(prettify = true)
127
+ _data = Rails.cache.read(self.name)
128
+ if prettify
129
+ if self.is_html
130
+ "<pre>#{CGI::escapeHTML(Nokogiri::HTML.fragment(_data).to_xhtml(indent: 2))}</pre>".html_safe
131
+ else
132
+ _data
133
+ end
134
+ else
135
+ _data
136
+ end
137
+ end
138
+
139
+ def set_last_clear_user(forced_user = nil)
140
+ unless forced_user
141
+ return false unless Mongoid::Userstamp.has_current_user?
142
+ self.last_clear_user = Mongoid::Userstamp.current_user
143
+ else
144
+ self.last_clear_user = forced_user
145
+ end
146
+ end
147
+
148
+ def self.set_for_object(key_name, obj)
149
+ if key_name.is_a?(Array)
150
+ return key_name.map do |k|
151
+ set_for_object(k, obj) unless k.blank?
152
+ end
153
+ else
154
+ _frag = self.where(name: key_name).first
155
+ _frag and _frag.set_for_object obj
156
+ end
157
+ end
158
+ def self.set_for_objects(key_name, _class)
159
+ if key_name.is_a?(Array)
160
+ return key_name.map do |k|
161
+ set_for_objects(k, _class) unless k.blank?
162
+ end
163
+ else
164
+ _frag = self.where(name: key_name).first
165
+ _frag and _frag.set_for_objects _class
166
+ end
167
+ end
168
+
169
+ # def set_for_object(obj)
170
+ # if obj.is_a?(Hash)
171
+ # if obj[:model].present?
172
+ # if obj[:ids].present?
173
+ # return obj[:ids].map do |_id|
174
+ # set_for_object({model: obj[:model], id: _id}) unless _id.blank?
175
+ # end
176
+ # else
177
+ # if obj[:id].nil?
178
+ # return set_for_objects(obj[:model])
179
+ # else
180
+ # obj = obj[:model].where(id: obj[:id]).first
181
+ # end
182
+ # end
183
+ # else
184
+ # return false
185
+ # end
186
+ #
187
+ # elsif obj.is_a?(Array)
188
+ # return obj.map do |_obj|
189
+ # set_for_object(_obj) unless _obj.blank?
190
+ # end
191
+ # end
192
+ #
193
+ # if obj
194
+ # if obj.is_a?(Class)
195
+ # set_for_objects obj
196
+ # else
197
+ # unless obj.cache_keys.include?(self.name)
198
+ # obj.set(cache_keys_str: (obj.cache_keys << self.name).uniq.join("\n"))
199
+ # obj.reload
200
+ # end
201
+ # end
202
+ # end
203
+ # end
204
+ # def set_for_objects(_class)
205
+ # _class.all.map { |obj|
206
+ # unless obj.cache_keys.include?(self.name)
207
+ # obj.set(cache_keys_str: (obj.cache_keys << self.name).uniq.join("\n"))
208
+ # obj.reload
209
+ # end
210
+ # }
211
+ # end
212
+
213
+ def self.set_for_setting(key_name, setting_obj)
214
+ if key_name.is_a?(Array)
215
+ return key_name.map do |k|
216
+ set_for_setting(k, setting_obj) unless k.blank?
217
+ end
218
+ else
219
+ _frag = self.where(name: key_name).first
220
+ _frag and _frag.set_for_setting setting_obj
221
+ end
222
+ end
223
+ # def set_for_setting(setting_obj)
224
+ # if defined?(RailsAdminModelSettings)
225
+ # if setting_obj.is_a?(Hash)
226
+ # unless setting_obj[:keys].present?
227
+ # if setting_obj[:key].nil?
228
+ # return set_for_setting({ns: setting_obj[:ns], key: //})
229
+ # else
230
+ # setting_obj = RailsAdminSettings::Setting.where(ns: setting_obj[:ns], key: setting_obj[:key]).first
231
+ # end
232
+ #
233
+ # else
234
+ # return setting_obj[:keys].map do |k|
235
+ # set_for_setting({ns: setting_obj[:ns], key: k}) unless k.blank?
236
+ # end
237
+ # end
238
+ #
239
+ # elsif setting_obj.is_a?(Array)
240
+ # return setting_obj.map do |obj|
241
+ # set_for_setting(obj) unless obj.blank?
242
+ # end
243
+ # end
244
+ #
245
+ # setting_obj and set_for_object(setting_obj) and setting_obj.reload
246
+ # end
247
+ # end
248
+
249
+ end
250
+
251
+ class_methods do
252
+ def track_history?
253
+ false
254
+ end
255
+ end
256
+
257
+ end
258
+ end
259
+ end
@@ -0,0 +1,95 @@
1
+ require 'rails_admin/config/actions'
2
+
3
+ module RailsAdmin
4
+ module Config
5
+ module Actions
6
+ class HancockCacheClear < Base
7
+ RailsAdmin::Config::Actions.register(self)
8
+
9
+ # Is the action acting on the root level (Example: /admin/contact)
10
+ register_instance_option :root? do
11
+ false
12
+ end
13
+
14
+ register_instance_option :collection? do
15
+ false
16
+ end
17
+
18
+ # Is the action on an object scope (Example: /admin/team/1/edit)
19
+ register_instance_option :member? do
20
+ true
21
+ end
22
+
23
+ register_instance_option :controller do
24
+ proc do
25
+ ajax_link = Proc.new do |fv, badge|
26
+ # can_edit_obj = can?(:edit, @object)
27
+ # render json: {
28
+ # text: fv.html_safe,
29
+ # href: hancock_cache_clear_path(model_name: @abstract_model, id: @object.id),
30
+ # class: 'label ' + badge,
31
+ # url: index_path(model_name: @abstract_model)
32
+ # }
33
+ end
34
+ if params['id'].present?
35
+ begin
36
+ @object = @abstract_model.model.unscoped.find(params['id'])
37
+ if @object.clear!
38
+ if params['ajax'].present?
39
+ ajax_link.call('♻', 'label-success')
40
+ else
41
+ flash[:success] = I18n.t('admin.hancock_cache_clear.cleared', obj: @object, name: @object.name)
42
+ # unless @object.parents.blank?
43
+ # flash[:info] = "Также, возможно необходимо сбросить кеш с этми ключами: #{@object.parents_str}"
44
+ # end
45
+ end
46
+ else
47
+ if params['ajax'].present?
48
+ render plain: @object.errors.full_messages.join(', '), layout: false, status: 422
49
+ else
50
+ flash[:error] = @object.errors.full_messages.join(', ')
51
+ end
52
+ end
53
+ rescue Exception => e
54
+ if params['ajax'].present?
55
+ render plain: I18n.t('admin.hancock_cache_clear.error', err: e.to_s), status: 422
56
+ else
57
+ flash[:error] = I18n.t('admin.hancock_cache_clear.error', err: e.to_s)
58
+ end
59
+ end
60
+ else
61
+ if params['ajax'].present?
62
+ render plain: I18n.t('admin.hancock_cache_clear.no_id'), status: 422
63
+ else
64
+ flash[:error] = I18n.t('admin.hancock_cache_clear.no_id')
65
+ end
66
+ end
67
+
68
+ unless params['ajax'].present?
69
+ begin
70
+ fallback_location = index_path(model_name: @abstract_model, id: @object.id)
71
+ rescue
72
+ fallback_location = index_path(model_name: @abstract_model)
73
+ end
74
+ redirect_back(fallback_location: fallback_location)
75
+ end
76
+
77
+ end
78
+ end
79
+
80
+ register_instance_option :link_icon do
81
+ 'icon-trash'
82
+ end
83
+
84
+ register_instance_option :pjax? do
85
+ false
86
+ end
87
+
88
+ register_instance_option :http_methods do
89
+ [:get]
90
+ end
91
+
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,92 @@
1
+ require 'rails_admin/config/actions'
2
+
3
+ module RailsAdmin
4
+ module Config
5
+ module Actions
6
+ class HancockCacheDumpSnapshot < Base
7
+ RailsAdmin::Config::Actions.register(self)
8
+
9
+ # Is the action acting on the root level (Example: /admin/contact)
10
+ register_instance_option :root? do
11
+ false
12
+ end
13
+
14
+ register_instance_option :collection? do
15
+ false
16
+ end
17
+
18
+ # Is the action on an object scope (Example: /admin/team/1/edit)
19
+ register_instance_option :member? do
20
+ true
21
+ end
22
+
23
+ register_instance_option :controller do
24
+ proc do
25
+ ajax_link = Proc.new do |fv, badge|
26
+ # can_edit_obj = can?(:edit, @object)
27
+ # render json: {
28
+ # text: fv.html_safe,
29
+ # href: hancock_cache_clear_path(model_name: @abstract_model, id: @object.id),
30
+ # class: 'label ' + badge,
31
+ # url: index_path(model_name: @abstract_model)
32
+ # }
33
+ end
34
+ if params['id'].present?
35
+ begin
36
+ @object = @abstract_model.model.unscoped.find(params['id'])
37
+ if @object.dump_snapshot!
38
+ if params['ajax'].present?
39
+ ajax_link.call('♻', 'label-success')
40
+ else
41
+ flash[:success] = I18n.t('admin.hancock_cache_dump_snapshot.dumped', obj: @object)
42
+ end
43
+ else
44
+ if params['ajax'].present?
45
+ render plain: @object.errors.full_messages.join(', '), layout: false, status: 422
46
+ else
47
+ flash[:error] = @object.errors.full_messages.join(', ')
48
+ end
49
+ end
50
+ rescue Exception => e
51
+ if params['ajax'].present?
52
+ render plain: I18n.t('admin.hancock_cache_dump_snapshot.error', err: e.to_s), status: 422
53
+ else
54
+ flash[:error] = I18n.t('admin.hancock_cache_dump_snapshot.error', err: e.to_s)
55
+ end
56
+ end
57
+ else
58
+ if params['ajax'].present?
59
+ render plain: I18n.t('admin.hancock_cache_dump_snapshot.no_id'), status: 422
60
+ else
61
+ flash[:error] = I18n.t('admin.hancock_cache_dump_snapshot.no_id')
62
+ end
63
+ end
64
+
65
+ unless params['ajax'].present?
66
+ begin
67
+ fallback_location = index_path(model_name: @abstract_model, id: @object.id)
68
+ rescue
69
+ fallback_location = index_path(model_name: @abstract_model)
70
+ end
71
+ redirect_back(fallback_location: fallback_location)
72
+ end
73
+
74
+ end
75
+ end
76
+
77
+ register_instance_option :link_icon do
78
+ 'fa fa-save'
79
+ end
80
+
81
+ register_instance_option :pjax? do
82
+ false
83
+ end
84
+
85
+ register_instance_option :http_methods do
86
+ [:get]
87
+ end
88
+
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,74 @@
1
+ require 'rails_admin/config/actions'
2
+
3
+ module RailsAdmin
4
+ module Config
5
+ module Actions
6
+ class HancockCacheGlobalClear < Base
7
+ RailsAdmin::Config::Actions.register(self)
8
+
9
+ # Is the action acting on the root level (Example: /admin/contact)
10
+ register_instance_option :root? do
11
+ false
12
+ end
13
+
14
+ register_instance_option :collection? do
15
+ true
16
+ end
17
+
18
+ # Is the action on an object scope (Example: /admin/team/1/edit)
19
+ register_instance_option :member? do
20
+ false
21
+ end
22
+
23
+ register_instance_option :route_fragment do
24
+ 'hancock_cache_global_clear'
25
+ end
26
+
27
+ register_instance_option :controller do
28
+ Proc.new do |klass|
29
+ # @config = ::HancockCacheGlobalClear::Configuration.new @abstract_model
30
+ if request.get?
31
+ render action: @action.template_name
32
+
33
+ elsif request.post?
34
+ case params[:type].to_s
35
+ when "global"
36
+ begin
37
+ Rails.cache.clear
38
+ ::Hancock::Cache::Fragment.all.to_a.map(&:clear_dry!)
39
+ flash[:success] = 'Весь кеш очищен'
40
+ rescue Exception => ex
41
+ flash[:error] = 'Ошибка'
42
+ end
43
+ when "fragments"
44
+ begin
45
+ # Hancock::Cache::Fragment.all.to_a.map do |f|
46
+ # f.clear!
47
+ # end
48
+ ::Hancock::Cache::Fragment.clear_all
49
+ flash[:success] = 'Кеш очищен'
50
+ rescue Exception => ex
51
+ flash[:error] = 'Ошибка'
52
+ end
53
+ else
54
+ flash[:error] = 'Неверно указан тип кеша для сброса'
55
+ end
56
+
57
+ redirect_to hancock_cache_global_clear_path(model_name: 'hancock~cache~fragment'.freeze)
58
+
59
+ end
60
+ end
61
+ end
62
+
63
+ register_instance_option :link_icon do
64
+ 'icon-refresh'
65
+ end
66
+
67
+ register_instance_option :http_methods do
68
+ [:get, :post]
69
+ end
70
+
71
+ end
72
+ end
73
+ end
74
+ end