hancock_cms_cache 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +4 -0
- data/README.md +35 -0
- data/Rakefile +2 -0
- data/app/assets/javascripts/hancock/rails_admin/plugins/cache.coffee +4 -0
- data/app/assets/javascripts/hancock/rails_admin/plugins/cache/custom/ui.coffee +0 -0
- data/app/assets/stylesheets/hancock/rails_admin/plugins/cache.sass +3 -0
- data/app/assets/stylesheets/hancock/rails_admin/plugins/cache/custom/theming.sass +0 -0
- data/app/controllers/concerns/hancock/cache/action.rb +58 -0
- data/app/controllers/concerns/hancock/cache/ajax_csrf.rb +25 -0
- data/app/controllers/concerns/hancock/cache/fragments.rb +34 -0
- data/app/controllers/concerns/hancock/cache/no_cache.rb +12 -0
- data/app/helpers/hancock/cache/cache_helper.rb +167 -0
- data/app/models/concerns/hancock/cache/cacheable.rb +164 -0
- data/app/models/concerns/hancock/cache/cleared_stack.rb +43 -0
- data/app/models/concerns/hancock/cache/decorators/fragment.rb +41 -0
- data/app/models/concerns/hancock/cache/loadable.rb +44 -0
- data/app/models/concerns/hancock/cache/snapshotable.rb +49 -0
- data/app/models/hancock/cache/fragment.rb +11 -0
- data/app/views/hancock/_assets.html.slim +24 -0
- data/app/views/layouts/application.html.slim +33 -0
- data/app/views/rails_admin/main/hancock_cache_global_clear.html.slim +25 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/config/initializers/cache_detector.rb +53 -0
- data/config/initializers/hancock_cache.rb +7 -0
- data/config/locales/hancock.cache.ru.yml +59 -0
- data/hancock_cms_cache.gemspec +34 -0
- data/lib/generators/hancock/cache/config/config_generator.rb +13 -0
- data/lib/generators/hancock/cache/config/templates/hancock_cache.erb +14 -0
- data/lib/generators/hancock/cache/models/decorators_generator.rb +24 -0
- data/lib/generators/hancock/cache/models/fragment_generator.rb +39 -0
- data/lib/generators/hancock/cache/models/templates/fragment.erb +38 -0
- data/lib/hancock/cache/admin.rb +37 -0
- data/lib/hancock/cache/admin/fragment.rb +140 -0
- data/lib/hancock/cache/configuration.rb +38 -0
- data/lib/hancock/cache/engine.rb +20 -0
- data/lib/hancock/cache/models/fragment.rb +310 -0
- data/lib/hancock/cache/models/mongoid/fragment.rb +259 -0
- data/lib/hancock/cache/rails_admin_ext/hancock_cache_clear.rb +95 -0
- data/lib/hancock/cache/rails_admin_ext/hancock_cache_dump_snapshot.rb +92 -0
- data/lib/hancock/cache/rails_admin_ext/hancock_cache_global_clear.rb +74 -0
- data/lib/hancock/cache/rails_admin_ext/hancock_cache_restore_snapshot.rb +92 -0
- data/lib/hancock/cache/rails_admin_ext/hancock_touch.rb +95 -0
- data/lib/hancock/cache/rails_admin_settings_patch.rb +185 -0
- data/lib/hancock/cache/version.rb +5 -0
- data/lib/hancock_cms_cache.rb +34 -0
- data/release.sh +6 -0
- metadata +141 -0
@@ -0,0 +1,43 @@
|
|
1
|
+
module Hancock::Cache::ClearedStack
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
included do
|
5
|
+
@@cleared_stack = []
|
6
|
+
cattr_reader :cleared_stack
|
7
|
+
@@cleared_stack_mutex = Mutex.new
|
8
|
+
def self.drop_cleared_stack
|
9
|
+
@@cleared_stack_mutex.synchronize do
|
10
|
+
@@cleared_stack = []
|
11
|
+
end
|
12
|
+
end
|
13
|
+
def drop_cleared_stack
|
14
|
+
self.class.drop_cleared_stack
|
15
|
+
end
|
16
|
+
def drop_cleared_stack_if_can
|
17
|
+
self.class.drop_cleared_stack if self.first_in_cleared_stack?
|
18
|
+
end
|
19
|
+
drop_cleared_stack
|
20
|
+
|
21
|
+
def self.add_to_cleared_stack(key)
|
22
|
+
@@cleared_stack_mutex.synchronize do
|
23
|
+
@@cleared_stack ||= []
|
24
|
+
@@cleared_stack << key unless is_in_cleared_stack?(key)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
def add_to_cleared_stack
|
28
|
+
self.class.add_to_cleared_stack(self.name) unless self.is_in_cleared_stack?
|
29
|
+
end
|
30
|
+
|
31
|
+
def first_in_cleared_stack?
|
32
|
+
@@cleared_stack and @@cleared_stack.first == self.name
|
33
|
+
end
|
34
|
+
|
35
|
+
def is_in_cleared_stack?
|
36
|
+
self.class.is_in_cleared_stack?(self.name)
|
37
|
+
end
|
38
|
+
def self.is_in_cleared_stack?(key)
|
39
|
+
@@cleared_stack.include?(key)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Hancock::Cache::Decorators
|
2
|
+
module Fragment
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
|
7
|
+
############# rails_admin ##############
|
8
|
+
# def self.rails_admin_name_synonyms
|
9
|
+
# "Кеш Кэш".freeze
|
10
|
+
# end
|
11
|
+
# def self.rails_admin_navigation_icon
|
12
|
+
# ''.freeze
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# def self.rails_admin_add_fields
|
16
|
+
# [].freeze #super
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# def self.rails_admin_add_config(config)
|
20
|
+
# #super(config)
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# def self.admin_can_user_defined_actions
|
24
|
+
# [].freeze
|
25
|
+
# end
|
26
|
+
# def self.admin_cannot_user_defined_actions
|
27
|
+
# [].freeze
|
28
|
+
# end
|
29
|
+
# def self.manager_can_user_defined_actions
|
30
|
+
# [].freeze
|
31
|
+
# end
|
32
|
+
# def self.manager_cannot_user_defined_actions
|
33
|
+
# [].freeze
|
34
|
+
# end
|
35
|
+
# def self.rails_admin_user_defined_visible_actions
|
36
|
+
# [].freeze
|
37
|
+
# end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Hancock::Cache::Loadable
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
included do
|
5
|
+
cattr_reader :loaded_info, :loaded
|
6
|
+
@@loaded = false
|
7
|
+
@@load_mutex = Mutex.new
|
8
|
+
|
9
|
+
class << self
|
10
|
+
def unload!
|
11
|
+
@@load_mutex.synchronize do
|
12
|
+
@@loaded_info = {}
|
13
|
+
@@loaded = false
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def load!
|
18
|
+
@@load_mutex.synchronize do
|
19
|
+
return if @@loaded
|
20
|
+
@@loaded_info = Hancock::Cache::Fragment.cutted.all.to_a.map { |f| f.load_data_on_ram; [f.name, f] }.to_h
|
21
|
+
@@loaded = true
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def reload!
|
26
|
+
unload!
|
27
|
+
load!
|
28
|
+
end
|
29
|
+
|
30
|
+
def [](key)
|
31
|
+
@@loaded_info[key]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def reload_info!
|
36
|
+
self.class.reload!
|
37
|
+
end
|
38
|
+
|
39
|
+
after_save :reload_info!
|
40
|
+
after_destroy :reload_info!
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
if Hancock.mongoid?
|
2
|
+
|
3
|
+
module Hancock::Cache::Snapshotable
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
|
8
|
+
scope :cutted, -> {
|
9
|
+
without(:snapshot)#, :last_dump_snapshot_time, :last_restore_snapshot_time)
|
10
|
+
}
|
11
|
+
|
12
|
+
field :last_dump_snapshot_time, type: DateTime
|
13
|
+
field :last_restore_snapshot_time, type: DateTime
|
14
|
+
field :snapshot, type: String, localize: false
|
15
|
+
|
16
|
+
def get_snapshot(prettify = true)
|
17
|
+
_data = self.snapshot || ""
|
18
|
+
if prettify
|
19
|
+
if self.is_html
|
20
|
+
"<pre>#{CGI::escapeHTML(Nokogiri::HTML.fragment(_data).to_xhtml(indent: 2))}</pre>".html_safe
|
21
|
+
else
|
22
|
+
_data
|
23
|
+
end
|
24
|
+
else
|
25
|
+
_data
|
26
|
+
end
|
27
|
+
end
|
28
|
+
def dump_snapshot
|
29
|
+
self.snapshot = self.data(false)
|
30
|
+
end
|
31
|
+
def dump_snapshot!
|
32
|
+
self.dump_snapshot
|
33
|
+
self.last_dump_snapshot_time = Time.new
|
34
|
+
self.save
|
35
|
+
end
|
36
|
+
|
37
|
+
def restore_snapshot
|
38
|
+
Rails.cache.write(self.name, self.get_snapshot(false))
|
39
|
+
end
|
40
|
+
def restore_snapshot!
|
41
|
+
self.restore_snapshot
|
42
|
+
self.last_restore_snapshot_time = Time.new
|
43
|
+
self.save
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Hancock::Cache
|
2
|
+
class Fragment
|
3
|
+
include Hancock::Cache::Models::Fragment
|
4
|
+
|
5
|
+
include Hancock::Cache::Decorators::Fragment
|
6
|
+
|
7
|
+
rails_admin(&Hancock::Cache::Admin::Fragment.config(rails_admin_add_fields) { |config|
|
8
|
+
rails_admin_add_config(config)
|
9
|
+
})
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
- layout_name ||= 'application'
|
2
|
+
- stylesheet_name ||= layout_name
|
3
|
+
- javascript_name ||= layout_name
|
4
|
+
- async = false unless defined?(async) #Rails.env.production?
|
5
|
+
- defer = true unless defined?(defer) #Rails.env.production?
|
6
|
+
- if Rails.env.production?
|
7
|
+
- hancock_cache "layouts/#{layout_name}/assets", on_ram: true do
|
8
|
+
- async = false #Rails.env.production?
|
9
|
+
= stylesheet_link_tag stylesheet_name, media: "all", async: async, defer: defer
|
10
|
+
= javascript_include_tag javascript_name, async: async, defer: defer
|
11
|
+
/[if lt IE 9]
|
12
|
+
= javascript_include_tag "//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.2/html5shiv.min.js", async: async, defer: defer
|
13
|
+
- else
|
14
|
+
= stylesheet_link_tag stylesheet_name, media: "all", async: async, defer: defer
|
15
|
+
= javascript_include_tag javascript_name, async: async, defer: defer
|
16
|
+
/[if lt IE 9]
|
17
|
+
= javascript_include_tag "//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.2/html5shiv.min.js", async: async, defer: defer
|
18
|
+
|
19
|
+
|
20
|
+
- hancock_cache "layouts/#{layout_name}/custom_head" do
|
21
|
+
css:
|
22
|
+
#{{hancock_cache_settings "custom_css", ns: "#{layout_name}_layout", default: '', kind: :css, label: "Дополнительный CSS"}}
|
23
|
+
javascript:
|
24
|
+
#{{hancock_cache_settings "custom_js", ns: "#{layout_name}_layout", default: '', kind: :js, label: "Дополнительный JS" }}
|
@@ -0,0 +1,33 @@
|
|
1
|
+
doctype html
|
2
|
+
html lang="ru"
|
3
|
+
head
|
4
|
+
meta charset="UTF-8"
|
5
|
+
meta name="viewport" content="width=device-width, maximum-scale=1"
|
6
|
+
title= yield(:title) || page_title
|
7
|
+
= yield :meta
|
8
|
+
= csrf_meta_tags
|
9
|
+
|
10
|
+
/ - hancock_cache 'favicons' do
|
11
|
+
/ = render partial: 'blocks/favicon'
|
12
|
+
|
13
|
+
= render partial: 'assets'
|
14
|
+
|
15
|
+
body{class="application_layout #{controller_name} #{action_name} #{controller_name}_#{action_name}"}
|
16
|
+
|
17
|
+
- hancock_cache 'preloader' do
|
18
|
+
= render partial: 'blocks/preloader'
|
19
|
+
|
20
|
+
#root role="main"
|
21
|
+
|
22
|
+
header#header
|
23
|
+
= render partial: 'blocks/header'
|
24
|
+
|
25
|
+
= render "shared/messages"
|
26
|
+
|
27
|
+
#content
|
28
|
+
= yield
|
29
|
+
|
30
|
+
footer#footer
|
31
|
+
= render partial: 'blocks/footer'
|
32
|
+
|
33
|
+
= render partial: 'hancock/toplink/toplink'
|
@@ -0,0 +1,25 @@
|
|
1
|
+
- if request.get?
|
2
|
+
- _model = @abstract_model.model
|
3
|
+
- _model_str = _model.name.underscore
|
4
|
+
|
5
|
+
#hancock_cache_global_clear_wrapper
|
6
|
+
|
7
|
+
#hancock_cache_global_clear.col-md-12
|
8
|
+
.controls
|
9
|
+
div= link_to "Сбросить весь кеш".freeze, hancock_cache_global_clear_path(model_name: _model.rails_admin_name, type: 'global'), data: {method: :post}
|
10
|
+
div
|
11
|
+
div= link_to "Сбросить кеш фрагментов".freeze, hancock_cache_global_clear_path(model_name: _model.rails_admin_name, type: 'fragments'), data: {method: :post}
|
12
|
+
div
|
13
|
+
.cf{style='clear: both'}
|
14
|
+
|
15
|
+
- elsif request.post?
|
16
|
+
/ - uniq_id = "rails_admin_model_accesses_#{(Time.new.to_f * 1000).to_i}".freeze
|
17
|
+
/ span(class="message #{@_class}" id=uniq_id)
|
18
|
+
/ = @message
|
19
|
+
/ javascript:
|
20
|
+
/ setTimeout(function(){
|
21
|
+
/ $('##{uniq_id}').fadeOut(100, function(){
|
22
|
+
/ $('##{uniq_id}').remove();
|
23
|
+
/ });
|
24
|
+
/ }, 1000);
|
25
|
+
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "hancock_cache"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
#
|
2
|
+
# module ActionView
|
3
|
+
# module Helpers
|
4
|
+
# module CacheHelper
|
5
|
+
#
|
6
|
+
# if Hancock.rails4?
|
7
|
+
# def cache_fragment_name(name = {}, options = nil)
|
8
|
+
# skip_digest = options && options[:skip_digest]
|
9
|
+
#
|
10
|
+
# if skip_digest
|
11
|
+
# begin
|
12
|
+
# if Hancock::Cache.config.runtime_cache_detector
|
13
|
+
# _name = Hancock::Cache::Fragment.name_from_view(name)
|
14
|
+
# if !respond_to?(:hancock_cache_fragments) or (frag = hancock_cache_fragments[_name]).nil? or !frag.enabled
|
15
|
+
# _desc = "" #"#{@virtual_path}\noptions: #{options}"
|
16
|
+
# _virtual_path = @virtual_path
|
17
|
+
# Hancock::Cache::Fragment.create_unless_exists(name: _name, desc: _desc, virtual_path: _virtual_path)
|
18
|
+
# end
|
19
|
+
# end
|
20
|
+
# rescue
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# name
|
24
|
+
# else
|
25
|
+
# fragment_name_with_digest(name)
|
26
|
+
# end
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# elsif Hancock.rails5?
|
30
|
+
# def cache_fragment_name(name = {}, skip_digest: nil, virtual_path: nil)
|
31
|
+
# if skip_digest
|
32
|
+
# begin
|
33
|
+
# if Hancock::Cache.config.runtime_cache_detector
|
34
|
+
# _name = Hancock::Cache::Fragment.name_from_view(name)
|
35
|
+
# if !respond_to?(:hancock_cache_fragments) or (frag = hancock_cache_fragments[_name]).nil? or !frag.enabled
|
36
|
+
# _desc = "" #"#{virtual_path}\noptions: #{options}"
|
37
|
+
# _virtual_path = virtual_path
|
38
|
+
# Hancock::Cache::Fragment.create_unless_exists(name: _name, desc: _desc, virtual_path: _virtual_path)
|
39
|
+
# end
|
40
|
+
# end
|
41
|
+
# rescue
|
42
|
+
# end
|
43
|
+
#
|
44
|
+
# name
|
45
|
+
# else
|
46
|
+
# fragment_name_with_digest(name, virtual_path)
|
47
|
+
# end
|
48
|
+
# end
|
49
|
+
# end
|
50
|
+
#
|
51
|
+
# end
|
52
|
+
# end
|
53
|
+
# end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
Hancock.rails_admin_configure do |config|
|
2
|
+
config.action_visible_for :hancock_cache_global_clear, 'Hancock::Cache::Fragment'
|
3
|
+
config.action_visible_for :hancock_cache_dump_snapshot, 'Hancock::Cache::Fragment'
|
4
|
+
config.action_visible_for :hancock_cache_restore_snapshot, 'Hancock::Cache::Fragment'
|
5
|
+
config.action_visible_for :hancock_cache_clear, 'Hancock::Cache::Fragment'
|
6
|
+
config.action_visible_for :hancock_touch, Proc.new { false }
|
7
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
ru:
|
2
|
+
hancock:
|
3
|
+
cache: 'Кэш'
|
4
|
+
|
5
|
+
mongoid: &mongoid
|
6
|
+
models:
|
7
|
+
hancock/cache/fragment: "Фрагмент"
|
8
|
+
|
9
|
+
attributes:
|
10
|
+
hancock/cache/fragment:
|
11
|
+
name: Метка
|
12
|
+
desc: Описание
|
13
|
+
last_clear_time: Время последнего сброса
|
14
|
+
last_clear_user: Автор последнего сброса
|
15
|
+
clear: Сбросить
|
16
|
+
|
17
|
+
|
18
|
+
activerecord:
|
19
|
+
<<: *mongoid
|
20
|
+
|
21
|
+
|
22
|
+
admin:
|
23
|
+
actions:
|
24
|
+
hancock_cache_clear:
|
25
|
+
menu: "Сбросить кеш"
|
26
|
+
breadcrumb: "Сбросить кеш"
|
27
|
+
title: "Сбросить кеш"
|
28
|
+
hancock_cache_global_clear:
|
29
|
+
menu: "Сброс кеша"
|
30
|
+
breadcrumb: "Сброс кеша"
|
31
|
+
title: "Сброс кеша"
|
32
|
+
hancock_cache_dump_snapshot:
|
33
|
+
menu: "Сохранить снапшот"
|
34
|
+
breadcrumb: "Сохранить снапшот"
|
35
|
+
title: "Сохранить снапшот"
|
36
|
+
hancock_cache_restore_snapshot:
|
37
|
+
menu: "Восстановить снапшот"
|
38
|
+
breadcrumb: "Восстановить снапшот"
|
39
|
+
title: "Восстановить снапшот"
|
40
|
+
hancock_touch:
|
41
|
+
menu: "Обновить контент на сайте"
|
42
|
+
breadcrumb: "Обновить контент на сайте"
|
43
|
+
title: "Обновить контент на сайте"
|
44
|
+
hancock_cache_clear:
|
45
|
+
cleared: 'Кеш %{name} сброшен'
|
46
|
+
error: "Ошибка: %{err}"
|
47
|
+
no_id: "Не указан ID"
|
48
|
+
hancock_touch:
|
49
|
+
touched: 'Обновлено'
|
50
|
+
error: "Ошибка: %{err}"
|
51
|
+
no_id: "Не указан ID"
|
52
|
+
hancock_cache_dump_snapshot:
|
53
|
+
dumped: 'Снапшот сохранен'
|
54
|
+
error: "Ошибка: %{err}"
|
55
|
+
no_id: "Не указан ID"
|
56
|
+
hancock_cache_restore_snapshot:
|
57
|
+
restored: 'Снапшот восстановлен'
|
58
|
+
error: "Ошибка: %{err}"
|
59
|
+
no_id: "Не указан ID"
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'hancock/cache/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "hancock_cms_cache"
|
8
|
+
spec.version = Hancock::Cache::VERSION
|
9
|
+
spec.authors = ["Alexander Kiseliev"]
|
10
|
+
spec.email = ["dev@redrocks.pro"]
|
11
|
+
|
12
|
+
spec.summary = %q{hancock_cms_cache}
|
13
|
+
spec.description = %q{hancock_cms_cache}
|
14
|
+
spec.homepage = "https://github.com/red-rocks/hancock_cms_cache"
|
15
|
+
|
16
|
+
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
17
|
+
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
18
|
+
# if spec.respond_to?(:metadata)
|
19
|
+
# spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
|
20
|
+
# else
|
21
|
+
# raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
|
22
|
+
# end
|
23
|
+
|
24
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
25
|
+
spec.bindir = "exe"
|
26
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
27
|
+
spec.require_paths = ["lib"]
|
28
|
+
|
29
|
+
spec.add_development_dependency "bundler", "~> 1.12"
|
30
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
31
|
+
|
32
|
+
spec.add_dependency 'hancock_cms', [">=1.0.2", "<2.1.x"]
|
33
|
+
# spec.add_dependency 'hancock_cms', ["~> 1.0.2", "~> 2.1.x"]
|
34
|
+
end
|