Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Um roadmap do Framework Ruby on Rails

Um roadmap do Framework Ruby on Rails

do Rails 1 ao Rails 4

More Decks by João Lucas Pereira de Santana

Other Decks in Programming

Transcript

  1. Um roadmap do Framework Ruby on Rails do Rails 1

    ao Rails 4 João Lucas Pereira de Santana
  2. #devday2013 @jlucasps Apresentação João Lucas Pereira de Santana twitter |

    github | fb | gtalk: @jlucasps Ciência da Computação pela UFLA Desenvolvedor Ruby, Java, JavaScript Instrutor Ruby on Rails
  3. #devday2013 @jlucasps Agenda ➔ Rails Full Stack - Request/Responder ➔

    Primeira versão ◆ Active Support, Active Record, Action Pack, Action Mailer ➔ Rails 2 ➔ Rails 3 ➔ Rails 4
  4. #devday2013 @jlucasps Rails Full Stack ➔ Rails Core Team Jeremy

    Kemper Michael Koziarski Yehuda Katz José Valim Santiago Pastorino Aaron Patterson Xavier Noria Jon Leighton Rafael França Andrew White Guillermo Iguaran Carlos Antonio
  5. ➔ Framework MVC para desenvolvimento Web #devday2013 @jlucasps Rails Full

    Stack Testes Testes Testes Model View Controller HTTP/SSL Routes Helpers Middleware Responders Renders Session Logs Associations Validations Queries Callbacks Connections Migrations Assets Helpers Builders Templates Partials
  6. #devday2013 @jlucasps Rails Full Stack Model View Controller Web Server

    App Server Rails REQUEST: GET http://myapp.com/users/2/lists ACCEPTED: passado para o App Server Request passado para o Rails
  7. #devday2013 @jlucasps Rails Full Stack Router user_lists GET /users/:user_id/lists(.:format) lists#index

    Controller e Action selecionadas: GET /users/2/lists CONTROLLER: "lists" ACTION: "index" NOME DA ROTA: "user_lists"
  8. #devday2013 @jlucasps Rails Full Stack Model View Controller Rails Router

    Controller ListsController Model View index new create update destroy ........ GET /users/2/lists CONTROLLER: "lists" ACTION: "index"
  9. #devday2013 @jlucasps Rails Full Stack Model @user = User.find(params[:user_id]) @lists

    = List.find_all_by_user_id(params[:user_id]) ListsController index new create update destroy ........ User Model List Model Active Record Active Record Banco de dados tabela 'users' tabela 'lists'
  10. #devday2013 @jlucasps Rails Full Stack REQUEST: GET http://myapp.com/users/2/lists ACCEPTED: passado

    para o App Server REQUEST passado para o Rails PATH e METHOD mapeados para CONTROLLER e ACTION CONTROLLER recupera informações dos MODELS para suprir a VIEW Model View Controller Web Server App Server Rails Router action action action
  11. #devday2013 @jlucasps Rails Full Stack View ListsController index update View

    app/views/lists/index.html.erb edit .......... app/views/lists/update.html.erb @vars .html @vars .html Request Headers Accept: text/html, application/xhtml+xml
  12. #devday2013 @jlucasps Rails Full Stack REQUEST: GET http://myapp.com/users/2/lists ACCEPTED: passado

    para o App Server REQUEST passado para o Rails PATH e METHOD mapeados para CONTROLLER e ACTION CONTROLLER recupera informações dos MODELS para suprir a VIEW Model View Controller Web Server App Server Rails Router action action action VIEW cria a resposta para o RESPONSE BODY
  13. #devday2013 @jlucasps Rails Full Stack Model View Controller Web Server

    App Server Rails Router action action action VIEW cria a resposta para o RESPONSE BODY RESPONSE volta através do middleware stack RESPONSE é retornada para o browser RESPONSE recebida :-)
  14. ➔ Inflectors #devday2013 @jlucasps rails-0.10.0 SingularToPlural = { "search" =>

    "searches", "category" => "categories", "wife" => "wives", "series" => "series" } CamelToUnderscore = { "Product" => "product", "SpecialGuest" => "special_guest" } CamelWithModuleToUnderscoreWithSlash = { "Admin::Product" => "admin/product", "UsersSection::CommissionDepartment" => "users_section/commission_department" } ClassNameToForeignKeyWithUnderscore = { "Person" => "person_id", "MyApplication::Billing::Account" => "account_id" } ClassNameToTableName = { "PrimarySpokesman" => "primary_spokesmen", "NodeChild" => "node_children" }
  15. ➔ Breakpoints #devday2013 @jlucasps rails-0.10.0 [0, 9] in /media/truecrypt1/rails4chat/app/controllers/pages_controller.rb 1

    class PagesController < ApplicationController 2 3 def index 4 debugger => 5 @messages = Message.limit(20) 6 end 7 8 end (rdb:1) params {"controller"=>"pages", "action"=>"index"} (rdb:1)
  16. ➔ active_support core_ext ◆ Time #devday2013 @jlucasps rails-0.10.0 # Calculations

    assert_equal Time.local(2006,2,22,15,15,10), Time.local(2005,2,22,15,15,10).change(:year => 2006) assert_equal Time.local(2005,2,22,10,10,9), Time.local(2005,2,22,10,10,10).ago(1) assert_equal Time.local(2005,2,20,10,10,10), Time.local(2005,2,22,10,10,10).ago(86400*2) assert_equal Time.local(2005,1,31), Time.local(2005,2,4,10,10,10).beginning_of_week assert_equal Time.local(2005,2,4,0,0,0), Time.local(2005,2,4,10,10,10).beginning_of_day # Conversions assert_equal "February 21, 2005 17:44", Time.local(2005, 2, 21, 17, 44, 30).to_s(:long) assert_equal Date.new(2005, 2, 21), Time.local(2005, 2, 21, 17, 44, 30).to_date
  17. ➔ active_support core_ext ◆ Numeric #devday2013 @jlucasps rails-0.10.0 # byte

    calculations 1024.kilobytes => 1.megabyte 1.kilobyte ** 4 => 1.terabyte time calculations 1.minute => 60 1.hour + 15.minutes => 4500 2.days + 4.hours + 30.minutes => 189000
  18. ➔ active_support core_ext ◆ Hash #devday2013 @jlucasps rails-0.10.0 # hash

    # stringify_keys, symbolize_keys e indifferent_access strings = { 'a' => 1, 'b' => 2 } symbols = { :a => 1, :b => 2 } mixed = { :a => 1, 'b' => 2 }
  19. ➔ active_support core_ext ◆ Date #devday2013 @jlucasps rails-0.10.0 # Getting

    dates in different convenient string representations and other objects assert_equal "21 Feb", Date.new(2005, 2, 21).to_s(:short) assert_equal "February 21, 2005", Date.new(2005, 2, 21).to_s(:long) # to_time assert_equal Time.local(2005, 2, 21), Date.new(2005, 2, 21).to_time # to_date assert_equal Date.new(2005, 2, 21), Date.new(2005, 2, 21).to_date
  20. ➔ active_record ◆ connections: • db2, mysql, oracle, postgresql, sqlite,

    sqlite3, sqlserver ◆ mapping: #devday2013 @jlucasps rails-0.10.0 table "products" class Product < ActiveRecord::Base end
  21. ➔ active_record ◆ associations: #devday2013 @jlucasps rails-0.10.0 class Firm <

    ActiveRecord::Base has_many :clients has_one :account belongs_to :conglomorate has_and_belongs_to_many :investors end # natural assignments: apple.account = citibank assert_equal apple.id, citibank.firm_id
  22. ➔ active_record ◆ validations: #devday2013 @jlucasps rails-0.10.0 # Validation rules

    that can differ for new or existing objects class Account < ActiveRecord::Base validates_presence_of :subdomain, :name, :email_address, : password validates_uniqueness_of :subdomain validates_acceptance_of :terms_of_service, :on => :create validates_confirmation_of :password, :email_address, :on => : create end
  23. ➔ active_record ◆ callbacks: #devday2013 @jlucasps rails-0.10.0 # Callbacks as

    methods or queues on the entire lifecycle # (instantiation, saving, destroying, validating, etc). :after_find, :after_initialize, :before_validation :before_validation_on_update, :after_validation :after_validation_on_update, :before_save :before_update, :after_update, :after_save :before_destroy, :after_destroy
  24. ➔ active_record ◆ find and dynamic methods #devday2013 @jlucasps rails-0.10.0

    # finds Firm.find(1, 2) Company.find_first "name = 'Next Angle'" Firm.find_by_sql("SELECT * FROM companies WHERE id = 1").first Topic.find(1, :conditions => "approved = 1") Topic.find_by_title("The First Topic") Topic.find_by_title_and_author_name("The First Topic", "David") Topic.find_all_by_content("Have a nice day") # dynamic methods next_angle.clients.find(2) next_angle.clients.empty? next_angle.clients.size
  25. ➔ action_pack ◆ action_controller: #devday2013 @jlucasps rails-0.10.0 BlogController < ActionController::Base

    def show @customer = find_customer end private def find_customer() Customer.find(@params["id"]) end end
  26. ➔ action_pack ◆ filters: #devday2013 @jlucasps rails-0.10.0 class WeblogController <

    ActionController::Base before_filter :authenticate, :cache, :audit after_filter { |c| c.response.body = GZip::compress(c.response.body) } end
  27. ➔ action_pack ◆ layouts: #devday2013 @jlucasps rails-0.10.0 class WeblogController <

    ActionController::Base layout "weblog_layout" def hello_world end end
  28. ➔ action_pack ◆ scaffold: #devday2013 @jlucasps rails-0.10.0 require 'account' #

    must be an Active Record class class AccountController < ActionController::Base scaffold :account end # templates: list, show, destroy, new, create, edit, update
  29. ➔ action_pack ◆ advanced redirection #devday2013 @jlucasps rails-0.10.0 # Advanced

    redirection that makes pretty urls easy: RewriteRule ^/library/books/([A-Z]+)([0-9]+)/([-_a-zA-Z0-9]+)$ \ /books_controller.cgi?action=$3&type=$1&code=$2 [QSA] [L] # Accessing /library/books/ISBN/0743536703/show calls BooksController#show
  30. ➔ action_pack ◆ action view: #devday2013 @jlucasps rails-0.10.0 <!-- Embedded

    Ruby for templates: --> <% for post in @posts %> Title: <%= post.title %> <% end %> <!-- Helpers for forms, dates, action links, and text: --> <%= text_field "post", "title", "size" => 30 %> <%= html_date_select(Date.today) %> <%= link_to "New post", :controller => "post", :action => "new" %> <%= truncate(post.title, 25) %>
  31. ➔ action_pack ◆ action view: #devday2013 @jlucasps rails-0.10.0 <!-- Form

    building for Active Record model objects: --> <%= form "post" %> <!-- This form generates a @params["post"] array that can be used directly in a save action <!-- Rendering shared partials: --> <%= render_partial "advertisement/ad", ad %>
  32. ➔ action_mailer #devday2013 @jlucasps rails-0.10.0 def signed_up(recipient) @recipients = recipient

    @subject = "[Signed up] Welcome #{recipient}" @from = "[email protected]" @sent_on = Time.local(2004, 12, 12) @body["recipient"] = recipient end ApplicationMailer.deliver_signed_up("[email protected]") # sends the email
  33. ➔ active_support ◆ string to date and time: #devday2013 @jlucasps

    rails-0.11.0 assert_equal Time.utc(2005, 2, 27, 23, 50), "2005-02-27 23:50".to_time assert_equal Date.new(2005, 2, 27), "2005-02-27".to_date ➔ action_pack ◆ ajax ➔ action_mailer ◆ incoming mails
  34. ➔ Eager associations ➔ new Base.find API ➔ more Ajax!

    #devday2013 @jlucasps rails-0.12.0 # Turning N+1 queries into 1 for post in Post.find(:all, :include => [ :author, :comments ]) puts "Post: " + post.title puts "Written by: " + post.author.name puts "Last comment on: " + post.comments.first.created_on end Person.find(1, :conditions =>"administrator = 1", :order =>"created_on DESC") Person.find(1, 5, 6, :conditions =>"administrator = 1", :order =>"created_on DESC") Person.find(:first, :order =>"created_on DESC", :offset => 5) Person.find(:all, :conditions => [ "category IN (?)", categories], :limit => 50) Person.find(:all, :offset => 10, :limit => 10)
  35. ➔ script.aculo.us ➔ ajax #devday2013 @jlucasps rails-0.13.0 # remote link:

    link_to_remote( "test", :url => { :action =>"faulty" }, :update => { :success =>"good", :failure =>"bad" }, 403 =>"alert('Forbidden- got ya!')", 404 =>"alert('Nothing there...?')", :failure =>"alert('Unkown error ' + request.status)" )
  36. ➔ Migrations for PostgreSQL and MySQL ➔ Rendering: One method

    to bind them all ➔ Named routes #devday2013 @jlucasps rails-0.13.0 map.home '', :controller => 'main', :action => 'start' redirect_to :controller => 'main', :action => 'start' # above route is now redirect_to :home_url ➔ Coditional validations validates_numericality_of :income, :if => :employed? validates_presence_of :username, :if => Proc.new { |user| user.signup_step > 1 }
  37. ➔ RJS: JavaScript written in Ruby ➔ Polymorphic associations #devday2013

    @jlucasps rails-1.1.0 class Address < ActiveRecord::Base belongs_to :addressable, :polymorphic => true end class Person < ActiveRecord::Base has_one :address, :as => :addressable end class Company < ActiveRecord::Base has_one :address, :as => :addressable end
  38. ➔ calculations: ◆ sum, average, count, max ➔ Eager loading

    #devday2013 @jlucasps rails-1.1.0 # Single database query: companies = Company.find(:all, :include => { :groups => { :members=> { : favorites } } }) # Just 1 database query for all of this: authors = Author.find(:all, :include => [ { :posts => :comments }, : categorizations ]) authors[0].posts[0].comments[0].body # => "Rock on Rails!" authors[0].categorizations[0].name # => "Less software"
  39. ➔ respond_to e format #devday2013 @jlucasps rails-1.2 class WeblogController <

    ActionController::Base def index @posts = Post.find :all respond_to do |format| format.html format.xml { render :xml => @posts.to_xml } format.rss { render :action => “feed.rxml” } end end end GET /weblog # returns HTML from browser Accept header GET /weblog.xml # returns the XML GET /weblog.rss # returns the RSS
  40. ➔ action_pack: ◆ resources e collection resources ◆ multiview (show.html.erb,

    show.js.erb) ◆ CRSF token ◆ record identification: #devday2013 @jlucasps rails-2 # person is a Person object, which by convention will # be mapped to person_url for lookup redirect_to(person) link_to(person.name, person) form_for(person)
  41. ➔ nested_attributes #devday2013 @jlucasps rails-2.3 class Book < ActiveRecord::Base has_one

    :author has_many :pages accepts_nested_attributes_for :author, :pages end ➔ find with having developers = Developer.find(:all, :group => "salary", :having => "sum(salary) > 10000", :select => "salary")
  42. ➔ Bundler and Gemfile ➔ New ActiveRecord query engine: #devday2013

    @jlucasps rails-3 users = User.where(:name => "david").limit(20) users.order(:name).each { |user| puts user.name } ➔ Agnosticism with jQuery, rSpec, and Data Mapper: ◆ DataMapper -> Active Record ◆ Query -> Prototype ◆ Spec -> test/unit
  43. ➔ AssetPipeline: ◆ Sprockets, SCSS, CoffeeScript ➔ JQuery by default

    ➔ Reversible migrations #devday2013 @jlucasps rails-3.1
  44. ➔ critical security fixies: ◆ CVE-2012-5664 ◆ CVE-2013-0155 ◆ CVE-2013-0156

    ◆ CVE-2013-0333 ➔ Vendor plugins -> gems ➔ Faster dev mode e routing #devday2013 @jlucasps rails-3.2
  45. #devday2013 @jlucasps rails-4 ➔ Turbolinks ➔ Live streaming ➔ ActiveModel::Model

    ◆ validations, accessors, no persistence ➔ Deprecate routes by match ➔ Concerns routes concern :commentable do resources :comments end resources :articles, concerns: :commentable resources :photos, concerns: :commentable
  46. ➔ Mass assignment protection from Models to Controllers #devday2013 @jlucasps

    rails-4 class MessagesController < ApplicationController def create @message = Message.new(message_params) @message.user = current_user @message.save end private def message_params params.require(:message).permit(:content) end end
  47. Um roadmap do Framework Ruby on Rails do Rails 1

    ao Rails 4 João Lucas Pereira de Santana @jlucasps Muito obrigado!