<?xml version="1.0" encoding="UTF-8"?>
<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom">
  <id>tag:sharagoz.com,2005:/posts</id>
  <link rel="alternate" type="text/html" href="http://sharagoz.com"/>
  <link rel="self" type="application/atom+xml" href="http://sharagoz.com/posts.atom"/>
  <title>Sharagoz' blog</title>
  <updated>2011-03-15T18:07:36+01:00</updated>
  <entry>
    <id>tag:sharagoz.com,2005:Post/8</id>
    <published>2011-10-20T13:57:42+02:00</published>
    <updated>2011-10-20T21:04:49+02:00</updated>
    <link rel="alternate" type="text/html" href="http://sharagoz.com/posts/8-rails-sql-anywhere-10-on-linux"/>
    <title>Rails + SQL Anywhere 10 on Linux</title>
    <content type="html">&lt;p&gt;
I recently had to make a rails app talk to an sqlanywhere database. The app was to be deployed on a linux server that runs nginx + passenger. This is a fairly simple process, but there arent a lot of information on it on the internet so I'm writing a quick article.&lt;/p&gt;

&lt;p&gt;&lt;h2&gt;Setting up a development environment on (arch) linux:&lt;/h2&gt;&lt;/p&gt;

&lt;p&gt;Here's how to make a rails app talk to a local database server. If you wanna talk to an external DB then see the section on deployment.&lt;/p&gt;

&lt;p&gt;(The paths used here assumes that you install sql anywhere to /opt/sqlanywhere10 and that you use the 64-bit version)&lt;/p&gt;

&lt;p&gt;The first step is to download and install the sql anywhere 10 developer edition for linux and get it patched to the latest version. I cant link to the tarball as it requires registration.
&lt;br /&gt;Extract the files and run the setup file. The installation is straight forward. I installed all the modules to be able to set up a local database server and use the Sybase Central. This requires a developer key, which my company already had. I think you can get one by registering on the sybase site.&lt;/p&gt;

&lt;p&gt;Right out of the gates you will have a couple of issues. Try to check which version you have:
&lt;br /&gt;&lt;code&gt;
&lt;br /&gt;/opt/sqlanywhere10/bin64/dbsrv10 -v
&lt;br /&gt;&lt;/code&gt;
&lt;br /&gt;You will probably get this error:
&lt;br /&gt;&lt;code&gt;
&lt;br /&gt;error while loading shared libraries: libdbserv10_r.so: cannot open shared object file: No such file or directory
&lt;br /&gt;&lt;/code&gt;
&lt;br /&gt;This is because sql anywhere requires some environment variables to be set up
&lt;br /&gt;You can set these up by sourcing a .sh script like so:
&lt;br /&gt;&lt;code&gt;
&lt;br /&gt;source /opt/sqlanywhere10/bin64/sa_config.sh
&lt;br /&gt;&lt;/code&gt;
&lt;br /&gt;Try checking the version again. It should show something like:
&lt;br /&gt;&lt;code&gt;
&lt;br /&gt;10.0.1.4239
&lt;br /&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If your version is below 10.0.1.4000 you'll most likely run into issues down the road. Get a hold of the update patch (again I cant link, as it requires login). Do not continue until you get this resolved.&lt;/p&gt;

&lt;p&gt;Having to source that sa_config.sh file every time you open a new shell gets annoying, so I recommend you add the command to /etc/profile or ~/.bashrc&lt;/p&gt;

&lt;p&gt;Btw, you may want to check out Sybase Central. It can be started with this command (if you have sourced that config file):
&lt;br /&gt;&lt;code&gt;
&lt;br /&gt;scjview
&lt;br /&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Sybase central enables you to do administer databases through a GUI, which is helpfull.&lt;/p&gt;

&lt;p&gt;Right, once you have a patched version of sqlanywhere 10 it is time to start a database server. Most likely you have an existing database you can use, otherwise you can create one through Sybase Central.&lt;/p&gt;

&lt;p&gt;This command launches the server:
&lt;br /&gt;&lt;code&gt;
&lt;br /&gt;/opt/sqlanywhere10/bin64/dbsrv10 -n your_sa_server_name /path/to/database/file
&lt;br /&gt;&lt;code&gt;&lt;/p&gt;

