SlideShare a Scribd company logo
1 of 135
Ruby on Rails
   Supinfo 2011
A propos

• Martin Catty, fondateur de Synbioz
• Rubyiste depuis 2006

    _fuse       mcatty@synbioz.com
Ruby avant Rails

• Ne partez pas sans vos bagages !
• Rails a aidé à l’essor de Ruby
• Mais pas de framework sans langage
Ruby
     On ne va pas (ou peu) parler de:

        I/O        Test
                                     VM
                          Thread
Implémentations
                  Debugger         Garbage
   Proc / lambda            Exceptions
              Réseau
L’Histoire


• Créé par Yukihiro Matsumoto (Matz)
• Release publique en 2005
Un langage

• Plus objet que python
• Plus puissant que perl
• Fun
Les versions

• Stable actuelle: 1.9.2
• 1.8.7 dans la branche 1.8
• 1.8.7 (p250) fonctionne avec Rails 2 et 3
• < 1.8.7 = Rails 2
• > 1.8.7 = Rails 3
Le fameux hello world
  Java          Ruby
Le fameux hello world
                Java                           Ruby


class Hello {
   public static void main(String [] args) {
         system.out.println(‘Hello’);
      }
}
Le fameux hello world
                Java                                          Ruby


class Hello {
   public static void main(String [] args) {
         system.out.println(‘Hello’);          puts ‘Hello’
      }
}
Le fameux hello world
                Java                                          Ruby


class Hello {
   public static void main(String [] args) {
         system.out.println(‘Hello’);          puts ‘Hello’
      }
}




                                       </troll>
Tout est objet
Tout est objet
  2.times { puts "Bonjour Supinfo." }

=> Bonjour Supinfo
=> Bonjour Supinfo
Tout est objet
  2.times { puts "Bonjour Supinfo." }     3.upto(5) { |i| puts i }

=> Bonjour Supinfo                      => 3
=> Bonjour Supinfo                      => 4
                                        => 5
Tout est objet
  2.times { puts "Bonjour Supinfo." }     3.upto(5) { |i| puts i }

=> Bonjour Supinfo                      => 3
=> Bonjour Supinfo                      => 4
                                        => 5


  p 1.zero?


=> false
Tout est objet
  2.times { puts "Bonjour Supinfo." }     3.upto(5) { |i| puts i }

=> Bonjour Supinfo                      => 3
=> Bonjour Supinfo                      => 4
                                        => 5


  p 1.zero?                               39 + 3


=> false                                => 39.+(3)
Les variables
class A
   MAX = 42
                           A.new("a")
   @@instances = 0         A.new("b")
   def initialize(name)
      @name = name         A.new("c")
      @@instances += 1
   end                     A.new("d")
  def self.instances
                           A.new("e")
     @@instances
  end
end                        p A.instances #=> 5
Itérations
Itérations
a = 1..9
for i in a
   puts i
end
Itérations
 a = 1..9
 for i in a
    puts i
 end
=> 1…9
Itérations
 a = 1..9
 for i in a
    puts i        ou
 end
=> 1…9
Itérations
 a = 1..9
 for i in a            a = 1..9
    puts i        ou   a.each { |i| puts i }
 end
=> 1…9
Itérations
 a = 1..9
 for i in a             a = 1..9
    puts i        ou    a.each { |i| puts i }
 end
=> 1…9                 => 1…9
Itérations
 a = 1..9
 for i in a                     a = 1..9
    puts i                ou    a.each { |i| puts i }
 end
=> 1…9                         => 1…9

 i=0
 loop do
   i += 1
   puts i
   break if 10 == i
 end
Itérations
 a = 1..9
 for i in a                     a = 1..9
    puts i                ou    a.each { |i| puts i }
 end
=> 1…9                         => 1…9

 i=0
 loop do
   i += 1
   puts i
   break if 10 == i
 end

=> 1…9
Itérations
 a = 1..9
 for i in a                     a = 1..9
    puts i                ou    a.each { |i| puts i }
 end
=> 1…9                         => 1…9

 i=0
 loop do
   i += 1                      1.upto(10) do |i|
   puts i                       next if i.odd? # pas d'impair en ruby
   break if 10 == i             puts i
 end                           end

=> 1…9
Itérations
 a = 1..9
 for i in a                        a = 1..9
    puts i                ou       a.each { |i| puts i }
 end
=> 1…9                          => 1…9

 i=0
 loop do
   i += 1                        1.upto(10) do |i|
   puts i                         next if i.odd? # pas d'impair en ruby
   break if 10 == i               puts i
 end                             end

=> 1…9                         => 2, 4, 6, 8, 10
Itérations
 a = 1..9
 for i in a                        a = 1..9
    puts i                ou       a.each { |i| puts i }
 end
=> 1…9                          => 1…9

 i=0
 loop do
   i += 1                        1.upto(10) do |i|
   puts i                         next if i.odd? # pas d'impair en ruby
   break if 10 == i               puts i
 end                             end

=> 1…9                         => 2, 4, 6, 8, 10

 1.upto(2) do |i|
   v = rand(2)
   retry if v.zero?
 end
Conditions
Conditions
if index == 1
else            puts ‘0’ if index.zero?   puts ‘not 0’ unless index.zero?
end
Conditions
if index == 1
else                       puts ‘0’ if index.zero?     puts ‘not 0’ unless index.zero?
end


def what_is_it?(a)
 case a                                              what_is_it?(1)
 when 1..2                                           # 1 or 2
  puts "1 or 2"                                      what_is_it?(2)
 when 3                                              # 1 or 2
  puts "3"                                           what_is_it?(3)
 when /4.*/ # Regexp                                 #3
  puts "something starting with 4."                  what_is_it?("4004")
 when "foo"                                          # something starting with 4.
  puts "foo"                                         what_is_it?("foo")
 else                                                # foo
  puts "I don't know."                               what_is_it?(5)
 end                                                 # Don't know.
end
Tableaux 1/2
1
Tableaux 1/2
1   lost = [8, 15, 16, 23]
    lost << 42 # push
    lost.unshift(4)
    # [4, 8, 15, 16, 23, 42]
Tableaux 1/2
1   lost = [8, 15, 16, 23]
    lost << 42 # push
    lost.unshift(4)
    # [4, 8, 15, 16, 23, 42]
Tableaux 1/2
1   lost = [8, 15, 16, 23]        lost.at(0)
    lost << 42 # push             #4
    lost.unshift(4)               lost[-1]
    # [4, 8, 15, 16, 23, 42]      # 42
Tableaux 1/2
1   lost = [8, 15, 16, 23]        lost.at(0)
    lost << 42 # push             #4
    lost.unshift(4)               lost[-1]
    # [4, 8, 15, 16, 23, 42]      # 42
Tableaux 1/2
1   lost = [8, 15, 16, 23]        lost.at(0)   lost << nil << nil
    lost << 42 # push             #4
    lost.unshift(4)               lost[-1]     # [4, 8, 15, 16, 23, 42,
    # [4, 8, 15, 16, 23, 42]      # 42         nil, nil]
Tableaux 1/2
1   lost = [8, 15, 16, 23]        lost.at(0)   lost << nil << nil
    lost << 42 # push             #4
    lost.unshift(4)               lost[-1]     # [4, 8, 15, 16, 23, 42,
    # [4, 8, 15, 16, 23, 42]      # 42         nil, nil]
Tableaux 1/2
1   lost = [8, 15, 16, 23]        lost.at(0)   lost << nil << nil
    lost << 42 # push             #4
    lost.unshift(4)               lost[-1]     # [4, 8, 15, 16, 23, 42,
    # [4, 8, 15, 16, 23, 42]      # 42         nil, nil]



                                               lost.compact!

                                               # [4, 8, 15, 16, 23, 42]
Tableaux 1/2
1   lost = [8, 15, 16, 23]        lost.at(0)   lost << nil << nil
    lost << 42 # push             #4
    lost.unshift(4)               lost[-1]     # [4, 8, 15, 16, 23, 42,
    # [4, 8, 15, 16, 23, 42]      # 42         nil, nil]



                                               lost.compact!

                                               # [4, 8, 15, 16, 23, 42]
Tableaux 1/2
1   lost = [8, 15, 16, 23]        lost.at(0)                 lost << nil << nil
    lost << 42 # push             #4
    lost.unshift(4)               lost[-1]                   # [4, 8, 15, 16, 23, 42,
    # [4, 8, 15, 16, 23, 42]      # 42                       nil, nil]


                                  lost << [4, 8]
                                                             lost.compact!
                                  # [4, 8, 15, 16, 23, 42,
                                                             # [4, 8, 15, 16, 23, 42]
                                  [4, 8]]
Tableaux 1/2
1   lost = [8, 15, 16, 23]        lost.at(0)                 lost << nil << nil
    lost << 42 # push             #4
    lost.unshift(4)               lost[-1]                   # [4, 8, 15, 16, 23, 42,
    # [4, 8, 15, 16, 23, 42]      # 42                       nil, nil]


                                  lost << [4, 8]
                                                             lost.compact!
                                  # [4, 8, 15, 16, 23, 42,
                                                             # [4, 8, 15, 16, 23, 42]
                                  [4, 8]]
