Crystalmeta helps you control meta tags through I18n and/or manually. It plays well with OpenGraph and Twitter Cards.
It gives you 3 helpers:
1. meta(options) — available in both controller & views.
Accepts Hash.
Collects meta tags for future use:
# folded hashes
meta og: {title: "The Rock (1996)", type: "video.movie"}
# one level hash
meta "og:title" => "The Rock (1996)", "og:type" => "video.movie"
meta :"og:image" => "the-rock.png"2. meta_tag(name) — available in views
Accepts String or Symbol.
Returns value for a certain tag:
<title><%= meta_tag 'og:title' %></title>3. meta_tags(pattern = //)
Returns all meta tags which names match the pattern. Under the hoods it uses the three-qual to pattern match (like in Enumerable#grep).
<%= meta_tags /^og:/ %>displays in this case:
<meta property="og:url" content="http://www.imdb.com/title/tt0117500/" />
<meta property="og:image" content="/assets/the-rock.png" />
<meta property="og:title" content="The Rock (1996)" />
<meta property="og:type" content="video.movie" />Please note that:
-
image_pathis automatically used forog:imageorog:image:url(video_pathforog:videoandaudio_pathforog:audiorespectively), so you don't have to bother setting explicit paths; -
og:urlis set tocontroller.request.url.
I18n translations
Crystalmeta tries to fetch translations and merge them in this order (consider an example for pages#show action):
-
meta._defaults— application defaults (lowest-priority) -
meta.pages._defaults— controller defaults -
meta.pages.show— action
Tags set manually by the meta helper will be given the highest priority.
Namespaced controllers
Crystalmeta uses controller_path in order to get the translation scope, so if you have a namespaced controller, for instance Library::BooksController, then the show action will use: meta.library.books._defaults & meta.library.books.show respectively.
Aliases
Crystalmeta uses translations for the edit action for update:
meta._defaultsmeta.movies._defaultsmeta.movies.editmeta.movies.update
And new for create:
meta._defaultsmeta.movies._defaultsmeta.movies.newmeta.movies.create
You can omit defining translations for update & create actions if they're the same.
Displaying only certain meta tags using a pattern
Usually I set window title with Crystalmeta separately (I call it head for example) and I don't want to display it in meta tags, so I can do:
<%= meta_tags /:/ %>It will filter tag names using /:/ === name.
You may wish to use a Proc in some cases:
<%= meta_tags Proc.new{|name| name != "head"} %>Interpolation
You can interpolate meta tags like this:
<%
meta({
"og:title" => "The Rock (1996)",
"og:site_name" => "IMDb",
"head" => "%{og:title} — %{og:site_name}"
})
%>meta_tag :head will return "The Rock (1996) — IMDb".
Please use this feature with care to avoid SystemStackError.
Caveats
Merging tags
When tags are merged (while fetching translations or collecting with meta) Crystalmeta doesn't do anything smart — it just merges hashes brutally. So if you defined a tag like that:
en:
meta:
_defaults:
og:
title: IMDband then you redefine it in different style:
meta 'og:title' => 'The Rock (1996)'then you'll just get 2 tags in the end:
<%= meta_tags /og:title/ %>will display
<meta property="og:title" content="IMDb" />
<meta property="og:title" content="Newer IMDb" />So you'd better prefer one style.
Date/Time
Crystalmeta will convert Date/Time/Datetime objects to iso8601 automatically, so if you don't want it, pass them as strings.
Arrays
To maximize OpenGraph compatibility, Crystalmeta handles Arrays in similar way:
<% meta :og => {:image => %w{1.png 2.png}} %>
<%= meta_tags /og:image/ %>will display:
<meta property="og:image" content="/assets/1.png" />
<meta property="og:image" content="/assets/2.png" />Multiple images with properties
If you have multiple images with properties like this:
<meta property="og:image:url" content="/assets/rock.jpg" />
<meta property="og:image:width" content="300" />
<meta property="og:image:height" content="300" />
<meta property="og:image:url" content="/assets/rock2.jpg" />
<meta property="og:image:url" content="/assets/rock3.jpg" />
<meta property="og:image:height" content="1000" />then you'll have to set them in a special way:
<% meta 'og:image' => [
{:url => 'rock.jpg', :width => 300, :height => 300},
{:url => 'rock2.jpg'},
{:url => 'rock3.jpg', :height => 1000},
] %>or:
en:
meta:
pages:
show:
og:image:
- url: rock.jpg
width: 300
height: 300
- url: rock2.jpg
- url: rock3.jpg
height: 1000It will sort keys so that the url property is on top.