&lt;p&gt;If everything is set up correctly you should get a stream of output that ends with these lines:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;
&lt;br /&gt;Starting on port 2638
&lt;br /&gt;TCPIP link started successfully
&lt;br /&gt;Now accepting requests
&lt;br /&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now we need to configuring Rails to talk to this database server and get the active record adapter installed.&lt;/p&gt;

&lt;p&gt;Add the activerecord-sqlanywhere-adapter to the gemfile:
&lt;br /&gt;&lt;code&gt;
&lt;br /&gt;gem 'activerecord-sqlanywhere-adapter'
&lt;br /&gt;&lt;/code&gt;
&lt;br /&gt;And run &lt;b&gt;bundle install&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;Set up database.yml
&lt;br /&gt;&lt;code&gt;
&lt;br /&gt;development:
&lt;br /&gt;  adapter: sqlanywhere
&lt;br /&gt;  server: your_sa_server_name # This must match what you set as the -n directive when you started the database server
&lt;br /&gt;  database: filename # This must match the filename of your database file. E.G: If the filename is my_database.db then use &quot;my_database&quot;
&lt;br /&gt;  host: localhost
&lt;br /&gt;  encoding: utf-8
&lt;br /&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Start a console with &lt;b&gt;rails c&lt;/b&gt; and execute a command to check that everything is OK:
&lt;br /&gt;&lt;code&gt;
&lt;br /&gt;ActiveRecord::Base.connection.execute(&quot;SELECT * FROM my_table&quot;)
&lt;br /&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;At the point of writing there are some issues with the sqlanywhere adapter for active record when used with Rails 3.0 and 3.1. I have a fork on Github that fixes some of these issues. Hopefully the maintainer will look into it soon and get it fixed properly in the main repo.&lt;/p&gt;

&lt;p&gt;&lt;h2&gt;Setting up the production environment on (arch) linux:&lt;/h2&gt;&lt;/p&gt;

&lt;p&gt;When installing on the server you only need the module called &quot;Network Client&quot; (no licence key required) if you are going to talk to a database on a different server.&lt;/p&gt;

&lt;p&gt;Make sure you apply the patch on the server too.&lt;/p&gt;

&lt;p&gt;When you are talking to an external database server you will have to specify its IP in database.yml
&lt;br /&gt;&lt;code&gt;
&lt;br /&gt;production:
&lt;br /&gt;  adapter: sqlanywhere
&lt;br /&gt;  database: external_db_name
&lt;br /&gt;  server: external_server_name
&lt;br /&gt;  commlinks: TCPIP(IP=80.80.80.80:2638)
&lt;br /&gt;  encoding: utf-8
&lt;br /&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;When you deploy the app you'll most likely get this error &quot;Could not load SQLAnywhere DBCAPI library&quot;. That is because those environment variables are missing again. On the server you cant simply source the script through /etc/profile or ~/.bashrc because the web server is not launched through a shell. Find a way to make the application server source the file.
&lt;br /&gt;I am using Nginx + passenger, and the way to do it here is to create a custom ruby wrapper that launches passenger. Here's how:&lt;/p&gt;

&lt;p&gt;In nginx.conf there is a line that looks like this:
&lt;br /&gt;&lt;code&gt;
&lt;br /&gt;passenger_ruby /usr/local/rvm/wrappers/ruby-1.9.2-p180/ruby
&lt;br /&gt;&lt;/code&gt;
&lt;br /&gt;Edit that command to use a custom wrapper that you'll define. E.G:
&lt;br /&gt;&lt;code&gt;
&lt;br /&gt;passenger_ruby /usr/local/rvm/wrappers/ruby-1.9.2-p180/custom_ruby
&lt;br /&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Copy the script from the original wrapper into the new custom wrapper and add the source command where appropriate. My wrapper looks like this:
&lt;br /&gt;&lt;code&gt;
&lt;br /&gt;#!/usr/bin/env bash&lt;/p&gt;

