Saturday, May 23, 2009

Loading smartclient in Rails...

How to load smartclient (LGPL javascript framework) in rails:
  1. Download smartclient LGPL version
  2. Copy smartclientRuntime/isomorphic/* --> RAILS_ROOT/public/isomorphic/
  3. Load up the javasacripts in your template
To help further, here's a nice application helper method (load_smart_client) to generate the right stuff for that last step:

module ApplicationHelper
# All the modules in smartclient
# (actually there's a few more -- but less useful)
ISC_MODULES = [
[:core, 'ISC_Core.js'],
[:foundation, 'ISC_Foundation.js'],
[:containers, 'ISC_Containers.js'],
[:grids, 'ISC_Grids.js'],
[:forms, 'ISC_Forms.js'],
[:data_binding, 'ISC_DataBinding.js']
]

# Helper to generate paths to static urls
#
# Useful when you deploy under a path prefix
# (for example, --prefix with mongrel)
def static_url_for(path)
"#{ActionController::Base.relative_url_root}#{path}"
end

# Load smartclient javascript framework (via script tags)
#
# Options are:
# :modules => array of js modules to load
# :skin => skin name, as per subfolder in /isomorphic/skins
#
# Skins include:
# BlackOps, Cupertino, Enterprise, fleet, SilverWave,
# SmartClient, standard, ToolSkin or TreeFrog
#
# Loadable modules include:
# :core, :foundation, :containers, :grids, :forms, :data_binding
#
# By default loads ALL modules, with Enterprise skin
def load_smart_client(opts={})
skin = opts[:skin] || 'Enterprise'
modules_to_load = opts[:modules] || ISC_MODULES.map(&:first)

# Set isomorphic dir
out = "<script>var isomorphicDir='#{static_url_for('/isomorphic')}/';</script>"

# Load each module
ISC_MODULES.each do |key, js_file|
if modules_to_load.include?(key)
js_url = static_url_for("/isomorphic/system/modules/#{js_file}")
out += "<script src='#{js_url}'></script>\n"
end
end

# Load skin
js_url = static_url_for("/isomorphic/skins/#{skin}/load_skin.js")
out += "<script src='#{js_url}'></script>\n"
end
end

Saturday, January 03, 2009

Languages to learn...

  • Javascript (more deeply)
  • Lisp
  • Smalltalk
  • OCAML
  • Haskell
  • Erlang

Tuesday, July 01, 2008

Don't lose my Money.new, or why 1 / 3 = ?

If you're using the Money object in rails, you'll be storing your money as cent in your DB. Then, you use composed_of to read this into a whole separate object (of type Money).

This works great, but, I don't like losing Money.

The problem is, Money objects can't go into fractions below a cent. So when you divide 1 by 3, you can't have .33333 reoccurring... you get .33.

We tackled this issue by modifying division to round to the nearest cent, but auto-calculate the total error. This only makes sense when you have a way of dealing with the rounding...


class Money
alias_method :lossy_divide, :/
def /(*params)
raise "Do not divide - losing Money!"
end

def split_between(x)
result = self.lossy_divide(x)
rounding_error = self - (result * x)

result, rounding_error
end
end


In this way, you 'split' money rather than exactly divide.

Our use-case is that we want to split the money between x people, or amongst x days. So, we generally have to assign the split money out to different instances.

This works beautifully if we return an array representing all the splits, and add the rounding error to the first entry:


class Money
alias_method :lossy_divide, :/
def /(*params)
raise "Do not divide - losing Money!"
end

def split_between(x)
result = self.lossy_divide(x)
rounding_error = self - (result * x)

[result + rounding_error] + (2..x).map{result}
end
end

Graphing in Rails Roundup

We recently built a small rails app to act as a portal into a large list of reports. Rails works great for this - we've added role-based authentication, integrated legacy reportss and, hmmm, why not add sexy graphs?

The following is a quick list of the current graphing/charting choices - with the intention of adding charts into this intranet-accessed reporting app...


Image Generating: GRUFF


The most often sited lib is 'gruff'. It works by generating an image of your graph which you can serve up. The API seemed very easy to use.

http://nubyonrails.com/pages/gruff

I had some issues when there were a lot of x-axis labels. You specify which x-label points to display in a hash, and to avoid the overlap it looked as though we would have to manually calculate an interval.

NOTE: there is also a library called scruff which generates SVG graphs. It uses a similar API to gruff.


Open Flash Charts


We are currently using Open Flash Charts. It's very easy to use, looks great, and provides a large number of styles.

The way it works is you embed a flash object into your browser, and tell it an url from where it should fetch it's data.

It puts your x-axis on an oblique which avoided our problem all together.

To help out, there's a nice Rails plugin, generating all of the above. See: http://www.pullmonkey.com/projects/open_flash_chart/.


AMCHARTS


AM Charts make some really professional looking components. It's pretty similar to Open Flash Charts, but the free version is not open source and contains a link back to amcharts.com.


However, it's not too expensive and there is a rails plugin for it: Ambling.

  • Ambling is a rails plugin makes it easy to generate XML needed by the wonderfully slick Amcharts.
  • Amcharts has two kinds of XML: the data xml and the settings xml. Ambling can help with both.



OTHERS


Fusion Charts - v2 is free: http://www.fusioncharts.com/free/
Fusion Charts - v3 is commercial: http://www.fusioncharts.com/

XML/SWF charts
XML/SWF has a free version - which if used, generates graphs as a link - where clicking on a graph directs you to their site. A commercial version is $45 for a developer.

XML/SWF plugin for rails: http://ziya.liquidrail.com/


One issue to be aware of - Flash objects don't seem to print in Firefox. I believe other browsers work fine - in particular, IE worked under test.

A work around (in most of the above libs) is to right click a particular graph and select "Print Chart".


JAVASCRIPT BASED


This is a very cool idea - javascript draws the graph in a canvas object within the browser. It works in IE too via an emulated canvas object.
http://en.wikipedia.org/wiki/Canvas_(HTML_element)

A roundup of these are as follows:

  • PLOTKIT, based on Mochikit javascript lib
  • PLOTR, is PLOTKIT with parts rewritten to use prototype
  • FLOT, is based off of jQuery
  • FLOTR, is similar to FLOT but uses prototype


All of these are quite simple to use, and have varying levels of maturity, documentation and compatibility. However, generally speaking they support browsers where the Canvas tag is supported: Firefox 1.5+, Safari 2.0+, Opera 9.0+ and IE6+ (emulated).

It's also worth mentioning that these integrate nicely with rails - all your app need do is embed JSON data (or return it via AJAX). The javascript is trivial to use - and can be controlled dynamically on the fly.


GOOGLE CHARTS


The charts you see in google analytics are openly available via a public API.

Lot's of info on their site (probably one of the best documented), and a rails plugin is available too: http://code.google.com/p/google-charts-on-rails/.

This is a very nice options if you have a public site, but not so good for intranet applications.


CSS GRAPHS HELPER


At the other end of the scale is this little plugin. It uses nothing but HTML, CSS (and optionally some images) to generate simple bar graphs.

I liked the simplicity of this one, but we did have some issues:

  • it seemed to conflict with some of our existing CSS
  • you are limited to one graph per page
  • all values need to be normalised to 100
  • it seemed to go wonky when you used more than 5 data points for vertical bar graphs (you can do more with horizontal ones)


It may still work well for you if you can work around those limitations. It's simplicity is also it's asset: no flash, no server-side processing, and works across browsers.
http://nubyonrails.com/pages/css_graphs.


If you've found another option please leave a note in a comment.

Thursday, February 07, 2008

Array Subsets and Supersets

I often find myself looking to see if an array contains all elements in another array. The code looks like this:-
!array.any? {|e| !other_array.include?(e)}

A much nicer solution is to use the build-in Set#subset because it reads so much better:
set.subset?(other_set)


A Set is like an array, but stores each element only once in an unordered sequence. You can't get at a particular index - but you can still use #each. Arrays, on the other hand, can store the same thing multiple times, and in different orders. Hence, it only makes sense to talk of 'subset' or 'superset' and not 'subarray'.

Quite usefully, Enumberable defines #to_set - which is included into Array giving us:-
array.to_set.subset?(other_array.to_set)

BTW - if you're outside rails, you'll need to require 'set'.

Monday, November 26, 2007

Fowler on Viagra Infused Rabbit Organisations

Martin Fowler on Organization Structures (Accountability)
If you are dealing with an organization with a single hierarchy, or even a couple, then Organization Hierarchy (7) is the simplest way to deal with things. However larger organizations grow beyond this. You often find a host of different relationships between parties, all of which carry their own meaning. If your hierarchies start breeding like viagra infused rabbits, it’s time to look to Accountability (17).

Gotta love that description :)

He's describing how you can structure organisations (including relationships between them).

I strongly recommend reading up on Fowler's work. I really like his style - especially his method of demonstrating the simplest possible model first, then building up complexity to maximum flexibility.

It's important to recognize that while no-one likes needless complexity, it's extremely beneficial to know how to add just enough to cover your needs.

Wednesday, November 21, 2007

Do NOT Override Rails :default DATE_FORMAT!

A subtle issue - I should've known better! Beware!

We defining our own date formats in our rails environment.rb - in order to format dates consistently across our app with 'some_date.to_formatted_s(:my_format)'. This is done by opening up the existing ActiveSupport class, and merging in your formats:


ActiveSupport::CoreExtensions::Date::Conversions::DATE_FORMATS.merge!(
:in_words => "%A, %d %B %Y", # Add format - Monday, 01 January 2007
:short => '%d/%m/%Y' # Override :short to ozzy style dates
)


However, do NOT go overriding the :default format!
This one ALSO seems to be used for converting dates into SQL string-formatted dates.

MySql ended up receiving a blank string, and stored '0000-00-00' for all my dates... ...but no errors.

Not nice.

Wednesday, November 14, 2007

Rails Coding Standard

The small team I'm part of work on a large Rails project (in complexity and scope). We've all got quite contrasting backgrounds: PHP hackers, J2EE pattern junkies & legacy spaghetti coders.

I've found some recurring issues that arise relating to code quality, so have set out to write a mini-code standard.


  1. IN ESSENCE: ALL CODE SHOULD BE READABLE!

  2. DO NOT OPTIMISE for performance - OPTIMISE FOR CLARITY OF CODE

  3. STYLE: use 2 spaces for indent (not tabs)

  4. STYLE: Line up hash arrows for readability

  5. STYLE: put spaces around => hash arrows

  6. STYLE: put spaces after ',' in method params - but none between method names and '('

  7. VIEWS: use HAML for views

  8. VIEWS: break up the structure with white space to help readability - VERTICALLY TOO!

  9. VIEWS STYLE: Rely on structure of page, without having to insert messages or new components...

    • Example: Effect to visually highlight then drop out an existing element rather than flash a message

    • Example: Highlight newly added row rather than a message about it



  10. AVOID logic in views - they should be simple

    • put html generating logic into helpers

    • instead of inline ruby logic, add to models (filtering, checking)



  11. NEVER use ActiveRecord models in migrations unless you re-define them within the migration

    • ...otherwise the migration fails when you later remove/rename the AR class

    • BETTER SOLUTION: use bootstrapping until deployed!!!



  12. AJAX only for sub-components of an object, and avoid over-use



Now the problem with code standards, is that they need to be adhered to, or they're totally useless. That's why the above is very short and easy to comprehend in one quick sitting.



What would you add or remove?

ActiveRecord Through ODBC Without Rails

  1. Install Ruby

  2. Install active-record (plus any adapters... such as ODBC) on command line

    gem install active_record --include-dependencies
    gem install odbc-rails --include-dependencies


  3. Write some Ruby code...

The simplest case looks something like this:


# require AR
require 'rubygems' # require gems first since AR is installed via gems
require 'active_record'

# connect to the database (sqlite in this case)
ActiveRecord::Base.establish_connection({
:adapter => odbc,
:dsn => your_pre-configured_odbc_datasource_name,
:username => user_name,
:password => secred_password,
:trace => true,
:convert_numeric_literals => true})

# define your models - this one looks for a table called 'tasks'
class Task < ActiveRecord::Base
end


Then you're good to go! Go ahead and use all that Active Record stuff from a local script...

See here for futher info on using ODBC with rails:

The rails wiki has more on active record outside rails.