Paul Barry

Hanami, a better Rails?

March 22, 2020

For some time now, I have been observing from afar Hanami, the framework previously known as Lotus. Hanami is promoted as a “modern web framework for Ruby”. What I see in Hanami is a new version of Rails re-designed from the ground up. It is still a full featured framework that has everything needed to build web applications, actions, views, layouts, templates, mailers, models, ORM, etc. So this isn’t like Sinatra or Merb, a lightweight framework that only is useful for very simple web application, it’s a batteries-included full-fledged web framework.

Hanami differs from Rails in several ways. First is the idea that each component of the framework should stand on its own. This is something that has always bugged me about Rails. It is very hard and unintuitive to use most of the components of Rails in a standalone, outside of Rails way. Not that you really do need to do this a lot, but where I did find this to be annoying is when debugging issues where you need to go into the internal implementation of Rails. I always found it to be unnecessarily complicated. I would often ask myself “why is this this hard?” and “why is there this much code required to do X?”.

For example, why can’t you just instantiate a controller, call it and get the response? There are several components like this, and as a side project, I started implementing things like this on my own. For example, I created Rack::Action. The idea is that each action is its own class, instead of multiple actions per controller. If you want to share functionality, you use inheritance. Each action ends up being a Rack app. It’s small (few hundred lines of code), fast and easy to use and understand. So I was excited to see that Hanami has actions that work the same way.

Next is routing. Now that each action is its own Rack app, it’s easy to think of routing as just having a router this is also itself a Rack app and all it does is find the right Rack app, call it and then return that response. So this is what lead me to create Rack::Router. Again, it’s small (few hundred lines of code), fast and easy to use and understand. You can write a few lines of standard Ruby, instantiate a router and use it, without even having to generate a project. And again in Hanami, the router works very similar.

So I’ll go on to views and templates. This is another one that bothers me about Rails. Why can’t I just instantiate a class and call a method to render a template? Do you know how to do that in Rails? Could you go into the console and just call a method where you give it a Hash and the name of template and it would give you the rendered result? This is why I created Curtain. Again, same philosophy here, a simple to use standalone component, small, fast, etc. This one also has a design difference from Rails, where you have a class that is called a view, that is separate from the actual template. Rails calls templates “views”, which never really made sense to me. In the terminology I use in Curtain, a View is the object that is the context that the template is rendered within. Views eliminate the need for “helpers”, because you can just define methods on the view and then call them from the template. You can organize your helpers into modules and include them in specific views as needed. This is another one where Hanami follows the same philosophy as Curtain, including separate view classes from the template.

Another thing to call out is code reloading. To avoid having to restart your application in development, Rails has a lot of code to take care of that for you. A much simpler way of achieving the same effect is to use Shotgun. This is what Hanami recommends and what I have used in non-Rails Rack applications in the past as well. It is another prudent choice here by Hanami to just encourage the use of Shotgun rather than complicate the framework with this functionality.

The last thing that I’ll point out that is something where I’ve independently come to the same conclusion as Hanami is what Hanami calls Interactors. I have to admit that I wasn’t familiar with the term Interactor until I saw it in the Hanami docs, but I’m definitely familiar with the concept. The basic idea here is that for somewhat complex business or persistent logic, that involve maybe wrapping multiple persistence calls in one transaction, instead of having that pollute your models with class or instance methods, write an Interactor for each of these operations. In my applications, I’ve been calling these things “Services” and I’ve heard that same terminology used by others. I have found this pattern to be a huge improvement in code testability, reusability and organization. This is such an improvement in the quality of application architecture that it is a bit of head scratcher to me that there isn’t something in Rails like this, if for no other reason to standardize and encourage the pattern.

I haven’t had a chance to build a real application with Hanami yet, but I’d like to give it a try at some point. There are so many design decisions in Hanami I agree with and have considered myself in the past. 7 years ago, I started to work on a framework that I was calling Sharp that pulled together all the components that I have mentioned in this article in a similar way to what Hanami has. I never got the opportunity to get it to be production ready, “life got in the way” as they say, but it is nice to see something complete and polished that is similar philosophically in so many ways.

Posted in Technology | Topics Ruby, Rails

How to spy on a Hash in Ruby

February 24, 2010

Let’s say you’re dealing with a large Rails codebase and you’ve got a Hash stored in a global variable or a constant and you want to know who is changing that Hash. Here’s a contrived example:

