Ruby on rails presentation
Upcoming SlideShare
Loading in...5
×
 

Ruby on rails presentation

on

  • 932 views

French presentation of ruby and ruby on rails for beginners.

French presentation of ruby and ruby on rails for beginners.

Statistics

Views

Total Views
932
Views on SlideShare
705
Embed Views
227

Actions

Likes
1
Downloads
18
Comments
0

1 Embed 227

http://www.synbioz.com 227

Accessibility

Categories

Upload Details

Uploaded via as Apple Keynote

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n

Ruby on rails presentation Ruby on rails presentation Presentation Transcript

  • 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 ThreadImplé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 Rubyclass Hello { public static void main(String [] args) { system.out.println(‘Hello’); }}
  • Le fameux hello world Java Rubyclass Hello { public static void main(String [] args) { system.out.println(‘Hello’); puts ‘Hello’ }}
  • Le fameux hello world Java Rubyclass 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 variablesclass 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 endend p A.instances #=> 5
  • Itérations
  • Itérationsa = 1..9for i in a puts iend
  • 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 dimpair 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 dimpair 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 dimpair 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
  • Conditionsif index == 1else puts ‘0’ if index.zero? puts ‘not 0’ unless index.zero?end
  • Conditionsif index == 1else puts ‘0’ if index.zero? puts ‘not 0’ unless index.zero?enddef 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 dont know." what_is_it?(5) end # Dont know.end
  • Tableaux 1/21
  • Tableaux 1/21 lost = [8, 15, 16, 23] lost << 42 # push lost.unshift(4) # [4, 8, 15, 16, 23, 42]
  • Tableaux 1/21 lost = [8, 15, 16, 23] lost << 42 # push lost.unshift(4) # [4, 8, 15, 16, 23, 42]
  • Tableaux 1/21 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/21 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/21 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/21 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/21 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/21 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/21 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/21 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/21 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/21 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/21 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/21 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/2double_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]# intersectiondouble_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 # jointuredouble_lost & lost (double_lost | lost).sort# [8, 16] # [4, 8, 15, 16, 23, 30, 32, 42, 46, 84]
  • String
  • Stringstr = "bar"puts foo #{str}# => foo #{str}
  • Stringstr = "bar" # Interpolationputs foo #{str} puts "foo #{str}"# => foo #{str} # => foo bar
  • Stringstr = "bar" # Interpolationputs foo #{str} puts "foo #{str}"# => foo #{str} # => foo barstr = "a"str.succ# => "b"
  • Stringstr = "bar" # Interpolationputs foo #{str} puts "foo #{str}"# => foo #{str} # => foo barstr = "a" str = "foon"str.succ str.chomp# => "b" # => "foo"
  • Stringstr = "bar" # Interpolationputs foo #{str} puts "foo #{str}"# => foo #{str} # => foo barstr = "a" str = "foon"str.succ str.chomp# => "b" # => "foo"str = "foo"str.chop# => "fo"
  • Stringstr = "bar" # Interpolationputs foo #{str} puts "foo #{str}"# => foo #{str} # => foo barstr = "a" str = "foon"str.succ str.chomp# => "b" # => "foo" "supinfo".capitalizestr = "foo" # => "Supinfo"str.chop "supinfo".upcase# => "fo" # => "SUPINFO"
  • Stringstr = "bar" # Interpolationputs 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.sizestr = "foo" #3 # => "Supinfo"str.chop "supinfo".upcase# => "fo" # => "SUPINFO"
  • HashAssociation clé / valeur
  • HashAssociation 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 constructeursclass A def A.new endendA.new
  • Class: les constructeursclass A class B def A.new def self.new end endend endA.new B.new
  • Class: les constructeursclass A class B def A.new def self.new end endend endA.new B.newclass C def initialize endendC.new
  • Class: les constructeursclass A class B def A.new def self.new end endend endA.new B.new class D # pas de constructeur multipleclass C def initialize; end def initialize end def initialize(*args)end end endC.new D.new # => KO D.new(1) # => OK
  • Class: les accesseurs
  • Class: les accesseursclass 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 accesseursclass 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éritageclass Animal def initialize puts "Born to be alive." end protected def breathe? puts "inhale, exhale" true end private def speak; endend# Animal.new.speak# => fail with private method `speak
  • Class: portée & héritageclass Animal class Dog < Animal def initialize def alive? puts "Born to be alive." puts "Im 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.speakend # woff. snoopy.alive?# Animal.new.speak # inhale, exhale# => fail with private method `speak # Im alive
  • Class: étendre
  • Class: étendre# Etendre un objetstr = "foo"class << str def blank? self !~ /S/ endendstr.blank?# => false
  • Class: étendre# Etendre un objet # Etendre une classestr = "foo" class String def blank?class << str self !~ /S/ def blank? end self !~ /S/ end endend " ".blank? # => truestr.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 outilsirb : 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
  • RailsOn 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 conventionsQuelques 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 app3 environnements
  • class Product < ActiveRecord::Base Modèleend app/models/product.rb
  • class Product < ActiveRecord::Base Modèleend app/models/product.rbclass ProductsController < ApplicationController Contrôleur def index @products = Product.all app/controllers/ end end products_controller.rb
  • class Product < ActiveRecord::Base Modèleend app/models/product.rbclass 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èleend app/models/product.rbclass 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:floatcategory_id:integer
  • Créer un modèle$ ruby script/generate model Product name:string description:text price:floatcategory_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 & logconfig/database.yml development: adapter: sqlite3 database: db/ Adaptateurs pour MySQL, development.sqlite3 pool: 5 Postgresql, oracle… timeout: 5000
  • Configuration & logconfig/database.yml development: adapter: sqlite3 database: db/ Adaptateurs pour MySQL, development.sqlite3 pool: 5 Postgresql, oracle… timeout: 5000Dans le contrôleur log/development.log Product Load (0.3ms) @products = Product.all SELECT * FROM "products"
  • Créer un produit
  • Créer un produitc = Category.firstProduct.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, Firstbook 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èdeend n produits
  • Les relations class Category < ActiveRecord::Base has_many :products Une catégorie possèdeend n produits class Product < ActiveRecord::Base Un produit appartient à belongs_to :categoryend une catégorie
  • Les relations class Category < ActiveRecord::Base has_many :products Une catégorie possèdeend n produits class Product < ActiveRecord::Base Un produit appartient à belongs_to :categoryend une catégorieou class Product < ActiveRecord::Base Une catégorie possède has_and_belongs_to_many :category n produits et unend produit n catégories
  • Les finder
  • Les finderProduct.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 scopeclass 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" } endInvoquer 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 :priceet bien d’autres:validates_confirmation_ofvalidates_exclusion_ofvalidates_format_ofvalidates_inclusion_ofvalidates_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 routeurconfig/routes.rbActionController::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 => productsend
  • 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ôleursclass 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 endend
  • La vue avec ActionView• Les vues : pas forcément du HTML• Layout• Partials• Helpers
  • Les types de vuesi18n des vues app/views/products/index.fr.html.erb app/views/products/index.es.html.erb Rails >= 2.3
  • Les types de vuesi18n des vues app/views/products/index.fr.html.erb app/views/products/index.es.html.erb Rails >= 2.3Différents formats app/views/products/index.iphone.erb app/views/products/index.xml.erb
  • Le layoutSquelette de base app/views/layouts/application.html.erbModifiable depuis <!DOCTYPE…> <html>le contrôleur <body> <%= yield %> </body> </html>
  • Les partialsDes 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