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.
@@ -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