&lt;p&gt;if [[ -s &quot;/usr/local/rvm/environments/ruby-1.9.2-p180&quot; ]]
&lt;br /&gt;then
&lt;br /&gt;  source &quot;/opt/sqlanywhere10/bin64/sa_config.sh&quot; # This is the custom line
&lt;br /&gt;  source &quot;/usr/local/rvm/environments/ruby-1.9.2-p180&quot;
&lt;br /&gt;  exec ruby &quot;$@&quot;
&lt;br /&gt;else
&lt;br /&gt;  echo &quot;ERROR: Missing RVM environment file: '/usr/local/rvm/environments/ruby-1.9.2-p180'&quot; &gt;&amp;2
&lt;br /&gt;  exit 1
&lt;br /&gt;fi
&lt;br /&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Restart nginx and that missing dbcapi error should be gone.&lt;/p&gt;

&lt;p&gt;If you run into any issues, feel free to message me on &lt;a href=&quot;https://github.com/Sharagoz&quot;&gt;Github&lt;/a&gt; and I'll try to assist.
&lt;/p&gt;</content>
    <author>
      <name>Sharagoz</name>
    </author>
  </entry>
  <entry>
    <id>tag:sharagoz.com,2005:Post/7</id>
    <published>2011-07-24T00:38:13+02:00</published>
    <updated>2011-07-24T00:38:13+02:00</updated>
    <link rel="alternate" type="text/html" href="http://sharagoz.com/posts/7-charles-max-wood-is-putting-out-great-screencasts"/>
    <title>Charles Max Wood is putting out great screencasts</title>
    <content type="html">&lt;p&gt;I think &lt;a href=&quot;http://www.youtube.com/user/charlesmaxwood&quot;&gt;this guy&lt;/a&gt; deserves more attention than he seem to be getting.  &lt;/p&gt;

&lt;p&gt;Keep up the good work Max!&lt;/p&gt;</content>
    <author>
      <name>Sharagoz</name>
    </author>
  </entry>
  <entry>
    <id>tag:sharagoz.com,2005:Post/6</id>
    <published>2011-07-21T22:39:36+02:00</published>
    <updated>2011-07-21T22:39:36+02:00</updated>
    <link rel="alternate" type="text/html" href="http://sharagoz.com/posts/6-user-stamping-in-rails-3"/>
    <title>User stamping in Rails 3</title>
    <content type="html">&lt;p&gt;If you used the user_stamp gem in Rails 2 to maintain creator_id and updater_id columns in every table, you'll find that it doesn't work in Rails 3. I have a patched version on my Github account that works in production mode in Rails 3, but falls victim to class reloading in development mode. Instead of fixing that by breaking the old API, I'm just gonna make a quick post here on how you can implement the functionality yourself without depending on a gem. It's so simple that it's not really worth an external dependency.&lt;/p&gt;

&lt;p&gt;Add a new file to app/models called &lt;strong&gt;user_stamper.rb&lt;/strong&gt;:
&lt;br /&gt;&lt;code&gt;
&lt;br /&gt;class UserStamper &amp;lt; ActionController::Caching::Sweeper
&lt;br /&gt;  observe Post, Comment, User #replace with your own models&lt;/p&gt;

&lt;p&gt;  def before_validation(record)
&lt;br /&gt;    return unless current_user
&lt;br /&gt;    record.send(:creator_id=, current_user.id) if(record.new_record? &amp;&amp; record.respond_to?(:creator_id=))
&lt;br /&gt;    record.send(:updater_id=, current_user.id) if(record.changed? &amp;&amp; record.respond_to?(:updater_id=))
&lt;br /&gt;  end
&lt;br /&gt;  
&lt;br /&gt;  private  &lt;/p&gt;

&lt;p&gt;  def current_user
&lt;br /&gt;    controller.send(:current_user) if(controller.respond_to?(:current_user))
&lt;br /&gt;  end
&lt;br /&gt;end
&lt;br /&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You'll also need this line in the ApplicationController:
&lt;br /&gt;&lt;code&gt;
&lt;br /&gt;cache_sweeper :user_stamper
&lt;br /&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;That's all there is to it.&lt;/p&gt;</content>
    <author>
      <name>Sharagoz</name>
    </author>
  </entry>
  <entry>
    <id>tag:sharagoz.com,2005:Post/5</id>
    <published>2011-07-21T21:50:35+02:00</published>
    <updated>2011-07-21T21:50:35+02:00</updated>
    <link rel="alternate" type="text/html" href="http://sharagoz.com/posts/5-interacting-with-javascript-prompts-with-capybara"/>
    <title>Interacting with Javascript prompts with Capybara</title>
    <content type="html">&lt;p&gt;I tried switching from Webrat to Capybara about 4 or 5 months ago, but aborted it due to some reason I can't recall. I think it was because the &quot;have_selector&quot; matcher wasn't implemented yet. I decided to give it another try today hoping to be able to implement some of those pending Javascript related specs Webrat was unable to handle.&lt;/p&gt;

