Skip to content

Instantly share code, notes, and snippets.

@saturnflyer
Created August 28, 2012 16:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save saturnflyer/3500369 to your computer and use it in GitHub Desktop.
Save saturnflyer/3500369 to your computer and use it in GitHub Desktop.
Radiant custom tag ideas
# This is from a production application of mine
def ExpertTag(tag)
tag.is_a?(ExpertTag) ? tag : ExpertTag.new(tag)
end
class ExpertTag
def initialize(radius_tag)
@radius_tag = radius_tag
end
def expand
@radius_tag.expand
end
def image
HtmlElement.new('img', {:src => profile_image, :self_closing => true }.merge(attrs)).to_s
end
def link
element = HtmlElement.new('a', attrs.merge('href' => path))
element.open do |el|
if double?
el.write expand
else
el.write image
end
end
element.to_s
end
def path
'/experts/' + expert.permalink
end
def name
expert.name
end
def expertise
expert.expertise
end
def credentials
expert.credentials
end
private
def attrs
@radius_tag.attr
end
def double?
@radius_tag.double?
end
def profile_image
expert.profile_image
end
def expert
@expert ||= @radius_tag.locals.expert || Expert.last(:order => 'rand()')
end
end
# And an example of using this
desc %{ Scope the expert of the featured question. }
tag 'featured_question:expert' do |tag|
ExpertTag(tag).expand
end
desc %{ Output an image for the featured question's expert. }
tag 'featured_question:expert:image' do |tag|
ExpertTag(tag).image
end
desc %{ Output the name of the featured question's expert. }
tag 'featured_question:expert:name' do |tag|
ExpertTag(tag).name
end
# Current massive, ugly definition for the r:content tag:
tag 'content' do |tag|
page = tag.locals.page
part_name = tag_part_name(tag)
# Prevent simple and deep recursive rendering of the same page part
rendering_parts = (tag.locals.rendering_parts ||= Hash.new {|h,k| h[k] = []})
if rendering_parts[page.id].include?(part_name)
raise TagError.new(%{Recursion error: already rendering the `#{part_name}' part.})
else
rendering_parts[page.id] << part_name
end
inherit = boolean_attr_or_error(tag,'inherit',false)
part_page = page
if inherit
while (part_page.part(part_name).nil? and (not part_page.parent.nil?)) do
part_page = part_page.parent
end
end
contextual = boolean_attr_or_error(tag,'contextual', true)
part = part_page.part(part_name)
tag.locals.page = part_page unless contextual
result = tag.globals.page.render_snippet(part) unless part.nil?
rendering_parts[page.id].delete(part_name)
result
end
# Reading that makes so little sense. That is a massive procedure that can be clarified.
# class Page
# # this makes sense:
# tag_with Radiant::CustomTags::Content
# # but this feels like over-engineering:
# tag_with Radiant::CustomTags::IfContent
# end
module Radiant
module CustomTags
class RadiantTag
class << self
def description(text)
@description = text
end
def attribute(name, options={})
@attributes ||= {}
@attributes[name] = options
end
def attributes
@attributes
end
end
def initialize(context)
@context = context
end
def local_scope
# tag.locals from a typical tag
end
end
class Content < RadiantTag
description %{Renders the main content of a page.}
attribute 'part', :default => 'body',
:description => %{Use this attribute to select a specific
page part. By default it is set to 'body'.}
attribute 'inherit', :options => :boolean,
:default => false,
:description => %{Use this attribute to specify that if a page does not have a content
part by that name that the tag should render the parent's content part.}
attribute 'contextual', :options => :boolean,
:default => true,
:description => %{Use this attribute to force a part inherited from a parent
part to be evaluated in the context of the child page.}
def call
# # Prevent simple and deep recursive rendering of the same page part
restrict_recursion and track_current_part
part_page = page
if inherit?
part_page = page_with_part(part_name)
end
local_scope.page = part_page unless contextual?
part = part_page.part(part_name)
@result = render_part(part)
untrack_current_part
self
end
def to_s
@result
end
alias :expand :to_s
def page
local_scope.page
end
def part_name
arguments['part'] || 'body'
end
def rendering_parts
@rendering_parts ||= (local_scope.rendering_parts ||= Hash.new {|h,k| h[k] = []})
end
def render_part(part)
part.nil? ? '' : global_scope.page.render_snippet(part)
end
def inherit?
boolean_attr_or_error('inherit',false)
end
def page_with_part(part_name, rendering_page = page)
return rendering_page if rendering_page.has_part?(part_name)
if rendering_page.parent.nil?
rendering_page
else
page_with_part(part_name, rendering_page.parent)
end
end
def contextual?
boolean_attr_or_error('contextual', true)
end
private
def track_current_part
rendering_parts[page.id] << part_name
end
def untrack_current_part
rendering_parts[page.id].delete(part_name)
end
def rendering_current_part?
rendering_parts[page.id].include?(part_name)
end
def restrict_recursion
if rendering_current_part?
raise tag_error(%{Recursion error: already rendering the `#{part_name}' part.})
end
true
end
def tag_error(message)
RadiantTag::TagError.new(message)
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment