gogo 1
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|