Technology Blogs by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
cancel
Showing results for 
Search instead for 
Did you mean: 
Former Member

Overview


Welcome aboard! The family of dynamic JVM languages integrated and showcased to work on top of SAP NetWeaver Cloud, is this time growing with one of its most prominent representatives: Ruby on Rails. After seeing the success stories with Clojure and Groovy/Grails, it's time to take a comfortable ride on NW Cloud's Rails and enjoy seamless usage of persistence, document and connectivity services.


Apart from the original reference MRI implementation, a lot of alternative Ruby interpreters have been created: JRuby for the JVM platform, Rubinius, IronRuby for .NET, and others. What makes the integration we are going to see here possible in the first place, is the amazing JRuby project and its supportive and admirably active community. Led by former Sun experts, this Java implementation of the Ruby programming language has evolved to a full-fledged competitive Ruby runtime, which has recently outperformed even the classical MRI environment at official benchmarks. The other key player in the picture is the JRuby-Rack adapter, which provides with a smooth bridge for Rack-based applications to run under the hoods of a servlet container environment, thus effectively enabling not only Ruby, but the whole Rails framework to run on the JVM (as well as other Rack-based technologies like Sinatra, for example). JRuby has been able to run Rails since 2006.


Enough with the technical background - a detailed insight for the integration internals will follow in a separate blog.

In this series of articles we will develop a small Rails application in the standard local scenario, and will then present with a step by step guide for how to run it on the NetWeaver Cloud platform. We will give some recipes for how the application can consume several NW Cloud services so that it could best leverage the platform. We believe that those recipes could be used by other Rails applications as well, and we hope that this example could inspire further experiments for Rails integration on top of NW Cloud. Finally, we will describe in details how this prototype works, for those who are interested to take a look behind the curtains.

Getting Started

As basic prerequisites, it is supposed that you have a JDK and JRuby installation for your OS platform (for the record, on our side we are running with Java 1.6.0_37 and JRuby 1.7.2 under Windows 7). It is recommended that you have some basic Rails familiarity. In case you'd like to make a reference, the application sources for this article can be found here, in the local branch.

We start with installing the latest version of the Rails framework:


jruby -S gem install rails -v 3.2.11

This will fetch quite some other gems, including the Bundler dependency management tool, so be patient. Now we create a new Rails application using the Rails command line tool:


jruby -S rails new photoapp

By default the app will use the SQLite3 database for all environments: development, test and production. For local testing we will keep the sqlite3 configuration, but later we will switch to using a different one for the production environment, which is the NetWeaver Cloud platform in our case.


Adding models and controllers

Our application is going to be a very simple photo management tool: it will allow you to create and upload photos, organized by albums. You can, of course, view those photos and albums in the browser, as well as edit and delete them, which is the classical CRUD functionality offered by ActiveRecord. Here is what our data layer looks like:

To feel the power of quickly starting our journey on Rails, we will scaffold the basic application entities, photos and albums:


jruby -S rails generate scaffold Album name:string
jruby -S rails generate scaffold Photo title:string picture_name:string album_id:integer


Now we add the relationship between our models, as well as some validations:


class Album < ActiveRecord::Base
  attr_accessible :name
  has_many :photos, :dependent => :destroy
  validates :name, presence: true
end

and prepare the photos to be stored right in the application's public directory, under a new folder called uploaded (so we will have to create this uploaded folder):


class Photo < ActiveRecord::Base
  belongs_to :album
  attr_accessible :picture_name, :title, :album_id
  validates :title, presence: true
  validates :picture_name, presence: true
  def delete_file
    return unless picture_name
    File.delete( internal_path ) rescue nil
  end
  # Used for displaying image in UI
  def picture_web_path
    File.join("/uploaded", picture_name)
  end
  private
  def internal_path
    return nil if picture_name.nil?
    directory = "public/uploaded"
    return File.join(directory, picture_name)
  end
end

Now that we have our data model created in ActiveRecord, let's put it into the database as well:


jruby -S rake db:migrate

Let's move on to the business logic in our controllers. We will need to change slightly only the create action in the photos controller so that it stores the photo on the file system; the other parts of the scaffold logic will do just fine:


# POST /photos
# POST /photos.json
def create
   @photo = Photo.new(params[:photo])
upload_picture = params[:upload][:picture] rescue nil
if upload_picture
   filename = upload_picture.original_filename
   directory = Rails.public_path + "/uploaded"
   path = File.join(directory, filename)
   File.open(path, "wb") { |f| f.write(upload_picture.read) }
   @photo.picture_name = filename
end
  respond_to do |format|
    if @photo.save
      format.html { redirect_to @photo, notice: 'Photo was successfully created.' }
      format.json { render json: @photo, status: :created, location: @photo }
    else
      format.html { render action: "new" }
      format.json { render json: @photo.errors, status: :unprocessable_entity }
    end
  end
end

Working on the presentation layer

From the view side, we need to show all pictures in the album which is requested: we change the app/views/albums/show.html.erb template like this:


<p id="notice"><%= notice %></p>
<p>
  <b>Name:</b>
  <%= @album.name %>
</p>
<% @album.photos.each do |photo| %>
<%= h photo.title %>
<%= image_tag photo.picture_web_path %>
<% end %>          
<%= link_to 'Edit', edit_album_path(@album) %> |
<%= link_to 'Back', albums_path %>

When uploading a new photo, we would like to be able to choose from all existing albums the one that will contain it, that's why we modify the app/views/photos/_form.html.erb partial with a corresponding query:


  <div class="field">
    <%= f.label :album_id %><br />
    <%= select "photo", "album_id", Album.all.collect { |a| [a.name, a.id] }, {:include_blank => "None"}  %>
  </div>

The upload will require that we use a corresponding file upload form, which is not present in the partial. So for the app/views/photos/new.html.erb template we have to replace the partial rendering (the <%= render 'form' %> line of code) with its contents, where in addition we specify multipart configuration (see the first snippet below) and right before the last div tag we insert the upload form (second snippet):


<%= form_for(@photo, :html => {:multipart => true}) do |f| %>


  <div class="field">
    <%= f.label :picture %><br />
    <%= file_field "upload", "picture" %>
  </div>
  <div class="actions">
    <%= f.submit %>
  </div>

Finally, we would need to display a photo when it is requested, which means that the view template for the index action (app/views/photos/index.html.erb) will be added what we already saw a couple of times - the image_tag method that ActionView offers:


<td>
  <%= photo.picture_name %>
  <%= image_tag "/uploaded/#{photo.picture_name}", :size => "48x48" %>
</td>

as well as the show template will need to have it:


<p>
  <b>Picture name:</b>
  <%= @photo.picture_name %>
  <%= image_tag @photo.picture_web_path %>
</p>

Running the application locally

This is it! We now just have to start our local server (WEBrick on our case) to host our simple photo management tool:


jruby -S rails server

and access the app in the browser at http://localhost:3000/photos and http://localhost:3000/albums. I really love fruits, so here's a humble collection of some of my favorite:

We hope you enjoyed this preliminary Rails walk-through. Join us in the next session as well, to see how all this could be run on SAP NetWeaver Cloud with easy to follow migration steps!

6 Comments
Labels in this area