open_exception gem: now with better emacs support!

I just released v0.3.1 of the open_exception gem. This release does a better job of handling exceptions that have been munged by Rails, and now provides a tempfile containing the full stack trace to the open command.

If you are using emacs, you can use the :emacs_with_trace open command, and get the stack trace as a navigable compilation buffer (next to || below) the source file in a split frame. For this to work, you’ll need to add the following function to your emacs init:

See github for the code and README.

open_exception gem: auto open exceptions in your editor

open_exception opens an exception in your favorite editor when developing locally. It works by parsing the backtrace, and opening the offending file at the offending line in your favorite editor (assuming your favorite editor supports remote open commands).

You can add filters that allow you to ignore some exceptions, and filters that allow you to scope the backtrace search. The backtrace scoping is useful for opening the last call in your application code when the exception occurs in a framework or lib.

If you are on MacOSX and have the growl gem installed, you will get a growl notification with the exception message when the file is opened.

Editors

Out if the box, the gem supports three editors (with the following open commands):

:emacs => '/usr/bin/emacsclient -n +{line} {file}',
:textmate => '/usr/local/bin/mate -a -d -l {line} {file}',
:macvim => '/usr/local/bin/mvim +{line} {file}'

Note: if using emacs, you will need to be running emacsserver. To start the server: M-x server-start

or add (server-start) to your init.

Configuration

To configure, pass a block to the configure method:

OpenException.configure do |oe|
    # open_with can be one of the built in editors (:emacs, :macvim, :textmate)
    # or a command to execute to open the file, where {file} and {line} will be replaced
    # with the file path and line number, respectively. See 'Editors' above for an example.
    # The default editor is :emacs.
     
    oe.open_with = :emacs
     
    # you can add exclusion filters to ignore exceptions. A filter can be an exception class to 
    # ignore, or a proc that is passed the exception, and should evaluate to true if the exception 
    # should be ignored. Be careful with using a class - it uses is_a?, so any subclasses of the
    # passed class will be ignored as well. The list of filters is [] by default.
     
    oe.exclusion_filters << SomeErrorClass
    oe.exclusion_filters << lambda { |exception| true if exception_should_be_excluded }
     
    # you can scope the search for the file:line to open with a filter as well. A filter can be a 
    # regular expression that is matched against the line, or a proc that is passed the line and 
    # should evaluate to true if the line should be used. The first line that any filter passes for 
    # will be the file:line that is opened. This is useful for opening the point in the stack just
    # before control passes out of your app code when the exception occurs in an external 
    # lib/framework. The list of filters is [] by default. 
     
    oe.backtrace_line_filters << %r{/app/root/(app|lib)} 
    oe.backtrace_line_filters << lambda { |backtrace_line| true if line_should_be_used }
     
end

Rails Integration

The gem also alias chains in to rails’ ActionController#rescue_action_locally method to automatically open exceptions in development mode. The gem also adds the following filter to the :backtrace_line_filters to scope the opened files to the app:

