Module: MethodExtensions::MethodSourceWithDoc

Defined in:
lib/method_extensions/method/source_with_doc.rb

Defined Under Namespace

Classes: MethodDocRipper, MethodSourceRipper

Instance Method Summary collapse

Instance Method Details

#docObject

Returns comment preceding the method definition by parsing the file returned by ‘Method#source_location`

Sample IRB session:

ruby-1.9.2-head > require 'fileutils'

ruby-1.9.2-head > puts FileUtils.method(:mkdir).doc
#
# Options: mode noop verbose
#
# Creates one or more directories.
#
#   FileUtils.mkdir 'test'
#   FileUtils.mkdir %w( tmp data )
#   FileUtils.mkdir 'notexist', :noop => true  # Does not really create.
#   FileUtils.mkdir 'tmp', :mode => 0700
#


53
54
55
# File 'lib/method_extensions/method/source_with_doc.rb', line 53

def doc
  MethodDocRipper.doc_from_source_location(source_location)
end

#full_inspectObject



110
111
112
# File 'lib/method_extensions/method/source_with_doc.rb', line 110

def full_inspect
  "#{ to_s }\n#{ source_location }\n#{ source_with_doc }"
end

#irb_inspectObject

Place this to the ~/.irbrc class Method

alias_method :inspect, :irb_inspect if method_defined?(:irb_inspect)

end class UnboundMethod

alias_method :inspect, :irb_inspect if method_defined?(:irb_inspect)

end



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# File 'lib/method_extensions/method/source_with_doc.rb', line 121

def irb_inspect
  return to_s unless caller.grep(/pp\.rb/).empty? # pretty_print has some logic
  # based on output of Method#inspect, nasty, huh?

  require "coderay"
  require "rdoc/ri/driver"
  
  puts to_s

  if source_location
    puts "#{ source_location[0] }:#{ source_location[1] }"
  end

  d = doc

  if d && !(d = d.chomp).empty?
    # puts
    # TODO
    # 1. is there better way to drive RDoc?
    # 2. probably need to detect other doc types?
    # 3. RDoc::Markup::ToAnsi formatter reflows to the 78 chars width which
    #    looks ugly
    # 
    #  begin
    #    formatter = Class.new(RDoc::Markup::ToAnsi) do
    #      def wrap(text)
    #        @res << text
    #      end
    #    end.new
    #    parser = Class.new.extend(RDoc::Text)
    #    d = d.split("\n").map { |l| parser.parse(l).accept(formatter) }.join("\n")
    ##        rescue Exception => e
    #    puts e.inspect
    #    # anything goes wrong - just display comment verbatim
    #  end
    puts d
    # puts
  end

  begin
    src = source
    if src && !src.empty?
      puts CodeRay.scan(source_unindent(src), :ruby).term
    end
  rescue ArgumentError => e
    puts e.message
  end
  
  nil
end

#sourceObject

Returns method source by parsing the file returned by ‘Method#source_location`.

If method definition cannot be found ‘ArgumentError` exception is raised (this includes methods defined by `attr_accessor`, `module_eval` etc.).

Sample IRB session:

ruby-1.9.2-head > require 'fileutils'

ruby-1.9.2-head > puts FileUtils.method(:mkdir).source
def mkdir(list, options = {})
    fu_check_options options, OPT_TABLE['mkdir']
    list = fu_list(list)
    fu_output_message "mkdir #{options[:mode] ? ('-m %03o ' % options[:mode]) : ''}#{list.join ' '}" if options[:verbose]
    return if options[:noop]

    list.each do |dir|
      fu_mkdir dir, options[:mode]
    end
  end
 => nil


31
32
33
# File 'lib/method_extensions/method/source_with_doc.rb', line 31

def source
  MethodSourceRipper.source_from_source_location(source_location)
end

#source_with_docObject

ruby-1.9.2-head > irb_context.inspect_mode = false # turn off inspect mode so that we can view sources

ruby-1.9.2-head > ActiveRecord::Base.method(:find).source_with_doc ArgumentError: failed to find method definition around the lines:

delegate :find, :first, :last, :all, :destroy, :destroy_all, :exists?, :delete, :delete_all, :update, :update_all, :to => :scoped
delegate :find_each, :find_in_batches, :to => :scoped

ruby-1.9.2-head > ActiveRecord::Base.method(:scoped).source_with_doc

# Returns an anonymous scope.
#
#   posts = Post.scoped
#   posts.size # Fires "select count(*) from  posts" and returns the count
#   posts.each {|p| puts p.name } # Fires "select * from posts" and loads post objects
#
#   fruits = Fruit.scoped
#   fruits = fruits.where(:colour => 'red') if options[:red_only]
#   fruits = fruits.limit(10) if limited?
#
# Anonymous \scopes tend to be useful when procedurally generating complex queries, where passing
# intermediate values (scopes) around as first-class objects is convenient.
#
# You can define a scope that applies to all finders using ActiveRecord::Base.default_scope.
def scoped(options = {}, &block)
  if options.present?
    relation = scoped.apply_finder_options(options)
    block_given? ? relation.extending(Module.new(&block)) : relation
  else
    current_scoped_methods ? unscoped.merge(current_scoped_methods) : unscoped.clone
  end
end

ruby-1.9.2-head > ActiveRecord::Base.method(:unscoped).source_with_doc
 => def unscoped
  @unscoped ||= Relation.new(self, arel_table)
  finder_needs_type_condition? ? @unscoped.where(type_condition) : @unscoped
end

ruby-1.9.2-head > ActiveRecord::Relation.instance_method(:find).source_with_doc
 => # Find operates with four different retrieval approaches:
...
def find(*args, &block)
  return to_a.find(&block) if block_given?

  options = args.extract_options!

  if options.present?
...


104
105
106
107
108
# File 'lib/method_extensions/method/source_with_doc.rb', line 104

def source_with_doc
  return unless source_location

  [doc.to_s.chomp, source_unindent(source)].compact.reject(&:empty?).join("\n")
end