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!