Tableaux 1/2
1   lost = [8, 15, 16, 23]        lost.at(0)                 lost << nil << nil
    lost << 42 # push             #4
    lost.unshift(4)               lost[-1]                   # [4, 8, 15, 16, 23, 42,
    # [4, 8, 15, 16, 23, 42]      # 42                       nil, nil]



    lost.flatten!.uniq!            lost << [4, 8]
                                                             lost.compact!

    # [4, 8, 15, 16, 23, 42]      # [4, 8, 15, 16, 23, 42,
                                                             # [4, 8, 15, 16, 23, 42]
                                  [4, 8]]
Tableaux 1/2
1   lost = [8, 15, 16, 23]        lost.at(0)                 lost << nil << nil
    lost << 42 # push             #4
    lost.unshift(4)               lost[-1]                   # [4, 8, 15, 16, 23, 42,
    # [4, 8, 15, 16, 23, 42]      # 42                       nil, nil]



    lost.flatten!.uniq!            lost << [4, 8]
                                                             lost.compact!

    # [4, 8, 15, 16, 23, 42]      # [4, 8, 15, 16, 23, 42,
                                                             # [4, 8, 15, 16, 23, 42]
                                  [4, 8]]



    lost.index(23)

    #4
Tableaux 1/2
1   lost = [8, 15, 16, 23]        lost.at(0)                  lost << nil << nil
    lost << 42 # push             #4
    lost.unshift(4)               lost[-1]                    # [4, 8, 15, 16, 23, 42,
    # [4, 8, 15, 16, 23, 42]      # 42                        nil, nil]



    lost.flatten!.uniq!            lost << [4, 8]
                                                              lost.compact!

    # [4, 8, 15, 16, 23, 42]      # [4, 8, 15, 16, 23, 42,
                                                              # [4, 8, 15, 16, 23, 42]
                                  [4, 8]]


                                  lost.shuffle
    lost.index(23)
                                  # [16, 23, 42, 4, 15, 8]
                                  [5, 3, 7, 39, 1, 15].sort
    #4
                                  # [1, 3, 5, 7, 15, 39]
Tableaux 1/2
1   lost = [8, 15, 16, 23]        lost.at(0)                  lost << nil << nil
    lost << 42 # push             #4
    lost.unshift(4)               lost[-1]                    # [4, 8, 15, 16, 23, 42,
    # [4, 8, 15, 16, 23, 42]      # 42                        nil, nil]



    lost.flatten!.uniq!            lost << [4, 8]
                                                              lost.compact!

    # [4, 8, 15, 16, 23, 42]      # [4, 8, 15, 16, 23, 42,
                                                              # [4, 8, 15, 16, 23, 42]
                                  [4, 8]]


                                  lost.shuffle
    lost.index(23)
                                  # [16, 23, 42, 4, 15, 8]    ('a'..'z').to_a
                                  [5, 3, 7, 39, 1, 15].sort   ["a", "b", "c", "d"…]
    #4
                                  # [1, 3, 5, 7, 15, 39]
Tableaux 2/2
Tableaux 2/2
double_lost = lost.map { |v| v * 2 }
# => [8, 16, 30, 32, 46, 84]
Tableaux 2/2
                                       # lost: [4, 8, 15, 16, 23, 42]
double_lost = lost.map { |v| v * 2 }
                                       double_lost - lost
# => [8, 16, 30, 32, 46, 84]
                                       # => [30, 32, 46, 84]
Tableaux 2/2
                                       # lost: [4, 8, 15, 16, 23, 42]
double_lost = lost.map { |v| v * 2 }
                                       double_lost - lost
# => [8, 16, 30, 32, 46, 84]
                                       # => [30, 32, 46, 84]




# intersection
double_lost & lost
# [8, 16]
Tableaux 2/2
                                       # lost: [4, 8, 15, 16, 23, 42]
double_lost = lost.map { |v| v * 2 }
                                       double_lost - lost
# => [8, 16, 30, 32, 46, 84]
                                       # => [30, 32, 46, 84]




# intersection                         # jointure
double_lost & lost                     (double_lost | lost).sort
# [8, 16]                              # [4, 8, 15, 16, 23, 30, 32, 42, 46, 84]
String
String
str = "bar"
puts 'foo #{str}'
# => foo #{str}
String
str = "bar"         # Interpolation
puts 'foo #{str}'   puts "foo #{str}"
# => foo #{str}     # => foo bar
String
str = "bar"         # Interpolation
puts 'foo #{str}'   puts "foo #{str}"
# => foo #{str}     # => foo bar



str = "a"
str.succ
# => "b"
String
str = "bar"         # Interpolation
puts 'foo #{str}'   puts "foo #{str}"
# => foo #{str}     # => foo bar



str = "a"           str = "foon"
str.succ            str.chomp
# => "b"            # => "foo"
String
str = "bar"         # Interpolation
puts 'foo #{str}'   puts "foo #{str}"
# => foo #{str}     # => foo bar



str = "a"           str = "foon"
str.succ            str.chomp
# => "b"            # => "foo"



str = "foo"
str.chop
# => "fo"
String
str = "bar"         # Interpolation
puts 'foo #{str}'   puts "foo #{str}"
# => foo #{str}     # => foo bar



str = "a"           str = "foon"
str.succ            str.chomp
# => "b"            # => "foo"



                    "supinfo".capitalize
str = "foo"
                    # => "Supinfo"
str.chop
                    "supinfo".upcase
# => "fo"
                    # => "SUPINFO"
String
str = "bar"         # Interpolation
puts 'foo #{str}'   puts "foo #{str}"
                                           # attention, en 1.8
# => foo #{str}     # => foo bar
                                           str = "éhé"
                                           str.size
                                           # => 5 et non 3
                                           str[0]
str = "a"           str = "foon"
                                           # 195 et non é (code ascii)
str.succ            str.chomp
# => "b"            # => "foo"
                                           # patché dans rails
                                           str.mb_chars[0]
                                           #é
                    "supinfo".capitalize   str.mb_chars.size
str = "foo"                                #3
                    # => "Supinfo"
str.chop
                    "supinfo".upcase
# => "fo"
                    # => "SUPINFO"
Hash
Association clé / valeur
Hash
Association clé / valeur
 h = { :a => 'a', :b => 42, :c => { :d => 'f' } }   h2 = { :a => 'foo' }
                                                    h.merge(h2)
                                                    => {:a=>"foo", :b=>42, :c=>{:d=>"f"}}
Class: les constructeurs
Class: les constructeurs
class A
  def A.new
  end
end

A.new
Class: les constructeurs
class A         class B
  def A.new       def self.new
  end             end
end             end

A.new           B.new
Class: les constructeurs
class A            class B
  def A.new          def self.new
  end                end
end                end

A.new              B.new



class C
  def initialize
  end
end

C.new
Class: les constructeurs
class A            class B
  def A.new          def self.new
  end                end
end                end

A.new              B.new

                   class D
                     # pas de constructeur multiple
class C
                     def initialize; end
  def initialize
  end
                    def initialize(*args)
end
                    end
                   end
C.new
                   D.new # => KO
                   D.new(1) # => OK
Class: les accesseurs
Class: les accesseurs
class Product
   def initialize(name, description, price)
      @name = name
      @description = description
      @price = price
   end

   def name
      @name
   end

   def name=(name)
      @name = name
   end
   …

end
Class: les accesseurs
class Product
   def initialize(name, description, price)
      @name = name
      @description = description              class Product
      @price = price                             attr_accessor :name
   end                                           attr_reader: description
                                                 attr_writer :price
   def name
      @name                                     def initialize(name, description, price)
   end                                             @name = name
                                                   @description = description
   def name=(name)                                 @price = price
      @name = name                              end
   end                                        end
   …

end
Class: portée & héritage
Class: portée & héritage
class Animal
  def initialize
   puts "Born to be alive."
  end

 protected
 def breathe?
  puts "inhale, exhale"
  true
 end

 private
 def speak; end
end

# Animal.new.speak
# => fail with private method `speak'
Class: portée & héritage
class Animal                            class Dog < Animal
  def initialize                          def alive?
   puts "Born to be alive."                puts "I'm alive" if breathe?
  end                                     end

 protected                               def speak
 def breathe?                             puts "woff."
  puts "inhale, exhale"                  end
  true                                  end
 end
                                        snoopy = Dog.new
 private                                # Born to be alive.
 def speak; end                         snoopy.speak
end                                     # woff.
                                        snoopy.alive?
# Animal.new.speak                      # inhale, exhale
# => fail with private method `speak'   # I'm alive
Class: étendre
Class: étendre

# Etendre un objet
str = "foo"

class << str
  def blank?
   self !~ /S/
  end
end

str.blank?
# => false
Class: étendre

# Etendre un objet           # Etendre une classe
str = "foo"                  class String
                               def blank?
class << str                    self !~ /S/
  def blank?                   end
   self !~ /S/              end
  end
end                          "     ".blank?
                             # => true
str.blank?                   "foo".blank?
# => false                   # => false
Class: ce qui n’existe pas

• Pas d’héritage multiple
• Basé sur les mixins
• Pas d’interface
• Pas de classe abstraite native
Les outils
irb : votre shell ruby
 [17:59:57] fuse@h [~]$ irb
 ruby-1.8.7-p302 :001 > puts ‘foo’
 foo
  => nil
 ruby-1.8.7-p302 :002 > 21 * 2
  => 42
 ruby-1.8.7-p302 :008 > String.methods.sort
  => ["<", "<=", "<=>", "==", "===", "=~", ">", …]



