rails 3 internals
DESCRIPTION
O Rails 3 foi finalmente anunciado e nele uma série de mudanças arquiteturais foram feitas.A princípio, para que programa, as mudanças podem parecer simples, penas novos comandos ou novas API’s. Mas se olharmos nos detalhes internos do framework podemos ver que as mudanças impactam diretamente na forma de usar o framework.TRANSCRIPT
Rails 3 InternalsConhecendo detalhes do framework que fazem a diferença.
Anderson Leite
@anderson_leite
www.andersonleite.com.br
Tuesday, September 14, 2010
Rails 3 Internals
Rails 3
Architectural changes
Rails + Merb
Tuesday, September 14, 2010
Rails 3 Internals
Modularidade
Rails 3
Tuesday, September 14, 2010
Rails 3 Internals
ActiveRelation
ActiveModel
Railtie
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
Tuesday, September 14, 2010
Rails 3 Internals
Tuesday, September 14, 2010
Rails 3 Internals
Diego Carrion ??
Tuesday, September 14, 2010
Rails 3 Internals
Diego Carrion ??
Tuesday, September 14, 2010
Rails 3 Internals
Diego Carrion ??
Tuesday, September 14, 2010
Rails 3 Internals
Diego Carrion ??
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
# Rails 2@models = Model.find(:all, :conditions => {:value => true} )
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
# Rails 3@models = Model.where(:value => true)
# Rails 2@models = Model.find(:all, :conditions => {:value => true} )
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
# Rails 3@models = Model.where(:value => true)
# Rails 2@models = Model.find(:all, :conditions => {:value => true} )
@models = @models.order(params[:order])
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
# Rails 3@models = Model.where(:value => true)
# Rails 2@models = Model.find(:all, :conditions => {:value => true} )
@models = @models.order(params[:order])
@models = Model.where(:value => true).order(params[:order])
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
# Rails 3@models = Model.where(:value => true)
# Rails 2@models = Model.find(:all, :conditions => {:value => true} )
@models = @models.order(params[:order])
@models = Model.where(:value => true).order(params[:order])
Array
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
# Rails 3@models = Model.where(:value => true)
# Rails 2@models = Model.find(:all, :conditions => {:value => true} )
@models = @models.order(params[:order])
@models = Model.where(:value => true).order(params[:order])
Array
Relation
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
# Rails 3@models = Model.where(:value => true)@models = @models.order(params[:order])
@models = Model.where(:value => true).order(params[:order])Relation
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
# Rails 3@models = Model.where(:value => true)@models = @models.order(params[:order])
@models = Model.where(:value => true).order(params[:order])Relation
@models.each do |m|#...end
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
# Rails 3@models = Model.where(:value => true)@models = @models.order(params[:order])
@models = Model.where(:value => true).order(params[:order])Relation
@models.each do |m|#...endLazy
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
# Rails 3@models = Model.where(:value => true).order(params[:order]).all
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
# Rails 3@models = Model.where(:value => true).order(params[:order]).all
Nova API (where, limit, having)
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
# Rails 3@models = Model.where(:value => true).order(params[:order]).allwhere
havingselectgrouporderlimitoffsetjoinsincludeslockreadonlyfrom
Nova API (where, limit, having)
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
# Rails 3@models = Model.where(:value => true).order(params[:order]).all
Relation
Encadeamento
wherehavingselectgrouporderlimitoffsetjoinsincludeslockreadonlyfrom
Nova API (where, limit, having)
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
1) internamente
2) minha app?
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
Nova API (where, limit, having)
Relation
Encadeamento
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
querys dinâmicas
class Post < ActiveRecord::Base belongs_to :usuario end
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
querys dinâmicas
class Post < ActiveRecord::Base belongs_to :usuario endtexto
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
querys dinâmicas
class Post < ActiveRecord::Base belongs_to :usuario endtexto
> 1 ano
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
querys dinâmicas
class Post < ActiveRecord::Base belongs_to :usuario endtexto
> 1 anotrue
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
> rails 2{ :filter => { :conteudo => "texto", :comentarios => true, :usuario_id => "1" } }
conditionsnamed scopes
Tuesday, September 14, 2010
Rails 3 Internals
class PostTest < ActiveSupport::TestCase
setup do create_posts end
test "filtro em branco devolve todos os posts" do assert_equal Post.all, Post.filtered_relation({}).all end
def create_posts valid_attributes = { :body => "Hello.", :title => "Hi!", :content => "text", :user_id => 1, :published_at => Time.now }
@base = Post.create(valid_attributes) @quote = Post.create(valid_attributes.merge(:content => "quote")) @number2 = Post.create(valid_attributes.merge(:user_id => 2)) @old = Post.create(valid_attribtues.merge(:published_at => 1.year.ago))
end end
Tuesday, September 14, 2010
Rails 3 Internals
class PostTest < ActiveSupport::TestCase
setup do create_posts end
test "filtro em branco devolve todos os posts" do assert_equal Post.all, Post.filtered_relation({}).all end
def create_posts valid_attributes = { :body => "Hello.", :title => "Hi!", :content => "text", :user_id => 1, :published_at => Time.now }
@base = Post.create(valid_attributes) @quote = Post.create(valid_attributes.merge(:content => "quote")) @number2 = Post.create(valid_attributes.merge(:user_id => 2)) @old = Post.create(valid_attribtues.merge(:published_at => 1.year.ago))
end end
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
class Post < ActiveRecord::Base belongs_to :user
end
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
class Post < ActiveRecord::Base belongs_to :user
end
def self.filtered_relation(params) relation = scoped
end
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
class Post < ActiveRecord::Base belongs_to :user
end
def self.filtered_relation(params) relation = scoped
end
params.each do |facet, value| relation = send("filter_by_#{facet}", value, relation) end
relation
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
class Post < ActiveRecord::Base belongs_to :user
end
def self.filtered_relation(params) relation = scoped
end
params.each do |facet, value| relation = send("filter_by_#{facet}", value, relation) end
relation
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
class Post < ActiveRecord::Base belongs_to :user
end
def self.filter_by_content(value, relation) relation.where(:content => value) end
def self.filtered_relation(params) relation = scoped
end
params.each do |facet, value| relation = send("filter_by_#{facet}", value, relation) end
relation
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
class Post < ActiveRecord::Base belongs_to :user
end
def self.filter_by_content(value, relation) relation.where(:content => value) end
test "apenas posts com conteudo especifico" do assert_equal @quote, Post.filtered_relation(:content => "quote").first end
def self.filtered_relation(params) relation = scoped
end
params.each do |facet, value| relation = send("filter_by_#{facet}", value, relation) end
relation
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
class Post < ActiveRecord::Base belongs_to :user
end
def self.filter_by_content(value, relation) relation.where(:content => value) end
test "apenas posts com conteudo especifico" do assert_equal @quote, Post.filtered_relation(:content => "quote").first end
def self.filtered_relation(params) relation = scoped
end
params.each do |facet, value| relation = send("filter_by_#{facet}", value, relation) end
relation
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
class Post < ActiveRecord::Base belongs_to :user
def self.filtered_relation(params) relation = scoped params.each do |facet, value| relation = send("filter_by_#{facet}", value, relation) end
relation endend
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
class Post < ActiveRecord::Base belongs_to :user
def self.filtered_relation(params) relation = scoped params.each do |facet, value| relation = send("filter_by_#{facet}", value, relation) end
relation endend
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
def self.filter_by_published_at(value, relation) value ? relation.where("published_at < ?", 1.month.ago) : relation end
class Post < ActiveRecord::Base belongs_to :user
def self.filtered_relation(params) relation = scoped params.each do |facet, value| relation = send("filter_by_#{facet}", value, relation) end
relation endend
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
def self.filter_by_published_at(value, relation) value ? relation.where("published_at < ?", 1.month.ago) : relation end
test "given a date filter, only gives us the filtered records" do assert_equal @old, Post.filtered_relation(:published_at => true).first end
class Post < ActiveRecord::Base belongs_to :user
def self.filtered_relation(params) relation = scoped params.each do |facet, value| relation = send("filter_by_#{facet}", value, relation) end
relation endend
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
def self.filter_by_published_at(value, relation) value ? relation.where("published_at < ?", 1.month.ago) : relation end
test "given a date filter, only gives us the filtered records" do assert_equal @old, Post.filtered_relation(:published_at => true).first end
class Post < ActiveRecord::Base belongs_to :user
def self.filtered_relation(params) relation = scoped params.each do |facet, value| relation = send("filter_by_#{facet}", value, relation) end
relation endend
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
def self.filter_by_comments(value, relation) if value relation.preload(:comments).\ select("posts.*, COUNT(comments.id) AS comment_count").\ from("posts, comments").having("comment_count > 0") else relation end end
test "given a comments count filter, only gives us the filtered records" do assert_equal @base, Post.filtered_relation(:comments => true).first end
class Post < ActiveRecord::Base belongs_to :user
def self.filtered_relation(params) relation = scoped params.each do |facet, value| relation = send("filter_by_#{facet}", value, relation) end
relation endend
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
def self.filter_by_comments(value, relation) if value relation.preload(:comments).\ select("posts.*, COUNT(comments.id) AS comment_count").\ from("posts, comments").having("comment_count > 0") else relation end end
test "given a comments count filter, only gives us the filtered records" do assert_equal @base, Post.filtered_relation(:comments => true).first end
class Post < ActiveRecord::Base belongs_to :user
def self.filtered_relation(params) relation = scoped params.each do |facet, value| relation = send("filter_by_#{facet}", value, relation) end
relation endend
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
def self.filter_by_comments(value, relation) if value relation.preload(:comments).\ select("posts.*, COUNT(comments.id) AS comment_count").\ from("posts, comments").having("comment_count > 0") else relation end end
test "given a comments count filter, only gives us the filtered records" do assert_equal @base, Post.filtered_relation(:comments => true).first end
class Post < ActiveRecord::Base belongs_to :user
def self.filtered_relation(params) relation = scoped params.each do |facet, value| relation = send("filter_by_#{facet}", value, relation) end
relation endend
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
test "given a content and comment filter, gives us filtered records" do @base.update_attribute(:content, "picture")
assert_equal @base, Post.filtered_relation(:content => "picture", :comments => true).first
end
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
test "given a content and comment filter, gives us filtered records" do @base.update_attribute(:content, "picture")
assert_equal @base, Post.filtered_relation(:content => "picture", :comments => true).first
end
test "given a date and comment filter, gives us filtered records" do @base.update_attribute(:published_at, 2.years.ago)
assert_equal @base, Post.filtered_relation(:published_at => true, :comments => true).first
end
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
test "given a content and comment filter, gives us filtered records" do @base.update_attribute(:content, "picture")
assert_equal @base, Post.filtered_relation(:content => "picture", :comments => true).first
end
test "given a date and comment filter, gives us filtered records" do @base.update_attribute(:published_at, 2.years.ago)
assert_equal @base, Post.filtered_relation(:published_at => true, :comments => true).first
end
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
test "given a content and comment filter, gives us filtered records" do @base.update_attribute(:content, "picture")
assert_equal @base, Post.filtered_relation(:content => "picture", :comments => true).first
end
test "given a date and comment filter, gives us filtered records" do @base.update_attribute(:published_at, 2.years.ago)
assert_equal @base, Post.filtered_relation(:published_at => true, :comments => true).first
end
test "given a date and content filter, gives us filtered records" do @base.update_attribute(:published_at, 2.years.ago) @base.update_attribute(:content, "picture")
record = Post.filtered_relation(:published_at => true, :content => "picture").first
assert_equal @base, record end
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
test "given a content and comment filter, gives us filtered records" do @base.update_attribute(:content, "picture")
assert_equal @base, Post.filtered_relation(:content => "picture", :comments => true).first
end
test "given a date and comment filter, gives us filtered records" do @base.update_attribute(:published_at, 2.years.ago)
assert_equal @base, Post.filtered_relation(:published_at => true, :comments => true).first
end
test "given a date and content filter, gives us filtered records" do @base.update_attribute(:published_at, 2.years.ago) @base.update_attribute(:content, "picture")
record = Post.filtered_relation(:published_at => true, :content => "picture").first
assert_equal @base, record end
Tuesday, September 14, 2010
ActiveRelation
Rails 3 Internals
posts = Post.filtered_relation(:comments => true).where(:user_id => 4).limit(3).order("id ASC")
posts.each do |post| # Do something here... end
Tuesday, September 14, 2010
Reflexão
Rails 3 Internals
Tuesday, September 14, 2010
Reflexão
Rails 3 Internals
Tuesday, September 14, 2010
class Message extend ActiveModel::Callbacks define_model_callbacks :deliver
def deliver _run_deliver_callbacks do puts "DELIVER!" end end
end
ActiveModel
Rails 3 Internals
Tuesday, September 14, 2010
class Message include ActiveModel::Validations
validates_presence_of :body, :user_id attr_accessor :body, :user_id, :posted_at
end m = Message.new(nil, 13) m.valid? # => false m.body = "Hello there!" m.valid? # => true
ActiveModel
Rails 3 Internals
Tuesday, September 14, 2010
class Message include ActiveModel::Validations
validates_presence_of :body, :user_id attr_accessor :body, :user_id, :posted_at
end m = Message.new(nil, 13) m.valid? # => false m.body = "Hello there!" m.valid? # => true
ActiveModel
Rails 3 Internals
AttributesCallbacksErrorsObservingSerializationTranslationValidations
Tuesday, September 14, 2010
ActiveModel
Rails 3 Internals
class ProperCategoryValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value) unless record.user.category_ids.include?(value) record.errors.add attribute, 'has bad category.' end end
end
Tuesday, September 14, 2010
ActiveModel
Rails 3 Internals
class ProperCategoryValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value) unless record.user.category_ids.include?(value) record.errors.add attribute, 'has bad category.' end end
end
validate :category_id, :proper_category => true
Tuesday, September 14, 2010
ActiveModel
Rails 3 Internals
class ProperCategoryValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value) unless record.user.category_ids.include?(value) record.errors.add attribute, 'has bad category.' end end
end
validate :category_id, :proper_category => true
Tuesday, September 14, 2010
ActiveModel
Rails 3 Internals
class ProperCategoryValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value) unless record.user.category_ids.include?(value) record.errors.add attribute, 'has bad category.' end end
end
validate :category_id, :proper_category => true
Tuesday, September 14, 2010
ActiveModel
Rails 3 Internals
class ReallyComplexValidator < ActiveModel::Validator
def validate(record) record.errors[:base] << "Validacao A" unless valid_a (record) record.errors[:base] << "Validacao B" unless valid_b (record) record.errors[:base] << "Validacao C" unless valid_c (record) end
private
def valid_a (record) # ... end def valid_b (record) # ... end def valid_c (record) # ... end end
Tuesday, September 14, 2010
ActiveModel
Rails 3 Internals
class ReallyComplexValidator < ActiveModel::Validator
def validate(record) record.errors[:base] << "Validacao A" unless valid_a (record) record.errors[:base] << "Validacao B" unless valid_b (record) record.errors[:base] << "Validacao C" unless valid_c (record) end
private
def valid_a (record) # ... end def valid_b (record) # ... end def valid_c (record) # ... end end
Tuesday, September 14, 2010
ActiveModel
Rails 3 Internals
class ReallyComplexValidator < ActiveModel::Validator
def validate(record) record.errors[:base] << "Validacao A" unless valid_a (record) record.errors[:base] << "Validacao B" unless valid_b (record) record.errors[:base] << "Validacao C" unless valid_c (record) end
private
def valid_a (record) # ... end def valid_b (record) # ... end def valid_c (record) # ... end end
class NewsPost < ActiveRecord::Base validates_with ReallyComplexValidator end
Tuesday, September 14, 2010
ActiveModel
Rails 3 Internals
template rendering, controller logic, e database query results
<% cache do %> <% @posts.each do |post| %> <%= render :partial => 'post', :object => post %> <% end %>
<% end %>
Tuesday, September 14, 2010
ActiveRecord::Relationvs
ARel
Rails 3 Internals
Tuesday, September 14, 2010
Rails 3 Internals
Rails 3 > Modularidade
Desacoplamento
Tuesday, September 14, 2010
Rails 3 Internals
Opnionated ?
Meta-framework ?
Rails 3 > Modularidade
Tuesday, September 14, 2010
Rails 3 Internals
config.ru
# This file is used by Rack-based servers to start the application.
require ::File.expand_path('../config/environment', __FILE__)run MinhaApp::Application
Rails 3
Tuesday, September 14, 2010
Railtie > Engine > Application
Rails 3 Internals
Inicializar Rails App
Coordenar processos de boot
Carregar plugins
Carregar ActiveSupport
Outros: database, logging, sessions
Tuesday, September 14, 2010
Rails 3 Internals
Tuesday, September 14, 2010
Railtie - autoload
Rails 3 Internals
Tuesday, September 14, 2010
Railtie - autoload
Rails 3 Internals
Tuesday, September 14, 2010
Railtie - autoload
Rails 3 Internals
Tuesday, September 14, 2010
Railtie
Rails 3 Internals
Tuesday, September 14, 2010
Railtie
Rails 3 Internals
Tuesday, September 14, 2010
Railtie
Rails 3 Internals
Tuesday, September 14, 2010
Railtie
Rails 3 Internals
Tuesday, September 14, 2010
Railtie
Rails 3 Internals
Tuesday, September 14, 2010
Railtie
Rails 3 Internals
Frameworks Rails > Rails Plugins
Tuesday, September 14, 2010
Rails 3 Internals
Railtie ... Plugins....ARel....
Tuesday, September 14, 2010
Railtie ... Plugins....ARel....
Rails 3 Internals
require 'filtered_relation'require 'rails'
module FilteredRelation class Railtie < Rails::Railtie railtie_name :filtered_relation
endend
Tuesday, September 14, 2010
Railtie ... Plugins....ARel....
Rails 3 Internals
require 'filtered_relation'require 'rails'
module FilteredRelation class Railtie < Rails::Railtie railtie_name :filtered_relation
endend
código
Tuesday, September 14, 2010
Links
Rails 3 Internals
http://www.engineyard.com/blog/2010/rails-and-merb-merge-orm-agnosticism-part-5-of-6/
http://vimeo.com/14550567
http://github.com/rails/rails/blob/master/activerecord/lib/active_record/relation.rb
http://piotrsarnacki.com/2010/06/18/rails-internals-railties/
http://rubyonrails.org/screencasts/rails3/action-controller
http://www.igvita.com/2010/08/04/rails-3-internals-railtie-creating-plugins/
http://piotrsarnacki.com/2010/06/18/rails-internals-railties/
http://metautonomo.us/2010/05/11/activerecord-relation-vs-arel/
Tuesday, September 14, 2010
Rails 3 InternalsConhecendo detalhes do framework que fazem a diferença.
Anderson Leite
@anderson_leite
www.andersonleite.com.br
Obrigado!
Tuesday, September 14, 2010