Presentation is loading. Please wait.

Presentation is loading. Please wait.

Ruby on Rails Supinfo 2011. A propos Martin Catty, fondateur de Synbioz Rubyiste depuis 2006 _fuse

Similar presentations


Presentation on theme: "Ruby on Rails Supinfo 2011. A propos Martin Catty, fondateur de Synbioz Rubyiste depuis 2006 _fuse"— Presentation transcript:

1 Ruby on Rails Supinfo 2011

2 A propos Martin Catty, fondateur de Synbioz Rubyiste depuis 2006 _fuse mcatty@synbioz.commcatty@synbioz.com

3 Ruby avant Rails Ne partez pas sans vos bagages ! Rails a aidé à lessor de Ruby Mais pas de framework sans langage

4 Ruby On ne va pas (ou peu) parler de: I/O Réseau Thread Test Debugger Proc / lambda Exceptions Garbage VM Implémentations

5 LHistoire 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 class Hello { public static void main(String [] args) { system.out.println(Hello);}} class Hello { public static void main(String [] args) { system.out.println(Hello); } } JavaRuby puts Hello

9 Tout est objet 2.times { puts "Bonjour Supinfo." } => Bonjour Supinfo 3.upto(5) { |i| puts i } => 3 => 4 => 5 p 1.zero? => false 39 + 3 => 39.+(3)

10 Les variables class A MAX = 42 @@instances = 0 def initialize(name) @name = name @@instances += 1 end def self.instances @@instancesendend class A MAX = 42 @@instances = 0 def initialize(name) @name = name @@instances += 1 end def self.instances @@instancesendend A.new("a")A.new("b")A.ne w("c")A.new("d")A.new("e") p A.instances #=> 5

11 Itérations a = 1..9 for i in a puts i end a = 1..9 for i in a puts i end a = 1..9 a.each { |i| puts i } a = 1..9 a.each { |i| puts i } => 1…9 ou i = 0loop do i += 1 puts i break if 10 == iend i = 0loop do i += 1 puts i break if 10 == iend 1.upto(10) do |i| next if i.odd? # pas d'impair en ruby puts iend 1.upto(10) do |i| next if i.odd? # pas d'impair en ruby puts iend => 2, 4, 6, 8, 10 => 1…9 1.upto(2) do |i| v = rand(2) retry if v.zero?end 1.upto(2) do |i| v = rand(2) retry if v.zero?end

12 Conditions if index == 1 elseend elseend puts 0 if index.zero? puts not 0 unless index.zero? def what_is_it?(a) case a when 1..2 puts "1 or 2" when 3 puts "3" when /4.*/ # Regexp puts "something starting with 4." when "foo" puts "foo" else puts "I don't know." endend what_is_it?(1)# 1 or 2what_is_it?(2)# 1 or 2what_is_it?(3)# 3what_is_it?("4004")# something starting with 4.what_is_it?("foo")# foowhat_is_it?(5)# Don't know.

13 Tableaux 1/2 lost = [8, 15, 16, 23] lost << 42 # push lost.unshift(4) # [4, 8, 15, 16, 23, 42] lost = [8, 15, 16, 23] lost << 42 # push lost.unshift(4) # [4, 8, 15, 16, 23, 42] lost << nil << nil # [4, 8, 15, 16, 23, 42, nil, nil] lost << nil << nil # [4, 8, 15, 16, 23, 42, nil, nil] lost.compact! # [4, 8, 15, 16, 23, 42] lost.compact! # [4, 8, 15, 16, 23, 42] lost << [4, 8] # [4, 8, 15, 16, 23, 42, [4, 8]] lost << [4, 8] # [4, 8, 15, 16, 23, 42, [4, 8]] lost.flatten!.uniq! # [4, 8, 15, 16, 23, 42] lost.flatten!.uniq! # [4, 8, 15, 16, 23, 42] lost.index(23) # 4 lost.index(23) # 4 lost.shuffle # [16, 23, 42, 4, 15, 8] [5, 3, 7, 39, 1, 15].sort # [1, 3, 5, 7, 15, 39] lost.shuffle # [16, 23, 42, 4, 15, 8] [5, 3, 7, 39, 1, 15].sort # [1, 3, 5, 7, 15, 39] ('a'..'z').to_a ["a", "b", "c", "d"…] ('a'..'z').to_a ["a", "b", "c", "d"…] lost.at(0) # 4 lost[-1] # 42 lost.at(0) # 4 lost[-1] # 42 11

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

15 String str = "a"str.succ# => "b" str = "a"str.succ# => "b" # Interpolationputs "foo #{str}"# => foo bar # Interpolationputs "foo #{str}"# => foo bar # attention, en 1.8 str = "éhé" str.size# => 5 et non 3 str[0]# 195 et non é (code ascii) # patché dans rails str.mb_chars[0] # é str.mb_chars.size # 3 # attention, en 1.8 str = "éhé" str.size# => 5 et non 3 str[0]# 195 et non é (code ascii) # patché dans rails str.mb_chars[0] # é str.mb_chars.size # 3 str = "bar" puts 'foo #{str}'# => foo #{str} str = "bar" puts 'foo #{str}'# => foo #{str} str = "foo\n"str.chomp# => "foo" str = "foo\n"str.chomp# => "foo" str = "foo"str.chop# => "fo" str = "foo"str.chop# => "fo" "supinfo".capitalize # => "Supinfo" "supinfo".upcase # => "SUPINFO" "supinfo".capitalize # => "Supinfo" "supinfo".upcase # => "SUPINFO"

16 Hash h = { :a => 'a', :b => 42, :c => { :d => 'f' } } h2 = { :a => 'foo' } h.merge(h2) => {:a=>"foo", :b=>42, :c=>{:d=>"f"}} h2 = { :a => 'foo' } h.merge(h2) => {:a=>"foo", :b=>42, :c=>{:d=>"f"}} Association clé / valeur

17 Class: les constructeurs class A def A.new endendA.new class A def A.new endendA.new class B def self.new endend B.new class B def self.new endend B.new class C def initialize endendC.new endendC.new class C def initialize endendC.new class D # pas de constructeur multiple def initialize; end def initialize(*args) endend D.new # => KOD.new(1) # => OK class D # pas de constructeur multiple def initialize; end def initialize(*args) endend D.new # => KOD.new(1) # => OK

18 Class: les accesseurs class Product def initialize(name, description, price) @name = name @description = description @price = price end def name @nameend def name=(name) @name = name end…end 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 Product attr_accessor :name attr_reader: description attr_writer :price def initialize(name, description, price) @name = name @description = description @price = price endend class Product attr_accessor :name attr_reader: description attr_writer :price def initialize(name, description, price) @name = name @description = description @price = price endend

19 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; endend # Animal.new.speak # => fail with private method `speak' class 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 Dog < Animal def alive? puts "I'm alive" if breathe? end def speak puts "woff." endend snoopy = Dog.new # Born to be alive.snoopy.speak # woff.snoopy.alive? # inhale, exhale# I'm alive class Dog < Animal def alive? puts "I'm alive" if breathe? end def speak puts "woff." endend snoopy = Dog.new # Born to be alive.snoopy.speak # woff.snoopy.alive? # inhale, exhale# I'm alive

20 Class: étendre # Etendre un objetstr = "foo"class false # Etendre un objetstr = "foo"class << str def blank? self !~ /\S/ endendstr.blank?# => false # Etendre une classe class String def blank? self !~ /\S/ endend" ".blank?# => true"foo".blank?# => false # Etendre une classe class String def blank? self !~ /\S/ endend" ".blank?# => true"foo".blank?# => false

21 Class: ce qui nexiste pas Pas dhéritage multiple Basé sur les mixins Pas dinterface Pas de classe abstraite native

22 Les outils [17:59:57] fuse@h [~]$ irbruby-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 => [" ", "==", "===", "=~", ">", …] [17:59:57] fuse@h [~]$ irbruby-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 => [" ", "==", "===", "=~", ">", …] irb : votre shell ruby rvm : gérer plusieurs versions de ruby

23 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://tryruby.org http://groups.google.com/group/rubyfr- public http://groups.google.com/group/rubyfr- public

24 Rails On ne va pas (ou peu) parler de: Test Cache Rake ActionMailer ActiveSupport I18n Déploiement Copieurs Rails 3

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

26 Rails en entreprise Plus un jouet Présent en entreprise, grandes et petites Opportunités en temps que développeur

27 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

28 Des conventions Convention over configuration DRY MVC Quelques noms barbares:

29 Convention over configuration Votre passion est de customiser Tomcat ?Désolé ! 0 conf pour commencer à développer Serveur web embarqué BDD embarquée

30 Dont repeat yourself - de code = - de bug - de code = - de maintenance - de code = + de temps

31 Modèle - Vue - Contrôleur Contrôle ur ModèleModèleVueVue MétierFonctionnelAffichage

32 Rails en vrai Pas de hello world, cest trop simple… La classique liste de produits plutôt.

33 Créons notre application $ rails app 3 environnements

34 class Product < ActiveRecord::Base end end Modèle app/models/product.rb class ProductsController < ApplicationController def index @products = Product.all endend class ProductsController < ApplicationController def index @products = Product.all endend Contrôleur app/controllers/products _controller.rb Vue app/views/products/i ndex.html.erb

