SlideShare una empresa de Scribd logo
1 de 70
Descargar para leer sin conexión
Web Development with

Ruby On Rails

Pedro Cunha
Ruby

Yukihiro "Matz" Matsumoto
       Ruby is designed for programmer
                    productivity and fun


                       Created February 1993
Ruby
Everything is an object     Dynamic Typing

 true.class # TrueClass   class Foo

 nil.class # NilClass       def initialize(x, y)

                              @x = x
                              @y = y
                            end
                          end

                          class Foo2
                          end

                          Foo.new(2, Foo2.new)
Ruby
class Foo                        class Bar
  # Parenthesis can be omitted     # Use ! if you change self
  def method                       def method!
    puts "Hello World"             end
  end
                                   # Use ? if you return a boolean
  # Default params                 def method?
  def method2(x = 2)               end
    puts x
  end                              # Only conventions
                                 end
  # Operator overload
  def +(x)
  end
end
Ruby
"hello".class # String
:hello.class # Symbol          a = "Hello"
                               b = "Hello"
# Convention
# Use string if you plan to    a.equal? b # false
compute text
                               x = :hello
# Use symbols if you want to   y = :hello
define or/and set a
behaviour which is not         x.equal? y # true
expected to change
Ruby
a = {}
a[:first] = 2
a[:things] = 3
a[:foo] = "bar"

b = {
        :first => 2,
        :things => 3,
        :foo => "bar"
}

b[:first] # 2
Ruby
x = [1,4,5,2,5,8,10]

x.sort # returns a copy of x sorted
[1,2,4,5,5,8,10]
x.sort! # modifies self

x.map{ |i| i + 4 } # [5,6,8,9,9,12,14]
x.map! do |i|
  i + 4
end # [5,6,8,9,9,12,14]
Ruby
             Monkey Patching

class String
  def +()
    # override string default + operator
  end
end




              “With great power comes great responsability”
                        Uncle Ben, Amazing Spiderman nº1
Ruby on Rails
Ruby on Rails
Created by David Heinemeir Hansson
• CEO at 37th Signals
• Personal Project, 2004
Present
• Rails 3.1
• Growing community
Ruby on Rails

Convention vs Configuration
MVC Architecture
REST routing
Convention
vs Configuration
• Don’t Repeat Yourself
• Increased productivity through
  conventions. Ex.: following a pattern for
  foreign key columns.

• Take advantage of singular and plural word
  meanings
MVC
RoR
REST
Representational State Transfer
CRUD      REST ROUTES

CREATE   POST /posts
READ     GET    /posts/1
UPDATE   PUT    /posts/1
DELETE   DELETE /posts/1
# routes.rb
Blog::Application.routes.draw do
  resources :posts
end
RoR
Starting development
pcunha:prompt$ rails new Blog -d mysql

Blog
 /app
       /controllers
       /mailers
       /models
       /views
 /config
       database.yml
 /db
       /migrate
 Gemfile
 /public
       /javascripts
       /stylesheets
# config/database.yml
development:
  adapter: sqlite3
  database: db/development.sqlite3

test:
  adapter: sqlite3
  database: db/test.sqlite3

production:
  adapter: sqlite3
  database: db/production.sqlite3
development:
  adapter: mysql2
  encoding: utf8
  database: Blog_development
  username: root
  password:

test:
  adapter: mysql2
  encoding: utf8
  database: Blog_test
  username: root
  password:

production:
  adapter: mysql2
  encoding: utf8
  database: Blog_production
  username: root
  password:              rails new with mysql option
pcunha:Blog$ rails server

=> Booting WEBrick
=> Rails 3.0.7 application starting in
development on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
localhost:3000
Model
Database Schema
pcunha:Blog$ rails generate scaffold Post title:string body:text

     invoke   active_record
     create     db/migrate/20110715102126_create_posts.rb
     create     app/models/post.rb
     invoke     test_unit
     create       test/unit/post_test.rb
     create       test/fixtures/posts.yml
     invoke   scaffold_controller
     create     app/controllers/posts_controller.rb
     invoke     erb
     create       app/views/posts
     create       app/views/posts/index.html.erb
     create       app/views/posts/edit.html.erb
     create       app/views/posts/show.html.erb
     create       app/views/posts/new.html.erb
     create       app/views/posts/_form.html.erb
# config/db/migrate/20110715102126_create_posts.rb
class CreatePosts < ActiveRecord::Migration
  def self.up
    create_table :posts do |t|
      t.string :title
      t.text :body

      t.timestamps
    end
  end

  def self.down
    drop_table :posts
  end
end
pcunha:Blog$ rake db:create
pcunha:Blog$ rake db:migrate
==    CreatePosts: migrating
-- create_table(:posts)
     -> 0.0015s
==    CreatePosts: migrated (0.0018s)
pcunha:Blog$ rails generate model Comment body:text

 invoke   active_record
 create     db/migrate/20110715103725_create_comments.rb
 create     app/models/comment.rb
 invoke     test_unit
 create       test/unit/comment_test.rb
 create       test/fixtures/comments.yml

pcunha:Blog$ rails generate migration AddPostIdToComments
post_id:integer

 invoke   active_record
 create     db/migrate/20110715103834_add_post_id_to_comments.rb
# 20110715103834_add_post_id_to_comments.rb
class AddPostIdToComments < ActiveRecord::Migration
  def self.up
    add_column :comments, :post_id, :integer
  end

  def self.down
    remove_column :comments, :post_id
  end
