new cache strategy + remember_me set to true by default + fix bugs (one with mongo_tree)
This commit is contained in:
parent
4e2e6411f3
commit
cc03e0b774
@ -20,13 +20,14 @@ module Admin::PagesHelper
|
|||||||
list
|
list
|
||||||
end
|
end
|
||||||
|
|
||||||
def options_for_page_cache_expiration
|
def options_for_page_cache_strategy
|
||||||
[
|
[
|
||||||
[t('.expiration.never'), 0],
|
[t('.cache_strategy.none'), 'none'],
|
||||||
[t('.expiration.hour'), 1.hour],
|
[t('.cache_strategy.simple'), 'simple'],
|
||||||
[t('.expiration.day'), 1.day],
|
[t('.cache_strategy.hour'), 1.hour.to_s],
|
||||||
[t('.expiration.week'), 1.week],
|
[t('.cache_strategy.day'), 1.day.to_s],
|
||||||
[t('.expiration.month'), 1.month]
|
[t('.cache_strategy.week'), 1.week.to_s],
|
||||||
|
[t('.cache_strategy.month'), 1.month.to_s]
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -23,7 +23,6 @@ module Models
|
|||||||
before_destroy :remove_from_list
|
before_destroy :remove_from_list
|
||||||
|
|
||||||
# Fixme (Didier L.): Instances methods are defined before the include itself
|
# Fixme (Didier L.): Instances methods are defined before the include itself
|
||||||
alias :ancestors :hacked_ancestors
|
|
||||||
alias :fix_position :hacked_fix_position
|
alias :fix_position :hacked_fix_position
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -43,11 +42,6 @@ module Models
|
|||||||
self.instance_variable_set :@_will_move, true
|
self.instance_variable_set :@_will_move, true
|
||||||
end
|
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
|
protected
|
||||||
|
|
||||||
def change_parent
|
def change_parent
|
||||||
|
@ -12,7 +12,7 @@ class Page
|
|||||||
field :slug
|
field :slug
|
||||||
field :fullpath
|
field :fullpath
|
||||||
field :published, :type => Boolean, :default => false
|
field :published, :type => Boolean, :default => false
|
||||||
field :cache_expires_in, :type => Integer, :default => 0
|
field :cache_strategy, :default => 'none'
|
||||||
|
|
||||||
## associations ##
|
## associations ##
|
||||||
belongs_to_related :site
|
belongs_to_related :site
|
||||||
@ -35,7 +35,6 @@ class Page
|
|||||||
named_scope :not_found, :where => { :slug => '404', :depth => 0, :published => true }
|
named_scope :not_found, :where => { :slug => '404', :depth => 0, :published => true }
|
||||||
|
|
||||||
## behaviours ##
|
## behaviours ##
|
||||||
# liquid_methods :title, :fullpath
|
|
||||||
liquify_template :joined_parts
|
liquify_template :joined_parts
|
||||||
|
|
||||||
## methods ##
|
## methods ##
|
||||||
@ -66,6 +65,10 @@ class Page
|
|||||||
"http://#{self.site.domains.first}/#{self.fullpath}.html"
|
"http://#{self.site.domains.first}/#{self.fullpath}.html"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def with_cache?
|
||||||
|
self.cache_strategy != 'none'
|
||||||
|
end
|
||||||
|
|
||||||
def to_liquid(options = {})
|
def to_liquid(options = {})
|
||||||
Locomotive::Liquid::Drops::Page.new(self)
|
Locomotive::Liquid::Drops::Page.new(self)
|
||||||
end
|
end
|
||||||
@ -73,9 +76,6 @@ class Page
|
|||||||
protected
|
protected
|
||||||
|
|
||||||
def do_not_remove_index_and_404_pages
|
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?
|
return if (self.site rescue nil).nil?
|
||||||
|
|
||||||
if self.index? || self.not_found?
|
if self.index? || self.not_found?
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
= f.custom_input :published, :css => 'toggle' do
|
= f.custom_input :published, :css => 'toggle' do
|
||||||
= f.check_box :published
|
= 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
|
#page-parts
|
||||||
.nav
|
.nav
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
- title t('.title')
|
- title t('.title')
|
||||||
|
|
||||||
= semantic_form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f|
|
= semantic_form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f|
|
||||||
|
= f.hidden_field :remember_me, :value => "true"
|
||||||
|
|
||||||
.inner
|
.inner
|
||||||
= login_flash_message
|
= login_flash_message
|
||||||
|
|
||||||
|
@ -25,8 +25,7 @@ en:
|
|||||||
site: Site
|
site: Site
|
||||||
theme_assets: Theme files
|
theme_assets: Theme files
|
||||||
footer:
|
footer:
|
||||||
developed_by: Developed by
|
who_is_behind: "Service developed by {{development}} and designed by <a href=\"http://www.sachagreif.com\">Sacha Greif</a>"
|
||||||
powered_by: and Powered by
|
|
||||||
form_actions:
|
form_actions:
|
||||||
back: Back without saving
|
back: Back without saving
|
||||||
create: Create
|
create: Create
|
||||||
@ -97,8 +96,9 @@ en:
|
|||||||
failed_create: "Page was not created."
|
failed_create: "Page was not created."
|
||||||
failed_update: "Page was not updated."
|
failed_update: "Page was not updated."
|
||||||
form:
|
form:
|
||||||
expiration:
|
cache_strategy:
|
||||||
never: Never
|
none: None
|
||||||
|
simple: Simple
|
||||||
hour: 1 hour
|
hour: 1 hour
|
||||||
day: 1 day
|
day: 1 day
|
||||||
week: 1 week
|
week: 1 week
|
||||||
@ -331,7 +331,7 @@ en:
|
|||||||
hints:
|
hints:
|
||||||
page:
|
page:
|
||||||
published: "Only authenticated accounts can view unpublished pages."
|
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:
|
snippet:
|
||||||
slug: "You need to know it in order to insert the snippet inside a page or a layout"
|
slug: "You need to know it in order to insert the snippet inside a page or a layout"
|
||||||
site:
|
site:
|
||||||
|
@ -118,8 +118,9 @@ fr:
|
|||||||
failed_create: "La page n'a pas été créée."
|
failed_create: "La page n'a pas été créée."
|
||||||
failed_update: "La page n'a pas été mise à jour."
|
failed_update: "La page n'a pas été mise à jour."
|
||||||
form:
|
form:
|
||||||
expiration:
|
cache_strategy:
|
||||||
never: Jamais
|
none: Aucun
|
||||||
|
simple: Simple
|
||||||
hour: 1 heure
|
hour: 1 heure
|
||||||
day: 1 jour
|
day: 1 jour
|
||||||
week: 1 semaine
|
week: 1 semaine
|
||||||
@ -352,7 +353,7 @@ fr:
|
|||||||
hints:
|
hints:
|
||||||
page:
|
page:
|
||||||
published: "Seuls les administrateurs authentifiés peuvent voir une page non publiée."
|
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:
|
snippet:
|
||||||
slug: "Utilisé pour insérer le snippet dans une page ou un gabarit."
|
slug: "Utilisé pour insérer le snippet dans une page ou un gabarit."
|
||||||
site:
|
site:
|
||||||
|
@ -57,7 +57,7 @@ fr:
|
|||||||
parent: Parent
|
parent: Parent
|
||||||
slug: Raccourci
|
slug: Raccourci
|
||||||
published: Publiée
|
published: Publiée
|
||||||
cache_expires_in: Cache expire dans
|
cache_strategy: Cache
|
||||||
content_type:
|
content_type:
|
||||||
name: Nom
|
name: Nom
|
||||||
description: Description
|
description: Description
|
||||||
|
7
doc/TODO
7
doc/TODO
@ -4,6 +4,10 @@ BOARD:
|
|||||||
- refactor slugify method (use parameterize + create a module)
|
- refactor slugify method (use parameterize + create a module)
|
||||||
|
|
||||||
- change action icons according to the right action [Sacha]
|
- 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:
|
BACKLOG:
|
||||||
|
|
||||||
@ -12,7 +16,6 @@ BACKLOG:
|
|||||||
- new custom field types:
|
- new custom field types:
|
||||||
- belongs_to => association
|
- belongs_to => association
|
||||||
- cucumber features for admin pages
|
- cucumber features for admin pages
|
||||||
- sitemap
|
|
||||||
- validation for custom fields
|
- validation for custom fields
|
||||||
|
|
||||||
BUGS:
|
BUGS:
|
||||||
@ -54,3 +57,5 @@ x localize application in French
|
|||||||
x change credits in the admin footer
|
x change credits in the admin footer
|
||||||
x license
|
x license
|
||||||
x textile filter
|
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
|
@ -30,3 +30,33 @@ class String
|
|||||||
end
|
end
|
||||||
|
|
||||||
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
|
@ -17,8 +17,9 @@ module Locomotive
|
|||||||
|
|
||||||
puts "[WebService] consuming #{path}, #{options.inspect}"
|
puts "[WebService] consuming #{path}, #{options.inspect}"
|
||||||
|
|
||||||
self.get(path, options)
|
self.get(path, options).try(:underscore_keys)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
@ -14,7 +14,7 @@ module Locomotive
|
|||||||
|
|
||||||
output = @page.render(locomotive_context)
|
output = @page.render(locomotive_context)
|
||||||
|
|
||||||
prepare_and_set_response(output, @page.cache_expires_in || 0)
|
prepare_and_set_response(output)
|
||||||
end
|
end
|
||||||
|
|
||||||
def locomotive_page
|
def locomotive_page
|
||||||
@ -48,9 +48,17 @@ module Locomotive
|
|||||||
::Liquid::Context.new(assigns, registers)
|
::Liquid::Context.new(assigns, registers)
|
||||||
end
|
end
|
||||||
|
|
||||||
def prepare_and_set_response(output, cache_expiration = 0)
|
def prepare_and_set_response(output)
|
||||||
response.headers['Cache-Control'] = "public, max-age=#{cache_expiration}" if cache_expiration > 0
|
|
||||||
response.headers['Content-Type'] = 'text/html; charset=utf-8'
|
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
|
render :text => output, :layout => false, :status => :ok
|
||||||
end
|
end
|
||||||
|
|
||||||
|
37
spec/lib/core_ext_spec.rb
Normal file
37
spec/lib/core_ext_spec.rb
Normal 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
|
@ -8,11 +8,13 @@ describe 'Locomotive rendering system' do
|
|||||||
@site = Factory.build(:site)
|
@site = Factory.build(:site)
|
||||||
Site.stubs(:find).returns(@site)
|
Site.stubs(:find).returns(@site)
|
||||||
@controller.current_site = @site
|
@controller.current_site = @site
|
||||||
|
@page = Factory.build(:page, :site => nil, :published => true)
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'setting the response' do
|
context 'setting the response' do
|
||||||
|
|
||||||
before(:each) do
|
before(:each) do
|
||||||
|
@controller.instance_variable_set(:@page, @page)
|
||||||
@controller.send(:prepare_and_set_response, 'Hello world !')
|
@controller.send(:prepare_and_set_response, 'Hello world !')
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -28,20 +30,26 @@ describe 'Locomotive rendering system' do
|
|||||||
@controller.response.headers['Cache-Control'].should be_nil
|
@controller.response.headers['Cache-Control'].should be_nil
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'sets the cache' do
|
it 'sets the cache by simply using etag' do
|
||||||
@controller.send(:prepare_and_set_response, 'Hello world !', 3600)
|
@page.cache_strategy = 'simple'
|
||||||
@controller.response.headers['Cache-Control'].should == 'public, max-age=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 == '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
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when retrieving page' do
|
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
|
it 'should retrieve the index page /' do
|
||||||
@controller.request.fullpath = '/'
|
@controller.request.fullpath = '/'
|
||||||
@controller.current_site.pages.expects(:where).with({ :fullpath => 'index' }).returns([@page])
|
@controller.current_site.pages.expects(:where).with({ :fullpath => 'index' }).returns([@page])
|
||||||
|
@ -74,6 +74,11 @@ describe Page do
|
|||||||
page.slug.should == 'Valid_ite'
|
page.slug.should == 'Valid_ite'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'has no cache strategy' do
|
||||||
|
page = Factory.build(:page, :site => nil)
|
||||||
|
page.with_cache?.should == false
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'delete' do
|
describe 'delete' do
|
||||||
|
@ -4,7 +4,7 @@ Locomotive.configure do |config|
|
|||||||
end
|
end
|
||||||
|
|
||||||
module Locomotive
|
module Locomotive
|
||||||
class TestController
|
class TestController < ApplicationController
|
||||||
|
|
||||||
include Locomotive::Render
|
include Locomotive::Render
|
||||||
|
|
||||||
@ -15,26 +15,20 @@ module Locomotive
|
|||||||
end
|
end
|
||||||
|
|
||||||
def response
|
def response
|
||||||
@response ||= TestResponse.new
|
@_response ||= TestResponse.new
|
||||||
end
|
end
|
||||||
|
|
||||||
def request
|
def request
|
||||||
@request ||= TestRequest.new
|
@_request ||= TestRequest.new
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
class TestResponse
|
class TestResponse < ActionDispatch::TestResponse
|
||||||
|
|
||||||
attr_accessor :headers
|
|
||||||
|
|
||||||
def initialize
|
|
||||||
self.headers = {}
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
class TestRequest
|
class TestRequest < ActionDispatch::TestRequest
|
||||||
|
|
||||||
attr_accessor :fullpath
|
attr_accessor :fullpath
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user