Class: Talk::Context
- Inherits:
-
Object
- Object
- Talk::Context
- Includes:
- Enumerable
- Defined in:
- lib/context.rb,
lib/context_class.rb
Class Attribute Summary collapse
-
.classname ⇒ Object
readonly
Returns the value of attribute classname.
-
.final_validations ⇒ Object
readonly
Returns the value of attribute final_validations.
-
.postprocesses ⇒ Object
readonly
Returns the value of attribute postprocesses.
-
.properties ⇒ Object
readonly
Returns the value of attribute properties.
-
.references ⇒ Object
readonly
Returns the value of attribute references.
-
.registrations ⇒ Object
readonly
Returns the value of attribute registrations.
-
.registry ⇒ Object
readonly
Returns the value of attribute registry.
-
.tags ⇒ Object
readonly
Returns the value of attribute tags.
-
.transforms ⇒ Object
readonly
Returns the value of attribute transforms.
-
.validations ⇒ Object
readonly
Returns the value of attribute validations.
Instance Attribute Summary collapse
-
#file ⇒ Object
readonly
Returns the value of attribute file.
-
#line ⇒ Object
readonly
Returns the value of attribute line.
-
#tag ⇒ Object
readonly
Returns the value of attribute tag.
Class Method Summary collapse
-
.add_key_support(name) ⇒ Object
Support stuff; avoid invoking directly.
- .add_property_allowed(name, allowed) ⇒ Object
- .add_property_params(name, params) ⇒ Object
- .add_property_required(name) ⇒ Object
- .add_property_support(name, params) ⇒ Object
- .add_property_transform(name, transform) ⇒ Object
- .add_tag_required(name) ⇒ Object
- .add_tag_singular(name) ⇒ Object
- .add_tag_support(name, params) ⇒ Object
-
.all_contexts ⇒ Object
Subclassing magic.
- .bridge_tag_to_property(name) ⇒ Object
- .canonical_path_for_name(name) ⇒ Object
-
.classname_for_filename(name) ⇒ Object
/path/to/file_name.rb to FileName.
- .context_for_name(name) ⇒ Object
- .has_tag?(tag) ⇒ Boolean
- .initialize(classname) ⇒ Object
- .load_child_tags(name, params) ⇒ Object
- .make_context(name) ⇒ Object
- .normalize_allowed(name, allowed) ⇒ Object
- .postprocess(block) ⇒ Object
- .predefined_context_for_name(name) ⇒ Object
-
.property(name, params = {}) ⇒ Object
Stuff to be used by context definitions All of this is documented in ./README.md.
-
.property_at_index(idx) ⇒ Object
Convenience and support methods for instance methods.
- .reference(name, namespace, params = {}) ⇒ Object
- .register(namespace, params = {}) ⇒ Object
- .tag(name, params = {}) ⇒ Object
- .tag_description(params = {}) ⇒ Object
- .tag_end ⇒ Object
- .tag_is_singular?(tag) ⇒ Boolean
- .unique_key_for_tag(key) ⇒ Object
- .validate(errmsg, name, block) ⇒ Object
- .validate_final(errmsg, block) ⇒ Object
Instance Method Summary collapse
- #[](key) ⇒ Object
- #[]=(key, value) ⇒ Object
- #add_tag(context) ⇒ Object
-
#check_child_uniqueness(child) ⇒ Object
Support for parser.
- #close ⇒ Object
- #crossreference ⇒ Object
- #crossreference_value(value, namespace) ⇒ Object
- #description ⇒ Object
-
#each ⇒ Object
Operators and other standard-ish public methods.
- #end_tag(context) ⇒ Object
- #final_validation ⇒ Object
- #finalize ⇒ Object
- #has_key?(key) ⇒ Boolean
- #has_tag?(tag) ⇒ Boolean
- #hashify_value(v) ⇒ Object
-
#initialize(tag, file, line) ⇒ Context
constructor
A new instance of Context.
- #key_multiplicity(key) ⇒ Object
- #namespace_for_reference(reg) ⇒ Object
-
#parse(word, file = nil, line = nil) ⇒ Object
Parser interface.
-
#parse_error(message, file = nil, line = nil) ⇒ Object
Output.
- #pluralize(num, word, suffix = "s") ⇒ Object
- #postprocess ⇒ Object
- #process_property_words ⇒ Object
- #property_range_for_variable_len(offset, word_count, prop_def) ⇒ Object
-
#property_ranges ⇒ Object
Property manipulation.
- #reference_skipped?(ref_value, params) ⇒ Boolean
- #register ⇒ Object
- #render(indent_level = 0) ⇒ Object
- #render_element(indent_level, key, element) ⇒ Object
- #start_tag(tag, file, line) ⇒ Object
- #to_h ⇒ Object
- #to_s ⇒ Object
-
#transformed_value_for_key(key, value) ⇒ Object
Key manipulation.
- #validated_value_for_key(key, value) ⇒ Object
Constructor Details
#initialize(tag, file, line) ⇒ Context
Returns a new instance of Context.
10 11 12 13 14 15 16 17 |
# File 'lib/context.rb', line 10 def initialize(tag, file, line) @tag = tag @file = file @line = line @contents = {} @property_words = [] end |
Class Attribute Details
.classname ⇒ Object (readonly)
Returns the value of attribute classname.
4 5 6 |
# File 'lib/context_class.rb', line 4 def classname @classname end |
.final_validations ⇒ Object (readonly)
Returns the value of attribute final_validations.
6 7 8 |
# File 'lib/context_class.rb', line 6 def final_validations @final_validations end |
.postprocesses ⇒ Object (readonly)
Returns the value of attribute postprocesses.
6 7 8 |
# File 'lib/context_class.rb', line 6 def postprocesses @postprocesses end |
.properties ⇒ Object (readonly)
Returns the value of attribute properties.
4 5 6 |
# File 'lib/context_class.rb', line 4 def properties @properties end |
.references ⇒ Object (readonly)
Returns the value of attribute references.
5 6 7 |
# File 'lib/context_class.rb', line 5 def references @references end |
.registrations ⇒ Object (readonly)
Returns the value of attribute registrations.
5 6 7 |
# File 'lib/context_class.rb', line 5 def registrations @registrations end |
.registry ⇒ Object (readonly)
Returns the value of attribute registry.
8 9 10 |
# File 'lib/context_class.rb', line 8 def registry @registry end |
.tags ⇒ Object (readonly)
Returns the value of attribute tags.
4 5 6 |
# File 'lib/context_class.rb', line 4 def end |
.transforms ⇒ Object (readonly)
Returns the value of attribute transforms.
4 5 6 |
# File 'lib/context_class.rb', line 4 def transforms @transforms end |
.validations ⇒ Object (readonly)
Returns the value of attribute validations.
6 7 8 |
# File 'lib/context_class.rb', line 6 def validations @validations end |
Instance Attribute Details
#file ⇒ Object (readonly)
Returns the value of attribute file.
6 7 8 |
# File 'lib/context.rb', line 6 def file @file end |
#line ⇒ Object (readonly)
Returns the value of attribute line.
6 7 8 |
# File 'lib/context.rb', line 6 def line @line end |
#tag ⇒ Object (readonly)
Returns the value of attribute tag.
6 7 8 |
# File 'lib/context.rb', line 6 def tag @tag end |
Class Method Details
.add_key_support(name) ⇒ Object
Support stuff; avoid invoking directly
142 143 144 145 |
# File 'lib/context_class.rb', line 142 def add_key_support(name) @transforms[name] = [] @validations[name] = [] end |
.add_property_allowed(name, allowed) ⇒ Object
163 164 165 166 167 168 169 |
# File 'lib/context_class.rb', line 163 def add_property_allowed(name, allowed) ref = "#{@classname}.#{name}" norm_allow = normalize_allowed(name, allowed).join(", ") errmsg = "#{ref}: must be one of #{norm_allow}" validate( errmsg, name, lambda { |c,v| norm_allow.include? v } ) end |
.add_property_params(name, params) ⇒ Object
158 159 160 161 |
# File 'lib/context_class.rb', line 158 def add_property_params(name, params) defaults = { :length => 1, :name => name } @properties[name] = defaults.merge(params) end |
.add_property_required(name) ⇒ Object
171 172 173 174 175 176 |
# File 'lib/context_class.rb', line 171 def add_property_required(name) ref = "#{@classname}.#{name}" errmsg = "#{ref}: required property cannot be omitted" validate_final( errmsg, lambda { |c| c.has_key? name } ) end |
.add_property_support(name, params) ⇒ Object
147 148 149 150 151 152 153 154 155 156 |
# File 'lib/context_class.rb', line 147 def add_property_support(name, params) defaults = { :required => true } params = defaults.merge(params) add_key_support(name) add_property_params(name, params) add_property_transform(name, params[:transform]) unless params[:transform].nil? add_property_allowed(name, params[:allowed]) if params.has_key?(:allowed) add_property_required(name) if params[:required] end |
.add_property_transform(name, transform) ⇒ Object
178 179 180 |
# File 'lib/context_class.rb', line 178 def add_property_transform(name, transform) @transforms[name].push transform end |
.add_tag_required(name) ⇒ Object
202 203 204 205 206 |
# File 'lib/context_class.rb', line 202 def add_tag_required(name) ref = "#{@classname}->@#{name}" errmsg = "#{ref}: required tag cannot be omitted" validate_final( errmsg, lambda { |c| c.key_multiplicity(name) >= 1 } ) end |
.add_tag_singular(name) ⇒ Object
196 197 198 199 200 |
# File 'lib/context_class.rb', line 196 def add_tag_singular(name) ref = "#{@classname}->@#{name}" errmsg = "#{ref}: tag may only be added once" validate_final( errmsg, lambda { |c| c.key_multiplicity(name) <= 1 } ) end |
.add_tag_support(name, params) ⇒ Object
182 183 184 185 186 187 188 189 190 191 192 193 194 |
# File 'lib/context_class.rb', line 182 def add_tag_support(name, params) add_key_support(name) params[:class] = name unless params.has_key?(:class) # ||= won't work since class might be nil add_tag_singular(name) unless params[:multi] add_tag_required(name) if params[:required] postprocess(lambda do |c| return if c.has_key? name tag = c.start_tag(name, c.file, c.line) tag.parse(params[:default]) c.end_tag(tag) end) if params[:default] end |
.all_contexts ⇒ Object
Subclassing magic
104 105 106 107 |
# File 'lib/context_class.rb', line 104 def all_contexts path = File.join(File.dirname(__FILE__), "contexts/*.rb"); Dir[path].collect { |file| context_for_name(name) } end |
.bridge_tag_to_property(name) ⇒ Object
73 74 75 76 77 78 79 80 81 |
# File 'lib/context_class.rb', line 73 def bridge_tag_to_property(name) fixed_keys = { required: false, length:[0,nil] } allowed_keys = [:transform, :context] # the new property will have parameters pre-defined fixed_keys, and also # parameters imported from the tag listed in allowed_keys params = allowed_keys.inject(fixed_keys) { |c, k| c.merge( k => [name][k] ) } property( name, params ) end |
.canonical_path_for_name(name) ⇒ Object
133 134 135 |
# File 'lib/context_class.rb', line 133 def canonical_path_for_name(name) File.absolute_path(File.join(File.dirname(__FILE__), "contexts", File.basename(name.to_s, ".rb")) + ".rb") end |
.classname_for_filename(name) ⇒ Object
/path/to/file_name.rb to FileName
137 138 139 |
# File 'lib/context_class.rb', line 137 def classname_for_filename(name) # /path/to/file_name.rb to FileName File.basename(name.to_s, ".rb").split('_').collect { |word| word.capitalize }.join("") end |
.context_for_name(name) ⇒ Object
109 110 111 |
# File 'lib/context_class.rb', line 109 def context_for_name(name) predefined_context_for_name(name) || make_context(name) end |
.has_tag?(tag) ⇒ Boolean
95 96 97 |
# File 'lib/context_class.rb', line 95 def has_tag?(tag) .has_key?(tag) end |
.initialize(classname) ⇒ Object
10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
# File 'lib/context_class.rb', line 10 def initialize(classname) @classname = classname @properties = {} @property_map = [] = {} @transforms = {} @registrations = [] @references = [] @validations = {} @final_validations = [] @postprocesses = [] end |
.load_child_tags(name, params) ⇒ Object
208 209 210 |
# File 'lib/context_class.rb', line 208 def (name, params) .each_value { |tag| Context.context_for_name(tag[:class]) unless tag[:class].nil? } end |
.make_context(name) ⇒ Object
118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/context_class.rb', line 118 def make_context(name) new_classname = classname_for_filename(name) subclass = Class.new(Talk::Context) do initialize(new_classname) end source_file = canonical_path_for_name(name) subclass.class_eval( IO.read(source_file), source_file ) props = Talk.instance_variable_get("@contexts") props = Talk.instance_variable_set("@contexts", {}) if props.nil? props[new_classname] = subclass end |
.normalize_allowed(name, allowed) ⇒ Object
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 |
# File 'lib/context_class.rb', line 212 def normalize_allowed(name, allowed) new_allowed = [] remap = {} allowed.each do |v| vv = [*v] # vv == [ v ] if v is scalar, vv == v if v is already an array new_allowed += vv vv.each { |u| remap[u] = vv[0] } end add_property_transform(name, lambda do |c,v| return remap[v] if remap.has_key? v v end) new_allowed end |
.postprocess(block) ⇒ Object
60 61 62 |
# File 'lib/context_class.rb', line 60 def postprocess(block) @postprocesses.push block end |
.predefined_context_for_name(name) ⇒ Object
113 114 115 116 |
# File 'lib/context_class.rb', line 113 def predefined_context_for_name(name) props = Talk.instance_variable_get("@contexts") props.nil? ? nil : props[classname_for_filename(name)] end |
.property(name, params = {}) ⇒ Object
Stuff to be used by context definitions All of this is documented in ./README.md
27 28 29 30 31 |
# File 'lib/context_class.rb', line 27 def property(name, params={}) raise "Duplicate property definition #{name} in #{@classname}" if @properties.has_key?(name) @property_map.push(name) add_property_support(name, params) end |
.property_at_index(idx) ⇒ Object
Convenience and support methods for instance methods
85 86 87 88 89 |
# File 'lib/context_class.rb', line 85 def property_at_index(idx) return nil unless idx < @property_map.length return @properties[@property_map[idx]] end |
.reference(name, namespace, params = {}) ⇒ Object
56 57 58 |
# File 'lib/context_class.rb', line 56 def reference(name, namespace, params={}) @references.push({ namespace:namespace, name:name, params: params }) end |
.register(namespace, params = {}) ⇒ Object
50 51 52 53 54 |
# File 'lib/context_class.rb', line 50 def register(namespace, params={}) defaults = { name: :name, delimiter: nil, namespace: namespace } params = defaults.merge(params) @registrations.push(params) end |
.tag(name, params = {}) ⇒ Object
33 34 35 36 37 38 |
# File 'lib/context_class.rb', line 33 def tag(name, params={}) raise "Duplicate tag definition #{name} in #{@classname}" if @properties.has_key?(name) [name] = params add_tag_support(name, params) (name, params) end |
.tag_description(params = {}) ⇒ Object
40 41 42 43 44 |
# File 'lib/context_class.rb', line 40 def tag_description(params={}) params = { :class => :string, :required => true, :bridge => true }.merge(params) tag(:description, params) bridge_tag_to_property :description if params[:bridge] end |
.tag_end ⇒ Object
46 47 48 |
# File 'lib/context_class.rb', line 46 def tag_end tag(:end, { :class => nil }) end |
.tag_is_singular?(tag) ⇒ Boolean
99 100 101 |
# File 'lib/context_class.rb', line 99 def tag_is_singular?(tag) has_tag? tag and ([tag][:multi] == false or [tag][:multi].nil?) end |
.unique_key_for_tag(key) ⇒ Object
91 92 93 |
# File 'lib/context_class.rb', line 91 def unique_key_for_tag(key) [key][:unique] end |
.validate(errmsg, name, block) ⇒ Object
64 65 66 67 |
# File 'lib/context_class.rb', line 64 def validate(errmsg, name, block) @validations[name] ||= [] @validations[name].push( { message: errmsg, block: block } ) end |
.validate_final(errmsg, block) ⇒ Object
69 70 71 |
# File 'lib/context_class.rb', line 69 def validate_final(errmsg, block) @final_validations.push( { message: errmsg, block: block }) end |
Instance Method Details
#[](key) ⇒ Object
71 72 73 |
# File 'lib/context.rb', line 71 def [](key) @contents[key.to_sym] end |
#[]=(key, value) ⇒ Object
75 76 77 78 79 80 81 82 83 |
# File 'lib/context.rb', line 75 def []=(key, value) if value.is_a? Array then value = value.map { |v| validated_value_for_key(key, transformed_value_for_key(key, value)) } else value = validated_value_for_key(key, transformed_value_for_key(key, value)) end @contents[key.to_sym] = value end |
#add_tag(context) ⇒ Object
85 86 87 88 89 |
# File 'lib/context.rb', line 85 def add_tag(context) key = context.tag self[key.to_sym] ||= [] self[key.to_sym].push validated_value_for_key(key, transformed_value_for_key(key, context)) end |
#check_child_uniqueness(child) ⇒ Object
Support for parser
93 94 95 96 97 98 99 100 101 102 |
# File 'lib/context.rb', line 93 def check_child_uniqueness(child) # we could do this as a validator, but then we'd lose ability to show sibling info return unless self.has_key? child.tag key = self.class.unique_key_for_tag(child.tag) self[child.tag].each do |sibling| errmsg = "Child tag @#{child.tag} must have unique #{key} value; previously used in sibling at line #{sibling.line}" parse_error(errmsg, child.file, child.line) if child[key] == sibling[key] end end |
#close ⇒ Object
54 55 56 57 58 |
# File 'lib/context.rb', line 54 def close process_property_words postprocess register end |
#crossreference ⇒ Object
136 137 138 139 140 141 142 143 |
# File 'lib/context.rb', line 136 def crossreference self.class.references.each do |r| namespace = namespace_for_reference(r) [*self[r[:name]]].each do |referenced_name| crossreference_value(referenced_name, namespace) unless reference_skipped?(referenced_name, r[:params]) end end end |
#crossreference_value(value, namespace) ⇒ Object
130 131 132 133 134 |
# File 'lib/context.rb', line 130 def crossreference_value(value, namespace) value = value[:value] if value.is_a? Context registered = Registry.registered?(value, namespace) parse_error("no symbol '#{value}' in #{namespace}") unless registered end |
#description ⇒ Object
240 241 242 |
# File 'lib/context.rb', line 240 def description "@#{tag} #{file}:#{line}" end |
#each ⇒ Object
Operators and other standard-ish public methods
67 68 69 |
# File 'lib/context.rb', line 67 def each @contents.each { |k,v| yield k,v } end |
#end_tag(context) ⇒ Object
33 34 35 36 37 |
# File 'lib/context.rb', line 33 def end_tag(context) context.close check_child_uniqueness(context) if self.class.unique_key_for_tag(context.tag) add_tag(context) end |
#final_validation ⇒ Object
117 118 119 |
# File 'lib/context.rb', line 117 def final_validation self.class.final_validations.each { |v| parse_error(v[:message]) unless v[:block].call(self) } end |
#finalize ⇒ Object
60 61 62 63 |
# File 'lib/context.rb', line 60 def finalize final_validation crossreference end |
#has_key?(key) ⇒ Boolean
39 40 41 |
# File 'lib/context.rb', line 39 def has_key?(key) @contents.has_key?(key.to_sym) end |
#has_tag?(tag) ⇒ Boolean
43 44 45 |
# File 'lib/context.rb', line 43 def has_tag?(tag) self.class.has_tag?(tag) end |
#hashify_value(v) ⇒ Object
270 271 272 273 274 275 276 277 278 279 280 281 |
# File 'lib/context.rb', line 270 def hashify_value(v) # cache method list to provide big speedup @class_methods ||= {} @class_methods[v.class] ||= v.methods return v.to_val if @class_methods[v.class].include? :to_val return v.to_h if @class_methods[v.class].include? :to_h return v.to_f if(v.is_a?(Fixnum) || v.is_a?(Float)) return v if (v == true || v == false) v.to_s end |
#key_multiplicity(key) ⇒ Object
47 48 49 50 51 52 |
# File 'lib/context.rb', line 47 def key_multiplicity(key) key = key.to_sym return 0 unless @contents.has_key?(key) and not @contents[key].nil? return 1 unless @contents[key].is_a? Array or @contents[key].is_a? Hash return @contents[key].length end |
#namespace_for_reference(reg) ⇒ Object
125 126 127 128 |
# File 'lib/context.rb', line 125 def namespace_for_reference(reg) return reg[:namespace].call(self) if reg[:namespace].methods.include? :call reg[:namespace] end |
#parse(word, file = nil, line = nil) ⇒ Object
Parser interface
21 22 23 |
# File 'lib/context.rb', line 21 def parse(word, file=nil, line=nil) @property_words.push word end |
#parse_error(message, file = nil, line = nil) ⇒ Object
Output
214 215 216 |
# File 'lib/context.rb', line 214 def parse_error(, file=nil, line=nil) Talk::Parser.error(@tag, file || @file, line || @line, ) end |
#pluralize(num, word, suffix = "s") ⇒ Object
208 209 210 |
# File 'lib/context.rb', line 208 def pluralize(num, word, suffix="s") num == 1 ? word : word + suffix end |
#postprocess ⇒ Object
113 114 115 |
# File 'lib/context.rb', line 113 def postprocess self.class.postprocesses.each { |p| p.call(self) } end |
#process_property_words ⇒ Object
104 105 106 107 108 109 110 111 |
# File 'lib/context.rb', line 104 def process_property_words ranges = property_ranges ranges.each_with_index do |range, idx| property = self.class.property_at_index(idx) value = @property_words[range[0] .. range[1]].join(" ") self[property[:name]] = value end end |
#property_range_for_variable_len(offset, word_count, prop_def) ⇒ Object
195 196 197 198 199 200 201 202 203 204 205 206 |
# File 'lib/context.rb', line 195 def property_range_for_variable_len(offset, word_count, prop_def) words_left = word_count - offset min = prop_def[:length][0] max = prop_def[:length][1] meets_min = words_left >= min meets_max = max.nil? or words_left <= max parse_error("Property #{prop_def[:name]} takes at least #{min} #{pluralize min, 'word'}; got #{words_left}") unless meets_min parse_error("Property #{prop_def[:name]} takes at most #{max} #{pluralize min, 'word'}; got #{words_left}") unless meets_max [ offset, word_count-1 ] end |
#property_ranges ⇒ Object
Property manipulation
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 |
# File 'lib/context.rb', line 167 def property_ranges word_count = @property_words.length ranges = [] self.class.properties.each do |prop_name, prop_def| len = prop_def[:length] offset = ranges.empty? ? 0 : ranges.last[1]+1 msg_start = "@#{self.tag} property '#{prop_name}' " if len.is_a? Array then new_range = property_range_for_variable_len(offset, word_count, prop_def) else if offset >= word_count then parse_error(msg_start+"cannot be omitted") if prop_def[:required] new_range = [1, 0] else length_ok = (word_count - offset >= len) parse_error(msg_start+"got #{word_count-offset} of #{len} words") unless length_ok new_range = [offset, offset+len-1] end end ranges.push new_range if new_range[1] >= new_range[0] end ranges end |
#reference_skipped?(ref_value, params) ⇒ Boolean
145 146 147 148 149 150 |
# File 'lib/context.rb', line 145 def reference_skipped?(ref_value, params) ref_value = ref_value[:value] if ref_value.is_a? Context return false if params[:skip].nil? return params[:skip].include? ref_value if params[:skip].is_a? Array return params[:skip] == ref_value end |
#register ⇒ Object
121 122 123 |
# File 'lib/context.rb', line 121 def register self.class.registrations.each { |r| Registry.add(self[r[:name]], r[:namespace], self.file, self.line, r[:delimiter]) } end |
#render(indent_level = 0) ⇒ Object
226 227 228 229 230 231 232 233 234 235 236 237 238 |
# File 'lib/context.rb', line 226 def render(indent_level=0) indent = "\t" * indent_level str = indent + "@" + self.tag.to_s + ' ' + @property_words.join(' ') + "\n" @contents.each do |key, value| if value.is_a? Array then str = value.inject(str) { |s, element| s + render_element(indent_level+1, key, element) } else render_element(indent_level+1, key, value) end end str end |
#render_element(indent_level, key, element) ⇒ Object
218 219 220 221 222 223 224 |
# File 'lib/context.rb', line 218 def render_element(indent_level, key, element) if element.methods.include? :render then element.render(indent_level) else "\t" * indent_level + "#{key.to_s} -> '#{element.to_s}'\n" end end |
#start_tag(tag, file, line) ⇒ Object
25 26 27 28 29 30 31 |
# File 'lib/context.rb', line 25 def start_tag(tag, file, line) parse_error("Unsupported tag @#{tag}", file, line) unless self.class..has_key?(tag) tag_class = self.class.[tag][:class] # @end tags use a nil class tag_class.nil? ? nil : Context.context_for_name(tag_class).new(tag, file, line) end |
#to_h ⇒ Object
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 |
# File 'lib/context.rb', line 248 def to_h dict = {} @contents.each do |k,v| if v.is_a? Array then if self.class.tag_is_singular? k and v.length > 0 dict[k] = hashify_value(v[0]) else dict[k] = v.map { |u| hashify_value(u) } end else dict[k] = hashify_value(v) end end dict[:__meta] ||= {} dict[:__meta][:file] = @file dict[:__meta][:tag] = @tag dict[:__meta][:line] = @line dict end |
#to_s ⇒ Object
244 245 246 |
# File 'lib/context.rb', line 244 def to_s render end |
#transformed_value_for_key(key, value) ⇒ Object
Key manipulation
154 155 156 157 158 |
# File 'lib/context.rb', line 154 def transformed_value_for_key(key, value) transforms = self.class.transforms[key] transforms.each { |t| value = t.call(self, value) } unless transforms.nil? value end |
#validated_value_for_key(key, value) ⇒ Object
160 161 162 163 |
# File 'lib/context.rb', line 160 def validated_value_for_key(key, value) self.class.validations[key].each { |v| parse_error(v[:message]) unless v[:block].call(self, value) } value end |