IMPORTANT_STUFF = {
  :password => "too many secrets"
}

def change_password(h)
  h[:password] = "FAIL"
end

def print_password
  puts IMPORTANT_STUFF[:password]
end

print_password
change_password(IMPORTANT_STUFF)
print_password

Here it’s pretty obvious where the Hash gets changed, but as I said, imagine you are trying to figure this out in a much larger codebase. Something is changing the value of IMPORTANT_STUFF and you don’t know what. So how do you figure out what is? Easy, you do what Lester Freeman would do!

Lester Freeman from The Wire

We set up a sting! We put a wire tap on IMPORTANT_STUFF and monitor all communication with IMPORTANT_STUFF. So how do we do that? Let’s create a class that proxies all communication with a Hash:

class HashSpy

  def initialize(hash={})
    @hash = hash
  end

  def method_missing(method_name, *args, &block)
    puts "***** hash access"
    puts "  before: #{@hash.inspect}"
    r = @hash.send(method_name, *args, &block)
    puts "  after: #{@hash.inspect}"
    puts "  backtrace:\n    #{caller.join("\n    ")}"
    r
  end

end

This uses a couple of interesting Ruby techniques. First, we just pass the actual Hash to the constructor. Then, we use method missing so that any method that is called on the HashSpy will be then called on the Hash and the return value of that method call with be called instead. Note that in Ruby 1.8, this isn’t a transparent proxy because if you called class on the HashSpy, you would get HashSpy, not Hash. In Ruby 1.9, you can have your object inherit from BasicObject, which won’t have those methods, making it easier to be a transparent proxy. In Ruby 1.8, you can use Jim Weirich’s Blank Slate pattern

In HashSpy’s method missing, we use caller to get a backtrace of the current call stack, which will tell us who the perpetrator is.

So, if we just change IMPORTANT_STUFF to be created like this:

IMPORTANT_STUFF = HashSpy.new(
  :password => "too many secrets"
)

Now when we run the program, we’ll get output something like this:

***** hash access
  before: {:password=>"too many secrets"}
  after: {:password=>"too many secrets"}
  backtrace:
    hash_spy.rb:27:in `print_password'
    hash_spy.rb:30
too many secrets
***** hash access
  before: {:password=>"too many secrets"}
  after: {:password=>"FAIL"}
  backtrace:
    hash_spy.rb:23:in `change_password'
    hash_spy.rb:31
