ruby 我感兴趣的库中的代码片段

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ruby 我感兴趣的库中的代码片段相关的知识,希望对你有一定的参考价值。

# rubytapas episode 10
# Ruby >= 1.9.2 && *nix and uses ENV['HOME']
Dir.home
# or Dir.home("avdi") if you wanted to set it yourself
# *nix
require 'etc'
Etc.getlogin
# therefore
user = Etc.getlogin             # => "avdi"
config_file = File.join(Dir.home(user), ".rubytapas") 
# => "/home/avdi/.rubytapas"
# in Rails
def track
  # do something with request
  send_file path_to_image('x.gif'), type: 'image/gif', disposition: 'inline', status: 200
end

# source: actionpack/lib/action_controller/metal/data_streaming.rb

  DEFAULT_SEND_FILE_OPTIONS = {
      :type         => 'application/octet-stream'.freeze,
      :disposition  => 'attachment'.freeze,
    }.freeze


      # Sends the file. This uses a server-appropriate method (such as X-Sendfile)
      # via the Rack::Sendfile middleware. The header to use is set via
      # config.action_dispatch.x_sendfile_header.
      # Your server can also configure this for you by setting the X-Sendfile-Type header.
      #
      # Be careful to sanitize the path parameter if it is coming from a web
      # page. <tt>send_file(params[:path])</tt> allows a malicious user to
      # download any file on your server.
      #
      # Options:
      # * <tt>:filename</tt> - suggests a filename for the browser to use.
      #   Defaults to <tt>File.basename(path)</tt>.
      # * <tt>:type</tt> - specifies an HTTP content type.
      #   You can specify either a string or a symbol for a registered type register with
      #   <tt>Mime::Type.register</tt>, for example :json
      #   If omitted, type will be guessed from the file extension specified in <tt>:filename</tt>.
      #   If no content type is registered for the extension, default type 'application/octet-stream' will be used.
      # * <tt>:disposition</tt> - specifies whether the file will be shown inline or downloaded.
      #   Valid values are 'inline' and 'attachment' (default).
      # * <tt>:status</tt> - specifies the status code to send with the response. Defaults to 200.
      # * <tt>:url_based_filename</tt> - set to +true+ if you want the browser guess the filename from
      #   the URL, which is necessary for i18n filenames on certain browsers
      #   (setting <tt>:filename</tt> overrides this option).
      #
      # The default Content-Type and Content-Disposition headers are
      # set to download arbitrary binary files in as many browsers as
      # possible. IE versions 4, 5, 5.5, and 6 are all known to have
      # a variety of quirks (especially when downloading over SSL).
      #
      # Simple download:
      #
      #   send_file '/path/to.zip'
      #
      # Show a JPEG in the browser:
      #
      #   send_file '/path/to.jpeg', :type => 'image/jpeg', :disposition => 'inline'
      #
      # Show a 404 page in the browser:
      #
      #   send_file '/path/to/404.html', :type => 'text/html; charset=utf-8', :status => 404
      #
      # Read about the other Content-* HTTP headers if you'd like to
      # provide the user with more information (such as Content-Description) in
      # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.11.
      #
      # Also be aware that the document may be cached by proxies and browsers.
      # The Pragma and Cache-Control headers declare how the file may be cached
      # by intermediaries. They default to require clients to validate with
      # the server before releasing cached responses. See
      # http://www.mnot.net/cache_docs/ for an overview of web caching and
      # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9
      # for the Cache-Control header spec.
      def send_file(path, options = {}) #:doc:
        raise MissingFile, "Cannot read file #{path}" unless File.file?(path) and File.readable?(path)

        options[:filename] ||= File.basename(path) unless options[:url_based_filename]
        send_file_headers! options

        self.status = options[:status] || 200
        self.content_type = options[:content_type] if options.key?(:content_type)
        self.response_body = FileBody.new(path)
      end

      # Avoid having to pass an open file handle as the response body.
      # Rack::Sendfile will usually intercept the response and uses
      # the path directly, so there is no reason to open the file.
      class FileBody #:nodoc:
        attr_reader :to_path

        def initialize(path)
          @to_path = path
        end

        # Stream the file's contents if Rack::Sendfile isn't present.
        def each
          File.open(to_path, 'rb') do |file|
            while chunk = file.read(16384)
              yield chunk
            end
          end
        end
      end
      
      
      # Sends the given binary data to the browser. This method is similar to
      # <tt>render :text => data</tt>, but also allows you to specify whether
      # the browser should display the response as a file attachment (i.e. in a
      # download dialog) or as inline data. You may also set the content type,
      # the apparent file name, and other things.
      #
      # Options:
      # * <tt>:filename</tt> - suggests a filename for the browser to use.
      # * <tt>:type</tt> - specifies an HTTP content type. Defaults to 'application/octet-stream'. You can specify
      #   either a string or a symbol for a registered type register with <tt>Mime::Type.register</tt>, for example :json
      #   If omitted, type will be guessed from the file extension specified in <tt>:filename</tt>.
      #   If no content type is registered for the extension, default type 'application/octet-stream' will be used.
      # * <tt>:disposition</tt> - specifies whether the file will be shown inline or downloaded.
      #   Valid values are 'inline' and 'attachment' (default).
      # * <tt>:status</tt> - specifies the status code to send with the response. Defaults to 200.
      #
      # Generic data download:
      #
      #   send_data buffer
      #
      # Download a dynamically-generated tarball:
      #
      #   send_data generate_tgz('dir'), :filename => 'dir.tgz'
      #
      # Display an image Active Record in the browser:
      #
      #   send_data image.data, :type => image.content_type, :disposition => 'inline'
      #
      # See +send_file+ for more information on HTTP Content-* headers and caching.
      def send_data(data, options = {}) #:doc:
        send_file_headers! options.dup
        render options.slice(:status, :content_type).merge(:text => data)
      end

    private
      def send_file_headers!(options)
        type_provided = options.has_key?(:type)

        options.update(DEFAULT_SEND_FILE_OPTIONS.merge(options))
        [:type, :disposition].each do |arg|
          raise ArgumentError, ":#{arg} option required" if options[arg].nil?
        end

        disposition = options[:disposition].to_s
        disposition += %(; filename="#{options[:filename]}") if options[:filename]

        content_type = options[:type]

        if content_type.is_a?(Symbol)
          extension = Mime[content_type]
          raise ArgumentError, "Unknown MIME type #{options[:type]}" unless extension
          self.content_type = extension
        else
          if !type_provided && options[:filename]
            # If type wasn't provided, try guessing from file extension.
            content_type = Mime::Type.lookup_by_extension(File.extname(options[:filename]).downcase.tr('.','')) || content_type
          end
          self.content_type = content_type
        end

        headers.merge!(
          'Content-Disposition'       => disposition,
          'Content-Transfer-Encoding' => 'binary'
        )

        response.sending_file = true

        # Fix a problem with IE 6.0 on opening downloaded files:
        # If Cache-Control: no-cache is set (which Rails does by default),
        # IE removes the file it just downloaded from its cache immediately
        # after it displays the "open/save" dialog, which means that if you
        # hit "open" the file isn't there anymore when the application that
        # is called for handling the download is run, so let's workaround that
        response.cache_control[:public] ||= false
      end
if defined?(JRUBY_VERSION) && defined?(ExecJS) && system('which node')
  STDOUT.puts "Using Node ExecJS runtime"
  ExecJS.runtime = ExecJS::Runtimes::Node
end
all_activated_gems = Gem::Specification.stubs.select(&:activated?)
first_activated_gem = all_activated_gems.first
name = first_activated_gem.name
version = first_activated_gem.version.version
task :clean do
  rm_rf(Dir["**/*~"] +
        Dir["**/*.diff"] +
        Dir["coverage.info"] +
        Dir["coverage"] +
        Dir["lib/*.output"])
end

def next_num(glob)
  num = Dir[glob].max[/\d+/].to_i + 1
end

desc "Compares PT to RP and deletes all files that match"
task :compare do
  files = Dir["unit/**/*.rb"]
  puts "Parsing #{files.size} files"
  files.each do |file|
    puts file
    system "./cmp.rb -q #{file} && rm #{file}"
  end
  system 'find -d unit -type d -empty -exec rmdir {} \;'
