#!/usr/bin/ruby # # CHANGELOG: # 12-19-07: added special source tab to determine if rails is frozen # in the application directory # require 'korundum' require 'yaml' require 'fileutils' require 'optparse' require 'pp' require 'rubygems' class RailsDev < KDE::Dialog BASEDIR = File.expand_path("~/rails") CONFIG_FILE = File.expand_path("~/.railsdevrc") ICON_FILE = File.join(File.dirname(__FILE__), 'rails.png') DEFAULT_CONFIG = { "tabs" => [ {"name"=>"dev"}, {"name"=>"mdls", "dir"=>"app/models", "exec"=>"vim -p *"}, {"name"=>"vws", "dir"=>"app/views"}, {"name"=>"ctrl", "dir"=>"app/controllers", "exec"=>"vim -p *"}, {"name"=>"lib", "dir"=>"lib"}, {"name"=>"othr"}, {"name"=>"cnsl", "exec"=>"script/console"}, {"name"=>"test", "dir"=>"test"}, {"name"=>"fxtr", "dir"=>"test/fixtures", "exec"=>"vim -p *"}, {"name"=>"log", "dir"=>"log", "exec"=>"tail -f ${RAILS_ENV}.log"}, {"name"=>"db", "special"=>"database"}, {"name"=>"srv", "special"=>"server"}, {"name"=>"misc"} ], "applications" => {} } slots 'btn_go_clicked()', 'btn_cancel_clicked()' attr_reader :lab_rails_app attr_reader :lab_env attr_reader :btn_cancel attr_reader :btn_go attr_reader :cb_rails_app attr_reader :cb_env def initialize(config_file = CONFIG_FILE, parent = nil, name = "railsdev", modal = false) flags = Qt::WStyle_Customize.to_i | Qt::WStyle_Title.to_i | Qt::WStyle_NormalBorder.to_i & ~(Qt::WStyle_Maximize.to_i) super(parent, name, modal, flags) @config_file = config_file pp @config_file # setGeometry(0, 0, 290, 130) setCaption("Rails Development") setIcon( Qt::Pixmap.new(ICON_FILE) ) if File.exist?(ICON_FILE) @lab_rails_app = Qt::Label.new(self, "lab_rails_app") @lab_rails_app.setGeometry(42, 10, 78, 30) @lab_rails_app.setText("Rails App:") @lab_env = Qt::Label.new(self, "lab_env") @lab_env.setGeometry(15, 50, 106, 30) @lab_env.setText("Environment:") @btn_cancel = KDE::PushButton.new(self, "btn_cancel") @btn_cancel.setGeometry(180, 90, 100, 28) @btn_cancel.setText("Cancel") @btn_go = KDE::PushButton.new(self, "btn_go") @btn_go.setGeometry(10, 90, 70, 28) @btn_go.setText("Go") @cb_rails_app = KDE::ComboBox.new(false, self, "cb_rails_app") @cb_rails_app.setGeometry(140, 10, 140, 26) @cb_env = KDE::ComboBox.new(false, self, "cb_env") @cb_env.setGeometry(140, 50, 140, 26) @cb_env.insertItem("development") @cb_env.insertItem("production") connect(@btn_go, SIGNAL("clicked()"), SLOT("btn_go_clicked()") ) connect(@btn_cancel, SIGNAL("clicked()"), SLOT("btn_cancel_clicked()") ) read_config add_apps end def btn_go_clicked() @app = @cb_rails_app.currentText @rails_env = @cb_env.currentText @appdir = File.join(BASEDIR, @app) # fire up konsole error = dcopService = "" pid = Qt::Integer.new errcode = KDE::Application.startServiceByDesktopName("konsole-script", "", error, dcopService, pid) dcopService = "konsole-" + pid.to_s konsole = KDE::DCOPRef.new(dcopService, "konsole") session = KDE::DCOPRef.new(dcopService, "session-1") # run shit @config['tabs'].each_with_index do |tab, i| session.renameSession tab['name'] if tab['name'] if tab['special'] != 'test' and @rails_env != 'development' session.sendSession "export RAILS_ENV=\"#{@rails_env}\"" end case tab['special'] when /^database$/i setup_database_tab(session) when /^test-server$/i setup_test_server_tab(session) when /^server$/i setup_server_tab(session) when /^source$/i setup_source_tab(session) else dir = tab['dir'] ? (tab['dir'][0].chr == "/" ? tab['dir'] : "#{@appdir}/#{tab['dir']}") : @appdir session.sendSession "cd #{dir}" session.sendSession "clear" case tab['exec'] when String session.sendSession tab['exec'] when Array tab['exec'].each { |e| session.sendSession e } end end unless i == (@config['tabs'].length - 1) session = KDE::DCOPRef.new(dcopService, konsole.newSession) end end close end def btn_cancel_clicked() close end def add_apps # figure out which directories are rails ones Dir["#{BASEDIR}/*/Rakefile"].collect { |path| path.split("/")[-2] }.sort.each do |appname| @cb_rails_app.insertItem(appname) end end def read_config FileUtils.touch(@config_file) unless File.exist?(@config_file) @config = YAML.load_file(@config_file) if @config.nil? @config = DEFAULT_CONFIG write_config elsif @config['tabs'].nil? || @config['tabs'].nil? @config['tabs'] ||= DEFAULT_CONFIG['tabs'] @config['applications'] ||= DEFAULT_CONFIG['applications'] write_config end end def write_config File.open(@config_file, "w") do |f| f.write @config.to_yaml end end def init_config_for(appname) require 'facets/core/array/at_rand' require 'socket' range = (37000..37200).to_a used_ports = @config['applications'].values.collect { |v| v['port'] } port = range.at_rand found = false until found while used_ports.include?(port) port = range.at_rand end # make sure port isn't in use s = Socket.new(Socket::PF_INET, Socket::SOCK_STREAM, 0) begin s.bind(Socket.pack_sockaddr_in(port, 'localhost')) s.close found = true rescue Errno::EADDRINUSE used_ports << port end end @config['applications'].merge!({ appname => { 'port' => port } }) write_config end def setup_database_tab(session) # grab database configuration db = YAML.load_file(File.join(@appdir, 'config', 'database.yml'))[@rails_env] session.sendSession "cd #{@appdir}" case db['adapter'] when 'mysql' session.sendSession "mysql -u #{db['username']} -p #{db['database']}" sleep 2 session.sendSession db['password'] when 'postgresql' session.sendSession "psql -U #{db['username']} #{db['database']}" pgpass = File.expand_path("~/.pgpass") unless File.exist?(pgpass) and IO.read(pgpass) =~ /#{db['database']}/ sleep 2 session.sendSession db['password'] end when 'sqlite3' session.sendSession "sqlite3 #{db['database']}" end end def setup_server_tab(session) # serv session session.sendSession "cd #{@appdir}" init_config_for(@app) unless @config['applications'][@app] session.sendSession "script/server webrick -p #{@config['applications'][@app]['port']}" end def setup_test_server_tab(session) # serv session session.sendSession "cd #{@appdir}" session.sendSession "script/server -p 31337 -e test" end def setup_source_tab(session) dir = File.join(@appdir, 'vendor', 'rails') if File.exist?(dir) session.sendSession "cd #{dir}" else session.sendSession "cd #{Gem.dir}" end session.sendSession "clear" end end config_file = RailsDev::CONFIG_FILE opts = OptionParser.new do |opts| opts.on('-f FILE', '--file=FILE') do |file| config_file = file end end opts.parse!(ARGV) about = KDE::AboutData.new("rails_dev", "rails_dev", "1.0", "Rails development script", KDE::AboutData::License_GPL, "(C) 2007 Viking") KDE::CmdLineArgs.init(ARGV, about) app = KDE::Application.new dialog = RailsDev.new(config_file) app.mainWidget = dialog dialog.show app.exec