Friday, September 18, 2015

wkhtmltopdf config on Mac

I ran into a snarl of a problem trying to get wkhtmltopdf working on my mac.  The long of the short of it, these instructions (should) work. 


Get the right version installed via brew:
brew uninstall wkhtmltopdf
cd /usr/local/Library/Formula/
git checkout https://gist.github.com/389944e2bcdba5424e01.git /usr/local/Library/Formula/wkhtmltopdf.rb
brew install wkhtmltopdf

WickedPDF needs to point to the development env properly:

# config/development.rb
WickedPdf.config = {
  :exe_path => "/usr/local/Cellar/wkhtmltopdf/0.9.9/bin/wkhtmltopdf",
  :root_url => "http://localhost:3000"}


Make sure you are not running a single threaded application server. In my cause configure unicorn:

# config/unicorn.rb
if ENV["RAILS_ENV"] == "development"  worker_processes 3
end
timeout 30

And last but not least. I'm using RubyMine.  Point the debugging environment to the unicorn config:


I hope this saves someone some time.

Credits:
http://stackoverflow.com/questions/12517640/why-does-pdfkit-wkhtmltopdf-hang-but-renders-pdf-as-expected-when-rails-app-is-k
https://github.com/pdfkit/pdfkit

Tuesday, September 27, 2011

Rails exception handling - Egregious

Version 0.2.9 released to https://rubygems.org/gems/egregious on 10.23.2015
        Added support for exceptions that define a http_status. The exception map can override this.
        This is a good way to allow a raise to specify a http_status using a custom exception.
        The idea for this came from the Stripe::Error exception classes.
        Also updated Gemfile.lock to ruby 2.2.1 and latest dependencies. This is for specs only.

Egregious is a rails based exception handling gem for well defined http exception handling for json, xml and html.

If you have a json or xml api into your rails application, you probably have added your own exception handling to map exceptions to a http status and formatting your json and xml output.

You probably have code sprinkled about like this:
rescue_from CanCan::AccessDenied do |exception|
    flash[:alert] = exception.message
    respond_to do |format|
      format.html { redirect_to dashboard_path }
      format.xml { render :xml => exception.to_xml, :status => :forbidden }
      format.json { render :json=> exception.to_json, :status => :forbidden }
    end
  end

This example is straight from the CanCan docs. You'll notice a couple of things here. This handles the CanCan::AccessDenied exception only. It then will redirect to the startup page, or render xml and json returning the http status code of :forbidden (403). You can see one of the first features of the Egregious gem. We extend Exception to add the to_xml and to_json methods. These return a well structured error that can be consumed by the API client.
Exception.new("Hi Mom").to_xml

returns:
"Hi MomException"

Exception.new("Hi Dad").to_json

returns:
"{\"error\":\"Hi Dad\", \"type\":\"Exception\"}"

So that's pretty handy in itself. Now all exceptions have a json and xml api that describe them. It happens to be the same xml and json that is returned from the errors active record object, with the addition of the type element. That allows you to mix and match validations and exceptions. Wow, big deal. We'll it is. If you are writing a client then you need to have a very well defined error handling. I'd like to see all of rails do this by default. So that anyone interacting with a rails resource has a consistent error handling experience. (Expect more on being a good REST API in future posts.) As a client we can now handle errors in a consistent way.

Besides the error message we would like a well defined mapping of classes of exceptions to http status codes. The idea is that if I get back a specific http status code then I can program against that 'class' of problems. For example if I know that what I did was because of invalid input from my user, I can display that message back to the user. They can correct it and continue down the path. But if the Http status code says that it was a problem with the server, then I know that I need to log it and notify someone to see how to resolve it.

We handle all exceptions of a given class with a mapping to an http status code. With all the most common Ruby, Rails, Devise, Warden and CanCan exceptions having reasonable defaults. (Devise, Warden and CanCan are all optional and ignored if their gems are not installed.)

As of 0.2.9 you can also define a method named 'http_status' on the exception and it will be used as the status code. This is a nice pattern that allows you to raise an exception and specify the status code. The Egregious::Error allows you to do this as a second parameter to initialize:
  raise Egregious::Error.new("My very bad error", :payment_required)

If the problem was the api caller then the result codes are in the 300 range. If the problem was on the server then the status codes are in the 500 range.

I'm guessing if you bother to read this far, you are probably interested in using Egregious. Its simple to use and configure. To install:

In you Gemfile add the following:
gem 'egregious'


In your ApplicationController class add the following at or near the top:
class ApplicationController < ActionController::Base
  include Egregious
  protect_from_forgery
end


That's it. You will now get reasonable api error handling.

If you want to add your own exceptions to http status codes mappings, or change the defaults add an initializer and put the following into it:
Egregious.exception_codes.merge!({NameError => :bad_request})

Here you can re-map anything and you can add new mappings.

Note: If you think the default exception mappings should be different, please contact me via the Egregious github project.

We also created exceptions for each of the http status codes, so that you can throw those exceptions in your code. Its an easy way to throw the right status code and setup a good message for it. If you want to provide more context, you can derive you own exceptions and add mappings for them.

Here is an example of throwing a bad request exception:
raise Egregious::BadRequest.new("You can not created an order without a customer.") unless customer_id


Egregious adds mapping of many exceptions, if you have your own rescue_from handlers those will get invoked. You will not lose any existing behavior, but you also might not see the changes you expect until you remove or modify those rescue_from calls. At a minimum I suggest using the .to_xml and .to_json calls io your existing rescue_from methods/blocks.

And finally if you don't like the default behavior. You can override any portion of it and change it to meet your needs.

