Module: MetaRuby::DSLs
- Defined in:
- lib/metaruby/dsls.rb,
lib/metaruby/dsls/doc.rb,
lib/metaruby/dsls/find_through_method_missing.rb
Overview
Helper functions to build DSLs
Class Method Summary collapse
-
.find_through_method_missing(object, m, args, *suffixes) ⇒ Object?
Generic implementation to create suffixed accessors for child objects on a class.
-
.parse_documentation_block(file_match, trigger_method = /.*/) ⇒ String?
Looks for the documentation block for the element that is being built.
-
.parse_documentation_block_at(file, line) ⇒ String?
Parses upwards a Ruby documentation block whose last line starts at or just before the given line in the given file.
Class Method Details
.find_through_method_missing(object, m, args, *suffixes) ⇒ Object?
Generic implementation to create suffixed accessors for child objects on a class
Given an object category (let’s say ‘state’), this allows to properly implement a method-missing based accessor of the style
blabla_state
using a find_state method that the object should respond to
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/metaruby/dsls/find_through_method_missing.rb', line 48 def self.find_through_method_missing(object, m, args, *suffixes) suffix_match = Hash.new if suffixes.last.kind_of?(Hash) suffix_match.merge!(suffixes.pop) end suffixes.each do |name| suffix_match[name] = "find_#{name}" end m = m.to_s suffix_match.each do |s, find_method_name| if m == find_method_name raise NoMethodError.new("#{object} has no method called #{find_method_name}", m) elsif m =~ /(.*)_#{s}$/ name = $1 if !args.empty? raise ArgumentError, "expected zero arguments to #{m}, got #{args.size}", caller(4) elsif found = object.send(find_method_name, name) return found else msg = "#{object} has no #{s} named #{name}" raise NoMethodError.new(msg, m), msg, caller(4) end end end nil end |
.parse_documentation_block(file_match, trigger_method = /.*/) ⇒ String?
Looks for the documentation block for the element that is being built.
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/metaruby/dsls/doc.rb', line 13 def self.parse_documentation_block(file_match, trigger_method = /.*/) last_method_matched = false call_stack.each do |call| this_method_matched = if trigger_method === call[2].to_s true elsif call[2] == :method_missing last_method_matched else false end if !this_method_matched && last_method_matched && (file_match === call[0]) if File.file?(call[0]) return parse_documentation_block_at(call[0], call[1]) else return end end last_method_matched = this_method_matched end nil end |
.parse_documentation_block_at(file, line) ⇒ String?
Parses upwards a Ruby documentation block whose last line starts at or just before the given line in the given file
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/metaruby/dsls/doc.rb', line 43 def self.parse_documentation_block_at(file, line) lines = File.readlines(file) block = [] # Lines are given 1-based (as all editors work that way), and we # want the line before the definition. Remove two line = line - 2 while true case l = lines[line] when /^\s*$/ break when /^\s*#/ block << l else break end line = line - 1 end block = block.map do |l| l.strip.gsub(/^\s*#/, '') end # Now remove the same amount of spaces in front of each lines space_count = block.map do |l| l =~ /^(\s*)/ if $1.size != l.size $1.size end end.compact.min block = block.map do |l| l[space_count..-1] end if !block.empty? block.reverse.join("\n") end end |