&lt;p&gt;And I was not disappointed, Capybara has excellent support for the selenium-webdriver. Look at this:
&lt;br /&gt;&lt;code&gt;
&lt;br /&gt;find('span', :text =&gt; 'Register your email address').click
&lt;br /&gt;prompt = page.driver.browser.switch_to.alert
&lt;br /&gt;prompt.send_keys('me@example.com')
&lt;br /&gt;prompt.accept
&lt;br /&gt;Email.first.address.should eq('me@example.com')
&lt;br /&gt;&lt;/code&gt;
&lt;br /&gt;I am clicking a non-button/link that triggers a javascript prompt. I fill out the text field in this prompt and then click the &quot;OK&quot; button, and it works!&lt;/p&gt;

&lt;p&gt;I'm in love with Capybara now.&lt;/p&gt;

&lt;p&gt;Btw, converting the existing specs created for Webrat was a very easy job.
&lt;br /&gt;There was some syntax changes to the &quot;have_selector&quot; matcher, calls to &quot;response&quot; had to be replaced by &quot;page&quot;, and the &quot;contains&quot; matcher had to be replaced by &quot;have_content&quot;. Easy.&lt;/p&gt;

&lt;p&gt;Right now I can't think of a single reason to choose Webrat over Capybara. Webrat isnt even maintained anymore as far as I can tell.&lt;/p&gt;</content>
    <author>
      <name>Sharagoz</name>
    </author>
  </entry>
  <entry>
    <id>tag:sharagoz.com,2005:Post/4</id>
    <published>2011-07-17T18:58:45+02:00</published>
    <updated>2011-07-17T18:59:25+02:00</updated>
    <link rel="alternate" type="text/html" href="http://sharagoz.com/posts/4-rails-exception-handler-gem-released"/>
    <title>Rails exception handler gem released</title>
    <content type="html">&lt;p&gt;Quick announcement:
&lt;br /&gt;I just released a gem called &quot;Rails Exception Handler&quot;, which is based on an earlier blog post of mine on rails exception handling. Check out the project &lt;a href=&quot;https://github.com/Sharagoz/rails_exception_handler&quot;&gt;on Github&lt;/a&gt;&lt;/p&gt;</content>
    <author>
      <name>Sharagoz</name>
    </author>
  </entry>
  <entry>
    <id>tag:sharagoz.com,2005:Post/3</id>
    <published>2011-05-24T17:16:35+02:00</published>
    <updated>2011-05-24T17:18:13+02:00</updated>
    <link rel="alternate" type="text/html" href="http://sharagoz.com/posts/3-changing-the-repository-location-for-gitosis"/>
    <title>Changing the repository location for gitosis</title>
    <content type="html">&lt;p&gt;This is how I did it on my company's git server, which resides on an Arch Linux box. Obviously, it's a very good idea to make a backup before starting a procedure like this.&lt;/p&gt;

&lt;p&gt;To change the location of the repo you need to do 3 things:
&lt;br /&gt;1. Add a line to gitosis.conf telling it that the repo is not in the default location
&lt;br /&gt;2. Move the repository folder
&lt;br /&gt;3. Update a symlink to gitosis.conf&lt;/p&gt;

&lt;p&gt;In the example below I am moving the repo from /srv/gitosis/repositories to /data/gitosis/repositories. Inside /srv/gitosis there is a symlink that looks like this, which has to be updated afterwards:
&lt;br /&gt;&lt;code&gt;.gitosis.conf -&gt; /srv/gitosis/repositories/gitosis-admin.git/gitosis.conf&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;h2&gt;gitosis.conf&lt;/h2&gt;
&lt;br /&gt;I assume you are familiar with gitosis.conf, where you configure users, repos etc. Add this line:
&lt;br /&gt;&lt;code&gt;[gitosis]
&lt;br /&gt;repositories = /data/gitosis/repositories&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Important: Push these changes before you move the repository folder&lt;/p&gt;

