Skip to main content

Sample Catalog Application using using JRuby and Rails

Posted by caroljmcdonald on October 10, 2007 at 2:20 PM PDT

Sample Store Catalog using using JRuby and
Rails





The RRCatalog Sample app demonstrates the usage of JRuby and Rails to
implement pagination of data sets for a Store Catalog.

href="http://techdayscode.dev.java.net/servlets/ProjectDocumentList?folderID=8159">
download RRCatalog sample code



Overview of the Technologies and Frameworks in the Sample Application



Rails is a
Model-View-Controller based framework for the development of
database-backed web applications in Ruby.


mvc2.gif



JRuby  is a 100%
pure-Java
implementation of the Ruby programming language. With JRuby and Rails
you get the advantage that  href="http://blogs.sun.com/arungupta/entry/jruby_on_rails_netbeans_and">you
can run your web app in a servlet container like Glassfish or
Tomcat.



The Sample Application

The sample application displays an online catalog of pets sold in a pet
store. The image below shows the Catalog Listing page, which allows a
user to
page through a list of items
in a store.



 
petcat.jpg




The Model 

The Model is your application's persistent business domain objects.
Rails implements the  href="http://www.martinfowler.com/eaaCatalog/activeRecord.html">Active
Record design pattern  for the model. An ActiveRecord
object
instance represents a row in a database table.  The item.rb and
address.rb
classes shown below were
generated by Rails for the items and addresses tables. To learn how to
generate Rails code
with Netbeans 6 see href="http://www.netbeans.org/kb/60/ruby/rapid-ruby-weblog.html">Creating
a
Ruby Weblog in 10 Minutes . After model code
generation you have to
add the relationships. The

 style="color: rgb(0, 0, 153); font-weight: bold;">Item

class has a many-to-one relationship
with the Address
and Contactinfo classes. In Rails
 style="color: rgb(0, 0, 153); font-weight: bold;">belongs_to

is the
many end of a many-to-one  relationship, and
 style="color: rgb(0, 0, 153); font-weight: bold;">has_many

is the one
end. In Rails the convention is that the object with the foreign key
belongs to the other object.




cellspacing="0">
Code Sample from: style="font-weight: bold;">app/models/item.rb 



class Item
< ActiveRecord::Base

  belongs_to
:address

  belongs_to :contactinfo

end

   


           

           
 
cellspacing="0">
Code Sample from: style="font-weight: bold;">app/models/address.rb



class Address
< ActiveRecord::Base

  has_many
:item

end

   


           

           



classrel.gif





The Item class is a subclass of the  Rails href="http://api.rubyonrails.com/classes/ActiveRecord/Base.html">ActiveRecord
Base class. At runtime the Rails framework dynamically adds column
names,
and attributes (with getters and setters) to the Item class for each
column in the corresponding items table. Rails uses default mapping
rules for this to work easily:  the item class defaults to
the items table, the address class to the addresses table, the primary
key defaults to id, a foreign key defaults to tablename_id...


SQL  Sample for items table style="font-family: monospace;">



CREATE TABLE items (

 id VARCHAR(10) NOT NULL,

 name VARCHAR(30) NOT NULL,

 description VARCHAR(500) NOT NULL,

 imageurl VARCHAR(55),

 imagethumburl VARCHAR(55),

 price DECIMAL(14,2) NOT NULL,

 address_id VARCHAR(10) NOT NULL,

 contactinfo_id VARCHAR(10) NOT NULL,

 primary key (id),

 foreign key (address_id) references addresses(id),

 foreign key (contactinfo_id) references contactinfos(id)

);

   


     




The Controller