end

task :sort do
  sh 'grepsort "^ +def" lib/ruby_lexer.rb'
  sh 'grepsort "^ +def (test|util)" test/test_ruby_lexer.rb'
end

task :loc do
  loc1  = `wc -l ../1.0.0/lib/ruby_lexer.rb`[/\d+/]
  flog1 = `flog -s ../1.0.0/lib/ruby_lexer.rb`[/\d+\.\d+/]
  loc2  = `cat lib/ruby_lexer.rb lib/ruby_parser_extras.rb | wc -l`[/\d+/]
  flog2 = `flog -s lib/ruby_lexer.rb lib/ruby_parser_extras.rb`[/\d+\.\d+/]

  loc1, loc2, flog1, flog2 = loc1.to_i, loc2.to_i, flog1.to_f, flog2.to_f

  puts "1.0.0: loc = #{loc1} flog = #{flog1}"
  puts "dev  : loc = #{loc2} flog = #{flog2}"
  puts "delta: loc = #{loc2-loc1} flog = #{flog2-flog1}"
end

desc "Validate against all normal files in unit dir"
task :validate do
  sh "./cmp.rb unit/*.rb"
end

def run_and_log cmd, prefix
  files = ENV['FILES'] || 'unit/*.rb'
  p, x = prefix, "txt"
  n = Dir["#{p}.*.#{x}"].map { |s| s[/\d+/].to_i }.max + 1 rescue 1
  f = "#{p}.#{n}.#{x}"

  sh "#{cmd} #{Hoe::RUBY_FLAGS} bin/ruby_parse -q -g #{files} &> #{f}"

  puts File.read(f)
end

desc "Benchmark against all normal files in unit dir"
task :benchmark do
  run_and_log "ruby", "benchmark"
end

desc "Profile against all normal files in unit dir"
task :profile do
  run_and_log "zenprofile", "profile"
end

desc "what was that command again?"
task :huh? do
  puts "ruby #{Hoe::RUBY_FLAGS} bin/ruby_parse -q -g ..."
end

task :irb => [:isolate] do
  sh "GEM_HOME=#{Gem.path.first} irb -rubygems -Ilib -rruby_parser;"
end

def (task(:phony)).timestamp
  Time.at 0
end

task :isolate => :phony

file "lib/ruby18_parser.rb" => :isolate
file "lib/ruby19_parser.rb" => :isolate
file "lib/ruby20_parser.rb" => :isolate

task :compare18 do
  sh "./yack.rb lib/ruby18_parser.output > racc18.txt"
  sh "./yack.rb parse18.output > yacc18.txt"
  sh "diff -du racc18.txt yacc18.txt || true"
  puts
  sh "diff -du racc18.txt yacc18.txt | wc -l"
end

task :compare19 do
  sh "./yack.rb lib/ruby19_parser.output > racc19.txt"
  sh "./yack.rb parse19.output > yacc19.txt"
  sh "diff -du racc19.txt yacc19.txt || true"
  puts
  sh "diff -du racc19.txt yacc19.txt | wc -l"
end

task :compare20 do
  sh "./yack.rb lib/ruby20_parser.output > racc20.txt"
  sh "./yack.rb parse20.output > yacc20.txt"
  sh "diff -du racc20.txt yacc20.txt || true"
  puts
  sh "diff -du racc20.txt yacc20.txt | wc -l"
end

task :debug => :isolate do
  ENV["V"] ||= "20"
  Rake.application[:parser].invoke # this way we can have DEBUG set

  $: << "lib"
  require 'ruby_parser'
  require 'pp'

  parser = case ENV["V"]
           when "18" then
             Ruby18Parser.new
           when "19" then
             Ruby19Parser.new
           else
             Ruby20Parser.new
           end

  time = (ENV["RP_TIMEOUT"] || 10).to_i

  file = ENV["F"] || ENV["FILE"]

  ruby = if file then
           File.read(file)
         else
           file = "env"
           ENV["R"] || ENV["RUBY"]
         end

  begin
    pp parser.process(ruby, file, time)
  rescue Racc::ParseError => e
    p e
    ss = parser.lexer.src
    src = ss.string
    lines = src[0..ss.pos].split(/\n/)
    abort "on #{file}:#{lines.size}"
  end
end

def ruby20
  "/Users/ryan/.multiruby/install/2.0.0-p195/bin/ruby"
end

task :debug_ruby do
  file = ENV["F"] || ENV["FILE"]
  sh "#{ruby20} -cwy #{file} 2>&1 | ./yuck.rb"
end

task :extract => :isolate do
  ENV["V"] ||= "19"
  Rake.application[:parser].invoke # this way we can have DEBUG set

  file = ENV["F"] || ENV["FILE"]

  ruby "-Ilib", "bin/ruby_parse_extract_error", file
end

task :bugs do
  sh "for f in bug*.rb ; do #{Gem.ruby} -S rake debug F=$f && rm $f ; done"
end
I have some more examples I've collected, but came across these two today and thought wow!

* README
  - https://github.com/ms-ati/docile
  - https://github.com/colszowka/simplecov
  - https://github.com/nathanl/authority
* Contributing
  - https://github.com/rubygems/gems/blob/master/CONTRIBUTING.md
  - https://github.com/bundler/bundler/blob/master/CONTRIBUTING.md
  - http://nikcodes.com/2013/05/10/new-contributor-jump-in/
  - https://github.com/blog/1184-contributing-guidelines
  - https://github.com/puppetlabs/puppet/blob/master/CONTRIBUTING.md
  - https://github.com/thoughtbot/factory_girl_rails/blob/master/CONTRIBUTING.md
  - http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
  - https://github.com/github/gemoji/blob/master/MAINTAINING.md
  - https://github.com/metricfu/metric_fu/blob/master/CONTRIBUTING.md
  - https://github.com/railsbridge/docs/blob/master/CONTRIBUTING.md
* Release
  - https://github.com/pivotal/LicenseFinder/blob/master/release/manual_instructions.md
* Troubleshooting
  - https://github.com/cucumber/cucumber/wiki/Troubleshooting
* Configuration
  - https://github.com/YorickPeterse/ruby-lint/blob/master/doc/configuration.md
* Rich detail
  - https://github.com/jrochkind/fake_work_app/blob/master/README.md
- https://github.com/jimweirich/argus/blob/master/rakelib/gem.rake
- https://github.com/jimweirich/rspec-given/blob/master/Rakefile
- https://github.com/jimweirich/rspec-given/blob/master/rakelib/gemspec.rake
- https://github.com/jimweirich/rspec-given/blob/master/rakelib/preview.rake
- https://github.com/jimweirich/rake/blob/master/doc/command_line_usage.rdoc
require 'pathname'
require 'rails/railtie'
require 'active_record/railtie'
require 'active_support/railtie'
require 'active_support/all'
# see https://github.com/rails/rails/tree/master/activesupport/lib/active_support/
# require 'active_support/core_ext'
# require 'active_support/inflections'
# require 'active_support/inflector'
require 'active_support/dependencies'
require "bundler/setup"
# Bundler.require

begin
  module RailsApp
    class Application < Rails::Application
      config.secret_token = routes.append {
        root to: proc {
          [200, {"Content-Type" => "text/html"}, []]
        }
      }.to_s
      config.root = Pathname(File.expand_path('../..', __FILE__))
      config.active_support.deprecation = :log
      config.eager_load = false

    end
  end
  include ActiveSupport
  ["app/**/", "lib/**/"].each do |glob|
    Dir.glob(glob).each do |dir|
      Dependencies.autoload_paths << File.join(File.dirname(__FILE__), dir)
    end
  end
end unless defined?(Rails.application)
db_config  = File.read(Rails.root.join('config/database.yml'))
db_config = ERB.new(db_config).result(binding)
db_settings = YAML::load(db_config)['test']
ActiveRecord::Base.establish_connection(db_settings)
require 'action_view/railtie'
require 'rspec/rails'
require 'rspec/autorun'
require 'rspec'
require 'factory_girl'
require 'factory_girl_rails'
require 'database_cleaner'