&lt;p&gt;&lt;h2&gt;Moving the repository folder&lt;/h2&gt;
&lt;br /&gt;&lt;code&gt;mv /srv/gitosis/repositories /data/gitosis/repositories&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;h2&gt;Update the symlink&lt;/h2&gt;
&lt;br /&gt;&lt;code&gt;ln -s -f /data/gitosis/repositories/gitosis-admin.git/gitosis.conf /srv/gitosis/.gitosis.conf&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Couldn't find any info on this online, so I wrote this post. Hope it helps.&lt;/p&gt;</content>
    <author>
      <name>Sharagoz</name>
    </author>
  </entry>
  <entry>
    <id>tag:sharagoz.com,2005:Post/2</id>
    <published>2011-03-15T20:29:51+01:00</published>
    <updated>2011-03-15T20:29:51+01:00</updated>
    <link rel="alternate" type="text/html" href="http://sharagoz.com/posts/2-doctype-tv-needs-more-love"/>
    <title>Doctype TV needs more love</title>
    <content type="html">&lt;p&gt;I can't belive these guys doesn't have more subscribers. They produce high quality screencasts on web UI related topics. Check them out and spread the word!
&lt;br /&gt;&lt;a href=&quot;http://www.youtube.com/user/doctypetv&quot;&gt;http://www.youtube.com/user/doctypetv&lt;/a&gt;&lt;/p&gt;</content>
    <author>
      <name>Sharagoz</name>
    </author>
  </entry>
  <entry>
    <id>tag:sharagoz.com,2005:Post/1</id>
    <published>2011-03-15T18:07:36+01:00</published>
    <updated>2011-03-15T20:00:07+01:00</updated>
    <link rel="alternate" type="text/html" href="http://sharagoz.com/posts/1-rolling-your-own-exception-handler-in-rails-3"/>
    <title>Rolling your own exception handler in Rails 3</title>
    <content type="html">&lt;p&gt;In Rails 2 you could override ActionController's &quot;rescue_action_in_public&quot; to do your own exception handling.
&lt;br /&gt;For Rails 3 the request handling was re-written to take full advantage of Rack, so now you need to use Rack middleware to catch and handle the exceptions manually.
&lt;br /&gt;For an introduction to Rack middleware you can checkout &lt;a href=&quot;http://railscasts.com/episodes/151-rack-middleware&quot;&gt;Railscasts ep. 151&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I will show you how to create a middleware app that serves as a backend for tracking exceptions in your rails apps. Catch the exception, store the relevant data in the database, and display a custom error message to the user. That's what I will cover. The front end is not the scope of this post.
&lt;br /&gt;&lt;h2&gt;The middleware skeleton&lt;/h2&gt;Create a file in the lib folder and call it &quot;exception_handler.rb&quot;. Here's the minimal code that will get us started:
&lt;br /&gt;&lt;code&gt;
&lt;br /&gt;class ExceptionHandler
&lt;br /&gt;  def initialize(app)
&lt;br /&gt;    @app = app
&lt;br /&gt;  end&lt;/p&gt;

&lt;p&gt;  def call(env)
&lt;br /&gt;    @app.call(env)
&lt;br /&gt;  rescue
&lt;br /&gt;    [&quot;200&quot;, {&quot;content-type&quot; =&gt; &quot;text/html&quot;}, &quot;An error has occured&quot;]
&lt;br /&gt;  end
&lt;br /&gt;end
&lt;br /&gt;&lt;/code&gt;
&lt;br /&gt;To hook the error handler into the application, add these lines to config/application.rb
&lt;br /&gt;&lt;code&gt;
&lt;br /&gt;require 'exception_handler'
&lt;br /&gt;config.middleware.use ExceptionHandler
&lt;br /&gt;&lt;/code&gt;
&lt;br /&gt;For production usage you'd move these into production.rb, as you want regular error messages in development. If you trigger an error now you should receive a response that says nothing more than &quot;An error has occured&quot;.
&lt;br /&gt;Note: What we have so far will not catch routing errors, I'll get to that in a minute.&lt;/p&gt;