Controllers handle incoming http requests, interact with the model to
get data and to process requests,  invoke the correct view, and
direct domain data to the view for display. 
In Rails, http requests are handled by ActionController classes which
are made up
of one or more action methods that are executed on request and then
either render
a template or redirect to another
action. Rails routes requests to the controller action which
corresponds to the URL mapping for the request. In Rails the default
mapping from URL to action method follows this convention: http://host/ style="font-weight: bold;">controller/action/id .  For
example the URL
http://host/item/list calls the
list style="font-family: monospace; font-weight: bold;"> style="color: rgb(0, 0, 153);"> style="font-weight: bold;">action method in the style="font-weight: bold;"> item controller style="font-family: monospace;"> style="color: rgb(0, 0, 153); font-weight: bold;">class
shown below.  href="http://www.netbeans.org/kb/60/ruby/rapid-ruby-weblog.html">Note
this code was generated using the Ruby Rails scaffolding support in the
NetBeans 6 IDE.  href="http://api.rubyonrails.com/classes/ActionController/Scaffolding/ClassMethods.html">Rails
Scaffolding provides a series of standardized
actions for listing, showing, creating, updating, and destroying
objects of a class.  These standardized actions
come with both controller logic and default view templates (I modified
the view templates). The style="color: rgb(0, 0, 153); font-weight: bold;">ItemController
style="color: rgb(0, 0, 153); font-weight: bold;">list
action renders a view with a paginated list of item objects.


Code Sample from: app/controllers/item_controller.rb


class ItemController
< ApplicationController

  def index

    list

    render :action => 'list'

  end



  def list

    style="color: rgb(0, 0, 153); font-weight: bold;">@item_pages
, style="color: rgb(0, 0, 153); font-weight: bold;">@items = style="color: rgb(0, 0, 153); font-weight: bold;">paginate
:items, :per_page
=> 10

  end



 

     



