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.
@@ -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 &mdash; or &mdash;
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,4 @@
1
+ - if page.cache_setting == "Default"
2
+ %td.status{:title=>Page.default_caching}= page.cache_setting
3
+ - else
4
+ %td.status= page.cache_setting
@@ -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
@@ -0,0 +1,6 @@
1
+ --colour
2
+ --format
3
+ progress
4
+ --loadby
5
+ mtime
6
+ --reverse
@@ -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