Ruby on Rails

Introduction to the rails platform for web application development.

1 History

David Hansson

2 Install Ruby On Rails with NetBeans

Rails recently went to 2.0 and the jruby that comes with netbeans does not seem to like it. Thus, ugliness:
  1. Install NetBeans 1.0.1. You might have to erase ~/.netbeans*
  2. Go to Tools->Plugins then update. Quit.
  3. Download and install jruby 1.0.3 [5].
  4. Start netbeans then create a new ruby on rails project:
    1. Select jRuby but set it to use the 1.0.3 binary.
    2. Update to rails 2.0
    3. Install JRuby openssl support.
    4. Select javaDB if you want to use derby (didn't work well for me: could not update).
  5. Copy derby.jar from glassfish subdir to netbeans/ruby1/jruby/lib (the database.yml file will remind you of this step.)

3 Demo

4 The Big Picture

5 The Model

5.1 ActiveRecord Model Relations

orders
id int
customer_id int
line_items
id int
order_id int
customers
id int
name string
addresses
id int
customer_id int
#Notice that the classes are in the Singular
class Order < ActiveRecord::Base
  has_many :line_items
  belongs_to :customer #there is a column customer_id in the table
end

class LineItem < ActiveRecord::Base
  belongs_to :order #there is a column order_id in the table
end

class Customer < ActiveRecord::Base
  has_many :orders
  has_one :address
end

class Address < ActiveRecord::Base
  belongs_to :customer
end

#It inherits a LOT of methods from ActiveRecord

myorder = Order.create(:customer_id => 33)

myorder.customer_id #get the customer_id for this order

myorder.name #gets Customer's name (assume 'name' column in customer table)

Order.find(:all) #all orders

#Other examples (assume the Company model has been defined with the appropriate columns).
Company.find(:first, :conditions => [
    "id = :id AND name = :name AND division = :division AND created_at > :accounting_date",
    { :id => 3, :name => "37signals", :division => "First", :accounting_date => '2005-01-01' }
])

Student.find(:all, :conditions => { :grade => 9..12 })



5.2 Many To Many Relations

products
id int
name string
categories
id int
name string
categories_products
category_id int
product_id int
class Category < ActiveRecord::Base
  has_and_belongs_to_many :products
end

class Product < ActiveRecord::Base
  has_and_belongs_to_many :categories
end

#You can now use

acategory.products #get all products with acategory
aproduct.categories #yes, it pluralizes category correctly

5.3 Through

class Author < ActiveRecord::Base
  has_many :authorships
  has_many :books, :through => :authorships
end

class Authorship < ActiveRecord::Base
  belongs_to :author
  belongs_to :book
end

@author = Author.find :first
@author.authorships.collect { |a| a.book } # selects all books that the author's authorships belong to.
@author.books                              # selects all books by using the Authorship join model


6 Scaffolding

7 Views

<h1>Listing posts</h1>


<% for post in @posts %>
  <h2><%=h post.title %></h2>
  <p><%=h post.body %></p>
  <p><%= link_to 'Show', post %> <%= link_to 'Edit', edit_post_path(post) %>
  <%= link_to 'Destroy', post, :confirm => 'Are you sure?', :method => :delete %></p>
<% end %>

<br/>

<%= link_to 'New post', new_post_path %>

7.1 View Helpers

#create a link to controller 'categories' at action 'list'
link_to "text of link", :controller => 'categories', :action => 'list'

image_tag "spinner.png", :class => "image", :alt => "Spinner"

stylesheet_link_tak "scaffold", "admin", :media => "all"

#Forms
<%
form_for :person, @person, :url => {:action => "update"},
  :html => {:id => 'person_form'} do |f|
%>

First name: <%= f.text_field :first_name %>
Age: <%= f.text_field :age, :size => 2 %>
Bio: <%= f.text_area :biography %>

<% end %>

#To insert a text field
text_field :modelname, :attribute_name, options
password_field....
file_field
text_area

#this
radio_button "model", "category", "rails"
#turns into this
<input type="radio" id="post_category" name="post[category]" value="rails"
   checked="checked"/>


check_box "post", "validated" #post.validated? return 1 or 0
#turns into
<input type="checkbox" id="post_validate" name="post[validated]"
       value="1" checked="checked"/>
<input name="post[validated]" type="hidden" value="0"/>

   

select "post", "person_id", Person.find_all.collect {|p| [p.name, p.id]},
    {:include_blank => true}
#turns into
<select name="post[person_id]">
  <option></option>
  <option value="1" selected="selected">David</option>
  <option value="2">Sam</option>
  <option value="3">Tobias</option>
</select>

7.2 Layouts

8 Ajax

The basic sequence: (documentation [14])
  1. A trigger action occurs on page (user clicks, timer)
  2. Data associated with trigger (field, form) sent to server via XHR.
  3. Server action handler is invoked, returns HTML.
  4. Client Javascript updates page using HTML.
<html>
  <head>
    <title>Ajax Demo</title>

    <!-- tell rails to include prototype.js -->
    <%= javascript_include_tag "prototype" %>
    
  </head>
  <body>
      <h1>What time is it?</h1>
      <div id="time_div">
        I don't have the time, but
        
        <!-- Create a link which calls the server-side action /say-when -->
        <!-- and then updates the "time_div" div with the results -->
        <%= link_to_remote( "click here", :update => "time_div",
            :url =>{ :action => :say_when }) %>
        and I will look it up.
      </div>
    </body>
</html>

On the server side the action is
class DemoController < ApplicationController

  def index
  end

  def say_when
    render_text "<p>The time is <b>" + DateTime.now.to_s + "</b></p>"
  end
end

8.2 form_remote_tag

<html>
<head>
    <title>Ajax List Demo</title>
  <%= javascript_include_tag "prototype" %>
  </head>
    <body>
      <h3>Add to list using Ajax</h3>

      <!-- Start the Ajax form -->
      <%= form_remote_tag(:update => "my_list",
        :url => { :action => :add_item },
        :position => "top" ) %>

       New item text:

      <!-- Add a text field to this form -->
      <%= text_field_tag :newitem %>

      <!-- Add a submit button -->
      <%= submit_tag "Add item with Ajax" %>

      <!-- End the form: </form>-->
      <%= end_form_tag %>

      <ul id="my_list">
        <li>Original item... please add more!</li>
      </ul>
    </body>
</html>

On the server, the controller says:
class ListdemoController < ApplicationController

  def index
  end

  def add_item
    # Get the text the user typed in using params[:newitem]
    render_text "<li>" + params[:newitem] + "</li>"
  end
end

8.3 Observers

<!--Implement a live search: update as the user types-->
Live Search: <%= text_field_tag :searchtext %>

<%= observe_field(:searchtext,
      :frequency => 0.25,
      :update => :search_hits,
      :url => { :action => :live_search }) %>

<p>Search Results:</p>
<div id="search_hits"></div>

URLs

  1. Ruby on Rails: Up and Running, http://jmvidal.cse.sc.edu/lib/tate06a.html
  2. Ruby on Rails demo, http://youtube.com/watch?v=Gzj723LkRJY
  3. api.rubyonrails.com, http://api.rubyonrails.com
  4. Basecamp, http://www.basecamphq.com
  5. jruby 1.0.3, http://dist.codehaus.org/jruby/
  6. the video, http://youtube.com/watch?v=Gzj723LkRJY
  7. this tutorial, http://blogs.sun.com/divas/entry/creating_a_rails_2_0
  8. ActiveRecord, http://api.rubyonrails.com/classes/ActiveRecord/Base.html
  9. wikipedia:Object-relational_mapping, http://www.wikipedia.org/wiki/Object-relational_mapping
  10. wikipedia:WebObjects, http://www.wikipedia.org/wiki/WebObjects
  11. wikipedia:Apache_Cayenne, http://www.wikipedia.org/wiki/Apache_Cayenne
  12. wikipedia:Java_Data_Objects, http://www.wikipedia.org/wiki/Java_Data_Objects
  13. Module ActiveRecord::Associations::ClassMethods documentation, http://api.rubyonrails.com/classes/ActiveRecord/Associations/ClassMethods.html
  14. documentation, http://rails.rubyonrails.com/classes/ActionView/Helpers/PrototypeHelper.html
  15. link_to_remote, http://api.rubyonrails.com/classes/ActionView/Helpers/PrototypeHelper.html#M000958
  16. form_remote_tag, http://api.rubyonrails.com/classes/ActionView/Helpers/PrototypeHelper.html#M000960

This talk available at http://jmvidal.cse.sc.edu/talks/rubyonrails/
Copyright © 2009 José M. Vidal . All rights reserved.

01 April 2008, 02:44PM