radiant-cache_by_page-extension 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/HELP_admin.textile +17 -0
- data/README.textile +60 -0
- data/Rakefile +136 -0
- data/VERSION +1 -0
- data/app/views/admin/pages/_caching_meta.html.haml +29 -0
- data/app/views/admin/pages/_caching_td.html.haml +4 -0
- data/app/views/admin/pages/_caching_th.html.haml +1 -0
- data/cache_by_page_extension.rb +17 -0
- data/db/migrate/001_add_page_options.rb +11 -0
- data/lib/cache_by_page/page_extensions.rb +87 -0
- data/lib/cache_by_page/site_controller_extensions.rb +18 -0
- data/lib/tasks/cache_by_page_extension_tasks.rake +28 -0
- data/radiant-cache_by_page-extension.gemspec +63 -0
- data/spec/controllers/admin_pages_controller_spec.rb +41 -0
- data/spec/controllers/site_controller_extensions_spec.rb +24 -0
- data/spec/integration/page_caching_spec.rb +112 -0
- data/spec/models/page_extensions_spec.rb +92 -0
- data/spec/spec.opts +6 -0
- data/spec/spec_helper.rb +39 -0
- metadata +104 -0
data/HELP_admin.textile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
h2. Usage
|
2
|
+
|
3
|
+
This is available to admin users only.
|
4
|
+
In Page Edit pane, open the drawer to set caching options specific to that page.
|
5
|
+
Instructions there should be sufficient:
|
6
|
+
* '0' for default caching
|
7
|
+
* '-1' for no caching
|
8
|
+
* 'n' for _n_ minutes caching
|
9
|
+
* or, on the right, set a 24 hr HH:MM time for the cache to expire for this page daily
|
10
|
+
|
11
|
+
h3. Notes
|
12
|
+
|
13
|
+
* The cache_expire_time is being set with a text field with no validation for a few reasons:
|
14
|
+
** The time_select in rails has issues when the :include_blank => true option is set, viz. it consistently throws multi-parameter assignment errors.
|
15
|
+
** At validation time the text entered has already been parsed into a Time object, therefore attempting validates_format_of with a regex for hh:mm is pointless.
|
16
|
+
** Consequently, if you enter "www" it will parse the input into Time 00:00 (midnight). To avoid possible confusion, I have added Current Setting in the meta partial.
|
17
|
+
* Expire time displays as hh:mm, due to fact that it is a Time object being handled by ActiveRecord, it is entered as hh:mm, with seconds defaulting to 00.
|
data/README.textile
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
h2. _Cache by Page_
|
2
|
+
|
3
|
+
Extension for Radiant CMS which enables per page admin option of setting caching to a non-default value, or turning it off altogether
|
4
|
+
|
5
|
+
* Created by: Andrew vonderLuft
|
6
|
+
* Contact: avonderluft [at] avlux [dot] net
|
7
|
+
|
8
|
+
h3. Revision History
|
9
|
+
|
10
|
+
* 1.0 - 4/2009 - Radiant 0.7 compatible, per page caching options
|
11
|
+
|
12
|
+
h3. Requirements
|
13
|
+
|
14
|
+
* Radiant 0.7 or greater
|
15
|
+
* no other known dependencies
|
16
|
+
|
17
|
+
h3. Installation
|
18
|
+
|
19
|
+
From your RADIANT_ROOT:
|
20
|
+
|
21
|
+
* <pre>$ script/extension install cache_by_page</pre>
|
22
|
+
* Restart your radiant app, and you should be good to go.
|
23
|
+
|
24
|
+
h2. Installation
|
25
|
+
|
26
|
+
h3. From the Radiant Extension Registry
|
27
|
+
|
28
|
+
# From your RAILS_ROOT run:
|
29
|
+
<pre>script/extension install cache_by_page</pre>
|
30
|
+
# Restart your app
|
31
|
+
NOTE: In some earlier versions of Radiant, the migrations may not run, and the assets may not be copied and you may therefore need to run:
|
32
|
+
<pre>rake radiant:extensions:cache_by_page:migrate</pre>
|
33
|
+
|
34
|
+
h3. From Github
|
35
|
+
|
36
|
+
# From your RAILS_ROOT run:
|
37
|
+
<pre>cd vendor/extensions
|
38
|
+
git clone git://github.com/avonderluft/radiant-cache_by_page-extension.git ./cache_by_page
|
39
|
+
cd ../../
|
40
|
+
rake radiant:extensions:cache_by_page:migrate
|
41
|
+
</pre>
|
42
|
+
# Restart your app
|
43
|
+
|
44
|
+
h3. Using the gem
|
45
|
+
|
46
|
+
# Install the gem
|
47
|
+
<pre>gem install radiant-cache_by_page-extension</pre>
|
48
|
+
# Update your Radiant config: add to environment.rb with other gem.configs
|
49
|
+
<pre>config.gem 'radiant-cache_by_page-extension', :lib => false</pre>
|
50
|
+
# Run database migrations
|
51
|
+
<pre>rake db:migrate:extensions</pre>
|
52
|
+
# Restart your app
|
53
|
+
|
54
|
+
h3. Usage
|
55
|
+
|
56
|
+
See Admin help doc
|
57
|
+
|
58
|
+
h3. Acknowledgments
|
59
|
+
|
60
|
+
As always, Sean Cribbs lent assistance with the finer points of Ruby, Rails and Radiant. The _Jupiter_ of Holst is still exquisite, even if it is a little bit of overkill for a podcast.
|
data/Rakefile
ADDED
@@ -0,0 +1,136 @@
|
|
1
|
+
begin
|
2
|
+
require 'jeweler'
|
3
|
+
Jeweler::Tasks.new do |gem|
|
4
|
+
gem.name = "radiant-cache_by_page-extension"
|
5
|
+
gem.summary = %Q{Cache By Page Extension for Radiant CMS}
|
6
|
+
gem.description = %Q{Enables per page admin option of setting caching to a non-default value, or turning it off altogether.}
|
7
|
+
gem.email = "avonderluft@avlux.net"
|
8
|
+
gem.homepage = "https://github.com/avonderluft/radiant-cache_by_page-extension"
|
9
|
+
gem.authors = ['Andrew vonderLuft']
|
10
|
+
gem.add_dependency 'radiant', ">=0.9.1"
|
11
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
12
|
+
end
|
13
|
+
rescue LoadError
|
14
|
+
puts "Jeweler (or a dependency) not available. This is only required if you plan to package banner_rotator as a gem."
|
15
|
+
end
|
16
|
+
|
17
|
+
# I think this is the one that should be moved to the extension Rakefile template
|
18
|
+
|
19
|
+
# In rails 1.2, plugins aren't available in the path until they're loaded.
|
20
|
+
# Check to see if the rspec plugin is installed first and require
|
21
|
+
# it if it is. If not, use the gem version.
|
22
|
+
|
23
|
+
# Determine where the RSpec plugin is by loading the boot
|
24
|
+
unless defined? RADIANT_ROOT
|
25
|
+
ENV["RAILS_ENV"] = "test"
|
26
|
+
case
|
27
|
+
when ENV["RADIANT_ENV_FILE"]
|
28
|
+
require File.dirname(ENV["RADIANT_ENV_FILE"]) + "/boot"
|
29
|
+
when File.dirname(__FILE__) =~ %r{vendor/radiant/vendor/extensions}
|
30
|
+
require "#{File.expand_path(File.dirname(__FILE__) + "/../../../../../")}/config/boot"
|
31
|
+
else
|
32
|
+
require "#{File.expand_path(File.dirname(__FILE__) + "/../../../")}/config/boot"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
require 'rake'
|
37
|
+
require 'rake/rdoctask'
|
38
|
+
require 'rake/testtask'
|
39
|
+
|
40
|
+
rspec_base = File.expand_path(RADIANT_ROOT + '/vendor/plugins/rspec/lib')
|
41
|
+
$LOAD_PATH.unshift(rspec_base) if File.exist?(rspec_base)
|
42
|
+
require 'spec/rake/spectask'
|
43
|
+
# require 'spec/translator'
|
44
|
+
|
45
|
+
# Cleanup the RADIANT_ROOT constant so specs will load the environment
|
46
|
+
Object.send(:remove_const, :RADIANT_ROOT)
|
47
|
+
|
48
|
+
extension_root = File.expand_path(File.dirname(__FILE__))
|
49
|
+
|
50
|
+
task :default => :spec
|
51
|
+
task :stats => "spec:statsetup"
|
52
|
+
|
53
|
+
desc "Run all specs in spec directory"
|
54
|
+
Spec::Rake::SpecTask.new(:spec) do |t|
|
55
|
+
t.spec_opts = ['--options', "\"#{extension_root}/spec/spec.opts\""]
|
56
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
57
|
+
end
|
58
|
+
|
59
|
+
namespace :spec do
|
60
|
+
desc "Run all specs in spec directory with RCov"
|
61
|
+
Spec::Rake::SpecTask.new(:rcov) do |t|
|
62
|
+
t.spec_opts = ['--options', "\"#{extension_root}/spec/spec.opts\""]
|
63
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
64
|
+
t.rcov = true
|
65
|
+
t.rcov_opts = ['--exclude', 'spec', '--rails']
|
66
|
+
end
|
67
|
+
|
68
|
+
desc "Print Specdoc for all specs"
|
69
|
+
Spec::Rake::SpecTask.new(:doc) do |t|
|
70
|
+
t.spec_opts = ["--format", "specdoc", "--dry-run"]
|
71
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
72
|
+
end
|
73
|
+
|
74
|
+
[:models, :controllers, :views, :helpers].each do |sub|
|
75
|
+
desc "Run the specs under spec/#{sub}"
|
76
|
+
Spec::Rake::SpecTask.new(sub) do |t|
|
77
|
+
t.spec_opts = ['--options', "\"#{extension_root}/spec/spec.opts\""]
|
78
|
+
t.spec_files = FileList["spec/#{sub}/**/*_spec.rb"]
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
# Hopefully no one has written their extensions in pre-0.9 style
|
83
|
+
# desc "Translate specs from pre-0.9 to 0.9 style"
|
84
|
+
# task :translate do
|
85
|
+
# translator = ::Spec::Translator.new
|
86
|
+
# dir = RAILS_ROOT + '/spec'
|
87
|
+
# translator.translate(dir, dir)
|
88
|
+
# end
|
89
|
+
|
90
|
+
# Setup specs for stats
|
91
|
+
task :statsetup do
|
92
|
+
require 'code_statistics'
|
93
|
+
::STATS_DIRECTORIES << %w(Model\ specs spec/models)
|
94
|
+
::STATS_DIRECTORIES << %w(View\ specs spec/views)
|
95
|
+
::STATS_DIRECTORIES << %w(Controller\ specs spec/controllers)
|
96
|
+
::STATS_DIRECTORIES << %w(Helper\ specs spec/views)
|
97
|
+
::CodeStatistics::TEST_TYPES << "Model specs"
|
98
|
+
::CodeStatistics::TEST_TYPES << "View specs"
|
99
|
+
::CodeStatistics::TEST_TYPES << "Controller specs"
|
100
|
+
::CodeStatistics::TEST_TYPES << "Helper specs"
|
101
|
+
::STATS_DIRECTORIES.delete_if {|a| a[0] =~ /test/}
|
102
|
+
end
|
103
|
+
|
104
|
+
namespace :db do
|
105
|
+
namespace :fixtures do
|
106
|
+
desc "Load fixtures (from spec/fixtures) into the current environment's database. Load specific fixtures using FIXTURES=x,y"
|
107
|
+
task :load => :environment do
|
108
|
+
require 'active_record/fixtures'
|
109
|
+
ActiveRecord::Base.establish_connection(RAILS_ENV.to_sym)
|
110
|
+
(ENV['FIXTURES'] ? ENV['FIXTURES'].split(/,/) : Dir.glob(File.join(RAILS_ROOT, 'spec', 'fixtures', '*.{yml,csv}'))).each do |fixture_file|
|
111
|
+
Fixtures.create_fixtures('spec/fixtures', File.basename(fixture_file, '.*'))
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
desc 'Generate documentation for the page_options extension.'
|
119
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
120
|
+
rdoc.rdoc_dir = 'rdoc'
|
121
|
+
rdoc.title = 'PageOptionsExtension'
|
122
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
123
|
+
rdoc.rdoc_files.include('README')
|
124
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
125
|
+
end
|
126
|
+
|
127
|
+
# For extensions that are in transition
|
128
|
+
desc 'Test the page_options extension.'
|
129
|
+
Rake::TestTask.new(:test) do |t|
|
130
|
+
t.libs << 'lib'
|
131
|
+
t.pattern = 'test/**/*_test.rb'
|
132
|
+
t.verbose = true
|
133
|
+
end
|
134
|
+
|
135
|
+
# Load any custom rakefiles for extension
|
136
|
+
Dir[File.dirname(__FILE__) + '/tasks/*.rake'].sort.each { |f| require f }
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.0.0
|
@@ -0,0 +1,29 @@
|
|
1
|
+
- if current_user.admin?
|
2
|
+
%tr
|
3
|
+
%th.label{:style => "vertical-align:middle"} Page Caching
|
4
|
+
%td.field{:style => "text-align: left"}
|
5
|
+
%table{:style => "vertical-align:top;"}
|
6
|
+
%row
|
7
|
+
%td{:style => "text-align: left"}
|
8
|
+
%label Current Setting:
|
9
|
+
%br
|
10
|
+
= @page.cache_setting if Page.exists? @page
|
11
|
+
%td{:style => "padding-left:40px"}
|
12
|
+
%label Override:
|
13
|
+
%td{:style => "padding-left:10px"}
|
14
|
+
%label Cache this page for
|
15
|
+
= text_field :page, :cache_expire_minutes, {:maxlength => 4}
|
16
|
+
= "minutes"
|
17
|
+
%br
|
18
|
+
%span.desc= "( '0' = Default of #{Page.default_caching}, '-1' = No Caching )"
|
19
|
+
%td — or —
|
20
|
+
%td
|
21
|
+
%label Expire cache each day at
|
22
|
+
= text_field_tag 'page[cache_expire_time]', @page.cache_expire_time ? @page.cache_expire_time.in_time_zone.strftime("%H:%M") : "", {:size => 5, :maxlength => 5}
|
23
|
+
= "(HH:MM)"
|
24
|
+
%br
|
25
|
+
%span.desc= "(Clear expire time to reset default of #{Page.default_caching})"
|
26
|
+
- content_for :page_css do
|
27
|
+
:sass
|
28
|
+
.desc
|
29
|
+
font-size: 80%
|
@@ -0,0 +1 @@
|
|
1
|
+
%th.caching Caching
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# Uncomment this if you reference any of your controllers in activate
|
2
|
+
# require_dependency 'application_controller'
|
3
|
+
|
4
|
+
class CacheByPageExtension < Radiant::Extension
|
5
|
+
version "#{File.read(File.expand_path(File.dirname(__FILE__)) + '/VERSION')}"
|
6
|
+
description "Enables per page admin option of setting caching to a non-default value, or turning it off altogether"
|
7
|
+
url "https://github.com/avonderluft/radiant-cache_by_page-extension"
|
8
|
+
|
9
|
+
def activate
|
10
|
+
SiteController.send :include, CacheByPage::SiteControllerExtensions
|
11
|
+
Page.send :include, CacheByPage::PageExtensions
|
12
|
+
admin.page.index.add :sitemap_head, 'caching_th', :before => 'status_column_header'
|
13
|
+
admin.page.index.add :node, 'caching_td', :before => 'status_column'
|
14
|
+
admin.page.edit.add :extended_metadata, 'caching_meta'
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class AddPageOptions < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
add_column :pages, :cache_expire_minutes, :integer, :allow_nil => false, :default => 0
|
4
|
+
add_column :pages, :cache_expire_time, :time, :default => nil
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.down
|
8
|
+
remove_column :pages, :cache_expire_minutes
|
9
|
+
remove_column :pages, :cache_expire_time
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module CacheByPage::PageExtensions
|
2
|
+
def self.included(base)
|
3
|
+
base.class_eval do
|
4
|
+
extend ClassMethods
|
5
|
+
validates_numericality_of :cache_expire_minutes, :allow_nil => false, :only_integer => true,
|
6
|
+
:message => 'must be a whole number'
|
7
|
+
def validate
|
8
|
+
self.cache_expire_minutes = -1 if self.cache_expire_minutes.to_i < -1
|
9
|
+
if self.cache_expire_minutes.to_i != 0 && self.changes.include?("cache_expire_minutes")
|
10
|
+
self.cache_expire_time = nil
|
11
|
+
end
|
12
|
+
if self.cache_expire_time != nil && self.changes.include?("cache_expire_time")
|
13
|
+
self.cache_expire_minutes = 0
|
14
|
+
end
|
15
|
+
super
|
16
|
+
end
|
17
|
+
|
18
|
+
def cache?
|
19
|
+
self.cache_expire_minutes.to_i >= 0
|
20
|
+
end
|
21
|
+
def cache_override?
|
22
|
+
self.cache_expire_minutes.to_i > 0 || self.cache_expire_time != nil
|
23
|
+
end
|
24
|
+
def cache_duration
|
25
|
+
@page = Page.find(self.id)
|
26
|
+
case true
|
27
|
+
when @page.cache_expire_minutes == 0 && @page.cache_expire_time == nil
|
28
|
+
if SiteController.respond_to?('cache_timeout')
|
29
|
+
SiteController.cache_timeout
|
30
|
+
else
|
31
|
+
ResponseCache.defaults[:expire_time]
|
32
|
+
end
|
33
|
+
when @page.cache_expire_minutes == -1: nil
|
34
|
+
when @page.cache_expire_minutes >= 1: @page.cache_expire_minutes.minutes
|
35
|
+
when @page.cache_expire_time != nil && @page.cache_expire_time.is_a?(Time)
|
36
|
+
next_expire_time = @page.cache_expire_time < Time.now ? @page.cache_expire_time.tomorrow : @page.cache_expire_time
|
37
|
+
(next_expire_time - Time.now).round
|
38
|
+
else nil
|
39
|
+
end
|
40
|
+
end
|
41
|
+
def cache_setting
|
42
|
+
@page = Page.find(self.id)
|
43
|
+
case true
|
44
|
+
when @page.cache_expire_minutes == 0 && @page.cache_expire_time == nil: Page.default_caching
|
45
|
+
when @page.cache_expire_minutes == -1: "No Caching"
|
46
|
+
when @page.cache_expire_minutes == 1: "1 minute"
|
47
|
+
when @page.cache_expire_minutes > 1: "#{@page.cache_expire_minutes} minutes"
|
48
|
+
when @page.cache_expire_time != nil && @page.cache_expire_time.is_a?(Time)
|
49
|
+
"Daily at #{@page.cache_expire_time.strftime("%H")}:#{@page.cache_expire_time.strftime("%M")}"
|
50
|
+
else "Not set"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
alias_method_chain :process, :expire_time
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def process_with_expire_time(request, response)
|
58
|
+
if cache?
|
59
|
+
if cache_expire_minutes.to_i > 0
|
60
|
+
response.cache_timeout = cache_expire_minutes.minutes.from_now
|
61
|
+
elsif ! cache_expire_time.nil?
|
62
|
+
expire_time = Time.parse("#{cache_expire_time.hour}:#{cache_expire_time.min}")
|
63
|
+
response.cache_timeout = expire_time < Time.now ? expire_time.tomorrow : expire_time
|
64
|
+
end
|
65
|
+
end
|
66
|
+
process_without_expire_time(request, response)
|
67
|
+
end
|
68
|
+
|
69
|
+
module ClassMethods
|
70
|
+
def default_caching
|
71
|
+
seconds = SiteController.respond_to?('cache_timeout') ? SiteController.cache_timeout : ResponseCache.defaults[:expire_time]
|
72
|
+
cache_expire_time = case true
|
73
|
+
when seconds >= 86400
|
74
|
+
"#{seconds/86400} days"
|
75
|
+
when seconds >= 3600
|
76
|
+
"#{seconds/3600} hours"
|
77
|
+
when seconds >= 120
|
78
|
+
"#{seconds/60} minutes"
|
79
|
+
else
|
80
|
+
"#{seconds} seconds"
|
81
|
+
end
|
82
|
+
cache_expire_time = cache_expire_time.chop if cache_expire_time[0,1] == "1"
|
83
|
+
cache_expire_time
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module CacheByPage::SiteControllerExtensions
|
2
|
+
def self.included(base)
|
3
|
+
base.class_eval do
|
4
|
+
alias_method_chain :set_cache_control, :cache_by_page
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def set_cache_control_with_cache_by_page
|
11
|
+
if (request.head? || request.get?) && @page.cache? && @page.cache_duration && live?
|
12
|
+
expires_in @page.cache_duration, :public => true, :private => false
|
13
|
+
else
|
14
|
+
set_cache_control_without_cache_by_page
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
namespace :radiant do
|
2
|
+
namespace :extensions do
|
3
|
+
namespace :cache_by_page do
|
4
|
+
|
5
|
+
desc "Runs the migration of the Cache By Page extension"
|
6
|
+
task :migrate => :environment do
|
7
|
+
require 'radiant/extension_migrator'
|
8
|
+
if ENV["VERSION"]
|
9
|
+
CacheByPageExtension.migrator.migrate(ENV["VERSION"].to_i)
|
10
|
+
else
|
11
|
+
CacheByPageExtension.migrator.migrate
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
desc "Copies public assets of the Page Options to the instance public/ directory."
|
16
|
+
task :update => :environment do
|
17
|
+
is_svn_or_dir = proc {|path| path =~ /\.svn/ || File.directory?(path) }
|
18
|
+
Dir[CacheByPageExtension.root + "/public/**/*"].reject(&is_svn_or_dir).each do |file|
|
19
|
+
path = file.sub(CacheByPageExtension.root, '')
|
20
|
+
directory = File.dirname(path)
|
21
|
+
puts "Copying #{path}..."
|
22
|
+
mkdir_p RAILS_ROOT + directory
|
23
|
+
cp file, RAILS_ROOT + path
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{radiant-cache_by_page-extension}
|
8
|
+
s.version = "1.0.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Andrew vonderLuft"]
|
12
|
+
s.date = %q{2011-05-09}
|
13
|
+
s.description = %q{Enables per page admin option of setting caching to a non-default value, or turning it off altogether.}
|
14
|
+
s.email = %q{avonderluft@avlux.net}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"README.textile"
|
17
|
+
]
|
18
|
+
s.files = [
|
19
|
+
"HELP_admin.textile",
|
20
|
+
"README.textile",
|
21
|
+
"Rakefile",
|
22
|
+
"VERSION",
|
23
|
+
"app/views/admin/pages/_caching_meta.html.haml",
|
24
|
+
"app/views/admin/pages/_caching_td.html.haml",
|
25
|
+
"app/views/admin/pages/_caching_th.html.haml",
|
26
|
+
"cache_by_page_extension.rb",
|
27
|
+
"db/migrate/001_add_page_options.rb",
|
28
|
+
"lib/cache_by_page/page_extensions.rb",
|
29
|
+
"lib/cache_by_page/site_controller_extensions.rb",
|
30
|
+
"lib/tasks/cache_by_page_extension_tasks.rake",
|
31
|
+
"radiant-cache_by_page-extension.gemspec",
|
32
|
+
"spec/controllers/admin_pages_controller_spec.rb",
|
33
|
+
"spec/controllers/site_controller_extensions_spec.rb",
|
34
|
+
"spec/integration/page_caching_spec.rb",
|
35
|
+
"spec/models/page_extensions_spec.rb",
|
36
|
+
"spec/spec.opts",
|
37
|
+
"spec/spec_helper.rb"
|
38
|
+
]
|
39
|
+
s.homepage = %q{https://github.com/avonderluft/radiant-cache_by_page-extension}
|
40
|
+
s.require_paths = ["lib"]
|
41
|
+
s.rubygems_version = %q{1.6.2}
|
42
|
+
s.summary = %q{Cache By Page Extension for Radiant CMS}
|
43
|
+
s.test_files = [
|
44
|
+
"spec/controllers/admin_pages_controller_spec.rb",
|
45
|
+
"spec/controllers/site_controller_extensions_spec.rb",
|
46
|
+
"spec/integration/page_caching_spec.rb",
|
47
|
+
"spec/models/page_extensions_spec.rb",
|
48
|
+
"spec/spec_helper.rb"
|
49
|
+
]
|
50
|
+
|
51
|
+
if s.respond_to? :specification_version then
|
52
|
+
s.specification_version = 3
|
53
|
+
|
54
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
55
|
+
s.add_runtime_dependency(%q<radiant>, [">= 0.9.1"])
|
56
|
+
else
|
57
|
+
s.add_dependency(%q<radiant>, [">= 0.9.1"])
|
58
|
+
end
|
59
|
+
else
|
60
|
+
s.add_dependency(%q<radiant>, [">= 0.9.1"])
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
Admin::PagesController.module_eval { def rescue_action(e); raise e; end }
|
4
|
+
|
5
|
+
describe Admin::PagesController, 'with cache_by_page' do
|
6
|
+
dataset :users_and_pages
|
7
|
+
integrate_views
|
8
|
+
|
9
|
+
before :each do
|
10
|
+
@page = pages(:home)
|
11
|
+
end
|
12
|
+
|
13
|
+
[:admin, :non_admin, :designer].each do |user|
|
14
|
+
describe "privileges for user '#{user}'" do
|
15
|
+
before(:each) do
|
16
|
+
login_as user
|
17
|
+
end
|
18
|
+
it "should display admin edit page on a new page" do
|
19
|
+
get :new
|
20
|
+
response.should render_template('new')
|
21
|
+
end
|
22
|
+
if user == :admin
|
23
|
+
it "should display page caching options on the admin edit page for an existing page" do
|
24
|
+
get :edit, :id => @page
|
25
|
+
response.should include_text("Cache this page for")
|
26
|
+
end
|
27
|
+
else
|
28
|
+
it "should not display page caching options on the admin edit page for an existing page" do
|
29
|
+
get :edit, :id => @page
|
30
|
+
response.should_not include_text("Cache this page for")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
after :each do
|
37
|
+
response.should be_success
|
38
|
+
logout
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
require 'site_controller'
|
3
|
+
SiteController.module_eval { def rescue_action(e); raise e; end }
|
4
|
+
|
5
|
+
describe SiteController, "(Extended) - cache by page changes" do
|
6
|
+
dataset :users_and_pages
|
7
|
+
|
8
|
+
before :each do
|
9
|
+
@page = pages(:home)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should include the extension module" do
|
13
|
+
SiteController.included_modules.should include(CacheByPage::SiteControllerExtensions)
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "alias method chain" do
|
17
|
+
it "should be set up" do
|
18
|
+
controller.private_methods.should include('set_cache_control_with_cache_by_page')
|
19
|
+
controller.private_methods.should include('set_cache_control_without_cache_by_page')
|
20
|
+
controller.private_methods.should include('set_cache_control')
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe Page, "with page-specific caching", :type => :integration do
|
4
|
+
dataset :pages
|
5
|
+
USING_RACK_CACHE = SiteController.respond_to?('cache_timeout')
|
6
|
+
|
7
|
+
before :all do
|
8
|
+
@cache_dir = "#{RAILS_ROOT}/tmp/cache"
|
9
|
+
@cache_file = USING_RACK_CACHE ? "#{@cache_dir}/meta/*/*" : "#{@cache_dir}/_site-root.yml"
|
10
|
+
end
|
11
|
+
|
12
|
+
before :each do
|
13
|
+
@page = pages(:home)
|
14
|
+
@default = 1.day
|
15
|
+
if USING_RACK_CACHE
|
16
|
+
SiteController.page_cache_directory = @cache_dir
|
17
|
+
SiteController.perform_caching = true
|
18
|
+
SiteController.cache_timeout = @default
|
19
|
+
else
|
20
|
+
ResponseCache.defaults[:directory] = @cache_dir
|
21
|
+
ResponseCache.defaults[:perform_caching] = true
|
22
|
+
ResponseCache.defaults[:expire_time] = @default
|
23
|
+
end
|
24
|
+
@expire_mins = @default.to_i/60
|
25
|
+
@cache = USING_RACK_CACHE ? Radiant::Cache : ResponseCache.instance
|
26
|
+
@cache.clear
|
27
|
+
end
|
28
|
+
|
29
|
+
def page_is_cached(page)
|
30
|
+
if response.nil?
|
31
|
+
@cache.clear
|
32
|
+
false
|
33
|
+
elsif USING_RACK_CACHE
|
34
|
+
! response.headers['Cache-Control'].include?('no-cache')
|
35
|
+
else
|
36
|
+
@cache.response_cached?(page.url)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def cache_expires
|
41
|
+
if USING_RACK_CACHE
|
42
|
+
Time.now + `cat #{@cache_file}`.split('max-age=')[1].split(',')[0].to_i rescue nil
|
43
|
+
else
|
44
|
+
YAML.load_file(@cache_file)['expires'] rescue nil
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "- intial fetch of page before updates" do
|
49
|
+
it "should render a page with default caching" do
|
50
|
+
get "#{@page.slug}"
|
51
|
+
response.should be_success
|
52
|
+
response.cache_timeout.should be_nil
|
53
|
+
page_is_cached(@page).should be_true
|
54
|
+
if USING_RACK_CACHE
|
55
|
+
response.headers['Cache-Control'].should == "max-age=#{@default}, public"
|
56
|
+
else
|
57
|
+
@cache.expire_time.should == @default
|
58
|
+
@cache.response_cached?(@page.url).should be_true
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
%w(minutes time).each do |att|
|
64
|
+
describe "- page with specific caching option by #{att}" do
|
65
|
+
|
66
|
+
before(:each) do
|
67
|
+
page_is_cached(@page).should be_false
|
68
|
+
@expire_mins = 180
|
69
|
+
@expire_time = @expire_mins.minutes.from_now
|
70
|
+
if att == "minutes"
|
71
|
+
@page.cache_expire_minutes = @expire_mins
|
72
|
+
elsif att == "time"
|
73
|
+
@page.cache_expire_time = @expire_time
|
74
|
+
end
|
75
|
+
@page.save!
|
76
|
+
get "#{@page.slug}"
|
77
|
+
page_is_cached(@page).should be_true
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should cache page for the specified #{att}" do
|
81
|
+
cache_expires.should be_close(@expire_mins.minutes.from_now, 30)
|
82
|
+
end
|
83
|
+
it "should re-cache the page if the expire_time is past" do
|
84
|
+
if USING_RACK_CACHE
|
85
|
+
unless `ls #{@cache_dir}/meta`.blank?
|
86
|
+
file_name = `ls -1 #{@cache_dir}/meta/*/*`.strip
|
87
|
+
file_contents = `cat #{file_name}`
|
88
|
+
year = Time.now.strftime('%Y')
|
89
|
+
file_contents = file_contents.sub(" #{year} ", " #{(year.to_i-1).to_s} ")
|
90
|
+
FileUtils.rm(file_name)
|
91
|
+
File.open(file_name, 'w') { |f| f.write(file_contents) }
|
92
|
+
end
|
93
|
+
else
|
94
|
+
file_contents = YAML.load_file(@cache_file)
|
95
|
+
file_contents['expires'] = 1.year.ago
|
96
|
+
FileUtils.rm(@cache_file)
|
97
|
+
File.open(@cache_file, 'w') { |f| f.write(file_contents.to_yaml) }
|
98
|
+
end
|
99
|
+
`sleep 1`
|
100
|
+
2.times { get "#{@page.slug}" }
|
101
|
+
page_is_cached(@page).should be_true
|
102
|
+
response.headers['Age'].should == "0" if USING_RACK_CACHE
|
103
|
+
cache_expires.should be_close(@expire_mins.minutes.from_now, 30)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
after(:each) do
|
109
|
+
@cache.clear
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe "CacheByPage::PageExtensions" do
|
4
|
+
dataset :pages
|
5
|
+
|
6
|
+
describe "page with Cache By Page extension" do
|
7
|
+
|
8
|
+
before(:each) do
|
9
|
+
@page = pages(:home)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should have alias method chain set up" do
|
13
|
+
@page.should respond_to(:process_without_expire_time)
|
14
|
+
@page.should respond_to(:process_with_expire_time)
|
15
|
+
@page.should respond_to(:process)
|
16
|
+
end
|
17
|
+
it "should have class method for default_caching" do
|
18
|
+
Page.should respond_to(:default_caching)
|
19
|
+
end
|
20
|
+
%w{cache_override? cache_duration cache_setting process_with_expire_time}.each do |method|
|
21
|
+
it "should have #{method} method" do
|
22
|
+
@page.should respond_to(method)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
it "should be valid" do
|
26
|
+
@page.should be_valid
|
27
|
+
end
|
28
|
+
it 'should cache by by default' do
|
29
|
+
@page.cache?.should == true
|
30
|
+
@page.cache_duration.should == 86400
|
31
|
+
@page.cache_setting.should == "1 day"
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "- after updates and validation with save" do
|
35
|
+
it "should return error if non-numeric is entered for cache_expire_minutes" do
|
36
|
+
@page.cache_expire_minutes = "five"
|
37
|
+
@page.save.should raise_error
|
38
|
+
end
|
39
|
+
it "should return error if non-integer is entered for cache_expire_minutes" do
|
40
|
+
@page.cache_expire_minutes = "3.3"
|
41
|
+
@page.save.should raise_error
|
42
|
+
end
|
43
|
+
it "should set cache_expire_minutes to 0 when cache_expire_time is updated" do
|
44
|
+
@page.update_attribute(:cache_expire_minutes, 30)
|
45
|
+
@page.cache_expire_time = 2.days.from_now
|
46
|
+
@page.save
|
47
|
+
@page.cache_expire_minutes.should == 0
|
48
|
+
@page.cache_duration.should be_close(2.days.to_i,2)
|
49
|
+
@page.cache_setting.should == "Daily at #{Time.now.strftime('%H:%M')}"
|
50
|
+
end
|
51
|
+
it "should set cache_expire_time to nil when cache_expire_minutes is updated" do
|
52
|
+
@page.update_attribute(:cache_expire_time, 1.day.from_now)
|
53
|
+
@page.cache_expire_minutes = 30
|
54
|
+
@page.save
|
55
|
+
@page.cache_expire_time.should be_nil
|
56
|
+
@page.cache_duration.should be_close(30.minutes.to_i,2)
|
57
|
+
@page.cache_setting.should == "30 minutes"
|
58
|
+
end
|
59
|
+
it "should not cache after setting cache_expire_minutes to -1" do
|
60
|
+
@page.update_attribute(:cache_expire_minutes, -1)
|
61
|
+
@page.cache?.should == false
|
62
|
+
@page.cache_duration.should be_nil
|
63
|
+
@page.cache_setting.should == "No Caching"
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "- updating a page which has caching turned off" do
|
67
|
+
before :each do
|
68
|
+
@page.update_attribute(:cache_expire_minutes, -1)
|
69
|
+
@page.cache?.should == false
|
70
|
+
@page.cache_duration.should be_nil
|
71
|
+
@page.cache_setting.should == "No Caching"
|
72
|
+
end
|
73
|
+
it "should cache after updating cache_expire_minutes" do
|
74
|
+
@page.cache_expire_minutes = 30
|
75
|
+
@page.save
|
76
|
+
@page.cache?.should == true
|
77
|
+
@page.cache_duration.should be_close(30.minutes.to_i,2)
|
78
|
+
@page.cache_setting.should == "30 minutes"
|
79
|
+
end
|
80
|
+
it "should cache after updating cache_expire_time" do
|
81
|
+
@page.cache_expire_time = 2.days.from_now
|
82
|
+
@page.save
|
83
|
+
@page.cache?.should == true
|
84
|
+
@page.cache_duration.should be_close(2.days.to_i,2)
|
85
|
+
@page.cache_setting.should == "Daily at #{Time.now.strftime('%H:%M')}"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
unless defined? RADIANT_ROOT
|
2
|
+
ENV["RAILS_ENV"] = "test"
|
3
|
+
case
|
4
|
+
when ENV["RADIANT_ENV_FILE"]
|
5
|
+
require ENV["RADIANT_ENV_FILE"]
|
6
|
+
when File.dirname(__FILE__) =~ %r{vendor/radiant/vendor/extensions}
|
7
|
+
require "#{File.expand_path(File.dirname(__FILE__) + "/../../../../../../")}/config/environment"
|
8
|
+
else
|
9
|
+
require "#{File.expand_path(File.dirname(__FILE__) + "/../../../../")}/config/environment"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
require "#{RADIANT_ROOT}/spec/spec_helper"
|
13
|
+
|
14
|
+
# if File.directory?(File.dirname(__FILE__) + "/scenarios")
|
15
|
+
# Scenario.load_paths.unshift File.dirname(__FILE__) + "/scenarios"
|
16
|
+
# end
|
17
|
+
Dataset::Resolver.default << (File.dirname(__FILE__) + "/datasets")
|
18
|
+
|
19
|
+
if File.directory?(File.dirname(__FILE__) + "/matchers")
|
20
|
+
Dir[File.dirname(__FILE__) + "/matchers/*.rb"].each {|file| require file }
|
21
|
+
end
|
22
|
+
|
23
|
+
Spec::Runner.configure do |config|
|
24
|
+
# config.use_transactional_fixtures = true
|
25
|
+
# config.use_instantiated_fixtures = false
|
26
|
+
# config.fixture_path = RAILS_ROOT + '/spec/fixtures'
|
27
|
+
|
28
|
+
# You can declare fixtures for each behaviour like this:
|
29
|
+
# describe "...." do
|
30
|
+
# fixtures :table_a, :table_b
|
31
|
+
#
|
32
|
+
# Alternatively, if you prefer to declare them only once, you can
|
33
|
+
# do so here, like so ...
|
34
|
+
#
|
35
|
+
# config.global_fixtures = :table_a, :table_b
|
36
|
+
#
|
37
|
+
# If you declare global fixtures, be aware that they will be declared
|
38
|
+
# for all of your examples, even those that don't use them.
|
39
|
+
end
|
metadata
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: radiant-cache_by_page-extension
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 23
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
- 0
|
10
|
+
version: 1.0.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Andrew vonderLuft
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-05-09 00:00:00 -07:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: radiant
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 57
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
- 9
|
33
|
+
- 1
|
34
|
+
version: 0.9.1
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id001
|
37
|
+
description: Enables per page admin option of setting caching to a non-default value, or turning it off altogether.
|
38
|
+
email: avonderluft@avlux.net
|
39
|
+
executables: []
|
40
|
+
|
41
|
+
extensions: []
|
42
|
+
|
43
|
+
extra_rdoc_files:
|
44
|
+
- README.textile
|
45
|
+
files:
|
46
|
+
- HELP_admin.textile
|
47
|
+
- README.textile
|
48
|
+
- Rakefile
|
49
|
+
- VERSION
|
50
|
+
- app/views/admin/pages/_caching_meta.html.haml
|
51
|
+
- app/views/admin/pages/_caching_td.html.haml
|
52
|
+
- app/views/admin/pages/_caching_th.html.haml
|
53
|
+
- cache_by_page_extension.rb
|
54
|
+
- db/migrate/001_add_page_options.rb
|
55
|
+
- lib/cache_by_page/page_extensions.rb
|
56
|
+
- lib/cache_by_page/site_controller_extensions.rb
|
57
|
+
- lib/tasks/cache_by_page_extension_tasks.rake
|
58
|
+
- radiant-cache_by_page-extension.gemspec
|
59
|
+
- spec/controllers/admin_pages_controller_spec.rb
|
60
|
+
- spec/controllers/site_controller_extensions_spec.rb
|
61
|
+
- spec/integration/page_caching_spec.rb
|
62
|
+
- spec/models/page_extensions_spec.rb
|
63
|
+
- spec/spec.opts
|
64
|
+
- spec/spec_helper.rb
|
65
|
+
has_rdoc: true
|
66
|
+
homepage: https://github.com/avonderluft/radiant-cache_by_page-extension
|
67
|
+
licenses: []
|
68
|
+
|
69
|
+
post_install_message:
|
70
|
+
rdoc_options: []
|
71
|
+
|
72
|
+
require_paths:
|
73
|
+
- lib
|
74
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
75
|
+
none: false
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
hash: 3
|
80
|
+
segments:
|
81
|
+
- 0
|
82
|
+
version: "0"
|
83
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
|
+
none: false
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
hash: 3
|
89
|
+
segments:
|
90
|
+
- 0
|
91
|
+
version: "0"
|
92
|
+
requirements: []
|
93
|
+
|
94
|
+
rubyforge_project:
|
95
|
+
rubygems_version: 1.6.2
|
96
|
+
signing_key:
|
97
|
+
specification_version: 3
|
98
|
+
summary: Cache By Page Extension for Radiant CMS
|
99
|
+
test_files:
|
100
|
+
- spec/controllers/admin_pages_controller_spec.rb
|
101
|
+
- spec/controllers/site_controller_extensions_spec.rb
|
102
|
+
- spec/integration/page_caching_spec.rb
|
103
|
+
- spec/models/page_extensions_spec.rb
|
104
|
+
- spec/spec_helper.rb
|