&lt;p&gt;Let's start by gathering the information we want to save.
&lt;br /&gt;Create a new class called &quot;Parser&quot; and define it within the ExceptionHandler class.
&lt;br /&gt;&lt;code&gt;
&lt;br /&gt;class Parser
&lt;br /&gt;  def initialize(exception, request)
&lt;br /&gt;    @exception = exception
&lt;br /&gt;    @request  = request
&lt;br /&gt;  end&lt;/p&gt;

&lt;p&gt;  def relevant_info
&lt;br /&gt;    info = {}
&lt;br /&gt;    info[:class_name] = @exception.class.to_s # The exception class, &quot;ActiveRecord::RecordNotFound&quot;
&lt;br /&gt;    info[:message] = @exception.to_s # The actual error message, &quot;Couldn't find Post with id=42&quot;
&lt;br /&gt;    info[:trace] = @exception.backtrace.join(&quot;\n&quot;) # I bet you have seen a backtrace before
&lt;br /&gt;    info[:target_url] = @request.url # Which URL did the client try to access
&lt;br /&gt;    info[:referer_url] = @request.referer # Which URL did he come from
&lt;br /&gt;    info[:params] = @request.params.inspect # The request parameters
&lt;br /&gt;    info[:user_agent] = @request.user_agent # The user agent string
&lt;br /&gt;    return info
&lt;br /&gt;  end
&lt;br /&gt;end
&lt;br /&gt;&lt;/code&gt;
&lt;br /&gt;To store this in the database we need a database table and a model:
&lt;br /&gt;&lt;code&gt;
&lt;br /&gt;rails g model ErrorMessage class_name:text message:text trace:text target_url:text referer_url:text params:text user_agent:text
&lt;br /&gt;rake db:migrate
&lt;br /&gt;&lt;/code&gt;
&lt;br /&gt;To use the class we just made, change the code of the rescue block in ExceptionHandler:
&lt;br /&gt;&lt;code&gt;
&lt;br /&gt;rescue Exception =&gt; e
&lt;br /&gt;  request = ActionDispatch::Request.new(env)
&lt;br /&gt;  parsed_error = Parser.new(e, request)
&lt;br /&gt;  ErrorMessage.create!(parsed_error.relevant_info)
&lt;br /&gt;  [&quot;200&quot;, {&quot;content-type&quot; =&gt; &quot;text/html&quot;}, &quot;An error has occured&quot;]
&lt;br /&gt;end
&lt;br /&gt;&lt;/code&gt;
&lt;br /&gt;I am creating a new request object here. It is a bit easier to extract information from it than the env object itself.&lt;/p&gt;

