Miles to go …

November 18, 2008

TOTD #53: Scaffold in Merb using JRuby/GlassFish

Filed under: rails, totd — arungupta @ 5:00 am

GlassFish Gem 0.9.0 can be used to run Rails and Merb applications. Support another Rack-based framework Sinatra is coming up in the near future. This blog shows how to create a scaffold in Merb and run it using the GlassFish gem.

Merb allows pluggable ORM and comes with DataMapper as the default one. However DataMapper has native dependencies and so cannot be used with JRuby. There is discussion about creating a DataMapper adapter over JDBC but in the meanwhile ActiveRecord is the only ORM that can be used with JRuby.

Merb wiki has extensive documentation but lacks clearly defined steps for generating scaffold when using ActiveRecord. This blog fulfills those gaps and provides a comprehensive tutorial to build a Merb scaffold.

  1. Lets create a Merb application using ActiveRecord ORM as:

    ~/samples/jruby/merb >~/tools/jruby-1.1.5/bin/jruby -S merb-gen core –orm activerecord hello
    Generating with core generator:
         [ADDED]  gems
         [ADDED]  merb.thor
         [ADDED]  .gitignore
         [ADDED]  public/.htaccess
         [ADDED]  doc/rdoc/generators/merb_generator.rb
         [ADDED]  doc/rdoc/generators/template/merb/api_grease.js
         [ADDED]  doc/rdoc/generators/template/merb/index.html.erb
         [ADDED]  doc/rdoc/generators/template/merb/merb.css
         [ADDED]  doc/rdoc/generators/template/merb/merb.rb
         [ADDED]  doc/rdoc/generators/template/merb/merb_doc_styles.css
         [ADDED]  doc/rdoc/generators/template/merb/prototype.js
         [ADDED]  public/favicon.ico
         [ADDED]  public/merb.fcgi
         [ADDED]  public/robots.txt
         [ADDED]  public/images/merb.jpg
         [ADDED]  Rakefile
         [ADDED]  app/controllers/application.rb
         [ADDED]  app/controllers/exceptions.rb
         [ADDED]  app/helpers/global_helpers.rb
         [ADDED]  app/views/exceptions/not_acceptable.html.erb
         [ADDED]  app/views/exceptions/not_found.html.erb
         [ADDED]  autotest/discover.rb
         [ADDED]  autotest/merb.rb
         [ADDED]  autotest/merb_rspec.rb
         [ADDED]  config/init.rb
         [ADDED]  config/rack.rb
         [ADDED]  config/router.rb
         [ADDED]  config/environments/development.rb
         [ADDED]  config/environments/production.rb
         [ADDED]  config/environments/rake.rb
         [ADDED]  config/environments/staging.rb
         [ADDED]  config/environments/test.rb
         [ADDED]  public/javascripts/application.js
         [ADDED]  public/stylesheets/master.css
         [ADDED]  spec
         [ADDED]  app/views/layout/application.html.erb
  2. Generate a Merb resource (model, controller and associated things):
    ~/samples/jruby/merb/hello >merb-gen resource Runner distance:float,minutes:integer
    Loading init file from /Users/arungupta/samples/jruby/merb/hello/config/init.rb
    Loading /Users/arungupta/samples/jruby/merb/hello/config/environments/development.rb
    Generating with resource generator:
    Loading init file from /Users/arungupta/samples/jruby/merb/hello/config/init.rb
    Loading /Users/arungupta/samples/jruby/merb/hello/config/environments/development.rb
    Loading init file from /Users/arungupta/samples/jruby/merb/hello/config/init.rb
    Loading /Users/arungupta/samples/jruby/merb/hello/config/environments/development.rb
    Loading init file from /Users/arungupta/samples/jruby/merb/hello/config/init.rb
    Loading /Users/arungupta/samples/jruby/merb/hello/config/environments/development.rb
    Loading init file from /Users/arungupta/samples/jruby/merb/hello/config/init.rb
    Loading /Users/arungupta/samples/jruby/merb/hello/config/environments/development.rb
         [ADDED]  spec/models/runner_spec.rb
         [ADDED]  app/models/runner.rb
         [ADDED]  schema/migrations/001_runner_migration.rb
         [ADDED]  spec/requests/runners_spec.rb
         [ADDED]  app/controllers/runners.rb
         [ADDED]  app/views/runners/index.html.erb
         [ADDED]  app/views/runners/show.html.erb
         [ADDED]  app/views/runners/edit.html.erb
         [ADDED]  app/views/runners/new.html.erb
         [ADDED]  app/helpers/runners_helper.rb
    resources :runners route added to config/router.rb

    As evident from the generated files Model, Controller, Helper and Views are generated. The Views are only template files with no code because this code end up getting changed anyway most of the times. Instead template Views can be written as explained in CRUD View Examples (more on this later).

  3. Configure Database
    1. Merb applications do not have a pre-generated “database.yml” so create one as:

      ~/samples/jruby/merb/hello >rake db:create
      (in /Users/arungupta/samples/jruby/merb/hello)
      JRuby limited openssl loaded. gem install jruby-openssl for full support.
      http://wiki.jruby.org/wiki/JRuby_Builtin_OpenSSL
      Loading init file from /Users/arungupta/samples/jruby/merb/hello/config/init.rb
      Loading /Users/arungupta/samples/jruby/merb/hello/config/environments/development.rb
      Loading init file from /Users/arungupta/samples/jruby/merb/hello/config/init.rb
      Loading /Users/arungupta/samples/jruby/merb/hello/config/environments/development.rb
       ~ It took: 0
       ~ Loading: Merb::BootLoader::MixinSession
       ~ It took: 0
       ~ Loading: Merb::BootLoader::BeforeAppLoads
       ~ It took: 0
       ~ Loading: Merb::Orms::ActiveRecord::Connect
       ~ No database.yml file found in /Users/arungupta/samples/jruby/merb/hello/config.
       ~ A sample file was created called database.yml.sample for you to copy and edit.
    2. Copy “config/database.yml.sample” to “config/database.yml”. Wonder why this step is explicitly required ?
    3. Edit database configuration such that it looks like:
      :development: &defaults
        :adapter: mysql
        :database: hello_development
        :username: root
        :password:
        :host: localhost
        :socket: /tmp/mysql.sock
        :encoding: utf8

      The changed lines are shown in bold.

    4. Create the database as:
      ~/samples/jruby/merb/hello >rake db:create
      (in /Users/arungupta/samples/jruby/merb/hello)
      JRuby limited openssl loaded. gem install jruby-openssl for full support.
      http://wiki.jruby.org/wiki/JRuby_Builtin_OpenSSL
      Loading init file from /Users/arungupta/samples/jruby/merb/hello/config/init.rb
      Loading /Users/arungupta/samples/jruby/merb/hello/config/environments/development.rb
      Loading init file from /Users/arungupta/samples/jruby/merb/hello/config/init.rb
      Loading /Users/arungupta/samples/jruby/merb/hello/config/environments/development.rb
       ~ It took: 0
       ~ Loading: Merb::BootLoader::MixinSession
       ~ It took: 0
       ~ Loading: Merb::BootLoader::BeforeAppLoads
       ~ It took: 0
       ~ Loading: Merb::Orms::ActiveRecord::Connect
       ~ Connecting to database…
       ~ It took: 0
       ~ Loading: Merb::BootLoader::LoadClasses
       ~ It took: 0
       ~ Loading: Merb::BootLoader::Router
       ~ Compiling routes…
       ~ It took: 0
       ~ Loading: Merb::BootLoader::Templates
       ~ It took: 0
       ~ Loading: Merb::BootLoader::MimeTypes
       ~ It took: 0
       ~ Loading: Merb::BootLoader::Cookies
       ~ It took: 0
       ~ Loading: Merb::BootLoader::SetupSession
       ~ It took: 1
       ~ Loading: Merb::BootLoader::SetupStubClasses
       ~ It took: 0
       ~ Loading: Merb::BootLoader::AfterAppLoads
       ~ It took: 0
       ~ Loading: Merb::BootLoader::ChooseAdapter
       ~ It took: 0
       ~ Loading: Merb::BootLoader::RackUpApplication
       ~ It took: 0
       ~ Loading: Merb::BootLoader::ReloadClasses
       ~ It took: 0
      DEPRECATION WARNING: You’re using the Ruby-based MySQL library that ships with Rails. This library will be REMOVED FROM RAILS 2.2. Please switch to the offical mysql gem: `gem install mysql`  See http://www.rubyonrails.org/deprecation for details. (called from mysql_connection at /Users/arungupta/tools/jruby-1.1.5/lib/ruby/gems/1.8/gems/activerecord-2.1.2/lib/active_record/connection_adapters/mysql_adapter.rb:81)
       ~   SQL (0.000581)   SET NAMES ‘utf8′
       ~   SQL (0.000581)   SET SQL_AUTO_IS_NULL=0
       ~   SQL (0.000894)   CREATE DATABASE `hello_development` DEFAULT CHARACTER SET `utf8` COLLATE `utf8_general_ci`
      MySQL hello_development database successfully created
    5. Migrate the database as:
      ~/samples/jruby/merb/hello >rake db:migrate
      (in /Users/arungupta/samples/jruby/merb/hello)
      JRuby limited openssl loaded. gem install jruby-openssl for full support.
      http://wiki.jruby.org/wiki/JRuby_Builtin_OpenSSL
      Loading init file from /Users/arungupta/samples/jruby/merb/hello/config/init.rb
      Loading /Users/arungupta/samples/jruby/merb/hello/config/environments/development.rb
      Loading init file from /Users/arungupta/samples/jruby/merb/hello/config/init.rb
      Loading /Users/arungupta/samples/jruby/merb/hello/config/environments/development.rb
       ~ It took: 0
       ~ Loading: Merb::BootLoader::MixinSession
       ~ It took: 0
       ~ Loading: Merb::BootLoader::BeforeAppLoads
       ~ It took: 0
       ~ Loading: Merb::Orms::ActiveRecord::Connect
       ~ Connecting to database…
       ~ It took: 0
       ~ Loading: Merb::BootLoader::LoadClasses
       ~ It took: 1
       ~ Loading: Merb::BootLoader::Router
       ~ Compiling routes…
       ~ It took: 0
       ~ Loading: Merb::BootLoader::Templates
       ~ It took: 0
       ~ Loading: Merb::BootLoader::MimeTypes
       ~ It took: 0
       ~ Loading: Merb::BootLoader::Cookies
       ~ It took: 0
       ~ Loading: Merb::BootLoader::SetupSession
       ~ It took: 0
       ~ Loading: Merb::BootLoader::SetupStubClasses
       ~ It took: 0
       ~ Loading: Merb::BootLoader::AfterAppLoads
       ~ It took: 0
       ~ Loading: Merb::BootLoader::ChooseAdapter
       ~ It took: 0
       ~ Loading: Merb::BootLoader::RackUpApplication
       ~ It took: 0
       ~ Loading: Merb::BootLoader::ReloadClasses
       ~ It took: 0
      DEPRECATION WARNING: You’re using the Ruby-based MySQL library that ships with Rails. This library will be REMOVED FROM RAILS 2.2. Please switch to the offical mysql gem: `gem install mysql`  See http://www.rubyonrails.org/deprecation for details. (called from mysql_connection at /Users/arungupta/tools/jruby-1.1.5/lib/ruby/gems/1.8/gems/activerecord-2.1.2/lib/active_record/connection_adapters/mysql_adapter.rb:81)
       ~   SQL (0.000769)   SET NAMES ‘utf8′
       ~   SQL (0.000610)   SET SQL_AUTO_IS_NULL=0
       ~   SQL (0.001609)   SHOW TABLES
       ~   SQL (0.003952)   CREATE TABLE `schema_migrations` (`version` varchar(255) NOT NULL) ENGINE=InnoDB
       ~   SQL (0.054355)   CREATE UNIQUE INDEX `unique_schema_migrations` ON `schema_migrations` (`version`)
       ~   SQL (0.001691)   SHOW TABLES
       ~   SQL (0.001643)   SELECT version FROM schema_migrations
       ~ Migrating to RunnerMigration (1)
      == 1 RunnerMigration: migrating ===============================================
      — create_table(:runners)
       ~   SQL (0.005301)   CREATE TABLE `runners` (`id` int(11) DEFAULT NULL auto_increment PRIMARY KEY, `distance` float, `minutes` int(11), `created_at` datetime, `updated_at` datetime) ENGINE=InnoDB
         -> 0.0107s
      == 1 RunnerMigration: migrated (0.0114s) ======================================

       ~   SQL (0.014063)   INSERT INTO schema_migrations (version) VALUES (‘1′)
       ~   SQL (0.003585)   SHOW TABLES
       ~   SQL (0.001324)   SELECT version FROM schema_migrations
       ~   SQL (0.001451)   SHOW TABLES
       ~   SQL (0.017054)   SHOW FIELDS FROM `runners`
       ~   SQL (0.018503)   describe `runners`
       ~   SQL (0.009372)   SHOW KEYS FROM `runners`

  4. Create the CRUD views
    1. Add dependencies
      1. Edit “config/init.rb” and add the following line:

        require ‘config/dependencies.rb’

        as the first uncommented line.

      2. Create “config/dependencies.rb” and add the following dependency (explained here):
        dependency “merb-assets”, “1.0″
        dependency “merb-helpers”, “1.0″
    2. Add the resource routes by editing “config/router.rb” and adding:
      resources :runners

      insider “Merb::Router.prepare do” block.

    3. Edit the “index” view in “app/views/runners/index.html.erb” as:
      <h1>Runner controller, index action</h1>

      <table>
        <tr>
          <th>Distance (in miles)</th>
          <th>Time (in mins)</th>

          <th colspan=”3″>Actions</th>
        </tr>

      <% @runners.each do |runner| %>
        <tr>
          <td><%=h runner.distance %></td>
          <td><%=h runner.minutes %></td>

          <td><%= link_to ‘Show’, resource(runner) %></td>
          <td><%= link_to ‘Edit’, resource(runner, :edit) %></td>
          <td><%= delete_button(runner, “Delete #{runner.distance}”) %></td>
        </tr>
      <% end %>
      </table>

      <%= link_to ‘New’, resource(:runners, :new) %>

    4. Edit the “new” in “app/views/runners/new.html.erb” view as:
      <h1>Runners controller, new action</h1>

      <%= form_for(@runner, :action => resource(:runners) ) do %>
       
        <p>
          <%= text_field :distance, :label => “Distance (in miles)” %>
        </p>
       
        <p>
          <%= text_field :minutes, :label => “Time (in mins)”  %>
        </p>
       
        <p>
          <%= submit “Create” %>
        </p>
      <% end =%>
       
      <%= link_to ‘Back’, resource(:runners) %>

    5. Edit the “show” view in “app/views/runners/show.html.erb” as:
      <h1>Runners controller, show action</h1>

      <p>Distance (in miles): <%=h @runner.distance %></p>
      <p>Time (in mins): <%=h @runner.minutes %></p>
       
      <%= link_to ‘Back’, resource(:runners) %>

    6. Edit the “edit” in “app/views/runners/edit.html.erb” view as:
      <h1>Runners controller, edit action</h1>

      <%= form_for(@runner, :action => resource(@runner)) do %>
       
        <p>
          <%= text_field :distance, :label => “Distance (in miles)”  %>
        </p>
       
        <p>
          <%= text_field :minutes, :label => “Time (in mins)”  %>
        </p>
       
        <p>
          <%= submit “Update” %>
        </p>
      <% end =%>
       
      <%= link_to ‘Show’, resource(@runner) %> | <%= link_to ‘Back’, resource(:runners) %>

That’s it!

And now here are some of the captured outputs.

The default output at “http://localhost:3000/runners”

Creating a new Runner at “http://localhost:3000/runners/new” as:

“Show” view of a runner at “http://localhost:3000/runners/<id>” as :

“Index” view with one runner at “http://localhost:3000/runners” as:

And now “index” view with 2 runners at “http://localhost:3000/runners” as:

A Merb app generated using MRI can also be run using GlassFish, provided it does not have any native dependencies.

And another useful piece of information is difference between Rails and Merb provide comparative syntax between Rails and Merb.

And thanks to all the discussion on merb@googlegroups where all my questions were answered very promptly!

Submit your bugs here, talk to us using GlassFish Forum, and get the latest information on JRuby wiki.

Technorati: totd glassfish v3 gem jruby rubyonrails merb

Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • DZone
  • StumbleUpon
  • Technorati
  • Twitter
  • Slashdot
Related posts:
  1. TOTD #52: Getting Started with Merb using GlassFish Gem
  2. Merb on JRuby 1.1 RC3
  3. TOTD #73: JRuby and GlassFish Integration Test #4: JRuby 1.2.0 RC2 + Rails 2.2.x + GlassFish v2 + Warbler
  4. TOTD #70: JRuby and GlassFish Integration Test# 1: JRuby 1.2.0 RC1 + Rails 2.2.x + GlassFish Gem
  5. TOTD #71: JRuby and GlassFish Integration Test #2: JRuby 1.2.0 RC1 + Rails 2.2.x + GlassFish v3 Prelude

5 Comments »

  1. [Trackback] GlassFish v3 with Merb and Warbler explains how to use Warbler to deploy a Merb application on GlassFish v3. Here is a quote&nbsp;from the blog: this lovely server had a gem which you can use to fire up a…

    Comment by Arun Gupta's Blog — December 3, 2008 @ 9:15 am

  2. [Trackback] Supper Happy Dev House is "a premier monthly hackathon event that combines serious and not-so-serious productivity with a fun and exciting party atmosphere." The 30th monthly event was hosted at Sun Microsystem’s Executive Briefing Center (aka EBC) in…

    Comment by Arun Gupta's Blog — February 3, 2009 @ 5:39 am

  3. thank u arun. Thanks for information

    Comment by sinema izle — March 13, 2009 @ 1:31 pm

  4. [Trackback] Sinatra is a DSL for quickly creating web-applications in Ruby with minimal effort. Like Rails and Merb, Sinatra is not an MVC framework and basically follows a flat-file structure instead. The framework define conventions such as location of static…

    Comment by Arun Gupta's Blog — April 28, 2009 @ 6:16 am

  5. [Trackback] This is a follow up post from David’s keynote. Attended Women in Rails panel discussion. The panel, Sarah Mei, Lori Olson, and Desi McAdam (from L to R), had a very interesting discussion around the genuine problems and possible solutions…

    Comment by Arun Gupta's Blog — May 6, 2009 @ 5:40 am

RSS feed for comments on this post. TrackBack URL

Leave a comment

Powered by WordPress