SlideShare ist ein Scribd-Unternehmen logo
1 von 70
Downloaden Sie, um offline zu lesen
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

Weitere ähnliche Inhalte

Was ist angesagt?

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
 

Was ist angesagt? (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
 

Andere mochten auch

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
 

Andere mochten auch (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
 

Ähnlich wie 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
 

Ähnlich wie 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
 

Kürzlich hochgeladen

Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesKari Kakkonen
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxLoriGlavin3
 
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Strongerpanagenda
 
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...panagenda
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...Wes McKinney
 
Scale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterScale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterMydbops
 
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesAssure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesThousandEyes
 
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Alkin Tezuysal
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI AgeCprime
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersRaghuram Pandurangan
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxLoriGlavin3
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Farhan Tariq
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPathCommunity
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfMounikaPolabathina
 
Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rick Flair
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsNathaniel Shimoni
 
Decarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityDecarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityIES VE
 
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Scott Andery
 

Kürzlich hochgeladen (20)

Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examples
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
 
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
 
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
 
Scale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterScale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL Router
 
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesAssure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
 
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI Age
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information Developers
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to Hero
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdf
 
Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directions
 
Decarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityDecarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a reality
 
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
 

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