Module: MetaRuby::DSLs
- Defined in:
- lib/metaruby/dsls.rb,
lib/metaruby/dsls/doc.rb,
lib/metaruby/dsls/find_through_method_missing.rb
Overview
DSLs-related tools
Find through method missing
The find through method missing functionality is meant to allow classes to turn objects that can be found (with a method that finds an object by its name) into an attribute call as e.g.
task.test_event # => task.find_event("test")
See FindThroughMethodMissing for a complete description
Documentation parsing
This provides the logic to find a documentation block above a DSL-like object creation. For instance, given a class that looks like
class Task
def event(name) # creates an event object with the given name
end
end
Used in a DSL context like so:
# The test event allows us
#
# To provide an example
event 'test'
The parse_documentation method allows to extract the comment block above the ‘event’ call. See DSLs.parse_documentation for more information
Defined Under Namespace
Modules: FindThroughMethodMissing
Class Method Summary collapse
-
.find_through_method_missing(object, m, args, suffix_match) ⇒ Object?
Generic implementation to create suffixed accessors for child objects on a class.
- .has_through_method_missing?(object, m, suffix_match) ⇒ Boolean
-
.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, suffix_match) ⇒ 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
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/metaruby/dsls/find_through_method_missing.rb', line 108 def self.find_through_method_missing(object, m, args, suffix_match) return false if m == :to_ary m = m.to_s suffix_match.each do |s, find_method_name| if m.end_with?(s) name = m[0, m.size - s.size] if !args.empty? raise ArgumentError, "expected zero arguments to #{m}, got #{args.size}", caller(4) else return object.send(find_method_name, name) end end end nil end |
.has_through_method_missing?(object, m, suffix_match) ⇒ Boolean
125 126 127 128 129 130 131 132 133 134 135 136 |
# File 'lib/metaruby/dsls/find_through_method_missing.rb', line 125 def self.has_through_method_missing?(object, m, suffix_match) return false if m == :to_ary m = m.to_s suffix_match.each do |s, has_method_name| if m.end_with?(s) name = m[0, m.size - s.size] return !!object.send(has_method_name, name) end end false end |
.parse_documentation_block(file_match, trigger_method = /.*/) ⇒ String?
Looks for the documentation block for the element that is being built.
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/metaruby/dsls/doc.rb', line 26 def self.parse_documentation_block(file_match, trigger_method = /.*/) last_method_matched = false caller_locations(1).each do |call| this_method_matched = if trigger_method === call.label true elsif call.label == 'method_missing' last_method_matched else false end if !this_method_matched && last_method_matched && (file_match === call.absolute_path) if File.file?(call.absolute_path) return parse_documentation_block_at(call.absolute_path, call.lineno) 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
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/metaruby/dsls/doc.rb', line 56 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 space_count = nil while true l = lines[line] comment_match = /^\s*#/.match(l) if comment_match comment_line = comment_match.post_match.rstrip stripped_line = comment_line.lstrip leading_spaces = comment_line.size - stripped_line.size if !stripped_line.empty? && (!space_count || space_count > leading_spaces) space_count = leading_spaces end block.unshift(comment_line) else break end line = line - 1 end if !block.empty? space_count ||= 0 block.map { |l| l[space_count..-1] }.join("\n") end end |