# DatabaseCleaner.clean_with :truncation
# RSpec.configure do |config|
#   config.treat_symbols_as_metadata_keys_with_true_values = true
#   config.filter_run focus: true
#   config.run_all_when_everything_filtered = true
#   config.filter_run_excluding :slow unless ENV["SLOW_SPECS"]
#   config.fail_fast = ENV.include?('FAIL_FAST')
#   # TODO: Set random ordering when we get the specs passing
#   # config.order = 'random'
#   config.use_transactional_examples = true
#   config.include FactoryGirl::Syntax::Methods
# end

def use_model(name)
  require Rails.root.join("app/models/#{name}")
end
def use_lib(name)
  require Rails.root.join("lib/#{name}")
end
def use_initializer(name)
  require Rails.root.join('config/initializers', name)
end
def ensure_model_loaded(model_name, &block)
  @tries = 1
  begin
    block.call
  rescue NameError => e
    @tries -= 1
    if model_path = Rails.configuration.autoload_paths.detect do |path|
        filename = path.basename.ext('')
        model_name == filename
      end
      require model_path
      retry if @tries.zero?
    end
  end
end
begin
  require 'pry'
  require 'pry-plus'
rescue LoadError
  STDOUT.puts "pry not loaded"
end
# Borrowed from:
# https://github.com/carlhuda/bundler/blob/v1.1.rc.7/spec/quality_spec.rb
# then from vcr
describe "The library itself" do

  def readlines(filename)
    File.open(filename, 'rb') {|file| file.readlines }
  end

  def check_for_tab_characters(filename)
    failing_lines = []
    readlines(filename).each_with_index do |line,number|
      failing_lines << number + 1 if line =~ /\t/
    end

    unless failing_lines.empty?
      "#{filename} has tab characters on lines #{failing_lines.join(', ')}"
    end
  end

  def check_for_extra_spaces(filename)
    failing_lines = []
    readlines(filename).each_with_index do |line,number|
      next if line =~ /^\s+#.*\s+\n$/
      failing_lines << number + 1 if line =~ /\s+\n$/
    end

    unless failing_lines.empty?
      "#{filename} has spaces on the EOL on lines #{failing_lines.join(', ')}"
    end
  end

  RSpec::Matchers.define :be_well_formed do
    failure_message_for_should do |actual|
      actual.join("\n")
    end

    match do |actual|
      actual.empty?
    end
  end

  it "has no malformed whitespace" do
    error_messages = []
    Dir.chdir(File.expand_path("../..", __FILE__)) do
      `git ls-files`.split("\n").each do |filename|
        next if filename =~ /vendor|.feature|.yml|.gitmodules/
        error_messages << check_for_tab_characters(filename)
        error_messages << check_for_extra_spaces(filename)
      end
    end
    expect(error_messages.compact).to be_well_formed
  end
end
desc 'Generate YARD documentation'
task :yard => :generate do
  sh('yard doc')
end

