Edgar J. Suarez   http://rails.mx
Ruby
1993
Yukihiro Matsumoto
...computer engineers, focus on the machines. They think, "By    doing this, the machine will run faster. By doing this, t...
"I hope to see Ruby help every programmer in the world to be productive, and to enjoy programming, and to be happy. That i...
Perl + Smalltalk + Eiffel + Lisp
Dynamic Typing
x = 1x = "hoge"x = Class
Duck typing
"When I see a bird that walks like a duck and swims like a duck and quacks like a      duck, I call that bird a duck."
Readable(human friendly)
3.times do |i|  puts "Now i is #{i}"end@user.is_admin?@transaction.complete!
Flexible syntax
say_hello()say_hellomultiply(3, 2)multiply 3, 2
Reflexive(metaprogramming)
a = "by_name"eval <<-eos  def find_#{a}(name)    puts "finding by name"  endeosfind_by_name("edgar") # => "finding by name"
Iterators / blocks
5.times do  puts "Hello"end[ruby, rocks].each do |word|  puts wordend1.upto(3) do |i|  puts iend
Exception handling
begin  this_line.could_throw_an_exception!rescue Exception => e  puts "Exception rescued: #{e}"end
Object oriented
person.say_hi3.to_s"a string".capitalize[].empty?nil.class # => NilClass
Data types
3.class                      #   =>   Fixnum4.24.class                   #   =>   Float"Campus".class               #   =>...
Symbols
"name".object_id # => 2156968560"name".object_id # => 2156964240:name.object_id # => 68828:name.object_id # => 68828
Hashes
{    "name" => "John",    2      => 54,    true   => "(345) 434-554"}
{    :name => "John",    :age   => 54,    :phone => "(345) 434-554"}
Automatic Garbage    Collection
Boolean coercion(everything is true except false and nil)
Open classes
class Person  def walk    "walking..."  endendjuan = Person.newjuan.walk # => "walking..."class Person  def eat    "eating...
Default arguments
def multiply(a, b = 2)  a * bendmultiply 3, 4 # => 12multiply 4 # => 8
Splat arguments
def menu_list(*args)  options = args.pop  args.each do |arg|    puts "<a href=# style=#{options[:style]}>#{arg}</a>"  ende...
Attributes
class Person  def name=(name)    @name = name  end  def name    @name  endenda = Person.newa.name = "Pepe"a.name # => Pepe
class Person  attr_accessor :name  attr_reader   :age  attr_writer   :phoneend
“Class” methods
class Number  def self.sum(a, b)    a + b  end  def Number.pow(a, b)    a ** b  endendNumber.sum(2, 2) # => 4Number.pow(4,...
Self
class Number  def self.base    10  end  def self.parse(str)    str.to_i(self.base)  endendNumber.parse("30") # => 30
class Person  attr_accessor :first_name, :last_name  def full_name    "#{self.first_name} #{self.last_name}"  endendraul =...
Inheritance
class Shape  def area    @a * @b  endendclass Square < Shapeendsq = Square.newsq.area
class Shape  def area    @a * @b  endendclass Square < Shape  def area    if @a == @b      @a * @a    else      super    e...
Mixins
module Walkable  def walk    puts "Im walking"  endendmodule Runnable  def run    puts "Im running"  endendclass Person  i...
module Summable  def sum(a, b)    a + b  endendclass Number  extend SummableendNumber.sum 2, 4 # => 6
Namespaces
module ActiveRecord  class Base  endendActiveRecord::Base.new
Blocks
3.times do  puts "hey"end3.times { puts "hey" }
3.times do  puts "hey"endclass Fixnum  def times    i = 0    while i < self      yield      i += 1    end  endend
3.times do  puts "hey"endclass Fixnum  def times(&block)    i = 0    while i < self      block.call      i += 1    end  en...
3.times do           3.times do  puts "hey"           puts "hey"end                  endclass Fixnum         class Fixnum ...
3.times do |i|  puts iendclass Fixnum  def times    i = 0    while i < self      yield(i)      i += 1    end  endend
Gemshttp://rubygems.org/
$ gem install rails$ gem list$ gem uninstall bundler
Implementations
• MRI (Matz)• JRuby (java)• Rubinius (Ruby)• IronRuby (.NET)• MacRuby (Cocoa)• REE (Enterprise Edition)
Versions
1.8.7
1.9.2
Installation
WindowsRuby Installer - http://j.mp/rubywindows
Linux / Mac RVM - http://j.mp/installrvm
Live CDUbuntu - http://j.mp/railsmxlivecd
Ruby on Rails
July 2004
David Heinemeier    Hansson     @ 37signals
$ rails new isshoni -d mysql
+-isshoni/  +-app/  +-config/  +-db/  +-public/
Bundler
$ gem install bundler
Gemfile
source http://rubygems.orggem rails, 3.0.9gem mysql2, 0.2.7
$ bundle install
MVC
+-isshoni/  +-app/  | +-controllers/  | +-models/  | +-views/  +-config/  +-db/  +-public/
Models
ORMActiveRecord
Database
+-isshoni/  +-app/  +-config/  | +-database.yml  +-db/  +-public/
login: &login  adapter: mysql2  encoding: utf8  username: root  password:development:  <<: *login  database: isshoni_devel...
$ rails g model User name:string email:string
+-isshoni/  +-app/  | +-models/  | | +-user.rb  +-config/  +-db/  | +-migrate/  | | +-201107211030001_create_users.rb  +-p...
class User < ActiveRecord::Baseend
class CreateUsers < ActiveRecord::Migration  def self.up    create_table :users do |t|      t.string :name      t.string :...
$ rails g model Profile user_id:integer about:text
+-isshoni/  +-app/  | +-models/  | | +-user.rb  | | +-profile.rb  +-config/  +-db/  | +-migrate/  | | +-201107211030001_cr...
class Profile < ActiveRecord::Baseend
class CreateProfiles < ActiveRecord::Migration  def self.up    create_table :profiles do |t|      t.integer :user_id      ...
Migrations
$   rake   db:create$   rake   db:migrate$   rake   db:rollback$   rake   db:drop
Associations
has_one
class User < ActiveRecord::Base  has_one :profile, :dependent => :destroyend
@user = User.new@user.profile = Profile.new@user.profile.about = “Me”
belongs_to
class Profile < ActiveRecord::Base  belongs_to :userend
@profile.user # => #<User id:1>
has_many
class User < ActiveRecord::Base  has_many :addressesend
@user.addresses = []@user.addresses.push(Address.new)
Persistence
@user = User.new@user.save@user = User.create
@user = User.new@user.new_record? # => true@user.save@user.new_record? # => false
@user = User.create@user.new_record? # => false
@user = User.new(:name => “Raj”)@user.save@user.name # => Raj@user = User.create(:name => “Penny”)@user.name # => Penny
Callbacks
class User < ActiveRecord::Base  before_create :set_profile  private  def set_profile    self.profile = Profile.new  endend
@user = User.new@user.save@user.profile # => <#Profile id: 1, about: nil>
Validations
class User < ActiveRecord::Base  validates_presence_of :email  validates_uniqueness_of :emailend
@user = User.new@user.save # => false@user.valid? # => false@user.errors # => { :email => [“Can’t be blank”] }@user.email ...
Finders / Arel / SQL
@user = User.find(3)# => SELECT * FROM users WHERE id = 3;@user = User.find_by_name(“Joe”)# => SELECT * FROM users WHERE n...
@users = User.all# => SELECT * FROM users;@users = User.where(:name => “John”)# => SELECT * FROM users WHERE name = ‘John’...
@users = User.order(“created_at DESC”)# => SELECT * FROM users ORDER BY created_at DESC;@users = User.joins(:profile).wher...
Scopes
class User < ActiveRecord::Base  scope :with_name, where(“name IS NOT NULL”)end
User.with_name# => SELECT * from users WHERE nameIS NOT NULL;
User.with_name.where(“email = ‘foo@bar.com’”)# => SELECT * FROM users WHERE name IS NOT NULL ANDemail = ‘foo@bar.com’;
Controllers
REST
GET /usersGET /users/2
POST /usersPUT /users/2DELETE /users/2
Routing
+-isshoni/  +-app/  +-config/  | +-routes.rb  +-db/  +-public/
Isshoni::Application.routes.draw do  get /users            =>   users#index  get /users/:id        =>   users#show  get /u...
Isshoni::Application.routes.draw do  resources :usersend
Isshoni::Application.routes.draw do  resources :users, :only => [:index, :show]end
Isshoni::Application.routes.draw do  resources :users do    resources :ideas  endend# => /users/:id/ideas
Isshoni::Application.routes.draw do resources :users do   match /activate => users#activate, :on => :member endend# => /us...
Isshoni::Application.routes.draw do resources :users do   match /active => users#active, :on => :collection endend# => /us...
Actions
$ rails g controller users
+-isshoni/  +-app/  | +-controllers/  | | +-application_controller.rb  | | +-users_controller.rb  +-config/  +-db/  +-publ...
class UsersController < ApplicationControllerend
class ApplicationController < ActionController::Baseend
Isshoni::Application.routes.draw do  get /users            =>   users#index  get /users/:id        =>   users#show  get /u...
Isshoni::Application.routes.draw do  resources :usersend
# /usersusers_path# /users/:iduser_path(@user)# /users/newnew_user_path# /users/:id/editedit_user_path(@user)
class UsersController < ApplicationController  def index  end  def show  end  def new  end  def create  end  def edit  end...
class UsersController < ApplicationController  # GET /users  def index    @users = User.all  endend
class UsersController < ApplicationController  # GET /users/:id  def show    @user = User.find(params[:id])  endend
class UsersController < ApplicationController  # GET /users/new  def new    @user = User.new  endend
class UsersController < ApplicationController  # POST /users  def create    @user = User.new(params[:user])    if @user.sa...
class UsersController < ApplicationController  # GET /users/:id/edit  def edit    @user = User.find(params[:id])  endend
class UsersController < ApplicationController  # PUT /users/:id  def update    @user = User.find(params[:id])    if @user....
class UsersController < ApplicationController  # DELETE /users/:id  def destroy    @user = User.find(params[:id])    @user...
class UsersController < ApplicationController  # GET /users  def index    @users = User.all  end                          ...
Filters
class UsersController < ApplicationController  before_filter :get_user, :only => [:show, :edit, :update, :destroy]  def sh...
#   . #around (code before yield)#   . . #before#   . . . execute action#   . . -#   . #around (code after yield)#   #after
Views
ERb
<%= "Hello" %>
<p><%= 3 * 2 %></p>     <p>6</p>
<% ["Joe", "Mei"].each do |name| %>  <p>Hello <%= name %></p><% end %>
<p>Hello Joe</p><p>Hello Mei</p>
+-isshoni/  +-app/  | +-views/  | | +-users/  | | | +-index.html.erb  | | | +-new.html.erb  | | | +-edit.html.erb  | | | +...
application.html.erb
<!DOCTYPE html><html><head>  <title>Isshoni</title>  <%= stylesheet_link_tag style %>  <%= javascript_include_tag :default...
<%= stylesheet_link_tag ‘style’ %># /public/stylesheets/style.css
<%= javascript_include_tag ‘application’ %># /public/javascripts/application.js
<%= yield %>
users/index.html.erb
<h1>Users</h1><p><%= link_to Add user, new_user_path %></p><% @users.each do |user| %>  <div class="user"><%= user.name %>...
users/show.html.erb
<h1><%= @user.name %></h1><p>  <strong>Email:</strong>  <%= @user.email %></p><p>  <strong>About:</strong>  <%= @user.prof...
users/new.html.erb
<h1>Add user</h1><%= form_for @user do |f| %>  <p>    <%= f.label :name %>    <%= f.text_field :name %>  </p>  <p>    <%= ...
users/edit.html.erb
<h1>Edit user</h1><%= form_for @user do |f| %>  <p>    <%= f.label :name %>    <%= f.text_field :name %>  </p>  <p>    <%=...
Partials
<h1>Add user</h1><%= form_for @user do |f| %>  <%= render :partial => form, :object => f %><% end %>
<h1>Edit user</h1><%= form_for @user do |f| %>  <%= render :partial => form, :object => f %><% end %>
users/_form.html.erb
<p>  <%= form.label :name %>  <%= form.text_field :name %></p><p>  <%= form.label :email %>  <%= form.email_field :email %...
Nested attributes
<% form.fields_for :profile do |p| %>  <p>    <%= p.label :about %>    <%= p.text_area :about %>  </p><% end %>
class User < ActiveRecord::Base  has_one :profile, :dependent => :destroy  accepts_nested_attributes_for :profileend
Helpers
<%= link_to Add user, new_user_path %><a href=”/users/new”>Add user</a><%= form_for @user do |f| %><% end %><form action=”...
Mailers
class UserMailer < ActionMailer::Base  default :from => "no-reply@foobar.com"  def password_reset_instructions(user)    @u...
UserMailer.password_reset_instructions(@user).deliver
Security
Mass-assignment
class UsersController < ApplicationController  def create    @user = User.new(params[:user])    if @user.save      redirec...
<%= form_for @user do |f| %>  <p>    <%= f.label :username %>    <%= f.text_field :username %>  </p>  <p>    <%= f.submit ...
<%= form_for @user do |f| %>  <p>    <%= f.label :username %>    <%= f.text_field :username %>  </p>  <input type="hidden"...
# params[:user] => { :username => "joe", :is_admin => true }@user = User.new(params[:user])@user.save@user.is_admin? # => ...
class User < ActiveRecord::Base  attr_protected :is_adminend
class User < ActiveRecord::Base  attr_accessible :usernameend
SQL injection
@users = User.where("username LIKE %#{params[:username]}%")
# params[:username] = "nick OR 1 = 1 OR username LIKE %"@users = User.where("username LIKE %#{params[:username]}%")# SELEC...
# params[:username] = "nick OR 1 = 1 OR username LIKE %"@users = User.where("username LIKE ?", "%#{params[:username]}%")# ...
XSS
mysite.com                  badsite.com     POST mysite.com/delete_account
class ApplicationController < ActionController::Base  protect_from_forgeryend
<head>  <%= csrf_meta_tag %></head><head>  <meta name="csrf-param" content="authenticity_token"/>  <meta name="csrf-token"...
Log Filtering
+-isshoni/  +-app/  +-config/  +-db/  +-public/  +-log/  | +-production.log
Started POST "/sessions" for 127.0.0.1 at Sat Jun 25 19:43:44 -0500 2011  Processing by SessionsController#create as HTML ...
+-isshoni/  +-app/  +-config/  | +-application.rb  +-db/  +-public/  +-log/
module Deli  class Application < Rails::Application   config.filter_parameters += [:password]  endend
Started POST "/sessions" for 127.0.0.1 at Sat Jun 25 19:43:44 -0500 2011  Processing by SessionsController#create as HTML ...
I18n / L10n
+-isshoni/  +-app/  +-config/  | +-application.rb  +-db/  +-public/  +-log/
module Deli  class Application < Rails::Application   config.i18n.default_locale = :es  endend
<h1><%= I18n.t(home.title) %></h1><h2><%= t(home.subtitle) %></h2>
+-isshoni/  +-app/  +-config/  | +-locales/  |   | +-es.yml  +-db/  +-public/  +-log/
es:  home:    title: "Ruby en la CP"    subtitle: "Taller de RoR en CP"
<h1>Ruby en la CP</h1><h2>Taller de RoR en CP</h2>
+-isshoni/  +-app/  +-config/  | +-locales/  |   | +-es.yml  |   | +-en.yml  +-db/  +-public/  +-log/
en:  home:    title: "Ruby at CP"    subtitle: "RoR workshopt at CP"
class ApplicationController < ActionController::Base  before_filter :set_language private  def set_language    I18n.locale...
http://mysite.com/users?lang=en
<h1>Ruby at CP</h1><h2>RoR workshop at CP</h2>
Console
$ rails console
Loading development environment (Rails 3.0.9)>>
Loading development environment (Rails 3.0.7)>> User.all=> []
Loading development environment (Rails 3.0.7)>> User.all=> []>> User.create(:username => Testing)=> #<User id: 2, username...
Best practices
DRY(Don’t Repeat Yourself)
KISS(Keep It Simple Stupid)
Convention over configuration
Fat models, thin  controllers
TDD / BDD
Thanks!Edgar J. Suarez  @edgarjs
Desarrollando aplicaciones web en minutos
Upcoming SlideShare
Loading in...5
×