If you want to change the behavior then you can override the following methods in your ApplicationController.
# override this if you want your flash to behave differently
def egregious_flash(exception)
    flash.now[:alert] = exception.message
end


# override this if you want your logging to behave differently
def egregious_log(exception)
    logger.fatal(
        "\n\n" + exception.class.to_s + ' (' + exception.message.to_s + '):\n    ' +
            clean_backtrace(exception).join("\n    ") +
            "\n\n")
    HoptoadNotifier.notify(exception) if defined?(HoptoadNotifier)
end


# override this if you want to change your respond_to behavior
def egregious_respond_to(exception)
    respond_to do |format|
          status = status_code_for_exception(exception)
          format.xml { render :xml=> exception.to_xml, :status => status }
          format.json { render :json=> exception.to_json, :status => status }
          # render the html page for the status we are returning it exists...if not then render the 500.html page.
          format.html { render :file => File.exists?(build_html_file_path(status)) ?
                                          build_html_file_path(status) : build_html_file_path('500')}
    end
end


# override this if you want to change what html static file gets returned.
def build_html_file_path(status)
    File.expand_path(Rails.root, 'public', status + '.html')
end


# override this if you want to control what gets sent to airbrake
# optionally you can configure the airbrake ignore list
def notify_airbrake(exception)
    # for ancient clients - can probably remove
    HoptoadNotifier.notify(exception) if defined?(HoptoadNotifier)
    # tested with airbrake 3.1.15 and 4.2.1
    env['airbrake.error_id'] = Airbrake.notify_or_ignore(exception) if defined?(Airbrake)
end


We are using this gem in all our Rails projects.

Go forth and be egregious!

Monday, August 8, 2011

Backbone.js and dependent selects

I had a fairly simple development task. Once I've done 20 different ways over the years. I have a select control with customers. When it changes I need to load the set of customer shipping addresses. The client code was a combination of jquery ajax calls and a custom client library for rendering/managing to server restful resources. Pretty quickly the code was getting messy! The problem seemed so easy, but the code did not reflect that. I decided to refactor it using backbone.js. I'm going to show you how I solved this problem in this post. It will not cover the basics of backbone.js. It will cover a simple use case and the design I came up with. It also covers some caveats I discovered with backbone.js.

Finally backbone.js has entered my development toolkit. I was waiting for it without even knowing it. It addresses so many issues with typical client code development.

If you don't know what Backbone is, then I suggest you visit backbone.js. They have a number of tutorials. (Including this one.) The docs are solid. Once you bone up on the basics come on back.

One of the first benefits was the code organization. With Backbone and Jammit (for rails) I can layout a really nice development tree with each class in its own file. Here is the tree I currently have setup:

├── app
│   ├── helpers
│   ├── models
│   │   └── collections
│   ├── templates
│   └── views
└── core
├── helpers
├── models
├── templates
│   └── controls
└── views
└── controls

I am able to have a 'core' set of helpers, models, templates, and views that are used across applications. This is not really a backbone feature, but because of backbone I setup Jammit this way.

The second thing I really loved was the clear separation between model and view. This just feels so natural having done the same thing on the server side for so many years. I'm going to assume you are familiar with the three basic backbone classes that I'm going to use: Model, Collection and View.

Ok the problem is how to have one select change and then once the change occurs, populate another select with a collection based on the first selected. In my case I have the models 'Customer' and 'Address'. A customer has many shipping addresses. So every time a new customer is selected a different set of shipping addresses need to be loaded.

Let's start by taking a look at the models (you'll see they are trivial).

App.Models.Customer = Backbone.Model.extend({});


App.Models.Address = Backbone.Model.extend({});


Ok those were trivial. I like trivial. Now we will look at the collections. These are bound to our select controls.

App.Collections.Customers = Backbone.Collection.extend({
model: App.Models.Customer,
url: '/customers'
});

App.Collections.Addresses = Backbone.Collection.extend({
model: App.Models.Address,
url: '/addresses'
});


Again trivial. We tell the collection what our resource url looks like.

Ok, now we get to the meat of the problem. The views. First I did was create a new view that can render a select based on a collection. It has a few other features I'll point out.

Core.Controls.Select = Backbone.View.extend({

initialize: function(){
_.bindAll(this, 'render','value','triggerDependents','selectControl','startingIndex','addModel');
this.selected = this.options.selected;
this.dependent_views = this.options.dependent_views;
// if the collection changes, re-renders
this.collection.bind("all", this.render);
this.render();
},
events:{
"change": "triggerDependents"
},
defaults:{
collection: [], // The collection to render
selected: null, // The selected model
dependent_views: []// The dependent views to notify on change
},
render: function(){
this.el.html(JST.select(this));
},
selectControl: function() {return this.$("select");},
value: function() { return this.selectControl().val();},
// returns the starting index into the collection
startingIndex: function(){
var index = 0;
if(this.options.blank)index = index +1;
return index;
},
addModel: function(model,selected){
if(selected)this.selected = model;
this.collection.add(model);
return this;
},
triggerDependents: function(event) {

if(this.selectControl().selectedIndex>=this.startingIndex())this.selected = this.collection.at(this.selectControl().selectedIndex-this.startingIndex());
var _this = this;
_.each(this.dependent_views,function(view){
view.trigger(_this.id+"."+event.type, _this);
});
}
});


Let's break this one done a little bit. Backbone has an initialize function that gets called after the object is created. In our initialize we do the following:

