Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥

Conhecendo as entranhas do Rails

Conhecendo as entranhas do Rails

Minha apresentação na RubyConfBR 2012

Rafael França

August 31, 2012
Tweet

More Decks by Rafael França

Other Decks in Technology

Transcript

  1. Middleware Stack Rack::Cache ActionDispatch::SSL Rack::Sendfile ActionDispatch::Static Rack::Lock Rack::Runtime Rack::MethodOverride ActionDispatch::RequestId

    Rails::Rack::Logger ActionDispatch::ShowExceptions ActionDispatch::DebugExceptions ActionDispatch::RemoteIp ActionDispatch::Reloader ActionDispatch::Callbacks ActionDispatch::Cookies ActionDispatch::Session::CookieStore ActionDispatch::Flash ActionDispatch::ParamsParser Rack::Head Rack::ConditionalGet Rack::ETag ActionDispatch::BestStandardsSupport Rails
  2. Middleware Stack Rack::Cache ActionDispatch::SSL Rack::Sendfile ActionDispatch::Static Rack::Lock Rack::Runtime Rack::MethodOverride ActionDispatch::RequestId

    Rails::Rack::Logger ActionDispatch::ShowExceptions ActionDispatch::DebugExceptions ActionDispatch::RemoteIp ActionDispatch::Reloader ActionDispatch::Callbacks ActionDispatch::Cookies ActionDispatch::Session::CookieStore ActionDispatch::Flash ActionDispatch::ParamsParser Rack::Head Rack::ConditionalGet Rack::ETag ActionDispatch::BestStandardsSupport rails-api
  3. rails-api $ rails new normal_application $ cd normal_application $ rake

    middleware RAILS_ENV=production | wc -l $ rails-api new api_application $ cd api_application $ rake middleware RAILS_ENV=production | wc -l 22 17
  4. Rails::Railtie # railties/lib/rails/all.rb require "rails" %w( active_record action_controller action_mailer rails/test_unit

    sprockets/rails ).each do |framework| begin require "#{framework}/railtie" rescue LoadError end end
  5. module ActiveRecord class Railtie < Rails::Railtie config.active_record = ActiveSupport::OrderedOptions.new config.app_generators.orm

    :active_record, :migration => true, :timestamps => true config.app_middleware.insert_after "::ActionDispatch::Callbacks", "ActiveRecord::QueryCache" # ... config.action_dispatch.rescue_responses.merge!( 'ActiveRecord::RecordNotFound' => :not_found, 'ActiveRecord::StaleObjectError' => :conflict, 'ActiveRecord::RecordInvalid' => :unprocessable_entity, 'ActiveRecord::RecordNotSaved' => :unprocessable_entity ) rake_tasks do # ... end console do |app| # ... end end end Rails::Railtie
  6. module ActiveRecord class Railtie < Rails::Railtie config.active_record = ActiveSupport::OrderedOptions.new config.app_generators.orm

    :active_record, :migration => true, :timestamps => true config.app_middleware.insert_after "::ActionDispatch::Callbacks", "ActiveRecord::QueryCache" # ... end end Rails::Railtie
  7. module ActiveRecord class Railtie < Rails::Railtie config.active_record = ActiveSupport::OrderedOptions.new config.app_generators.orm

    :active_record, :migration => true, :timestamps => true config.app_middleware.insert_after "::ActionDispatch::Callbacks", "ActiveRecord::QueryCache" # ... end end Rails::Railtie
  8. module ActiveRecord class Railtie < Rails::Railtie config.active_record = ActiveSupport::OrderedOptions.new config.app_generators.orm

    :active_record, :migration => true, :timestamps => true config.app_middleware.insert_after "::ActionDispatch::Callbacks", "ActiveRecord::QueryCache" # ... end end Rails::Railtie
  9. module ActiveRecord class Railtie < Rails::Railtie # ... config.action_dispatch.rescue_responses.merge!( 'ActiveRecord::RecordNotFound'

    => :not_found, 'ActiveRecord::StaleObjectError' => :conflict, 'ActiveRecord::RecordInvalid' => :unprocessable_entity, 'ActiveRecord::RecordNotSaved' => :unprocessable_entity ) # ... end end Rails::Railtie
  10. module ActiveRecord class Railtie < Rails::Railtie # ... rake_tasks do

    # ... end console do |app| # ... end end end Rails::Railtie
  11. Rails::Engine module Devise class Engine < ::Rails::Engine config.app_middleware.use Warden::Manager do

    |config| Devise.warden_config = config end config.before_eager_load { |app| app.reload_routes! } initializer "devise.url_helpers" do # ... end initializer "devise.omniauth" do |app| # ... end end end https://github.com/plataformatec/devise
  12. Rails::Engine module Devise class Engine < ::Rails::Engine config.app_middleware.use Warden::Manager do

    |config| Devise.warden_config = config end config.before_eager_load { |app| app.reload_routes! } initializer "devise.url_helpers" do # ... end initializer "devise.omniauth" do |app| # ... end end end https://github.com/plataformatec/devise
  13. Rails::Engine module Devise class Engine < ::Rails::Engine config.app_middleware.use Warden::Manager do

    |config| Devise.warden_config = config end config.before_eager_load { |app| app.reload_routes! } initializer "devise.url_helpers" do # ... end initializer "devise.omniauth" do |app| # ... end end end https://github.com/plataformatec/devise
  14. Rails::Engine module Devise class Engine < ::Rails::Engine config.app_middleware.use Warden::Manager do

    |config| Devise.warden_config = config end config.before_eager_load { |app| app.reload_routes! } initializer "devise.url_helpers" do # ... end initializer "devise.omniauth" do |app| # ... end end end https://github.com/plataformatec/devise
  15. Mountable Engines # ENGINE/config/routes.rb MyBlogEngine::Engine.routes.draw do resources :posts do resources

    :comments end end MyRailsApp::Application.routes.draw do mount MyBlogEngine::Engine => "/blog" end
  16. Isolated Engines module MyBlog class Engine < Rails::Engine end end

    MyBlog::Engine.routes.draw do resources :posts end MyRailsApp::Application.routes.draw do resources :posts mount MyBlog::Engine => "/blog" end posts_path # => PostsController#index
  17. Isolated Engines module MyBlog class Engine < Rails::Engine isolate_namespace MyBlog

    end end MyBlog::Engine.routes.draw do resources :posts end posts_path # => MyBlog::PostsController#index
  18. Rails::Application module MyProject class Application < Rails::Application config.i18n.default_locale = "pt-BR"

    config.encoding = "utf-8" config.filter_parameters += [:password] config.generators do |g| g.orm :mongoid g.test_framework :rspec g.stylesheets false end end end
  19. Rails::Application module MyProject class Application < Rails::Application config.i18n.default_locale = "pt-BR"

    config.encoding = "utf-8" config.filter_parameters += [:password] config.generators do |g| g.orm :mongoid g.test_framework :rspec g.stylesheets false end end end
  20. Rails::Application module MyProject class Application < Rails::Application config.i18n.default_locale = "pt-BR"

    config.encoding = "utf-8" config.filter_parameters += [:password] config.generators do |g| g.orm :mongoid g.test_framework :rspec g.stylesheets false end end end
  21. Rails::Application module MyProject class Application < Rails::Application config.i18n.default_locale = "pt-BR"

    config.encoding = "utf-8" config.filter_parameters += [:password] config.generators do |g| g.orm :mongoid g.test_framework :rspec g.stylesheets false end end end
  22. class UsersController < ActionController::Base def create @user = User.new params[:user]

    if @user.save UserMailer.deliver_welcome_email @user end respond_with @user end end Rails 3
  23. class UsersController < ActionController::Base def create @user = User.new params[:user]

    if @user.save UserMailer.deliver_welcome_email @user end respond_with @user end end Rails 3
  24. class UsersController < ActionController::Base def create @user = User.new params[:user]

    if @user.save UserMailer.deliver_welcome_email @user end respond_with @user end end Rails 4
  25. class ExplainSubscriber # :nodoc: def start(name, id, payload) # unused

    end def finish(name, id, payload) if queries = Thread.current[:queries] unless ignore_payload?(payload) queries << payload.values_at(:sql, :binds) end end end ActiveSupport::Notifications. subscribe("sql.active_record", new) end
  26. class ExplainSubscriber # :nodoc: def start(name, id, payload) # unused

    end def finish(name, id, payload) if queries = Thread.current[:queries] unless ignore_payload?(payload) queries << payload.values_at(:sql, :binds) end end end ActiveSupport::Notifications. subscribe("sql.active_record", new) end
  27. class ExplainSubscriber # :nodoc: def start(name, id, payload) # unused

    end def finish(name, id, payload) if queries = Thread.current[:queries] unless ignore_payload?(payload) queries << payload.values_at(:sql, :binds) end end end ActiveSupport::Notifications. subscribe("sql.active_record", new) end
  28. class ExplainSubscriber # :nodoc: def start(name, id, payload) # unused

    end def finish(name, id, payload) if queries = Thread.current[:queries] unless ignore_payload?(payload) queries << payload.values_at(:sql, :binds) end end end ActiveSupport::Notifications. subscribe("sql.active_record", new) end
  29. def log(sql, name = "SQL", binds = []) @instrumenter.instrument( "sql.active_record",

    :sql => sql, :name => name, :connection_id => object_id, :binds => binds) { yield } # ... end log(sql, name) { @connection.execute(sql) }
  30. def log(sql, name = "SQL", binds = []) @instrumenter.instrument( "sql.active_record",

    :sql => sql, :name => name, :connection_id => object_id, :binds => binds) { yield } # ... end log(sql, name) { @connection.execute(sql) }
  31. def log(sql, name = "SQL", binds = []) @instrumenter.instrument( "sql.active_record",

    :sql => sql, :name => name, :connection_id => object_id, :binds => binds) { yield } # ... end log(sql, name) { @connection.execute(sql) }
  32. def log(sql, name = "SQL", binds = []) @instrumenter.instrument( "sql.active_record",

    :sql => sql, :name => name, :connection_id => object_id, :binds => binds) { yield } # ... end log(sql, name) { @connection.execute(sql) }
  33. def log(sql, name = "SQL", binds = []) @instrumenter.instrument( "sql.active_record",

    :sql => sql, :name => name, :connection_id => object_id, :binds => binds) { yield } # ... end log(sql, name) { @connection.execute(sql) }
  34. def logging_query_plan # ... begin queries = current[:queries] = []

    start = Time.now result = yield if Time.now - start > threshold logger.warn(exec_explain(queries)) end result ensure current[:queries] = nil end end
  35. def logging_query_plan # ... begin queries = current[:queries] = []

    start = Time.now result = yield if Time.now - start > threshold logger.warn(exec_explain(queries)) end result ensure current[:queries] = nil end end
  36. def logging_query_plan # ... begin queries = current[:queries] = []

    start = Time.now result = yield if Time.now - start > threshold logger.warn(exec_explain(queries)) end result ensure current[:queries] = nil end end
  37. def logging_query_plan # ... begin queries = current[:queries] = []

    start = Time.now result = yield if Time.now - start > threshold logger.warn(exec_explain(queries)) end result ensure current[:queries] = nil end end
  38. class ExplainSubscriber # :nodoc: def start(name, id, payload) # unused

    end def finish(name, id, payload) if queries = Thread.current[:queries] unless ignore_payload?(payload) queries << payload.values_at(:sql, :binds) end end end ActiveSupport::Notifications. subscribe("sql.active_record", new) end
  39. class ExplainSubscriber # :nodoc: def start(name, id, payload) # unused

    end def finish(name, id, payload) if queries = Thread.current[:queries] unless ignore_payload?(payload) queries << payload.values_at(:sql, :binds) end end end ActiveSupport::Notifications. subscribe("sql.active_record", new) end
  40. class ExplainSubscriber # :nodoc: def start(name, id, payload) # unused

    end def finish(name, id, payload) if queries = Thread.current[:queries] unless ignore_payload?(payload) queries << payload.values_at(:sql, :binds) end end end ActiveSupport::Notifications. subscribe("sql.active_record", new) end
  41. # config/routes.rb MyApp::Application.routes.draw do resources :messages { resources :comments }

    resources :forwards { resources :comments } resources :uploads { resources :comments } resources :documents { resources :comments } resources :todos { resources :comments } end
  42. # config/routes.rb MyApp::Application.routes.draw do resources :messages { resources :comments }

    resources :forwards { resources :comments } resources :uploads { resources :comments } resources :documents { resources :comments } resources :todos { resources :comments } end
  43. # config/routes.rb MyApp::Application.routes.draw do concerns :commentable do resources :comments end

    resources :messages, :forwards, :uploads, :documents, :todos, :concerns => :commentable end
  44. # config/routes.rb MyApp::Application.routes.draw do concerns :commentable do resources :comments end

    resources :messages, :forwards, :uploads, :documents, :todos, :concerns => :commentable end
  45. # config/routes.rb MyApp::Application.routes.draw do concerns :commentable do resources :comments end

    resources :messages, :forwards, :uploads, :documents, :todos, :concerns => :commentable end
  46. # config/routes.rb MyApp::Application.routes.draw do concerns :commentable do resources :comments end

    resources :messages, :forwards, :uploads, :documents, :todos, :concerns => :commentable end
  47. class PeopleController < ApplicationController def create person = Person.create(params[:person]) respond_with

    person end end class Person < ActiveRecord::Base attr_accessible :name, :age end Rails 3
  48. class PeopleController < ApplicationController def create person = Person.create(params[:person]) respond_with

    person end end class Person < ActiveRecord::Base attr_accessible :name, :age end Rails 3
  49. class PeopleController < ApplicationController def create person = Person.create(params[:person]) respond_with

    person end end class Person < ActiveRecord::Base attr_accessible :name, :age end Rails 3
  50. class PeopleController < ApplicationController def create person = Person.create(params[:person]) respond_with

    person end end class Person < ActiveRecord::Base attr_accessible :name, :age end Rails 3
  51. class Person include ActiveRecord::Model end class PeopleController < ApplicationController def

    create person = Person.create(params[:person]) # BOOM!!!! respond_with person end end Rails 4
  52. class Person include ActiveRecord::Model end class PeopleController < ApplicationController def

    create person = Person.create(params[:person]) # BOOM!!!! respond_with person end end Rails 4
  53. class Person include ActiveRecord::Model end class PeopleController < ApplicationController def

    create person = Person.create(params[:person]) # BOOM!!!! respond_with person end end Rails 4
  54. class Person include ActiveRecord::Model end class PeopleController < ApplicationController def

    create person = Person.create(params[:person]) # BOOM!!!! respond_with person end end Rails 4
  55. class PeopleController < ApplicationController def update person = Person.find(params[:id]) person.update_attributes(person_params)

    respond_with person end private def person_params params.require(:person).permit(:name, :age) end end Rails 4
  56. class PeopleController < ApplicationController def update person = Person.find(params[:id]) person.update_attributes(person_params)

    respond_with person end private def person_params params.require(:person).permit(:name, :age) end end Rails 4
  57. class PeopleController < ApplicationController def update person = Person.find(params[:id]) person.update_attributes(person_params)

    respond_with person end private def person_params params.require(:person).permit(:name, :age) end end Rails 4
  58. class PeopleController < ApplicationController def update person = Person.find(params[:id]) person.update_attributes(person_params)

    respond_with person end private def person_params params.require(:person).permit(:name, :age) end end Rails 4
  59. class PeopleController < ApplicationController def update person = Person.find(params[:id]) person.update_attributes(person_params)

    respond_with person end private def person_params params.require(:person).permit(:name, :age) end end Rails 4
  60. class PostsController < ApplicationController def show @post = Post.find(params[:id]) render

    :json => post_json end private def post_json @post.as_json(:only => [:id, :title, :body], :include => { :comments => { :only => [:id, :body] } } ) end end
  61. class PostsController < ApplicationController def show @post = Post.find(params[:id]) render

    :json => post_json end private def post_json @post.as_json(:only => [:id, :title, :body], :include => { :comments => { :only => [:id, :body] } } ) end end
  62. class PostsController < ApplicationController def show @post = Post.find(params[:id]) render

    :json => post_json end private def post_json @post.as_json(:only => [:id, :title, :body], :include => { :comments => { :only => [:id, :body] } } ) end end
  63. class PostsController < ApplicationController def show @post = Post.find(params[:id]) render

    :json => post_json end private def post_json @post.as_json(:only => [:id, :title, :body], :include => { :comments => { :only => [:id, :body] } } ) end end
  64. class PostsController < ApplicationController def show @post = Post.find(params[:id]) render

    :json => post_json end private def post_json @post.as_json(:only => [:id, :title, :body], :include => { :comments => { :only => [:id, :body] } } ) end end
  65. class PostsController < ApplicationController def show @post = Post.find(params[:id]) render

    :json => post_json end private def post_json @post.as_json(:only => [:id, :title, :body], :include => { :comments => { :only => [:id, :body] } } ) end end
  66. class PostsController < ApplicationController def show @post = Post.find(params[:id]) render

    :json => @post end end # app/serializers/post_serializer.rb class PostSerializer < ActiveModel::Serializer embed :ids, :include => true attributes :id, :title, :body has_many :comments end
  67. class PostsController < ApplicationController def show @post = Post.find(params[:id]) render

    :json => @post end end # app/serializers/post_serializer.rb class PostSerializer < ActiveModel::Serializer embed :ids, :include => true attributes :id, :title, :body has_many :comments end
  68. class PostsController < ApplicationController def show @post = Post.find(params[:id]) render

    :json => @post end end # app/serializers/post_serializer.rb class PostSerializer < ActiveModel::Serializer embed :ids, :include => true attributes :id, :title, :body has_many :comments end
  69. class PostsController < ApplicationController def show @post = Post.find(params[:id]) render

    :json => @post end end # app/serializers/post_serializer.rb class PostSerializer < ActiveModel::Serializer embed :ids, :include => true attributes :id, :title, :body has_many :comments end
  70. class PostsController < ApplicationController def show @post = Post.find(params[:id]) render

    :json => @post end end # app/serializers/post_serializer.rb class PostSerializer < ActiveModel::Serializer embed :ids, :include => true attributes :id, :title, :body has_many :comments end
  71. class PostsController < ApplicationController def show @post = Post.find(params[:id]) render

    :json => @post end end # app/serializers/post_serializer.rb class PostSerializer < ActiveModel::Serializer embed :ids, :include => true attributes :id, :title, :body has_many :comments end
  72. { "post": { "id": 1, "title": "New post", "body": "A

    body!", "comments": [ 1, 2 ] }, "comments": [ { "id": 1, "body": "what a dumb post" }, { "id": 2, "body": "i liked it" }, ] }
  73. { "body": "<p>This is <i>serious</i> monkey business", "id": 1, "title":

    "New post", "comments": [ { "id": 1, "body": "what a dumb post" }, { "id": 2, "body": "i liked it" } ], }