This is another way to apply tags to objects in your radiant site and retrieve objects by tag. If you're looking at this you will also want to look at the tags extension, which does a good job of tag-clouding and may be all you need.
Taggable now includes what was previously the library
extension so it handles radiant assets as well as pages and provides radius tags to support a faceted search.
This extension differs from tags
in a few ways that matter to me but may not to you:
- We're not so focused on tag clouds - though you can still make them - but more on archival and linking functions.
- It provides faceted search of any tagged class.
- We subvert the keywords mechanism on pages rather than adding another one. I am likely to change this soon to play more nicely with page fields.
- The tag-choosing and tag-removal interface is (about to be) quite nice.
- It's editorially versatile: tags can be used as page pointers and their visibility is controllable
- Anything can be tagged. By default we only do pages and assets but other extensions can participate with a single line in a model class. See the taggable_events extension for a minimal example or just put
has_tags
at the top of a model class. - We don't use
has_many_polymorphs
(it burns!) - Or any of the tagging libraries: it only takes a few scopes
- Because the library is entirely scope-based it's easy to add more retrieval filters. Want a tagged and faceted googlemap of your calendar events?
event_calendar
+event_map
*taggable
+taggable_events
.
When you first install the extension you shouldn't see much difference: all we do out of the box is to take over (and make more prominent) the keywords field in the page and asset editing views.
Versions 2.x of taggable are meant for use with radiant 1. They expect to be included in your application as a bundled gem. There is a '0.9.1' tag in the repository for the latest version compatible with older versions of radiant.
Install the gem:
sudo gem install radiant-taggable-extension
and add it to your application's Gemfile:
gem radiant-taggable-extension, '~>2.0.0'
Apart from any crumpling caused by the recent re-incorporation of Library and all its asset tags, this is all mature code that has been in use for years.
Not too bad, I think. Most of the heavy retrieval functions have been squashed down into single queries. Each of these:
Tag.most_popular(50)
Tag.coincident_with(tag1, tag2, tag3)
Page.tagged_with(tag1, tag2, tag3)
Page.related_pages # equivalent to Page.tagged_with(self.attached_tags) - [self]
Tag.suggested_by('stem')
is handled in a single pass.
The exception is the r:tag_cloud
tag: there we have to gather a list of descendant pages first. It's done in a fairly frugal way (by generation rather than individual) but still likely to involve several preparatory queries as well as the cloud computation.
The LibraryPage page type is a handy cache-friendly way of catching tag parameters and displaying lists of related items: any path following the address of the page is taken as a slash-separated list of tags, so with a tag page at /archive you can call addresses like:
/archive/lasagne/chips/pudding
The right tags will be retrieved, if they exist, and with the radius tags below they can be used to populate the page.
This extension creates a great many radius tags but in an orderly way. There are four kinds:
are used in the usual to display the properties and associations of a given tag (which can be supplied to a library as a query parameter or just specified in the radius tag)
<r:tag:title />
<r:tag:description />
<r:tag:pages:each>...</r:tag:pages:each>
<r:tags:each >...</r:tags:each>
currently only available in a tag cloud (or a top_tags
list):
<r:tag:use_count />
These display the tag-associations of a given page.
<r:if_tags>...</r:if_tags>
<r:unless_tags>...</r:unless_tags>
<r:tags:each>...</r:tags:each>
<r:related_pages:each>...</r:related_pages:each>
<r:tag_cloud [url=""] />
The library extension adds a lot more ways to retrieve lists of tags and tagged objects, and to work with assets in the same way as we do here with pages.
All the page tags have asset equivalents:
<r:tags:assets:each tags="foo, bar">...</r:tags:assets:each>
<r:related_assets:each>...</r:related_assets:each>
and for any *asset*
tag you can substitute an asset type, so this also works:
<r:related_images:each>...</r:related_images:each>
Within the each loops you can use all the usual page and asset tags.
The library tags focus on two tasks: choosing a set of tags and displaying a set of matching objects.
<r:library:tags />
<r:library:tags:each>...</r:library:tags:each>
Displays a list of the tags available. If any tags have been requested, this will show the list of coincident tags (that can be used to limit the result set further). If not it shows all the available tags. If a for
attribute is set:
<r:library:tags for="images" />
<r:library:tags for="pages" />
Then we show only the set of tags attached to any object of that kind.
<r:library:requested_tags />
<r:library:requested_tags:each>...</r:library:requested_tags:each>
Displays the currently-limiting set of tags.
<r:library:pages:each>...</r:library:pages:each>
<r:library:assets:each>...</r:library:assets:each>
<r:library:images:each>...</r:library:images:each>
<r:library:videos:each>...</r:library:videos:each>
Display the list of (that kind of) objects associated with the current tag set.
The calculation of prominence here applies a logarithmic curve to create a more even distribution of weight. It's continuous rather than banded, and sets the font size and opacity for each tag in a style attribute.
Add tags to your pages by putting a comma-separated list in the 'keywords' box. That's about to get more helpful.
Put this in your layout:
<r:if_tags>
<h3>See also</h3>
<ul>
<r:related_pages.each>
<li><r:link /></li>
</r:related_pages.each>
</ul>
</r:if_tags>
Include the sample tagcloud.css in your styles and put this somewhere in the page or layout:
<r:tag_cloud />
Seek venture capital immediately.
<r:library:if_requested_tags>
<p>Displaying pictures tagged with <r:library:requested_tags /></p>
</r:library:if_requested_tags>
<r:library:images:each paginated="true" per_page="20">
<r:assets:link size="full"><r:assets:image size="small" /></r:assets:link>
</r:library:images:each>
<r:library:tags for="images" />
<r:related_images:each limit="3">
<r:assets:image size="standard" />
<p class="caption"><r:assets:caption /></p>
</r:related_images:each>
- William Ross, for spanner. will at spanner.org
- Copyright 2008-2011 spanner ltd
- released under the same terms as Rails and/or Radiant