First we use the underscore function that will ensure that when our function is called from an event somewhere, the this variable is setup as we expect it. In Ruby or other languages it is impossible to call an object without its self or this setup correctly. Javascript is like C. You can do objects, but they are not really first class citizens. Once you get used to these quirks they are quite serviceable. Second we pull out a couple of class attributes that we expect to be passed into the constructor. By default the constructor puts these into the options hash, because they are really core to our class we pull them up. This is a style thing. I left some other options in the hash, because they were not a fundamental data structure to our view. We then bind to our collection, so if anything changes on the collection it will all our render method and redraw our view. Finally we render the control.

The next thing you see are two hashes: events and defaults. Events in views are jquery events and this hash is a shortcut for binding to them. We bind to the change event and call our function triggerDependents. Note: If you extend this 'class' and define an events hash it will take precedence over the base. The defaults hash is used to pre-populate the options with defaults. I've setup the collection and dependent_views as empty arrays (instead of null). I also setup select as null. Although null is not a very useful default , I think it documents what options the class will accept.

Now in our render we are simply putting into the html element the results of our select template. We are using the _.template method from the underscore library and Jammit is managing the template loading and compilation. Let's take a look at the template:



We are building the select control using the collection, selected and options passed in.

So far so good. Nice and clean.

I'm going to leave the rest of the select control as an exercise for the reader. I do want to point out the triggerDependents function. This will trigger the change event to any dependent_views passed into our constructor. It appends the id of the control so that a dependent view can listen to many controls and catch their events separately. We are using the event binding with backbone.js for this communication. This is independent from jquery events. it seems a little strange at first that they are not related, but the separation makes sense. If you have non-DOM events you want to trigger and handle, then use the model and view .bind and .trigger methods. The events hash does not route these non-dom events, so you have to bind to them in your initialize (or wherever is most appropriate.)

OK so were are we at. We have a select control that will notify any dependent views when they are changed. I think we are ready to actually use them. Let's start with the select for customer addresses.

App.Views.CustomersAddressSelect =  Core.Controls.Select.extend({   
initialize: function(){
Core.Controls.Select.prototype.initialize.call(this);
this.bind("order_customer_id.change", this.loadAddresses);
},
loadAddresses: function(control){
this.collection.reset();
if(control.value()>0){
this.collection.fetch({data: {"parent_key[customer_id]": control.value()}});
}
}
});


Here you see we are binding to the order_customer_id.change event that will get fired by the customer select. In response to this event we reset our collection. (This will cause a render that will disable the control, while we fetch the new records.) Then we fetch the addresses passing the parent key that our controller expects to filter the addresses.

Note: From a security perspective you are going to want some server side check to make sure the given request is allowed to view the given records. That is clearly beyond the scope of this post!

OK now to hook it all up we have the following:

$(function(){
// our empty address collection
var addresses = new App.Collections.Addresses([]);
// Our dependent customer addresses select
var shipping_address_select = new App.Views.CustomersAddressSelect({el: $('#ship_to_address_select'),
id: 'order_shipping_address_id',
name: 'order[ shipping_address_id]',
collection: addresses});
// Our customers collection - populated from the server
var customers = new App.Collections.Customers(<%= raw select.collect{ |ct| {:name=>ct.name, :id=>ct.id}}.to_json %>);
// The customer select, here we pass in the customers collection and the shipping_address_select dependent view.
new Core.Controls.Select({el: $('#customer_select'),
id: 'order_customer_id',
name: 'order[customer_id]',
collection: customers,
blank: 'Select a customer',
// set the shipping_address_select as dependent view
// this will cause all events of the customer select to get
// fired to the dependent controls with the id.event
dependent_views:[shipping_address_select]});
});


Wow that looks pretty simple. We are doing a couple of things here to note:

This is a erb file that is building up the collection of customers on the server. Since we sourced this code from the server, we could save the round trip to fetch the customers. We could have fetched the customers from the client just as easily.

We are binding to existing elements on the page by passing in
el: $(selector)
.

We are passing in the shipping_address_select control as a dependent_view, this hooks up our notifications on change.

Note: if you override the events hash in a derived class you will need to proxy any events that the base class was handling. In my case I ended up deriving a customer select class and wanted to listen to the change event. I lost my dependent view notifications, so in my change function I added a call to triggerDependents. I was not thrilled about this approach. I think preserving events in base classes would be a nice change for backbone.js.

I hope you enjoyed this post. I loved working with Backbone.js and plan on building a full scale view library that makes all the crud operations easy as this.

Cheers - Russell

Monday, February 14, 2011

Rails Stack on OS X

I just got a new MacBook Pro. I spent so much time creating recipes for our production deployment stack, I wanted to reuse that effort. I also wanted a consistent stack from all developers. When I looked around I found smeagol and cinderella. They were close, but of course the stack I wanted was different. Then I found chef-homebrew. This fit the bill perfectly. I could now use my existing recipes (adapted slightly for OS X). So I created a public project that does just that. It provides a default rails stack on OS X. It works with a clean OS X install. Your mileage may vary.

First thing first is to install CodeX from the installation DVD. It is in the Optional Install. (You can register on the apple site and download it, but the download is 3.4 GB.)

git clone git://github.com/voomify/strudel.git
cd strudel
rake strudel:install

Thursday, May 13, 2010

Rails 3, Gems, Rake and Bundler

I ran into a bit of a mystery the other day. I have a new rails 3 (beta3) install.

I'm using Jeweler to build a new gem using Rake. When I install the gem using Rake all goes along as expected. If I go to the command line and type gem list. My gem does not show up. After digging around I found that the gem is getting installed into the ~/.bundler gem location.