rvm : gérer plusieurs versions de ruby
Documentation
• http://www.ruby-doc.org/
• http://www.ruby-lang.org/
• http://apidock.com/ruby
• Le pickAxe: LA référence
• http://tryruby.org/
• http://groups.google.com/group/rubyfr-
  public
Rails
On ne va pas (ou peu) parler de:

           Copieurs
  Test                   I18n
           Rake
 Cache                  Rails 3
         ActionMailer
                        Déploiement
 ActiveSupport
L’Histoire

• Créé par DHH (David Heinemeier Hansson)
• Version 1 en décembre 2005
• Pragmatique dès le début: basecamp
Rails en entreprise

• Plus un jouet
• Présent en entreprise, grandes et petites
• Opportunités en temps que développeur
Les versions

• Stable actuelle: 3.0.7
 • Rails 3 issue du merge avec merb (08/10)
 • Framework agnostic
• Stable actuelle: 2.3.11
 • La plus rencontrée en entreprise
Des conventions
Quelques noms barbares:


• Convention over configuration
• DRY
• MVC
Convention over
      configuration
• Votre passion est de customiser Tomcat ?
  Désolé !
• 0 conf pour commencer à développer
 • Serveur web embarqué
 • BDD embarquée
Don’t repeat yourself

• - de code = - de bug
• - de code = - de maintenance
• - de code = + de temps
Modèle - Vue - Contrôleur

     Modèle     Contrôleur      Vue



    Métier    Fonctionnel    Affichage
Rails en vrai


• Pas de hello world, c’est trop simple…
• La classique liste de produits plutôt.
Créons notre application

 $ rails app



3 environnements
class Product < ActiveRecord::Base   Modèle
end
                                     app/models/product.rb
class Product < ActiveRecord::Base                 Modèle
end
                                                   app/models/product.rb

class ProductsController < ApplicationController   Contrôleur
    def index
       @products = Product.all                     app/controllers/
    end
 end                                               products_controller.rb
class Product < ActiveRecord::Base                 Modèle
end
                                                   app/models/product.rb

class ProductsController < ApplicationController   Contrôleur
    def index
       @products = Product.all                     app/controllers/
    end
 end                                               products_controller.rb

 <html><body>                                      Vue
 <% for product in @products %>
 <p><%= product.name %></p>                        app/views/products/
 <% end %>
 </body></html>                                    index.html.erb
class Product < ActiveRecord::Base                 Modèle
end
                                                   app/models/product.rb

class ProductsController < ApplicationController   Contrôleur
    def index
       @products = Product.all                     app/controllers/
    end
 end                                               products_controller.rb

 <html><body>                                      Vue
 <% for product in @products %>
 <p><%= product.name %></p>                        app/views/products/
 <% end %>
 </body></html>                                    index.html.erb
Que vient on de faire ?

• Créer une classe product qui hérite de AR::Base
  Model

• Créer un contrôleur qui gère les actions (ex: index)
  Contrôleur

• Créer des vues pour afficher la liste et les formulaires
   Vue
Le modèle avec
      Active Record
• S’interface avec la base de données
• SQLite par défaut
• Plus de SQL manuel
• Plus de risque d’injections
Créer un modèle
Créer un modèle
$ ruby script/generate model Product name:string description:text price:float
category_id:integer
Créer un modèle
$ ruby script/generate model Product name:string description:text price:float
category_id:integer


  class CreateProducts < ActiveRecord::Migration
    def self.up
     create_table :products do |t|                     db/migrate/
       t.string :name
       t.text :description
                                                       20110322113407_
       t.float :price                                   create_products.rb
       t.integer :category_id

     t.timestamps
    end                                                 rake db:migrate
   end

   def self.down
    drop_table :products
   end
  end
Configuration & log
Configuration & log
config/database.yml
    development:
     adapter: sqlite3
     database: db/        Adaptateurs pour MySQL,
    development.sqlite3
     pool: 5
                          Postgresql, oracle…
     timeout: 5000
Configuration & log
config/database.yml
    development:
     adapter: sqlite3
     database: db/            Adaptateurs pour MySQL,
    development.sqlite3
     pool: 5
                              Postgresql, oracle…
     timeout: 5000

Dans le contrôleur                log/development.log

                                      Product Load (0.3ms)
    @products = Product.all
                                      SELECT * FROM "products"
Créer un produit
Créer un produit
c = Category.first
Product.create({
   :name => "Ruby 'on Rails", # injection SQL
   :description => "First book on RoR",
   :price => 10.0,
   :category => c })
Créer un produit
   c = Category.first
   Product.create({
      :name => "Ruby 'on Rails", # injection SQL
      :description => "First book on RoR",
      :price => 10.0,
      :category => c })


log/development.log
  Product Create (0.8ms) INSERT INTO "products"
