class Radius::Context
A context contains the tag definitions which are available for use in a template. See the QUICKSTART for a detailed explaination its usage.
Public Class Methods
Creates a new Context object.
# File lib/radius/context.rb, line 13 def initialize(*args, &block) @definitions = {} @tag_binding_stack = [] @globals = DelegatingOpenStruct.new with(&block) if block_given? end
Public Instance Methods
Returns the state of the current render stack. Useful from inside a tag definition. Normally just use Radius::TagBinding#nesting.
# File lib/radius/context.rb, line 79 def current_nesting @tag_binding_stack.collect { |tag| tag.name }.join(':') end
Creates a tag definition on a context. Several options are available to you when creating a tag:
for
-
Specifies an object that the tag is in reference to. This is applicable when a block is not passed to the tag, or when the
expose
option is also used. expose
-
Specifies that child tags should be set for each of the methods contained in this option. May be either a single symbol/string or an array of symbols/strings.
attributes
-
Specifies whether or not attributes should be exposed automatically. Useful for ActiveRecord objects. Boolean. Defaults to
true
.
# File lib/radius/context.rb, line 48 def define_tag(name, options = {}, &block) type = Utility.impartial_hash_delete(options, :type).to_s klass = Utility.constantize('Radius::TagDefinitions::' + Utility.camelize(type) + 'TagFactory') rescue raise(ArgumentError.new("Undefined type `#{type}' in options hash")) klass.new(self).define_tag(name, options, &block) end
Returns the value of a rendered tag. Used internally by Radius::Parser#parse.
# File lib/radius/context.rb, line 55 def render_tag(name, attributes = {}, &block) if name =~ /^(.+?):(.+)$/ render_tag($1) { render_tag($2, attributes, &block) } else tag_definition_block = @definitions[qualified_tag_name(name.to_s)] if tag_definition_block stack(name, attributes, block) do |tag| tag_definition_block.call(tag).to_s end else tag_missing(name, attributes, &block) end end end
Like method_missing for objects, but fired when a tag is undefined. Override in your own Context to change what happens when a tag is undefined. By default this method raises an UndefinedTagError.
# File lib/radius/context.rb, line 73 def tag_missing(name, attributes, &block) raise UndefinedTagError.new(name) end
Yield an instance of self for tag definitions:
context.with do |c| c.define_tag 'test' do 'test' end end
# File lib/radius/context.rb, line 28 def with yield self self end
Private Instance Methods
Returns the specificity for tag_name
at nesting defined by
nesting_parts
as a number.
# File lib/radius/context.rb, line 128 def numeric_specificity(tag_name, nesting_parts) nesting_parts = nesting_parts.dup name_parts = tag_name.split(':') specificity = 0 value = 1 if nesting_parts.last == name_parts.last while nesting_parts.size > 0 if nesting_parts.last == name_parts.last specificity += value name_parts.pop end nesting_parts.pop value *= 0.1 end specificity = 0 if (name_parts.size > 0) end specificity end
Returns a fully qualified tag name based on state of the tag binding stack.
# File lib/radius/context.rb, line 108 def qualified_tag_name(name) nesting_parts = @tag_binding_stack.collect { |tag| tag.name } nesting_parts << name unless nesting_parts.last == name specific_name = nesting_parts.join(':') # specific_name always has the highest specificity unless @definitions.has_key? specific_name possible_matches = @definitions.keys.grep(/(^|:)#{name}$/) specificity = possible_matches.inject({}) { |hash, tag| hash[numeric_specificity(tag, nesting_parts)] = tag; hash } max = specificity.keys.max if max != 0 specificity[max] else name end else specific_name end end
A convienence method for managing the various parts of the tag binding stack.
# File lib/radius/context.rb, line 95 def stack(name, attributes, block) previous = @tag_binding_stack.last previous_locals = previous.nil? ? globals : previous.locals locals = DelegatingOpenStruct.new(previous_locals) binding = TagBinding.new(self, locals, name, attributes, block) @tag_binding_stack.push(binding) result = yield(binding) @tag_binding_stack.pop result end