duoconsole 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/bin/duoconsole +12 -0
  2. data/lib/duoconsole.rb +162 -0
  3. metadata +81 -0
data/bin/duoconsole ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ APP_PATH = File.join(Dir.pwd, 'config', 'application')
4
+
5
+ begin
6
+ require File.join(Dir.pwd, 'config', 'boot')
7
+ rescue LoadError
8
+ abort "Duoconsole must be run from the root directory of a Rails project."
9
+ end
10
+
11
+ require 'duoconsole'
12
+ Duoconsole.start
data/lib/duoconsole.rb ADDED
@@ -0,0 +1,162 @@
1
+ require 'socket'
2
+
3
+ class Duoconsole
4
+
5
+ def self.start
6
+ new.start
7
+ end
8
+
9
+ attr_accessor :child_socket, :parent_socket
10
+
11
+ def start
12
+ preload_gems
13
+ create_socket_pair
14
+ fork_child
15
+ load_application
16
+ initialize_command_client
17
+ start_console
18
+ end
19
+
20
+ def preload_gems
21
+ require 'rails/all'
22
+
23
+ if defined?(Bundler)
24
+ Bundler.require(:default, :assets)
25
+ end
26
+
27
+ require 'commands'
28
+ end
29
+
30
+ def create_socket_pair
31
+ self.child_socket, self.parent_socket = Socket.pair(:UNIX, :DGRAM, 0)
32
+ end
33
+
34
+ def fork_child
35
+ child_pid = fork do
36
+ ENV['RAILS_ENV'] = 'test'
37
+
38
+ if defined?(Rails)
39
+ Rails.env = 'test'
40
+ end
41
+
42
+ load_application
43
+ monkeypatch_test_environment
44
+
45
+ trap(:INT) {
46
+ # Ignore. This process needs to stay alive until the parent process exits
47
+ }
48
+
49
+ CommandServer.new(child_socket).start
50
+ end
51
+
52
+ # cleanup before exiting
53
+ at_exit {
54
+ Process.kill(:QUIT, child_pid)
55
+ parent_socket.close
56
+ child_socket.close
57
+ }
58
+ end
59
+
60
+ def load_application
61
+ require APP_PATH
62
+ Rails.application.require_environment!
63
+ end
64
+
65
+ def initialize_command_client
66
+ ConsoleDelegation.command_client = CommandClient.new(parent_socket)
67
+ end
68
+
69
+ def start_console
70
+ require 'rails/commands/console'
71
+ require 'rails/console/app'
72
+ Rails::ConsoleMethods.send :include, ConsoleDelegation
73
+ Rails::Console.start(Rails.application)
74
+ end
75
+
76
+ def monkeypatch_test_environment
77
+ Rails::Commands::TestEnvironment.module_eval do
78
+ # Overriding this method to add the following behavior:
79
+ # 1. fix issue with Postgres adapter and forking behavior
80
+ # 2. trap INT signal and exit
81
+ def fork
82
+ ActiveRecord::Base.clear_active_connections!
83
+ Rails::Commands::Environment.fork do
84
+ setup_for_test
85
+ trap(:INT) { exit(1) }
86
+
87
+ yield
88
+ ActiveRecord::Base.clear_active_connections!
89
+ end
90
+ end
91
+ end
92
+ end
93
+
94
+
95
+ class CommandClient
96
+ attr_reader :socket
97
+
98
+ def initialize socket
99
+ @socket = socket
100
+ end
101
+
102
+ def send msg
103
+ socket.write(msg)
104
+ socket.recv(1000)
105
+ end
106
+
107
+ def method_missing(m, *args, &block)
108
+ send "#{m} #{args.join(' ')}"
109
+ end
110
+ end
111
+
112
+
113
+ class CommandServer
114
+ attr_reader :socket
115
+
116
+ def initialize socket
117
+ @socket = socket
118
+ end
119
+
120
+ def start
121
+ loop do
122
+ msg = socket.recv(1000)
123
+ command, args = get_command_and_args msg
124
+
125
+ retval = if commander.respond_to?(command)
126
+ commander.send(command, args)
127
+ else
128
+ 'Unrecognized command'
129
+ end
130
+
131
+ socket.write(retval)
132
+ end
133
+ end
134
+
135
+ def get_command_and_args msg
136
+ parts = msg.split(' ')
137
+ command = parts.shift
138
+ args = parts.join(' ')
139
+ args = nil unless args.match(/\S/)
140
+ [command, args]
141
+ end
142
+
143
+ def commander
144
+ @commander ||= Rails::Commands::Commander.new
145
+ end
146
+ end
147
+
148
+
149
+ module ConsoleDelegation
150
+ def self.command_client= client
151
+ @@command_client = client
152
+ end
153
+
154
+ def testenv
155
+ @@command_client
156
+ end
157
+
158
+ def test *args
159
+ testenv.test *args
160
+ end
161
+ end
162
+ end
metadata ADDED
@@ -0,0 +1,81 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: duoconsole
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Geoff Buesing
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-12-27 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rails
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 3.2.0
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 3.2.0
30
+ - !ruby/object:Gem::Dependency
31
+ name: commands
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: 0.2.1
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: 0.2.1
46
+ description:
47
+ email: gbuesing@gmail.com
48
+ executables:
49
+ - duoconsole
50
+ extensions: []
51
+ extra_rdoc_files: []
52
+ files:
53
+ - lib/duoconsole.rb
54
+ - bin/duoconsole
55
+ homepage: https://github.com/gbuesing/duoconsole
56
+ licenses:
57
+ - MIT
58
+ post_install_message:
59
+ rdoc_options: []
60
+ require_paths:
61
+ - lib
62
+ required_ruby_version: !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ! '>='
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ! '>='
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ requirements: []
75
+ rubyforge_project:
76
+ rubygems_version: 1.8.23
77
+ signing_key:
78
+ specification_version: 3
79
+ summary: Launch Rails development console with test environment as a child process
80
+ test_files: []
81
+ has_rdoc: