Handling strange Rails URLs

Came across an interesting situation where my Rails application was going to be receiving URLs with characters like (dash) and . (period or dot). Something like this:

http://example.com/my_controller/action-with-odd.characters

Ruby doesn’t allow dashes or periods in identifiers, so this was going to cause a problem with method naming. I couldn’t figure out how to handle this from the web and so I dove into the source and found that when the action method doesn’t exist Rails calls a catch all method called perform_action. Adding my logic to this method worked well. Looks something like this:

def perform_action
  ...
end

[tags]rails urls,ruby identifiers[/tags]

Handling Rails 404 and 500 errors

I spent a couple of hours trying to figure out how to handle 404 and 500 errors in Rails. This is not simple and actually really annoying. Hopefully future versions clean this up because right now it sucks pretty badly. Anyways, I found a page on the wiki and some other blogs, but the issue was that they wouldn’t handle all the cases. So, here’s the solution:

1. Edit your app/controllers/application.rb file and add these three methods:

  def rescue_404
    rescue_action_in_public CustomNotFoundError.new
  end

  def rescue_action_in_public(exception)
    case exception
      when CustomNotFoundError, ::ActionController::UnknownAction then
        #render_with_layout "shared/error404", 404, "standard"
        render :template => "shared/error404", :layout => "standard", :status => "404"
      else
        @message = exception
        render :template => "shared/error", :layout => "standard", :status => "500"
    end
  end

  def local_request?
    return false
  end

The first method will be explained in the next step. The second method is the method that Rails calls to handle most errors. This method will not capture a certain class of errors where neither the controller nor the action requested exist. The third method tells rails to stop sucking. Normally Rails handles requests made to localhost or 127.0.0.1 differently than all others. This might be for debugging purposes, but it sucks when testing error handling.

2. Edit config/routes.rb and add this line TO THE END OF THE FILE:

  map.connect '*path', :controller => 'application', :action => 'rescue_404' unless ::ActionController::Base.consider_all_requests_local

This tells Rails that if it can’t find any other route to handle the request (i.e. the *path) it should call the rescue_404 action on the application controller (the first method above).

3. Edit config/environments/development.rb and add this line:

ActionController::Base.consider_all_requests_local = false

This additionally tells Rails to stop sucking and stop handling requests to localhost and 127.0.0.1 differently.

Anyways, happy coding.

Programming languages IM conversation

Here’s a conversation between James and I that started on dynamic languages and went on a tangent about languages, revolutions and evolutions.
Ponch: I’ve just been working on Naymz stuff lately. Also tinkering with Groovy and using it with an MVC
James Humphrey: haven’t heard any good things about Groovy
James Humphrey: hearing a lot of bad things though
Ponch: Like what?
James Humphrey: can’t remember exactly…I think I remember something about it was just a pain in the ass to code in it. trying to remember specifics
Ponch: I think Groovy is fine for what it is, but I prefer ruby mostly.
James Humphrey: I think one was, there’s no good IDE out there for it
Ponch: Eclipse is really good, even has debugging for groovy
Ponch: Ruby is way behind in the IDE space.
Ponch: Groovy is way ahead.
Ponch: Groovy is much easier since it is just converted to Java. Ruby is different because it is a lot more dynamic
Ponch: So, you can’t really make a java class out of a ruby class
James Humphrey: I dunno, can’t really remember. I think most of the issues I read were programmatic. You know, loosely typed scripting issues; too much power given to the programmers, convention issues, etc
Ponch: haha those dudes would definitely hate ruby then.
James Humphrey: which dudes?
James Humphrey: oh, the dudes I read the artices ffrom?
Ponch: There are a lot of good articles about how loosely typed languages sometimes are better for large projects.
Ponch: Chcek out this thread I started at Groovy user list: Here’s the thread list that shows the replies:
http://www.nabble.com/codehaus—Groovy-f11866.html
and here is the post:
http://www.nabble.com/Trying-to-get-a-sense-for-dynamic-groovy-tf2665364.html
Ponch: It might be the largest thread. not sure though. hehe
James Humphrey: wtf is ‘duck typed’
Ponch: it is a loosely typed term. Here’s an example:
class Foo {
def foo() {}
}
class Bar {
def foo() {}
}

def someMethodThatCallsFoo(obj) { obj.foo() }

someMethodThatCallsFoo(new Foo())
someMethodThatCallsFoo(new Bar())
Ponch: I can call the method with any object that has that method. Only way to do this in Java is use an interface and have everything implement that interface and then the method takes the interface. Or using reflection (eeck!)
Ponch: That’s why most folks favor naming conventions heavily in dynamic languages, that way you can call methods that use length() and pass them String, Array, List, Map, anything that has that method on it.
James Humphrey: this is exactly why I hate scripting languages. I don’t understand any of this nor do I want to
Ponch: Man your already an old java meiser (sp?) hehe
James Humphrey: no, I just don’t like loosely typed languages. Usually, scripting languages are loosely typed. It’s just too hard to figure out what’s going on
James Humphrey: there’s just way too much freedom to write bad code and causing pain for maintaners
James Humphrey: er maintainers (ppl who do maintenance on the code)
Ponch: That is the most common misconception I think. Most people feel that way about them
Ponch: The freedom allows for less coders, less coder and easier maintenance (usually).
Ponch: sorry less code
James Humphrey: imo, there’s a programming semantic continuum. On the far right is DSLs and the far left SCripting languages. In the middle you have things like Java, C#, etc.

Imo, we should be moving more towards DSLs. SCripting languages are just too hard to figure out, maintain, and document. Sure, it’s easy to program in it…that’s the problem though
James Humphrey: contiuum is probably a bad model
James Humphrey: evolution maybe. dunno, you know what I mean though I think
Ponch: Many believe that DSLs are built on top of dyNamic languages.
Ponch: You can find a lot of information about using ruby to build DSLs very quickly
Ponch: To me it is more about features of a language because in the end they all do the same thing, compile down to assembler.
James Humphrey: I agree with that. I just think that you can evolutionize languages without making them loosely typed
Ponch: You can go both ways in evolution. C# is evolution on Java. Ruby is evolution on Perl
James Humphrey: and, you’re right. Honestly, I could care less about what’s underneath the language (usually) because in the end I know that it’s all assembly anyway. What’s important to me is not just how it’s coded but how it’s maintained
Ponch: my motto is use the right tool for the job. I don’t like writing java to handle a simple command line search and replace. Much better to use ruby. Don’t like using ruby to build a text parser, to slow.
James Humphrey: and, in my limited experience, it just seems to me that maintaining scripting languages are a pain in the ass because you never know what you’re going to get. One person does it this way, another does it that way, which leads to confusion
Ponch: Usually that doesn’t happen though.
Ponch: The code is concise enough that to understand it takes very little time.
Ponch: I figure the more tools I have in my toolkit the better off I am.
Ponch: That is why I’m learning groovy and python and c#, so I can figure out how they all work in case I need them
James Humphrey: it’s like, why create the allen wrench? now I have to have more tools in my toolbox to get a job done to maintain something. ;). I think there’s a fine line with evolving and just creating more shit
Ponch: haha you definitely carry a sentiment that many others do. The problem in our business is productivity. How can I get something done faster, better, more well tested, more maintainable, etc. Java just doesn’t fit the bill in all cases. Nor does C++ or Ruby or anything. You could use Java to make a 3D game, but you’ll probably spend more time doing it, and have worse results. The key is to figure out how to be the most productive and often that means looking at lots of different languages, frameworks, tools, IDEs, etc.
James Humphrey: I think scripting languages have their use, don’t get me wrong. I also think that they are probably a natural process to evolution within the software world. I just don’t think they are the revolution that we’re all waiting for
Ponch: I agree with that. I don’t think there ever will be one of those.
Ponch: It will just be a constant refresh of ideas and principles
James Humphrey: like anything yeah, but I disagree. I think something (like c, like java) will come to revolutionize the way software engineers do things
Ponch: maybe, I wouldn’t discount that, but I don’t think Java was a revolution. It was just C++ with a few tweaks.
(09:42:06 AM) James Humphrey: maybe yeah. I dunno though: garbage collection, exception handling, pure OO….there wasn’t much of that around, or at the very least there wasn’t anything getting a lot of visibility
Ponch: You are right about those things, but C++ had garbage collection it was just manual and dangerous, it had exceptions they just sucked and Java still isn’t pure OO because it has primitives (unlike ruby).
James Humphrey: true, I should have said ‘automatic garbage collection’ (which isn’t all that to be honest). And, yeah, java primatives…/shrug
Ponch: Maybe a revolution will happen, but it will be something like IAL, which BTW sounds like Isle, which is kinda a cool name.
James Humphrey: whoa, never looked at it that way before
Ponch: A DSL for a very common domain (web aps)
James Humphrey: that would rule
James Humphrey: it’s also very very very very fucking complicated. even with your and my experience combined, we can’t figure it out
Ponch: probably not completely, but we can make good steps and then get people interested and helping out.
James Humphrey: and we have over what…at least 15 years combined web experience (I have 9 or 10 I think)
Ponch: I started building web apps in 98 I think.
Ponch: Maybe 97. hmmm not sure
Ponch: so 8-9 years for me
Ponch: BTW this conversation is really good. Mind if I post it?
James Humphrey: sure, I don’t mind
James Humphrey: good luck organizing the flow of this though
James Humphrey: hehe
Ponch: I was just gonna copy and paste. 😉
James Humphrey: haha
James Humphrey: ugh
James Humphrey: kinda funny…you spend your ‘free’ time blogging. I spend my ‘free’ time playing games
Ponch: yeah, moved from games to dork-dom
Ponch: hehe

Ruby reflection 'requires' a lot

I’m been doing some work in Ruby to build a parser framework and I wanted to have pluggable parsers from the command line. I figured this would be simple because in Java it actually is pretty simple, as long as the pluggable parser is in the classpath. Well, with Ruby, this isn’t quite the case. Even if a class is in the load path, it still isn’t visible until it has been loaded either via the load method or the require method on Kernel. This is annoying and something I wasn’t used to. But a quick hackery fixes this nicely:

# Load all the local rb files
Dir.glob("*.rb").each do |d|
  load(d) unless d == $0
end

This loads every *.rb file in the current directory into the current Ruby process. Then you can do some String reflection magic to load a class:

parser = eval(ARGV[0] + "Parser.new(ARGV[0].downcase())")

This allows me to call my scriptage and pass in the prefix of the class name like this:

ruby scriptage.rb MySpecial

This will then instantiate an instance of MySpecialParser. I could have iterated over all the constants in the entire Ruby process and found the symbol I needed and then called new on that, but that sucks. Eval is much cleaner in this case.

In fact, in Java loading a class by name is simple:

Class.forName("com.inversoft." + prefix + "Parser");

In Ruby this doesn’t work so well. You have to first load all the .rb files like I did and then use eval. They really should add something to Class or ObjectSpace or Kernel to do all this for you. In fact, I think in 2.0 load_path should be able to load all files in the load path via reflection without any requires or load crapola.

Eeck more Ruby parser crapola!

Oh my god! This one pass Ruby parser is really annoying. Here’s todays example that doesn’t compile:

DICTIONARY = create_dictionary
def MyClass.create_dictionary
  ...
end

Yep, you got it, this blows up with a nice error message stating that the variable or method named create_dictionary couldn’t be found. Move the constant definition below, everything is fine. Lame.

RoR plugin woes

I’m been doing a lot of work with RoR plugins trying to make things generic. The RoR plugin mechanism is just plain horrible. Plugins do not work like most ruby classes because they are loaded in a slightly convoluted way and most errors end up getting swallowed by RoR. Of course this can be fixed, but it is really annoying and makes programming even more stone-age than it should be. You end up with errors like this:

/usr/lib/ruby/gems/1.8/gems/activesupport-1.3.1/lib/active_support/dependencies.rb:123: in `const_missing': uninitialized constant AjaxValidation (NameError)
        from /usr/lib/ruby/gems/1.8/gems/activesupport-1.3.1/lib/active_support/dependencies.rb:133:in `const_missing'
        from script/../config/../vendor/plugins/ajax_validation/init.rb:3: in `load_plugin'
...

The issue here is NOT that AjaxValidation isn’t defined. Instead, it is that in the definition of AjaxValidation an error has occurred and this caused the load of AjaxValidation to completely fail AND there is absolutely no logging of the error that caused AjaxValidation to fail. So, you resort to writing to stdout each line of code to figure out where the problem is. That sucks.

Another issue I have with plugins is that I cannot define standard action methods in a plugin. There should be a mechanism for doing this. The issue seems to be that how RoR is handling action method invocation is not standard reflection because this would mean that all methods on the object could be actions. Instead it only allows the methods defined in a controller to be called. This makes sense, but makes life hard on plugin developers.

Ruby Locale 0.1

I wanted a ruby version of the Java Locale object and couldn’t find one, so i created a project for it. Here’s the address:

http://rubyforge.org/projects/locale/

It is pretty minimal, but it does contain all the current ISO country and language codes as well as a simple class for accessing them. It is also in a rails compliant plugin layout so it can just be dropped into the rails vendor/plugin directory.

The unit tests are failing, but it is just a numbering issue, which I’ll fix this afternoon or next week.

Enjoy.

Making jEdit like IntelliJ

First download JDK 1.6 and use that to run jEdit. I also add this tweak to the command line:

-Dsun.java2d.opengl=true

Also, remove the -server option. No clue if that is gonna help at all in JDK 1.6, but things are blazing fast without it and I assume Swing likes it without.

Next, download these plugins:

  1. Buffer Tabs
  2. Project Viewer
  3. SideKick
  4. FastOpen
  5. Ruby (http://rubyjedit.org/download/)

Next, follow the ruby plugin directions to get that up and running. If you are using Java, I would assume that you can find lots of help with that out in the ether.

Also, dock the Project Viewer window on the left of the screen.

I turn on the BufferTabs by default and set them on the right.

Okay, now start binding keys. Here are mine thus far:

Plugin: Project Viewer

Command Key
Show Project Viewer Alt+1

Plugin: FastOpen

Command Key
Show Fast Open Window Ctrl+n

Built-in commands

Command Key
Close current docking area escape
Close Ctrl+F4
Find next F3
Go to line Ctrl+g
Global Options Ctrl+Alt+Shift+s
Join lines Ctrl+Shift+j

This is about all I have thus far, but it looks to be pretty good. I’ll add more as I think of new stuff.

Configuration vs. convention

My buddy Dave Thomas has an interesting blog entry concerning convention vs. configuration. I’ve given it a considerable amount of thought today because it is something that hits you square in the face when switching between frameworks and languages (i.e. WebWork to Rails and back each day).

Both have upsides and downsides and nothing seems to really bring one out as a front runner. Dave’s point about ramp up time is completely accurate. But those configuration nightmares also have that same issue right? No one is really going to memorize what a WebWork validator XML file looks like. Who wants to do that? But they also suffer from double work. The work of coding and the work of configuring, which makes it difficult to compare with convention based programming where configuration is removed.

The major problem I see with convention based programming is always constraints. Of course Rails and Ruby allow you a lot of freedom to modify classes and intercept method calls and stuff like that, which alleviate some of the constraints, but there are constraints. For example, in Rails it is difficult to externalize an action chain and reuse actions for multiple events. Something like this:

Action #1
one -> two -> three

Action #2
four -> three -> five

If each of the steps are atomic units of work and simply state their outcome as success or failure, this makes sense. You can reuse three because it doesn’t know who it chains to. The chaining is externalized into some XML configuration somewhere. You can pull this off in Rails using YAML and some hacking around inside your controllers, but it can get ugly quick. In something like WebWork, this can be handled entirely in the XML configuration without the code changing at all.

Dave’s second point about maintenance seems to me to be an issue with language rather than framework. Creating crazy method-missing handlers and classes that are defined in 15 files are features of languages and this is where I see the cost of maintenance is incurred. Rails itself doesn’t really let you tweak too much. It seems to me that Ruby let’s you tweak just about anything. Of course, not being an expert in either, I won’t speak definitively about that.

Dave’s last point about Perl I’ve kinda covered already. This happens with configuration and convention. However, with IntelliJ and configuration, you get some pretty good help and code completion that can really make the re-learning much faster. You still have to recall how to code on the configuration side as well as the convention side and nothing can really make that less teadeous and error prone except documentation and good exception messages.

I’m not certain that I fully grok meta-frameworks per se. But I will say this, I have developed systems that are both configuration and convention and they always seem to make me happy. To this day I’m still floored at how few frameworks do this and even more floored and how few people have used mine even if they realize that it supports both styles. The JavaLobby link on Dave’s blog entry covers this a little bit but I think folks still lack the understanding of configurable/overridable conventions.

Take for example the Savant 2.0 alpha I released. This system I love for its use of convention and configuration. If you want to get up and running fast, you can run Savant to create a project layout for you (or just follow the convention for layouts and build one yourself) and that’s it. You can now build, clean, jar, deploy, whatever. The standard layout (the convention) is like this:

src/java/main = The main source files that will be included in the JAR
src/java/test = Unit tests for the source files (not included in the JAR)
target/classes/main = The location where the main source files are compiled to
target/classes/test = The location where the test source files are compiled to
target/jars = The location where the JARs are placed after they are built

Its simple, straight-forward and works with absolutely NO configuration. This is where it gets good though (and personally I feel really Savant excels past Maven and Ant). Let’s say you can’t use the convention or need to tweak it. Let’s say you have this project layout:

src/java/library-1
src/java/library-2
src/java/shared

Now the Maven folks will say, “that’s three projects with separate JARs” and perhaps it is, but you can’t change it right now or you can’t change it ever and really would like a nice build system to help you out. Well, Savant to the rescue:

java-project.xml
--------------------
<java-project>
  <directories id="library-1">
    <source location="src/java/library-1"/>
    <output location="target/classes-1"/>
  </directories>

  <directories id="library-2">
    <source location="src/java/library-2"/>
    <output location="target/classes-2"/>
  </directories>

  <directories id="shared">
    <source location="src/java/shared"/>
    <output location="target/classes-shared"/>
  </directories>

</java-project>

This configuration overrides the default project structure and allows you to define as many source directories, build directories, test directories and JAR files as necessary. It even lets you define which JDK to use to compile each one if you want.

The moral of my story is that I think frameworks should always work based on convention right out of the box with as little configuration as humanly possible. Then if you want to tweak, slap down some configuration and go to town! Perhaps this is the meta-framework that Dave is talking about or perhaps not. Either way, this to me seems like a good solution that reduces the overhead as much as possible while still allowing the flexibility to tackle tough situations and problems.

New Inversoft Product

I’ve finished launching my latest Inversoft product – The Inversoft Bad Word Database. The website is written entirely in Ruby on Rails and uses PayPal for purchases. All and all the coding was extremely straight forward and simple. Here’s the address:

http://badwords.inversoft.com

The product idea essentially sprouted from my work on https://www.naymz.com where I need to add some filtering logic to the site so that folks could not enter any restricted words (cuss, slang, swear, superlatives, derogatory, etc.) when constructing their ad for the search engines. Google, Yahoo and the others reject advertisements whose content is not valid or contains restricted words. As I built out the functionality for Naymz, I wanted to test it with some data. Unfortunately there was no data to be found.

I did quite a bit of searching and found that there were services out there who offered a web service you would sent the content to and they would validate it. This just didn’t make sense to me since I wanted to have as few external dependencies as possible and most of these sites could not guarentee reliability, up-time or accuracy of the content filtering. I also found a few other sites that had lists of words, but they were not in a database friendly form. These websites also suffered from the fact that some words I would not consider “restricted” at all and yet again the data would need major scrubbing. Another site I found offered hundreds of thousands of words entered completely by its users. This was probably the worst considering that I had no way of making a determination of which words I wanted to load and which I didn’t because as we all know users will add anything when there aren’t any checks and balances.

What I really wanted was a list of words, with definitions, ratings and categories. So, in my spare time I started building this out. I surfed the web and found all the words I could. I started adding definitions to them as well as a ranking system that would allow applications to adjust the level of leniency they wanted to allow. I also found that many times a list of alternate spellings was need because folks are smart and can beat filters by typing something like sh7t.

After quite a bit of data scrubbing, tweaking and coding, I finished the website and did an initial data load. The initial load contained approximately 500 words and another 500+ misspellings (or something close). The website is live and I’ll be adding words to the database each day and also be building out an multi-language version that contains bad words from as many languages as possible. Check it out and feedback is much appreciated.