new cache strategy + remember_me set to true by default + fix bugs (one with mongo_tree)

This commit is contained in:
dinedine 2010-07-09 12:38:50 +02:00
parent 4e2e6411f3
commit cc03e0b774
16 changed files with 140 additions and 54 deletions

View File

@ -20,13 +20,14 @@ module Admin::PagesHelper
list
end
def options_for_page_cache_expiration
def options_for_page_cache_strategy
[
[t('.expiration.never'), 0],
[t('.expiration.hour'), 1.hour],
[t('.expiration.day'), 1.day],
[t('.expiration.week'), 1.week],
[t('.expiration.month'), 1.month]
[t('.cache_strategy.none'), 'none'],
[t('.cache_strategy.simple'), 'simple'],
[t('.cache_strategy.hour'), 1.hour.to_s],
[t('.cache_strategy.day'), 1.day.to_s],
[t('.cache_strategy.week'), 1.week.to_s],
[t('.cache_strategy.month'), 1.month.to_s]
]
end

View File

@ -23,7 +23,6 @@ module Models
before_destroy :remove_from_list
# Fixme (Didier L.): Instances methods are defined before the include itself
alias :ancestors :hacked_ancestors
alias :fix_position :hacked_fix_position
end
@ -43,11 +42,6 @@ module Models
self.instance_variable_set :@_will_move, true
end
def hacked_ancestors
return [] if root?
self.class.find(self.path.clone << nil) # bug in mongoid (it does not handle array with one element)
end
protected
def change_parent

View File

@ -12,7 +12,7 @@ class Page
field :slug
field :fullpath
field :published, :type => Boolean, :default => false
field :cache_expires_in, :type => Integer, :default => 0
field :cache_strategy, :default => 'none'
## associations ##
belongs_to_related :site
@ -35,7 +35,6 @@ class Page
named_scope :not_found, :where => { :slug => '404', :depth => 0, :published => true }
## behaviours ##
# liquid_methods :title, :fullpath
liquify_template :joined_parts
## methods ##
@ -66,6 +65,10 @@ class Page
"http://#{self.site.domains.first}/#{self.fullpath}.html"
end
def with_cache?
self.cache_strategy != 'none'
end
def to_liquid(options = {})
Locomotive::Liquid::Drops::Page.new(self)
end
@ -73,9 +76,6 @@ class Page
protected
def do_not_remove_index_and_404_pages
# safe_site = self.site rescue nil
# return if safe_site.nil?
return if (self.site rescue nil).nil?
if self.index? || self.not_found?

View File

@ -16,7 +16,7 @@
= f.custom_input :published, :css => 'toggle' do
= f.check_box :published
= f.input :cache_expires_in, :as => :select, :collection => options_for_page_cache_expiration, :include_blank => false
= f.input :cache_strategy, :as => :select, :collection => options_for_page_cache_strategy, :include_blank => false
#page-parts
.nav

View File

@ -1,6 +1,8 @@
- title t('.title')
= semantic_form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f|
= f.hidden_field :remember_me, :value => "true"
.inner
= login_flash_message

View File

@ -25,8 +25,7 @@ en:
site: Site
theme_assets: Theme files
footer:
developed_by: Developed by
powered_by: and Powered by
who_is_behind: "Service developed by {{development}} and designed by <a href=\"http://www.sachagreif.com\">Sacha Greif</a>"
form_actions:
back: Back without saving
create: Create
@ -97,8 +96,9 @@ en:
failed_create: "Page was not created."
failed_update: "Page was not updated."
form:
expiration:
never: Never
cache_strategy:
none: None
simple: Simple
hour: 1 hour
day: 1 day
week: 1 week
@ -331,7 +331,7 @@ en:
hints:
page:
published: "Only authenticated accounts can view unpublished pages."
cache_expires_in: "Cache the page for better performance. Pressing shift-reload in the browser will regenerate the page."
cache_strategy: "Cache the page for better performance. The 'Simple' choice is a good compromise."
snippet:
slug: "You need to know it in order to insert the snippet inside a page or a layout"
site:

View File

@ -118,8 +118,9 @@ fr:
failed_create: "La page n'a pas été créée."
failed_update: "La page n'a pas été mise à jour."
form:
expiration:
never: Jamais
cache_strategy:
none: Aucun
simple: Simple
hour: 1 heure
day: 1 jour
week: 1 semaine
@ -352,7 +353,7 @@ fr:
hints:
page:
published: "Seuls les administrateurs authentifiés peuvent voir une page non publiée."
cache_expires_in: "Cache la page pour de meilleure performance. Presser la touche SHIFT et le bouton \"Rafraichir\" dans le navigateur rechargera la page."
cache_strategy: "Cache la page pour de meilleure performance. L'option 'Simple' est le meilleur compromis."
snippet:
slug: "Utilisé pour insérer le snippet dans une page ou un gabarit."
site:

View File

@ -57,7 +57,7 @@ fr:
parent: Parent
slug: Raccourci
published: Publiée
cache_expires_in: Cache expire dans
cache_strategy: Cache
content_type:
name: Nom
description: Description

View File

@ -4,6 +4,10 @@ BOARD:
- refactor slugify method (use parameterize + create a module)
- change action icons according to the right action [Sacha]
- page redirection (option)
- send email when new content added thru api
- sitemap
- save layout / snippet / page / stylesheet / javascript with CMD + S (ajax)
BACKLOG:
@ -12,7 +16,6 @@ BACKLOG:
- new custom field types:
- belongs_to => association
- cucumber features for admin pages
- sitemap
- validation for custom fields
BUGS:
@ -54,3 +57,5 @@ x localize application in French
x change credits in the admin footer
x license
x textile filter
x [bug] varnish can not be refreshed in heroku so "max-age" has to be disabled => modify cache strategy
x "remember me" should always be enabled