("name", "price", "created_at", "updated_at", "category_id", "description")
VALUES
('Ruby ''on Rails', 10.0, '2011-03-22 18:13:07', '2011-03-22 18:13:07', 1, 'First
book on RoR')
Encore trop complexe ?
Besoin d’un outil qui gère le CRUD en 1 commande:

  • Create
  • Read
  • Update
  • Delete
Scaffold
Scaffold
Plus qu’une migration

• Et vous pouvez:
 • Créer des produits (Create)
 • Les lister et afficher (Read)
 • Les mettre à jour (Update)
 • Et les supprimer (Delete)
En images
Les relations
Les relations
 class Category < ActiveRecord::Base
   has_many :products
                                       Une catégorie possède
end                                    n produits
Les relations
 class Category < ActiveRecord::Base
   has_many :products
                                       Une catégorie possède
end                                    n produits

 class Product < ActiveRecord::Base    Un produit appartient à
  belongs_to :category
end                                    une catégorie
Les relations
 class Category < ActiveRecord::Base
   has_many :products
                                       Une catégorie possède
end                                    n produits

 class Product < ActiveRecord::Base    Un produit appartient à
  belongs_to :category
end                                    une catégorie
ou
 class Product < ActiveRecord::Base
                                       Une catégorie possède
  has_and_belongs_to_many :category    n produits et un
end
                                       produit n catégories
Les finder
Les finder
Product.find(:all, :conditions => { :price => 18 })
Product.find(:first)
Product.find(:last)
Les finder
 Product.find(:all, :conditions => { :price => 18 })
 Product.find(:first)
 Product.find(:last)


Plusieurs finder dynamiques:

 Product.find_by_name(‘rails’)
 Product.find_all_by_name(‘rails’)
 Product.find_by_name_and_price(‘book’, 18)
Les finder
 Product.find(:all, :conditions => { :price => 18 })
 Product.find(:first)
 Product.find(:last)


Plusieurs finder dynamiques:

 Product.find_by_name(‘rails’)
 Product.find_all_by_name(‘rails’)
 Product.find_by_name_and_price(‘book’, 18)



Jointure:
 Product.find(:all, :joins => :category,
 :conditions => { :categories => { :name => "books" }})
Les scope
Les scope
class Product < ActiveRecord::Base
     named_scope :recent, lambda { { :conditions => ["created_at > ?", 5.days.ago] } }
     named_scope :limit, lambda { |n| { :limit => n } }
     named_scope :ordered_by_name, { :order => "NAME ASC" }
   end
Les scope
 class Product < ActiveRecord::Base
      named_scope :recent, lambda { { :conditions => ["created_at > ?", 5.days.ago] } }
      named_scope :limit, lambda { |n| { :limit => n } }
      named_scope :ordered_by_name, { :order => "NAME ASC" }
    end


Invoquer les scope, de façon chaînable

 Product.recent.ordered_by_name.limit(2)
 Product Load (0.3ms) SELECT * FROM "products" WHERE (created_at > '2011-03-17
 21:08:24') ORDER BY NAME ASC LIMIT 2
Les validations
  class Product < ActiveRecord::Base
     belongs_to :category
     validates_presence_of :name, :category_id
     validates_numericality_of :price



et bien d’autres:

validates_confirmation_of
validates_exclusion_of
validates_format_of
validates_inclusion_of
validates_length_of
…
Le contrôleur avec
    ActionController
• L’interface entre le modèle et la vue
• Association automatique méthode / vue
• @variable directement disponible dans la
  vue
• Possibilité de filtrer des actions
Le routeur
config/routes.rb
ActionController::Routing::Routes.draw do |map|
  # RESTful /categories/1/products/1/
  map.resources :categories do |category|
     category.resources :products
  end
  # route nommée
  map.purchase 'products/:id/purchase', :controller => 'catalog', :action => 'purchase'
  # namespace
  map.namespace :admin do |admin|
     # /admin/products
     admin.resource :products
  end
  # route par défaut
  map.root :controller => 'products'
end
Les routes
 rake routes
   categories GET        /categories(.:format)        {:controller=>"categories", :action=>"index"}
              POST /categories(.:format)               {:controller=>"categories", :action=>"create"}
 new_category GET /categories/new(.:format)           {:controller=>"categories", :action=>"new"}
edit_category GET /categories/:id/edit(.:format) {:controller=>"categories", :action=>"edit"}
    category GET        /categories/:id(.:format)    {:controller=>"categories", :action=>"show"}
          PUT          /categories/:id(.:format)      {:controller=>"categories", :action=>"update"}
          DELETE      /categories/:id(.:format)      {:controller=>"categories", :action=>"destroy"}
    products GET     /products(.:format)             {:controller=>"products", :action=>"index"}
          POST       /products(.:format)             {:controller=>"products", :action=>"create"}
  new_product GET /products/new(.:format)            {:controller=>"products", :action=>"new"}
 edit_product GET /products/:id/edit(.:format)       {:controller=>"products", :action=>"edit"}
     product GET     /products/:id(.:format)         {:controller=>"products", :action=>"show"}
          PUT       /products/:id(.:format)           {:controller=>"products", :action=>"update"}
          DELETE /products/:id(.:format)             {:controller=>"products", :action=>"destroy"}
                  /:controller/:action/:id
                  /:controller/:action/:id(.:format)
       root       /                                   {:controller=>"products", :action=>"index"}
Les contrôleurs
class ProductsController < ApplicationController
   before_filter :authenticate, :only => :index

  def index
    @products = Product.all #disponible dans la vue

     respond_to do |format|
        # GET /products
        format.html # index.html.erb
        # GET /products.xml
        format.xml { render :xml => @products }
     end
  end
  private
  def authenticate
     # do some stuff
  end
end
La vue avec
         ActionView
• Les vues : pas forcément du HTML
• Layout
• Partials
• Helpers
Les types de vues
i18n des vues
 app/views/products/index.fr.html.erb
 app/views/products/index.es.html.erb   Rails >= 2.3
Les types de vues
i18n des vues
 app/views/products/index.fr.html.erb
 app/views/products/index.es.html.erb   Rails >= 2.3

Différents formats
 app/views/products/index.iphone.erb
 app/views/products/index.xml.erb
Le layout
Squelette de base   app/views/layouts/application.html.erb



Modifiable depuis    <!DOCTYPE…>
                    <html>
le contrôleur       <body>
                    <%= yield %>
                    </body>
                    </html>
Les partials
Des morceaux de vue

 <!DOCTYPE…>
 <html>
 <body>                                         app/views/products/_sidebar.html.erb
 <%= render :partial => ‘products/sidebar’ %>
 <%= yield %>
 </body>
 </html>
Exemple de vue: liste
<h1>Listing categories</h1>

<table>
 <tr>
  <th>Name</th>
 </tr>

<% @categories.each do |category| %>
 <tr>
   <td><%=h truncate(category.name, :size => 10) %></td>
   <td><%= link_to 'Show', category %></td>
   <td><%= link_to 'Edit', edit_category_path(category) %></td>
   <td><%= link_to 'Destroy', category, :confirm => 'Are you sure?', :method
=> :delete %></td>
 </tr>
<% end %>
</table>

<br />

<%= link_to 'New category', new_category_path %>
Exemple de vue: édition
<% form_for(@product) do |f| %>
 <%= f.error_messages %>

 <p>
  <%= f.label :name %><br />
  <%= f.text_field :name %>
 </p><p>
  <%= f.label :description %><br />
  <%= f.text_area :description %>
 </p><p>
  <%= f.label :available %><br />
  <%= f.check_box :available %>
 </p><p>
  <%= f.label :category_id %><br />
  <%= f.select :category_id, (Category.all.map do |c| [c.name, c.id] end) %>
 </p><p>
  <%= f.submit 'Update' %>
 </p>
<% end %>

<%= link_to 'Show', @product %> |
<%= link_to 'Back', products_path %>
Autour de Rails

•   Communauté active     config/environment.rb
•   Autour de github       Rails::Initializer.run do |config|
                             config.gem ‘hpricot’

•
                           end
    Gems
    •   Authentification
    •   Pagination
    •   …
Documentation

• http://www.rubyonrails.org/
• http://guides.rubyonrails.org/
• http://apidock.com/rails
• http://railsforzombies.org/
• http://groups.google.com/group/railsfrance
Merci, c’est à vous !


• Des questions ?


    _fuse      mcatty@synbioz.com

More Related Content

What's hot

Python Functions (PyAtl Beginners Night)
Python Functions (PyAtl Beginners Night)Python Functions (PyAtl Beginners Night)
Python Functions (PyAtl Beginners Night)Rick Copeland
 
Functions in python
Functions in pythonFunctions in python
Functions in pythonIlian Iliev
 
13 recursion-120712074623-phpapp02
13 recursion-120712074623-phpapp0213 recursion-120712074623-phpapp02
13 recursion-120712074623-phpapp02Abdul Samee
 
Kotlin Collections
Kotlin CollectionsKotlin Collections
Kotlin CollectionsHalil Özcan
 
Functional programming in ruby
Functional programming in rubyFunctional programming in ruby
Functional programming in rubyKoen Handekyn
 
Introduction to Erlang
Introduction to ErlangIntroduction to Erlang
Introduction to ErlangGabriele Lana
 
Exact Real Arithmetic for Tcl
Exact Real Arithmetic for TclExact Real Arithmetic for Tcl
Exact Real Arithmetic for Tclke9tv
 
Design Pattern Observations
Design Pattern ObservationsDesign Pattern Observations
Design Pattern ObservationsDmitri Nesteruk
 
Intro To Erlang
Intro To ErlangIntro To Erlang
Intro To Erlangasceth
 
learn you some erlang - chap0 to chap2
learn you some erlang - chap0 to chap2learn you some erlang - chap0 to chap2
learn you some erlang - chap0 to chap2경미 김
 
A Language Designer’s Workbench. A one-stop shop for implementation and verif...
A Language Designer’s Workbench. A one-stop shop for implementation and verif...A Language Designer’s Workbench. A one-stop shop for implementation and verif...
A Language Designer’s Workbench. A one-stop shop for implementation and verif...Eelco Visser
 
Scala for ruby programmers
Scala for ruby programmersScala for ruby programmers
Scala for ruby programmerstymon Tobolski
 
Dynamic Semantics Specification and Interpreter Generation
Dynamic Semantics Specification and Interpreter GenerationDynamic Semantics Specification and Interpreter Generation
Dynamic Semantics Specification and Interpreter GenerationEelco Visser
 
Are we ready to Go?
Are we ready to Go?Are we ready to Go?
Are we ready to Go?Adam Dudczak
 

What's hot (20)

Pooya Khaloo Presentation on IWMC 2015
Pooya Khaloo Presentation on IWMC 2015Pooya Khaloo Presentation on IWMC 2015
Pooya Khaloo Presentation on IWMC 2015
 
Erlang
ErlangErlang
Erlang
 
Python Functions (PyAtl Beginners Night)
Python Functions (PyAtl Beginners Night)Python Functions (PyAtl Beginners Night)
Python Functions (PyAtl Beginners Night)
 
Python
PythonPython
Python
 
Functions in python
Functions in pythonFunctions in python
Functions in python
 
13 recursion-120712074623-phpapp02
13 recursion-120712074623-phpapp0213 recursion-120712074623-phpapp02
13 recursion-120712074623-phpapp02
 
Kotlin Collections
Kotlin CollectionsKotlin Collections
Kotlin Collections
 
Functional programming in ruby
Functional programming in rubyFunctional programming in ruby
Functional programming in ruby
 
Introduction to Erlang
Introduction to ErlangIntroduction to Erlang
Introduction to Erlang
 
Introduction to Erlang
Introduction to ErlangIntroduction to Erlang
Introduction to Erlang
 
Exact Real Arithmetic for Tcl
Exact Real Arithmetic for TclExact Real Arithmetic for Tcl
Exact Real Arithmetic for Tcl
 
Design Pattern Observations
Design Pattern ObservationsDesign Pattern Observations
Design Pattern Observations
 
Intro To Erlang
Intro To ErlangIntro To Erlang
Intro To Erlang
 
Hammurabi
HammurabiHammurabi
Hammurabi
 
learn you some erlang - chap0 to chap2
learn you some erlang - chap0 to chap2learn you some erlang - chap0 to chap2
learn you some erlang - chap0 to chap2
 
A Language Designer’s Workbench. A one-stop shop for implementation and verif...
A Language Designer’s Workbench. A one-stop shop for implementation and verif...A Language Designer’s Workbench. A one-stop shop for implementation and verif...
A Language Designer’s Workbench. A one-stop shop for implementation and verif...
 
Go Java, Go!
Go Java, Go!Go Java, Go!
Go Java, Go!
 
Scala for ruby programmers
Scala for ruby programmersScala for ruby programmers
Scala for ruby programmers
 
Dynamic Semantics Specification and Interpreter Generation
Dynamic Semantics Specification and Interpreter GenerationDynamic Semantics Specification and Interpreter Generation
Dynamic Semantics Specification and Interpreter Generation
 
Are we ready to Go?
Are we ready to Go?Are we ready to Go?
Are we ready to Go?
 

Viewers also liked

Reuters: Pictures of the Year 2016 (Part 2)
Reuters: Pictures of the Year 2016 (Part 2)Reuters: Pictures of the Year 2016 (Part 2)
Reuters: Pictures of the Year 2016 (Part 2)maditabalnco
 
What's Next in Growth? 2016
What's Next in Growth? 2016What's Next in Growth? 2016
What's Next in Growth? 2016Andrew Chen
 
The Six Highest Performing B2B Blog Post Formats
The Six Highest Performing B2B Blog Post FormatsThe Six Highest Performing B2B Blog Post Formats
The Six Highest Performing B2B Blog Post FormatsBarry Feldman
 
The Outcome Economy
The Outcome EconomyThe Outcome Economy
The Outcome EconomyHelge Tennø
 
32 Ways a Digital Marketing Consultant Can Help Grow Your Business
32 Ways a Digital Marketing Consultant Can Help Grow Your Business32 Ways a Digital Marketing Consultant Can Help Grow Your Business
32 Ways a Digital Marketing Consultant Can Help Grow Your BusinessBarry Feldman
 

Viewers also liked (6)

Lean startup
Lean startupLean startup
Lean startup
 
Reuters: Pictures of the Year 2016 (Part 2)
Reuters: Pictures of the Year 2016 (Part 2)Reuters: Pictures of the Year 2016 (Part 2)
Reuters: Pictures of the Year 2016 (Part 2)
 
What's Next in Growth? 2016
What's Next in Growth? 2016What's Next in Growth? 2016
What's Next in Growth? 2016
 
The Six Highest Performing B2B Blog Post Formats
The Six Highest Performing B2B Blog Post FormatsThe Six Highest Performing B2B Blog Post Formats
The Six Highest Performing B2B Blog Post Formats
 
The Outcome Economy
The Outcome EconomyThe Outcome Economy
The Outcome Economy
 
32 Ways a Digital Marketing Consultant Can Help Grow Your Business
32 Ways a Digital Marketing Consultant Can Help Grow Your Business32 Ways a Digital Marketing Consultant Can Help Grow Your Business
32 Ways a Digital Marketing Consultant Can Help Grow Your Business
 

Similar to Ruby on rails presentation

Ruby: OOP, metaprogramming, blocks, iterators, mix-ins, duck typing. Code style
Ruby: OOP, metaprogramming, blocks, iterators, mix-ins, duck typing. Code styleRuby: OOP, metaprogramming, blocks, iterators, mix-ins, duck typing. Code style
Ruby: OOP, metaprogramming, blocks, iterators, mix-ins, duck typing. Code styleAnton Shemerey
 
Ruby 程式語言綜覽簡介
Ruby 程式語言綜覽簡介Ruby 程式語言綜覽簡介
Ruby 程式語言綜覽簡介Wen-Tien Chang
 
Patterns 200711
Patterns 200711Patterns 200711
Patterns 200711ClarkTony
 
Functional Programming with Groovy
Functional Programming with GroovyFunctional Programming with Groovy
Functional Programming with GroovyArturo Herrero
 
Feel of Kotlin (Berlin JUG 16 Apr 2015)
Feel of Kotlin (Berlin JUG 16 Apr 2015)Feel of Kotlin (Berlin JUG 16 Apr 2015)
Feel of Kotlin (Berlin JUG 16 Apr 2015)intelliyole
 
Dts x dicoding #2 memulai pemrograman kotlin
Dts x dicoding #2 memulai pemrograman kotlinDts x dicoding #2 memulai pemrograman kotlin
Dts x dicoding #2 memulai pemrograman kotlinAhmad Arif Faizin
 
Zhifu Ge - How To Be Weird In Ruby - With Notes
Zhifu Ge - How To Be Weird In Ruby - With NotesZhifu Ge - How To Be Weird In Ruby - With Notes
Zhifu Ge - How To Be Weird In Ruby - With Notesottawaruby
 
Por qué Crystal? Why Crystal Language?
Por qué Crystal? Why Crystal Language?Por qué Crystal? Why Crystal Language?
Por qué Crystal? Why Crystal Language?Crystal Language
 
Threequals - Case Equality in Ruby
Threequals - Case Equality in RubyThreequals - Case Equality in Ruby
Threequals - Case Equality in RubyLouis Scoras
 
Introduction to Kotlin.pptx
Introduction to Kotlin.pptxIntroduction to Kotlin.pptx
Introduction to Kotlin.pptxAzharFauzan9
 
01 Introduction to Kotlin - Programming in Kotlin.pptx
01 Introduction to Kotlin - Programming in Kotlin.pptx01 Introduction to Kotlin - Programming in Kotlin.pptx
01 Introduction to Kotlin - Programming in Kotlin.pptxIvanZawPhyo
 
Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017
Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017 Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017
Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017 Codemotion
 

Similar to Ruby on rails presentation (20)

Ruby: OOP, metaprogramming, blocks, iterators, mix-ins, duck typing. Code style
Ruby: OOP, metaprogramming, blocks, iterators, mix-ins, duck typing. Code styleRuby: OOP, metaprogramming, blocks, iterators, mix-ins, duck typing. Code style
Ruby: OOP, metaprogramming, blocks, iterators, mix-ins, duck typing. Code style
 
CoffeeScript
CoffeeScriptCoffeeScript
CoffeeScript
 
Ruby 程式語言綜覽簡介
Ruby 程式語言綜覽簡介Ruby 程式語言綜覽簡介
Ruby 程式語言綜覽簡介
 
Patterns 200711
Patterns 200711Patterns 200711
Patterns 200711
 
Ruby 101
Ruby 101Ruby 101
Ruby 101
 
Ruby Gotchas
Ruby GotchasRuby Gotchas
Ruby Gotchas
 
Ruby Intro {spection}
Ruby Intro {spection}Ruby Intro {spection}
Ruby Intro {spection}
 
Functional Programming with Groovy
Functional Programming with GroovyFunctional Programming with Groovy
Functional Programming with Groovy
 
An introduction to Ruby
An introduction to RubyAn introduction to Ruby
An introduction to Ruby
 
Feel of Kotlin (Berlin JUG 16 Apr 2015)
Feel of Kotlin (Berlin JUG 16 Apr 2015)Feel of Kotlin (Berlin JUG 16 Apr 2015)
Feel of Kotlin (Berlin JUG 16 Apr 2015)
 
CoffeeScript
CoffeeScriptCoffeeScript
CoffeeScript
 
Dts x dicoding #2 memulai pemrograman kotlin
Dts x dicoding #2 memulai pemrograman kotlinDts x dicoding #2 memulai pemrograman kotlin
Dts x dicoding #2 memulai pemrograman kotlin
 
Zhifu Ge - How To Be Weird In Ruby - With Notes
Zhifu Ge - How To Be Weird In Ruby - With NotesZhifu Ge - How To Be Weird In Ruby - With Notes
Zhifu Ge - How To Be Weird In Ruby - With Notes
 
Por qué Crystal? Why Crystal Language?
Por qué Crystal? Why Crystal Language?Por qué Crystal? Why Crystal Language?
Por qué Crystal? Why Crystal Language?
 
Threequals - Case Equality in Ruby
Threequals - Case Equality in RubyThreequals - Case Equality in Ruby
Threequals - Case Equality in Ruby
 
Ruby
RubyRuby
Ruby
 
Introduction to Kotlin.pptx
Introduction to Kotlin.pptxIntroduction to Kotlin.pptx
Introduction to Kotlin.pptx
 
01 Introduction to Kotlin - Programming in Kotlin.pptx
01 Introduction to Kotlin - Programming in Kotlin.pptx01 Introduction to Kotlin - Programming in Kotlin.pptx
01 Introduction to Kotlin - Programming in Kotlin.pptx
 
Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017
Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017 Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017
Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017
 
Ruby Gotchas
Ruby GotchasRuby Gotchas
Ruby Gotchas
 

Recently uploaded

Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)wesley chun
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
Tech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfTech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfhans926745
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdflior mazor
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAndrey Devyatkin
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProduct Anonymous
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherRemote DBA Services
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUK Journal
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoffsammart93
 

Recently uploaded (20)

Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
Tech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfTech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdf
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 

Ruby on rails presentation

  • 1. Ruby on Rails Supinfo 2011
  • 2. A propos • Martin Catty, fondateur de Synbioz • Rubyiste depuis 2006 _fuse mcatty@synbioz.com
  • 3. Ruby avant Rails • Ne partez pas sans vos bagages ! • Rails a aidé à l’essor de Ruby • Mais pas de framework sans langage
  • 4. Ruby On ne va pas (ou peu) parler de: I/O Test VM Thread Implémentations Debugger Garbage Proc / lambda Exceptions Réseau
  • 5. L’Histoire • Créé par Yukihiro Matsumoto (Matz) • Release publique en 2005
  • 6. Un langage • Plus objet que python • Plus puissant que perl • Fun
  • 7. Les versions • Stable actuelle: 1.9.2 • 1.8.7 dans la branche 1.8 • 1.8.7 (p250) fonctionne avec Rails 2 et 3 • < 1.8.7 = Rails 2 • > 1.8.7 = Rails 3
  • 8. Le fameux hello world Java Ruby
  • 9. Le fameux hello world Java Ruby class Hello { public static void main(String [] args) { system.out.println(‘Hello’); } }
  • 10. Le fameux hello world Java Ruby class Hello { public static void main(String [] args) { system.out.println(‘Hello’); puts ‘Hello’ } }
  • 11. Le fameux hello world Java Ruby class Hello { public static void main(String [] args) { system.out.println(‘Hello’); puts ‘Hello’ } } </troll>
  • 13. Tout est objet 2.times { puts "Bonjour Supinfo." } => Bonjour Supinfo => Bonjour Supinfo
  • 14. Tout est objet 2.times { puts "Bonjour Supinfo." } 3.upto(5) { |i| puts i } => Bonjour Supinfo => 3 => Bonjour Supinfo => 4 => 5
  • 15. Tout est objet 2.times { puts "Bonjour Supinfo." } 3.upto(5) { |i| puts i } => Bonjour Supinfo => 3 => Bonjour Supinfo => 4 => 5 p 1.zero? => false
  • 16. Tout est objet 2.times { puts "Bonjour Supinfo." } 3.upto(5) { |i| puts i } => Bonjour Supinfo => 3 => Bonjour Supinfo => 4 => 5 p 1.zero? 39 + 3 => false => 39.+(3)
  • 17. Les variables class A MAX = 42 A.new("a") @@instances = 0 A.new("b") def initialize(name) @name = name A.new("c") @@instances += 1 end A.new("d") def self.instances A.new("e") @@instances end end p A.instances #=> 5
  • 19. Itérations a = 1..9 for i in a puts i end
  • 20. Itérations a = 1..9 for i in a puts i end => 1…9
  • 21. Itérations a = 1..9 for i in a puts i ou end => 1…9
  • 22. Itérations a = 1..9 for i in a a = 1..9 puts i ou a.each { |i| puts i } end => 1…9
  • 23. Itérations a = 1..9 for i in a a = 1..9 puts i ou a.each { |i| puts i } end => 1…9 => 1…9
  • 24. Itérations a = 1..9 for i in a a = 1..9 puts i ou a.each { |i| puts i } end => 1…9 => 1…9 i=0 loop do i += 1 puts i break if 10 == i end
  • 25. Itérations a = 1..9 for i in a a = 1..9 puts i ou a.each { |i| puts i } end => 1…9 => 1…9 i=0 loop do i += 1 puts i break if 10 == i end => 1…9
  • 26. Itérations a = 1..9 for i in a a = 1..9 puts i ou a.each { |i| puts i } end => 1…9 => 1…9 i=0 loop do i += 1 1.upto(10) do |i| puts i next if i.odd? # pas d'impair en ruby break if 10 == i puts i end end => 1…9
  • 27. Itérations a = 1..9 for i in a a = 1..9 puts i ou a.each { |i| puts i } end => 1…9 => 1…9 i=0 loop do i += 1 1.upto(10) do |i| puts i next if i.odd? # pas d'impair en ruby break if 10 == i puts i end end => 1…9 => 2, 4, 6, 8, 10
  • 28. Itérations a = 1..9 for i in a a = 1..9 puts i ou a.each { |i| puts i } end => 1…9 => 1…9 i=0 loop do i += 1 1.upto(10) do |i| puts i next if i.odd? # pas d'impair en ruby break if 10 == i puts i end end => 1…9 => 2, 4, 6, 8, 10 1.upto(2) do |i| v = rand(2) retry if v.zero? end
  • 30. Conditions if index == 1 else puts ‘0’ if index.zero? puts ‘not 0’ unless index.zero? end
  • 31. Conditions if index == 1 else puts ‘0’ if index.zero? puts ‘not 0’ unless index.zero? end def what_is_it?(a) case a what_is_it?(1) when 1..2 # 1 or 2 puts "1 or 2" what_is_it?(2) when 3 # 1 or 2 puts "3" what_is_it?(3) when /4.*/ # Regexp #3 puts "something starting with 4." what_is_it?("4004") when "foo" # something starting with 4. puts "foo" what_is_it?("foo") else # foo puts "I don't know." what_is_it?(5) end # Don't know. end
  • 33. Tableaux 1/2 1 lost = [8, 15, 16, 23] lost << 42 # push lost.unshift(4) # [4, 8, 15, 16, 23, 42]
  • 34. Tableaux 1/2 1 lost = [8, 15, 16, 23] lost << 42 # push lost.unshift(4) # [4, 8, 15, 16, 23, 42]
  • 35. Tableaux 1/2 1 lost = [8, 15, 16, 23] lost.at(0) lost << 42 # push #4 lost.unshift(4) lost[-1] # [4, 8, 15, 16, 23, 42] # 42
  • 36. Tableaux 1/2 1 lost = [8, 15, 16, 23] lost.at(0) lost << 42 # push #4 lost.unshift(4) lost[-1] # [4, 8, 15, 16, 23, 42] # 42
  • 37. Tableaux 1/2 1 lost = [8, 15, 16, 23] lost.at(0) lost << nil << nil lost << 42 # push #4 lost.unshift(4) lost[-1] # [4, 8, 15, 16, 23, 42, # [4, 8, 15, 16, 23, 42] # 42 nil, nil]
  • 38. Tableaux 1/2 1 lost = [8, 15, 16, 23] lost.at(0) lost << nil << nil lost << 42 # push #4 lost.unshift(4) lost[-1] # [4, 8, 15, 16, 23, 42, # [4, 8, 15, 16, 23, 42] # 42 nil, nil]
  • 39. Tableaux 1/2 1 lost = [8, 15, 16, 23] lost.at(0) lost << nil << nil lost << 42 # push #4 lost.unshift(4) lost[-1] # [4, 8, 15, 16, 23, 42, # [4, 8, 15, 16, 23, 42] # 42 nil, nil] lost.compact! # [4, 8, 15, 16, 23, 42]
  • 40. Tableaux 1/2 1 lost = [8, 15, 16, 23] lost.at(0) lost << nil << nil lost << 42 # push #4 lost.unshift(4) lost[-1] # [4, 8, 15, 16, 23, 42, # [4, 8, 15, 16, 23, 42] # 42 nil, nil] lost.compact! # [4, 8, 15, 16, 23, 42]
  • 41. Tableaux 1/2 1 lost = [8, 15, 16, 23] lost.at(0) lost << nil << nil lost << 42 # push #4 lost.unshift(4) lost[-1] # [4, 8, 15, 16, 23, 42, # [4, 8, 15, 16, 23, 42] # 42 nil, nil] lost << [4, 8] lost.compact! # [4, 8, 15, 16, 23, 42, # [4, 8, 15, 16, 23, 42] [4, 8]]
  • 42. Tableaux 1/2 1 lost = [8, 15, 16, 23] lost.at(0) lost << nil << nil lost << 42 # push #4 lost.unshift(4) lost[-1] # [4, 8, 15, 16, 23, 42, # [4, 8, 15, 16, 23, 42] # 42 nil, nil] lost << [4, 8] lost.compact! # [4, 8, 15, 16, 23, 42, # [4, 8, 15, 16, 23, 42] [4, 8]]
  • 43. Tableaux 1/2 1 lost = [8, 15, 16, 23] lost.at(0) lost << nil << nil lost << 42 # push #4 lost.unshift(4) lost[-1] # [4, 8, 15, 16, 23, 42, # [4, 8, 15, 16, 23, 42] # 42 nil, nil] lost.flatten!.uniq! lost << [4, 8] lost.compact! # [4, 8, 15, 16, 23, 42] # [4, 8, 15, 16, 23, 42, # [4, 8, 15, 16, 23, 42] [4, 8]]
  • 44. Tableaux 1/2 1 lost = [8, 15, 16, 23] lost.at(0) lost << nil << nil lost << 42 # push #4 lost.unshift(4) lost[-1] # [4, 8, 15, 16, 23, 42, # [4, 8, 15, 16, 23, 42] # 42 nil, nil] lost.flatten!.uniq! lost << [4, 8] lost.compact! # [4, 8, 15, 16, 23, 42] # [4, 8, 15, 16, 23, 42, # [4, 8, 15, 16, 23, 42] [4, 8]] lost.index(23) #4
  • 45. Tableaux 1/2 1 lost = [8, 15, 16, 23] lost.at(0) lost << nil << nil lost << 42 # push #4 lost.unshift(4) lost[-1] # [4, 8, 15, 16, 23, 42, # [4, 8, 15, 16, 23, 42] # 42 nil, nil] lost.flatten!.uniq! lost << [4, 8] lost.compact! # [4, 8, 15, 16, 23, 42] # [4, 8, 15, 16, 23, 42, # [4, 8, 15, 16, 23, 42] [4, 8]] lost.shuffle lost.index(23) # [16, 23, 42, 4, 15, 8] [5, 3, 7, 39, 1, 15].sort #4 # [1, 3, 5, 7, 15, 39]
  • 46. Tableaux 1/2 1 lost = [8, 15, 16, 23] lost.at(0) lost << nil << nil lost << 42 # push #4 lost.unshift(4) lost[-1] # [4, 8, 15, 16, 23, 42, # [4, 8, 15, 16, 23, 42] # 42 nil, nil] lost.flatten!.uniq! lost << [4, 8] lost.compact! # [4, 8, 15, 16, 23, 42] # [4, 8, 15, 16, 23, 42, # [4, 8, 15, 16, 23, 42] [4, 8]] lost.shuffle lost.index(23) # [16, 23, 42, 4, 15, 8] ('a'..'z').to_a [5, 3, 7, 39, 1, 15].sort ["a", "b", "c", "d"…] #4 # [1, 3, 5, 7, 15, 39]
  • 48. Tableaux 2/2 double_lost = lost.map { |v| v * 2 } # => [8, 16, 30, 32, 46, 84]
  • 49. Tableaux 2/2 # lost: [4, 8, 15, 16, 23, 42] double_lost = lost.map { |v| v * 2 } double_lost - lost # => [8, 16, 30, 32, 46, 84] # => [30, 32, 46, 84]
  • 50. Tableaux 2/2 # lost: [4, 8, 15, 16, 23, 42] double_lost = lost.map { |v| v * 2 } double_lost - lost # => [8, 16, 30, 32, 46, 84] # => [30, 32, 46, 84] # intersection double_lost & lost # [8, 16]
  • 51. Tableaux 2/2 # lost: [4, 8, 15, 16, 23, 42] double_lost = lost.map { |v| v * 2 } double_lost - lost # => [8, 16, 30, 32, 46, 84] # => [30, 32, 46, 84] # intersection # jointure double_lost & lost (double_lost | lost).sort # [8, 16] # [4, 8, 15, 16, 23, 30, 32, 42, 46, 84]
  • 53. String str = "bar" puts 'foo #{str}' # => foo #{str}
  • 54. String str = "bar" # Interpolation puts 'foo #{str}' puts "foo #{str}" # => foo #{str} # => foo bar
  • 55. String str = "bar" # Interpolation puts 'foo #{str}' puts "foo #{str}" # => foo #{str} # => foo bar str = "a" str.succ # => "b"
  • 56. String str = "bar" # Interpolation puts 'foo #{str}' puts "foo #{str}" # => foo #{str} # => foo bar str = "a" str = "foon" str.succ str.chomp # => "b" # => "foo"
  • 57. String str = "bar" # Interpolation puts 'foo #{str}' puts "foo #{str}" # => foo #{str} # => foo bar str = "a" str = "foon" str.succ str.chomp # => "b" # => "foo" str = "foo" str.chop # => "fo"
  • 58. String str = "bar" # Interpolation puts 'foo #{str}' puts "foo #{str}" # => foo #{str} # => foo bar str = "a" str = "foon" str.succ str.chomp # => "b" # => "foo" "supinfo".capitalize str = "foo" # => "Supinfo" str.chop "supinfo".upcase # => "fo" # => "SUPINFO"
  • 59. String str = "bar" # Interpolation puts 'foo #{str}' puts "foo #{str}" # attention, en 1.8 # => foo #{str} # => foo bar str = "éhé" str.size # => 5 et non 3 str[0] str = "a" str = "foon" # 195 et non é (code ascii) str.succ str.chomp # => "b" # => "foo" # patché dans rails str.mb_chars[0] #é "supinfo".capitalize str.mb_chars.size str = "foo" #3 # => "Supinfo" str.chop "supinfo".upcase # => "fo" # => "SUPINFO"
  • 61. Hash Association clé / valeur h = { :a => 'a', :b => 42, :c => { :d => 'f' } } h2 = { :a => 'foo' } h.merge(h2) => {:a=>"foo", :b=>42, :c=>{:d=>"f"}}
  • 63. Class: les constructeurs class A def A.new end end A.new
  • 64. Class: les constructeurs class A class B def A.new def self.new end end end end A.new B.new
  • 65. Class: les constructeurs class A class B def A.new def self.new end end end end A.new B.new class C def initialize end end C.new
  • 66. Class: les constructeurs class A class B def A.new def self.new end end end end A.new B.new class D # pas de constructeur multiple class C def initialize; end def initialize end def initialize(*args) end end end C.new D.new # => KO D.new(1) # => OK
  • 68. Class: les accesseurs class Product def initialize(name, description, price) @name = name @description = description @price = price end def name @name end def name=(name) @name = name end … end
  • 69. Class: les accesseurs class Product def initialize(name, description, price) @name = name @description = description class Product @price = price attr_accessor :name end attr_reader: description attr_writer :price def name @name def initialize(name, description, price) end @name = name @description = description def name=(name) @price = price @name = name end end end … end
  • 70. Class: portée & héritage
  • 71. Class: portée & héritage class Animal def initialize puts "Born to be alive." end protected def breathe? puts "inhale, exhale" true end private def speak; end end # Animal.new.speak # => fail with private method `speak'
  • 72. Class: portée & héritage class Animal class Dog < Animal def initialize def alive? puts "Born to be alive." puts "I'm alive" if breathe? end end protected def speak def breathe? puts "woff." puts "inhale, exhale" end true end end snoopy = Dog.new private # Born to be alive. def speak; end snoopy.speak end # woff. snoopy.alive? # Animal.new.speak # inhale, exhale # => fail with private method `speak' # I'm alive
  • 74. Class: étendre # Etendre un objet str = "foo" class << str def blank? self !~ /S/ end end str.blank? # => false
  • 75. Class: étendre # Etendre un objet # Etendre une classe str = "foo" class String def blank? class << str self !~ /S/ def blank? end self !~ /S/ end end end " ".blank? # => true str.blank? "foo".blank? # => false # => false
  • 76. Class: ce qui n’existe pas • Pas d’héritage multiple • Basé sur les mixins • Pas d’interface • Pas de classe abstraite native
  • 77. Les outils irb : votre shell ruby [17:59:57] fuse@h [~]$ irb ruby-1.8.7-p302 :001 > puts ‘foo’ foo => nil ruby-1.8.7-p302 :002 > 21 * 2 => 42 ruby-1.8.7-p302 :008 > String.methods.sort => ["<", "<=", "<=>", "==", "===", "=~", ">", …] rvm : gérer plusieurs versions de ruby
  • 78. Documentation • http://www.ruby-doc.org/ • http://www.ruby-lang.org/ • http://apidock.com/ruby • Le pickAxe: LA référence • http://tryruby.org/ • http://groups.google.com/group/rubyfr- public
  • 79. Rails On ne va pas (ou peu) parler de: Copieurs Test I18n Rake Cache Rails 3 ActionMailer Déploiement ActiveSupport
  • 80. L’Histoire • Créé par DHH (David Heinemeier Hansson) • Version 1 en décembre 2005 • Pragmatique dès le début: basecamp
  • 81. Rails en entreprise • Plus un jouet • Présent en entreprise, grandes et petites • Opportunités en temps que développeur
  • 82. Les versions • Stable actuelle: 3.0.7 • Rails 3 issue du merge avec merb (08/10) • Framework agnostic • Stable actuelle: 2.3.11 • La plus rencontrée en entreprise
  • 83. Des conventions Quelques noms barbares: • Convention over configuration • DRY • MVC
  • 84. Convention over configuration • Votre passion est de customiser Tomcat ? Désolé ! • 0 conf pour commencer à développer • Serveur web embarqué • BDD embarquée
  • 85. Don’t repeat yourself • - de code = - de bug • - de code = - de maintenance • - de code = + de temps
  • 86. Modèle - Vue - Contrôleur Modèle Contrôleur Vue Métier Fonctionnel Affichage
  • 87. Rails en vrai • Pas de hello world, c’est trop simple… • La classique liste de produits plutôt.
  • 88. Créons notre application $ rails app 3 environnements
  • 89.
  • 90. class Product < ActiveRecord::Base Modèle end app/models/product.rb
  • 91. class Product < ActiveRecord::Base Modèle end app/models/product.rb class ProductsController < ApplicationController Contrôleur def index @products = Product.all app/controllers/ end end products_controller.rb
  • 92. class Product < ActiveRecord::Base Modèle end app/models/product.rb class ProductsController < ApplicationController Contrôleur def index @products = Product.all app/controllers/ end end products_controller.rb <html><body> Vue <% for product in @products %> <p><%= product.name %></p> app/views/products/ <% end %> </body></html> index.html.erb
  • 93. class Product < ActiveRecord::Base Modèle end app/models/product.rb class ProductsController < ApplicationController Contrôleur def index @products = Product.all app/controllers/ end end products_controller.rb <html><body> Vue <% for product in @products %> <p><%= product.name %></p> app/views/products/ <% end %> </body></html> index.html.erb
  • 94. Que vient on de faire ? • Créer une classe product qui hérite de AR::Base Model • Créer un contrôleur qui gère les actions (ex: index) Contrôleur • Créer des vues pour afficher la liste et les formulaires Vue
  • 95. Le modèle avec Active Record • S’interface avec la base de données • SQLite par défaut • Plus de SQL manuel • Plus de risque d’injections
  • 97. Créer un modèle $ ruby script/generate model Product name:string description:text price:float category_id:integer
  • 98. Créer un modèle $ ruby script/generate model Product name:string description:text price:float category_id:integer class CreateProducts < ActiveRecord::Migration def self.up create_table :products do |t| db/migrate/ t.string :name t.text :description 20110322113407_ t.float :price create_products.rb t.integer :category_id t.timestamps end rake db:migrate end def self.down drop_table :products end end
  • 100. Configuration & log config/database.yml development: adapter: sqlite3 database: db/ Adaptateurs pour MySQL, development.sqlite3 pool: 5 Postgresql, oracle… timeout: 5000
  • 101. Configuration & log config/database.yml development: adapter: sqlite3 database: db/ Adaptateurs pour MySQL, development.sqlite3 pool: 5 Postgresql, oracle… timeout: 5000 Dans le contrôleur log/development.log Product Load (0.3ms) @products = Product.all SELECT * FROM "products"
  • 103. Créer un produit c = Category.first Product.create({ :name => "Ruby 'on Rails", # injection SQL :description => "First book on RoR", :price => 10.0, :category => c })
  • 104. Créer un produit c = Category.first Product.create({ :name => "Ruby 'on Rails", # injection SQL :description => "First book on RoR", :price => 10.0, :category => c }) log/development.log Product Create (0.8ms) INSERT INTO "products" ("name", "price", "created_at", "updated_at", "category_id", "description") VALUES ('Ruby ''on Rails', 10.0, '2011-03-22 18:13:07', '2011-03-22 18:13:07', 1, 'First book on RoR')
  • 105. Encore trop complexe ? Besoin d’un outil qui gère le CRUD en 1 commande: • Create • Read • Update • Delete
  • 108. Plus qu’une migration • Et vous pouvez: • Créer des produits (Create) • Les lister et afficher (Read) • Les mettre à jour (Update) • Et les supprimer (Delete)
  • 111. Les relations class Category < ActiveRecord::Base has_many :products Une catégorie possède end n produits
  • 112. Les relations class Category < ActiveRecord::Base has_many :products Une catégorie possède end n produits class Product < ActiveRecord::Base Un produit appartient à belongs_to :category end une catégorie
  • 113. Les relations class Category < ActiveRecord::Base has_many :products Une catégorie possède end n produits class Product < ActiveRecord::Base Un produit appartient à belongs_to :category end une catégorie ou class Product < ActiveRecord::Base Une catégorie possède has_and_belongs_to_many :category n produits et un end produit n catégories
  • 115. Les finder Product.find(:all, :conditions => { :price => 18 }) Product.find(:first) Product.find(:last)
  • 116. Les finder Product.find(:all, :conditions => { :price => 18 }) Product.find(:first) Product.find(:last) Plusieurs finder dynamiques: Product.find_by_name(‘rails’) Product.find_all_by_name(‘rails’) Product.find_by_name_and_price(‘book’, 18)
  • 117. Les finder Product.find(:all, :conditions => { :price => 18 }) Product.find(:first) Product.find(:last) Plusieurs finder dynamiques: Product.find_by_name(‘rails’) Product.find_all_by_name(‘rails’) Product.find_by_name_and_price(‘book’, 18) Jointure: Product.find(:all, :joins => :category, :conditions => { :categories => { :name => "books" }})
  • 119. Les scope class Product < ActiveRecord::Base named_scope :recent, lambda { { :conditions => ["created_at > ?", 5.days.ago] } } named_scope :limit, lambda { |n| { :limit => n } } named_scope :ordered_by_name, { :order => "NAME ASC" } end
  • 120. Les scope class Product < ActiveRecord::Base named_scope :recent, lambda { { :conditions => ["created_at > ?", 5.days.ago] } } named_scope :limit, lambda { |n| { :limit => n } } named_scope :ordered_by_name, { :order => "NAME ASC" } end Invoquer les scope, de façon chaînable Product.recent.ordered_by_name.limit(2) Product Load (0.3ms) SELECT * FROM "products" WHERE (created_at > '2011-03-17 21:08:24') ORDER BY NAME ASC LIMIT 2
  • 121. Les validations class Product < ActiveRecord::Base belongs_to :category validates_presence_of :name, :category_id validates_numericality_of :price et bien d’autres: validates_confirmation_of validates_exclusion_of validates_format_of validates_inclusion_of validates_length_of …
  • 122. Le contrôleur avec ActionController • L’interface entre le modèle et la vue • Association automatique méthode / vue • @variable directement disponible dans la vue • Possibilité de filtrer des actions
  • 123. Le routeur config/routes.rb ActionController::Routing::Routes.draw do |map| # RESTful /categories/1/products/1/ map.resources :categories do |category| category.resources :products end # route nommée map.purchase 'products/:id/purchase', :controller => 'catalog', :action => 'purchase' # namespace map.namespace :admin do |admin| # /admin/products admin.resource :products end # route par défaut map.root :controller => 'products' end
  • 124. Les routes rake routes categories GET /categories(.:format) {:controller=>"categories", :action=>"index"} POST /categories(.:format) {:controller=>"categories", :action=>"create"} new_category GET /categories/new(.:format) {:controller=>"categories", :action=>"new"} edit_category GET /categories/:id/edit(.:format) {:controller=>"categories", :action=>"edit"} category GET /categories/:id(.:format) {:controller=>"categories", :action=>"show"} PUT /categories/:id(.:format) {:controller=>"categories", :action=>"update"} DELETE /categories/:id(.:format) {:controller=>"categories", :action=>"destroy"} products GET /products(.:format) {:controller=>"products", :action=>"index"} POST /products(.:format) {:controller=>"products", :action=>"create"} new_product GET /products/new(.:format) {:controller=>"products", :action=>"new"} edit_product GET /products/:id/edit(.:format) {:controller=>"products", :action=>"edit"} product GET /products/:id(.:format) {:controller=>"products", :action=>"show"} PUT /products/:id(.:format) {:controller=>"products", :action=>"update"} DELETE /products/:id(.:format) {:controller=>"products", :action=>"destroy"} /:controller/:action/:id /:controller/:action/:id(.:format) root / {:controller=>"products", :action=>"index"}
  • 125. Les contrôleurs class ProductsController < ApplicationController before_filter :authenticate, :only => :index def index @products = Product.all #disponible dans la vue respond_to do |format| # GET /products format.html # index.html.erb # GET /products.xml format.xml { render :xml => @products } end end private def authenticate # do some stuff end end
  • 126. La vue avec ActionView • Les vues : pas forcément du HTML • Layout • Partials • Helpers
  • 127. Les types de vues i18n des vues app/views/products/index.fr.html.erb app/views/products/index.es.html.erb Rails >= 2.3
  • 128. Les types de vues i18n des vues app/views/products/index.fr.html.erb app/views/products/index.es.html.erb Rails >= 2.3 Différents formats app/views/products/index.iphone.erb app/views/products/index.xml.erb
  • 129. Le layout Squelette de base app/views/layouts/application.html.erb Modifiable depuis <!DOCTYPE…> <html> le contrôleur <body> <%= yield %> </body> </html>
  • 130. Les partials Des morceaux de vue <!DOCTYPE…> <html> <body> app/views/products/_sidebar.html.erb <%= render :partial => ‘products/sidebar’ %> <%= yield %> </body> </html>
  • 131. Exemple de vue: liste <h1>Listing categories</h1> <table> <tr> <th>Name</th> </tr> <% @categories.each do |category| %> <tr> <td><%=h truncate(category.name, :size => 10) %></td> <td><%= link_to 'Show', category %></td> <td><%= link_to 'Edit', edit_category_path(category) %></td> <td><%= link_to 'Destroy', category, :confirm => 'Are you sure?', :method => :delete %></td> </tr> <% end %> </table> <br /> <%= link_to 'New category', new_category_path %>
  • 132. Exemple de vue: édition <% form_for(@product) do |f| %> <%= f.error_messages %> <p> <%= f.label :name %><br /> <%= f.text_field :name %> </p><p> <%= f.label :description %><br /> <%= f.text_area :description %> </p><p> <%= f.label :available %><br /> <%= f.check_box :available %> </p><p> <%= f.label :category_id %><br /> <%= f.select :category_id, (Category.all.map do |c| [c.name, c.id] end) %> </p><p> <%= f.submit 'Update' %> </p> <% end %> <%= link_to 'Show', @product %> | <%= link_to 'Back', products_path %>
  • 133. Autour de Rails • Communauté active config/environment.rb • Autour de github Rails::Initializer.run do |config| config.gem ‘hpricot’ • end Gems • Authentification • Pagination • …
  • 134. Documentation • http://www.rubyonrails.org/ • http://guides.rubyonrails.org/ • http://apidock.com/rails • http://railsforzombies.org/ • http://groups.google.com/group/railsfrance
  • 135. Merci, c’est à vous ! • Des questions ? _fuse mcatty@synbioz.com

Editor's Notes

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n
  38. \n
  39. \n
  40. \n
  41. \n
  42. \n
  43. \n
  44. \n
  45. \n
  46. \n
  47. \n
  48. \n
  49. \n
  50. \n
  51. \n
  52. \n
  53. \n
  54. \n
  55. \n
  56. \n
  57. \n
  58. \n
  59. \n
  60. \n
  61. \n
  62. \n
  63. \n
  64. \n
  65. \n
  66. \n
  67. \n
  68. \n
  69. \n
  70. \n
  71. \n
  72. \n
  73. \n
  74. \n
  75. \n
  76. \n
  77. \n
  78. \n
  79. \n
  80. \n
  81. \n
  82. \n
  83. \n
  84. \n
  85. \n
  86. \n
  87. \n
  88. \n
  89. \n
  90. \n
  91. \n
  92. \n
  93. \n
  94. \n
  95. \n
  96. \n
  97. \n
  98. \n
  99. \n
  100. \n
  101. \n
  102. \n
  103. \n
  104. \n
  105. \n
  106. \n
  107. \n
  108. \n
  109. \n
  110. \n
  111. \n
  112. \n
  113. \n
  114. \n