Rails 3 Internals

Post on 10-May-2015

1,747 views 1 download

Tags:

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