Skip to main content

TOTD #53: Scaffold in Merb using JRuby/GlassFish

Posted by arungupta on November 18, 2008 at 6:04 AM PST



href="http://blogs.sun.com/arungupta/entry/getting_started_with_merb_using">GlassFish
Gem 0.9.0 can be used to run href="http://rubyonrails.org">Rails and href="http://merbivore.com">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.


style="width: 441px; height: 298px;" alt=""
src="http://blogs.sun.com/arungupta/resource/images/ruby-frameworks-glassfish.png">



Merb allows pluggable ORM and comes with href="http://www.datamapper.org/">DataMapper as
the default one. However href="http://groups.google.com/group/merb/browse_thread/thread/8a3f0433a1fa1fed">DataMapper
has native dependencies and so cannot be used with href="http://jruby.org">JRuby.
There is discussion about creating a href="http://groups.google.com/group/merb/msg/6de5c0b6c956059a">DataMapper
adapter over JDBC but in the meanwhile href="http://ar.rubyonrails.com/">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:


    style="text-align: left; background-color: rgb(204, 204, 255); width: 100%;"
    cellpadding="2" cellspacing="2">
    ~/samples/jruby/merb > style="font-weight: bold;">~/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):


    style="text-align: left; background-color: rgb(204, 204, 255); width: 100%;"
    cellpadding="2" cellspacing="2">
    ~/samples/jruby/merb/hello > style="font-weight: bold;">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 href="http://wiki.merbivore.com/howto/crud_view_example_with_merb_using_erb">CRUD
    View Examples (more on this later).

  3. Configure Database
    1. Merb applications href="http://groups.google.com/group/merb/msg/9866fead9d19e4bd">do
      not have a pre-generated "database.yml" so create one as:


      cellpadding="2" cellspacing="2">
      ~/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:


      style="text-align: left; background-color: rgb(204, 204, 255); width: 100%;"
      cellpadding="2" cellspacing="2">
      :development: &defaults

        :adapter: mysql

       
      :database: hello_development
      style="font-weight: bold;">
       
      :username: root


       
      :password:


        :host: localhost

        :socket: /tmp/mysql.sock

        :encoding: utf8



      The changed lines are shown in bold.

    4. Create the database as:


      style="text-align: left; background-color: rgb(204, 204, 255); width: 100%;"
      cellpadding="2" cellspacing="2">
      ~/samples/jruby/merb/hello > style="font-weight: bold;">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:


      cellpadding="2" cellspacing="2">
      ~/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:


        style="text-align: left; background-color: rgb(204, 204, 255); width: 100%;"
        cellpadding="2" cellspacing="2">
        require 'config/dependencies.rb'



        as the first uncommented line.

      2. Create "config/dependencies.rb" and add the following
        dependency ( href="http://wiki.merbivore.com/howto/crud_view_example_with_merb_using_erb">explained
        here):


        style="text-align: left; background-color: rgb(204, 204, 255); width: 100%;"
        cellpadding="2" cellspacing="2">
        dependency "merb-assets", "1.0"

        dependency "merb-helpers", "1.0"
    2. Add the href="http://wiki.merbivore.com/development/resource_urls">resource
      routes by editing "config/router.rb" and adding:


      style="text-align: left; background-color: rgb(204, 204, 255); width: 100%;"
      cellpadding="2" cellspacing="2">
      resources :runners



      insider "Merb::Router.prepare do" block.

    3. Edit the "index" view in
      "app/views/runners/index.html.erb" as:


      style="text-align: left; background-color: rgb(204, 204, 255); width: 100%;"
      cellpadding="2" cellspacing="2">
      <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:


      style="text-align: left; background-color: rgb(204, 204, 255); width: 100%;"
      cellpadding="2" cellspacing="2">
      <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:


      style="text-align: left; background-color: rgb(204, 204, 255); width: 100%;"
      cellpadding="2" cellspacing="2">
      <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:


      style="text-align: left; background-color: rgb(204, 204, 255); width: 100%;"
      cellpadding="2" cellspacing="2">
      <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"



alt=""
src="http://blogs.sun.com/arungupta/resource/images/merb-scaffold-runners-index-default.png">



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



alt=""
src="http://blogs.sun.com/arungupta/resource/images/merb-scaffold-runners-new.png">



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



alt=""
src="http://blogs.sun.com/arungupta/resource/images/merb-scaffold-runners-show.png">



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



alt=""
src="http://blogs.sun.com/arungupta/resource/images/merb-scaffold-runners-index-1.png">



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



alt=""
src="http://blogs.sun.com/arungupta/resource/images/merb-scaffold-runners-index-2.png">



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 href="http://wiki.merbivore.com/what_s_the_difference_between_rails_and_merb">difference
between Rails and Merb provide comparative syntax between
Rails and Merb.



And thanks to all the discussion on href="http://groups.google.com/group/merb/browse_thread/thread/fc7960afaaf760f2">merb@googlegroups
where all my questions were answered very promptly!



Submit your bugs href="http://rubyforge.org/tracker/?func=add&group_id=5450&atid=21080">here,
talk to us using href="http://forums.java.net/jive/forum.jspa?forumID=56&start=0">GlassFish
Forum, and get the latest information on href="http://wiki.glassfish.java.net/Wiki.jsp?page=JRuby">JRuby
wiki.



Technorati: href="http://technorati.com/tag/glassfish">glassfish
v3 href="http://technorati.com/tag/gem">gem href="http://technorati.com/tag/jruby">jruby href="http://technorati.com/tag/rubyonrails">rubyonrails
merb

Related Topics >>