radiant-cache_by_page-extension 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|