end
pcunha:Blog$ rake db:migrate
==    CreateComments: migrating
-- create_table(:comments)
     -> 0.0011s
==    CreateComments: migrated (0.0012s)


==    AddPostIdToComments: migrating
-- add_column(:comments, :post_id, :integer)
     -> 0.0011s
==    AddPostIdToComments: migrated (0.0041s)
rake   db:create
rake   db:migrate
rake   db:migrate:redo
rake   db:rollback




blog_db.schema_migrations
- keeps the version number of all
migrations already runned
Model
 Relations
# app/models/post.rb
class Post < ActiveRecord::Base
  has_many :comments
end


# app/models/comment.rb
class Comment < ActiveRecord::Base
  belongs_to :post
end


Post.all
Post.find(1).comments
Comments.find(1).post
Post.order(:created_at)
Post.limit(5).offset(2)
Model
 Validations
# app/models/post.rb
class Post < ActiveRecord::Base
  has_many :comments

  validates_presence_of :title
  validates_format_of :title, :with => /ASLB.*z/
end



p = Post.new
p.save # false
p.errors.full_messages # ["Title can't be blank", "Title
is invalid"]

p.title = "SLB is the best"
p.save # true
validates_presence_of :nif

validates_format_of :name

validates_acceptance_of :terms_and_conditions, :on => :create

validates_numericality_of :age, :greater_than_or_equal_to => 18

validates_uniqueness_of :model_fk_key, :scope => :model_fk_key2

validates_length_of :minimum => 5
Controllers
  Managing the CRUD
# app/controllers/posts_controller.rb
class PostsController < ApplicationController
  # GET /posts
  def index ...

  # GET /posts/1
  def show ...

  # GET /posts/new
  def new ...

  # GET /posts/1/edit
  def edit ...

  # POST /posts
  def create ...

  # PUT /posts/1
  def update ...

  # DELETE /posts/1
  def destroy ...
end
                                    Generated with scaffold