View File

@ -30,3 +30,33 @@ class String
end
end
## Hash
class Hash
def underscore_keys
new_hash = {}
self.each_pair do |key, value|
if value.respond_to?(:collect!) # Array
value.collect do |item|
if item.respond_to?(:each_pair) # Hash item within
item.underscore_keys
else
item
end
end
elsif value.respond_to?(:each_pair) # Hash
value = value.underscore_keys
end
new_key = key.is_a?(String) ? key.underscore : key # only String keys
new_hash[new_key] = value
end
self.replace(new_hash)
end
end

View File

@ -17,8 +17,9 @@ module Locomotive
puts "[WebService] consuming #{path}, #{options.inspect}"
self.get(path, options)
self.get(path, options).try(:underscore_keys)
end
end
end
end

View File

@ -14,7 +14,7 @@ module Locomotive
output = @page.render(locomotive_context)
prepare_and_set_response(output, @page.cache_expires_in || 0)
prepare_and_set_response(output)
end
def locomotive_page
@ -48,9 +48,17 @@ module Locomotive
::Liquid::Context.new(assigns, registers)
end
def prepare_and_set_response(output, cache_expiration = 0)
response.headers['Cache-Control'] = "public, max-age=#{cache_expiration}" if cache_expiration > 0
def prepare_and_set_response(output)
response.headers['Content-Type'] = 'text/html; charset=utf-8'
if @page.with_cache?
fresh_when :etag => @page, :last_modified => @page.updated_at.utc, :public => true
if @page.cache_strategy != 'simple' # varnish
response.cache_control[:max_age] = @page.cache_strategy
end
end
render :text => output, :layout => false, :status => :ok
end

37
spec/lib/core_ext_spec.rb Normal file
View File

@ -0,0 +1,37 @@
require 'spec_helper'
describe 'Core extensions' do
describe 'Adding new methods for Hash items' do
describe 'defining underscore_keys' do
context 'from simple plain hash' do
it 'underscores each key' do
{ 'foo-bar' => 42, :foo => 42, 'foo' => 42 }.underscore_keys.should == { 'foo_bar' => 42, :foo => 42, 'foo' => 42 }
end
end
context 'from nested hashes' do
it 'underscores each key' do
{ 'foo-bar' => { 'bar-foo' => 42, :test => { 'bar-foo' => 42 } } }.underscore_keys.should == { 'foo_bar' => { 'bar_foo' => 42, :test => { 'bar_foo' => 42 } } }
end
end
context 'from hash with arrays of hashes' do
it 'underscores each key' do
{ 'foo-bar' => [{ 'bar-foo' => 42 }, 42, { 'bar-foo' => 42 }] }.underscore_keys.should == { 'foo_bar' => [{ 'bar_foo' => 42 }, 42, { 'bar_foo' => 42 }] }
end
end
end
end
end

View File

@ -8,11 +8,13 @@ describe 'Locomotive rendering system' do
@site = Factory.build(:site)
Site.stubs(:find).returns(@site)
@controller.current_site = @site
@page = Factory.build(:page, :site => nil, :published => true)
end
context 'setting the response' do
before(:each) do
@controller.instance_variable_set(:@page, @page)
@controller.send(:prepare_and_set_response, 'Hello world !')
end
@ -28,20 +30,26 @@ describe 'Locomotive rendering system' do
@controller.response.headers['Cache-Control'].should be_nil
end
it 'sets the cache' do
@controller.send(:prepare_and_set_response, 'Hello world !', 3600)
@controller.response.headers['Cache-Control'].should == 'public, max-age=3600'
it 'sets the cache by simply using etag' do
@page.cache_strategy = 'simple'
@page.stubs(:updated_at).returns(Time.now)
@controller.send(:prepare_and_set_response, 'Hello world !')
@controller.response.to_a # force to build headers
@controller.response.headers['Cache-Control'].should == 'public'
end
it 'sets the cache for Varnish' do
@page.cache_strategy = '3600'
@page.stubs(:updated_at).returns(Time.now)
@controller.send(:prepare_and_set_response, 'Hello world !')
@controller.response.to_a # force to build headers
@controller.response.headers['Cache-Control'].should == 'max-age=3600, public'
end
end
context 'when retrieving page' do
before(:each) do
@page = Factory.build(:page, :site => nil, :published => true)
@controller
end
it 'should retrieve the index page /' do
@controller.request.fullpath = '/'
@controller.current_site.pages.expects(:where).with({ :fullpath => 'index' }).returns([@page])

View File

@ -74,6 +74,11 @@ describe Page do
page.slug.should == 'Valid_ite'
end
it 'has no cache strategy' do
page = Factory.build(:page, :site => nil)
page.with_cache?.should == false
end
end
describe 'delete' do

View File

@ -4,7 +4,7 @@ Locomotive.configure do |config|
end
module Locomotive
class TestController
class TestController < ApplicationController
include Locomotive::Render
@ -15,26 +15,20 @@ module Locomotive
end
def response
@response ||= TestResponse.new
@_response ||= TestResponse.new
end
def request
@request ||= TestRequest.new
@_request ||= TestRequest.new
end
end
class TestResponse
attr_accessor :headers
def initialize
self.headers = {}
end
class TestResponse < ActionDispatch::TestResponse
end
class TestRequest
class TestRequest < ActionDispatch::TestRequest
attr_accessor :fullpath