Skip to content

Instantly share code, notes, and snippets.

@bill-transue
Created November 29, 2012 18:32
Show Gist options
  • Select an option

  • Save bill-transue/4170980 to your computer and use it in GitHub Desktop.

Select an option

Save bill-transue/4170980 to your computer and use it in GitHub Desktop.
# Load plugins (only those I whitelist)
Pry.config.should_load_plugins = false
Pry.plugins["doc"].activate!
# Launch Pry with access to the entire Rails stack.
# If you have Pry in your Gemfile, you can pass: ./script/console --irb=pry instead.
# If you don't, you can load it through the lines below :)
rails = File.join Dir.getwd, 'config', 'environment.rb'
if File.exist?(rails) && ENV['SKIP_RAILS'].nil?
require rails
if Rails.version[0..0] == "2"
require 'console_app'
require 'console_with_helpers'
elsif Rails.version[0..0] == "3"
require 'rails/console/app'
require 'rails/console/helpers'
else
warn "[WARN] cannot load Rails console commands (Not on Rails2 or Rails3?)"
end
end
require '~/.irb/irb/awesome_print_loader'
require '~/.irb/irb/bypass_reloader'
require '~/.irb/irb/env'
require '~/.irb/irb/rspec'
require '~/.irb/irb/cucumber'
require '~/.irb/irb/plot'
module IRB::Env::ActiveRecord
def self.switch_env(old_env, env)
::ActiveRecord::Base.clear_cache! if ::ActiveRecord::Base.respond_to? :clear_cache
::ActiveRecord::Base.clear_all_connections!
::ActiveRecord::Base.establish_connection
end
IRB::Env.add_handler(self) if defined?(::ActiveRecord::Base)
end
module IRB
module AwesomePrintLoader
def self.setup
return unless IRB.try_require 'awesome_print'
::Pry.config.print = proc do |output, value|
::Pry::Helpers::BaseHelpers.stagger_output("=> #{value.ai}", output)
end
end
end
end
IRB::AwesomePrintLoader.setup
module IRB::Env::Bundler
def self.switch_env(old_env, env)
Bundler.require(env)
end
IRB::Env.add_handler(self) if defined?(::Bundler)
end
module IRB
module BypassReloader
def self.setup
ActionDispatch::Reloader.class_eval do
def call(env)
@app.call(env)
end
end
if defined?(RailsDevTweaks::GranularAutoload::Middleware)
RailsDevTweaks::GranularAutoload::Middleware.class_eval do
def call(env)
@app.call(env)
end
end
end
end
end
end
IRB::BypassReloader.setup if defined?(Rails)
module IRB
module CodeRayTerm
def self.setup
return unless IRB.try_require 'coderay'
CodeRay.scan('', :ruby).term
colors = CodeRay::Encoders::Term::TOKEN_COLORS
colors[:string][:self] = '36'
colors[:string][:modifier] = colors[:string][:delimiter] = '1;36'
colors[:symbol] = '1;33'
end
end
end
IRB::CodeRayTerm.setup
module IRB::Env::CopycopterClient
def self.switch_env(old_env, env)
::CopycopterClient::Rails.initialize
end
def self.setup
conf = ::CopycopterClient.configuration
def conf.environment_name
::Rails.env
end
::CopycopterClient::RequestSync.class_eval do
def call(env)
@app.call(env)
end
end
end
IRB::Env.add_handler(self) if defined?(::CopycopterClient::Rails)
setup if defined?(::CopycopterClient) && defined?(::Rails)
end
module IRB
module Cucumber
def self.reset(args)
require 'cucumber'
require 'cucumber/rspec/disable_option_parser'
require 'optparse'
require 'cucumber'
require 'logger'
require 'cucumber/parser'
require 'cucumber/feature_file'
require 'cucumber/cli/configuration'
# If we are using RSpec, make sure we load it before, because some step
# definitions may contain some rspec wizardry.
IRB::RSpec.reset if defined?(::RSpec)
config = ::Cucumber::Cli::Configuration.new
config.parse!(args)
::Cucumber.logger = config.log
if @runtime
def config.support_to_load
begin
load 'factory_girl/step_definitions.rb' if defined?(FactoryGirl)
rescue LoadError
end
[]
end
@runtime.configure(config)
else
@runtime = ::Cucumber::Runtime.new(config)
end
@runtime.instance_eval do
@loader = nil
@results = ::Cucumber::Runtime::Results.new(config)
@support_code.instance_eval do
@programming_languages.map do |programming_language|
programming_language.step_definitions.clear
end
end
end
end
def self.run(args)
IRB::Env::Reloader.need_reload
IRB::Env.with_env('test') do
self.reset(args)
@runtime.run!
@runtime.write_stepdefs_json
@runtime.results.failure?
end
end
def self.setup
::Pry::CommandSet.new do
create_command "cucumber", "Works pretty much like the regular cucumber command" do
group "Testing"
def process(*args)
IRB::Cucumber.run(args)
end
end
end.tap { |cmd| ::Pry::Commands.import cmd }
end
end
end
IRB::Cucumber.setup
module IRB
module Env
@@env = defined?(::Rails) ? ::Rails.env : "development"
def self.with_env(env)
return yield if @@env == env
old_env = @@env
# Not using ActiveSupport callbacks because the order matters.
@@handlers.reverse.reduce(proc { yield }) do |chain, handler|
proc do
handler.switch_env(old_env, env)
begin
chain.call
ensure
handler.switch_env(env, old_env)
end
end
end.call
end
def self.switch_env(old_env, env)
@@env = env
end
@@handlers = []
def self.add_handler(handler)
@@handlers << handler
end
def self.setup(*handlers)
::Pry::CommandSet.new do
create_command "env", "Switch environment. ctrl+d to leave" do
group "Environment"
def process(env)
IRB::Env.with_env(env) do
TopLevel.new.pry
end
end
end
end.tap { |cmd| ::Pry::Commands.import cmd }
end
# The order matters: handlers are executed top to bottom when switching env
load '~/.irb/irb/env/bundler.rb'
load '~/.irb/irb/env/reloader.rb'
load '~/.irb/irb/env/rails.rb'
load '~/.irb/irb/env/active_record.rb'
load '~/.irb/irb/env/mongoid.rb'
load '~/.irb/irb/env/copycopter_client.rb'
load '~/.irb/irb/env/rails.rb'
load '~/.irb/irb/env/reloader.rb'
IRB::Env.add_handler(self)
Env.setup if @@handlers.size > 1
end
end
module IRB
module GemLoader
def self.setup
# We make everything in the global gemset available, bypassing Bundler
global_gemset = ENV['GEM_PATH'].split(':').grep(/ruby.*@global/).first
Dir["#{global_gemset}/gems/*"].each { |p| $LOAD_PATH << "#{p}/lib" } if global_gemset
end
end
def self.try_require(file)
begin
require file
true
rescue LoadError => e
warn "=> Unable to load #{file}"
false
end
end
end
IRB::GemLoader.setup if defined?(Bundler)
module IRB::Env::Mongoid
def self.switch_env(old_env, env)
reconnect
end
def self.reconnect
old_level = Mongoid.logger.level
Mongoid.logger.level = Logger::WARN
Mongoid.load!("./config/mongoid.yml")
Mongoid.logger.level = old_level
IRB::Env::Reloader.need_reload # finalizes the mongodb database switch
end
IRB::Env.add_handler(self) if defined?(::Mongoid)
end
# encoding: utf-8
module IRB
module MongoidLogger
# Mongoid pretty prints its command, colorized with coderay
def self.setup
Mongoid.logger = Rails.logger if defined?(Rails)
return unless IRB.try_require 'coderay'
require '~/.irb/irb/coderay_term'
old_formatter = Mongoid.logger.formatter
Mongoid.logger.formatter = proc do |severity, datetime, progname, msg|
m = parse(msg)
if m.nil?
unless msg =~ /which could negatively impact client-side performance/
old_formatter.call(severity, datetime, progname, msg)
end
else
m[:query].gsub!(/BSON::ObjectId\('([^']+)'\)/, '0x\1')
m[:duration] = m[:duration].split('.')[0] if m[:duration]
line = "\033[1;32m☘ \033[1;37mMongoDB\033[0m "
line << "(#{m[:duration]}ms) " if m[:duration]
if m[:database]
if m[:collection]
line << colorize("[#{m[:database]}::#{m[:collection]}] ")
else
line << colorize("[#{m[:database]}] ")
end
end
line << "#{colorize(m[:operation])} " if m[:operation]
line << colorize(m[:query])
line << "\n"
end
end
end
def self.colorize(msg)
CodeRay.scan(msg, :ruby).term
end
def self.parse(msg)
case msg
when /^MONGODB \((.*)ms\) (.*)\['(.*)'\]\.(.*)$/
{:duration => $1, :database => $2, :collection => $3, :query => $4}
when /^MONGODB (.*)\['(.*)'\]\.(.*)$/
{:database => $1, :collection => $2, :query => $3}
when /^ *MOPED: (\S+:\S+) (\S+) +database=(\S+) collection=(\S+) (.*) \((.*)ms\)/
{:host => $1, :operation => $2, :database => $3, :collection => $4, :query => $5, :duration => $6}
when /^ *MOPED: (\S+:\S+) (\S+) +database=(\S+) (.*) \((.*)ms\)/
{:host => $1, :operation => $2, :database => $3, :query => $4, :duration => $5}
end
end
end
end
IRB::MongoidLogger.setup if defined?(Mongoid)
module IRB
module Plot
class << self; attr_accessor :fork; end
def self.plot(array)
array = array.to_a if array.is_a?(Hash)
array = array.transpose
Gnuplot.open do |gp|
Gnuplot::Plot.new(gp) do |plot|
plot.data << Gnuplot::DataSet.new(array) do |ds|
ds.with = "linespoints"
ds.notitle
end
end
end
true
end
def self.setup_fork
Gnuplot.module_eval do
class << self
alias_method :open_no_fork, :open
def open(persist=true, &block)
begin
# cleanup the previous zombies
Process.wait(-1, Process::WNOHANG)
rescue
end
_open = proc { open_no_fork(persist, &block) }
IRB::Plot.fork ? fork { _open.call } : _open.call
end
end
end
end
def self.setup
return unless IRB.try_require 'gnuplot'
IRB::Plot.setup_fork
::Pry::CommandSet.new do
create_command "plot", "gnuplot an array of 2D points" do
group "Math"
def options(opt)
opt.on :f, "no-fork", "Do not fork gnuplot"
end
def process
cmd = eval(args.join(' '))
cmd = eval(cmd) if cmd.is_a?(String)
IRB::Plot.fork = !opts.present?(:'no-fork')
IRB::Plot.plot(cmd)
end
end
end.tap { |cmd| ::Pry::Commands.import cmd }
end
end
end
IRB::Plot.setup
module IRB
module Pry
def self.setup
return unless IRB.try_require 'pry'
load_pry_plugins
::Pry.prompt = [proc { |obj, nest_level| "#{self.pwd} (#{obj}) > " },
proc { |obj, nest_level| "#{self.pwd} (#{obj}) * " }]
@@home = Dir.home
TopLevel.new.pry
exit
end
def self.load_pry_plugins
IRB.try_require 'pry-doc'
IRB.try_require 'pry-rails' if defined?(Rails)
IRB.try_require 'pry-debugger'
IRB.try_require 'pry-stack_explorer'
end
def self.pwd
Dir.pwd.gsub(/^#{@@home}/, '~')
end
end
class TopLevel
def to_s
defined?(Rails) ? Rails.env : "main"
end
Object.__send__(:include, Rails::ConsoleMethods) if defined?(Rails::ConsoleMethods)
end
end
IRB::Pry.setup
module IRB::Env::Rails
def self.switch_env(old_env, env)
if ::Rails.env != env
ENV['RAILS_ENV'] = env
::Rails.env = env
Dir[Rails.root.join('config', 'initializers', '*.rb')].map do |file|
load file
end
load "./config/environments/#{env}.rb"
end
end
IRB::Env.add_handler(self) if defined?(::Rails)
end
module IRB
module RailsLogger
# Purple messages for Rails logger
def self.setup
require 'logger'
Rails.logger = Logger.new(STDOUT)
Rails.logger.formatter = proc do |severity, datetime, progname, msg|
"\033[35m#{msg}\033[0m\n"
end
end
end
end
IRB::RailsLogger.setup if defined?(Rails)
module IRB::Env::Reloader
def self.switch_env(old_env, env)
if @@need_reload
reload!(false) if respond_to?(:reload!)
FactoryGirl.reload if defined?(FactoryGirl)
end
@@need_reload = false
end
@@need_reload = false
def self.need_reload
@@need_reload = true
end
IRB::Env.add_handler(self)
end
module IRB
module RSpec
def self.reset
require 'rspec'
require '~/.irb/irb/rspec_config_cache'
if Gem.loaded_specs['rspec'].version < Gem::Version.new('2.9.10')
raise 'Please use RSpec 2.9.10 or later'
end
::RSpec::Core::Runner.disable_autorun!
::RSpec::Core::Configuration.class_eval { define_method(:command) { 'rspec' } }
::RSpec.reset
self.config_cache.cache do
::RSpec.configure do |config|
if defined?(Mongoid)
config.before do
@logger_level = ::Mongoid.logger.level
::Mongoid.logger.level = Logger::WARN
end
end
config.output_stream = STDOUT
config.color_enabled = true
end
require "./spec/spec_helper"
::RSpec.configure do |config|
if defined?(Mongoid)
config.before do
::Mongoid.logger.level = @logger_level
end
end
end
end
end
def self.config_cache
@config_cache ||= RSpecConfigCache.new
end
def self.run(args)
IRB::Env::Reloader.need_reload
IRB::Env.with_env('test') do
self.reset
::RSpec::Core::CommandLine.new(args).run(STDERR, STDOUT)
end
end
def self.setup
::Pry::CommandSet.new do
create_command "rspec", "Works pretty much like the regular rspec command" do
group "Testing"
def process(*args)
IRB::RSpec.run(args)
end
end
end.tap { |cmd| ::Pry::Commands.import cmd }
end
end
end
IRB::RSpec.setup
module IRB
#
# We have to reset the RSpec.configuration, because it contains a lot of
# information related to the current test (what's running, what are the
# different test results, etc).
#
# RSpec.configuration gets also loaded with a bunch of stuff from the
# 'spec/spec_helper.rb' file. Often that instance is extended with other
# modules (FactoryGirl, Mocha,...) and we don't want to replace requires with
# load all around the place.
#
# Instead, we cache whatever is done to RSpec.configuration during the
# first invokration of require('spec_helper').
# This is done by interposing the Proxy class on top of RSpec.configuration.
#
class RSpecConfigCache
def initialize
::RSpec.instance_eval do
def self.configuration=(value)
@configuration = value
end
end
end
def cache
if @proxy
# replay
::RSpec.configure do |config|
@recorded_config.each do |msg|
config.send(msg[:method], *msg[:args], &msg[:block])
end
end
::RSpec.world.shared_example_groups.merge!(@shared_examples_groups)
else
# record
real_config = ::RSpec.configuration
@proxy = Proxy.new(@recorded_config = [], real_config)
::RSpec.configuration = @proxy
yield
::RSpec.configuration = real_config
@shared_examples_groups = ::RSpec.world.shared_example_groups.dup
# rspec-rails/lib/rspec/rails/view_rendering.rb add methods on the
# configuration singleton. Need advice to copy them without going down
# the road with object2module.
end
# Well, instead of copying them, we redirect them to the configuration
# proxy. Looks like it good enough.
proxy = @proxy
::RSpec.configuration.define_singleton_method(:method_missing) do |method, *args, &block|
proxy.send(method, *args, &block)
end
end
end
class Proxy
def initialize(output, target)
@output = output
@target = target
end
def method_missing(method, *args, &block)
@output << {:method => method, :args => args, :block => block}
@target.send(method, *args, &block)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment