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
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
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
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
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
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
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
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
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 %>
133. Autour de Rails
• Communauté active config/environment.rb
• Autour de github Rails::Initializer.run do |config|
config.gem ‘hpricot’
•
end
Gems
• Authentification
• Pagination
• …