Wednesday, September 9, 2009

Using rsruby in RubyOnRails

  1. Create your Rails application
  2. Let’s call it Plotter. Usual procedure:
    rails Plotter
    cd Plotter
    rake db:create
    We won’t use the database (default sqlite3) in this example, but you may use it later on.
  3. Tell the application about R_HOME
  4. RSRuby will fail unless the environment variable R_HOME is set.
    To tell Plotter that R_HOME is /usr/lib/R, I put this in the file app/helpers/application_helper.rb:
    module ApplicationHelper
    # set R_HOME if not set
    if ENV['R_HOME'].nil?
    ENV['R_HOME'] = "/usr/lib/R"
    end
    end
  5. Make an instance of RSRuby available to all controllers
  6. RSRuby works by providing an instance of an “R object”, on which you call R functions as methods.
    I provided the object by editing app/controllers/application_controller.rb to include a method named InitR:
    class ApplicationController < r =" RSRuby.instance">
    
  7. Create a sample controller and view
  8. For testing purposes, I created a controller named Home with a single view named index:
    ./script/generate controller Home index
    rm public/index.html
    I edited config/routes.rb so as the root of the application is the index view for the home controller:
    ActionController::Routing::Routes.draw do |map|
    map.root      :controller => "home"  #default view is app/views/home/index.html.erb
    map.connect  ':controller/:action/:id'
    map.connect  ':controller/:action/:id.:format'
    end
    Now we can get to work on the file app/controllers/home_controller.rb. I wrote a sample method, show_image to plot a histogram using R via RSRuby:
      def show_image
    # next 6 lines use R to plot a histogram
    @r = InitR()
    @d = @r.rnorm(1000)
    @l = @r.range(-4,4,@d)
    @r.png "/tmp/plot.png"
    @r.par(:bg => "cornsilk")
    @r.hist(@d, :range => @l, :col => "lavender", :main => "My Plot")
    @r.eval_R("dev.off()")  #required for png output
    # then read the png file and deliver it to the browser
    @g = File.open("/tmp/plot.png", "rb") {|@f| @f.read}
    send_data @g, :type=>"image/png", :disposition=>'inline'
    end
    Not the prettiest code, but you get the idea. Obviously the owner of the HTTP daemon (www-data on Ubuntu) must have write permission to the location of the PNG file; /tmp in this case.
  9. Create the view
  10. All that remains is to edit app/views/home/index.html.erb so as it displays the image:

    Home#index

    Find me in app/views/home/index.html.erb <%= image_tag(url_for(:controller => "home", :action => "show_image")) %>
    Which just says “wrap whatever comes out of the method show_image in an IMG SRC tag”.

No comments:

HTMLCode

HTMLCode Content