gogo 1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE +13 -0
- data/README.md +76 -0
- data/Rakefile +2 -0
- data/bin/gogo +97 -0
- data/gogo.gemspec +17 -0
- data/lib/gogo.rb +1 -0
- data/lib/gogo/gofile_templates/rails.rb +90 -0
- data/lib/gogo/version.rb +3 -0
- metadata +58 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Originally authored 2012 Brian Hempel
|
2
|
+
|
3
|
+
Public domain; no restrictions.
|
4
|
+
|
5
|
+
While the software is provided without copyright, the following clause from the MIT License applies:
|
6
|
+
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
8
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
9
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
10
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE
|
11
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
12
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
13
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
# GoGo
|
2
|
+
|
3
|
+
Yaknow how you're waiting for waiting for Rails to start and other people overhear you say "Go Go Go Go!" to your computer?
|
4
|
+
|
5
|
+
Install the gem:
|
6
|
+
|
7
|
+
gem install gogo
|
8
|
+
|
9
|
+
Make sure you're in your Rails project and then run:
|
10
|
+
|
11
|
+
$ gogo
|
12
|
+
|
13
|
+
That will launch you into a pseudo-shell with the Rails test environment reloaded. If you want to use gogo for development commands such as `rake db:seed`, `rake db:migrate`, or `rails console`, launch a separate shell and run:
|
14
|
+
|
15
|
+
$ gogo d
|
16
|
+
|
17
|
+
Now, run some commands. Ruby scripts that load Rails should start astronomically faster.
|
18
|
+
|
19
|
+
## Sounds fishy...
|
20
|
+
|
21
|
+
It is fishy. GoGo is a hack script.
|
22
|
+
|
23
|
+
I'm sharing it with the world because it's an incredibly useful hack, but I can't guarantee any level of maintenance on my part. If stuff breaks, you're on your own to fix it. Leave your experience in the [wiki](https://github.com/brianhempel/gogo/wiki) to help others.
|
24
|
+
|
25
|
+
GoGo is a lot like Spork. GoGo preloads your rails environment. When you run a ruby command, the gogo process is forked and the command is loaded into that environment. Here's a performance comparison for a large project:
|
26
|
+
|
27
|
+
$ time bundle exec cucumber features/admin/dashboard.feature:0
|
28
|
+
real 0m30.457s
|
29
|
+
user 0m27.300s
|
30
|
+
sys 0m2.941s
|
31
|
+
|
32
|
+
$ gogo
|
33
|
+
Creating default Gofile for Rails...
|
34
|
+
Loading application.rb...and environment.rb...and cucumber...and cucumber/rails...and webmock/cucumber...and ruby-debug...and factory_girl/step_definitions...and email_spec...and email_spec/cucumber...and capybara/firebug...and vcr...and rake...took 26.25 seconds.
|
35
|
+
test $ cucumber features/admin/dashboard.feature:0
|
36
|
+
cucumber took 3.65 seconds.
|
37
|
+
test $ cucumber features/admin/dashboard.feature:0
|
38
|
+
cucumber took 3.58 seconds.
|
39
|
+
|
40
|
+
The advantages over Spork are:
|
41
|
+
|
42
|
+
1. No DRB weirdness
|
43
|
+
2. Easy install -- little to no modification to test environment.
|
44
|
+
3. Speeds up other rails commands: rake routes, rails g migration, rake db:seed
|
45
|
+
4. Single tab, so you know when code reloads are complete.
|
46
|
+
|
47
|
+
General disadvantages:
|
48
|
+
|
49
|
+
1. It's not a full shell. No aliases or boolean logic || && for commands.
|
50
|
+
2. You're already in a bundled environment, so rake db:seed is going to apply to the test environment. You probably don't want that.
|
51
|
+
3. Have to ctrl-D and reload after Gemfile changes.
|
52
|
+
4. Uses some Mac OS X only features, but if you want to hack those out it shouldn't be too hard.
|
53
|
+
|
54
|
+
One advantage over even the shell is a per-project and per-environment command history.
|
55
|
+
|
56
|
+
## Contributing
|
57
|
+
|
58
|
+
To fix a problem or add a feature, use the standard pull request workflow:
|
59
|
+
|
60
|
+
# fork it on github, then clone:
|
61
|
+
git clone git@github.com:YOUR_USERNAME/gogo.git
|
62
|
+
# hack away
|
63
|
+
git push
|
64
|
+
# then make a pull request
|
65
|
+
|
66
|
+
Once you get a pull request accepted, I'll add you so you can commit directly to the repository.
|
67
|
+
|
68
|
+
git clone git@github.com:brianhempel/gogo.git
|
69
|
+
# hack away
|
70
|
+
git push
|
71
|
+
|
72
|
+
## License
|
73
|
+
|
74
|
+
Public domain; no restrictions.
|
75
|
+
|
76
|
+
And certainly: no warrantee of fitness for any purpose. It's a hack. Use at your own risk.
|
data/Rakefile
ADDED
data/bin/gogo
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'benchmark'
|
4
|
+
require 'fileutils'
|
5
|
+
require 'readline'
|
6
|
+
|
7
|
+
module GoGo
|
8
|
+
def self.preload(&block)
|
9
|
+
@preload = block if block_given?
|
10
|
+
@preload || Proc.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.command_filter(&block)
|
14
|
+
@command_filter = block if block_given?
|
15
|
+
@command_filter || Proc.new
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.before_each_ruby_command(&block)
|
19
|
+
@before_each_ruby_command = block if block_given?
|
20
|
+
@before_each_ruby_command || Proc.new
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
unless File.exists?("Gofile")
|
25
|
+
puts "Creating default Gofile for Rails..."
|
26
|
+
default_template_path = File.expand_path('../../lib/gogo/gofile_templates/rails.rb', __FILE__)
|
27
|
+
FileUtils.cp(default_template_path, "Gofile")
|
28
|
+
end
|
29
|
+
load("Gofile")
|
30
|
+
|
31
|
+
GoGo.preload.call
|
32
|
+
|
33
|
+
Readline.completion_proc = Proc.new do |str|
|
34
|
+
Readline.completion_append_character = "" # space doesn't work on OS X :(
|
35
|
+
command_candidates = AUTOCOMPLETE_COMMANDS.grep(/^#{Regexp.escape(str)}/)
|
36
|
+
file_candidates = Dir[str+'*'].grep(/^#{Regexp.escape(str)}/)
|
37
|
+
file_candidates.map! do |path|
|
38
|
+
# add a space unless a directory
|
39
|
+
File.directory?(path) ? path : path + ' '
|
40
|
+
end
|
41
|
+
rake_task_candidates = RAKE_COMMANDS.grep(/^#{Regexp.escape(str)}/)
|
42
|
+
command_candidates + file_candidates + rake_task_candidates
|
43
|
+
end
|
44
|
+
|
45
|
+
ENV['GOGO_ENV'] ||= 'development'
|
46
|
+
history_file_path = ".gogo_history-#{ENV['GOGO_ENV']}"
|
47
|
+
|
48
|
+
# load old history
|
49
|
+
if File.exists?(history_file_path)
|
50
|
+
Readline::HISTORY.clear
|
51
|
+
File.read(history_file_path).lines.each { |l| Readline::HISTORY << l.chomp }
|
52
|
+
end
|
53
|
+
|
54
|
+
while line = Readline.readline("\033[1;32m#{Dir.pwd.sub(/.*\//, '')} \033[0;35m#{ENV['GOGO_ENV']} \033[0;34m$ \033[0m", true)
|
55
|
+
if line.blank?
|
56
|
+
Readline::HISTORY.pop # don't store blank commands in history
|
57
|
+
next
|
58
|
+
end
|
59
|
+
given_command, *arguments = line.split
|
60
|
+
|
61
|
+
command = GoGo.command_filter.call(given_command)
|
62
|
+
|
63
|
+
unless given_command == 'eval'
|
64
|
+
command = `which #{command}`.chomp
|
65
|
+
|
66
|
+
if command.size == 0
|
67
|
+
STDERR.puts "#{given_command}: command not found"
|
68
|
+
next
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
command_pid = fork do
|
73
|
+
File.open(history_file_path, "a") { |f| f.puts(line) }
|
74
|
+
|
75
|
+
if given_command == "eval"
|
76
|
+
p eval(line.sub(/^eval\s+/, ''))
|
77
|
+
elsif `file #{command}` =~ /: a .*ruby.* script text executable/
|
78
|
+
|
79
|
+
GoGo.before_each_ruby_command.call(given_command, arguments)
|
80
|
+
|
81
|
+
silence_warnings { ARGV = arguments }
|
82
|
+
load(command)
|
83
|
+
else
|
84
|
+
exec line
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# send cntl-c to the child
|
89
|
+
trap("INT") { Process.kill("INT", command_pid) }
|
90
|
+
|
91
|
+
command_time = Benchmark.realtime { Process.wait(command_pid) }
|
92
|
+
puts "#{line.size < 15 ? line : given_command} took %.2f seconds." % command_time if command_time > 0.4
|
93
|
+
|
94
|
+
trap("INT", "DEFAULT")
|
95
|
+
end
|
96
|
+
|
97
|
+
puts
|
data/gogo.gemspec
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/gogo/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Brian Hempel"]
|
6
|
+
gem.email = ["plastichicken@gmail.com"]
|
7
|
+
gem.description = "Pseudo-shell hack with Rails environment preloaded for faster boot times and thus faster testing iterations. Go go go go go!"
|
8
|
+
gem.summary = gem.description
|
9
|
+
gem.homepage = "https://github.com/brianhempel/gogo"
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "gogo"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = GoGo::VERSION
|
17
|
+
end
|
data/lib/gogo.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "gogo/version"
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# autocomplete commands
|
2
|
+
# thanks to http://bogojoker.com/readline/
|
3
|
+
# and to https://github.com/ruby/ruby/blob/trunk/ext/readline/readline.c
|
4
|
+
AUTOCOMPLETE_COMMANDS = ['rake ', 'cucumber features/', 'rails ', 'rspec spec/'].sort
|
5
|
+
RAKE_COMMANDS = ['db', 'db:migrate', 'db:test:prepare', 'db:rollback', 'routes', 'sunspot:reindex', 'sunspot:solr:start', 'sunspot:solr:start', 'sunspot:solr:stop', 'assets:clean', 'assets:precompile']
|
6
|
+
|
7
|
+
GoGo.preload do
|
8
|
+
if ARGV[0]
|
9
|
+
ENV['RAILS_ENV'] = %w{development test production staging}.find { |e| e[0] == ARGV[0][0] } || ARGV[0]
|
10
|
+
else
|
11
|
+
ENV['RAILS_ENV'] = ENV['GOGO_ENV'] || 'test'
|
12
|
+
end
|
13
|
+
# need GOGO_ENV for the history file
|
14
|
+
ENV['GOGO_ENV'] = ENV['RAILS_ENV']
|
15
|
+
|
16
|
+
load_time = Benchmark.realtime do
|
17
|
+
print "Loading application.rb..."
|
18
|
+
require File.expand_path('./config/application', Dir.pwd)
|
19
|
+
|
20
|
+
# we'll use class reloading
|
21
|
+
# thanks to spork for lots of direction here
|
22
|
+
# https://github.com/sporkrb/spork-rails/blob/master/lib/spork/app_framework/rails.rb
|
23
|
+
# https://github.com/sporkrb/spork-rails/blob/master/lib/spork/ext/rails-reloader.rb
|
24
|
+
Rails::Engine.class_eval do
|
25
|
+
def eager_load!
|
26
|
+
railties.all(&:eager_load!) if defined?(railties)
|
27
|
+
# but don't eager load the eager_load_paths
|
28
|
+
end
|
29
|
+
end
|
30
|
+
print "and environment.rb..."
|
31
|
+
require File.expand_path('./config/environment', Dir.pwd)
|
32
|
+
ActiveSupport::Dependencies.mechanism = :load
|
33
|
+
|
34
|
+
if Rails.env.test?
|
35
|
+
print "and cucumber..."
|
36
|
+
require 'rspec'
|
37
|
+
begin
|
38
|
+
require 'cucumber' # saves 0.4 seconds when running cucumber
|
39
|
+
|
40
|
+
# load everything that appears in test env.rb
|
41
|
+
# this shaves off another 2 seconds
|
42
|
+
# even though most of the loads technically fail
|
43
|
+
ENV['RAILS_ROOT'] = Dir.pwd
|
44
|
+
other_paths = File.read(Dir.pwd + "/features/support/env.rb").scan(/^require ['"](.+?)['"](?!.*gogo: skip)/).flatten
|
45
|
+
other_paths.each do |path|
|
46
|
+
print "and #{path}..."
|
47
|
+
begin
|
48
|
+
# load in annoymous modules so, basically, we're just cache-warming
|
49
|
+
load(path + '.rb', true)
|
50
|
+
rescue
|
51
|
+
end
|
52
|
+
end
|
53
|
+
rescue LoadError
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
print "and rake..."
|
58
|
+
require 'rake'
|
59
|
+
end
|
60
|
+
|
61
|
+
puts "took %.2f seconds." % load_time
|
62
|
+
end
|
63
|
+
|
64
|
+
GoGo.command_filter do |given_command|
|
65
|
+
# running just "rails" does an exec which reloads everything and defeats the point of preloading
|
66
|
+
given_command == 'rails' ? './script/rails' : given_command
|
67
|
+
end
|
68
|
+
|
69
|
+
GoGo.before_each_ruby_command do |given_command, arguments|
|
70
|
+
if given_command =~ /^(cucumber|rspec)$/ && ENV['RAILS_ENV'] != 'test'
|
71
|
+
STDERR.puts "Don't run your tests when not in the test environment!"
|
72
|
+
exit 1
|
73
|
+
end
|
74
|
+
|
75
|
+
# reload classes
|
76
|
+
if defined?(ActionDispatch::Reloader)
|
77
|
+
# Rails 3.1
|
78
|
+
ActionDispatch::Reloader.cleanup!
|
79
|
+
ActionDispatch::Reloader.prepare!
|
80
|
+
else
|
81
|
+
# Rails 3.0
|
82
|
+
# pulled from Railties source, this triggers something
|
83
|
+
ActionDispatch::Callbacks.new(Proc.new {}, false).call({})
|
84
|
+
# ActiveSupport::DescendantsTracker.clear
|
85
|
+
# ActiveSupport::Dependencies.clear
|
86
|
+
|
87
|
+
# fix problem with ::Something::OtherThing resolving to ::OtherThing
|
88
|
+
Rails.application.config.eager_load_paths.map { |p| Dir[p + '/**/*.rb'] }.flatten.each { |rb| require_dependency rb }
|
89
|
+
end
|
90
|
+
end
|
data/lib/gogo/version.rb
ADDED
metadata
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gogo
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '1'
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Brian Hempel
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-05-01 00:00:00.000000000Z
|
13
|
+
dependencies: []
|
14
|
+
description: Pseudo-shell hack with Rails environment preloaded for faster boot times
|
15
|
+
and thus faster testing iterations. Go go go go go!
|
16
|
+
email:
|
17
|
+
- plastichicken@gmail.com
|
18
|
+
executables:
|
19
|
+
- gogo
|
20
|
+
extensions: []
|
21
|
+
extra_rdoc_files: []
|
22
|
+
files:
|
23
|
+
- .gitignore
|
24
|
+
- Gemfile
|
25
|
+
- LICENSE
|
26
|
+
- README.md
|
27
|
+
- Rakefile
|
28
|
+
- bin/gogo
|
29
|
+
- gogo.gemspec
|
30
|
+
- lib/gogo.rb
|
31
|
+
- lib/gogo/gofile_templates/rails.rb
|
32
|
+
- lib/gogo/version.rb
|
33
|
+
homepage: https://github.com/brianhempel/gogo
|
34
|
+
licenses: []
|
35
|
+
post_install_message:
|
36
|
+
rdoc_options: []
|
37
|
+
require_paths:
|
38
|
+
- lib
|
39
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ! '>='
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '0'
|
45
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
46
|
+
none: false
|
47
|
+
requirements:
|
48
|
+
- - ! '>='
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: '0'
|
51
|
+
requirements: []
|
52
|
+
rubyforge_project:
|
53
|
+
rubygems_version: 1.8.17
|
54
|
+
signing_key:
|
55
|
+
specification_version: 3
|
56
|
+
summary: Pseudo-shell hack with Rails environment preloaded for faster boot times
|
57
|
+
and thus faster testing iterations. Go go go go go!
|
58
|
+
test_files: []
|