%r{#{Rails.root}/(app|lib)}

To replace or remove this filter, you will need to reset the :backtrace_line_filters in your configure block:

OpenException.configure do |oe|
    oe.backtrace_line_filters = []
    oe.backtrace_line_filters << my_new_filter
end

This has been tested with rails v2.3.5, but should work fine with 2.1 <= rails < 3. It may work with rails 3 as well, I just haven’t yet looked at rails 3.

Standalone/Other Frameworks

# To manually open an exception, or wire it up in another framework, you call:
OpenException.open(exception)
 
# You can override the default (or configured) options by passing a hash as the second arg:
OpenException.open(exception, {:open_with => :textmate, :backtrace_line_filters => [filter, another_filter])

The source is on github, and the gem is on rubygems.

Refreshing an individual gemspec

I’m in the process of upgrading a rails app from 2.1 to 2.3, and 2.3 wants me to refresh some of the gemspecs for my vendored gems. Unfortunately, when I run rake gems:refresh_specs I get the dreaded:

rake aborted!
can't activate , already activated json-1.1.9

I was able to refresh the spec in question outside of rake with (in the console):

>> Rails::GemDependency.from_directory_name('vendor/gems/gem_name-0.1.0', false).refresh

Hopefully that helps someone else out.

zendesk_remote_auth gem makes Zendesk SSO easy!

I extracted how we are doing Zendesk remote authentication from an app at Dealer Ignition, and stuck it in a small gem for your enjoyment. You can find it on GitHub.

Installation and Setup

Install:

gem install tobias-zendesk_remote_auth

Setup:

You will need to give the gem your token and authentication url, perhaps in an initializer:

Zendesk::RemoteAuth.token = 'YOUR-TOKEN'
Zendesk::RemoteAuth.auth_url = 'https://yourcompany.zendesk.com/access/remote/'

and config the gem in environment.rb (if using rails):

config.gem 'tobias-zendesk_remote_auth', :lib => 'zendesk_remote_auth', :source => http://gems.github.com'

Usage

Mixin the Zendesk::RemoteAuthHelper module wherever needed, then call:

zendesk_remote_auth_url(:name => 'user name',
                        :email => 'user email',
                        <optional params>)

This will return a url you can redirect the user to to log them in to your zendesk account.

As a convenience, you can pass a user object to zendesk_remote_auth_url:

zendesk_remote_auth_url(user)

This user must respond_to? :name and :email, and its :id will be used as the :external_id (making it useless with user objects that return an ephemeral object_id, but works well with ActiveRecord and the like). If the user object responds to :zendesk_organization, that will be used as the :o rganization for the call.

This method will generate and include the hash of the parameters for you if necessary.

Example Auth Controller

Here is an example controller that handles login and logout for zendesk:

# Uses restful-authentication style auth. 
# 
# Define the following in routes.rb:
# map.with_options :controller => 'zendesk_auth' do |zd|
#   zd.connect '/zendesk/authorize', :action => 'authorize'
#   zd.connect '/zendesk/logout', :action => 'logout'
# end
class ZendeskAuthController < ApplicationController
    include Zendesk::RemoteAuthHelper
     
    skip_before_filter :login_required, :only => :logout
     
    def authorize
        redirect_to zendesk_remote_auth_url(current_user)
    end
     
    def logout
        redirect_to logout_url
    end
     
    protected
    def login_required
        if !logged_in?
            flash[:notice] = 'You must log in to access the support site.'
            store_location
            redirect_to login_path
        end
    end
end

server_remote gem

I just re-released my server_remote plugin as a gem server_remote on github. I converted it to a gem to make it easier to use in multiple apps, and to make it easier to update (see here for the blog entry on the (now obselete) plugin).

It is a gem that provides support for running commands on remote server. Once set up, it provides commands via script/remote:

  • remote shell – same as ssh’ing to the server (this is the default command, so it can be called with just remote)
  • remote console – executes a script/console on the server
  • remote logtail – executes tail -f log/<environment>.log on the server
  • remote cmd <some command> executes command on the server, displaying the result. It cd‘s to the remote app root first.
  • remote scp <local_file> :<remote_file> provides scp. Prefix remote files with ‘:’
Configuration is in config/server_remote.yml, and is grouped into profiles.

Here is the output of remote usage:

Executes commands on a remote server over ssh. Configuration is in:
/Users/tobias/customers/DealerIgnition/dealer_ignition/script/../config/server_remote.yml
 
You can override the profile used with -p profile. The default profile is: app
 
Learn more in the readme:
/opt/local/lib/ruby/gems/1.8/gems/tobias-server_remote-0.2.0/lib/server_remote/../../README.textile
 
remote commands are:
 
DEFAULT COMMAND   shell
 
cmd               executes an arbitrary command on the server after a cd to the app path
commands          List all 'remote' commands
console           executes remote console
help              Provide help documentation for a command
logtail           executes remote tail -f on the log
scp               copies files over scp (prefix remote files with ':')
shell             executes remote shell
usage             prints usage message
 
For help on a particular command, use 'remote help COMMAND'.

It uses remi’s simplecli gem.

I plan to add other commands as needed, or you can open up Remote::Commands and add your own.

Installation

You will need to install the gem (only once), then setup any apps where you want to use it.

sudo gem install tobias-server_remote --source http://gems.github.com/
server_remotify path_to_app