Desarrollando aplicaciones web en minutos

1,748

Published on

Published in: Technology
0 Comments
4 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
1,748
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
16
Comments
0
Likes
4
Embeds 0
No embeds

No notes for slide
  • \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
  • \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
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Desarrollando aplicaciones web en minutos

    1. 1. Edgar J. Suarez http://rails.mx
    2. 2. Ruby
    3. 3. 1993
    4. 4. Yukihiro Matsumoto
    5. 5. ...computer engineers, focus on the machines. They think, "By doing this, the machine will run faster. By doing this, the machine will run more effectively..." They are focusing on machines. But in fact we need to focus on humans, on how humans care about doing programming... We are the masters. They are the slaves.
    6. 6. "I hope to see Ruby help every programmer in the world to be productive, and to enjoy programming, and to be happy. That is the primary purpose of Ruby language."
    7. 7. Perl + Smalltalk + Eiffel + Lisp
    8. 8. Dynamic Typing
    9. 9. x = 1x = "hoge"x = Class
    10. 10. Duck typing
    11. 11. "When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck."
    12. 12. Readable(human friendly)
    13. 13. 3.times do |i| puts "Now i is #{i}"end@user.is_admin?@transaction.complete!
    14. 14. Flexible syntax
    15. 15. say_hello()say_hellomultiply(3, 2)multiply 3, 2
    16. 16. Reflexive(metaprogramming)
    17. 17. a = "by_name"eval <<-eos def find_#{a}(name) puts "finding by name" endeosfind_by_name("edgar") # => "finding by name"
    18. 18. Iterators / blocks
    19. 19. 5.times do puts "Hello"end[ruby, rocks].each do |word| puts wordend1.upto(3) do |i| puts iend
    20. 20. Exception handling
    21. 21. begin this_line.could_throw_an_exception!rescue Exception => e puts "Exception rescued: #{e}"end
    22. 22. Object oriented
    23. 23. person.say_hi3.to_s"a string".capitalize[].empty?nil.class # => NilClass
    24. 24. Data types
    25. 25. 3.class # => Fixnum4.24.class # => Float"Campus".class # => String[1, 2, 3, 4].class # => Array(10..15).class # => Range:name.class # => Symbol{ :name => "Maria" }.class # => Hash
    26. 26. Symbols
    27. 27. "name".object_id # => 2156968560"name".object_id # => 2156964240:name.object_id # => 68828:name.object_id # => 68828
    28. 28. Hashes
    29. 29. { "name" => "John", 2 => 54, true => "(345) 434-554"}
    30. 30. { :name => "John", :age => 54, :phone => "(345) 434-554"}
    31. 31. Automatic Garbage Collection
    32. 32. Boolean coercion(everything is true except false and nil)
    33. 33. Open classes
    34. 34. class Person def walk "walking..." endendjuan = Person.newjuan.walk # => "walking..."class Person def eat "eating..." endendjuan.eat # => "eating..."
    35. 35. Default arguments
    36. 36. def multiply(a, b = 2) a * bendmultiply 3, 4 # => 12multiply 4 # => 8
    37. 37. Splat arguments
    38. 38. def menu_list(*args) options = args.pop args.each do |arg| puts "<a href=# style=#{options[:style]}>#{arg}</a>" endendmenu_list :home, :about, :contact, {:style => "color: green;"} # => <a href=’#’ style=’color: green;’>home</a> # => <a href=’#’ style=’color: green;’>about</a> # => <a href=’#’ style=’color: green;’>contact</a>menu_list :home, :about, {:style => "color: green;"} # => <a href=’#’ style=’color: green;’>home</a> # => <a href=’#’ style=’color: green;’>about</a>
    39. 39. Attributes
    40. 40. class Person def name=(name) @name = name end def name @name endenda = Person.newa.name = "Pepe"a.name # => Pepe
    41. 41. class Person attr_accessor :name attr_reader :age attr_writer :phoneend
    42. 42. “Class” methods
    43. 43. class Number def self.sum(a, b) a + b end def Number.pow(a, b) a ** b endendNumber.sum(2, 2) # => 4Number.pow(4, 2) # => 16
    44. 44. Self
    45. 45. class Number def self.base 10 end def self.parse(str) str.to_i(self.base) endendNumber.parse("30") # => 30
    46. 46. class Person attr_accessor :first_name, :last_name def full_name "#{self.first_name} #{self.last_name}" endendraul = Person.newraul.first_name = "Raul"raul.last_name = "Mendez"raul.full_name # => Raul Mendez
    47. 47. Inheritance
    48. 48. class Shape def area @a * @b endendclass Square < Shapeendsq = Square.newsq.area
    49. 49. class Shape def area @a * @b endendclass Square < Shape def area    if @a == @b @a * @a else super end endendsq = Square.newsq.area
    50. 50. Mixins
    51. 51. module Walkable def walk puts "Im walking" endendmodule Runnable def run puts "Im running" endendclass Person include Walkable include Runnableendjoe = Person.newjoe.walk # => Im walkingjoe.run # => Im running
    52. 52. module Summable def sum(a, b) a + b endendclass Number extend SummableendNumber.sum 2, 4 # => 6
    53. 53. Namespaces
    54. 54. module ActiveRecord class Base endendActiveRecord::Base.new
    55. 55. Blocks
    56. 56. 3.times do puts "hey"end3.times { puts "hey" }
    57. 57. 3.times do puts "hey"endclass Fixnum def times i = 0 while i < self yield i += 1 end endend
    58. 58. 3.times do puts "hey"endclass Fixnum def times(&block) i = 0 while i < self block.call i += 1 end endend
    59. 59. 3.times do 3.times do puts "hey" puts "hey"end endclass Fixnum class Fixnum def times def times(&block) i = 0 i = 0 while i < self while i < self yield block.call i += 1 i += 1 end end end endend end
    60. 60. 3.times do |i| puts iendclass Fixnum def times i = 0 while i < self yield(i) i += 1 end endend
    61. 61. Gemshttp://rubygems.org/
    62. 62. $ gem install rails$ gem list$ gem uninstall bundler
    63. 63. Implementations
    64. 64. • MRI (Matz)• JRuby (java)• Rubinius (Ruby)• IronRuby (.NET)• MacRuby (Cocoa)• REE (Enterprise Edition)
    65. 65. Versions
    66. 66. 1.8.7
    67. 67. 1.9.2
    68. 68. Installation
    69. 69. WindowsRuby Installer - http://j.mp/rubywindows
    70. 70. Linux / Mac RVM - http://j.mp/installrvm
    71. 71. Live CDUbuntu - http://j.mp/railsmxlivecd
    72. 72. Ruby on Rails
    73. 73. July 2004
    74. 74. David Heinemeier Hansson @ 37signals
    75. 75. $ rails new isshoni -d mysql
    76. 76. +-isshoni/ +-app/ +-config/ +-db/ +-public/
    77. 77. Bundler
    78. 78. $ gem install bundler
    79. 79. Gemfile
    80. 80. source http://rubygems.orggem rails, 3.0.9gem mysql2, 0.2.7
    81. 81. $ bundle install
    82. 82. MVC
    83. 83. +-isshoni/ +-app/ | +-controllers/ | +-models/ | +-views/ +-config/ +-db/ +-public/
    84. 84. Models
    85. 85. ORMActiveRecord
    86. 86. Database
    87. 87. +-isshoni/ +-app/ +-config/ | +-database.yml +-db/ +-public/
    88. 88. login: &login  adapter: mysql2  encoding: utf8  username: root  password:development: <<: *login  database: isshoni_developmenttest: <<: *login  database: isshoni_testproduction: <<: *login  database: isshoni_production
    89. 89. $ rails g model User name:string email:string
    90. 90. +-isshoni/ +-app/ | +-models/ | | +-user.rb +-config/ +-db/ | +-migrate/ | | +-201107211030001_create_users.rb +-public/
    91. 91. class User < ActiveRecord::Baseend
    92. 92. class CreateUsers < ActiveRecord::Migration def self.up create_table :users do |t| t.string :name t.string :email t.timestamps end end def self.down drop_table :users endend
    93. 93. $ rails g model Profile user_id:integer about:text
    94. 94. +-isshoni/ +-app/ | +-models/ | | +-user.rb | | +-profile.rb +-config/ +-db/ | +-migrate/ | | +-201107211030001_create_users.rb | | +-201107211035002_create_profiles.rb +-public/
    95. 95. class Profile < ActiveRecord::Baseend
    96. 96. class CreateProfiles < ActiveRecord::Migration def self.up create_table :profiles do |t| t.integer :user_id t.text :about t.timestamps end end def self.down drop_table :profiles endend
    97. 97. Migrations
    98. 98. $ rake db:create$ rake db:migrate$ rake db:rollback$ rake db:drop
    99. 99. Associations
    100. 100. has_one
    101. 101. class User < ActiveRecord::Base has_one :profile, :dependent => :destroyend
    102. 102. @user = User.new@user.profile = Profile.new@user.profile.about = “Me”
    103. 103. belongs_to
    104. 104. class Profile < ActiveRecord::Base belongs_to :userend
    105. 105. @profile.user # => #<User id:1>
    106. 106. has_many
    107. 107. class User < ActiveRecord::Base has_many :addressesend
    108. 108. @user.addresses = []@user.addresses.push(Address.new)
    109. 109. Persistence
    110. 110. @user = User.new@user.save@user = User.create
    111. 111. @user = User.new@user.new_record? # => true@user.save@user.new_record? # => false
    112. 112. @user = User.create@user.new_record? # => false
    113. 113. @user = User.new(:name => “Raj”)@user.save@user.name # => Raj@user = User.create(:name => “Penny”)@user.name # => Penny
    114. 114. Callbacks
    115. 115. class User < ActiveRecord::Base before_create :set_profile private def set_profile self.profile = Profile.new endend
    116. 116. @user = User.new@user.save@user.profile # => <#Profile id: 1, about: nil>
    117. 117. Validations
    118. 118. class User < ActiveRecord::Base validates_presence_of :email validates_uniqueness_of :emailend
    119. 119. @user = User.new@user.save # => false@user.valid? # => false@user.errors # => { :email => [“Can’t be blank”] }@user.email = “foo@bar.com”@user.save # => true
    120. 120. Finders / Arel / SQL
    121. 121. @user = User.find(3)# => SELECT * FROM users WHERE id = 3;@user = User.find_by_name(“Joe”)# => SELECT * FROM users WHERE name = ‘Joe’ LIMIT 1;@user = User.first# => SELECT * FROM users LIMIT 1;
    122. 122. @users = User.all# => SELECT * FROM users;@users = User.where(:name => “John”)# => SELECT * FROM users WHERE name = ‘John’;@users = User.where(“name LIKE ?”, “Jo%”)# => SELECT * FROM users WHERE name LIKE ‘Jo%’;
    123. 123. @users = User.order(“created_at DESC”)# => SELECT * FROM users ORDER BY created_at DESC;@users = User.joins(:profile).where(“profiles.about IS NULL”)# => SELECT * FROM users LEFT OUTER JOIN profiles ON users.id =profiles.user_id WHERE profiles.about IS NULL;
    124. 124. Scopes
    125. 125. class User < ActiveRecord::Base scope :with_name, where(“name IS NOT NULL”)end
    126. 126. User.with_name# => SELECT * from users WHERE nameIS NOT NULL;
    127. 127. User.with_name.where(“email = ‘foo@bar.com’”)# => SELECT * FROM users WHERE name IS NOT NULL ANDemail = ‘foo@bar.com’;
    128. 128. Controllers
    129. 129. REST
    130. 130. GET /usersGET /users/2
    131. 131. POST /usersPUT /users/2DELETE /users/2
    132. 132. Routing
    133. 133. +-isshoni/ +-app/ +-config/ | +-routes.rb +-db/ +-public/
    134. 134. Isshoni::Application.routes.draw do get /users => users#index get /users/:id => users#show get /users/new => users#new post /users => users#create get /users/:id/edit => users#edit put /users/:id => users#update delete /users/:id => users#destroyend
    135. 135. Isshoni::Application.routes.draw do resources :usersend
    136. 136. Isshoni::Application.routes.draw do resources :users, :only => [:index, :show]end
    137. 137. Isshoni::Application.routes.draw do resources :users do resources :ideas endend# => /users/:id/ideas
    138. 138. Isshoni::Application.routes.draw do resources :users do match /activate => users#activate, :on => :member endend# => /users/:id/activate
    139. 139. Isshoni::Application.routes.draw do resources :users do match /active => users#active, :on => :collection endend# => /users/active
    140. 140. Actions
    141. 141. $ rails g controller users
    142. 142. +-isshoni/ +-app/ | +-controllers/ | | +-application_controller.rb | | +-users_controller.rb +-config/ +-db/ +-public/
    143. 143. class UsersController < ApplicationControllerend
    144. 144. class ApplicationController < ActionController::Baseend
    145. 145. Isshoni::Application.routes.draw do get /users => users#index get /users/:id => users#show get /users/new => users#new post /users => users#create get /users/:id/edit => users#edit put /users/:id => users#update delete /users/:id => users#destroyend
    146. 146. Isshoni::Application.routes.draw do resources :usersend
    147. 147. # /usersusers_path# /users/:iduser_path(@user)# /users/newnew_user_path# /users/:id/editedit_user_path(@user)
    148. 148. class UsersController < ApplicationController def index end def show end def new end def create end def edit end def update end def destroy endend
    149. 149. class UsersController < ApplicationController # GET /users def index @users = User.all endend
    150. 150. class UsersController < ApplicationController # GET /users/:id def show @user = User.find(params[:id]) endend
    151. 151. class UsersController < ApplicationController # GET /users/new def new @user = User.new endend
    152. 152. class UsersController < ApplicationController # POST /users def create @user = User.new(params[:user])    if @user.save redirect_to users_path else render :new end endend
    153. 153. class UsersController < ApplicationController # GET /users/:id/edit def edit @user = User.find(params[:id]) endend
    154. 154. class UsersController < ApplicationController # PUT /users/:id def update @user = User.find(params[:id])    if @user.update_attributes(params[:user]) redirect_to user_path(@user) else render :edit end endend
    155. 155. class UsersController < ApplicationController # DELETE /users/:id def destroy @user = User.find(params[:id]) @user.destroy redirect_to users_path endend
    156. 156. class UsersController < ApplicationController # GET /users def index @users = User.all end # GET /users/:id/edit # GET /users/:id def edit def show @user = User.find(params[:id]) @user = User.find(params[:id]) end end # PUT /users/:id # GET /users/new def update def new @user = User.find(params[:id]) @user = User.new     if end @user.update_attributes(params[:user]) redirect_to user_path(@user) # POST /users else def create render :edit @user = User.new(params[:user]) end    if @user.save end redirect_to users_path else # DELETE /users/:id render :new def destroy end @user = User.find(params[:id]) end @user.destroy redirect_to users_path end end
    157. 157. Filters
    158. 158. class UsersController < ApplicationController before_filter :get_user, :only => [:show, :edit, :update, :destroy] def show end def edit end def update    if @user.update_attributes(params[:user]) redirect_to user_path(@user) else render :edit end end def destroy @user.destroy redirect_to users_path end private def get_user @user = User.find(params[:id]) endend
    159. 159. # . #around (code before yield)# . . #before# . . . execute action# . . -# . #around (code after yield)# #after
    160. 160. Views
    161. 161. ERb
    162. 162. <%= "Hello" %>
    163. 163. <p><%= 3 * 2 %></p> <p>6</p>
    164. 164. <% ["Joe", "Mei"].each do |name| %> <p>Hello <%= name %></p><% end %>
    165. 165. <p>Hello Joe</p><p>Hello Mei</p>
    166. 166. +-isshoni/ +-app/ | +-views/ | | +-users/ | | | +-index.html.erb | | | +-new.html.erb | | | +-edit.html.erb | | | +-show.html.erb | | | +-_form.html.erb | | +-layouts/ | | | +-application.html.erb +-config/ +-db/ +-public/
    167. 167. application.html.erb
    168. 168. <!DOCTYPE html><html><head> <title>Isshoni</title> <%= stylesheet_link_tag style %> <%= javascript_include_tag :defaults %></head><body> <%= yield %></body></html>
    169. 169. <%= stylesheet_link_tag ‘style’ %># /public/stylesheets/style.css
    170. 170. <%= javascript_include_tag ‘application’ %># /public/javascripts/application.js
    171. 171. <%= yield %>
    172. 172. users/index.html.erb
    173. 173. <h1>Users</h1><p><%= link_to Add user, new_user_path %></p><% @users.each do |user| %> <div class="user"><%= user.name %></div><% end %>
    174. 174. users/show.html.erb
    175. 175. <h1><%= @user.name %></h1><p> <strong>Email:</strong> <%= @user.email %></p><p> <strong>About:</strong> <%= @user.profile.about %></p>
    176. 176. users/new.html.erb
    177. 177. <h1>Add user</h1><%= form_for @user do |f| %> <p> <%= f.label :name %> <%= f.text_field :name %> </p> <p> <%= f.label :email %> <%= f.email_field :email %> </p> <% f.fields_for :profile do |p| %> <p> <%= p.label :about %> <%= p.text_area :about %> </p> <% end %> <p> <%= f.submit %> </p><% end %>
    178. 178. users/edit.html.erb
    179. 179. <h1>Edit user</h1><%= form_for @user do |f| %> <p> <%= f.label :name %> <%= f.text_field :name %> </p> <p> <%= f.label :email %> <%= f.email_field :email %> </p> <% f.fields_for :profile do |p| %> <p> <%= p.label :about %> <%= p.text_area :about %> </p> <% end %> <p> <%= f.submit %> </p><% end %>
    180. 180. Partials
    181. 181. <h1>Add user</h1><%= form_for @user do |f| %> <%= render :partial => form, :object => f %><% end %>
    182. 182. <h1>Edit user</h1><%= form_for @user do |f| %> <%= render :partial => form, :object => f %><% end %>
    183. 183. users/_form.html.erb
    184. 184. <p> <%= form.label :name %> <%= form.text_field :name %></p><p> <%= form.label :email %> <%= form.email_field :email %></p><% form.fields_for :profile do |p| %> <p> <%= p.label :about %> <%= p.text_area :about %> </p><% end %><p> <%= form.submit %></p>
    185. 185. Nested attributes
    186. 186. <% form.fields_for :profile do |p| %> <p> <%= p.label :about %> <%= p.text_area :about %> </p><% end %>
    187. 187. class User < ActiveRecord::Base has_one :profile, :dependent => :destroy accepts_nested_attributes_for :profileend
    188. 188. Helpers
    189. 189. <%= link_to Add user, new_user_path %><a href=”/users/new”>Add user</a><%= form_for @user do |f| %><% end %><form action=”/users” method=”post”></form><%= text_field_tag :name %><input type=”text” name=”name” id=”name” /><%= javascript_include_tag application %><script type=”text/javascript” src=”/javascripts/application.js”></script><%= image_tag background.png %><img src=”/images/background.png” alt=”background” />
    190. 190. Mailers
    191. 191. class UserMailer < ActionMailer::Base default :from => "no-reply@foobar.com" def password_reset_instructions(user) @user = user mail :to => @user.email, :subject => "Password Reset" endend
    192. 192. UserMailer.password_reset_instructions(@user).deliver
    193. 193. Security
    194. 194. Mass-assignment
    195. 195. class UsersController < ApplicationController def create @user = User.new(params[:user])    if @user.save redirect_to users_path else render :new end endend
    196. 196. <%= form_for @user do |f| %> <p> <%= f.label :username %> <%= f.text_field :username %> </p> <p> <%= f.submit %> </p><% end %>
    197. 197. <%= form_for @user do |f| %> <p> <%= f.label :username %> <%= f.text_field :username %> </p> <input type="hidden" name="user[is_admin]" value="1" /> <p> <%= f.submit %> </p><% end %>
    198. 198. # params[:user] => { :username => "joe", :is_admin => true }@user = User.new(params[:user])@user.save@user.is_admin? # => true
    199. 199. class User < ActiveRecord::Base attr_protected :is_adminend
    200. 200. class User < ActiveRecord::Base attr_accessible :usernameend
    201. 201. SQL injection
    202. 202. @users = User.where("username LIKE %#{params[:username]}%")
    203. 203. # params[:username] = "nick OR 1 = 1 OR username LIKE %"@users = User.where("username LIKE %#{params[:username]}%")# SELECT * FROM users WHERE username LIKE %nick OR 1 = 1 OR username LIKE %;
    204. 204. # params[:username] = "nick OR 1 = 1 OR username LIKE %"@users = User.where("username LIKE ?", "%#{params[:username]}%")# SELECT * FROM users WHERE username LIKE nick OR 1 = 1 OR username LIKE %;
    205. 205. XSS
    206. 206. mysite.com badsite.com POST mysite.com/delete_account
    207. 207. class ApplicationController < ActionController::Base protect_from_forgeryend
    208. 208. <head> <%= csrf_meta_tag %></head><head> <meta name="csrf-param" content="authenticity_token"/> <meta name="csrf-token" content="W8oH32123LgvCYNlVjQXsPAcLigB8CtX8eXYBGyp3yE="/></head>
    209. 209. Log Filtering
    210. 210. +-isshoni/ +-app/ +-config/ +-db/ +-public/ +-log/ | +-production.log
    211. 211. Started POST "/sessions" for 127.0.0.1 at Sat Jun 25 19:43:44 -0500 2011 Processing by SessionsController#create as HTML Parameters: {"password"=>"123456", "email"=>"foo@bar.com"} SQL (0.5ms) SHOW TABLES Account Load (0.2ms) SELECT `accounts`.* FROM `accounts` WHERE`accounts`.`email` = foo@bar.com LIMIT 1Completed 200 OK in 274ms (Views: 66.3ms | ActiveRecord: 0.7ms)
    212. 212. +-isshoni/ +-app/ +-config/ | +-application.rb +-db/ +-public/ +-log/
    213. 213. module Deli class Application < Rails::Application config.filter_parameters += [:password] endend
    214. 214. Started POST "/sessions" for 127.0.0.1 at Sat Jun 25 19:43:44 -0500 2011 Processing by SessionsController#create as HTML Parameters: {"password"=>"[FILTERED]", "email"=>"foo@bar.com"} SQL (0.5ms) SHOW TABLES Account Load (0.2ms) SELECT `accounts`.* FROM `accounts` WHERE`accounts`.`email` = foo@bar.com LIMIT 1Completed 200 OK in 274ms (Views: 66.3ms | ActiveRecord: 0.7ms)
    215. 215. I18n / L10n
    216. 216. +-isshoni/ +-app/ +-config/ | +-application.rb +-db/ +-public/ +-log/
    217. 217. module Deli class Application < Rails::Application config.i18n.default_locale = :es endend
    218. 218. <h1><%= I18n.t(home.title) %></h1><h2><%= t(home.subtitle) %></h2>
    219. 219. +-isshoni/ +-app/ +-config/ | +-locales/ | | +-es.yml +-db/ +-public/ +-log/
    220. 220. es:  home:    title: "Ruby en la CP"    subtitle: "Taller de RoR en CP"
    221. 221. <h1>Ruby en la CP</h1><h2>Taller de RoR en CP</h2>
    222. 222. +-isshoni/ +-app/ +-config/ | +-locales/ | | +-es.yml | | +-en.yml +-db/ +-public/ +-log/
    223. 223. en:  home:    title: "Ruby at CP"    subtitle: "RoR workshopt at CP"
    224. 224. class ApplicationController < ActionController::Base before_filter :set_language private def set_language I18n.locale = params[:lang].to_sym if params[:lang] endend
    225. 225. http://mysite.com/users?lang=en
    226. 226. <h1>Ruby at CP</h1><h2>RoR workshop at CP</h2>
    227. 227. Console
    228. 228. $ rails console
    229. 229. Loading development environment (Rails 3.0.9)>>
    230. 230. Loading development environment (Rails 3.0.7)>> User.all=> []
    231. 231. Loading development environment (Rails 3.0.7)>> User.all=> []>> User.create(:username => Testing)=> #<User id: 2, username: "Testing", email: nil>
    232. 232. Best practices
    233. 233. DRY(Don’t Repeat Yourself)
    234. 234. KISS(Keep It Simple Stupid)
    235. 235. Convention over configuration
    236. 236. Fat models, thin controllers
    237. 237. TDD / BDD
    238. 238. Thanks!Edgar J. Suarez @edgarjs
    1. A particular slide catching your eye?

      Clipping is a handy way to collect important slides you want to go back to later.

    ×