Your SlideShare is downloading. ×
0
Web Development withRuby On RailsPedro Cunha
RubyYukihiro "Matz" Matsumoto       Ruby is designed for programmer                    productivity and fun               ...
RubyEverything is an object     Dynamic Typing true.class # TrueClass   class Foo
 nil.class # NilClass       def initia...
Rubyclass Foo                        class Bar  # Parenthesis can be omitted     # Use ! if you change self  def method   ...
Ruby"hello".class # String:hello.class # Symbol          a = "Hello"                               b = "Hello"# Convention...
Rubya = {}a[:first] = 2a[:things] = 3a[:foo] = "bar"b = {        :first => 2,        :things => 3,        :foo => "bar"}b[...
Rubyx = [1,4,5,2,5,8,10]x.sort # returns a copy of x sorted[1,2,4,5,5,8,10]x.sort! # modifies selfx.map{ |i| i + 4 } # [5,...
Ruby             Monkey Patchingclass String  def +()    # override string default + operator  endend              “With g...
Ruby on Rails
Ruby on RailsCreated by David Heinemeir Hansson• CEO at 37th Signals• Personal Project, 2004Present• Rails 3.1• Growing co...
Ruby on RailsConvention vs ConfigurationMVC ArchitectureREST routing
Conventionvs Configuration
• Don’t Repeat Yourself• Increased productivity through  conventions. Ex.: following a pattern for  foreign key columns.• ...
MVC
RoR
RESTRepresentational State Transfer
CRUD      REST ROUTESCREATE   POST /postsREAD     GET    /posts/1UPDATE   PUT    /posts/1DELETE   DELETE /posts/1
# routes.rbBlog::Application.routes.draw do  resources :postsend
RoRStarting development
pcunha:prompt$ rails new Blog -d mysqlBlog /app       /controllers       /mailers       /models       /views /config      ...
# config/database.ymldevelopment:  adapter: sqlite3  database: db/development.sqlite3test:  adapter: sqlite3  database: db...
development:  adapter: mysql2  encoding: utf8  database: Blog_development  username: root  password:test:  adapter: mysql2...
pcunha:Blog$ rails server=> Booting WEBrick=> Rails 3.0.7 application starting indevelopment on http://0.0.0.0:3000=> Call...
localhost:3000
ModelDatabase Schema
pcunha:Blog$ rails generate scaffold Post title:string body:text     invoke   active_record     create     db/migrate/2011...
# config/db/migrate/20110715102126_create_posts.rbclass CreatePosts < ActiveRecord::Migration  def self.up    create_table...
pcunha:Blog$ rake db:createpcunha:Blog$ rake db:migrate==    CreatePosts: migrating-- create_table(:posts)     -> 0.0015s=...
pcunha:Blog$ rails generate model Comment body:text invoke   active_record create     db/migrate/20110715103725_create_com...
# 20110715103834_add_post_id_to_comments.rbclass AddPostIdToComments < ActiveRecord::Migration  def self.up    add_column ...
pcunha:Blog$ rake db:migrate==    CreateComments: migrating-- create_table(:comments)     -> 0.0011s==    CreateComments: ...
rake   db:createrake   db:migraterake   db:migrate:redorake   db:rollbackblog_db.schema_migrations- keeps the version numb...
Model Relations
# app/models/post.rbclass Post < ActiveRecord::Base  has_many :commentsend# app/models/comment.rbclass Comment < ActiveRec...
Model Validations
# app/models/post.rbclass Post < ActiveRecord::Base  has_many :comments  validates_presence_of :title  validates_format_of...
validates_presence_of :nifvalidates_format_of :namevalidates_acceptance_of :terms_and_conditions, :on => :createvalidates_...
Controllers  Managing the CRUD
# app/controllers/posts_controller.rbclass PostsController < ApplicationController  # GET /posts  def index ...  # GET /po...
# POST /posts  # POST /posts.xml  def create    @post = Post.new(params[:post])    respond_to do |format|      if @post.sa...
def index   @posts = Post.all   respond_to do |format|     format.html # index.html.erb     format.xml { render :xml => @p...
Views
# app/views/posts/new.html.erb                                        <h1>New post</h1>                                   ...
# app/views/posts/edit.html.erb                                        <h1>Edit post</h1>                                 ...
Rails builds the route for youlink_to Show, @post   # GET posts/@post.idform_for(@post)if @post.new_record? POST /postsels...
Views Partials
# app/views/posts/new.html.erb      # app/views/posts/edit.html.erb<h1>New post</h1>                   <h1>Edit post</h1><...
# app/views/posts/_form.html.erb# app/views/posts/new.html.erb                                    <%= form_for(@post) do |...
AJAXImprove user experience
Improve user experience by not having thewhole page reload when submitting a formor simple pagination linkAlso save resour...
AJAXChanging default forms to AJAX
# config/routes.rbBlog::Application.routes.draw do  resources :posts do    resources :comments, :only => [:create]  endend...
# app/controllers/comments_controller.rbclass CommentsController < ApplicationController  def create    @post = Post.find(...
# app/views/posts/show.html.erb...<h1>Comments</h1><div id="comments">  <%= render :partial => "comments/comment",        ...
# app/views/comments/_form.html.erb<%= form_for [post,comment] do |f| %>  <div class="field">    <%= f.label :body %><br /...
# app/views/comments/_form.html.erb<%= form_for [post,comment], :remote => true do |f| %>  <div class="field">    <%= f.la...
# app/controllers/comments_controller.rbclass CommentsController < ApplicationController  def create    @post = Post.find(...
# app/views/comments/create.js.erb//Dump javascript here!document.getElementById...Notice:- create.js.erb- writing native ...
Rails 2.X and 3.0.X- Prototype JS Framework as defaultRails 3.1 (released 2011)- jQuery JS Framework as default
# app/views/comments/create.js.erb<% if @comment.new_record? %>  <% content = render(:partial => "comments/form",         ...
Almost there... but- Complex code- We can do better with Rails
RJSRuby (to) JavaScript Templates
# app/views/comments/create.js.rjsif @comment.new_record?  page.replace :new_comment,               :partial => "comments/...
Gems
GemsExtend Rails frameworkEasy installation and usageIncreasing community • Github • Gemcutter
Bundler gem# Gemfilegem "rails", "2.3.10"gem "will_paginate"gem "authlogic"gem "pg"gem "postgis_adapter", "0.7.8"gem "GeoR...
Questions ?
Referenceshttp://rubyonrails.org/http://railsapi.com/http://railscasts.com/http://railsforzombies.org/
References
Thanks :)pedro.cunha@rupeal.com        @mryise
Upcoming SlideShare
Loading in...5
×

