spin 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (2) hide show
  1. data/bin/spin +120 -0
  2. metadata +71 -0
data/bin/spin ADDED
@@ -0,0 +1,120 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Spin will speed up your autotest(ish) workflow for Rails.
4
+
5
+ # Spin preloads your Rails environment for testing, so you don't load the same code over and over and over... Spin works best with an autotest(ish) workflow.
6
+
7
+ require 'socket'
8
+ # This brings in `Dir.tmpdir`
9
+ require 'tempfile'
10
+ # This lets us hash the parameters we want to include in the filename
11
+ # without having to worry about subdirectories, special chars, etc.
12
+ require 'digest/md5'
13
+ # So we can tell users how much time they're saving by preloading their
14
+ # environment.
15
+ require 'benchmark'
16
+
17
+ def usage(stream = $stderr)
18
+ stream.puts <<-USAGE
19
+ Usage: spin serve
20
+ spin push <file>...
21
+ Spin preloads your Rails environment to speed up your autotest(ish) workflow.
22
+ USAGE
23
+
24
+ exit 1
25
+ end
26
+
27
+ def socket_file
28
+ key = Digest::MD5.hexdigest [Dir.pwd, 'spin-gem'].join
29
+ [Dir.tmpdir, key].join('-')
30
+ end
31
+
32
+ def require_relative?
33
+ @require_relative ||= respond_to?(:require_relative)
34
+ end
35
+
36
+ # ## spin serve
37
+ def serve
38
+ file = socket_file
39
+ # We delete the tmp file for the Unix socket if it already exists. The file
40
+ # is scoped to the `pwd`, so if it already exists then it must be from an
41
+ # old run of `spin serve` and can be cleaned up.
42
+ File.delete(file) if File.exist?(file)
43
+ # This socket is how we communicate with `spin push`.
44
+ socket = UNIXServer.open(file)
45
+
46
+ ENV['RAILS_ENV'] = 'test' unless ENV['RAILS_ENV']
47
+
48
+ if File.exist? 'config/application.rb'
49
+ sec = Benchmark.realtime {
50
+ # We require config/application because that file (typically) loads Rails
51
+ # and any Bundler deps, as well as loading the initialization code for
52
+ # the app, but it doesn't actually perform the initialization. That happens
53
+ # in config/environment.
54
+ #
55
+ # In my experience that's the best we can do in terms of preloading. Rails
56
+ # and the gem dependencies rarely change and so don't need to be reloaded.
57
+ # But you can't initialize the application because any non-trivial app will
58
+ # involve it's models/controllers, etc. in its initialization, which you
59
+ # definitely don't want to preload.
60
+ require File.expand_path 'config/application'
61
+ }
62
+ # This is the amount of time that you'll save on each subsequent test run.
63
+ puts "Preloaded Rails env in #{sec}s..."
64
+ else
65
+ warn "Could not find config/application.rb. Are you running this from the root of a Rails project?"
66
+ end
67
+
68
+ loop do
69
+ # Since `spin push` reconnects each time it has a new file for us we just
70
+ # need to accept(2) connections from it.
71
+ conn = socket.accept
72
+ # This should be a relative path to a file.
73
+ file = conn.gets.chomp
74
+
75
+ # We fork(2) before loading the file so that our pristine preloaded
76
+ # environment is untouched. The child process will load whatever code it
77
+ # needs to, then it exits and we're back to the baseline preloaded app.
78
+ fork do
79
+ puts
80
+ puts "Loading #{file}"
81
+
82
+ # We require the full path of the file here in the child process.
83
+ require File.expand_path file
84
+ end
85
+
86
+ # We don't want the parent process handling multiple test runs at the same
87
+ # time because then we'd need to deal with multiple test databases, and
88
+ # that destroys the idea of being simple to use. So we wait(2) until the
89
+ # child process has finished running the test.
90
+ Process.wait
91
+ end
92
+ end
93
+
94
+ # ## spin push
95
+ def push
96
+ # This is the other end of the socket that `spin serve` opens. At this point
97
+ # `spin serve` will accept(2) our connection.
98
+ socket = UNIXSocket.open(socket_file)
99
+ # The filenames that we will spin up to `spin serve` are passed in as
100
+ # arguments.
101
+ files_to_load = ARGV
102
+
103
+ # We reject anything in ARGV that isn't a file that exists. This takes
104
+ # care of scripts that specify files like `spin push -r file.rb`. The `-r`
105
+ # bit will just be ignored.
106
+ files_to_load.select { |f| File.exist?(f) }.each do |f|
107
+ puts "Spinning up #{f}"
108
+ # We put the filename on the socket for the server to read and then load.
109
+ socket.puts f
110
+ end
111
+ rescue Errno::ECONNREFUSED
112
+ abort "Connection was refused. Have you started up `spin serve` yet?"
113
+ end
114
+
115
+ subcommand = ARGV.shift
116
+ case subcommand
117
+ when 'serve' then serve
118
+ when 'push' then push
119
+ else usage
120
+ end
metadata ADDED
@@ -0,0 +1,71 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: spin
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Jesse Storimer
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-10-28 00:00:00 -04:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: |-
23
+ Spin preloads your Rails environment to speed up your autotest(ish) workflow.
24
+
25
+ By preloading your Rails environment for testing you don't load the same code over and over and over... Spin works best for an autotest(ish) workflow.
26
+ email:
27
+ - jstorimer@gmail.com
28
+ executables:
29
+ - spin
30
+ extensions: []
31
+
32
+ extra_rdoc_files: []
33
+
34
+ files:
35
+ - bin/spin
36
+ has_rdoc: true
37
+ homepage: http://jstorimer.github.com/spin
38
+ licenses: []
39
+
40
+ post_install_message:
41
+ rdoc_options: []
42
+
43
+ require_paths:
44
+ - lib
45
+ required_ruby_version: !ruby/object:Gem::Requirement
46
+ none: false
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ hash: 3
51
+ segments:
52
+ - 0
53
+ version: "0"
54
+ required_rubygems_version: !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ hash: 3
60
+ segments:
61
+ - 0
62
+ version: "0"
63
+ requirements: []
64
+
65
+ rubyforge_project:
66
+ rubygems_version: 1.6.2
67
+ signing_key:
68
+ specification_version: 3
69
+ summary: Spin preloads your Rails environment to speed up your autotest(ish) workflow.
70
+ test_files: []
71
+