The style="color: rgb(0, 0, 153); font-weight: bold;">ItemController is
a subclass of  style="font-family: monospace; font-weight: bold;"> style="color: rgb(0, 0, 153);"> style="font-family: monospace;"> style="color: rgb(0, 0, 153); font-weight: bold;">ApplicationController
which is
a subclass of the Rails href="http://api.rubyonrails.com/classes/ActionController/Base.html"> style="font-weight: bold;">ActionController Base class.
When a URL has a controller but no action (e.g.
http://host/controller/  ), Rails defaults to the
index action. In the style="font-weight: bold;"> style="font-family: monospace;"> style="color: rgb(0, 0, 153); font-weight: bold;">ItemController
code the  style="color: rgb(0, 0, 153); font-weight: bold;"> style="font-family: monospace;"> style="color: rgb(0, 0, 153); font-weight: bold;">index
action method redirects to the style="color: rgb(0, 0, 153); font-weight: bold;">list
action.  The style="color: rgb(0, 0, 153); font-weight: bold;">list action
method calls the ActionController  href="http://api.rubyonrails.com/classes/ActionController/Pagination.html"> style="font-family: monospace;"> style="color: rgb(0, 0, 153); font-weight: bold;">paginate
method which queries the style="color: rgb(0, 0, 153); font-weight: bold;">Item
Active
Record model  for pagination. The pagination method creates the style="color: rgb(0, 0, 153); font-weight: bold;">@items
instance variable, which is an ordered collection of model objects for
the
current page (at most 10), and a style="font-family: monospace; color: rgb(0, 0, 153); font-weight: bold;">@item_pages
paginator instance, which is a class representing a paginator for an
Active Record collection. The style="color: rgb(0, 0, 153); font-weight: bold;">@item_pages and
style="color: rgb(0, 0, 153); font-weight: bold;">@items variables 
are automatically made available to the list view by the framework.



After executing
code, actions usually render a template in the views directory
corresponding to the name of the controller and action, for example the
list action will render the
app/views/item/list.rthml template.


The View

The view layer generates a web
page, using data from domain objects provided by the controller. In
Rails, the view is rendered using href="http://api.rubyonrails.com/classes/ActionView/Base.html">RHTML
, RXML, or RJS.  RHTML is HTML with
embedded Ruby code.




Code Sample from: app/views/item/list.rhtml



     

Listing items



     

      <%=
link_to 'Previous page', { :page =>
@item_pages.current.previous }
style="color: rgb(0, 0, 153); font-weight: bold;">
        
if @item_pages.current.previous %>
style="color: rgb(0, 0, 153); font-weight: bold;">
      <%=
link_to 'Next page', { :page => @item_pages.current.next }
style="color: rgb(0, 0, 153); font-weight: bold;">
        
if @item_pages.current.next %>


     



 

   

      scope="col">Name

      scope="col">photo

      scope="col">Price

   


 

 

   

   <%
for item in @items %>


    

      

      

      

    

  
<% end %>


 



          style="color: rgb(0, 0, 153); font-weight: bold;"><%= link_to
%Q{#{item.name}}, :action => 'show', :id => item %>

      
 

          style="color: rgb(0, 0, 153); font-weight: bold;"><%= image_tag
item.imagethumburl %>

      


          style="color: rgb(0, 0, 153);"> <%=h
item.price %>


      


     

     



The view uses instance variables set by the controller to
access the data it needs to render the rhtml. In the list.rhtml:



<% for
item in @items %>

loops through the objects in the style="color: rgb(0, 0, 153); font-weight: bold;">@items instance
variable, which is an ordered collection of
 style="color: rgb(0, 0, 153); font-weight: bold;">Item 
model
objects,  and assigns each
 style="color: rgb(0, 0, 153); font-weight: bold;">Item

model object to the
 style="color: rgb(0, 0, 153); font-weight: bold;">item 
variable.

 
<%=
link_to
%Q{#{item.name}}, :action => 'show', :id => item %>

calls the Rails helper method
 style="color: rgb(0, 0, 153); font-weight: bold;">link_to, 
which
creates an html link to the item/show/id action which will display the
corresponding item details. Rails helpers
are  methods that help your view templates generate HTML. For
example this line will generate the following HTML for one item:
<a class="attribute-name"> href="/item/show/1">Friendly Cat class="end-tag">a>

<%=
image_tag
item.imagethumburl %> 

calls the Rails helper method
 style="color: rgb(0, 0, 153); font-weight: bold;">image_tag
,
which generates an HTML image tag for the
item's
imagethumburl
 style="color: rgb(0, 0, 153); font-weight: bold;">
attribute. 



  style="font-weight: bold;"><%=h
item.price %>

displays the value of the 
 style="color: rgb(0, 0, 153); font-weight: bold;">item 's price 
attribute.The
Rails
 style="font-weight: bold;">h
method creates
escaped HTML text.


<%=
link_to 'Previous page',{:page =>
@item_pages.current.previous}
style="color: rgb(0, 0, 153); font-weight: bold;">if
@item_pages.current.previous %>

creates an html link to the previous
page of items, using the style="font-family: monospace; color: rgb(0, 0, 153); font-weight: bold;">@item_pages
paginator instance, if there is a previous page.


The Show Action Method

In Rails the mapping for the URL http://host class="attribute-value">/item/show/1  (
http://host/controller/action/id ) to
action method will
route to the style="color: rgb(0, 0, 153); font-weight: bold;">show
action method in the style="color: rgb(0, 0, 153); font-weight: bold;">ItemController
passing 1 to the method as the style="color: rgb(0, 0, 153); font-weight: bold;">id
member of the style="color: rgb(0, 0, 153); font-weight: bold;">params parameter
hash. The style="color: rgb(0, 0, 153); font-weight: bold;">show
action method of the style="color: rgb(0, 0, 153); font-weight: bold;">ItemController class
is shown below. The style="color: rgb(0, 0, 153); font-weight: bold;">ItemController
style="color: rgb(0, 0, 153); font-weight: bold;">show
action renders a view showing the details of the item object
corresponding to the id parameter.


Code Sample from: app/controllers/item_controller.rb


  def show

    style="color: rgb(0, 0, 153); font-weight: bold;">@item =
Item.find(params[:id])


  end



 

     



The style="color: rgb(0, 0, 153); font-weight: bold;">show
action method  calls the style="color: rgb(0, 0, 153); font-weight: bold;">Item style="font-family: monospace;"> style="color: rgb(0, 0, 153); font-weight: bold;">

ActiveRecord Base class style="color: rgb(0, 0, 153); font-weight: bold;">find method
which queries the items table creating the style="font-family: monospace;">
 style="font-family: monospace;"> style="color: rgb(0, 0, 153); font-weight: bold;">@item instance
variable corresponding to the item with the attribute id (primary key)
equal to the  style="color: rgb(0, 0, 153); font-weight: bold;">id
parameter. This is the equivalent of the following sql : style="font-family: monospace;">select * from items where id=' style="font-family: monospace;"> style="color: rgb(0, 0, 153); font-weight: bold;">1' .
The style="color: rgb(0, 0, 153); font-weight: bold;">@item variable
is automatically made available to the Show view by the framework. style="font-weight: bold;">




The Show View Template


After executing
code in the action, the style="color: rgb(0, 0, 153); font-weight: bold;">show action
renders the app/views/item/show.rthml template. Below is the RHTML for
the item show view :






 
   
     
   
   
     
Code Sample from: app/views/item/show.rhtml

     


Detail of item





 

   

     

     

   

   

     

     

   

   

     

     

   

   

     

     

   

   

     

     

   

   

     

     

   

 

Name:  style="color: rgb(0, 0, 153); font-weight: bold;"><%=h
@item.name%>
Description: style="color: rgb(0, 0, 153); font-weight: bold;"><%=h
@item.description%>
Photo: style="color: rgb(0, 0, 153); font-weight: bold;"><%= image_tag
@item.imageurl %>
Price: style="color: rgb(0, 0, 153); font-weight: bold;"><%=h
@item.price%>
Seller's Location:

        style="color: rgb(0, 0, 153); font-weight: bold;"><%=h
@item.address.city%> ,

        style="color: rgb(0, 0, 153); font-weight: bold;"><%=h
@item.address.state%>

     
Seller's email: style="color: rgb(0, 0, 153); font-weight: bold;"><%=h
@item.contactinfo.email%>
  





<%=h
@item.description%>
displays the value of the 
 style="color: rgb(0, 0, 153); font-weight: bold;">item 's 
description
 style="color: rgb(0, 0, 153); font-weight: bold;"> 
attribute,
in escaped HTML text.
<%=
image_tag
@item.imageurl %>

generates an HTML
image tag for the
 style="color: rgb(0, 0, 153); font-weight: bold;">item's imageurl

attribute.

<%=h
@item.address.city%>

displays the value of the 
 style="color: rgb(0, 0, 153); font-weight: bold;">item's 
 style="font-family: mon;">address city
 style="color: rgb(0, 0, 153); font-weight: bold;"> 
attribute,
in escaped HTML text.


The image below shows the resulting page for the url
http://host/item/show/id, which displays the item's details:


    
petcat_detail.jpg


Layout Templates

Rails layout templates let you put common html on multiple views (for
example page headers,  footers, sidebars). By default layout
templates are in the views layouts directory with a file name
corresponding to the controller. To add a title and parrot image to the
top of the Pet Catalog pages, I put this table in the
app\views\layouts\item.rhtml  template:


Code Sample from: app/views/layouts/item.rhtml




 

  

  

 

Pet Catalog src="/images/banner_logo.gif">




     







Conclusion

This concludes the sample application which demonstrates how to work
with JRuby and Rails  to page through a list
of  Item Model objects
which are retrieved using Item
Controller action methods, and
displayed using Item rhtml View
templates.


Running the Sample Application:

Setting Things Up

  1. href="http://dlc.sun.com/netbeans/download/6.0/milestones/latest/">Download
    and install NetBeans 6.0 Beta 1. Get the full distribution so you can
    get the Java IDE, Ruby and GlassFish.


  2. Configure JRuby to use the
    Derby Database
    (by default Ruby uses MySQL, but I use Derby
    because I like it. If you prefer MySQL, then ignore this ,  change
    the
    RRCatalog\config\database.yml file, and add the tables below to your
    MySQL db )

    1. Open the Tools Options dialog to find the location of your
      JRuby
      interpreter.
    2. Copy the following jar to your JRuby lib directory:
      derbyclient.jar (Tools > Java DB Database > Settings will give
      you the location of derbyclient.jar)

Open and Run the Sample code:

  1. Download the href="http://techdayscode.dev.java.net/servlets/ProjectDocumentList?folderID=8159">sample
    code and extract its contents. You should now see the newly
    extracted directory as /RRCatalog,
    where is the directory where
    you unzipped the sample package. For example, if you extracted the
    contents to C:\ on a Windows machine, then your newly
    created directory should be at C:\RRCatalog.


  2. Start the NetBeans IDE. Click Open Project in the File menu and
    select
    the RRCatalog directory you just unzipped.


  3. Start the Java DB database as follows:


    • Select Java DB Database in the Tools menu.
    • Select Start Java DB Server.


  4. Add a connection to the Java DB database as follows:


    • Select the Services Tab on the left.
    • Select Databases, Right mouse click and select New Connection.
    • In the New DB Connection window:

        for Name: select Java DB (Network)

        for URL enter: jdbc:derby://localhost:1527/pet-catalog

        for username enter: app , for password enter: app


  5. Create the tables in the pet-catalog database as follows:


    • Under Databases, select the connection pet-catalog that you
      just created. Right mouse click and select Connect.
    • enter the username app and password app.
    • Right mouse click on pet-catalog and select Excecute Command.

    • In the SQL command window copy paste all the sql text from
      the file /RRCatalog/catalog.sql,

    • At the top of the window click on the icon for Run SQL. This
      will create all of the tables and data for the application.


  6. Run the project as follows:


    • Right click the RRCatalog node in the Projects
      window.
    • Select Run.  This will run the Application with the
      WEBrick server.

When you run the project, your browser should display the List Items
page
of the Sample Application (at http://localhost:3000/).




Run the Sample code on Glassfish:

  1. Use the  WAR file in
    /RRCatalog/RRCatalog.war
       
    or Create a WAR file:
    • In the NetBeans IDE, right-select the project, select
      Run
      Rake Target, war, standalone, create



  2. Copy the WAR file (RRCatalog.war) to  your
    Glassfish installation "domains/domain/autodeploy"
    directory.


  3. Enter the URL  http://localhost:8080/RRCatalog/  in
    your browser, you should see the display the List Items
    page of the Sample Application.

References

  • To learn how to build a Ruby Rails app froms scratch see: href="http://www.netbeans.org/kb/60/ruby/rapid-ruby-weblog.html">Creating
    a
    Ruby Weblog with Netbeans 6 in 10 Minutes
  • To learn how to run a JRuby app on Glassfish see: href="http://blogs.sun.com/arungupta/entry/jruby_on_rails_netbeans_and">JRuby
    on Rails, NetBeans 6 and GlassFish V2 - Simplified Steps
  • To learn how to run a JRuby app on Glassfish using the Derby db
    see: href="http://weblogs.java.net/blog/arungupta/archive/2007/08/totd_3_using_ja.html">Using
    JavaDB with JRuby on Rails
  • Rails framework
    documentation

  • Ruby on Rails Wiki
  • href="http://www.onlamp.com/pub/a/onlamp/2005/10/13/what_is_rails.html?page=5">What
    is Ruby on Rails article
  • JRuby Inside web site
  • Ruby on
    Rails: Up and Running Book
  • Rails for Java
    Developers book


Related Topics >>