Share
Embed
Conhecendo as Entranhas do Rails
Por Rafael França, na RubyConf Brasil 2012.
Plataformatec
August 31, 2012
Transcript
154 slides
-
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 -
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 -
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 -
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 -
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 -
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 -
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 -
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 -
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 -
module ActiveRecord class Railtie < Rails::Railtie # ... rake_tasks do
# ... end console do |app| # ... end end end Rails::Railtie -
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 -
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 -
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 -
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 -
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 -
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 -
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 -
Isolated Engines # config/routes.rb MyApplication::Application.routes.draw do mount MyBlog::Engine => "/blog",
:as => "my_blog" get "/foo" => "foo#index" end -
Isolated Engines # config/routes.rb MyApplication::Application.routes.draw do mount MyBlog::Engine => "/blog",
:as => "my_blog" get "/foo" => "foo#index" end -
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 -
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 -
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 -
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 -
ActionController::API ActionController::UrlFor ActionController::Redirecting ActionController::Rendering ActionController::Renderers::All ActionController::ConditionalGet ActionController::ForceSSL ActionController::RackDelegation ActionController::DataStreaming AbstractController::Callbacks
ActionController::Instrumentation ActionController::Rescue ActionController::HideActions https://github.com/rails/rails/blob/c0b69630/ actionpack/lib/action_controller/base.rb#L183-225 -
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 -
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 -
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 -
# app/mailers/user_mailer.rb class UserMailer < ActionMailer::Base self.async = true def
welcome_email # ... end end Rails 4 -
# app/mailers/user_mailer.rb class UserMailer < ActionMailer::Base self.async = true def
welcome_email # ... end end Rails 4 -
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 -
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 -
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 -
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 -
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) } -
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) } -
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) } -
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) } -
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) } -
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 -
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 -
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 -
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 -
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 -
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 -
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 -
# 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 -
# 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 -
# config/routes.rb MyApp::Application.routes.draw do concerns :commentable do resources :comments end
resources :messages, :forwards, :uploads, :documents, :todos, :concerns => :commentable end -
# config/routes.rb MyApp::Application.routes.draw do concerns :commentable do resources :comments end
resources :messages, :forwards, :uploads, :documents, :todos, :concerns => :commentable end -
# config/routes.rb MyApp::Application.routes.draw do concerns :commentable do resources :comments end
resources :messages, :forwards, :uploads, :documents, :todos, :concerns => :commentable end -
# config/routes.rb MyApp::Application.routes.draw do concerns :commentable do resources :comments end
resources :messages, :forwards, :uploads, :documents, :todos, :concerns => :commentable end -
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 -
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 -
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 -
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 -
class Person include ActiveRecord::Model end class PeopleController < ApplicationController def
create person = Person.create(params[:person]) # BOOM!!!! respond_with person end end Rails 4 -
class Person include ActiveRecord::Model end class PeopleController < ApplicationController def
create person = Person.create(params[:person]) # BOOM!!!! respond_with person end end Rails 4 -
class Person include ActiveRecord::Model end class PeopleController < ApplicationController def
create person = Person.create(params[:person]) # BOOM!!!! respond_with person end end Rails 4 -
class Person include ActiveRecord::Model end class PeopleController < ApplicationController def
create person = Person.create(params[:person]) # BOOM!!!! respond_with person end end Rails 4 -
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 -
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 -
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 -
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 -
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 -
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 -
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 -
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 -
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 -
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 -
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 -
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 -
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 -
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 -
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 -
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 -
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 -
{ "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" }, ] } -
{ "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" } ], } -
Serializers Jbuilder Abordagem OO Fácil de configurar Frameworks Javascript Abordagem
de view Helpers Respostas customizadas -
ActionController::Live class MyController < ActionController::Base def index 100.times { response.stream.write
"hello world\n" } response.stream.close end end -
ActionController::Live class MyController < ActionController::Base include ActionController::Live def index 100.times
{ response.stream.write "hello world\n" } response.stream.close end end -
ActionController::Live class MyController < ActionController::Base include ActionController::Live def index 100.times
{ response.stream.write "hello world\n" } response.stream.close end end -
ActionController::Live class MyController < ActionController::Base include ActionController::Live def index 100.times
{ response.stream.write "hello world\n" } response.stream.close end end