SlideShare a Scribd company logo
1 of 153
Download to read offline
bogers on flickr




    Thomas Fuchs

Ruby on Rails




                              1
http://script.aculo.us/thomas
                                2
ABC      Digg      Nasa
Amazon   ESPN       NBC
Apple    Gucci      Tivo
CNET     last.fm   Twitter

                             3
.
prototype
    .
prototypejs.org
                  4
script.aculo.us
                  5
Part 1
Rails Overview and Demo

Part 2
Introduction to Ruby

Part 3
More Rails!

                          6
rubyonrails.org

                  7
Ruby
http://www.ruby-lang.org/


                            8
Programming      Web
 Language     Framework

                          9
10
Programming      Web
 Language     Framework

                          11
12
Ruby on Rails is an open-source
web framework that’s optimized
for programmer happiness and
sustainable productivity.

It lets you write beautiful code
by favoring convention over
configuration.
                                   13
Ruby on Rails is an open-source
web framework that’s optimized
for programmer happiness and
sustainable productivity.

It lets you write beautiful code
by favoring convention over
configuration.
                                   14
Ruby on Rails is an open-source
web framework that’s optimized
for programmer happiness and
sustainable productivity.

It lets you write beautiful code
by favoring convention over
configuration.
                                   15
Ruby on Rails is an open-source
web framework that’s optimized
for programmer happiness and
sustainable productivity.

It lets you write beautiful code
by favoring convention over
configuration.
                                   16
Ruby on Rails is an open-source
web framework that’s optimized
for programmer happiness and
sustainable productivity.

It lets you write beautiful code
by favoring convention over
configuration.
                                   17
Ruby on Rails is an open-source
web framework that’s optimized
for programmer happiness and
sustainable productivity.

It lets you write beautiful code
by favoring convention over
configuration.
                                   18
80/20
        19
Opinionated
 Software



         dbloete on flickr

                       20
Don’t
 repeat
yourself
           21
Demo
Building a Rails App
                       22
"app"
application logic




"config"
database and deployment information

"db"
database structure and migrations
"public"
CSS, images, JavaScripts and static
HTML
"vendor/plugins"
add-ons to "core" rails



                                      23
Controllers
Models
Views




              24
Model
  View
Controller
 (MVC)
             25
Controller

           Structures
           application




Provides                   Provides
  data                   user interface



Model                      View
                                          26
controller/posts_controller.rb




def index
  @posts = Post.find(:all)

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




                                           27
"index" maps to the name of the
controller by default, so
http://localhost:3000/posts
accesses this action

def index
  @posts = Post.find(:all)

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




                                           28
find all posts and assign them to a
           variable named @posts
def index
  @posts = Post.find(:all)

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


          "Post" is the name of the model




                                                 29
def index
  @posts = Post.find(:all)

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


        we decide to respond to different
        requests, so we can serve a web site
        for users, but also XML data for other
        systems (API)


                                                 30
def index
  @posts = Post.find(:all)

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


       for HTML, just use the defaults:
       get the view that is named the same as
       the action, and render it



                                                31
def index
  @posts = Post.find(:all)

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


        for XML requests, use the default
        XML rendering, no more code required




                                               32
views/posts/index.html.erb

<h1>Listing posts</h1>

<table>
  <tr>
    <th>Title</th>
    <th>Body</th>
    <th>Published</th>
  </tr>

<% for post in @posts %>
  <tr>
    <td><%=h post.title %></td>
    <td><%=h post.body %></td>
    <td><%=h post.published %></td>
    <td><%= link_to ‘Show’, post %></td>
    <td><%= link_to ‘Edit’, edit_post_path(post) %></td>
    <td><%= link_to ‘Destroy’, post, :confirm => ‘Are you sure?’, :method => :delete %></td>
  </tr>
<% end %>
</table>

<br />

<%= link_to ‘New post’, new_post_path %>




                                                                                              33
views/posts/index.html.erb

<h1>Listing posts</h1>

<table>
  <tr>
    <th>Title</th>
    <th>Body</th>
    <th>Published</th>       embedded Ruby (.erb)
  </tr>

<% for post in @posts %>
  <tr>
    <td><%=h post.title %></td>
    <td><%=h post.body %></td>
    <td><%=h post.published %></td>
    <td><%= link_to ‘Show’, post %></td>
    <td><%= link_to ‘Edit’, edit_post_path(post) %></td>
    <td><%= link_to ‘Destroy’, post, :confirm => ‘Are you sure?’, :method => :delete %></td>
  </tr>
<% end %>
</table>
                automatically provided link helpers
<br />

<%= link_to ‘New post’, new_post_path %>




                                                                                              34
35
36
models/post.rb




class Post < ActiveRecord::Base
  validates_presence_of :title
  validates_length_of   :body, :minimum=>10
end




                                              37
self-explanatory validations

class Post < ActiveRecord::Base
  validates_presence_of :title
  validates_length_of   :body, :minimum=>10
end




                                                        38
39
class Post < ActiveRecord::Base
  validates_presence_of :title
  validates_length_of   :body, :minimum=>10
end




   What is missing here?

                                              40
Because fields are
 already declared in the
  Database, no need to
redeclare it in the model


                            41
db/schema.rb (automatically created)


ActiveRecord::Schema.define(:version => 1) do

 create_table   "posts", :force => true do |t|
   t.string     "title"
   t.text       "body"
   t.boolean    "published"
   t.datetime   "created_at"
   t.datetime   "updated_at"
 end

end




                                                 42
db/migrate/001_create_posts.rb
       (automatically created by generator)

class CreatePosts < ActiveRecord::Migration
  def self.up
    create_table :posts do |t|
      t.string :title
      t.text :body
      t.boolean :published

     t.timestamps
   end
 end

  def self.down
    drop_table :posts
  end
end




                                              43
Ruby
http://www.ruby-lang.org/


                            44
Programming      Web
 Language     Framework

                          45
Why an other
programming
 language?



               46
Source: http://www.kerrolisaa.com/i/1/5637.jpg


                                                 47
Some might like this, but it's
   mostly because most
Software Development Tools
are designed for computers,
   not for human beings.


                                 48
"Ruby is simple in
appearance, but is
very complex
inside, just like our
human body."
Yukihiro “Matz” Matsumoto,
Creator of Ruby




                             49
growing steadily
                   50
Make the
computer work
   for you


                51
Design the
language and
 libraries for
 people first


                 52
Let others care
about performance



                    53
A Programmer’s
  Best Friend

                 54
say = "I love Ruby"
puts say

=> "I love Ruby"


                      55
no type              no “main” method
declarations
"String..."


                                        no “end of
  say = "I love Ruby"                   instruction”
                                        marker
  puts say
  no superflous
  keywords (“var”)




                                                       56
say = "I love Ruby"
say['love'] = "*love*"
puts say.upcase

=> "I *LOVE* RUBY"


                         57
5.times { puts say }

=>   "I   *love*   Ruby"
=>   "I   *love*   Ruby"
=>   "I   *love*   Ruby"
=>   "I   *love*   Ruby"
=>   "I   *love*   Ruby"

                           58
[Ruby is] a dynamic, open
source programming language
with a focus on simplicity and
productivity.

It has an elegant syntax that is
natural to read and easy to write.

                                     59
[Ruby is] a dynamic, open
source programming language
with a focus on simplicity and
productivity.

It has an elegant syntax that is
natural to read and easy to write.

                                     60
[Ruby is] a dynamic, open
source programming language
with a focus on simplicity and
productivity.

It has an elegant syntax that is
natural to read and easy to write.

                                     61
[Ruby is] a dynamic, open
source programming language
with a focus on simplicity and
productivity.

It has an elegant syntax that is
natural to read and easy to write.

                                     62
[Ruby is] a dynamic, open
source programming language
with a focus on simplicity and
productivity.

It has an elegant syntax that is
natural to read and easy to write.

                                     63
[Ruby is] a dynamic, open
source programming language
with a focus on simplicity and
productivity.

It has an elegant syntax that is
natural to read and easy to write.

                                     64
dan_h on flickr




Less is more




                                 65
Java
public static String reverseString(String source) {
  int i, len = source.length();
  StringBuffer dest = new StringBuffer(len);

    for (i = (len - 1); i >= 0; i--)
      dest.append(source.charAt(i));

    return dest.toString();
}

reverseString("Krawutzikapuzi");
=> "izupakiztuwarK"




                                                      66
PHP


strrev("Krawutzikapuzi");
=> "izupakiztuwarK"




                            67
Ruby


"Krawutzikapuzi".reverse
=> "izupakiztuwarK"




                           68
Ruby