If I run gem commands from the terminal then GEM_HOME is as I set it.
If I run gem commands from inside Rake (for my Rails 3 project that has had bundler install run on it) then it is using ~/.bundler/.. as the root of GEM_HOME.

As a result I have a gem that i need to install and re-install a lot. So I have to execute the gem uninstall commands from inside Rake.

Here is what my rake file looks like now:

Monday, May 10, 2010

Rails 3 templates and engines


What I really wanted to do was to setup a rails 3 environment that uses engines to organize modular functionality.

It has ALWAYS been my experience that any project will quickly get out of hand if the organization is not tackled very early. Rails projects get messy fast. If you are disciplined enough to use modules for functionality then you can avoid some of these issues. But I really don't like having module names that I have to use spread out in my code. (Albeit sometimes a module to separate functionality is the best course of action.) I've always wanted to have my own app namespace for my functionality boundaries. Wouldn't this be nice:



With plugins I got closer. With the gemifcation I got a little help packaging my plugins up and defining dependencies.

Then came along the rails engines plugin. I have to admit I liked it, but never felt comfortable diving in. The reason is that engine plugins required a fair amount of twidling bits in rails to get it working right. Whenever that happens I feel a little exposed. (Not that that is always a bad thing!) We'll good news for me...I waited long enough and rails 3 (and rails 2.3 as well) has engines as first class citizens.

I've spend a few days pushing them around and I like it. With a little work I was able to create some rails templates that will generate a new rails engine. I then configure the hosting app Gemfile to include my engine and I'm off and running. Nice!

I thought I'd share the work I've done for those that want to do something similar.

NOTE: All these samples are for postgres and rspec. On testing, there are many options out there. I happen to dig rspec, if you have not tried it you should. If you care about your data you will stop using mysql or sqllite and start using postgres.

You can find the templates @ http://github.com/voomify/voomify/templates.
(Warning they reference each other using a local path, so you will need to change that if you plan on using them for yourself. You can create a directory ~/dev/voomify/templates and put the templates there and they will work for you.)

If you have not checked out templates for rails 2.3 and rails 3 then you should do some reading. This is not a tutorial. Here are some references to get started with:
http://m.onkey.org/2008/12/4/rails-templates
http://asciicasts.com/episodes/148-app-templates-in-rails-2-3
http://benscofield.com/2009/09/application-templates-in-rails-3/

Here are some sample templates that really helped me get started:
http://github.com/jm/rails-templates

So what do these templates do? Well there are three templates:
1) app.rb - this creates a rails application with rspec and sets it up to be compatible with our engines.
2) engine.rb - this creates a rails application that is also an engine.
3) finailize.rb - this finalizes our application or engine. It is always called at the end of the process.


I then created a litle bash script that will make it easy for me to call these.

Normally I have to put together a long command line:


With this bash script (in ~/.bashrc on ubuntu):