***** hash access
  before: {:password=>"FAIL"}
  after: {:password=>"FAIL"}
  backtrace:
    hash_spy.rb:27:in `print_password'
    hash_spy.rb:32
FAIL

And by reading through the output, we can see that the second time the hash is accessed is when the value is changed, so the perpetrator is on line 23 of hash_spy.rb in the change_password method. Here’s the entire script in one gist for reference.

Posted in Technology | Topics Ruby, Rails | 4 Comments

Customizing Generators in Rails 3

January 13, 2010

As you probably already know, Rails 3 is just around the corner. There are some pretty nice features being added and one of them is the ability to customize the way the generators work. I personally prefer Haml over ERB, RSpec over Test::Unit and Factory Girl over Fixtures. So let’s see how we can configure a Rails 3 app to do that.

First, follow Yehuda’s instructions on how to create a Rails 3 app. Next, you have to tell Rails that you want to use Haml, RSpec and Factory Girl. First, add this somewhere in the Gemfile:

gem "haml"

only :test do
  gem "rspec"
  gem "rspec-rails"
  gem "factory_girl"
end

Then, re-run the bundler and initialize the Haml plugin:

$ gem bundle
$ bin/haml --rails .

Finally, you have to install the custom generators for the frameworks that you want to use. I found a repo on github that already had RSpec, so I forked it and added Haml and Factory Girl. Clone the repo into the lib/generators directory of your app:

$ git clone git://github.com/pjb3/rails3-generators.git lib/generators

Now, in the config/application.rb file in your app, near the bottom there is a section related to config.generators. Put this in that section:

config.generators do |g|
  g.template_engine :haml
  g.test_framework :rspec, :fixture => true, :views => false
  g.fixture_replacement :factory_girl, :dir => "spec/factories"
end

Here is where we reap the benefits of the modularity in Rails 3. What this says is that we want to use Haml as the template enging, we want to use RSpec as the test framework and we want to generate fixtures with our generated specs, but we don’t want to generate view specs and that instead of fixtures, we actually want to use factory girl and we want the factories to be put into spec/factories. Whew! So does this all work?

$ script/generate rspec:install
$ script/generate scaffold person name:string dob:date age:integer male:boolean bio:text

At this point you should see that Rails has generated what we want, which is scaffolding that uses Haml for the views, RSpec for the tests and Factory Girl for the fixtures. Run the migrations, start the server and open the browser http://localhost:3000/people to see your scaffolding in action.

Now if you try to actually run rake spec, you’ll get an error, at least I do. I’m not sure that RSpec 1.X is going to ever work with Rails 3. I think the intent is for RSpec 2 to be compatible with Rails 3, so keep an eye out for that.

Ain't Nothing But A G Thang

October 9, 2009

You’ve probably seen more than a few articles on the web showing how to build a Rack app. If not, here’s a good one to start with. You’ll quickly see that building a Rack app is really simple, which is why Rack is awesome, because it’s simple. But what about writing a Rack-compliant server? Well it turns out that is pretty easy as well.

I just pushed a little Rack-compliant HTTP Server that I wrote using GServer to github. The whole thing is less than 200 lines of code. The core of it is short enough that I can explain how it works here.

First, GServer. GServer, which is short for “Generic Server” makes it pretty simple to create a multithreaded TCP Server. Taking out some error handling code, here’s what the GServer looks like for our Rack HTTP Server:

module GThang
  class HttpServer < GServer

    attr_reader :port, :rack_app

    def initialize(options={})
      @port = options[:Port] || 8080
      @rack_app = options[:rack_app]
      super(@port)
    end

    def serve(socket)
      RackHandler.new(socket, rack_app, port).handle_request
    end

  end
end

So all there is to a GServer is basically a serve method. This will be called each time a client connects to the server. The argument to the method is the client socket connection. You read and write data from the socket as you see fit for your application. As you can see here, we just pass the socket, along with the rack app and the port to the RackHandler initializer and then call handle_request on that. We’ll look at how you setup the rack app in a minute, but first let’s take a look at the meat of what the RackHandler does. The handle_request method looks like this:

def handle_request
  return unless add_rack_variables_to_env
  return unless add_connection_info_to_env
  return unless add_request_line_info_to_env
  return unless add_headers_to_env
  send_response(app.call(env))
end

So what happens is the various add_ methods build up the rack environment. Once the environment is ready, we call the rack app. The rack app responds with the standard 3 element array, which we pass off to the send_response method, which writes the actual http response to the client. Take a look at the full code for this on github for the details.

Now the fun part is that we now have a fully functional HTTP server that is capable of acting as a file server or serving a Rails app. All we have to do is give the HttpServer the correct Rails app. If you look in the examples, you see this for the file server:

GThang::HttpServer.run(
  Rack::CommonLogger.new(
    Rack::Lint.new(
      Rack::Directory.new(root, Rack::File.new(root)))),
  :Port => 8080)

Now I choose to write it this way to make it clear what is actually happening. You will normally see the builder DSL used to configure a rack app, which would look like this:

use Rack::CommonLogger.new
use Rack::Lint.new
use Rack::Directory.new(root)
run Rack::File.new(root)

This is obviously a lot cleaner, but to understand how Rack works, you have to realize that all this is doing is what we see in the first example. A Rack app with Rack middleware is simple a chain of apps that call the next app in the chain, possibly modifying the environment or response before or after the rest of the chain is called.

So there you have it, beauty in simplicity.

Posted in Technology | Topics Rack, Ruby, Rails | 8 Comments

ExtJS On Rails

September 23, 2009

If you are looking to give ExtJS a spin, I’ve created a Rails Application Template to setup a Rails app with ExtJS installed. To use it, just do:

rails -m http://tinyurl.com/extjs-rb my-extjs-app

To see a sample of this in use, take a look at this Rails app. It is a port of Chapter 1 of ExtJS In Action to Rails. Assuming you have Rails 2.3.2 installed, you should be able to download the Rails app from that git repo, run script/server and then try out the app at http://localhost:3000.

UPDATE: This code actually refers to the code in the sample chapter on the Manning website. Chapter 1 in the latest version of the book has actually been completely re-written, so I’ve included the sample chapter in the git repo. Also be sure to check out the author’s blog which covers the development of the book.

Posted in Technology | Topics Javascript, Rails, ExtJS