"Krawutzikapuzi".split(//).inject(""){|m,c|c+m}
=> "izupakiztuwarK"



               Not using the built-in
               “reverse” method: still
               much smaller than Java




                                                  69
Do the
“right thing”
                70
def fact(n)
  return 1 if n == 0
  n * fact(n-1)
end




                       71
47584772842188967964624494516076535340819890
38544248798495995331910172335555660213945039
73628075013783761530712776192684903435262520
01588853514733161170210396817592151090778801
39317811419454525722386554146106289218796022
83897147608850627686296714667469756291123408
43920816015378088989396451826324367161676217
    (for non-maths people:
16890977991190375403127462228998800519544441
28201218736174599264295658174662830295557029
   this produces laaaaaarge
02432415318161721046583203678690611726015878
52075151628422554026517048330422614397428693
           numbers)
06169089796848259012545832716822645806652676
95865268227280707578139185817888965220816434
34482599326604336766017699961283186078838615
27946595513115655203609398818061213855860030
43569452722420634463179746059468257310379008
02443243846565724501440282188525247093519062
92902313649327349756551395872055965422874977
                                          72
>>fact(2)
=> 2

>> fact(3)
=> 6

>> fact(10)
=> 3628800


              73
<?php
function fact($int){
  if ($int<2) return 1;
  for ($f=2; $int-1>1; $f*=$int--);
  return $f;
};

echo fact(10)."n";
echo fact(999)."n";
?>
                                   PHP
$ php fact.php
3628800
        PHP overflows and cannot
INF     calculate a result

                                         74
Ruby does not care about overflows and does
                      the right thing: calculate what you want
>> fact(999)
=>
402387260077093773543702433923003985719374864210714632543799910429938512398629020592044208
486969404800479988610197196058631666872994808558901323829669944590997424504087073759918823
627727188732519779505950995276120874975462497043601418278094646496291056393887437886487337
119181045825783647849977012476632889835955735432513185323958463075557409114262417474349347
553428646576611667797396668820291207379143853719588249808126867838374559731746136085379534
524221586593201928090878297308431392844403281231558611036976801357304216168747609675871348
312025478589320767169132448426236131412508780208000261683151027341827977704784635868170164
365024153691398281264810213092761244896359928705114964975419909342221566832572080821333186
116811553615836546984046708975602900950537616475847728421889679646244945160765353408198901
385442487984959953319101723355556602139450399736280750137837615307127761926849034352625200
015888535147331611702103968175921510907788019393178114194545257223865541461062892187960223
838971476088506276862967146674697562911234082439208160153780889893964518263243671616762179
168909779911903754031274622289988005195444414282012187361745992642956581746628302955570299
024324153181617210465832036786906117260158783520751516284225540265170483304226143974286933
061690897968482590125458327168226458066526769958652682272807075781391858178889652208164348
344825993266043367660176999612831860788386150279465955131156552036093988180612138558600301
435694527224206344631797460594682573103790084024432438465657245014402821885252470935190620
929023136493273497565513958720559654228749774011413346962715422845862377387538230483865688
976461927383814900140767310446640259899490222221765904339901886018566526485061799702356193
897017860040811889729918311021171229845901641921068884387121855646124960798722908519296819
372388642614839657382291123125024186649353143970137428531926649875337218940694281434118520
158014123344828015051399694290153483077644569099073152433278288269864602789864321139083506
217095002597389863554277196742822248757586765752344220207573630569498825087968928162753848
863396909959826280956121450994871701244516461260379029309120889086942028510640182154399457
156805941872748998094254742173582401063677404595741785160829230135358081840096996372524230
560855903700624271243416909004153690105933983835777939410970027753472000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000




                                                                                             75
Complete
  Object
Orientation
              76
10.class
=> Fixnum



            77
Fixnum.object_id
=> 108610



                   78
(10*10).class
=> Fixnum

(10*10*100_000_000).class
=> Bignum


                            79
awesome joolie




Taking the pain
out of things you
don't like doing

                            80
attwenger   = [
  { :year   => 1991,   :tracks   =>   18,   :title   =>   "Most"           },
  { :year   => 1992,   :tracks   =>   10,   :title   =>   "Pflug"          },
  { :year   => 1993,   :tracks   =>   17,   :title   =>   "Luft"           },
  { :year   => 1997,   :tracks   =>   5,    :title   =>   "Song"           },
  { :year   => 2002,   :tracks   =>   15,   :title   =>   "Sun"            },
  { :year   => 2005,   :tracks   =>   14,   :title   =>   "dog"            },
  { :year   => 2006,   :tracks   =>   17,   :title   =>   "dog2 remixes"   },
  { :year   => 2007,   :tracks   =>   8,    :title   =>   "die Kia"        }
]




                                                                                81
# calculate the total amount of tracks in all albums
total = attwenger.inject(0) { |memo, album| memo + album[:tracks] }
puts "There are #{total} Attwenger tracks on #{attwenger.size} albums."




                                                                          82
# average number of tracks
puts "The average number of tracks per album is #{total/attwenger.size}."




                                                                        83
# which letters are used in album titles?
title_strings = attwenger.map{ |album| album[:title] }.join.gsub(/s/,'').upcase
title_letters = title_strings.split(//).uniq.sort.join

puts "These letters are used in album titles: #{title_letters}"




                                                                                   84
Java
public static String reverseString(String source) {
  int i, len = source.length();
  StringBuffer dest = new StringBuffer(len);

    for (i = (len - 1); i >= 0; i--)
      dest.append(source.charAt(i));

    return dest.toString();
}

reverseString("Krawutzikapuzi");
=> "izupakiztuwarK"




                                                      85
# most common letters in album titles
title_count = title_letters.split(//).sort_by{|letter| title_strings.count(letter) }.
  reverse.map{ |letter| "#{letter}: #{title_strings.count(letter)}" }

puts "Number of times individual letters are used in album titles, highest first:"
puts "#{title_count.join(', ')}"




                                                                                        86
just 10 lines of code


$ ruby arrays.rb
There are 104 Attwenger tracks on 8 albums.
The average number of tracks per album is 13.
These letters are used in album titles:
2ADEFGIKLMNOPRSTUX
Number of times individual letters are used in
album titles, highest first:
O: 4, S: 4, G: 4, U: 3, D: 3, I: 3, E: 3, N: 2,
F: 2, L: 2, T: 2, M: 2, X: 1, K: 1, P: 1, R: 1,
A: 1, 2: 1



                                                  87
Dynamic

          88
class Fixnum
  def fact
    return 1 if self == 0
    self * (self-1).fact
  end
end

10.fact
=> 3628800




                            89
class String
  def count_letters
    cleaned = self.gsub(/s/,'').upcase
    letters = cleaned.split(//).uniq.sort.join
    letters.split(//).sort_by{|letter| cleaned.count(letter) }.
      reverse.map{ |letter| "#{letter}: #{cleaned.count(letter)}" }
  end
end

>> puts "Lorem ipsum dolor sit amet, consectetur adipisicing
elit.".count_letters.join(', ')
=> "I: 7, T: 5, E: 5, S: 4, O: 4, C: 3, R: 3, M: 3, L: 3, U: 2, P:
2, N: 2, D: 2, A: 2, G: 1, .: 1, ,: 1"




                                                                      90
class String
  def method_missing(method)
    puts "intercepting call to #{method}"
  end
end

"Lorem ipsum dolor".krawutzikaputzi
=> "intercepting call to krawutzikaputzi"




                                            91
method_missing is used to
                   provide on-the-fly "finders"


>> Post.find_by_published(true)
=> #<Post id: 1, title: "Hallo FH!",
body: "Lorem ipsum dolor sit amet,
consectetur adipisicing...", published:
true, created_at: "2008-04-14 12:07:46",
updated_at: "2008-04-14 12:07:46">




                                                  92
Demo
Toying with Ruby
                   93
More…

        94
hellochris on flickr




         REST


                      95
In the beginning,
there was the URI.




                     96
http://script.aculo.us/thomas/index.html




                                           97
http://script.aculo.us/thomas/index.html


                          this is an actual file,
                        in the thomas directory




                                                    98
http://www.merriam-webster.com/cgi-bin/mwwod.pl




                                                  99
http://www.merriam-webster.com/cgi-bin/mwwod.pl


                        "cgi-bin" was a special
                        location for executable
                                  files




                                                  100
http://gilesbowkett.blogspot.com/search?updated-
max=2008-04-08T09%3A25%3A00-07%3A00&max-results=7




                                                101
"search" is probably
                                 not a filename



 http://gilesbowkett.blogspot.com/search?updated-
max=2008-04-08T09%3A25%3A00-07%3A00&max-results=7

                       wtf?




                                                     102
http://www.amazon.de/gp/
      product/B0000262LH/
      ref=s9subs_c3_img1-
      rfc_p_19_32_31_9_9?
pf_rd_m=A1IDDPBG1NC5TQ&pf_rd_
s=center-2&pf_rd_r=1FMGVYJN44
H7WQD9YCR9&pf_rd_t=101&pf_rd_
  p=139524591&pf_rd_i=301128



                                103
http://www.amazon.de/gp/
      product/B0000262LH/
      ref=s9subs_c3_img1-
      rfc_p_19_32_31_9_9?
pf_rd_m=A1IDDPBG1NC5TQ&pf_rd_
s=center-2&pf_rd_r=1FMGVYJN44
H7WQD9YCR9&pf_rd_t=101&pf_rd_
  p=139524591&pf_rd_i=301128
           yeah, right.



                                104
http://www.amazon.de/cd/attwenger/dog




                                        105
http://www.amazon.de/cd/attwenger/dog


           wouldn't this be nicer?




                                        106
URIs were supposed to be about
resources—aka objects—not some
frankenstein combination of actual
   file paths and query strings to
dictate which thing, and what to do
                with it

                                      107
REST
(Representational State Transfer)
    follows this definition and
  identifies resources uniformly


                                    108
Web applications
 usually consist
   of objects



                   109
(like, say, blog posts)




                          110
What's a blog post?

It's an entry in a database.
Consists of title, body, date,
 whether it's public or not,
       and other data.

                                 111
HTML representation (read)




     http://0.0.0.0:3000/posts/1
                                   112
XML representation (read)
<?xml version=“1.0” encoding=“UTF-8”?>
<post>
  <body>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad
minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex
ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate
velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat
cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id
est laborum.</body>
  <created-at type=“datetime”>2008-04-14T12:07:46+02:00</created-at>
  <id type=“integer”>1</id>
  <published type=“boolean”>true</published>
  <title>Another title</title>
  <updated-at type=“datetime”>2008-04-15T11:30:50+02:00</updated-at>
  <version type=“integer”>2</version>
</post>




               http://0.0.0.0:3000/posts/1.xml
                                                                             113
def show
  @post = Post.find(params[:id])

  respond_to do |format|
    format.html
    format.xml { render :xml => @post }
  end
end




                                          114
database entry gets
              converted into…
def show
  @post = Post.find(params[:id])

  respond_to do |format|
    format.html
    format.xml { render :xml => @post }
  end
end
        …REST representations




                                          115
RESTful operations

     Create
      Read
     Update
     Delete

                     116
Read




       117
HTTP verbs




             118
In HTTP each request is
 preceeded by a request
     type, or "verb".


                          119
Normal page loads use
 the "GET" verb, while
web forms use "POST".


                         120
HTTP knows more verbs,
most importantly "PUT",
 "DELETE" and "HEAD".


                          121
REST operation   HTTP verb

Create           POST
Read             GET
Update           PUT
Delete           DELETE


                             122
operation (read)


     GET     http://0.0.0.0:3000/posts/1


                      resource identifier




                                            123
operation (delete)



   DELETE        http://0.0.0.0:3000/posts/1


                        resource identifier
                        (same as for read)




                                               124
REST allows for
  consistent,
guessable URIs


                  125
The best thing is
that Rails does all
 this completely
  automatically


                      126
Plugins




juiceboxgasoline on flickr


                            127
100s of plugins available




                            128
Don’t
 repeat
yourself
           129
acts_as_versioned




                    130
>> post = Post.find(:first)
=> #<Post id: 1, title: "Another title", body: "Lorem
ipsum dolor sit amet, consectetur adipisicing...",
published: true, created_at: "2008-04-14 12:07:46",
updated_at: "2008-04-15 11:30:50", version: 2>
>> post.versions
=> [#<Post::Version id: 1, post_id: 1, version: 1,
title: "This is a test post", body: "Lorem ipsum dolor
sit amet, consectetur adipisicing...", published:
true, created_at: "2008-04-14 12:07:46", updated_at:
"2008-04-15 11:29:44">, #<Post::Version id: 2,
post_id: 1, version: 2, title: "Another title", body:
"Lorem ipsum dolor sit amet, consectetur
adipisicing...", published: true, created_at:
"2008-04-14 12:07:46", updated_at: "2008-04-15
11:30:50">]
>> post.versions.size
=> 2                       title changed
                          between versions


                                                         131
db/migrate/002_add_post_versions.rb


class AddPostVersions < ActiveRecord::Migration
  require_dependency 'post'

 def self.up
   Post.create_versioned_table
 end

  def self.down
    Post.drop_versioned_table
  end
end




                                                  132
one line of code


class Post < ActiveRecord::Base
  acts_as_versioned

  validates_presence_of :title
  validates_length_of   :body, :minimum=>10
end




                                              133
Demo
Plugins
          134
Ajax

       135
"Ajax" allows to update
    parts of the page,
without a complete reload



                            136
.
Rails includes the -------- and
                    prototype
                        .

 and             JavaScript
         frameworks



                                  137
display current (server) time




                                138
Demo
Ajax on Rails
                139
Testing




          140
class PostsControllerTest < ActionController::TestCase

 def test_should_get_index
   get :index
   assert_response :success
   assert_not_nil assigns(:posts)
 end

end




                                                         141
vintagehalloweencollector on flickr




                                     Debugging




                                                 142
super-easy way to really find out
def index    what happens in your code
  @posts = Post.find(:all)
  debugger

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




                                                 143
Demo
Debugging
            144
Rails
Ecosystem
            145
IDEs and Editors like Textmate

                                 146
Web services like github

                           147
Web- and Application
  Server software
                       148
Conferences

              149
tbiyonysHhoips
        ReilccoertdshReegluae Am y
Actuibven Ra s h a e t id
 aR yo
                                                                                       note: has_many and has_one
                                                                                       work identically except for the
                                                                                     number of relationships. both go on
                                                                                       the table/model that does not
                                                                                           feature the foreign key
belongs to                                                    has many
   create table customers (                                     create table companies (
      id int auto_increment primary key,                           id int auto_increment primary key,
      name varchar(75),                                            name varchar(75)
      company_id int                                            )
   )

       customers belongs_to :company
           company_id                                         companies has_many :customers
                                                                       id




has and belongs to many
 create table articles (                   create table authors (                     create table articles_authors (
    id int auto_increment primary key,        id int auto_increment primary key,         author_id int,
    name varchar(75),                         name varchar(75)                           article_id int
    body text                              )                                          )
 )


   articles                                                                   authors
   has_and_belongs_to_many :authors                                           has_and_belongs_to_many :articles
           id
                                              articles_authors                         id
                                                 article_id
                                                 author_id


note: the articles_authors table is implicit due to the two models that call habtm, and it does not require a model of
   its own. when making implicit mapping tables such as this, it must be named tablea_tableb where a is first in
                                                   alphabetical order.


                           © 2005 Amy Hoy / amy@infocookie.com / www.slash7.com
                             MIT License — see http://www.slash7.org/cheats/license.html




                                                              Podcasts, Books and
                                                               other Publications
                                                                                                                           150
Operating Systems

                    151
.
prototype
    .



 "Spinoffs"

              152
Q+A
      153

More Related Content

What's hot

Distributed Ruby and Rails
Distributed Ruby and RailsDistributed Ruby and Rails
Distributed Ruby and RailsWen-Tien Chang
 
Ruby on Rails Presentation
Ruby on Rails PresentationRuby on Rails Presentation
Ruby on Rails Presentationadamcookeuk
 
Ruby on Rails Presentation
Ruby on Rails PresentationRuby on Rails Presentation
Ruby on Rails PresentationJoost Hietbrink
 
Ruby Basics
Ruby BasicsRuby Basics
Ruby BasicsSHC
 
Ruby on Rails - An overview
Ruby on Rails -  An overviewRuby on Rails -  An overview
Ruby on Rails - An overviewThomas Asikis
 
Ruby on Rails workshop for beginner
Ruby on Rails workshop for beginnerRuby on Rails workshop for beginner
Ruby on Rails workshop for beginnerUmair Amjad
 
Developing cross platform desktop application with Ruby
Developing cross platform desktop application with RubyDeveloping cross platform desktop application with Ruby
Developing cross platform desktop application with RubyAnis Ahmad
 
Ruby on Rails Training - Module 1
Ruby on Rails Training - Module 1Ruby on Rails Training - Module 1
Ruby on Rails Training - Module 1Mark Menard
 
Ruby on Rails 101 - Presentation Slides for a Five Day Introductory Course
Ruby on Rails 101 - Presentation Slides for a Five Day Introductory CourseRuby on Rails 101 - Presentation Slides for a Five Day Introductory Course
Ruby on Rails 101 - Presentation Slides for a Five Day Introductory Coursepeter_marklund
 
Let's Learn Ruby - Basic
Let's Learn Ruby - BasicLet's Learn Ruby - Basic
Let's Learn Ruby - BasicEddie Kao
 
O que há de novo no Rails 3
O que há de novo no Rails 3O que há de novo no Rails 3
O que há de novo no Rails 3Hugo Baraúna
 
Introduction to Rails - presented by Arman Ortega
Introduction to Rails - presented by Arman OrtegaIntroduction to Rails - presented by Arman Ortega
Introduction to Rails - presented by Arman Ortegaarman o
 
Be Happy With Ruby on Rails - Ecosystem
Be Happy With Ruby on Rails - EcosystemBe Happy With Ruby on Rails - Ecosystem
Be Happy With Ruby on Rails - EcosystemLucas Renan
 
Introduction to JRuby
Introduction to JRubyIntroduction to JRuby
Introduction to JRubyelliando dias
 
Ruby application based on http
Ruby application based on httpRuby application based on http
Ruby application based on httpRichard Huang
 
Security Goodness with Ruby on Rails
Security Goodness with Ruby on RailsSecurity Goodness with Ruby on Rails
Security Goodness with Ruby on RailsSource Conference
 
Ruby on Rails 2.1 What's New
Ruby on Rails 2.1 What's NewRuby on Rails 2.1 What's New
Ruby on Rails 2.1 What's NewLibin Pan
 

What's hot (20)

Distributed Ruby and Rails
Distributed Ruby and RailsDistributed Ruby and Rails
Distributed Ruby and Rails
 
Ruby on Rails Presentation
Ruby on Rails PresentationRuby on Rails Presentation
Ruby on Rails Presentation
 
遇見 Ruby on Rails
遇見 Ruby on Rails遇見 Ruby on Rails
遇見 Ruby on Rails
 
Ruby on Rails Presentation
Ruby on Rails PresentationRuby on Rails Presentation
Ruby on Rails Presentation
 
Ruby on Rails
Ruby on RailsRuby on Rails
Ruby on Rails
 
Ruby Basics
Ruby BasicsRuby Basics
Ruby Basics
 
Ruby on Rails - An overview
Ruby on Rails -  An overviewRuby on Rails -  An overview
Ruby on Rails - An overview
 
Ruby on Rails workshop for beginner
Ruby on Rails workshop for beginnerRuby on Rails workshop for beginner
Ruby on Rails workshop for beginner
 
Developing cross platform desktop application with Ruby
Developing cross platform desktop application with RubyDeveloping cross platform desktop application with Ruby
Developing cross platform desktop application with Ruby
 
Ruby on Rails Training - Module 1
Ruby on Rails Training - Module 1Ruby on Rails Training - Module 1
Ruby on Rails Training - Module 1
 
Ruby on Rails 101 - Presentation Slides for a Five Day Introductory Course
Ruby on Rails 101 - Presentation Slides for a Five Day Introductory CourseRuby on Rails 101 - Presentation Slides for a Five Day Introductory Course
Ruby on Rails 101 - Presentation Slides for a Five Day Introductory Course
 
Let's Learn Ruby - Basic
Let's Learn Ruby - BasicLet's Learn Ruby - Basic
Let's Learn Ruby - Basic
 
O que há de novo no Rails 3
O que há de novo no Rails 3O que há de novo no Rails 3
O que há de novo no Rails 3
 
Introduction to Rails - presented by Arman Ortega
Introduction to Rails - presented by Arman OrtegaIntroduction to Rails - presented by Arman Ortega
Introduction to Rails - presented by Arman Ortega
 
Be Happy With Ruby on Rails - Ecosystem
Be Happy With Ruby on Rails - EcosystemBe Happy With Ruby on Rails - Ecosystem
Be Happy With Ruby on Rails - Ecosystem
 
Introduction to JRuby
Introduction to JRubyIntroduction to JRuby
Introduction to JRuby
 
Ruby application based on http
Ruby application based on httpRuby application based on http
Ruby application based on http
 
Security Goodness with Ruby on Rails
Security Goodness with Ruby on RailsSecurity Goodness with Ruby on Rails
Security Goodness with Ruby on Rails
 
Ruby on Rails 2.1 What's New
Ruby on Rails 2.1 What's NewRuby on Rails 2.1 What's New
Ruby on Rails 2.1 What's New
 
Ruby on Rails
Ruby on RailsRuby on Rails
Ruby on Rails
 

Viewers also liked

Why every startup built with Ruby on Rails has an upper hand over their compe...
Why every startup built with Ruby on Rails has an upper hand over their compe...Why every startup built with Ruby on Rails has an upper hand over their compe...
Why every startup built with Ruby on Rails has an upper hand over their compe...DreamToIPO
 
Launching Ruby on Rails projects: A checklist
Launching Ruby on Rails projects: A checklistLaunching Ruby on Rails projects: A checklist
Launching Ruby on Rails projects: A checklistRobby Russell
 
Social and Technical Evolution of the Ruby on Rails Software Ecosystem
Social and Technical Evolution of the Ruby on Rails Software EcosystemSocial and Technical Evolution of the Ruby on Rails Software Ecosystem
Social and Technical Evolution of the Ruby on Rails Software EcosystemTom Mens
 
Introduction to Ruby on Rails
Introduction to Ruby on RailsIntroduction to Ruby on Rails
Introduction to Ruby on RailsAmit Patel
 
Enterprise Architectures with Ruby (and Rails)
Enterprise Architectures with Ruby (and Rails)Enterprise Architectures with Ruby (and Rails)
Enterprise Architectures with Ruby (and Rails)Konstantin Gredeskoul
 

Viewers also liked (9)

Why every startup built with Ruby on Rails has an upper hand over their compe...
Why every startup built with Ruby on Rails has an upper hand over their compe...Why every startup built with Ruby on Rails has an upper hand over their compe...
Why every startup built with Ruby on Rails has an upper hand over their compe...
 
Launching Ruby on Rails projects: A checklist
Launching Ruby on Rails projects: A checklistLaunching Ruby on Rails projects: A checklist
Launching Ruby on Rails projects: A checklist
 
Why MVC?
Why MVC?Why MVC?
Why MVC?
 
MVC Architecture
MVC ArchitectureMVC Architecture
MVC Architecture
 
Proyecto
ProyectoProyecto
Proyecto
 
Social and Technical Evolution of the Ruby on Rails Software Ecosystem
Social and Technical Evolution of the Ruby on Rails Software EcosystemSocial and Technical Evolution of the Ruby on Rails Software Ecosystem
Social and Technical Evolution of the Ruby on Rails Software Ecosystem
 
Introduction to Ruby on Rails
Introduction to Ruby on RailsIntroduction to Ruby on Rails
Introduction to Ruby on Rails
 
Enterprise Architectures with Ruby (and Rails)
Enterprise Architectures with Ruby (and Rails)Enterprise Architectures with Ruby (and Rails)
Enterprise Architectures with Ruby (and Rails)
 
Mvc architecture
Mvc architectureMvc architecture
Mvc architecture
 

Similar to Ruby On Rails Introduction

Ruby on Rails introduction
Ruby on Rails introduction Ruby on Rails introduction
Ruby on Rails introduction Tran Hung
 
Phoenix for Rails Devs
Phoenix for Rails DevsPhoenix for Rails Devs
Phoenix for Rails DevsDiacode
 
Building web framework with Rack
Building web framework with RackBuilding web framework with Rack
Building web framework with Racksickill
 
RoR 101: Session 2
RoR 101: Session 2RoR 101: Session 2
RoR 101: Session 2Rory Gianni
 
Ruby/Rails
Ruby/RailsRuby/Rails
Ruby/Railsrstankov
 
Fast Web Applications Development with Ruby on Rails on Oracle
Fast Web Applications Development with Ruby on Rails on OracleFast Web Applications Development with Ruby on Rails on Oracle
Fast Web Applications Development with Ruby on Rails on OracleRaimonds Simanovskis
 
Extending Oracle E-Business Suite with Ruby on Rails
Extending Oracle E-Business Suite with Ruby on RailsExtending Oracle E-Business Suite with Ruby on Rails
Extending Oracle E-Business Suite with Ruby on RailsRaimonds Simanovskis
 
Ruby on Rails - Introduction
Ruby on Rails - IntroductionRuby on Rails - Introduction
Ruby on Rails - IntroductionVagmi Mudumbai
 
TorqueBox: The beauty of Ruby with the power of JBoss. Presented at Devnexus...
TorqueBox: The beauty of Ruby with the power of JBoss.  Presented at Devnexus...TorqueBox: The beauty of Ruby with the power of JBoss.  Presented at Devnexus...
TorqueBox: The beauty of Ruby with the power of JBoss. Presented at Devnexus...bobmcwhirter
 
Connecting the Worlds of Java and Ruby with JRuby
Connecting the Worlds of Java and Ruby with JRubyConnecting the Worlds of Java and Ruby with JRuby
Connecting the Worlds of Java and Ruby with JRubyNick Sieger
 
Pourquoi ruby et rails déchirent
Pourquoi ruby et rails déchirentPourquoi ruby et rails déchirent
Pourquoi ruby et rails déchirentNicolas Ledez
 
Intro to Ruby on Rails
Intro to Ruby on RailsIntro to Ruby on Rails
Intro to Ruby on Railselpizoch
 
Code for Startup MVP (Ruby on Rails) Session 2
Code for Startup MVP (Ruby on Rails) Session 2Code for Startup MVP (Ruby on Rails) Session 2
Code for Startup MVP (Ruby on Rails) Session 2Henry S
 

Similar to Ruby On Rails Introduction (20)

Ruby on Rails introduction
Ruby on Rails introduction Ruby on Rails introduction
Ruby on Rails introduction
 
Supa fast Ruby + Rails
Supa fast Ruby + RailsSupa fast Ruby + Rails
Supa fast Ruby + Rails
 
Ruby On Rails
Ruby On RailsRuby On Rails
Ruby On Rails
 
Phoenix for Rails Devs
Phoenix for Rails DevsPhoenix for Rails Devs
Phoenix for Rails Devs
 
Building web framework with Rack
Building web framework with RackBuilding web framework with Rack
Building web framework with Rack
 
RoR 101: Session 2
RoR 101: Session 2RoR 101: Session 2
RoR 101: Session 2
 
Wider than rails
Wider than railsWider than rails
Wider than rails
 
Ruby/Rails
Ruby/RailsRuby/Rails
Ruby/Rails
 
Fast Web Applications Development with Ruby on Rails on Oracle
Fast Web Applications Development with Ruby on Rails on OracleFast Web Applications Development with Ruby on Rails on Oracle
Fast Web Applications Development with Ruby on Rails on Oracle
 
Extending Oracle E-Business Suite with Ruby on Rails
Extending Oracle E-Business Suite with Ruby on RailsExtending Oracle E-Business Suite with Ruby on Rails
Extending Oracle E-Business Suite with Ruby on Rails
 
Ruby on Rails - Introduction
Ruby on Rails - IntroductionRuby on Rails - Introduction
Ruby on Rails - Introduction
 
Dev streams2
Dev streams2Dev streams2
Dev streams2
 
PDF Ruby on Rails 3 Day BC
 PDF Ruby on Rails 3 Day BC PDF Ruby on Rails 3 Day BC
PDF Ruby on Rails 3 Day BC
 
TorqueBox: The beauty of Ruby with the power of JBoss. Presented at Devnexus...
TorqueBox: The beauty of Ruby with the power of JBoss.  Presented at Devnexus...TorqueBox: The beauty of Ruby with the power of JBoss.  Presented at Devnexus...
TorqueBox: The beauty of Ruby with the power of JBoss. Presented at Devnexus...
 
Ruby on rails for beginers
Ruby on rails for beginersRuby on rails for beginers
Ruby on rails for beginers
 
Connecting the Worlds of Java and Ruby with JRuby
Connecting the Worlds of Java and Ruby with JRubyConnecting the Worlds of Java and Ruby with JRuby
Connecting the Worlds of Java and Ruby with JRuby
 
Pourquoi ruby et rails déchirent
Pourquoi ruby et rails déchirentPourquoi ruby et rails déchirent
Pourquoi ruby et rails déchirent
 
Intro to Ruby on Rails
Intro to Ruby on RailsIntro to Ruby on Rails
Intro to Ruby on Rails
 
Code for Startup MVP (Ruby on Rails) Session 2
Code for Startup MVP (Ruby on Rails) Session 2Code for Startup MVP (Ruby on Rails) Session 2
Code for Startup MVP (Ruby on Rails) Session 2
 
Ruby on rails
Ruby on railsRuby on rails
Ruby on rails
 

More from Thomas Fuchs

Zepto and the rise of the JavaScript Micro-Frameworks
Zepto and the rise of the JavaScript Micro-FrameworksZepto and the rise of the JavaScript Micro-Frameworks
Zepto and the rise of the JavaScript Micro-FrameworksThomas Fuchs
 
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2K
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2KZepto.js, a jQuery-compatible mobile JavaScript framework in 2K
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2KThomas Fuchs
 
I Can't Believe It's Not Flash
I Can't Believe It's Not FlashI Can't Believe It's Not Flash
I Can't Believe It's Not FlashThomas Fuchs
 
Prototype & Scriptaculous
Prototype  & ScriptaculousPrototype  & Scriptaculous
Prototype & ScriptaculousThomas Fuchs
 
Extreme JavaScript Performance
Extreme JavaScript PerformanceExtreme JavaScript Performance
Extreme JavaScript PerformanceThomas Fuchs
 
Adventures In JavaScript Testing
Adventures In JavaScript TestingAdventures In JavaScript Testing
Adventures In JavaScript TestingThomas Fuchs
 
Rich and Snappy Apps (No Scaling Required)
Rich and Snappy Apps (No Scaling Required)Rich and Snappy Apps (No Scaling Required)
Rich and Snappy Apps (No Scaling Required)Thomas Fuchs
 

More from Thomas Fuchs (9)

Zepto and the rise of the JavaScript Micro-Frameworks
Zepto and the rise of the JavaScript Micro-FrameworksZepto and the rise of the JavaScript Micro-Frameworks
Zepto and the rise of the JavaScript Micro-Frameworks
 
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2K
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2KZepto.js, a jQuery-compatible mobile JavaScript framework in 2K
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2K
 
I Can't Believe It's Not Flash
I Can't Believe It's Not FlashI Can't Believe It's Not Flash
I Can't Believe It's Not Flash
 
Prototype & Scriptaculous
Prototype  & ScriptaculousPrototype  & Scriptaculous
Prototype & Scriptaculous
 
Extreme JavaScript Performance
Extreme JavaScript PerformanceExtreme JavaScript Performance
Extreme JavaScript Performance
 
Textorize
TextorizeTextorize
Textorize
 
Adventures In JavaScript Testing
Adventures In JavaScript TestingAdventures In JavaScript Testing
Adventures In JavaScript Testing
 
Twistori Tech
Twistori TechTwistori Tech
Twistori Tech
 
Rich and Snappy Apps (No Scaling Required)
Rich and Snappy Apps (No Scaling Required)Rich and Snappy Apps (No Scaling Required)
Rich and Snappy Apps (No Scaling Required)
 

Recently uploaded

20230202 - Introduction to tis-py
20230202 - Introduction to tis-py20230202 - Introduction to tis-py
20230202 - Introduction to tis-pyJamie (Taka) Wang
 
100+ ChatGPT Prompts for SEO Optimization
100+ ChatGPT Prompts for SEO Optimization100+ ChatGPT Prompts for SEO Optimization
100+ ChatGPT Prompts for SEO Optimizationarrow10202532yuvraj
 
UiPath Solutions Management Preview - Northern CA Chapter - March 22.pdf
UiPath Solutions Management Preview - Northern CA Chapter - March 22.pdfUiPath Solutions Management Preview - Northern CA Chapter - March 22.pdf
UiPath Solutions Management Preview - Northern CA Chapter - March 22.pdfDianaGray10
 
Valere | Digital Solutions & AI Transformation Portfolio | 2024
Valere | Digital Solutions & AI Transformation Portfolio | 2024Valere | Digital Solutions & AI Transformation Portfolio | 2024
Valere | Digital Solutions & AI Transformation Portfolio | 2024Alexander Turgeon
 
Machine Learning Model Validation (Aijun Zhang 2024).pdf
Machine Learning Model Validation (Aijun Zhang 2024).pdfMachine Learning Model Validation (Aijun Zhang 2024).pdf
Machine Learning Model Validation (Aijun Zhang 2024).pdfAijun Zhang
 
UiPath Clipboard AI: "A TIME Magazine Best Invention of 2023 Unveiled"
UiPath Clipboard AI: "A TIME Magazine Best Invention of 2023 Unveiled"UiPath Clipboard AI: "A TIME Magazine Best Invention of 2023 Unveiled"
UiPath Clipboard AI: "A TIME Magazine Best Invention of 2023 Unveiled"DianaGray10
 
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...UbiTrack UK
 
Igniting Next Level Productivity with AI-Infused Data Integration Workflows
Igniting Next Level Productivity with AI-Infused Data Integration WorkflowsIgniting Next Level Productivity with AI-Infused Data Integration Workflows
Igniting Next Level Productivity with AI-Infused Data Integration WorkflowsSafe Software
 
activity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdf
activity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdf
activity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdfJamie (Taka) Wang
 
How Accurate are Carbon Emissions Projections?
How Accurate are Carbon Emissions Projections?How Accurate are Carbon Emissions Projections?
How Accurate are Carbon Emissions Projections?IES VE
 
VoIP Service and Marketing using Odoo and Asterisk PBX
VoIP Service and Marketing using Odoo and Asterisk PBXVoIP Service and Marketing using Odoo and Asterisk PBX
VoIP Service and Marketing using Odoo and Asterisk PBXTarek Kalaji
 
Artificial Intelligence & SEO Trends for 2024
Artificial Intelligence & SEO Trends for 2024Artificial Intelligence & SEO Trends for 2024
Artificial Intelligence & SEO Trends for 2024D Cloud Solutions
 
Governance in SharePoint Premium:What's in the box?
Governance in SharePoint Premium:What's in the box?Governance in SharePoint Premium:What's in the box?
Governance in SharePoint Premium:What's in the box?Juan Carlos Gonzalez
 
Nanopower In Semiconductor Industry.pdf
Nanopower  In Semiconductor Industry.pdfNanopower  In Semiconductor Industry.pdf
Nanopower In Semiconductor Industry.pdfPedro Manuel
 
99.99% of Your Traces Are (Probably) Trash (SRECon NA 2024).pdf
99.99% of Your Traces  Are (Probably) Trash (SRECon NA 2024).pdf99.99% of Your Traces  Are (Probably) Trash (SRECon NA 2024).pdf
99.99% of Your Traces Are (Probably) Trash (SRECon NA 2024).pdfPaige Cruz
 
OpenShift Commons Paris - Choose Your Own Observability Adventure
OpenShift Commons Paris - Choose Your Own Observability AdventureOpenShift Commons Paris - Choose Your Own Observability Adventure
OpenShift Commons Paris - Choose Your Own Observability AdventureEric D. Schabell
 
KubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCost
KubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCostKubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCost
KubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCostMatt Ray
 
UiPath Studio Web workshop series - Day 6
UiPath Studio Web workshop series - Day 6UiPath Studio Web workshop series - Day 6
UiPath Studio Web workshop series - Day 6DianaGray10
 
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...Aggregage
 

Recently uploaded (20)

20230202 - Introduction to tis-py
20230202 - Introduction to tis-py20230202 - Introduction to tis-py
20230202 - Introduction to tis-py
 
100+ ChatGPT Prompts for SEO Optimization
100+ ChatGPT Prompts for SEO Optimization100+ ChatGPT Prompts for SEO Optimization
100+ ChatGPT Prompts for SEO Optimization
 
UiPath Solutions Management Preview - Northern CA Chapter - March 22.pdf
UiPath Solutions Management Preview - Northern CA Chapter - March 22.pdfUiPath Solutions Management Preview - Northern CA Chapter - March 22.pdf
UiPath Solutions Management Preview - Northern CA Chapter - March 22.pdf
 
Valere | Digital Solutions & AI Transformation Portfolio | 2024
Valere | Digital Solutions & AI Transformation Portfolio | 2024Valere | Digital Solutions & AI Transformation Portfolio | 2024
Valere | Digital Solutions & AI Transformation Portfolio | 2024
 
Machine Learning Model Validation (Aijun Zhang 2024).pdf
Machine Learning Model Validation (Aijun Zhang 2024).pdfMachine Learning Model Validation (Aijun Zhang 2024).pdf
Machine Learning Model Validation (Aijun Zhang 2024).pdf
 
UiPath Clipboard AI: "A TIME Magazine Best Invention of 2023 Unveiled"
UiPath Clipboard AI: "A TIME Magazine Best Invention of 2023 Unveiled"UiPath Clipboard AI: "A TIME Magazine Best Invention of 2023 Unveiled"
UiPath Clipboard AI: "A TIME Magazine Best Invention of 2023 Unveiled"
 
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
 
Igniting Next Level Productivity with AI-Infused Data Integration Workflows
Igniting Next Level Productivity with AI-Infused Data Integration WorkflowsIgniting Next Level Productivity with AI-Infused Data Integration Workflows
Igniting Next Level Productivity with AI-Infused Data Integration Workflows
 
activity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdf
activity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdf
activity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdf
 
How Accurate are Carbon Emissions Projections?
How Accurate are Carbon Emissions Projections?How Accurate are Carbon Emissions Projections?
How Accurate are Carbon Emissions Projections?
 
VoIP Service and Marketing using Odoo and Asterisk PBX
VoIP Service and Marketing using Odoo and Asterisk PBXVoIP Service and Marketing using Odoo and Asterisk PBX
VoIP Service and Marketing using Odoo and Asterisk PBX
 
Artificial Intelligence & SEO Trends for 2024
Artificial Intelligence & SEO Trends for 2024Artificial Intelligence & SEO Trends for 2024
Artificial Intelligence & SEO Trends for 2024
 
Governance in SharePoint Premium:What's in the box?
Governance in SharePoint Premium:What's in the box?Governance in SharePoint Premium:What's in the box?
Governance in SharePoint Premium:What's in the box?
 
201610817 - edge part1
201610817 - edge part1201610817 - edge part1
201610817 - edge part1
 
Nanopower In Semiconductor Industry.pdf
Nanopower  In Semiconductor Industry.pdfNanopower  In Semiconductor Industry.pdf
Nanopower In Semiconductor Industry.pdf
 
99.99% of Your Traces Are (Probably) Trash (SRECon NA 2024).pdf
99.99% of Your Traces  Are (Probably) Trash (SRECon NA 2024).pdf99.99% of Your Traces  Are (Probably) Trash (SRECon NA 2024).pdf
99.99% of Your Traces Are (Probably) Trash (SRECon NA 2024).pdf
 
OpenShift Commons Paris - Choose Your Own Observability Adventure
OpenShift Commons Paris - Choose Your Own Observability AdventureOpenShift Commons Paris - Choose Your Own Observability Adventure
OpenShift Commons Paris - Choose Your Own Observability Adventure
 
KubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCost
KubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCostKubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCost
KubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCost
 
UiPath Studio Web workshop series - Day 6
UiPath Studio Web workshop series - Day 6UiPath Studio Web workshop series - Day 6
UiPath Studio Web workshop series - Day 6
 
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...
 

Ruby On Rails Introduction

  • 1. bogers on flickr Thomas Fuchs Ruby on Rails 1
  • 3. ABC Digg Nasa Amazon ESPN NBC Apple Gucci Tivo CNET last.fm Twitter 3
  • 4. . prototype . prototypejs.org 4
  • 6. Part 1 Rails Overview and Demo Part 2 Introduction to Ruby Part 3 More Rails! 6
  • 9. Programming Web Language Framework 9
  • 10. 10
  • 11. Programming Web Language Framework 11
  • 12. 12
  • 13. Ruby on Rails is an open-source web framework that’s optimized for programmer happiness and sustainable productivity. It lets you write beautiful code by favoring convention over configuration. 13
  • 14. Ruby on Rails is an open-source web framework that’s optimized for programmer happiness and sustainable productivity. It lets you write beautiful code by favoring convention over configuration. 14
  • 15. Ruby on Rails is an open-source web framework that’s optimized for programmer happiness and sustainable productivity. It lets you write beautiful code by favoring convention over configuration. 15
  • 16. Ruby on Rails is an open-source web framework that’s optimized for programmer happiness and sustainable productivity. It lets you write beautiful code by favoring convention over configuration. 16
  • 17. Ruby on Rails is an open-source web framework that’s optimized for programmer happiness and sustainable productivity. It lets you write beautiful code by favoring convention over configuration. 17
  • 18. Ruby on Rails is an open-source web framework that’s optimized for programmer happiness and sustainable productivity. It lets you write beautiful code by favoring convention over configuration. 18
  • 19. 80/20 19
  • 20. Opinionated Software dbloete on flickr 20
  • 23. "app" application logic "config" database and deployment information "db" database structure and migrations "public" CSS, images, JavaScripts and static HTML "vendor/plugins" add-ons to "core" rails 23
  • 26. Controller Structures application Provides Provides data user interface Model View 26
  • 27. controller/posts_controller.rb def index @posts = Post.find(:all) respond_to do |format| format.html format.xml { render :xml => @posts } end end 27
  • 28. "index" maps to the name of the controller by default, so http://localhost:3000/posts accesses this action def index @posts = Post.find(:all) respond_to do |format| format.html format.xml { render :xml => @posts } end end 28
  • 29. find all posts and assign them to a variable named @posts def index @posts = Post.find(:all) respond_to do |format| format.html format.xml { render :xml => @posts } end end "Post" is the name of the model 29
  • 30. def index @posts = Post.find(:all) respond_to do |format| format.html format.xml { render :xml => @posts } end end we decide to respond to different requests, so we can serve a web site for users, but also XML data for other systems (API) 30
  • 31. def index @posts = Post.find(:all) respond_to do |format| format.html format.xml { render :xml => @posts } end end for HTML, just use the defaults: get the view that is named the same as the action, and render it 31
  • 32. def index @posts = Post.find(:all) respond_to do |format| format.html format.xml { render :xml => @posts } end end for XML requests, use the default XML rendering, no more code required 32
  • 33. views/posts/index.html.erb <h1>Listing posts</h1> <table> <tr> <th>Title</th> <th>Body</th> <th>Published</th> </tr> <% for post in @posts %> <tr> <td><%=h post.title %></td> <td><%=h post.body %></td> <td><%=h post.published %></td> <td><%= link_to ‘Show’, post %></td> <td><%= link_to ‘Edit’, edit_post_path(post) %></td> <td><%= link_to ‘Destroy’, post, :confirm => ‘Are you sure?’, :method => :delete %></td> </tr> <% end %> </table> <br /> <%= link_to ‘New post’, new_post_path %> 33
  • 34. views/posts/index.html.erb <h1>Listing posts</h1> <table> <tr> <th>Title</th> <th>Body</th> <th>Published</th> embedded Ruby (.erb) </tr> <% for post in @posts %> <tr> <td><%=h post.title %></td> <td><%=h post.body %></td> <td><%=h post.published %></td> <td><%= link_to ‘Show’, post %></td> <td><%= link_to ‘Edit’, edit_post_path(post) %></td> <td><%= link_to ‘Destroy’, post, :confirm => ‘Are you sure?’, :method => :delete %></td> </tr> <% end %> </table> automatically provided link helpers <br /> <%= link_to ‘New post’, new_post_path %> 34
  • 35. 35
  • 36. 36
  • 37. models/post.rb class Post < ActiveRecord::Base validates_presence_of :title validates_length_of :body, :minimum=>10 end 37
  • 38. self-explanatory validations class Post < ActiveRecord::Base validates_presence_of :title validates_length_of :body, :minimum=>10 end 38
  • 39. 39
  • 40. class Post < ActiveRecord::Base validates_presence_of :title validates_length_of :body, :minimum=>10 end What is missing here? 40
  • 41. Because fields are already declared in the Database, no need to redeclare it in the model 41
  • 42. db/schema.rb (automatically created) ActiveRecord::Schema.define(:version => 1) do create_table "posts", :force => true do |t| t.string "title" t.text "body" t.boolean "published" t.datetime "created_at" t.datetime "updated_at" end end 42
  • 43. db/migrate/001_create_posts.rb (automatically created by generator) class CreatePosts < ActiveRecord::Migration def self.up create_table :posts do |t| t.string :title t.text :body t.boolean :published t.timestamps end end def self.down drop_table :posts end end 43
  • 45. Programming Web Language Framework 45
  • 46. Why an other programming language? 46
  • 48. Some might like this, but it's mostly because most Software Development Tools are designed for computers, not for human beings. 48
  • 49. "Ruby is simple in appearance, but is very complex inside, just like our human body." Yukihiro “Matz” Matsumoto, Creator of Ruby 49
  • 52. Design the language and libraries for people first 52
  • 53. Let others care about performance 53
  • 54. A Programmer’s Best Friend 54
  • 55. say = "I love Ruby" puts say => "I love Ruby" 55
  • 56. no type no “main” method declarations "String..." no “end of say = "I love Ruby" instruction” marker puts say no superflous keywords (“var”) 56
  • 57. say = "I love Ruby" say['love'] = "*love*" puts say.upcase => "I *LOVE* RUBY" 57
  • 58. 5.times { puts say } => "I *love* Ruby" => "I *love* Ruby" => "I *love* Ruby" => "I *love* Ruby" => "I *love* Ruby" 58
  • 59. [Ruby is] a dynamic, open source programming language with a focus on simplicity and productivity. It has an elegant syntax that is natural to read and easy to write. 59
  • 60. [Ruby is] a dynamic, open source programming language with a focus on simplicity and productivity. It has an elegant syntax that is natural to read and easy to write. 60
  • 61. [Ruby is] a dynamic, open source programming language with a focus on simplicity and productivity. It has an elegant syntax that is natural to read and easy to write. 61
  • 62. [Ruby is] a dynamic, open source programming language with a focus on simplicity and productivity. It has an elegant syntax that is natural to read and easy to write. 62
  • 63. [Ruby is] a dynamic, open source programming language with a focus on simplicity and productivity. It has an elegant syntax that is natural to read and easy to write. 63
  • 64. [Ruby is] a dynamic, open source programming language with a focus on simplicity and productivity. It has an elegant syntax that is natural to read and easy to write. 64
  • 65. dan_h on flickr Less is more 65
  • 66. Java public static String reverseString(String source) { int i, len = source.length(); StringBuffer dest = new StringBuffer(len); for (i = (len - 1); i >= 0; i--) dest.append(source.charAt(i)); return dest.toString(); } reverseString("Krawutzikapuzi"); => "izupakiztuwarK" 66
  • 69. Ruby "Krawutzikapuzi".split(//).inject(""){|m,c|c+m} => "izupakiztuwarK" Not using the built-in “reverse” method: still much smaller than Java 69
  • 71. def fact(n) return 1 if n == 0 n * fact(n-1) end 71
  • 72. 47584772842188967964624494516076535340819890 38544248798495995331910172335555660213945039 73628075013783761530712776192684903435262520 01588853514733161170210396817592151090778801 39317811419454525722386554146106289218796022 83897147608850627686296714667469756291123408 43920816015378088989396451826324367161676217 (for non-maths people: 16890977991190375403127462228998800519544441 28201218736174599264295658174662830295557029 this produces laaaaaarge 02432415318161721046583203678690611726015878 52075151628422554026517048330422614397428693 numbers) 06169089796848259012545832716822645806652676 95865268227280707578139185817888965220816434 34482599326604336766017699961283186078838615 27946595513115655203609398818061213855860030 43569452722420634463179746059468257310379008 02443243846565724501440282188525247093519062 92902313649327349756551395872055965422874977 72
  • 73. >>fact(2) => 2 >> fact(3) => 6 >> fact(10) => 3628800 73
  • 74. <?php function fact($int){ if ($int<2) return 1; for ($f=2; $int-1>1; $f*=$int--); return $f; }; echo fact(10)."n"; echo fact(999)."n"; ?> PHP $ php fact.php 3628800 PHP overflows and cannot INF calculate a result 74
  • 75. Ruby does not care about overflows and does the right thing: calculate what you want >> fact(999) => 402387260077093773543702433923003985719374864210714632543799910429938512398629020592044208 486969404800479988610197196058631666872994808558901323829669944590997424504087073759918823 627727188732519779505950995276120874975462497043601418278094646496291056393887437886487337 119181045825783647849977012476632889835955735432513185323958463075557409114262417474349347 553428646576611667797396668820291207379143853719588249808126867838374559731746136085379534 524221586593201928090878297308431392844403281231558611036976801357304216168747609675871348 312025478589320767169132448426236131412508780208000261683151027341827977704784635868170164 365024153691398281264810213092761244896359928705114964975419909342221566832572080821333186 116811553615836546984046708975602900950537616475847728421889679646244945160765353408198901 385442487984959953319101723355556602139450399736280750137837615307127761926849034352625200 015888535147331611702103968175921510907788019393178114194545257223865541461062892187960223 838971476088506276862967146674697562911234082439208160153780889893964518263243671616762179 168909779911903754031274622289988005195444414282012187361745992642956581746628302955570299 024324153181617210465832036786906117260158783520751516284225540265170483304226143974286933 061690897968482590125458327168226458066526769958652682272807075781391858178889652208164348 344825993266043367660176999612831860788386150279465955131156552036093988180612138558600301 435694527224206344631797460594682573103790084024432438465657245014402821885252470935190620 929023136493273497565513958720559654228749774011413346962715422845862377387538230483865688 976461927383814900140767310446640259899490222221765904339901886018566526485061799702356193 897017860040811889729918311021171229845901641921068884387121855646124960798722908519296819 372388642614839657382291123125024186649353143970137428531926649875337218940694281434118520 158014123344828015051399694290153483077644569099073152433278288269864602789864321139083506 217095002597389863554277196742822248757586765752344220207573630569498825087968928162753848 863396909959826280956121450994871701244516461260379029309120889086942028510640182154399457 156805941872748998094254742173582401063677404595741785160829230135358081840096996372524230 560855903700624271243416909004153690105933983835777939410970027753472000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000 75
  • 80. awesome joolie Taking the pain out of things you don't like doing 80
  • 81. attwenger = [ { :year => 1991, :tracks => 18, :title => "Most" }, { :year => 1992, :tracks => 10, :title => "Pflug" }, { :year => 1993, :tracks => 17, :title => "Luft" }, { :year => 1997, :tracks => 5, :title => "Song" }, { :year => 2002, :tracks => 15, :title => "Sun" }, { :year => 2005, :tracks => 14, :title => "dog" }, { :year => 2006, :tracks => 17, :title => "dog2 remixes" }, { :year => 2007, :tracks => 8, :title => "die Kia" } ] 81
  • 82. # calculate the total amount of tracks in all albums total = attwenger.inject(0) { |memo, album| memo + album[:tracks] } puts "There are #{total} Attwenger tracks on #{attwenger.size} albums." 82
  • 83. # average number of tracks puts "The average number of tracks per album is #{total/attwenger.size}." 83
  • 84. # which letters are used in album titles? title_strings = attwenger.map{ |album| album[:title] }.join.gsub(/s/,'').upcase title_letters = title_strings.split(//).uniq.sort.join puts "These letters are used in album titles: #{title_letters}" 84
  • 85. Java public static String reverseString(String source) { int i, len = source.length(); StringBuffer dest = new StringBuffer(len); for (i = (len - 1); i >= 0; i--) dest.append(source.charAt(i)); return dest.toString(); } reverseString("Krawutzikapuzi"); => "izupakiztuwarK" 85
  • 86. # most common letters in album titles title_count = title_letters.split(//).sort_by{|letter| title_strings.count(letter) }. reverse.map{ |letter| "#{letter}: #{title_strings.count(letter)}" } puts "Number of times individual letters are used in album titles, highest first:" puts "#{title_count.join(', ')}" 86
  • 87. just 10 lines of code $ ruby arrays.rb There are 104 Attwenger tracks on 8 albums. The average number of tracks per album is 13. These letters are used in album titles: 2ADEFGIKLMNOPRSTUX Number of times individual letters are used in album titles, highest first: O: 4, S: 4, G: 4, U: 3, D: 3, I: 3, E: 3, N: 2, F: 2, L: 2, T: 2, M: 2, X: 1, K: 1, P: 1, R: 1, A: 1, 2: 1 87
  • 88. Dynamic 88
  • 89. class Fixnum def fact return 1 if self == 0 self * (self-1).fact end end 10.fact => 3628800 89
  • 90. class String def count_letters cleaned = self.gsub(/s/,'').upcase letters = cleaned.split(//).uniq.sort.join letters.split(//).sort_by{|letter| cleaned.count(letter) }. reverse.map{ |letter| "#{letter}: #{cleaned.count(letter)}" } end end >> puts "Lorem ipsum dolor sit amet, consectetur adipisicing elit.".count_letters.join(', ') => "I: 7, T: 5, E: 5, S: 4, O: 4, C: 3, R: 3, M: 3, L: 3, U: 2, P: 2, N: 2, D: 2, A: 2, G: 1, .: 1, ,: 1" 90
  • 91. class String def method_missing(method) puts "intercepting call to #{method}" end end "Lorem ipsum dolor".krawutzikaputzi => "intercepting call to krawutzikaputzi" 91
  • 92. method_missing is used to provide on-the-fly "finders" >> Post.find_by_published(true) => #<Post id: 1, title: "Hallo FH!", body: "Lorem ipsum dolor sit amet, consectetur adipisicing...", published: true, created_at: "2008-04-14 12:07:46", updated_at: "2008-04-14 12:07:46"> 92
  • 94. More… 94
  • 96. In the beginning, there was the URI. 96
  • 98. http://script.aculo.us/thomas/index.html this is an actual file, in the thomas directory 98
  • 100. http://www.merriam-webster.com/cgi-bin/mwwod.pl "cgi-bin" was a special location for executable files 100
  • 102. "search" is probably not a filename http://gilesbowkett.blogspot.com/search?updated- max=2008-04-08T09%3A25%3A00-07%3A00&max-results=7 wtf? 102
  • 103. http://www.amazon.de/gp/ product/B0000262LH/ ref=s9subs_c3_img1- rfc_p_19_32_31_9_9? pf_rd_m=A1IDDPBG1NC5TQ&pf_rd_ s=center-2&pf_rd_r=1FMGVYJN44 H7WQD9YCR9&pf_rd_t=101&pf_rd_ p=139524591&pf_rd_i=301128 103
  • 104. http://www.amazon.de/gp/ product/B0000262LH/ ref=s9subs_c3_img1- rfc_p_19_32_31_9_9? pf_rd_m=A1IDDPBG1NC5TQ&pf_rd_ s=center-2&pf_rd_r=1FMGVYJN44 H7WQD9YCR9&pf_rd_t=101&pf_rd_ p=139524591&pf_rd_i=301128 yeah, right. 104
  • 106. http://www.amazon.de/cd/attwenger/dog wouldn't this be nicer? 106
  • 107. URIs were supposed to be about resources—aka objects—not some frankenstein combination of actual file paths and query strings to dictate which thing, and what to do with it 107
  • 108. REST (Representational State Transfer) follows this definition and identifies resources uniformly 108
  • 109. Web applications usually consist of objects 109
  • 110. (like, say, blog posts) 110
  • 111. What's a blog post? It's an entry in a database. Consists of title, body, date, whether it's public or not, and other data. 111
  • 112. HTML representation (read) http://0.0.0.0:3000/posts/1 112
  • 113. XML representation (read) <?xml version=“1.0” encoding=“UTF-8”?> <post> <body>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</body> <created-at type=“datetime”>2008-04-14T12:07:46+02:00</created-at> <id type=“integer”>1</id> <published type=“boolean”>true</published> <title>Another title</title> <updated-at type=“datetime”>2008-04-15T11:30:50+02:00</updated-at> <version type=“integer”>2</version> </post> http://0.0.0.0:3000/posts/1.xml 113
  • 114. def show @post = Post.find(params[:id]) respond_to do |format| format.html format.xml { render :xml => @post } end end 114
  • 115. database entry gets converted into… def show @post = Post.find(params[:id]) respond_to do |format| format.html format.xml { render :xml => @post } end end …REST representations 115
  • 116. RESTful operations Create Read Update Delete 116
  • 117. Read 117
  • 118. HTTP verbs 118
  • 119. In HTTP each request is preceeded by a request type, or "verb". 119
  • 120. Normal page loads use the "GET" verb, while web forms use "POST". 120
  • 121. HTTP knows more verbs, most importantly "PUT", "DELETE" and "HEAD". 121
  • 122. REST operation HTTP verb Create POST Read GET Update PUT Delete DELETE 122
  • 123. operation (read) GET http://0.0.0.0:3000/posts/1 resource identifier 123
  • 124. operation (delete) DELETE http://0.0.0.0:3000/posts/1 resource identifier (same as for read) 124
  • 125. REST allows for consistent, guessable URIs 125
  • 126. The best thing is that Rails does all this completely automatically 126
  • 128. 100s of plugins available 128
  • 131. >> post = Post.find(:first) => #<Post id: 1, title: "Another title", body: "Lorem ipsum dolor sit amet, consectetur adipisicing...", published: true, created_at: "2008-04-14 12:07:46", updated_at: "2008-04-15 11:30:50", version: 2> >> post.versions => [#<Post::Version id: 1, post_id: 1, version: 1, title: "This is a test post", body: "Lorem ipsum dolor sit amet, consectetur adipisicing...", published: true, created_at: "2008-04-14 12:07:46", updated_at: "2008-04-15 11:29:44">, #<Post::Version id: 2, post_id: 1, version: 2, title: "Another title", body: "Lorem ipsum dolor sit amet, consectetur adipisicing...", published: true, created_at: "2008-04-14 12:07:46", updated_at: "2008-04-15 11:30:50">] >> post.versions.size => 2 title changed between versions 131
  • 132. db/migrate/002_add_post_versions.rb class AddPostVersions < ActiveRecord::Migration require_dependency 'post' def self.up Post.create_versioned_table end def self.down Post.drop_versioned_table end end 132
  • 133. one line of code class Post < ActiveRecord::Base acts_as_versioned validates_presence_of :title validates_length_of :body, :minimum=>10 end 133
  • 134. Demo Plugins 134
  • 135. Ajax 135
  • 136. "Ajax" allows to update parts of the page, without a complete reload 136
  • 137. . Rails includes the -------- and prototype . and JavaScript frameworks 137
  • 140. Testing 140
  • 141. class PostsControllerTest < ActionController::TestCase def test_should_get_index get :index assert_response :success assert_not_nil assigns(:posts) end end 141
  • 143. super-easy way to really find out def index what happens in your code @posts = Post.find(:all) debugger respond_to do |format| format.html format.xml { render :xml => @posts } end end 143
  • 146. IDEs and Editors like Textmate 146
  • 147. Web services like github 147
  • 148. Web- and Application Server software 148
  • 149. Conferences 149
  • 150. tbiyonysHhoips ReilccoertdshReegluae Am y Actuibven Ra s h a e t id aR yo note: has_many and has_one work identically except for the number of relationships. both go on the table/model that does not feature the foreign key belongs to has many create table customers ( create table companies ( id int auto_increment primary key, id int auto_increment primary key, name varchar(75), name varchar(75) company_id int ) ) customers belongs_to :company company_id companies has_many :customers id has and belongs to many create table articles ( create table authors ( create table articles_authors ( id int auto_increment primary key, id int auto_increment primary key, author_id int, name varchar(75), name varchar(75) article_id int body text ) ) ) articles authors has_and_belongs_to_many :authors has_and_belongs_to_many :articles id articles_authors id article_id author_id note: the articles_authors table is implicit due to the two models that call habtm, and it does not require a model of its own. when making implicit mapping tables such as this, it must be named tablea_tableb where a is first in alphabetical order. © 2005 Amy Hoy / amy@infocookie.com / www.slash7.com MIT License — see http://www.slash7.org/cheats/license.html Podcasts, Books and other Publications 150
  • 152. . prototype . "Spinoffs" 152
  • 153. Q+A 153