Credit for this goes to: Ryan Bates (http://asciicasts.com/episodes/148-app-templates-in-rails-2-3)

My command line is now much simpler (whew!):


OK time to get cooking. First let's create a rails 3 engine. This engine will be embedded in our application container. It will be setup with rspec and all the proper '.gitignore' files. It will prompt you for the engine name and the database username. (It also adds jeweler to the app gems. We need this because our engines use jeweler to gemify themselves. Maybe in a later post I will figure out how to remove this dependency.)

Side Note: With rails 3 you no longer have to do that messy 'script/generate rspec_XXXX' junk anymore. Rspec is now installed as the default generator and you can simply run 'rails g scaffold ...'. I dig it.



Now let's add some job scaffolding:



The way these engines are setup they are also full blown applications that we can test inside. This way we develop the engine functionality just like we are in any other application. We can run generators, write tests the way we are accustom to. From your perspective it is just a rails app. How easy is that?

Now let's see it running like any other rails app:



Let's goto the jobs and see them in action: http://localhost:3000/jobs

Before we embed this we need to create a gem.


Ok let's embed this into our 'host' application.

Generate the host application:



Add the following to your Gemfile:



Ok now for migrations. We don't have any helpers for migrations yet. So for now you need to copy your engine migration into your app. Something like this:



Now startup your 'host' app and you will see your jobs. Nice! Imagine how modular you could be! Like a lego version of your coding self.



Let's goto the jobs and see them embedded inside our application as a rails 3 engine!: http://localhost:3000/jobs


Using the voomify-jobs.gemspec in the jobs engine directory you can specify gem depenencies. So if your engine depends on other gems you just need to add them here. That includes other engines. Now you can explicitly manage your dependencies. I feel so clean ... you?

Happy engines.

Note: I ran into a bundler, rake, gem install issue that I cover in this post:
Rails 3, Gems, Rake and Bundler

Friday, May 7, 2010

Setting Rails 3 Beta on Ubuntu 9.10

I spent some time trying to get rails 3 beta 2 running on Ubuntu.
The default gem install using apt-get is 1.3.5.
For rails 3 you will need gem 1.3.6.

Install RubyGems 1.3.6


OK now you are ready to follow the rails guide:
http://weblog.rubyonrails.org/2010/2/5/rails-3-0-beta-release/

Ok Now to install rspec:
If you don't have xmllib already setup you will get errors building nokogiri. Follow these to fix that:

http://nokogiri.org/tutorials/installing_nokogiri.html

Then install rspec-rails 2.0:
http://github.com/rspec/rspec-rails

Happy Rails 3 Riding!

Tuesday, February 23, 2010

Vendor rails and svn

We are using SVN and vendoring Rails. Everytime we update to a new version of rails it requires a bunch of deletes and adds. We do this for multiple projects. It is a pain. So I finally bit the bullet and decided to create a repository area for rails version. In our tree we put our rails versions off our trunk like the following:

/etorg/trunk/rails/rails-2.3.5

Then we us svn:externals with the path in the vendor directory.

The trick (and the reason I'm writing this down) is that to keep svn from either complaining with a warning or giving an error was to move the original vendor/rails directory to another name 'vendor/dead_rails' then commit. That results in no conflicts or warnings.

I hope this saves someone some head scratching time.

Sunday, May 10, 2009

Erector - ruby CRUD views

In my last post I created a simple Erector view with a layout and talked about the pro's and con's of using a ruby class based view. Before we go any further I want to re-establish that I'm not a fan of markup. So if you are a markup jockey ... then you might want to move on. This Object Oriented view business is probably not your cup of tea. After all who would want clean, testable code in their views? Besides me that is.

OK you decided that you care enough about your views to read on. Stick with it, its worth the ride.

Let's get started by using the default scaffolding to generate a customer model. Run the following:


script/generate scaffold customer first_name:string, last_name:string, company:string, phone:string, email:string


Then run the migration and test the pages.

rake db:migrate


Now lets turn these views into erector views. Erector comes with a tool that will turn your erb's into erector classes. Run the following from your application root directory:

erector app/views/customers/**

If you look in your views/customers directory you will now see .rb files. Let's compare the code. Here is our show.html.erb:


<p>
<b>First name:</b>
<%=h @customer.first_name %>
</p>

<p>
<b>Last name:</b>
<%=h @customer.last_name %>
</p>

<p>
<b>Company:</b>
<%=h @customer.company %>
</p>

<p>
<b>Phone:</b>
<%=h @customer.phone %>
</p>

<p>
<b>Email:</b>
<%=h @customer.email %>
</p>


<%= link_to 'Edit', edit_customer_path(@customer) %> |
<%= link_to 'Back', customers_path %>


Now here is the erector equivalent:


class Views::Customers::Show < Erector::Widget
def content
p do
b do
text 'First name:'
end
text @customer.first_name
end
p do
b do
text 'Last name:'
end
text @customer.last_name
end
p do
b do
text 'Company:'
end
text @customer.company
end
p do
b do
text 'Phone:'
end
text @customer.phone
end
p do
b do
text 'Email:'
end
text @customer.email
end
rawtext link_to('Edit', edit_customer_path(@customer))
text '|'
rawtext link_to('Back', customers_path)
end
end


It is pretty straight forward. One gotcha is that the base class is the
Erector::Widget class. The problem is that we are using rails helper and these are exposed using the Erector::RailsWidget base class. You can either change the base class to Erector::RailsWidget or you can introduce an erector layout that derives from Erector::RailsWidget and then you would derive from your layout class. (See my last post for more info on this.) The other thing you need to do is to move or destroy the erb files. If you don't move or delete them then your new erector view classes will not be found. Now you have erector views for your scaffolded customer. Take it for a spin.

I personally think the syntax is cleaner if we use the {} block syntax instead of do end. Here is the same view re-written to use {}:


class Views::Customers::Show < Erector::Widget
def content
p {
b {text 'First name:'}
text @customer.first_name
}
p {
b {text 'Last name:'}
text @customer.last_name
}
p {
b {text 'Company:'}
text @customer.company
}
p {
b {text 'Phone:'}
text @customer.phone
}
p {
b {text 'Email:'}
text @customer.email
}
rawtext link_to('Edit', edit_customer_path(@customer))
text '|'
rawtext link_to('Back', customers_path)
end
end


Now you have a feel for what it looks like. How about a quick refactor of this code. I personally don't like the hard coded labels, so let's remove that:


class Views::Customers::Show < Erector::Widget

def show_column(col)
p {
b {text col.to_s.titleize }
text @customer[col]
}
end

def content
show_column :first_name
show_column :last_name
show_column :company
show_column :phone
show_column :email

rawtext link_to('Edit', edit_customer_path(@customer))
text '|'
rawtext link_to('Back', customers_path)
end
end


Now that's what I'm talking about. Now gee, if i do that in all my show views, I can easily refactor that method and make it available in either a base class or a module mix-in. What I like is how easy the refactoring is. It feels as it should easy.

Rawtext and text


You'll notice that we output using either text or rawtext. The difference is text is escaped and rawtext is not.

Erector - Object Oriented views

I just got back from railsconf. On the plane ride home I decided to take a look at Erector. Erector, besides having a cool name, is a dsl for writing markup. It is very similar to markaby, except erector views are not templates, they are plain old ruby objects. Let's look at an example:

class Views::Home::Index < Views::Layouts::Application
def main_content
h1 'Welcome to Voomify'
p do
text 'What is Voomify?'
end
p "Voomify is the verb for applying Voom to a problem."

p "Voom as defined by Dr Seuss in 'The Cat in the Hat Comes Back':"

blockquote do
p "'Voom is so hard to get,
You never saw anything
Like it, I bet.
Why, Voom cleans up anything
Clean as can be!'"

p "Then he yelled,
'Take your hat off now,
Little Cat Z!
Take the Voom off your head!
Make it clean up the snow!
Hurry! You Little Cat!
One! Two! Three! GO!'"

p "Then the Voom...
It went VOOM!
And, oh boy! What a VOOM!"


p "Now, don't ask me what Voom is.
I never will know.
But, boy! Let me tell you
It DOES clean up snow!"
end

end
end


This will render the following code:


<h1>Welcome to Voomify</h1><p>What is Voomify?</p><p>Voomify is the verb for applying Voom to a problem.</p><p>Voom as defined by Dr Seuss in 'The Cat in the Hat Comes Back':</p><blockquote><p>'Voom is so hard to get,
You never saw anything
Like it, I bet.
Why, Voom cleans up anything
Clean as can be!'</p><p>Then he yelled,
'Take your hat off now,
Little Cat Z!
Take the Voom off your head!
Make it clean up the snow!
Hurry! You Little Cat!
One! Two! Three! GO!'</p><p>Then the Voom...
It went VOOM!
And, oh boy! What a VOOM!</p><p>Now, don't ask me what Voom is.
I never will know.
But, boy! Let me tell you
It DOES clean up snow!</p></blockquote>



Admittedly this is not a very good example showing any benefit at all to using Erector. It is all markup and requires no real logic at all. Be patient we'll eventually get there.


Why would anyone want to do that? We'll for one I hate markup. (When I'm in full markup mode, i feel dirty.) If you love markup and erbs, then you should stop reading now. Before you leave, I'll leave you with this, you can easily mix erector and erbs (or any other template that works with rails). Some tasks are very well suited to markup and others are better suited to a markup dsl. If you are tag heavy then you should stick with your erb's. If you find you views are light with markup but heavy with ruby flow and control logic then erector or markaby may be the ticket.

Markaby or Erector



I dont' know much about Markaby. After taking Erector for a spin, I took a closer look at Markaby. I like it. The biggest difference to me is that Markaby allows you to create ruby template files the same way erb's do. The views are still templates with ruby syntax. They are not first class ruby objects. With erector they are first class plain old ruby objects. Why is this good? It gives you all the tools of inheritance and mixin's for your views. That is cool. Especially for an application with multiple views of the same underlying models. You can refactor your views into base classes that derive and render the same data in different ways. This is object oriented design for views. Nice.


Side Note



I've seen object oriented view code in other languages and it leads to some very powerful re-use that all OO programmers can understand. The most ambitious of these attemps was by an HR company named Seeker in the bay area. I was working for Concur at the time and we bought Seeker back in 1999. (It did not work out well, but that is a story for another time.) Seeker created their own markup language that was object oriented. The nature of HR data is that it has very complicated rules regarding who can see what data and when. The OO design of the language allowed that to be abstracted to the base classes and a functional programmer simply focused on the problem at hand. They took it further, as all commercial enterprise applications do, and they allowed the customer to define new models and views. Those views were very easy to write with this advanced data access logic abstracted out. Their customers loved it. They wrote very advanced business applications on top of this abstraction.


A Closer Look



So let's look a little deeper at using Erector with rails. Follow the erector installation and you'll be able to write an erector view. One gotcha I ran into was the fact that your views should derive from Erector::RailsWidget. If you don't do that you don't have access to the rails helpers.

To layout or not to layout



You have a couple of options for the layout. You can keep your erb layout and just drop in your Erector views. That is cool if you have an app already that you want to mix erector into quickly. It also allows the views to be rendered with different layouts.


The other option is to create an Erector layout. If you do that then you set your controler like so:


class HomeController < ApplicationController
layout nil
...


Here is a simple erector layout:


class Views::Layouts::Application < Erector::RailsWidget
def javascript_includes
javascript_include_tag 'application'
end

def stylesheet_includes
stylesheet_link_tag 'styles'
end

def header
h1 'Voomify'
end

# override this to render your view 'main' content
def main_content
end

def footer
a 'Home', :href=>"/"
end


def content

html do
head do
title "Voomify"
javascript_includes
stylesheet_includes
end
body do

div :id=>"maincontainer" do

div :id=>"contentwrapper" do
div :id=>"topsection" do
header
end

div :id=>"contentcolumn" do
main_content
end
div :id=>"footer" do
footer
end
end
end
end
end
end
end




Then you derive your view from the layout erector class. The view example above does just that. Notice that the view defined above implements main_content. This is the method defined by our layout, you can name it whatever you want. You'll also notice that it has methods to override for the header, footer, javascript_includes and stylesheet_includes. So if the page want's to modify any of those elements all it needs to do is override those methods. It can call super if it wants or just replace it.


This got me thinking about the decoupled relationship between templates and their view. The view does not know anything about where they are being rendered. Generally this is a very good thing. For example a view may be rendered on a page, or as an ajax call. Coupling the view to the layout creates a tight dependency between the two. This troubled me at first. (OK not that much, the world has bigger problems!) But then I started thinking about it. How often do I have single view that has a different layout? Not much. When I do with Erector I could use a decorator pattern from my base layout. OK that works. What about ajax forms? I have not tried it yet, but I'm pretty sure I can call my main_content to return to an ajax request.



OK so not very often do I have multiple layout variations with the same view. What does happen a lot is that I would like to make a modification to how the layout renders based on the view. Eventually the layout ends up with conditionals that render some of the erb if some variable is set by the controller. Yuck! How many times have you done that. (Be honest!) You say to yourself its ugly, but it's a template. You grit your teeth and move on. Or if it really bothers you, you introduce a helper, but it suffers from the same condition, branching logic, but now its written in ruby. An Object Oriented layout can easily eliminate that. Another case is when a view participates in another relationship. For example a given view may be related to other models in the system. The layout defines a standard layout for this relationship and then the view code implements main_content and related_content. The related_content method could return markup, or the layout may take care of the markup, and all the related content needs to do is return the model objects that are related to my current view.


In my next post I'll be building a simple contact model and then turning it into an Erector set of views. Until then ... keep it clean.

Thursday, May 7, 2009

Railsconf 09 -Vegas

Here are my takes on the railsconf 09. It was my first railsconf. I've attended many JavaOne and MSFT PDC's, dating back to 1990. What struck me most was the enthusiasm of the community. You get that vibe in general, but to see a ballroom full of rails enthusiasts is another story.

In Java and MSFT events they are pushing new technology, even when it is barely baked. I expected this railsconf to do the same with rails 3, but there was not much content talking about rails 3. DHH did spend his keynote talking about some major highlights. My take is that rails 3 will be more elegant, flexible and performant, but the migration will be painful.

At the keynote DHH opened up talking about the attacks on rails. He was telling his on story about how he came to understand they were not personal attacks and it really just did not matter. It made me realize how early stage the rails community really is.(I'm not talking about the technology, but the community.) The vibe is: the rails world has been growing, but is it grown up enough to become a major player? You can especially hear it when people start talking about enterprise rails. Those conversations always start with a justification of how rails is ready.

The rails community at large is a passionate group that believes they have a better way of doing things. (Even if it is not entirely true.) It has a rebel feeling. I love that. The rails community needs to own its success. Strut around with more confidence. (BTW I'm NOT saying DHH does not have confidence!) Getting early adopters to use it is easy, getting wide spread adoption is much harder. Right now it still feels like early adoption. I'm not sure the rails community wants wide spread adoption. Careful for what you wish for.

Other highlights for me:
* Obie Fernandez being so passionate and honest about what he and hash rocket have gone through.
* Jim Weirich - Writing Modular Applications. Jim did a great job outlining a taxonomy for describing dependencies. The base material dates back to the 80's.
* Pen & Teller - They rock.

Tuesday, April 28, 2009

DRY views using builders - AKA markup sucks

In this post I'm taking a look at how to DRY the view code from the Getting Started with Rails

The first thing I noticed about the Getting Started Guide was that the mark-up was really not very dry, so the question became how can I dry up the mark-up? OK so it does use a partial for the shared edit and new form. It has been my experience that most forms and lists are pretty simple and should not need this much mark-up. Truth be told, I hate writing mark-up. So how can I describe the presentation with enough detail so that I don't have to write so much? Don't get me wrong I don't mind writing mark-up that is unique for a given page. Just don't make me write more form and table markup...please.

So we want to be dry, cool. But we also want to be DRO (don't repeat others). So who is solving this problem? Let's start with our forms. How to DRY our forms. A quick look around a common pattern appears: Use Builders. A builder allows an application to emit custom code for a given form field. Were going to examine the formtastic plugin:
* http://github.com/justinfrench/formtastic/tree/master

In our case we would like to write simple erb code that emits all the tags for our form. In keeping with our DRO model we are going to take the formtastic plugin for a spin and see what we get.

First thing is to install the formtastic plugin:


script/plugin install git://github.com/justinfrench/formtastic.git


Now let's see if we can update the _form.html.erb file using formtastic:


<% @post.tags.build if @post.tags.empty? %>
<% form_for(@post) do |post_form| %>
<%= post_form.error_messages %>
<p>
<%= post_form.label :name %><br/>
<%= post_form.text_field :name %>
</p>
<p>
<%= post_form.label :title, "title" %><br/>
<%= post_form.text_field :title %>
</p>
<p>
<%= post_form.label :content %><br/>
<%= post_form.text_area :content %>
</p>
<h2>Tags</h2>
<% post_form.fields_for :tags do |tag_form| %>
<p>
<%= tag_form.label :name, 'Tag:' %>
<%= tag_form.text_field :name %>
</p>
<% unless tag_form.object.nil? || tag_form.object.new_record? %>
<p>
<%= tag_form.label :_delete, 'Remove:' %>
<%= tag_form.check_box :_delete %>
</p>
<% end %>
<% end %>
<p>
<%= post_form.submit "Save" %>
</p>
<% end %>


With our new form builder we can dry this up a little bit:

<% @post.tags.build if @post.tags.empty? %>

<% semantic_form_for(@post) do |post_form| %>
<%= post_form.error_messages %>
<%= form.inputs %>

<h2>Tags</h2>
<% post_form.fields_for :tags do |tag_form| %>
<p>
<%= tag_form.label :name, 'Tag:' %>
<%= tag_form.text_field :name %>
</p>
<% unless tag_form.object.nil? || tag_form.object.new_record? %>
<p>
<%= tag_form.label :_delete, 'Remove:' %>
<%= tag_form.check_box :_delete %>
</p>
<% end %>
<% end %>
<%= form.buttons %>
<% end %>


A couple of things to notice when you run this. You now have some more view logic that was provided by formtastic. Required fields are marked on the form with an *. The form is now drawn with a fieldset. The form uses left justified labels. If you look at the browswer source you'll also notice that it uses a <ol>> elements. (This is why the fields are numbered.) The form fields tags now have classes and id's for all the tags.

OK that went pretty well..so let's go a step further and refactor the tags:

<% @post.tags.build if @post.tags.empty? %>
<% semantic_form_for(@post) do |post_form| %>
<%= post_form.inputs %>
<% post_form.semantic_fields_for :tags do |tag_form| %>
<% tag_form.inputs :name, :name => 'Tags' do %>
<%= tag_form.input :name %>
<% unless tag_form.object.nil? || tag_form.object.new_record? %>
<%= tag_form.input :_delete, :as=>:boolean, :label => 'Remove:' %>
<% end %>
<% end %>
<% end %>
<%= post_form.buttons %>
<% end %>


Now we are getting somewhere! No mark-up! I could get use to doing forms like this.

My next implementation step is to generate client side validations by reading the model validations and presenting them at input time. Check out the livevalidation plugin

Friday, April 17, 2009

All great journeys start with one step

Like most of you that came to Ruby on Rails.  I was excited to see what this promising framework could do for productivity.  Before Rails I had designed large scale commercial web applications on both C++ and Java.  My real specialty was to define the framework and then extend it as the application demands.  We wanted our code to be DRY (before everyone was using the term DRY).  A good framework adds structure, is easy to understand, is easy to extend and eliminates repetitive code.  Rails certainly lives up to my definition of a good framework. It handles many of the most common issues that teams building data driven web applications have to solve.  Ruby is the giant's shoulders that Rails stands on.  The language is so expressive and dynamic it creates so many possibilities.  

Now it is time for a small trip down architecture memory lane. 

I've been developing data driven web applications since 1996.  Looking back on it is seems archaic.   At the time we were forging new ground.  

Version 1.0 1996:  We created one of the earliest commercial, dynamic, configurable, web based business applications.  One thing that made these applications so effective is that they were massively configurable by the clients.  Everything, and I mean everything, could be customized by the client.  Back then the tools were non-existent.  Our first application was MSFT based.  Good old fashion COM objects talking to ASP 1.0.  We developed a model layer with the COM objects and the ASP programmers then consumed them to present the view.  It was a simple MV design.  (No controller.)  HTML was so limited back then, so we had a java applet that handled the advanced data entry UI.  This essentially had to mimic what we had built as a windows application.   

Version 2.0 1997: We designed a JavaScript version that eliminated the 'heavy' Java applet from the client. This was a very ambitious multiplatform JavaScript library.  It had to understand a very rich meta-data layer that described how the data entry for the client should behave.  The DOM was not very rich and if you wanted to dynamically do much of anything on the client you had to write it from scratch and then make it work on all the browsers.

Version 3.0 1998: So far these applications were installed by large fortune 500 businesses.   But it was too complicated to setup and maintain for a midsize company.  So we introduced the Software as a Service (SaaS).  Back then we called it ASP or our Hosted business.  This introduced a whole bunch of new design challenges.  Should there be one database per customer or larger databases shared with a 'domain' column partitioning the data.  How do you manage it?  How do you scale it? How do you secure it.  This is before really anyone else had a viable SaaS product much less business model.

Version 3.0 2001:  The success of all the earlier projects led to more customers with even more needs.  This time they need to have a global solution that could handle many languages simultaneously.  Like many code bases the investment into refactoring the original design was borrowed from for years.  As a result it never really evolved as it could have.  By now the tools had advanced very far.  Java (J2EE) was leading the charge with MSFT 'embracing and 'extending' with .Net.  We had already  switched to Java (J2EE) and built a very cool XML driven B2B product that integrated suppliers in the procurement chain. 

So it was time to build the mother of all projects.  It had a list of requirements that would scare off most engineers.   

We started with a simple J2EE stack layered with a bunch of Apache technologies.  We chose Turbine as our MVC. Our model layer was based on Torque.  Torque was great for navigating the model, insert, updates, deletes and transactions.  But our views were often hitting many tables and a pedestrian Torque implementation would result in too many database round trips.  So we introduced our own read only data access layer RDAL (Rapid Data Access Layer).  RDAL allowed us to write portable SQL and get very efficient data-access out of the system all while looking like a Torque model object to the view.  We considered JSP, ECS and Struts for the view layer.  In the end we decided against all of them to selected Velocity.  What attracted me to Velocity was the simplicity of the templating language.  It could do what you normally need to do in a view very well, loop, conditionals.  It was not expressive enough to put logic into the view.  We could re-use snippets of code with it (like a Rails partial).   Essentially what we had was a J2EE/Apache MVC stack that did much of what you find in Rails.  

So now we had an application framework, big deal.  We were building database driven web applications.  So we have a lot of CRUD operations to deal with.  Those CRUD interfaces all had to deal with the following:

·          It was a SaaS offering so every CRUD set of views had to be domain aware.

·          Most CRUD views had to support custom fields

·          Every view had to be multi-lingual with multiple users viewing the site in different languages simultaneously.

·          Views had to support role based behavior.  (Be aware of the role of the current user and present different options based on their role.)

·          It was a SaaS application so it had to be VERY secure.  We chose to implement the OWASP security standards for the application.

·          Every view could be customized by an consulting engineer.  That customization would override the default view behavior on a per-customer basis.  The consults should also be able to add new views for that client.

Dang that’s a lot of stuff each developer has to be concerned about.  Where to start? The view layer really does nothing to provide any productivity to solve any of these problems.  If you want to build a new or edit form you have to write a whole bunch of form html.  If you wanted a list you would have to write a bunch of table markup.  So the question became how do you DRY up the view and meet the requirements above? 

Our answer was to introduce a presentation markup language.  You would describe your model in the markup and it would generate a CRUD set of views for you that does all of the above automatically.  It was really easy to add new CRUD views on a given model.   It was easy to change the UI design for a given element.  We had a UI designer that would introduce new behavior as we progressed on the project.  We could modify all the views built so far with this new UI behavior.  Did I mention that it would generate tests for you as well? It was slick as snot.

The presentation markup was concerned only with how you want to render the model(s).  From the markup you could embed velocity code just like a partial.  You could call java ‘helper’ methods.  It allowed us to have declarative UI for much of the system. 

This blog is will follow along as I solve the same problem, extending the rails framework along the way.