Ruby on Rails at PROMPT ISEL '11

1,456

Published on

An introduction to Ruby on Rails. Presentation made at PROMP, a pos-graduation on ISEL university at Portugal.

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

  • Be the first to like this

No Downloads
Views
Total Views
1,456
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
22
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Transcript of "Ruby on Rails at PROMPT ISEL '11"

  1. 1. Web Development withRuby On RailsPedro Cunha
  2. 2. RubyYukihiro "Matz" Matsumoto Ruby is designed for programmer productivity and fun Created February 1993
  3. 3. RubyEverything is an object Dynamic Typing true.class # TrueClass class Foo
 nil.class # NilClass def initialize(x, y)
 @x = x @y = y end end class Foo2 end Foo.new(2, Foo2.new)
  4. 4. Rubyclass Foo class Bar # Parenthesis can be omitted # Use ! if you change self def method def method! puts "Hello World" end end # Use ? if you return a boolean # Default params def method? def method2(x = 2) end puts x end # Only conventions end # Operator overload def +(x) endend
  5. 5. Ruby"hello".class # String:hello.class # Symbol a = "Hello" b = "Hello"# Convention# Use string if you plan to a.equal? b # falsecompute text x = :hello# Use symbols if you want to y = :hellodefine or/and set abehaviour which is not x.equal? y # trueexpected to change
  6. 6. Rubya = {}a[:first] = 2a[:things] = 3a[:foo] = "bar"b = { :first => 2, :things => 3, :foo => "bar"}b[:first] # 2
  7. 7. Rubyx = [1,4,5,2,5,8,10]x.sort # returns a copy of x sorted[1,2,4,5,5,8,10]x.sort! # modifies selfx.map{ |i| i + 4 } # [5,6,8,9,9,12,14]x.map! do |i| i + 4end # [5,6,8,9,9,12,14]
  8. 8. Ruby Monkey Patchingclass String def +() # override string default + operator endend “With great power comes great responsability” Uncle Ben, Amazing Spiderman nº1
  9. 9. Ruby on Rails
  10. 10. Ruby on RailsCreated by David Heinemeir Hansson• CEO at 37th Signals• Personal Project, 2004Present• Rails 3.1• Growing community
  11. 11. Ruby on RailsConvention vs ConfigurationMVC ArchitectureREST routing
  12. 12. Conventionvs Configuration
  13. 13. • Don’t Repeat Yourself• Increased productivity through conventions. Ex.: following a pattern for foreign key columns.• Take advantage of singular and plural word meanings
  14. 14. MVC
  15. 15. RoR
  16. 16. RESTRepresentational State Transfer
  17. 17. CRUD REST ROUTESCREATE POST /postsREAD GET /posts/1UPDATE PUT /posts/1DELETE DELETE /posts/1
  18. 18. # routes.rbBlog::Application.routes.draw do resources :postsend
  19. 19. RoRStarting development
  20. 20. pcunha:prompt$ rails new Blog -d mysqlBlog /app /controllers /mailers /models /views /config database.yml /db /migrate Gemfile /public /javascripts /stylesheets
  21. 21. # config/database.ymldevelopment: adapter: sqlite3 database: db/development.sqlite3test: adapter: sqlite3 database: db/test.sqlite3production: adapter: sqlite3 database: db/production.sqlite3
  22. 22. development: adapter: mysql2 encoding: utf8 database: Blog_development username: root password:test: adapter: mysql2 encoding: utf8 database: Blog_test username: root password:production: adapter: mysql2 encoding: utf8 database: Blog_production username: root password: rails new with mysql option
  23. 23. pcunha:Blog$ rails server=> Booting WEBrick=> Rails 3.0.7 application starting indevelopment on http://0.0.0.0:3000=> Call with -d to detach=> Ctrl-C to shutdown server
  24. 24. localhost:3000
  25. 25. ModelDatabase Schema
  26. 26. pcunha:Blog$ rails generate scaffold Post title:string body:text invoke active_record create db/migrate/20110715102126_create_posts.rb create app/models/post.rb invoke test_unit create test/unit/post_test.rb create test/fixtures/posts.yml invoke scaffold_controller create app/controllers/posts_controller.rb invoke erb create app/views/posts create app/views/posts/index.html.erb create app/views/posts/edit.html.erb create app/views/posts/show.html.erb create app/views/posts/new.html.erb create app/views/posts/_form.html.erb
  27. 27. # config/db/migrate/20110715102126_create_posts.rbclass CreatePosts < ActiveRecord::Migration def self.up create_table :posts do |t| t.string :title t.text :body t.timestamps end end def self.down drop_table :posts endend
  28. 28. pcunha:Blog$ rake db:createpcunha:Blog$ rake db:migrate== CreatePosts: migrating-- create_table(:posts) -> 0.0015s== CreatePosts: migrated (0.0018s)
  29. 29. pcunha:Blog$ rails generate model Comment body:text invoke active_record create db/migrate/20110715103725_create_comments.rb create app/models/comment.rb invoke test_unit create test/unit/comment_test.rb create test/fixtures/comments.ymlpcunha:Blog$ rails generate migration AddPostIdToCommentspost_id:integer invoke active_record create db/migrate/20110715103834_add_post_id_to_comments.rb
  30. 30. # 20110715103834_add_post_id_to_comments.rbclass AddPostIdToComments < ActiveRecord::Migration def self.up add_column :comments, :post_id, :integer end def self.down remove_column :comments, :post_id endend
  31. 31. pcunha:Blog$ rake db:migrate== CreateComments: migrating-- create_table(:comments) -> 0.0011s== CreateComments: migrated (0.0012s)== AddPostIdToComments: migrating-- add_column(:comments, :post_id, :integer) -> 0.0011s== AddPostIdToComments: migrated (0.0041s)
  32. 32. rake db:createrake db:migraterake db:migrate:redorake db:rollbackblog_db.schema_migrations- keeps the version number of allmigrations already runned
  33. 33. Model Relations
  34. 34. # app/models/post.rbclass Post < ActiveRecord::Base has_many :commentsend# app/models/comment.rbclass Comment < ActiveRecord::Base belongs_to :postendPost.allPost.find(1).commentsComments.find(1).postPost.order(:created_at)Post.limit(5).offset(2)
  35. 35. Model Validations
  36. 36. # app/models/post.rbclass Post < ActiveRecord::Base has_many :comments validates_presence_of :title validates_format_of :title, :with => /ASLB.*z/endp = Post.newp.save # falsep.errors.full_messages # ["Title cant be blank", "Titleis invalid"]p.title = "SLB is the best"p.save # true
  37. 37. validates_presence_of :nifvalidates_format_of :namevalidates_acceptance_of :terms_and_conditions, :on => :createvalidates_numericality_of :age, :greater_than_or_equal_to => 18validates_uniqueness_of :model_fk_key, :scope => :model_fk_key2validates_length_of :minimum => 5
  38. 38. Controllers Managing the CRUD
  39. 39. # app/controllers/posts_controller.rbclass PostsController < ApplicationController # GET /posts def index ... # GET /posts/1 def show ... # GET /posts/new def new ... # GET /posts/1/edit def edit ... # POST /posts def create ... # PUT /posts/1 def update ... # DELETE /posts/1 def destroy ...end Generated with scaffold
  40. 40. # POST /posts # POST /posts.xml def create @post = Post.new(params[:post]) respond_to do |format| if @post.save format.html { redirect_to(@post, :notice => Post wassuccessfully created.) } format.xml { render :xml => @post, :status=> :created, :location => @post } else format.html { render :action => "new" } format.xml { render :xml => @post.errors, :status=> :unprocessable_entity } end end end
  41. 41. def index @posts = Post.all respond_to do |format| format.html # index.html.erb format.xml { render :xml => @posts } end endpcunha:Blog$ curl http://localhost:3000/posts.xml<?xml version="1.0" encoding="UTF-8"?><posts type="array"> <post> <created-at type="datetime">2011-07-15T13:39:51Z</created-at> <body>This is the body of the first post</body> <title>The first very post of this blog</title> <updated-at type="datetime">2011-07-15T13:39:51Z</updated-at> <id type="integer">1</id> </post></posts>
  42. 42. Views
  43. 43. # app/views/posts/new.html.erb <h1>New post</h1> <%= form_for(@post) do |f| %># app/controllers/posts_controller.rbdef new <div class="field"> @post = Post.new <%= f.label :title %><br /> respond_to do |format| <%= f.text_field :title %> format.html # new.html.erb} </div> end <div class="field"> <%= f.label :body %><br />end <%= f.text_area :body %> </div> <div class="actions"> <%= f.submit %> </div> <% end %> <%= link_to Back, posts_path %>
  44. 44. # app/views/posts/edit.html.erb <h1>Edit post</h1> <%= form_for(@post) do |f| %> <div class="field"> <%= f.label :title %><br /># app/controllers/posts_controller.rb <%= f.text_field :title %>def edit </div> @post = Post.find(params[:id]) <div class="field"> respond_to do |format| <%= f.label :body %><br /> format.html # edit.html.erb} <%= f.text_area :body %> end </div> <div class="actions">end <%= f.submit %> </div> <% end %> <%= link_to Show, @post %> | <%= link_to Back, posts_path %>
  45. 45. Rails builds the route for youlink_to Show, @post # GET posts/@post.idform_for(@post)if @post.new_record? POST /postselse PUT /posts/@post.idend
  46. 46. Views Partials
  47. 47. # app/views/posts/new.html.erb # app/views/posts/edit.html.erb<h1>New post</h1> <h1>Edit post</h1><%= form_for(@post) do |f| %> <%= form_for(@post) do |f| %> <div class="field"> <div class="field"> <%= f.label :title %><br /> <%= f.label :title %><br /> <%= f.text_field :title %> <%= f.text_field :title %> </div> </div> <div class="field"> <div class="field"> <%= f.label :body %><br /> <%= f.label :body %><br /> <%= f.text_area :body %> <%= f.text_area :body %> </div> </div> <div class="actions"> <div class="actions"> <%= f.submit %> <%= f.submit %> </div> </div><% end %> <% end %><%= link_to Back, posts_path %> <%= link_to Show, @post %> | <%= link_to Back, posts_path %> Bad pattern
  48. 48. # app/views/posts/_form.html.erb# app/views/posts/new.html.erb <%= form_for(@post) do |f| %><h1>New post</h1> <div class="field"><%= render "form" %>%> <%= f.label :title %><br /><%= link_to Back, posts_path %> <%= f.text_field :title %> </div> <div class="field"> <%= f.label :body %><br /># app/views/posts/edit.html.erb <%= f.text_area :body %><h1>Edit post</h1> </div> <div class="actions"><%= render "form" %>%> <%= f.submit %><%= link_to Show, @post %> | </div><%= link_to Back, posts_path %> <% end %> The right way
  49. 49. AJAXImprove user experience
  50. 50. Improve user experience by not having thewhole page reload when submitting a formor simple pagination linkAlso save resources used (SQL queries,memory, more bandwidth usage,... etc)
  51. 51. AJAXChanging default forms to AJAX
  52. 52. # config/routes.rbBlog::Application.routes.draw do resources :posts do resources :comments, :only => [:create] endendPOST /posts/:post_id/comments Limiting actions is always the best practice
  53. 53. # app/controllers/comments_controller.rbclass CommentsController < ApplicationController def create @post = Post.find(params[:post_id]) @comment = @post.comments.new(params[:comment]) respond_to do |format| if @comment.save format.html { redirect_to(@post } else format.html { render :template => "posts/show.html.erb" } end end endend
  54. 54. # app/views/posts/show.html.erb...<h1>Comments</h1><div id="comments"> <%= render :partial => "comments/comment", :collection => @post.commments %></div><%= render :partial => "comments/form", :locals => { :post => @post, :comment => @comment || Comment.new } %>
  55. 55. # app/views/comments/_form.html.erb<%= form_for [post,comment] do |f| %> <div class="field"> <%= f.label :body %><br /> <%= f.text_area :body %> <p><%= f.submit %></p> </div><% end %> Our HTML form What needs to change?
  56. 56. # app/views/comments/_form.html.erb<%= form_for [post,comment], :remote => true do |f| %> <div class="field"> <%= f.label :body %><br /> <%= f.text_area :body %> <p><%= f.submit %></p> </div><% end %> That’s it? Not yet!
  57. 57. # app/controllers/comments_controller.rbclass CommentsController < ApplicationController def create @post = Post.find(params[:post_id]) @comment = @post.comments.new(params[:comment]) respond_to do |format| if @comment.save format.html { redirect_to(@post, :notice => Comment wassuccessfully created.) } format.js else format.html { render :action => "new" } format.js end end endend
  58. 58. # app/views/comments/create.js.erb//Dump javascript here!document.getElementById...Notice:- create.js.erb- writing native javascript is not optimal: 1. You will forget something about IE 2. We are at 21st Century 3. Lots of good frameworks
  59. 59. Rails 2.X and 3.0.X- Prototype JS Framework as defaultRails 3.1 (released 2011)- jQuery JS Framework as default
  60. 60. # app/views/comments/create.js.erb<% if @comment.new_record? %> <% content = render(:partial => "comments/form", :locals => { :post => @post, :comment => @comment }) content = escape_javascript(content) %> $(new_comment).replace("<%= content %>");<% else %> <% comment_content = render(:partial => "comments/comment", :object => @comment) comment_content = escape_javascript(comment_content) %> $(comments).insert({ bottom : <%= comment_content %> }) $(new_comment).reset();<% end %>
  61. 61. Almost there... but- Complex code- We can do better with Rails
  62. 62. RJSRuby (to) JavaScript Templates
  63. 63. # app/views/comments/create.js.rjsif @comment.new_record? page.replace :new_comment, :partial => "comments/form", :locals => { :post => @post, :comment => @comment }else page.insert_html :bottom, :comments, :partial=> "comments/comment", :object => @comment page[:new_comment].resetend
  64. 64. Gems
  65. 65. GemsExtend Rails frameworkEasy installation and usageIncreasing community • Github • Gemcutter
  66. 66. Bundler gem# Gemfilegem "rails", "2.3.10"gem "will_paginate"gem "authlogic"gem "pg"gem "postgis_adapter", "0.7.8"gem "GeoRuby", "1.3.4"# Sphinxgem "thinking-sphinx", "1.4.5"group :development do gem "capistrano" gem "capistrano-ext" gem "ruby-debug" gem "wirble" gem "mongrel"end
  67. 67. Questions ?
  68. 68. Referenceshttp://rubyonrails.org/http://railsapi.com/http://railscasts.com/http://railsforzombies.org/
  69. 69. References
  70. 70. Thanks :)pedro.cunha@rupeal.com @mryise
  1. A particular slide catching your eye?

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

×