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 函数中的嵌套列表并仅打印出我感兴趣的字段?
Visual Studio 2013 - 如何在我自己的库中链接/包含其他库