desc 'Generate Changelog'
task :changelog do
  fs     = "\u{fffd}"
  format = "%d#{fs}%s#{fs}%an#{fs}%ai"

  # Format: version => { commit-class => changes }
  changelog = Hash.new do |hash, version|
    hash[version] = Hash.new do |hash, klass|
      hash[klass] = []
    end
  end

  IO.popen("git log --pretty='#{format}' 2.0 master", 'r') do |io|
    current_version = nil

    io.each_line do |line|
      version, message, author, date = line.
            match(/^(?: \((.*)\))?#{fs}(.*)#{fs}(.*)#{fs}(.*)$/o).captures
      date = Date.parse(date)

      current_version = "#{$1} (#{date})" if version =~ /(v[\d\w.]+)/
      current_version = "v#{Parser::VERSION} (#{date})" if version =~ /HEAD/

      next if current_version.nil? || message !~ /^[+*-]/

      changelog[current_version][message[0]] << "#{message[1..-1]} (#{author})"
    end
  end

  commit_classes = {
    '*' => 'API modifications:',
    '+' => 'Features implemented:',
    '-' => 'Bugs fixed:',
  }

  File.open('CHANGELOG.md', 'w') do |io|
    io.puts 'Changelog'
    io.puts '========='
    io.puts

    changelog.each do |version, commits|
      io.puts version
      io.puts '-' * version.length
      io.puts

      commit_classes.each do |sigil, description|
        next unless commits[sigil].any?

        io.puts description
        commits[sigil].uniq.each do |commit|
          io.puts " * #{commit.gsub('<', '\<').lstrip}"
        end
        io.puts
      end
    end
  end

  sh('git commit CHANGELOG.md -m "Update changelog." || true')
end

rule '.rb' => '.rl' do |t|
  sh "ragel -F1 -R #{t.source} -o #{t.name}"
end

rule '.rb' => '.y' do |t|
  opts = [ "--superclass=Parser::Base",
           t.source,
           "-o", t.name
         ]
  opts << "--debug" if ENV['RACC_DEBUG']

  sh "racc", *opts
end
- [erd generator](https://gist.github.com/bf4/7209165)
- [git ranking](https://gist.github.com/bf4/7209165)
- [fake github api](https://gist.github.com/bf4/7310171)
- [misc](https://gist.github.com/bf4/b13867c5a083382f0c08)
- [rubygems s3 fetcher](https://github.com/rubygems/rubygems/pull/856#issuecomment-45749890)
- [capistrano deploy notifications](https://github.com/bf4/capistrano_deploy_lock/blob/notifications/notifications.rb#L72)

```plain
highlight files https://gist.github.com/bf4/7531475
code snippets https://gist.github.com/bf4/7157519
resolve gem dependencies  https://gist.github.com/bf4/6731278
mti like stuff https://gist.github.com/bf4/6300884
capistrano deploy lock removal on error https://gist.github.com/bf4/5823660
logger with proc as adapter https://gist.github.com/bf4/5797905
js loader https://gist.github.com/bf4/5597117
expand uri https://gist.github.com/bf4/5541450
active record macros https://gist.github.com/bf4/cfaf172426210b8f0434
server.sh https://gist.github.com/bf4/5519396
auto_mount https://gist.github.com/bf4/5456978
custom rails validations, date range https://gist.github.com/bf4/5320847
rails router constraints https://gist.github.com/bf4/5320631
ruby object model https://gist.github.com/bf4/5225535
ruby data uri https://gist.github.com/bf4/5188994
imdb celeb search https://gist.github.com/bf4/43d48d5a279462705f95
polymorphic many to many in rails https://gist.github.com/bf4/4742122
rails error handling in view https://gist.github.com/bf4/4381029
rails template / layout inheritance https://gist.github.com/bf4/4370117
string to date https://gist.github.com/bf4/4370014
timezone converter https://gist.github.com/bf4/3668333#file-timezone_converter-rb-L53
cli pipeable or interactibve parsing executable in ruby https://gist.github.com/bf4/0b43ed1e75a69fb40513
null object https://gist.github.com/bf4/3438476
ruby  module pattern https://gist.github.com/bf4/3438307
rails attribute serializer macro https://gist.github.com/bf4/3151933
MetricFile https://github.com/bf4/metric_fu/blob/dev/lib/metric_fu/metric_file.rb
OptionsHash https://github.com/bf4/metric_fu/blob/dev/lib/metric_fu/options_hash.rb
remote pairing steps through remote tunnel https://gist.github.com/rjackson/5396105
configure multiple ssh identities https://confluence.atlassian.com/pages/viewpage.action?pageId=271943168
trace calls https://github.com/metricfu/metric_fu/pull/77
matrix stuff https://gist.github.com/bf4/7125723

https://github.com/howaboutwe/rspec-style-guide

rubygtems api https://gist.github.com/shaiguitar/d2af997b7f58e24fd305
https://github.com/shaiguitar/gem_velocities
https://gist.github.com/shaiguitar/7e6d95971c5254fa3665

https://gist.github.com/mrflip/910255#file_awk_vs_ruby.sh
https://en.wikibooks.org/wiki/Ad_Hoc_Data_Analysis_From_The_Unix_Command_Line
http://strata.oreilly.com/2011/04/data-hand-tools.html

https://github.com/whitequark/rack-utf8_sanitizer/blob/master/lib/rack/utf8_sanitizer.rb

verified accounts on twitter http://www.wikihow.com/Get-a-Verified-Account-on-Twitter#_note-7
rails rumble cli toolkit https://github.com/railsrumble/cli-toolkit cap script https://gist.github.com/tsmango/3849380
fast deploy https://github.com/flogic/whiskey_disk
heroku deployer https://github.com/inancgumus/heroku-deployer
cap tasks: https://github.com/freerange/recap/blob/1.x/lib/recap/tasks/rails.rb#L45
  https://github.com/freerange/recap/blob/1.x/lib/recap/tasks/bundler.rb#L30
https://github.com/freerange/recap/blob/1.x/lib/recap/tasks/rails.rb
https://github.com/freerange/recap/blob/1.x/lib/recap/tasks/deploy.rb
 see http://blog.codeclimate.com/blog/2013/10/02/high-speed-rails-deploys-with-git/?utm_source=Code+Climate&utm_campaign=11f3651828-newsletter-2013-10&utm_medium=email&utm_term=0_672a7f5529-11f3651828-323541861
 ```
# Usage:  MailCatcher.catch_all! will set the delivery_method
# for ActionMailer::Base and Mail to :mail_catcher, which uses
# changes the 'to' email address before sending to '@catch_all_domain'
# and sends the email using the default smtp connection settigs
module MailCatcher
  class DeliveryMethod
     attr_accessor :settings

     def initialize(options = {})
       self.settings = options
     end

     def deliver!(mail)
       catch_emails(mail)
     end

     def catch_emails(mail)
       MailCatcher.munge_email(mail)
       MailCatcher.delivery_method.deliver!(mail)
     end

  end
  mattr_accessor :mailer_config
  mattr_accessor :original_delivery_method, :original_smtp_settings
  mattr_accessor :delivery_method
  mattr_accessor :catch_all_domain

  # Converts all of the email addresses into a user_at_domain_dot_com format
  # and appends with an @domain.com. This is useful to send registration emails
  # to a catch-all email address like *@domain.com.
  def self.munge_email(mail)
    mail.to = rewrite_email_address(mail.to)
  end

  def self.rewritten_address_prefix
    "mail_catcher"
  end
  
  def self.rewrite_email_address(addresses)
    Array(mail.to).flat_map do |address|
      sanitized_original_address = address.gsub('@', '_at_').gsub('.','_dot_')
      "#{rewritten_address_prefix}+#{sanitized_original_address}@#{catch_all_domain}"
    end
  end

  def self.catch_all!(domain = self.catch_all_domain)
    initialize
    Rails.application.config.action_mailer.delivery_method = :mail_catcher
    ActionMailer::Base.delivery_method = :mail_catcher
    Mail.defaults do
      delivery_method MailCatcher::DeliveryMethod
    end
  end

  def self.initialize
    self.catch_all_domain = "localhost"
    self.mailer_config = Rails.application.config.action_mailer
    mailer_config.add_delivery_method(:mail_catcher, MailCatcher::DeliveryMethod)
    self.original_delivery_method = mailer_config.delivery_method
    self.original_smtp_settings   = mailer_config.smtp_settings
    self.delivery_method = Mail::Configuration.instance.
           lookup_delivery_method(original_delivery_method).
           new(original_smtp_settings)
  end

end
# https://github.com/rubygems/rubygems/blob/master/lib/rubygems.rb#L763
 ##
  # Safely read a file in binary mode on all platforms.

  def self.read_binary(path)
    open path, 'rb+' do |f|
      f.flock(File::LOCK_EX)
      f.read
    end
  end
  
# exec from jvm
# https://github.com/davetron5000/methadone/blob/master/lib/methadone/execution_strategy/jvm.rb#L10

      def run_command(command)

        process = case command

                  when String then

                    java.lang.Runtime.get_runtime.exec(command)

                  else
                    java.lang.Runtime.get_runtime.exec(*command)

                  end
        process.get_output_stream.close

        stdout = input_stream_to_string(process.get_input_stream)

        stderr = input_stream_to_string(process.get_error_stream)

        exitstatus = process.wait_for

        [stdout.chomp,stderr.chomp,OpenStruct.new(:exitstatus => exitstatus)]

      end


      def exception_meaning_command_not_found
        NativeException

      end


    private
      def input_stream_to_string(is)

        ''.tap do |string|

          ch = is.read

          while ch != -1

            string << ch

            ch = is.read

          end
        end

      end
    end
- img_url = "http://example.com/image.jpg"
- img_type = img_url.split('.')[-1]
- img_binary = open(img_url).read
- img_data = ActiveSupport::Base64.encode64(img_binary).gsub("\n", '')
%img{src: "data:image/#{img_type};base64,#{img_data}"}

# sass-rails can do this with asset-data-url('path_to_img_in_pipeline')
module Hoe::Publish
  ##
  # Optional: An array of the project's blog categories. Defaults to project
  # name.

  attr_accessor :blog_categories

  ##
  # Optional: Name of destination directory for RDoc generated files.
  # [default: doc]

  attr_accessor :local_rdoc_dir

  ##
  # Optional: Should RDoc and ri generation tasks be defined? [default: true]
  #
  # Allows you to define custom RDoc tasks then use the publish_rdoc task to
  # upload them all.  See also local_rdoc_dir

  attr_accessor :need_rdoc

  ##
  # Optional: An array of remote (rsync) paths to copy rdoc to.
  #
  # eg:
  #
  #     rdoc_locations << "user@server:Sites/rdoc/#{remote_rdoc_dir}"

  attr_accessor :rdoc_locations

  ##
  # Optional: Name of RDoc destination directory on Rubyforge. [default: +name+]

  attr_accessor :remote_rdoc_dir

  ##
  # Optional: Flags for RDoc rsync. [default: "-av --delete"]

  attr_accessor :rsync_args

  Hoe::DEFAULT_CONFIG["publish_on_announce"] = true
  Hoe::DEFAULT_CONFIG["blogs"] = [
                                  {
                                    "user"     => "user",
                                    "password" => "password",
                                    "url"      => "url",
                                    "blog_id"  => "blog_id",
                                    "extra_headers" => {
                                      "mt_convert_breaks" => "markdown"
                                    },
                                  }
                                 ]

  ##
  # Initialize variables for plugin.

  def initialize_publish
    self.blog_categories ||= [self.name]
    self.local_rdoc_dir  ||= 'doc'
    self.need_rdoc       ||= true
    self.rdoc_locations  ||= []
    self.remote_rdoc_dir ||= self.name
    self.rsync_args      ||= '-av -O --delete'
  end

  ##
  # Declare a dependency on rdoc, IF NEEDED.

  def activate_publish_deps
    dependency "rdoc", "~> 4.0", :developer if need_rdoc
  end

  ##
  # Define tasks for plugin.

  def define_publish_tasks
    if need_rdoc then
      task :isolate # ensure it exists

      desc "Generate rdoc"
      task :docs => [:clobber_docs, :isolate] do
        sh(*make_rdoc_cmd)
      end

      desc "Generate rdoc coverage report"
      task :dcov => :isolate do
        sh(*make_rdoc_cmd('-C'))
      end

      desc "Remove RDoc files"
      task :clobber_docs do
        rm_rf local_rdoc_dir
      end

      task :clobber => :clobber_docs

      desc 'Generate ri locally for testing.'
      task :ridocs => [:clean, :isolate] do
        ruby(*make_rdoc_cmd('--ri', '-o', 'ri'))
      end
    end

    desc "Publish RDoc to wherever you want."
    task :publish_docs => [:clean, :docs] do
      publish_docs_task
    end

    # no doco for this one
    task :publish_on_announce do
      publish_on_announce_task
    end

    desc 'Generate email announcement file.'
    task :debug_email do
      puts generate_email
    end

    desc 'Post announcement to blog. Uses the "blogs" array in your hoerc.'
    task :post_blog do
      post_blog_task
    end

    desc 'Announce your release.'
    task :announce => [:post_blog, :publish_on_announce ]
  end

  def publish_docs_task # :nodoc:
    warn "no rdoc_location values" if rdoc_locations.empty?
    self.rdoc_locations.each do |dest|
      sh %{rsync #{rsync_args} #{local_rdoc_dir}/ #{dest}}
    end
  end

  def publish_on_announce_task # :nodoc:
    with_config do |config, _|
      Rake::Task['publish_docs'].invoke if config["publish_on_announce"]
    end
  end

  def post_blog_task # :nodoc:
    with_config do |config, path|
      break unless config['blogs']

      config['blogs'].each do |site|
        if site['path'] then
          msg = "post_blog_#{site['type']}"
          send msg, site
          system site["cmd"] if site["cmd"]
        else
          require 'xmlrpc/client'

          _, title, body, urls = announcement
          body += "\n\n#{urls}"

          server = XMLRPC::Client.new2(site['url'])
          content = site['extra_headers'].merge(:title => title,
                                                :description => body,
                                                :categories => blog_categories)

          server.call('metaWeblog.newPost',
                      site['blog_id'],
                      site['user'],
                      site['password'],
                      content,
                      true)
        end
      end
    end
  end

  def make_rdoc_cmd(*extra_args) # :nodoc:
    title = "#{name}-#{version} Documentation"
    title = "#{group_name}'s #{title}" if group_name != name
    rdoc  = Gem.bin_wrapper "rdoc"

    %W[#{rdoc}
       --title #{title}
       -o #{local_rdoc_dir}
      ] +
      spec.rdoc_options +
      extra_args +
      spec.require_paths +
      spec.extra_rdoc_files
  end

  def post_blog_zenweb site # :nodoc:
    dir = site["path"]

    _, title, body, urls = announcement
    body += "\n\n#{urls}"

    Dir.chdir File.expand_path dir do
      time = Time.at Time.now.to_i # nukes fractions
      path = [time.strftime("%Y-%m-%d-"),
              title.sub(/\W+$/, '').gsub(/\W+/, '-'),
              ".html.md"].join

      header = {
        "title"      => title,
        "categories" => blog_categories,
        "date"       => time,
      }

      File.open path, "w" do |f|
        f.puts header.to_yaml.gsub(/\s$/, '')
        f.puts "..."
        f.puts
        f.puts body
      end
    end
  end

  def generate_email full = nil # :nodoc:
    require 'time'

    abort "No email 'to' entry. Run `rake config_hoe` to fix." unless
      !full || email_to

    from_name, from_email      = author.first, email.first
    subject, title, body, urls = announcement

    [
     full && "From: #{from_name} <#{from_email}>",
     full && "To: #{email_to.join(", ")}",
     full && "Date: #{Time.now.rfc2822}",
     "Subject: [ANN] #{subject}",
     "", title,
     "", urls,
     "", body,
    ].compact.join("\n")
  end

  def announcement # :nodoc:
    changes = self.changes.rdoc_to_markdown
    subject = "#{name} #{version} Released"
    title   = "#{name} version #{version} has been released!"
    body    = "#{description}\n\nChanges:\n\n#{changes}".rdoc_to_markdown

    urls =
      case self.urls
      when Hash then
        self.urls.map { |k,v| "* #{k}: <#{v.strip.rdoc_to_markdown}>" }
      when Array then
        self.urls.map { |s| "* <#{s.strip.rdoc_to_markdown}>" }
      else
        raise "unknown urls format: #{urls.inspect}"
      end


    return subject, title, body, urls.join("\n")
  end
end

class ::Rake::SshDirPublisher # :nodoc:
  attr_reader :host, :remote_dir, :local_dir
end

class String
  ##
  # Very basic munge from rdoc to markdown format.

  def rdoc_to_markdown
    self.gsub(/^mailto:/, '').gsub(/^(=+)/) { "#" * $1.size }
  end
end
# https://github.com/seattlerb/hoe-seattlerb/blob/master/lib/hoe/history.rb

##
# History plugin for Hoe. Allows you to calculate all of the flog &
# flay scores over the releases of your project in an SCM independent
# way.

module Hoe::History
  def define_history_tasks # :nodoc:
    # do nothing
  end

  ##
  # Calculate the flog and flay score for a Hoe project.

  def flog_flay
    flog = `flog -s -c $(cat Manifest.txt | grep -v txt$) 2>/dev/null`
    flay = `flay -s    $(cat Manifest.txt | grep -v txt$) 2>/dev/null`

    flog_total = flog[/([\d\.]+): flog total/, 1].to_f
    flog_avg   = flog[/([\d\.]+): flog\/method average/, 1].to_f
    flay_total = flay[/Total score .lower is better. = (\d+)/, 1].to_i

    return flog_total, flog_avg, flay_total
  end

  ##
  # Load cached history.

  def load_history
    require "yaml"
    YAML.load_file(".history.yaml") rescue {}
  end

  ##
  # Save cached history.

  def save_history data
    require "yaml"
    File.open ".history.yaml", "w" do |f|
      YAML.dump data, f
    end
  end

  ##
  # Calculate the history across all versions. Uses `versions` from an
  # SCM plugin to figure out how to deal with the SCM.

  def history versions
    history = load_history
    history.delete "dev" # FIX: this is p4 specific - make a variable?

    flog_total = flog_avg = flay_total = nil

    puts "version\tflog\tavg\tflay"
    versions.each do |version|
      history[version] = yield(version) unless history[version]

      flog_total, flog_avg, flay_total = history[version]
      puts "%s\t%.1f\t%.1f\t%d" % [version, flog_total, flog_avg, flay_total]
    end
  ensure
    save_history history
  end
end
##
# Email plugin for Hoe.
# from https://github.com/seattlerb/hoe-seattlerb/blob/master/lib/hoe/email.rb

module Hoe::Email

  # e.g.
  #  email:
  #  user: user.name
  #  pass: xxxx
  #  auth: plain
  #  port: submission
  #  to:
  #  - ruby-talk@ruby-lang.org
  #  host: smtp.gmail.com

  Hoe::DEFAULT_CONFIG["email"] = {
    "to"   => [],
    "user" => nil,
    "pass" => nil,
    "host" => nil,
    "port" => "smtp",
    "auth" => nil,
    "tls"  => nil,
  }

  ##
  # Who to send email to.

  attr_reader :email_to

  ##
  # Initialize the email plugin. Get the email/to from hoe's config.

  def initialize_email
    with_config do |config, _|
      @email_to = config["email"]["to"] rescue nil
    end
  end

  ##
  # Define email tasks.

  def define_email_tasks
    require 'net/smtp'
    begin
      require 'smtp_tls'
    rescue LoadError
    end

    # attach to announcements
    task :announce => :send_email

    desc "Send an announcement email."
    task :send_email do
      warn "sending email"
      message = generate_email :full

      with_config do |conf, _|
        host = conf["email"]["host"]
        port = conf["email"]["port"]
        user = conf["email"]["user"]
        pass = conf["email"]["pass"]
        auth = conf["email"]["auth"]
        tls  = conf["email"]["tls"]

        port = Socket.getservbyname port unless Integer === port

        tls = port != 25 if tls.nil?

        start_args = [Socket.gethostname, user, pass, auth].compact

        raise 'gem install smtp_tls' if tls and
          not Net::SMTP.method_defined? :starttls

        smtp = Net::SMTP.new(host, port)
        smtp.set_debug_output $stderr if $DEBUG
        smtp.enable_starttls if tls
        smtp.start(*start_args) do |server|
          server.send_message message, Array(email).first, *email_to
        end
      end
      warn "...done"
    end
  end
end
task :plugins do
  puts `find lib/hoe -name \*.rb | xargs grep -h module.Hoe::`.
    gsub(/module/, '*')
end

task :known_plugins do
  dep         = Gem::Dependency.new(/^hoe-/, Gem::Requirement.default)
  fetcher     = Gem::SpecFetcher.fetcher
  spec_tuples = fetcher.find_matching dep

  max = spec_tuples.map { |(tuple, source)| tuple.first.size }.max

  spec_tuples.each do |(tuple, source)|
    spec = Gem::SpecFetcher.fetcher.fetch_spec(tuple, URI.parse(source))
    puts "* %-#{max}s - %s (%s)" % [spec.name, spec.summary, spec.authors.first]
  end
end
# from https://github.com/metricfu/metric_fu/issues/107
# require 'date'
# 
# today=Date.today.strftime('%Y%m%d')
# from_date=Date.parse('2013-06-29')
# until_date=Date.parse('2013-07-29')
# (from_date..until_date).each{|date|
#   git_log_cmd = "git log --max-count=1 --before=#{date} --after=#{date - 1} --format='%H'"
#   puts "git_log_cmd: #{git_log_cmd}"
#   hash = `#{git_log_cmd}`.to_s.strip
#   process_commit(hash, date.strftime('%Y%m%d'))
# }; nil

# get you the last commit for `date`, where date is end of day on a given day
# `git rev-list -n 1 --before=#{date} master`

# git log --max-count=1 --after=2013-07-24 --before=2013-07-25 --date=iso --format="%H, %ai"

execute_cmd = "metric_fu --format yaml --out _data/#{date.strftime('%Y%m%d')}.yml"
def pattern(tag_pattern=nil)
  ["refs/tags",tag_pattern].compact.join('/')
end
TagRange = Struct.new(:output) do
  def tag_name
   output.split(',')[1]
  end
  def date
    output.split(',')[0].gsub(/[^\d]/,'')
  end
end
# @return
def tag_range(count,tag_pattern=nil)
  hash_format = '%(objectname:short)'
  ymd_format = '%(taggerdate:short)'
  tag_name_format = '%(refname:short)'
  format = "#{ymd_format},#{tag_name_format}"
  ` git for-each-ref #{pattern(tag_pattern)} --sort=-taggerdate --format='#{format}' --count=#{count}`.split(/\n/).map(&:strip).map{|output|TagRange.new(output)}
end
# matches either tags starting with the stage name
# or containing 'ruby' e.g.
# refs/tags/cruby* or ref/tags/*ruby*
def process_commit(hash, date)
  execute_cmd = "metric_fu --format yaml --out _data/#{date}.yml"
  unless hash == ''
    message = "#{date},#{hash}"
    puts "BEGIN #{message}"
    puts "execute_cmd: #{execute_cmd}"
    p `git reset --hard origin/master && git checkout #{hash} && #{execute_cmd}; git checkout master`
    puts "END #{message}"
  end
end
tag_range(10,'v*').each do |range|
  process_commit(range.tag_name,range.date)
end

################
 def current_time
      Time.now.strftime('%Y-%m-%d %H:%M')
    end

    # see http://stackoverflow.com/questions/1404796/how-to-get-the-latest-tag-name-in-current-branch-in-git
    # see https://www.kernel.org/pub/software/scm/git/docs/git-for-each-ref.html
    # see https://www.kernel.org/pub/software/scm/git/docs/git-describe.html
    # see https://www.kernel.org/pub/software/scm/git/docs/git-log.html
    def change_log
      last_deploy_tag = `git for-each-ref #{pattern} --sort=-taggerdate --format='%(objectname:short)' --count=1`.strip
      `git log --pretty='%d %s <%an>' --abbrev-commit --graph --decorate #{last_deploy_tag}..HEAD`.strip
    end

    # matches either tags starting with the stage name
    # or containing 'ruby' e.g.
    # refs/tags/cruby* or ref/tags/*ruby*
    def pattern
      "refs/tags/#{defined?(stage) ? stage : '*ruby'}*"
    end

    def current_hash
      `git describe`.strip
    end
# https://github.com/gemnasium/gemnasium-parser/blob/master/lib/gemnasium/parser/patterns.rb#L11
module Gemnasium
  module Parser
    module Patterns
      GEM_NAME = /[a-zA-Z0-9\-_\.]+/
      QUOTED_GEM_NAME = /(?:(?<gq>["'])(?<name>#{GEM_NAME})\k<gq>|%q<(?<name>#{GEM_NAME})>)/

      MATCHER = /(?:=|!=|>|<|>=|<=|~>)/
      VERSION = /[0-9]+(?:\.[a-zA-Z0-9]+)*/
      REQUIREMENT = /[ \t]*(?:#{MATCHER}[ \t]*)?#{VERSION}[ \t]*/
      REQUIREMENT_LIST = /(?<qr1>["'])(?<req1>#{REQUIREMENT})\k<qr1>(?:[ \t]*,[ \t]*(?<qr2>["'])(?<req2>#{REQUIREMENT})\k<qr2>)?/
      REQUIREMENTS = /(?:#{REQUIREMENT_LIST}|\[[ \t]*#{REQUIREMENT_LIST}[ \t]*\])/

      KEY = /(?::\w+|:?"\w+"|:?'\w+')/
      SYMBOL = /(?::\w+|:"[^"#]+"|:'[^']+')/
      STRING = /(?:"[^"#]*"|'[^']*')/
      BOOLEAN = /(?:true|false)/
      NIL = /nil/
      ELEMENT = /(?:#{SYMBOL}|#{STRING})/
      ARRAY = /\[(?:#{ELEMENT}(?:[ \t]*,[ \t]*#{ELEMENT})*)?\]/
      VALUE = /(?:#{BOOLEAN}|#{NIL}|#{ELEMENT}|#{ARRAY}|)/
      PAIR = /(?:(#{KEY})[ \t]*=>[ \t]*(#{VALUE})|(\w+):[ \t]+(#{VALUE}))/
      OPTIONS = /#{PAIR}(?:[ \t]*,[ \t]*#{PAIR})*/
      COMMENT = /(#[^\n]*)?/

      GEM_CALL = /^[ \t]*gem\(?[ \t]*#{QUOTED_GEM_NAME}(?:[ \t]*,[ \t]*#{REQUIREMENT_LIST})?(?:[ \t]*,[ \t]*(?<opts>#{OPTIONS}))?[ \t]*\)?[ \t]*#{COMMENT}$/

      SYMBOLS = /#{SYMBOL}([ \t]*,[ \t]*#{SYMBOL})*/
      GROUP_CALL = /^(?<i1>[ \t]*)group\(?[ \t]*(?<grps>#{SYMBOLS})[ \t]*\)?[ \t]+do[ \t]*?\n(?<blk>.*?)\n^\k<i1>end[ \t]*$/m

      GIT_CALL = /^(?<i1>[ \t]*)git[ \(][^\n]*?do[ \t]*?\n(?<blk>.*?)\n^\k<i1>end[ \t]*$/m

      PATH_CALL = /^(?<i1>[ \t]*)path[ \(][^\n]*?do[ \t]*?\n(?<blk>.*?)\n^\k<i1>end[ \t]*$/m

      GEMSPEC_CALL = /^[ \t]*gemspec(?:\(?[ \t]*(?<opts>#{OPTIONS}))?[ \t]*\)?[ \t]*$/

      ADD_DEPENDENCY_CALL = /^[ \t]*\w+\.add(?<type>_runtime|_development)?_dependency\(?[ \t]*#{QUOTED_GEM_NAME}(?:[ \t]*,[ \t]*#{REQUIREMENTS})?[ \t]*\)?[ \t]*#{COMMENT}$/

      def self.options(string)
        {}.tap do |hash|
          return hash unless string
          pairs = Hash[*string.match(OPTIONS).captures.compact]
          pairs.each{|k,v| hash[key(k)] = value(v) }
        end
      end

      def self.key(string)
        string.tr(%(:"'), "")
      end

      def self.value(string)
        case string
        when ARRAY then values(string.tr("[]", ""))
        when SYMBOL then string.tr(%(:"'), "").to_sym
        when STRING then string.tr(%("'), "")
        when BOOLEAN then string == "true"
        when NIL then nil
        end
      end

      def self.values(string)
        string.strip.split(/[ \t]*,[ \t]*/).map{|v| value(v) }
      end
    end
  end
end
- https://speakerdeck.com/jasonrclark/extending-gems-patterns-and-anti-patterns-of-making-your-gem-pluggable
- https://github.com/intridea/omniauth/blob/master/lib/omniauth/strategy.rb#L52
- https://github.com/intridea/multi_json/blob/master/lib/multi_json.rb#L103
- https://github.com/rspec/rspec-core/blob/master/lib/rspec/core.rb#L144
- https://github.com/avdi/naught/blob/master/lib/naught/null_class_builder.rb#L40
- https://github.com/pry/pry/blob/master/lib/pry/plugins.rb#L70
- https://github.com/seattlerb/flog/blob/master/lib/flog_cli.rb#L34
- https://github.com/seattlerb/hoe/blob/master/lib/hoe.rb#L301
- https://github.com/guard/guard/blob/master/lib/guard.rb#L275
- https://github.com/rspec/rspec-mocks/blob/master/lib/rspec/mocks/space.rb#L63
- https://github.com/plataformatec/devise/blob/master/lib/devise.rb#L333
- https://github.com/hassox/warden/blob/master/lib/warden/strategies.rb#L6
- https://github.com/hassox/warden/blob/master/lib/warden/hooks.rb
- loading plugins https://github.com/lsegal/yard/blob/master/lib/yard/config.rb#L144
  - gems https://github.com/lsegal/yard/blob/master/lib/yard/config.rb#L169
  - from hash by name https://github.com/lsegal/yard/blob/master/lib/yard/config.rb#L189
  - from arguments by name https://github.com/lsegal/yard/blob/master/lib/yard/config.rb#L194
  - universal plugin name translator https://github.com/lsegal/yard/blob/master/lib/yard/config.rb#L248
  - results like registry https://github.com/lsegal/yard/blob/master/lib/yard/registry.rb
  - gem backparts source_index.rb https://github.com/lsegal/yard/tree/master/lib/yard/rubygems/backports
  - https://github.com/lsegal/yard/blob/master/lib/yard/options.rb options hash
  - https://github.com/lsegal/yard/blob/master/lib/yard/logging.rb logger
  - https://github.com/lsegal/yard/blob/master/lib/yard/globals.rb global
  - temporary method __p https://github.com/lsegal/yard/blob/master/lib/yard/autoload.rb
  - rake::tasklib https://github.com/lsegal/yard/blob/master/lib/yard/rake/yardoc_task.rb
- rubygems plugin register command https://github.com/avdi/gem-love/blob/master/lib/rubygems_plugin.rb
  - https://github.com/avdi/gem-love/blob/master/lib/rubygems/commands/love_command.rb 
- [Bundler should have a plugin system](https://github.com/bundler/bundler/issues/1945)
- http://andre.arko.net/2010/09/06/jekyll-postfiles-plugin/
- http://blog.engineyard.com/2010/extending-rails-3-with-railties
- http://api.rubyonrails.org/classes/ActionDispatch/MiddlewareStack.html
- http://api.rubyonrails.org/classes/Rails/Railtie/Configuration.html
- https://github.com/intridea/omniauth/wiki/List-of-Strategies
- https://github.com/colszowka/simplecov/blob/master/lib/simplecov/formatter/multi_formatter.rb
- https://github.com/jeremyevans/sequel/blob/master/lib/sequel/model/plugins.rb
# https://github.com/sferik/twitter/blob/master/lib/twitter/utils.rb
module Twitter
  module Utils
    class << self
      def included(base)
        base.extend(ClassMethods)
      end
    end

    module ClassMethods
      def deprecate_alias(new_name, old_name)
        define_method(new_name) do |*args, &block|
          warn "#{Kernel.caller.first}: [DEPRECATION] ##{new_name} is deprecated. Use ##{old_name} instead."
          send(old_name, *args, &block)
        end
      end
    end
  end
end

# https://github.com/rubygems/rubygems/blob/master/lib/rubygems/deprecate.rb
##
# Provides a single method +deprecate+ to be used to declare when
# something is going away.
#
#     class Legacy
#       def self.klass_method
#         # ...
#       end
#
#       def instance_method
#         # ...
#       end
#
#       extend Gem::Deprecate
#       deprecate :instance_method, "X.z", 2011, 4
#
#       class << self
#         extend Gem::Deprecate
#         deprecate :klass_method, :none, 2011, 4
#       end
#     end

module Gem::Deprecate

  def self.skip # :nodoc:
    @skip ||= false
  end

  def self.skip= v # :nodoc:
    @skip = v
  end

  ##
  # Temporarily turn off warnings. Intended for tests only.

  def skip_during
    Gem::Deprecate.skip, original = true, Gem::Deprecate.skip
    yield
  ensure
    Gem::Deprecate.skip = original
  end

  ##
  # Simple deprecation method that deprecates +name+ by wrapping it up
  # in a dummy method. It warns on each call to the dummy method
  # telling the user of +repl+ (unless +repl+ is :none) and the
  # year/month that it is planned to go away.

  def deprecate name, repl, year, month
    class_eval {
      old = "_deprecated_#{name}"
      alias_method old, name
      define_method name do |*args, &block|
        klass = self.kind_of? Module
        target = klass ? "#{self}." : "#{self.class}#"
        msg = [ "NOTE: #{target}#{name} is deprecated",
          repl == :none ? " with no replacement" : "; use #{repl} instead",
          ". It will be removed on or after %4d-%02d-01." % [year, month],
          "\n#{target}#{name} called from #{Gem.location_of_caller.join(":")}",
        ]
        warn "#{msg.join}." unless Gem::Deprecate.skip
        send old, *args, &block
      end
    }
  end

  module_function :deprecate, :skip_during

end

# http://www.seejohncode.com/2012/01/09/deprecating-methods-in-ruby/
module Deprecated
 
  # Define a deprecated alias for a method
  # @param [Symbol] name - name of method to define
  # @param [Symbol] replacement - name of method to (alias)
  def deprecated_alias(name, replacement)
    # Create a wrapped version
    define_method(name) do |*args, &block|
      warn "IceCube: ##{name} deprecated (please use ##{replacement})"
      send replacement, *args, &block
    end
  end
 
  # Deprecate a defined method
  # @param [Symbol] name - name of deprecated method
  # @param [Symbol] replacement - name of the desired replacement
  def deprecated(name, replacement = nil)
    # Replace old method
    old_name = :"#{name}_without_deprecation"
    alias_method old_name, name
    # And replace it with a wrapped version
    define_method(name) do |*args, &block|
      if replacement
        warn "IceCube: ##{name} deprecated (please use ##{replacement})"
      else
        warn "IceCube: ##{name} deprecated"
      end
      send old_name, *args, &block
    end
  end
 
end
- [sidekiq](https://github.com/mperham/sidekiq/blob/master/lib/sidekiq/cli.rb)
# https://github.com/rails/rails/blob/70ae89c321444eef42c0c011b522f926250e7acd/activesupport/lib/active_support/core_ext/kernel/reporting.rb#L82
require 'rbconfig'
require 'tempfile'

module Kernel
  # Sets $VERBOSE to nil for the duration of the block and back to its original
  # value afterwards.
  #
  #   silence_warnings do
  #     value = noisy_call # no warning voiced
  #   end
  #
  #   noisy_call # warning voiced
  def silence_warnings
    with_warnings(nil) { yield }
  end

  # Sets $VERBOSE to +true+ for the duration of the block and back to its
  # original value afterwards.
  def enable_warnings
    with_warnings(true) { yield }
  end

  # Sets $VERBOSE for the duration of the block and back to its original
  # value afterwards.
  def with_warnings(flag)
    old_verbose, $VERBOSE = $VERBOSE, flag
    yield
  ensure
    $VERBOSE = old_verbose
  end

  # For compatibility
  def silence_stderr #:nodoc:
    silence_stream(STDERR) { yield }
  end

  # Silences any stream for the duration of the block.
  #
  #   silence_stream(STDOUT) do
  #     puts 'This will never be seen'
  #   end
  #
  #   puts 'But this will'
  def silence_stream(stream)
    old_stream = stream.dup
    stream.reopen(RbConfig::CONFIG['host_os'] =~ /mswin|mingw/ ? 'NUL:' : '/dev/null')
    stream.sync = true
    yield
  ensure
    stream.reopen(old_stream)
  end

  # Blocks and ignores any exception passed as argument if raised within the block.
  #
  #   suppress(ZeroDivisionError) do
  #     1/0
  #     puts 'This code is NOT reached'
  #   end
  #
  #   puts 'This code gets executed and nothing related to ZeroDivisionError was seen'
  def suppress(*exception_classes)
    yield
  rescue Exception => e
    raise unless exception_classes.any? { |cls| e.kind_of?(cls) }
  end

  # Captures the given stream and returns it:
  #
  #   stream = capture(:stdout) { puts 'notice' }
  #   stream # => "notice\n"
  #
  #   stream = capture(:stderr) { warn 'error' }
  #   stream # => "error\n"
  #
  # even for subprocesses:
  #
  #   stream = capture(:stdout) { system('echo notice') }
  #   stream # => "notice\n"
  #
  #   stream = capture(:stderr) { system('echo error 1>&2') }
  #   stream # => "error\n"
  def capture(stream)
    stream = stream.to_s
    captured_stream = Tempfile.new(stream)
    stream_io = eval("$#{stream}")
    origin_stream = stream_io.dup
    stream_io.reopen(captured_stream)

    yield

    stream_io.rewind
    return captured_stream.read
  ensure
    captured_stream.unlink
    stream_io.reopen(origin_stream)
  end
  alias :silence :capture

  # Silences both STDOUT and STDERR, even for subprocesses.
  #
  #   quietly { system 'bundle install' }
  def quietly
    silence_stream(STDOUT) do
      silence_stream(STDERR) do
        yield
      end
    end
  end
end

# https://github.com/rubygems/rubygems/blob/master/lib/rubygems/util.rb#L72
  ##
  # Invokes system, but silences all output.

  def self.silent_system *command
    require 'thread'

    @silent_mutex ||= Mutex.new

    null_device = Gem.win_platform? ? 'NUL' : '/dev/null'

    @silent_mutex.synchronize do
      begin
        stdout = STDOUT.dup
        stderr = STDERR.dup

        STDOUT.reopen null_device, 'w'
        STDERR.reopen null_device, 'w'

        return system(*command)
      ensure
        STDOUT.reopen stdout
        STDERR.reopen stderr
      end
    end
  end
# https://github.com/pivotal/git_scripts/blob/master/Rakefile
# and see https://github.com/gregorym/bump/blob/master/lib/bump/tasks.rb
require "bundler/gem_tasks"

task :default do
  sh "bundle exec rspec spec"
end

# extracted from https://github.com/grosser/project_template
rule /^version:bump:.*/ do |t|
  sh "git status | grep 'nothing to commit'" # ensure we are not dirty
  index = ['major', 'minor','patch'].index(t.name.split(':').last)
  file = 'lib/pivotal_git_scripts/version.rb'

  version_file = File.read(file)
  old_version, *version_parts = version_file.match(/(\d+)\.(\d+)\.(\d+)/).to_a
  version_parts[index] = version_parts[index].to_i + 1
  version_parts[2] = 0 if index < 2 # remove patch for minor
  version_parts[1] = 0 if index < 1 # remove minor for major
  new_version = version_parts * '.'
  File.open(file,'w'){|f| f.write(version_file.sub(old_version, new_version)) }

  sh "bundle && git add #{file} Gemfile.lock && git commit -m 'bump version to #{new_version}'"
end
diff --git a/Gemfile b/Gemfile
index 22bde6e..a429815 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,5 +1,15 @@
 source 'https://rubygems.org'
 
+require 'rubygems'
+def Gem.source_index
+  STDERR.puts "Guess who wants Gem.source_index? #{caller[0]}"
+  # see https://github.com/slimgems/slimgems/blob/master/lib/rubygems/source_index.rb#L124
+  Gem.const_set(:SourceIndex, Class.new  do
+    def initialize(specifications={})
+      p ["Source index", specifications]
+    end
+  end)
+end unless Gem.respond_to?(:source_index)
require 'active_record'
require 'database_cleaner'

connection_info = YAML.load_file("config/database.yml")["test"]
ActiveRecord::Base.establish_connection(connection_info)

RSpec.configure do |config|
  config.before(:suite) do
    DatabaseCleaner.strategy = :transaction
    DatabaseCleaner.clean_with(:truncation)
  end
  config.before(:each) do
    DatabaseCleaner.start
  end
  config.after(:each) do
    DatabaseCleaner.clean
  end

  config.mock_with :rspec do |c|
    c.yield_receiver_to_any_instance_implementation_blocks = true
  end
end
# encoding: utf-8
# from devtools
# and see https://github.com/rom-rb/devtools/tree/master/tasks
guard :bundler do
  watch('Gemfile')
  watch('Gemfile.lock')
  watch(%w{.+.gemspec\z})
end

guard :rspec, cli: File.read('.rspec').split.push('--fail-fast').join(' '), keep_failed: false do
  # Run all specs if configuration is modified
  watch('.rspec')              { 'spec' }
  watch('Guardfile')           { 'spec' }
  watch('Gemfile.lock')        { 'spec' }
  watch('spec/spec_helper.rb') { 'spec' }

  # Run all specs if supporting files are modified
  watch(%r{\Aspec/(?:fixtures|lib|support|shared)/.+\.rb\z}) { 'spec' }

  # Run unit specs if associated lib code is modified
  watch(%r{\Alib/(.+)\.rb\z})                                         { |m| Dir["spec/unit/#{m[1]}*"]         }
  watch(%r{\Alib/(.+)/support/(.+)\.rb\z})                            { |m| Dir["spec/unit/#{m[1]}/#{m[2]}*"] }
  watch("lib/#{File.basename(File.expand_path('../', __FILE__))}.rb") { 'spec'                                }

  # Run a spec if it is modified
  watch(%r{\Aspec/(?:unit|integration)/.+_spec\.rb\z})
end

guard :rubocop, cli: %w[--config config/rubocop.yml] do
  watch(%r{.+\.(?:rb|rake)\z})
  watch(%r{\Aconfig/rubocop\.yml\z})  { |m| File.dirname(m[0]) }
  watch(%r{(?:.+/)?\.rubocop\.yml\z}) { |m| File.dirname(m[0]) }
end
# https://github.com/heroku/rails_stdout_logging/blob/master/lib/rails_stdout_logging/rails.rb
module RailsStdoutLogging
  class Rails
    def self.heroku_stdout_logger
      logger       = Logger.new(STDOUT)
      logger       = ActiveSupport::TaggedLogging.new(logger) if defined?(ActiveSupport::TaggedLogging)
      logger.level = Logger.const_get(log_level)
      logger
    end

    def self.log_level
      ([(ENV['LOG_LEVEL'] || ::Rails.application.config.log_level).to_s.upcase, "INFO"] & %w[DEBUG INFO WARN ERROR FATAL UNKNOWN]).compact.first
    end

    def self.set_logger
      STDOUT.sync = true
    end
  end
end
module RailsStdoutLogging
  class Rails3 < Rails
    def self.set_logger(config)
      super()
      ::Rails.logger = config.logger = heroku_stdout_logger
    end
  end
end
module RailsStdoutLogging
  class Railtie < ::Rails::Railtie
    config.before_initialize do
      Rails3.set_logger(config)
    end
  end
end
# https://github.com/heroku/rails_serve_static_assets/blob/master/lib/rails_serve_static_assets/railtie.rb
module RailsServeStaticAssets
  class Railtie < Rails::Railtie
    config.before_initialize do
      ::Rails.configuration.serve_static_assets = true
      ::Rails.configuration.action_dispatch.x_sendfile_header = nil
    end
  end
end

以上是关于ruby 我感兴趣的库中的代码片段的主要内容,如果未能解决你的问题,请参考以下文章

如何遍历 Spotipy 的 playlist_items 函数中的嵌套列表并仅打印出我感兴趣的字段?

使用 Ruby / Nokogiri 解析随机类名

如何在 Ruby 中解析 pdf

Visual Studio 2013 - 如何在我自己的库中链接/包含其他库

使用标准库Ruby将数据标记到Elasticsearch批量中

C: 为啥我的库中的全局变量不会更新? (使用 ALSA 库)