diff --git a/app/models/content_instance.rb b/app/models/content_instance.rb
index a14f620e..d4104d4c 100644
--- a/app/models/content_instance.rb
+++ b/app/models/content_instance.rb
@@ -5,6 +5,7 @@ class ContentInstance
## extensions ##
include CustomFields::ProxyClassEnabler
+ include Extensions::Shared::Seo
## fields (dynamic fields) ##
field :_slug
@@ -29,6 +30,8 @@ class ContentInstance
## methods ##
+ delegate :site, :to => :content_type
+
alias :visible? :_visible?
alias :_permalink :_slug
diff --git a/app/models/extensions/shared/seo.rb b/app/models/extensions/shared/seo.rb
new file mode 100644
index 00000000..06d190bc
--- /dev/null
+++ b/app/models/extensions/shared/seo.rb
@@ -0,0 +1,13 @@
+module Extensions
+ module Shared
+ module Seo
+ extend ActiveSupport::Concern
+
+ included do
+ field :meta_keywords, :type => String
+ field :meta_description, :type => String
+ end
+
+ end # Seo
+ end # Shared
+end # Extensions
diff --git a/app/models/page.rb b/app/models/page.rb
index a64b45db..2a6a4125 100644
--- a/app/models/page.rb
+++ b/app/models/page.rb
@@ -10,6 +10,7 @@ class Page
include Extensions::Page::Templatized
include Extensions::Page::Redirect
include Extensions::Page::Listed
+ include Extensions::Shared::Seo
## fields ##
field :title
diff --git a/app/views/admin/contents/_form.html.haml b/app/views/admin/contents/_form.html.haml
index d79bacaf..745b8129 100644
--- a/app/views/admin/contents/_form.html.haml
+++ b/app/views/admin/contents/_form.html.haml
@@ -2,4 +2,9 @@
= include_javascripts :edit_custom_fields, :contents
= include_stylesheets :fancybox
+= f.foldable_inputs :name => :meta do
+
+ = f.input :meta_keywords
+ = f.input :meta_description
+
= render 'admin/custom_fields/custom_form', :form => f, :title => :attributes, :parent => @content_type
\ No newline at end of file
diff --git a/app/views/admin/pages/_form.html.haml b/app/views/admin/pages/_form.html.haml
index 6db15972..34ed29bd 100644
--- a/app/views/admin/pages/_form.html.haml
+++ b/app/views/admin/pages/_form.html.haml
@@ -11,6 +11,10 @@
= f.input :slug, :required => false, :hint => @page.slug.blank? ? ' ' : page_url(@page), :input_html => { :data_url => get_path_admin_pages_url, :disabled => @page.index? || @page.not_found? }, :wrapper_html => { :style => "#{'display: none' if @page.templatized?}; height: 50px" }
+= f.foldable_inputs :name => :meta do
+
+ = f.input :meta_keywords
+ = f.input :meta_description
= f.foldable_inputs :name => :advanced_options do
diff --git a/config/locales/formtastic.en.yml b/config/locales/formtastic.en.yml
index c8baf61d..0e11199f 100644
--- a/config/locales/formtastic.en.yml
+++ b/config/locales/formtastic.en.yml
@@ -50,10 +50,12 @@ en:
templatized: "Use the page as a template for a model you defined."
listed: "Control whether to show the page from generated menus."
content_type_id: "The type of content this page will be a template for."
+ meta_keywords: "Overrides the site's meta keywords used within the head tag of the page. They are separated by a comma."
+ meta_description: "Overrides the site's meta description used within the head tag of the page."
snippet:
slug: "You need to know it in order to insert the snippet inside a page"
site:
- meta_keywords: "Meta keywords used within the head tag of the page. They are separeted by an empty space. Required for SEO."
+ meta_keywords: "Meta keywords used within the head tag of the page. They are separated by a comma. Required for SEO."
meta_description: "Meta description used within the head tag of the page. Required for SEO."
domain_name: "ex: locomotiveapp.org"
theme_asset:
diff --git a/lib/locomotive/liquid/drops/content.rb b/lib/locomotive/liquid/drops/content.rb
index 19715b41..5aafcf75 100644
--- a/lib/locomotive/liquid/drops/content.rb
+++ b/lib/locomotive/liquid/drops/content.rb
@@ -2,6 +2,7 @@ module Locomotive
module Liquid
module Drops
class Content < Base
+ delegate :meta_keywords, :meta_description, :to => "@source"
def before_method(meth)
return '' if @source.nil?
diff --git a/lib/locomotive/liquid/drops/page.rb b/lib/locomotive/liquid/drops/page.rb
index ea7e0e2c..a6b092a8 100644
--- a/lib/locomotive/liquid/drops/page.rb
+++ b/lib/locomotive/liquid/drops/page.rb
@@ -2,6 +2,7 @@ module Locomotive
module Liquid
module Drops
class Page < Base
+ delegate :meta_keywords, :meta_description, :to => "@source"
def title
@source.templatized? ? @context['content_instance'].highlighted_field_value : @source.title
diff --git a/lib/locomotive/liquid/tags/seo_metadata.rb b/lib/locomotive/liquid/tags/seo_metadata.rb
index c170729b..5958b47d 100644
--- a/lib/locomotive/liquid/tags/seo_metadata.rb
+++ b/lib/locomotive/liquid/tags/seo_metadata.rb
@@ -5,8 +5,8 @@ module Locomotive
def render(context)
%{
-
-
+
+
}
end
@@ -15,6 +15,19 @@ module Locomotive
string.strip.gsub(/"/, '')
end
+ def meta_description(context)
+ object = metadata_object(context)
+ object.try(:meta_description).blank? ? context.registers[:site].meta_description : object.meta_description
+ end
+
+ def meta_keywords(context)
+ object = metadata_object(context)
+ object.try(:meta_keywords).blank? ? context.registers[:site].meta_keywords : object.meta_keywords
+ end
+
+ def metadata_object(context)
+ context['content_instance'] || context['page']
+ end
end
::Liquid::Template.register_tag('seo_metadata', SEOMetadata)
diff --git a/spec/lib/locomotive/liquid/drops/content_spec.rb b/spec/lib/locomotive/liquid/drops/content_spec.rb
new file mode 100644
index 00000000..624cff4c
--- /dev/null
+++ b/spec/lib/locomotive/liquid/drops/content_spec.rb
@@ -0,0 +1,27 @@
+require 'spec_helper'
+
+describe Locomotive::Liquid::Drops::Content do
+
+ before(:each) do
+ @site = Factory.build(:site)
+ content_type = Factory.build(:content_type)
+ content_type.content_custom_fields.build :label => 'anything', :kind => 'String'
+ @content = content_type.contents.build(:meta_keywords => 'Libidinous, Angsty', :meta_description => "Quite the combination.")
+ end
+
+ describe 'meta_keywords' do
+ subject { render_template('{{ content.meta_keywords }}') }
+ it { should == @content.meta_keywords }
+ end
+
+ describe 'meta_description' do
+ subject { render_template('{{ content.meta_description }}') }
+ it { should == @content.meta_description }
+ end
+
+ def render_template(template = '', assigns = {})
+ assigns = { 'content' => @content }.merge(assigns)
+ Liquid::Template.parse(template).render(::Liquid::Context.new({}, assigns, { :site => @site }))
+ end
+
+end
diff --git a/spec/lib/locomotive/liquid/drops/page_spec.rb b/spec/lib/locomotive/liquid/drops/page_spec.rb
index ec53c262..b80328cd 100644
--- a/spec/lib/locomotive/liquid/drops/page_spec.rb
+++ b/spec/lib/locomotive/liquid/drops/page_spec.rb
@@ -3,7 +3,8 @@ require 'spec_helper'
describe Locomotive::Liquid::Drops::Page do
before(:each) do
- @home = Factory.build(:page)
+ site = Factory.build(:site)
+ @home = Factory.build(:page, :site => site, :meta_keywords => 'Libidinous, Angsty', :meta_description => "Quite the combination.")
end
context '#rendering tree' do
@@ -56,6 +57,16 @@ describe Locomotive::Liquid::Drops::Page do
end
+ describe 'meta_keywords' do
+ subject { render_template('{{ home.meta_keywords }}') }
+ it { should == @home.meta_keywords }
+ end
+
+ describe 'meta_description' do
+ subject { render_template('{{ home.meta_description }}') }
+ it { should == @home.meta_description }
+ end
+
def render_template(template = '', assigns = {})
assigns = {
'home' => @home
diff --git a/spec/lib/locomotive/liquid/tags/seo_metadata_spec.rb b/spec/lib/locomotive/liquid/tags/seo_metadata_spec.rb
index fe7200c5..5a5eeea3 100644
--- a/spec/lib/locomotive/liquid/tags/seo_metadata_spec.rb
+++ b/spec/lib/locomotive/liquid/tags/seo_metadata_spec.rb
@@ -1,19 +1,17 @@
require 'spec_helper'
describe Locomotive::Liquid::Tags::SEOMetadata do
-
- before :each do
- @site = Factory.build(:site, :meta_description => 'A short site description', :meta_keywords => 'test only cat dog')
+ let(:site) do
+ Factory.build(:site, :meta_description => 'A short site description', :meta_keywords => 'test only cat dog')
end
- context '#rendering' do
-
+ describe 'rendering' do
it 'renders a a meta description tag' do
render_seo_metadata.should include ''
end
it 'strips and removes quote characters from the description' do
- @site.meta_description = ' String with " " quotes '
+ site.meta_description = ' String with " " quotes '
render_seo_metadata.should include ''
end
@@ -22,16 +20,53 @@ describe Locomotive::Liquid::Tags::SEOMetadata do
end
it 'strips and removes quote characters from the keywords' do
- @site.meta_keywords = ' one " two " three '
+ site.meta_keywords = ' one " two " three '
render_seo_metadata.should include ''
end
+
+ context "when page" do
+ context "has metadata" do
+ let(:page) { site.pages.build(:meta_keywords => 'hulk,gamma', :meta_description => "Bruce Banner") }
+ subject { render_seo_metadata('page' => page) }
+ it { should include(%Q[]) }
+ it { should include(%Q[]) }
+ end
+ context "does not have metadata" do
+ let(:page) { site.pages.build }
+ subject { render_seo_metadata('page' => page) }
+ it { should include(%Q[]) }
+ it { should include(%Q[]) }
+ end
+ end
+
+ context "when content instance" do
+ let(:content_type) do
+ Factory.build(:content_type, :site => site).tap do |ct|
+ ct.content_custom_fields.build :label => 'anything', :kind => 'String'
+ end
+ end
+
+ context "has metadata" do
+ let(:content) { content_type.contents.build(:meta_keywords => 'Libidinous, Angsty', :meta_description => "Quite the combination.") }
+ subject { render_seo_metadata('content_instance' => content) }
+ it { should include(%Q[]) }
+ it { should include(%Q[]) }
+ end
+
+ context "does not have metadata" do
+ let(:content) { content_type.contents.build }
+ subject { render_seo_metadata('content_instance' => content) }
+ it { should include(%Q[]) }
+ it { should include(%Q[]) }
+ end
+ end
end
+
- def render_seo_metadata
- registers = { :site => @site }
- liquid_context = ::Liquid::Context.new({}, {}, registers)
+ def render_seo_metadata(assigns={})
+ registers = { :site => site }
+ liquid_context = ::Liquid::Context.new({}, assigns, registers)
output = Liquid::Template.parse("{% seo_metadata %}").render(liquid_context)
end
-
end
\ No newline at end of file
diff --git a/spec/models/content_instance_spec.rb b/spec/models/content_instance_spec.rb
index 1585ac24..987281f4 100644
--- a/spec/models/content_instance_spec.rb
+++ b/spec/models/content_instance_spec.rb
@@ -93,6 +93,13 @@ describe ContentInstance do
end
end
+
+ describe '#site' do
+ it 'delegates to the content type' do
+ @content_type.expects(:site)
+ build_content.site
+ end
+ end
def build_content(options = {})
@content_type.contents.build({ :title => 'Locomotive', :description => 'Lorem ipsum....' }.merge(options))
@@ -101,5 +108,4 @@ describe ContentInstance do
def fake_bson_id(id)
BSON::ObjectId(id.to_s.rjust(24, '0'))
end
-
-end
+end
\ No newline at end of file
diff --git a/spec/models/page_spec.rb b/spec/models/page_spec.rb
index 11ecf9d6..9d896aa8 100644
--- a/spec/models/page_spec.rb
+++ b/spec/models/page_spec.rb
@@ -229,8 +229,6 @@ describe Page do
@page.redirect_url = "invalid url with spaces"
@page.should_not be_valid
@page.errors[:redirect_url].should == ["is invalid"]
-
end
-
end
end