&lt;p&gt;Give this a test. What we have made so far is the gist of it. We catch the exception and store the info we want in the database. There are some important details to take care of though, before it can be put into production.
&lt;br /&gt;&lt;h2&gt;Filtering&lt;/h2&gt;Crawlers and bots are going to generate a bunch of errors, regardless of what you put in robot.txt. Let's add some basic filtering. Change the create statement to this:
&lt;br /&gt;&lt;code&gt;
&lt;br /&gt;ErrorMessage.create(parsed_error.relevant_info) unless(parsed_error.ignore?)
&lt;br /&gt;&lt;/code&gt;
&lt;br /&gt;Then define the ignore? function on the Parser class like so:
&lt;br /&gt;&lt;code&gt;
&lt;br /&gt;def ignore?
&lt;br /&gt;  # Ignore routing errors in requests without a referer as they are going to be bots in 99.99235% of the cases
&lt;br /&gt;  routing_errors = [ActionController::RoutingError, AbstractController::ActionNotFound, ActiveRecord::RecordNotFound]
&lt;br /&gt;  if(routing_errors.include?(@exception.class) &amp;&amp; @request.referer.blank?)
&lt;br /&gt;    return true
&lt;br /&gt;  end
&lt;br /&gt;  # Ignore requests with user agent string matching this regxp as they are surely made by bots
&lt;br /&gt;  if(@request.user_agent =~ /\b(Baidu|Gigabot|Googlebot|libwww-perl|lwp-trivial|msnbot|SiteUptime|Slurp|WordPress|ZIBB|ZyBorg|Yandex|Jyxobot|Huaweisymantecspider|ApptusBot)\b/i)
&lt;br /&gt;    return true
&lt;br /&gt;  end
&lt;br /&gt;  return false
&lt;br /&gt;end
&lt;br /&gt;&lt;/code&gt;
&lt;br /&gt;That's all the filtering I've needed. Some chose to ignore all routing errors, I prefer not to. Mortals like myself sometimes put broken links into production. If you start to get a large amount of error messages, it might be better to group them on the front end than apply a lot of filtering on the back end.
&lt;br /&gt;&lt;h2&gt;Catching routing errors&lt;/h2&gt;As I said before, we are not catching routing errors yet. To catch those you need to override a method in ActionDispatch:
&lt;br /&gt;Put this at the end of error_handler.rb
&lt;br /&gt;&lt;code&gt;
&lt;br /&gt;module ActionDispatch
&lt;br /&gt;  class ShowExceptions
&lt;br /&gt;    private
&lt;br /&gt;      def render_exception_with_template(env, exception)
&lt;br /&gt;        # Handle error and return response
&lt;br /&gt;      end
&lt;br /&gt;      alias_method_chain :render_exception, :template
&lt;br /&gt;  end
&lt;br /&gt;end
&lt;br /&gt;&lt;/code&gt;
&lt;br /&gt;Credit: I got that snipped from &lt;a href=&quot;http://accuser.cc/posts/1-rails-3-0-exception-handling&quot;&gt;a blog post by AccUser&lt;/a&gt;.
&lt;br /&gt;&lt;h2&gt;A bit of refactoring&lt;/h2&gt;Instead of copy pasting the code from the ExceptionHandler's rescue block into the ActionDispatch method, I'm gonna be DRY and extract the code into its own class, so that maintaining and expanding the code is easier. Define a new class within the ExceptionHandler class called &quot;Handler&quot;:
&lt;br /&gt;&lt;code&gt;
&lt;br /&gt;class Handler
&lt;br /&gt;  def initialize(env, exception)
&lt;br /&gt;    @exception = exception
&lt;br /&gt;    @env = env
&lt;br /&gt;  end&lt;/p&gt;

&lt;p&gt;  def handle_exception
&lt;br /&gt;    request = ActionDispatch::Request.new(@env)
&lt;br /&gt;    parsed_error = Parser.new(@exception, request)
&lt;br /&gt;    ErrorMessage.create(parsed_error.relevant_info) unless(parsed_error.ignore?)
&lt;br /&gt;    return response
&lt;br /&gt;  end&lt;/p&gt;

&lt;p&gt;  def response
&lt;br /&gt;    [&quot;200&quot;, {&quot;content-type&quot; =&gt; &quot;text/html&quot;}, &quot;An error has occured&quot;]
&lt;br /&gt;  end
&lt;br /&gt;end
&lt;br /&gt;&lt;/code&gt;
&lt;br /&gt;Replace the rescue block with this line:
&lt;br /&gt;&lt;code&gt;Handler.new(env, e).handle_exception&lt;/code&gt;
&lt;br /&gt;Replace the comment in the ActionDispatch function with this line:
&lt;br /&gt;&lt;code&gt;ExceptionHandler::Handler.new(env, exception).handle_exception&lt;/code&gt;
&lt;br /&gt;With that you should be catching the routing errors as well.
&lt;br /&gt;&lt;h2&gt;Displaying a nicer error message&lt;/h2&gt;I prefer to display the error messages within the regular layout of the page. It looks nicer and feels less like &quot;MAYDAY! MAYDAY!&quot; for the user.
&lt;br /&gt;Trying to send responses with layouts without using a controller in Rails takes a bit of work, so I'm gonna define an error response controller in the exception catcher to take care of this. Put this at the bottom of exception_catcher.rb:
&lt;br /&gt;&lt;code&gt;
&lt;br /&gt;class ErrorResponseController &amp;lt; ActionController::Base
&lt;br /&gt;  def index
&lt;br /&gt;    render(:text =&gt; &quot;&lt;h1&gt;An error has occured&lt;/h1&gt;&lt;p&gt;The error message has been logged&lt;/p&gt;&quot;, :layout =&gt; 'layouts/application')
&lt;br /&gt;  end
&lt;br /&gt;end
&lt;br /&gt;&lt;/code&gt;
&lt;br /&gt;Redefine the response function in the Handler class so that it calls upon this controller to generate the response:
&lt;br /&gt;&lt;code&gt;ErrorResponseController.action(:index).call(@env)&lt;/code&gt;
&lt;br /&gt;The error message should now be rendered within the default layout of the site.
&lt;br /&gt;&lt;h2&gt;Regular logging&lt;/h2&gt;Even with your own error handler you may want to continue having the errors logged to the default log file.
&lt;br /&gt;If you want this, add this function to the Handler class:
&lt;br /&gt;&lt;code&gt;
&lt;br /&gt;def log_error(info)
&lt;br /&gt;  message = &quot;#{info[:class_name]} (#{info[:message]}):\n  &quot;
&lt;br /&gt;  message += Rails.backtrace_cleaner.clean(info[:trace].split(&quot;\n&quot;)).join(&quot;\n&quot;)
&lt;br /&gt;  Rails.logger.fatal(message)
&lt;br /&gt;end
&lt;br /&gt;&lt;/code&gt;
&lt;br /&gt;Add this line to the handle_exception function:
&lt;br /&gt;&lt;code&gt;log_error(parsed_error.relevant_info)&lt;/code&gt;
&lt;br /&gt;That will log an error to the log file that looks identical to the one Rails creates by default, without any filtering applied.
&lt;br /&gt;&lt;h2&gt;Keeping track of who triggered the request&lt;/h2&gt;In applications that has user accounts it is usefull to keep track of who experienced the error. If a critical error occurs it can enable you to contact the user directly. I once had an incident where users got an error page displayed after pressing &quot;confirm order&quot;, which is about as bad as it gets, and knowing the login name of the ones who got this error enabled me to contact each one and tell them that the order went through OK.&lt;/p&gt;