# POST /posts
  # POST /posts.xml
  def create
    @post = Post.new(params[:post])

    respond_to do |format|
      if @post.save
        format.html { redirect_to(@post, :notice => 'Post was
successfully created.') }
        format.xml { render :xml => @post, :status
=> :created, :location => @post }
      else
        format.html { render :action => "new" }
        format.xml { render :xml => @post.errors, :status
=> :unprocessable_entity }
      end
    end
  end
def index
   @posts = Post.all

   respond_to do |format|
     format.html # index.html.erb
     format.xml { render :xml => @posts }
   end
 end

pcunha:Blog$ curl http://localhost:3000/posts.xml
<?xml version="1.0" encoding="UTF-8"?>
<posts type="array">
  <post>
    <created-at type="datetime">2011-07-15T13:39:51Z</created-at>
    <body>This is the body of the first post</body>
    <title>The first very post of this blog</title>
    <updated-at type="datetime">2011-07-15T13:39:51Z</updated-at>
    <id type="integer">1</id>
  </post>
</posts>
Views
# app/views/posts/new.html.erb
                                        <h1>New post</h1>

                                        <%= form_for(@post) do |f| %>
# app/controllers/posts_controller.rb
def new                                   <div class="field">
  @post = Post.new                          <%= f.label :title %><br />
  respond_to do |format|                    <%= f.text_field :title %>
    format.html # new.html.erb}           </div>
  end                                     <div class="field">
                                            <%= f.label :body %><br />
end
                                            <%= f.text_area :body %>
                                          </div>
                                          <div class="actions">
                                            <%= f.submit %>
                                          </div>
                                        <% end %>

                                        <%= link_to 'Back', posts_path %>
# app/views/posts/edit.html.erb
                                        <h1>Edit post</h1>

                                        <%= form_for(@post) do |f| %>

                                          <div class="field">
                                            <%= f.label :title %><br />
# app/controllers/posts_controller.rb
                                            <%= f.text_field :title %>
def edit                                  </div>
  @post = Post.find(params[:id])          <div class="field">
  respond_to do |format|                    <%= f.label :body %><br />
    format.html # edit.html.erb}            <%= f.text_area :body %>
  end                                     </div>
                                          <div class="actions">
end
                                            <%= f.submit %>
                                          </div>
                                        <% end %>

                                        <%= link_to 'Show', @post %> |
                                        <%= link_to 'Back', posts_path %>
Rails builds the route for you

link_to 'Show', @post   # GET posts/@post.id


form_for(@post)

if @post.new_record?
 POST /posts
else
 PUT /posts/@post.id
end
Views
 Partials
# app/views/posts/new.html.erb      # app/views/posts/edit.html.erb
<h1>New post</h1>                   <h1>Edit post</h1>

<%= form_for(@post) do |f| %>       <%= form_for(@post) do |f| %>

  <div class="field">                 <div class="field">
    <%= f.label :title %><br />         <%= f.label :title %><br />
    <%= f.text_field :title %>          <%= f.text_field :title %>
  </div>                              </div>
  <div class="field">                 <div class="field">
    <%= f.label :body %><br />          <%= f.label :body %><br />
    <%= f.text_area :body %>            <%= f.text_area :body %>
  </div>                              </div>
  <div class="actions">               <div class="actions">
    <%= f.submit %>                     <%= f.submit %>
  </div>                              </div>
<% end %>                           <% end %>

<%= link_to 'Back', posts_path %>   <%= link_to 'Show', @post %> |
                                    <%= link_to 'Back', posts_path %>


                           Bad pattern
# app/views/posts/_form.html.erb
# app/views/posts/new.html.erb
                                    <%= form_for(@post) do |f| %>
<h1>New post</h1>

                                      <div class="field">
<%= render "form" %>%>
                                        <%= f.label :title %><br />
<%= link_to 'Back', posts_path %>
                                        <%= f.text_field :title %>
                                      </div>
                                      <div class="field">
                                        <%= f.label :body %><br />
# app/views/posts/edit.html.erb
                                        <%= f.text_area :body %>
<h1>Edit post</h1>
                                      </div>
                                      <div class="actions">
<%= render "form" %>%>
                                        <%= f.submit %>
<%= link_to 'Show', @post %> |
                                      </div>
<%= link_to 'Back', posts_path %>
                                    <% end %>




                          The right way
AJAX
Improve user experience
Improve user experience by not having the
whole page reload when submitting a form
or simple pagination link

Also save resources used (SQL queries,
memory, more bandwidth usage,... etc)
AJAX
Changing default forms to AJAX
# config/routes.rb
Blog::Application.routes.draw do
  resources :posts do
    resources :comments, :only => [:create]
  end
end



POST /posts/:post_id/comments




              Limiting actions is always the best practice
# app/controllers/comments_controller.rb
class CommentsController < ApplicationController

  def create
    @post = Post.find(params[:post_id])
    @comment = @post.comments.new(params[:comment])

    respond_to do |format|
      if @comment.save
        format.html { redirect_to(@post }
      else
        format.html { render :template => "posts/
show.html.erb" }
      end
    end
  end
end
# app/views/posts/show.html.erb
...
<h1>Comments</h1>
<div id="comments">
  <%= render :partial => "comments/comment",
             :collection => @post.commments %>
</div>

<%= render :partial => "comments/form",
           :locals => {
              :post => @post,
              :comment => @comment || Comment.new } %>
# app/views/comments/_form.html.erb
<%= form_for [post,comment] do |f| %>
  <div class="field">
    <%= f.label :body %><br />
    <%= f.text_area :body %>

    <p><%= f.submit %></p>
  </div>
<% end %>


            Our HTML form
          What needs to change?
# app/views/comments/_form.html.erb
<%= form_for [post,comment], :remote => true do |f| %>
  <div class="field">
    <%= f.label :body %><br />
    <%= f.text_area :body %>

    <p><%= f.submit %></p>
  </div>
<% end %>




                     That’s it? Not yet!
# app/controllers/comments_controller.rb
class CommentsController < ApplicationController

  def create
    @post = Post.find(params[:post_id])
    @comment = @post.comments.new(params[:comment])

    respond_to do |format|
      if @comment.save
        format.html { redirect_to(@post, :notice => 'Comment was
successfully created.') }
        format.js
      else
        format.html { render :action => "new" }
        format.js
      end
    end
  end
end
# app/views/comments/create.js.erb
//Dump javascript here!
document.getElementById...



Notice:
- create.js.erb
- writing native javascript is not optimal:
    1. You will forget something about IE
    2. We are at 21st Century
    3. Lots of good frameworks
Rails 2.X and 3.0.X

- Prototype JS Framework as default

Rails 3.1 (released 2011)

- jQuery JS Framework as default
# app/views/comments/create.js.erb
<% if @comment.new_record? %>

  <% content = render(:partial => "comments/form",
                       :locals => {
                         :post => @post,
                         :comment => @comment })
     content = escape_javascript(content)
  %>

  $('new_comment').replace("<%= content %>");

<% else %>
  <% comment_content = render(:partial => "comments/comment", :object => @comment)
     comment_content = escape_javascript(comment_content)
  %>

  $('comments').insert({
     bottom : '<%= comment_content %>'
  })

  $('new_comment').reset();
<% end %>
Almost there... but

- Complex code
- We can do better with Rails
RJS
Ruby (to) JavaScript Templates
# app/views/comments/create.js.rjs
if @comment.new_record?
  page.replace :new_comment,
               :partial => "comments/form",
               :locals => {
                    :post => @post,
                    :comment => @comment }
else
  page.insert_html :bottom, :comments, :partial
=> "comments/comment", :object => @comment
  page[:new_comment].reset
end
Gems
Gems
Extend Rails framework

Easy installation and usage

Increasing community

 • Github
 • Gemcutter
Bundler gem
# Gemfile
gem "rails", "2.3.10"
gem "will_paginate"
gem "authlogic"

gem "pg"
gem "postgis_adapter", "0.7.8"
gem "GeoRuby", "1.3.4"

# Sphinx
gem "thinking-sphinx", "1.4.5"

group   :development do
  gem   "capistrano"
  gem   "capistrano-ext"
  gem   "ruby-debug"
  gem   "wirble"
  gem   "mongrel"
end
Questions ?
References

http://rubyonrails.org/
http://railsapi.com/
http://railscasts.com/
http://railsforzombies.org/
References
Thanks :)
pedro.cunha@rupeal.com
        @mryise

Más contenido relacionado

La actualidad más candente

What to do when things go wrong
What to do when things go wrongWhat to do when things go wrong
What to do when things go wrongDorneles Treméa
 
Chef on Python and MongoDB
Chef on Python and MongoDBChef on Python and MongoDB
Chef on Python and MongoDBRick Copeland
 
Service approach for development REST API in Symfony2
Service approach for development REST API in Symfony2Service approach for development REST API in Symfony2
Service approach for development REST API in Symfony2Sumy PHP User Grpoup
 
Introdução Ruby On Rails
Introdução Ruby On RailsIntrodução Ruby On Rails
Introdução Ruby On RailsLukas Alexandre
 
Getting Into FLOW3 (DPC12)
Getting Into FLOW3 (DPC12)Getting Into FLOW3 (DPC12)
Getting Into FLOW3 (DPC12)Robert Lemke
 
IPCSE12: Getting into FLOW3
IPCSE12: Getting into FLOW3IPCSE12: Getting into FLOW3
IPCSE12: Getting into FLOW3Robert Lemke
 
Rails vs Web2py
Rails vs Web2pyRails vs Web2py
Rails vs Web2pyjonromero
 
Rails for PHP Developers
Rails for PHP DevelopersRails for PHP Developers
Rails for PHP DevelopersRobert Dempsey
 
RubyConf Portugal 2014 - Why ruby must go!
RubyConf Portugal 2014 - Why ruby must go!RubyConf Portugal 2014 - Why ruby must go!
RubyConf Portugal 2014 - Why ruby must go!Gautam Rege
 
Symfony2, Backbone.js &amp; socket.io - SfLive Paris 2k13 - Wisembly
Symfony2, Backbone.js &amp; socket.io - SfLive Paris 2k13 - WisemblySymfony2, Backbone.js &amp; socket.io - SfLive Paris 2k13 - Wisembly
Symfony2, Backbone.js &amp; socket.io - SfLive Paris 2k13 - WisemblyGuillaume POTIER
 
A tour on ruby and friends
A tour on ruby and friendsA tour on ruby and friends
A tour on ruby and friends旻琦 潘
 
When To Use Ruby On Rails
When To Use Ruby On RailsWhen To Use Ruby On Rails
When To Use Ruby On Railsdosire
 
Taking Care of The REST - Creating your own RESTful API Server using Restler 2.0
Taking Care of The REST - Creating your own RESTful API Server using Restler 2.0Taking Care of The REST - Creating your own RESTful API Server using Restler 2.0
Taking Care of The REST - Creating your own RESTful API Server using Restler 2.0Arul Kumaran
 
Migrating Legacy Rails Apps to Rails 3
Migrating Legacy Rails Apps to Rails 3Migrating Legacy Rails Apps to Rails 3
Migrating Legacy Rails Apps to Rails 3Clinton Dreisbach
 
Custom post-framworks
Custom post-framworksCustom post-framworks
Custom post-framworksKiera Howe
 
Ruby On Rails Introduction
Ruby On Rails IntroductionRuby On Rails Introduction
Ruby On Rails IntroductionThomas Fuchs
 
Symfony2 Introduction Presentation
Symfony2 Introduction PresentationSymfony2 Introduction Presentation
Symfony2 Introduction PresentationNerd Tzanetopoulos
 
RestfulX “The RESTful Way to develop Adobe Flex and AIR applications”
RestfulX “The RESTful Way to develop Adobe Flex and AIR applications”RestfulX “The RESTful Way to develop Adobe Flex and AIR applications”
RestfulX “The RESTful Way to develop Adobe Flex and AIR applications”elliando dias
 

La actualidad más candente (20)

What to do when things go wrong
What to do when things go wrongWhat to do when things go wrong
What to do when things go wrong
 
Chef on Python and MongoDB
Chef on Python and MongoDBChef on Python and MongoDB
Chef on Python and MongoDB
 
Service approach for development REST API in Symfony2
Service approach for development REST API in Symfony2Service approach for development REST API in Symfony2
Service approach for development REST API in Symfony2
 
Introdução Ruby On Rails
Introdução Ruby On RailsIntrodução Ruby On Rails
Introdução Ruby On Rails
 
Getting Into FLOW3 (DPC12)
Getting Into FLOW3 (DPC12)Getting Into FLOW3 (DPC12)
Getting Into FLOW3 (DPC12)
 
IPCSE12: Getting into FLOW3
IPCSE12: Getting into FLOW3IPCSE12: Getting into FLOW3
IPCSE12: Getting into FLOW3
 
Rails vs Web2py
Rails vs Web2pyRails vs Web2py
Rails vs Web2py
 
Rails for PHP Developers
Rails for PHP DevelopersRails for PHP Developers
Rails for PHP Developers
 
Vim Hacks
Vim HacksVim Hacks
Vim Hacks
 
RubyConf Portugal 2014 - Why ruby must go!
RubyConf Portugal 2014 - Why ruby must go!RubyConf Portugal 2014 - Why ruby must go!
RubyConf Portugal 2014 - Why ruby must go!
 
Symfony2, Backbone.js &amp; socket.io - SfLive Paris 2k13 - Wisembly
Symfony2, Backbone.js &amp; socket.io - SfLive Paris 2k13 - WisemblySymfony2, Backbone.js &amp; socket.io - SfLive Paris 2k13 - Wisembly
Symfony2, Backbone.js &amp; socket.io - SfLive Paris 2k13 - Wisembly
 
A tour on ruby and friends
A tour on ruby and friendsA tour on ruby and friends
A tour on ruby and friends
 
When To Use Ruby On Rails
When To Use Ruby On RailsWhen To Use Ruby On Rails
When To Use Ruby On Rails
 
Taking Care of The REST - Creating your own RESTful API Server using Restler 2.0
Taking Care of The REST - Creating your own RESTful API Server using Restler 2.0Taking Care of The REST - Creating your own RESTful API Server using Restler 2.0
Taking Care of The REST - Creating your own RESTful API Server using Restler 2.0
 
Migrating Legacy Rails Apps to Rails 3
Migrating Legacy Rails Apps to Rails 3Migrating Legacy Rails Apps to Rails 3
Migrating Legacy Rails Apps to Rails 3
 
Custom post-framworks
Custom post-framworksCustom post-framworks
Custom post-framworks
 
Ruby On Rails Introduction
Ruby On Rails IntroductionRuby On Rails Introduction
Ruby On Rails Introduction
 
Symfony2 Introduction Presentation
Symfony2 Introduction PresentationSymfony2 Introduction Presentation
Symfony2 Introduction Presentation
 
RestfulX “The RESTful Way to develop Adobe Flex and AIR applications”
RestfulX “The RESTful Way to develop Adobe Flex and AIR applications”RestfulX “The RESTful Way to develop Adobe Flex and AIR applications”
RestfulX “The RESTful Way to develop Adobe Flex and AIR applications”
 
How to build the Web
How to build the WebHow to build the Web
How to build the Web
 

Destacado

Dando os primeiros passos com rails
Dando os primeiros passos com railsDando os primeiros passos com rails
Dando os primeiros passos com railsMarcos Sousa
 
Ruby On Rails
Ruby On RailsRuby On Rails
Ruby On Railsousli07
 
What is-google-adwords
What is-google-adwordsWhat is-google-adwords
What is-google-adwordsAnthony Greene
 
Introdução ao Ruby on Rails
Introdução ao Ruby on RailsIntrodução ao Ruby on Rails
Introdução ao Ruby on RailsJuan Maiz
 
BRANDING & PERSONAL SELLING
BRANDING & PERSONAL SELLINGBRANDING & PERSONAL SELLING
BRANDING & PERSONAL SELLINGAlchemedia
 

Destacado (7)

Dando os primeiros passos com rails
Dando os primeiros passos com railsDando os primeiros passos com rails
Dando os primeiros passos com rails
 
Ruby On Rails
Ruby On RailsRuby On Rails
Ruby On Rails
 
RubyonRails
RubyonRailsRubyonRails
RubyonRails
 
Creating Android apps
Creating Android appsCreating Android apps
Creating Android apps
 
What is-google-adwords
What is-google-adwordsWhat is-google-adwords
What is-google-adwords
 
Introdução ao Ruby on Rails
Introdução ao Ruby on RailsIntrodução ao Ruby on Rails
Introdução ao Ruby on Rails
 
BRANDING & PERSONAL SELLING
BRANDING & PERSONAL SELLINGBRANDING & PERSONAL SELLING
BRANDING & PERSONAL SELLING
 

Similar a Ruby on Rails at PROMPT ISEL '11

Getting started with Rails (2), Season 2
Getting started with Rails (2), Season 2Getting started with Rails (2), Season 2
Getting started with Rails (2), Season 2RORLAB
 
Ruby/Rails
Ruby/RailsRuby/Rails
Ruby/Railsrstankov
 
Introduction à Ruby
Introduction à RubyIntroduction à Ruby
Introduction à RubyMicrosoft
 
Pourquoi ruby et rails déchirent
Pourquoi ruby et rails déchirentPourquoi ruby et rails déchirent
Pourquoi ruby et rails déchirentNicolas Ledez
 
More to RoC weibo
More to RoC weiboMore to RoC weibo
More to RoC weiboshaokun
 
Ruby on Rails - Introduction
Ruby on Rails - IntroductionRuby on Rails - Introduction
Ruby on Rails - IntroductionVagmi Mudumbai
 
Rails 3 overview
Rails 3 overviewRails 3 overview
Rails 3 overviewYehuda Katz
 
Rails 3: Dashing to the Finish
Rails 3: Dashing to the FinishRails 3: Dashing to the Finish
Rails 3: Dashing to the FinishYehuda Katz
 
Rails3ハンズオン資料
Rails3ハンズオン資料Rails3ハンズオン資料
Rails3ハンズオン資料Shinsaku Chikura
 
Decent exposure: Controladores sin @ivars
Decent exposure: Controladores sin @ivarsDecent exposure: Controladores sin @ivars
Decent exposure: Controladores sin @ivarsLeonardo Soto
 
Simple restfull app_s
Simple restfull app_sSimple restfull app_s
Simple restfull app_snetwix
 
浜松Rails3道場 其の四 View編
浜松Rails3道場 其の四 View編浜松Rails3道場 其の四 View編
浜松Rails3道場 其の四 View編Masakuni Kato
 
OSDC 2009 Rails Turtorial
OSDC 2009 Rails TurtorialOSDC 2009 Rails Turtorial
OSDC 2009 Rails TurtorialYi-Ting Cheng
 
Rails2 Pr
Rails2 PrRails2 Pr
Rails2 Prxibbar
 
Como programar un blog REST
Como programar un blog RESTComo programar un blog REST
Como programar un blog RESTJavier Vidal
 
Presentation.Key
Presentation.KeyPresentation.Key
Presentation.Keyguesta2b31d
 

Similar a Ruby on Rails at PROMPT ISEL '11 (20)

Getting started with Rails (2), Season 2
Getting started with Rails (2), Season 2Getting started with Rails (2), Season 2
Getting started with Rails (2), Season 2
 
Ruby/Rails
Ruby/RailsRuby/Rails
Ruby/Rails
 
Introduction à Ruby
Introduction à RubyIntroduction à Ruby
Introduction à Ruby
 
Ruby on Rails
Ruby on RailsRuby on Rails
Ruby on Rails
 
Pourquoi ruby et rails déchirent
Pourquoi ruby et rails déchirentPourquoi ruby et rails déchirent
Pourquoi ruby et rails déchirent
 
More to RoC weibo
More to RoC weiboMore to RoC weibo
More to RoC weibo
 
Ruby on Rails - Introduction
Ruby on Rails - IntroductionRuby on Rails - Introduction
Ruby on Rails - Introduction
 
Rails 3 overview
Rails 3 overviewRails 3 overview
Rails 3 overview
 
Rails 3: Dashing to the Finish
Rails 3: Dashing to the FinishRails 3: Dashing to the Finish
Rails 3: Dashing to the Finish
 
Rails3ハンズオン資料
Rails3ハンズオン資料Rails3ハンズオン資料
Rails3ハンズオン資料
 
Why ruby
Why rubyWhy ruby
Why ruby
 
Decent exposure: Controladores sin @ivars
Decent exposure: Controladores sin @ivarsDecent exposure: Controladores sin @ivars
Decent exposure: Controladores sin @ivars
 
Simple restfull app_s
Simple restfull app_sSimple restfull app_s
Simple restfull app_s
 
浜松Rails3道場 其の四 View編
浜松Rails3道場 其の四 View編浜松Rails3道場 其の四 View編
浜松Rails3道場 其の四 View編
 
The Rails Way
The Rails WayThe Rails Way
The Rails Way
 
OSDC 2009 Rails Turtorial
OSDC 2009 Rails TurtorialOSDC 2009 Rails Turtorial
OSDC 2009 Rails Turtorial
 
Rails2 Pr
Rails2 PrRails2 Pr
Rails2 Pr
 
Como programar un blog REST
Como programar un blog RESTComo programar un blog REST
Como programar un blog REST
 
Php
PhpPhp
Php
 
Presentation.Key
Presentation.KeyPresentation.Key
Presentation.Key
 

Último

TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piececharlottematthew16
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionDilum Bandara
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Enterprise Knowledge
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfAddepto
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfPrecisely
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsPixlogix Infotech
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyAlfredo García Lavilla
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...Fwdays
 
H2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo Day
H2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo DayH2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo Day
H2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo DaySri Ambati
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 

Último (20)

TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piece
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An Introduction
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdf
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and Cons
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easy
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
 
H2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo Day
H2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo DayH2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo Day
H2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo Day
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 

Ruby on Rails at PROMPT ISEL '11

  • 1. Web Development with Ruby On Rails Pedro Cunha
  • 2. Ruby Yukihiro "Matz" Matsumoto Ruby is designed for programmer productivity and fun Created February 1993
  • 3. Ruby Everything is an object Dynamic Typing true.class # TrueClass class Foo
 nil.class # NilClass def initialize(x, y)
 @x = x @y = y end end class Foo2 end Foo.new(2, Foo2.new)
  • 4. Ruby class Foo class Bar # Parenthesis can be omitted # Use ! if you change self def method def method! puts "Hello World" end end # Use ? if you return a boolean # Default params def method? def method2(x = 2) end puts x end # Only conventions end # Operator overload def +(x) end end
  • 5. Ruby "hello".class # String :hello.class # Symbol a = "Hello" b = "Hello" # Convention # Use string if you plan to a.equal? b # false compute text x = :hello # Use symbols if you want to y = :hello define or/and set a behaviour which is not x.equal? y # true expected to change
  • 6. Ruby a = {} a[:first] = 2 a[:things] = 3 a[:foo] = "bar" b = { :first => 2, :things => 3, :foo => "bar" } b[:first] # 2
  • 7. Ruby x = [1,4,5,2,5,8,10] x.sort # returns a copy of x sorted [1,2,4,5,5,8,10] x.sort! # modifies self x.map{ |i| i + 4 } # [5,6,8,9,9,12,14] x.map! do |i| i + 4 end # [5,6,8,9,9,12,14]
  • 8. Ruby Monkey Patching class String def +() # override string default + operator end end “With great power comes great responsability” Uncle Ben, Amazing Spiderman nº1
  • 10. Ruby on Rails Created by David Heinemeir Hansson • CEO at 37th Signals • Personal Project, 2004 Present • Rails 3.1 • Growing community
  • 11. Ruby on Rails Convention vs Configuration MVC Architecture REST routing
  • 13. • Don’t Repeat Yourself • Increased productivity through conventions. Ex.: following a pattern for foreign key columns. • Take advantage of singular and plural word meanings
  • 14. MVC
  • 15. RoR
  • 17. CRUD REST ROUTES CREATE POST /posts READ GET /posts/1 UPDATE PUT /posts/1 DELETE DELETE /posts/1
  • 20. pcunha:prompt$ rails new Blog -d mysql Blog /app /controllers /mailers /models /views /config database.yml /db /migrate Gemfile /public /javascripts /stylesheets
  • 21. # config/database.yml development: adapter: sqlite3 database: db/development.sqlite3 test: adapter: sqlite3 database: db/test.sqlite3 production: adapter: sqlite3 database: db/production.sqlite3
  • 22. development: adapter: mysql2 encoding: utf8 database: Blog_development username: root password: test: adapter: mysql2 encoding: utf8 database: Blog_test username: root password: production: adapter: mysql2 encoding: utf8 database: Blog_production username: root password: rails new with mysql option
  • 23. pcunha:Blog$ rails server => Booting WEBrick => Rails 3.0.7 application starting in development on http://0.0.0.0:3000 => Call with -d to detach => Ctrl-C to shutdown server
  • 26. pcunha:Blog$ rails generate scaffold Post title:string body:text invoke active_record create db/migrate/20110715102126_create_posts.rb create app/models/post.rb invoke test_unit create test/unit/post_test.rb create test/fixtures/posts.yml invoke scaffold_controller create app/controllers/posts_controller.rb invoke erb create app/views/posts create app/views/posts/index.html.erb create app/views/posts/edit.html.erb create app/views/posts/show.html.erb create app/views/posts/new.html.erb create app/views/posts/_form.html.erb
  • 27. # config/db/migrate/20110715102126_create_posts.rb class CreatePosts < ActiveRecord::Migration def self.up create_table :posts do |t| t.string :title t.text :body t.timestamps end end def self.down drop_table :posts end end
  • 28. pcunha:Blog$ rake db:create pcunha:Blog$ rake db:migrate == CreatePosts: migrating -- create_table(:posts) -> 0.0015s == CreatePosts: migrated (0.0018s)
  • 29. pcunha:Blog$ rails generate model Comment body:text invoke active_record create db/migrate/20110715103725_create_comments.rb create app/models/comment.rb invoke test_unit create test/unit/comment_test.rb create test/fixtures/comments.yml pcunha:Blog$ rails generate migration AddPostIdToComments post_id:integer invoke active_record create db/migrate/20110715103834_add_post_id_to_comments.rb
  • 30. # 20110715103834_add_post_id_to_comments.rb class AddPostIdToComments < ActiveRecord::Migration def self.up add_column :comments, :post_id, :integer end def self.down remove_column :comments, :post_id end end
  • 31. pcunha:Blog$ rake db:migrate == CreateComments: migrating -- create_table(:comments) -> 0.0011s == CreateComments: migrated (0.0012s) == AddPostIdToComments: migrating -- add_column(:comments, :post_id, :integer) -> 0.0011s == AddPostIdToComments: migrated (0.0041s)
  • 32. rake db:create rake db:migrate rake db:migrate:redo rake db:rollback blog_db.schema_migrations - keeps the version number of all migrations already runned
  • 34. # app/models/post.rb class Post < ActiveRecord::Base has_many :comments end # app/models/comment.rb class Comment < ActiveRecord::Base belongs_to :post end Post.all Post.find(1).comments Comments.find(1).post Post.order(:created_at) Post.limit(5).offset(2)
  • 36. # app/models/post.rb class Post < ActiveRecord::Base has_many :comments validates_presence_of :title validates_format_of :title, :with => /ASLB.*z/ end p = Post.new p.save # false p.errors.full_messages # ["Title can't be blank", "Title is invalid"] p.title = "SLB is the best" p.save # true
  • 37. validates_presence_of :nif validates_format_of :name validates_acceptance_of :terms_and_conditions, :on => :create validates_numericality_of :age, :greater_than_or_equal_to => 18 validates_uniqueness_of :model_fk_key, :scope => :model_fk_key2 validates_length_of :minimum => 5
  • 39. # app/controllers/posts_controller.rb class PostsController < ApplicationController # GET /posts def index ... # GET /posts/1 def show ... # GET /posts/new def new ... # GET /posts/1/edit def edit ... # POST /posts def create ... # PUT /posts/1 def update ... # DELETE /posts/1 def destroy ... end Generated with scaffold
  • 40. # POST /posts # POST /posts.xml def create @post = Post.new(params[:post]) respond_to do |format| if @post.save format.html { redirect_to(@post, :notice => 'Post was successfully created.') } format.xml { render :xml => @post, :status => :created, :location => @post } else format.html { render :action => "new" } format.xml { render :xml => @post.errors, :status => :unprocessable_entity } end end end
  • 41. def index @posts = Post.all respond_to do |format| format.html # index.html.erb format.xml { render :xml => @posts } end end pcunha:Blog$ curl http://localhost:3000/posts.xml <?xml version="1.0" encoding="UTF-8"?> <posts type="array"> <post> <created-at type="datetime">2011-07-15T13:39:51Z</created-at> <body>This is the body of the first post</body> <title>The first very post of this blog</title> <updated-at type="datetime">2011-07-15T13:39:51Z</updated-at> <id type="integer">1</id> </post> </posts>
  • 42. Views
  • 43. # app/views/posts/new.html.erb <h1>New post</h1> <%= form_for(@post) do |f| %> # app/controllers/posts_controller.rb def new <div class="field"> @post = Post.new <%= f.label :title %><br /> respond_to do |format| <%= f.text_field :title %> format.html # new.html.erb} </div> end <div class="field"> <%= f.label :body %><br /> end <%= f.text_area :body %> </div> <div class="actions"> <%= f.submit %> </div> <% end %> <%= link_to 'Back', posts_path %>
  • 44. # app/views/posts/edit.html.erb <h1>Edit post</h1> <%= form_for(@post) do |f| %> <div class="field"> <%= f.label :title %><br /> # app/controllers/posts_controller.rb <%= f.text_field :title %> def edit </div> @post = Post.find(params[:id]) <div class="field"> respond_to do |format| <%= f.label :body %><br /> format.html # edit.html.erb} <%= f.text_area :body %> end </div> <div class="actions"> end <%= f.submit %> </div> <% end %> <%= link_to 'Show', @post %> | <%= link_to 'Back', posts_path %>
  • 45. Rails builds the route for you link_to 'Show', @post # GET posts/@post.id form_for(@post) if @post.new_record? POST /posts else PUT /posts/@post.id end
  • 47. # app/views/posts/new.html.erb # app/views/posts/edit.html.erb <h1>New post</h1> <h1>Edit post</h1> <%= form_for(@post) do |f| %> <%= form_for(@post) do |f| %> <div class="field"> <div class="field"> <%= f.label :title %><br /> <%= f.label :title %><br /> <%= f.text_field :title %> <%= f.text_field :title %> </div> </div> <div class="field"> <div class="field"> <%= f.label :body %><br /> <%= f.label :body %><br /> <%= f.text_area :body %> <%= f.text_area :body %> </div> </div> <div class="actions"> <div class="actions"> <%= f.submit %> <%= f.submit %> </div> </div> <% end %> <% end %> <%= link_to 'Back', posts_path %> <%= link_to 'Show', @post %> | <%= link_to 'Back', posts_path %> Bad pattern
  • 48. # app/views/posts/_form.html.erb # app/views/posts/new.html.erb <%= form_for(@post) do |f| %> <h1>New post</h1> <div class="field"> <%= render "form" %>%> <%= f.label :title %><br /> <%= link_to 'Back', posts_path %> <%= f.text_field :title %> </div> <div class="field"> <%= f.label :body %><br /> # app/views/posts/edit.html.erb <%= f.text_area :body %> <h1>Edit post</h1> </div> <div class="actions"> <%= render "form" %>%> <%= f.submit %> <%= link_to 'Show', @post %> | </div> <%= link_to 'Back', posts_path %> <% end %> The right way
  • 50. Improve user experience by not having the whole page reload when submitting a form or simple pagination link Also save resources used (SQL queries, memory, more bandwidth usage,... etc)
  • 52. # config/routes.rb Blog::Application.routes.draw do resources :posts do resources :comments, :only => [:create] end end POST /posts/:post_id/comments Limiting actions is always the best practice
  • 53. # app/controllers/comments_controller.rb class CommentsController < ApplicationController def create @post = Post.find(params[:post_id]) @comment = @post.comments.new(params[:comment]) respond_to do |format| if @comment.save format.html { redirect_to(@post } else format.html { render :template => "posts/ show.html.erb" } end end end end
  • 54. # app/views/posts/show.html.erb ... <h1>Comments</h1> <div id="comments"> <%= render :partial => "comments/comment", :collection => @post.commments %> </div> <%= render :partial => "comments/form", :locals => { :post => @post, :comment => @comment || Comment.new } %>
  • 55. # app/views/comments/_form.html.erb <%= form_for [post,comment] do |f| %> <div class="field"> <%= f.label :body %><br /> <%= f.text_area :body %> <p><%= f.submit %></p> </div> <% end %> Our HTML form What needs to change?
  • 56. # app/views/comments/_form.html.erb <%= form_for [post,comment], :remote => true do |f| %> <div class="field"> <%= f.label :body %><br /> <%= f.text_area :body %> <p><%= f.submit %></p> </div> <% end %> That’s it? Not yet!
  • 57. # app/controllers/comments_controller.rb class CommentsController < ApplicationController def create @post = Post.find(params[:post_id]) @comment = @post.comments.new(params[:comment]) respond_to do |format| if @comment.save format.html { redirect_to(@post, :notice => 'Comment was successfully created.') } format.js else format.html { render :action => "new" } format.js end end end end
  • 58. # app/views/comments/create.js.erb //Dump javascript here! document.getElementById... Notice: - create.js.erb - writing native javascript is not optimal: 1. You will forget something about IE 2. We are at 21st Century 3. Lots of good frameworks
  • 59. Rails 2.X and 3.0.X - Prototype JS Framework as default Rails 3.1 (released 2011) - jQuery JS Framework as default
  • 60. # app/views/comments/create.js.erb <% if @comment.new_record? %> <% content = render(:partial => "comments/form", :locals => { :post => @post, :comment => @comment }) content = escape_javascript(content) %> $('new_comment').replace("<%= content %>"); <% else %> <% comment_content = render(:partial => "comments/comment", :object => @comment) comment_content = escape_javascript(comment_content) %> $('comments').insert({ bottom : '<%= comment_content %>' }) $('new_comment').reset(); <% end %>
  • 61. Almost there... but - Complex code - We can do better with Rails
  • 63. # app/views/comments/create.js.rjs if @comment.new_record? page.replace :new_comment, :partial => "comments/form", :locals => { :post => @post, :comment => @comment } else page.insert_html :bottom, :comments, :partial => "comments/comment", :object => @comment page[:new_comment].reset end
  • 64. Gems
  • 65. Gems Extend Rails framework Easy installation and usage Increasing community • Github • Gemcutter
  • 66. Bundler gem # Gemfile gem "rails", "2.3.10" gem "will_paginate" gem "authlogic" gem "pg" gem "postgis_adapter", "0.7.8" gem "GeoRuby", "1.3.4" # Sphinx gem "thinking-sphinx", "1.4.5" group :development do gem "capistrano" gem "capistrano-ext" gem "ruby-debug" gem "wirble" gem "mongrel" end