35 Que vient on de faire ? Créer une classe product qui hérite de AR::Base Créer un contrôleur qui gère les actions (ex: index) Créer des vues pour afficher la liste et les formulaires Model Contrôleur Vue

36 Le modèle avec Active Record Sinterface avec la base de données SQLite par défaut Plus de SQL manuel Plus de risque dinjections

37 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| t.string :name t.text :description t.float :price t.integer :category_id t.timestamps end end def self.down drop_table :products endend db/migrate/ 20110322113407 _create_products. rb rake db:migrate

38 Configuration & log @products = Product.all Dans le contrôleurlog/development.log Product Load (0.3ms) SELECT * FROM "products" config/database.yml development: adapter: sqlite3 database: db/development.sqlite3 pool: 5 timeout: 5000 Adaptateurs pour MySQL, Postgresql, oracle…

39 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 }) c = Category.first Product.create({ :name => "Ruby 'on Rails", # injection SQL :description => "First book on RoR", :price => 10.0, :category => c }) Product Create (0.8ms) INSERT INTO "products" 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') Product Create (0.8ms) INSERT INTO "products" 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') log/development.log

40 Encore trop complexe ? Create Read Update Delete Besoin dun outil qui gère le CRUD en 1 commande:

41 Scaffold

42 Plus quune migration Et vous pouvez: Créer des produits (Create) Les lister et afficher (Read) Les mettre à jour (Update) Et les supprimer (Delete)

43 En images

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

45 Les finder Product.find(:all, :conditions => { :price => 18 }) Product.find(:first) Product.find(:last) 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) Product.find_by_name(rails) Product.find_all_by_name(rails) Product.find_by_name_and_price(book, 18) Product.find(:all, :joins => :category, :conditions => { :categories => { :name => "books" }}) Product.find(:all, :joins => :category, :conditions => { :categories => { :name => "books" }}) Jointure:

46 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 :recent, lambda { { :conditions => ["created_at > ?", 5.days.ago] } } named_scope :limit, lambda { |n| { :limit => n } } named_scope :ordered_by_name, { :order => "NAME ASC" } named_scope :ordered_by_name, { :order => "NAME ASC" }end class Product < ActiveRecord::Base named_scope :recent, lambda { { :conditions => ["created_at > ?", 5.days.ago] } } named_scope :limit, lambda { |n| { :limit => n } } 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" } 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 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

47 Les validations class Product < ActiveRecord::Base belongs_to :category validates_presence_of :name, :category_id validates_numericality_of :price class Product < ActiveRecord::Base belongs_to :category validates_presence_of :name, :category_id validates_numericality_of :price et bien dautres: validates_confirmation_of validates_exclusion_of validates_format_oflidates_format_of valivalidates_inclusion_of validates_length_ofdates_length_of …

48 Le contrôleur avec ActionController Linterface entre le modèle et la vue Association automatique méthode / vue @variable directement disponible dans la vue Possibilité de filtrer des actions

49 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 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

50 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"} 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"}

51 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 endprivate def authenticate # do some stuff endend 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 endprivate def authenticate # do some stuff endend

52 La vue avec ActionView Les vues : pas forcément du HTML Layout Partials Helpers

53 Les types de vues i18n des vues app/views/products/index.fr.html.erb app/views/products/index.es.html.erb 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 app/views/products/index.iphone.erb app/views/products/index.xml.erb

54 Le layout Squelette de base app/views/layouts/application.html.erb Modifiable depuis le contrôleur

55 Les partials Des morceaux de vue products/sidebar %> products/sidebar %> app/views/products/_sidebar.html. erb

56 Exemple de vue: liste Listing categories Name 10) %> 'Are you sure?', :method => :delete %> Listing categories Name 10) %> 'Are you sure?', :method => :delete %>

57 Exemple de vue: édition | |

58 Autour de Rails Communauté active Autour de github Gems Authentification Pagination … config/environment.rb Rails::Initializer.run do |config| config.gem hpricot end Rails::Initializer.run do |config| config.gem hpricot end

59 Documentation http://www.rubyonrails.org/ http://guides.rubyonrails.org/ http://guides.rubyonrails.org http://apidock.com/rails http://railsforzombies.org/ http://groups.google.com/group/railsfran ce http://groups.google.com/group/railsfran ce

60 Merci, cest à vous ! Des questions ? _fuse mcatty@synbioz.commcatty@synbioz.com


Download ppt "Ruby on Rails Supinfo 2011. A propos Martin Catty, fondateur de Synbioz Rubyiste depuis 2006 _fuse"

Similar presentations


Ads by Google