&lt;p&gt;Add a new function to the Parser class:
&lt;br /&gt;&lt;code&gt;
&lt;br /&gt;def user_info
&lt;br /&gt;  if(@controller.respond_to?(:current_user))
&lt;br /&gt;    current_user = @controller.current_user
&lt;br /&gt;    [:login, :username, :email].each do |field|
&lt;br /&gt;      return current_user.send(field) if(current_user.respond_to?(field))
&lt;br /&gt;    end
&lt;br /&gt;  end
&lt;br /&gt;  return nil
&lt;br /&gt;end
&lt;br /&gt;&lt;/code&gt;
&lt;br /&gt;I made the function probe for fields on the user object, as I dont universally use the same login field in all my apps. If you dont always use &quot;current_user&quot; you can easily expand the function to probe for the helper method as well.&lt;/p&gt;

&lt;p&gt;Add the line below to the relevant_info function and add the new field to the database table.
&lt;br /&gt;&lt;code&gt;info[:user_info] = user_info&lt;/code&gt;
&lt;br /&gt;The initializer on the Parser class must be expanded to take the controller instance:
&lt;br /&gt;&lt;code&gt;
&lt;br /&gt;def initialize(exception, request, controller)
&lt;br /&gt;  @exception = exception
&lt;br /&gt;  @request  = request
&lt;br /&gt;  @controller = controller
&lt;br /&gt;end
&lt;br /&gt;&lt;/code&gt;
&lt;br /&gt;and finally, the handle_exception function must fetch the controller instance and pass it to the handler
&lt;br /&gt;&lt;code&gt;
&lt;br /&gt;controller = @env['action_controller.instance']
&lt;br /&gt;parsed_error = Parser.new(@exception, request, controller)
&lt;br /&gt;&lt;/code&gt;
&lt;br /&gt;That's it. You can get the entire code of exception_handler.rb &lt;a href=&quot;/code/exception_handler.rb&quot;&gt;from here&lt;/a&gt;. I defined all the code in one file here to keep the handler easily contained. It's a lot cleaner to split this up into several files and keep it contained as a gem/plugin instead.&lt;/p&gt;

&lt;p&gt;You can use this code as a basis for making your own error tracking system. It wouldnt take a lot of work to extract this into a gem and have all your applications store error messages in the same database. With a simple web front on top of that you have a pretty decent system in place already that you can modify and expand as needed.&lt;/p&gt;

&lt;p&gt;Happy bug hunting!&lt;/p&gt;</content>
    <author>
      <name>Sharagoz</name>
    </author>
  </entry>
</feed>
