Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Rails 3 Internals

2,018 views

Published on

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.

Published in: Technology
  • Be the first to comment

  • Be the first to like this

Rails 3 Internals

  1. 1. Rails 3 Internals Conhecendo detalhes do framework que fazem a diferença. Anderson Leite @anderson_leite www.andersonleite.com.br Tuesday, September 14, 2010
  2. 2. Rails 3 Internals Rails 3 Architectural changes Rails + Merb Tuesday, September 14, 2010
  3. 3. Rails 3 Internals Rails 3 Modularidade Tuesday, September 14, 2010
  4. 4. Rails 3 Internals ActiveRelation ActiveModel Railtie Tuesday, September 14, 2010
  5. 5. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  6. 6. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  7. 7. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  8. 8. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  9. 9. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  10. 10. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  11. 11. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  12. 12. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  13. 13. Rails 3 Internals Tuesday, September 14, 2010
  14. 14. Rails 3 Internals Diego Carrion ?? Tuesday, September 14, 2010
  15. 15. Rails 3 Internals Diego Carrion ?? Tuesday, September 14, 2010
  16. 16. Rails 3 Internals Diego Carrion ?? Tuesday, September 14, 2010
  17. 17. Rails 3 Internals Diego Carrion ?? Tuesday, September 14, 2010
  18. 18. Rails 3 Internals ActiveRelation # Rails 2 @models = Model.find(:all, :conditions => {:value => true} ) Tuesday, September 14, 2010
  19. 19. Rails 3 Internals ActiveRelation # Rails 2 @models = Model.find(:all, :conditions => {:value => true} ) # Rails 3 @models = Model.where(:value => true) Tuesday, September 14, 2010
  20. 20. Rails 3 Internals ActiveRelation # Rails 2 @models = Model.find(:all, :conditions => {:value => true} ) # Rails 3 @models = Model.where(:value => true) @models = @models.order(params[:order]) Tuesday, September 14, 2010
  21. 21. Rails 3 Internals ActiveRelation # Rails 2 @models = Model.find(:all, :conditions => {:value => true} ) # Rails 3 @models = Model.where(:value => true) @models = @models.order(params[:order]) @models = Model.where(:value => true).order(params[:order]) Tuesday, September 14, 2010
  22. 22. Rails 3 Internals ActiveRelation # Rails 2 @models = Model.find(:all, :conditions => {:value => true} ) Array # Rails 3 @models = Model.where(:value => true) @models = @models.order(params[:order]) @models = Model.where(:value => true).order(params[:order]) Tuesday, September 14, 2010
  23. 23. Rails 3 Internals ActiveRelation # Rails 2 @models = Model.find(:all, :conditions => {:value => true} ) Array # 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
  24. 24. Rails 3 Internals ActiveRelation # 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
  25. 25. Rails 3 Internals ActiveRelation # 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
  26. 26. Rails 3 Internals ActiveRelation # 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 Lazy Tuesday, September 14, 2010
  27. 27. Rails 3 Internals ActiveRelation # Rails 3 @models = Model.where(:value => true).order(params[:order]).all Tuesday, September 14, 2010
  28. 28. Rails 3 Internals ActiveRelation # Rails 3 @models = Model.where(:value => true).order(params[:order]).all Nova API (where, limit, having) Tuesday, September 14, 2010
  29. 29. Rails 3 Internals ActiveRelation # Rails 3 @models = Model.where(:value => true).order(params[:order]).all where having select group Nova API (where, limit, having) order limit offset joins includes lock readonly from Tuesday, September 14, 2010
  30. 30. Rails 3 Internals ActiveRelation # Rails 3 @models = Model.where(:value => true).order(params[:order]).all where having select group Nova API (where, limit, having) order limit Relation offset joins Encadeamento includes lock readonly from Tuesday, September 14, 2010
  31. 31. Rails 3 Internals ActiveRelation 1) internamente 2) minha app? Tuesday, September 14, 2010
  32. 32. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  33. 33. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  34. 34. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  35. 35. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  36. 36. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  37. 37. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  38. 38. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  39. 39. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  40. 40. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  41. 41. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  42. 42. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  43. 43. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  44. 44. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  45. 45. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  46. 46. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  47. 47. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  48. 48. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  49. 49. Rails 3 Internals ActiveRelation Nova API (where, limit, having) Relation Encadeamento Tuesday, September 14, 2010
  50. 50. Rails 3 Internals ActiveRelation querys dinâmicas class Post < ActiveRecord::Base belongs_to :usuario end Tuesday, September 14, 2010
  51. 51. Rails 3 Internals ActiveRelation querys dinâmicas class Post < ActiveRecord::Base belongs_to :usuario texto end Tuesday, September 14, 2010
  52. 52. Rails 3 Internals ActiveRelation querys dinâmicas class Post < ActiveRecord::Base belongs_to :usuario texto end > 1 ano Tuesday, September 14, 2010
  53. 53. Rails 3 Internals ActiveRelation querys dinâmicas class Post < ActiveRecord::Base belongs_to :usuario texto end > 1 ano true Tuesday, September 14, 2010
  54. 54. Rails 3 Internals ActiveRelation { :filter => { > rails 2 :conteudo => "texto", :comentarios => true, conditions :usuario_id => "1" } named scopes } Tuesday, September 14, 2010
  55. 55. 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
  56. 56. 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
  57. 57. Rails 3 Internals ActiveRelation class Post < ActiveRecord::Base belongs_to :user end Tuesday, September 14, 2010
  58. 58. Rails 3 Internals ActiveRelation class Post < ActiveRecord::Base belongs_to :user def self.filtered_relation(params) relation = scoped end end Tuesday, September 14, 2010
  59. 59. Rails 3 Internals ActiveRelation 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 end end Tuesday, September 14, 2010
  60. 60. Rails 3 Internals ActiveRelation 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 end end Tuesday, September 14, 2010
  61. 61. Rails 3 Internals ActiveRelation class Post < ActiveRecord::Base def self.filter_by_content(value, relation) belongs_to :user relation.where(:content => value) end def self.filtered_relation(params) relation = scoped params.each do |facet, value| relation = send("filter_by_#{facet}", value, relation) end relation end end Tuesday, September 14, 2010
  62. 62. Rails 3 Internals ActiveRelation test "apenas posts com conteudo especifico" do assert_equal @quote, Post.filtered_relation(:content => "quote").first end class Post < ActiveRecord::Base def self.filter_by_content(value, relation) belongs_to :user relation.where(:content => value) end def self.filtered_relation(params) relation = scoped params.each do |facet, value| relation = send("filter_by_#{facet}", value, relation) end relation end end Tuesday, September 14, 2010
  63. 63. Rails 3 Internals ActiveRelation test "apenas posts com conteudo especifico" do assert_equal @quote, Post.filtered_relation(:content => "quote").first end class Post < ActiveRecord::Base def self.filter_by_content(value, relation) belongs_to :user relation.where(:content => value) end def self.filtered_relation(params) relation = scoped params.each do |facet, value| relation = send("filter_by_#{facet}", value, relation) end relation end end Tuesday, September 14, 2010
  64. 64. Rails 3 Internals ActiveRelation 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 end end Tuesday, September 14, 2010
  65. 65. Rails 3 Internals ActiveRelation 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 end end Tuesday, September 14, 2010
  66. 66. Rails 3 Internals ActiveRelation 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 end end Tuesday, September 14, 2010
  67. 67. Rails 3 Internals ActiveRelation test "given a date filter, only gives us the filtered records" do assert_equal @old, Post.filtered_relation(:published_at => true).first end 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 end end Tuesday, September 14, 2010
  68. 68. Rails 3 Internals ActiveRelation test "given a date filter, only gives us the filtered records" do assert_equal @old, Post.filtered_relation(:published_at => true).first end 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 end end Tuesday, September 14, 2010
  69. 69. Rails 3 Internals ActiveRelation test "given a comments count filter, only gives us the filtered records" do assert_equal @base, Post.filtered_relation(:comments => true).first end def self.filter_by_comments(value, relation) if value relation.preload(:comments). select("posts.*, COUNT(comments.id) AS comment_count"). class Post < ActiveRecord::Base from("posts, comments").having("comment_count > 0") belongs_to :user else relation def self.filtered_relation(params) end end relation = scoped params.each do |facet, value| relation = send("filter_by_#{facet}", value, relation) end relation end end Tuesday, September 14, 2010
  70. 70. Rails 3 Internals ActiveRelation test "given a comments count filter, only gives us the filtered records" do assert_equal @base, Post.filtered_relation(:comments => true).first end def self.filter_by_comments(value, relation) if value relation.preload(:comments). select("posts.*, COUNT(comments.id) AS comment_count"). class Post < ActiveRecord::Base from("posts, comments").having("comment_count > 0") belongs_to :user else relation def self.filtered_relation(params) end end relation = scoped params.each do |facet, value| relation = send("filter_by_#{facet}", value, relation) end relation end end Tuesday, September 14, 2010
  71. 71. Rails 3 Internals ActiveRelation test "given a comments count filter, only gives us the filtered records" do assert_equal @base, Post.filtered_relation(:comments => true).first end def self.filter_by_comments(value, relation) if value relation.preload(:comments). select("posts.*, COUNT(comments.id) AS comment_count"). class Post < ActiveRecord::Base from("posts, comments").having("comment_count > 0") belongs_to :user else relation def self.filtered_relation(params) end end relation = scoped params.each do |facet, value| relation = send("filter_by_#{facet}", value, relation) end relation end end Tuesday, September 14, 2010
  72. 72. Rails 3 Internals ActiveRelation 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
  73. 73. Rails 3 Internals ActiveRelation 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
  74. 74. Rails 3 Internals ActiveRelation 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
  75. 75. Rails 3 Internals ActiveRelation 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
  76. 76. Rails 3 Internals ActiveRelation 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
  77. 77. Rails 3 Internals ActiveRelation 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
  78. 78. Rails 3 Internals Reflexão Tuesday, September 14, 2010
  79. 79. Rails 3 Internals Reflexão Tuesday, September 14, 2010
  80. 80. Rails 3 Internals ActiveModel class Message extend ActiveModel::Callbacks define_model_callbacks :deliver def deliver _run_deliver_callbacks do puts "DELIVER!" end end end Tuesday, September 14, 2010
  81. 81. Rails 3 Internals ActiveModel 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 Tuesday, September 14, 2010
  82. 82. Rails 3 Internals ActiveModel class Message include ActiveModel::Validations Attributes validates_presence_of :body, :user_id attr_accessor :body, :user_id, :posted_at Callbacks Errors end Observing m = Message.new(nil, 13) Serialization m.valid? # => false Translation m.body = "Hello there!" m.valid? # => true Validations Tuesday, September 14, 2010
  83. 83. Rails 3 Internals ActiveModel 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
  84. 84. Rails 3 Internals ActiveModel 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
  85. 85. Rails 3 Internals ActiveModel 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
  86. 86. Rails 3 Internals ActiveModel 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
  87. 87. Rails 3 Internals ActiveModel 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
  88. 88. Rails 3 Internals ActiveModel 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
  89. 89. Rails 3 Internals ActiveModel 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) class NewsPost < ActiveRecord::Base # ... end validates_with ReallyComplexValidator end def valid_b (record) # ... end def valid_c (record) # ... end end Tuesday, September 14, 2010
  90. 90. Rails 3 Internals ActiveModel 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
  91. 91. Rails 3 Internals ActiveRecord::Relation vs ARel Tuesday, September 14, 2010
  92. 92. Rails 3 Internals Rails 3 > Modularidade Desacoplamento Tuesday, September 14, 2010
  93. 93. Rails 3 Internals Rails 3 > Modularidade Opnionated ? Meta-framework ? Tuesday, September 14, 2010
  94. 94. Rails 3 Internals Rails 3 config.ru # This file is used by Rack-based servers to start the application. require ::File.expand_path('../config/environment', __FILE__) run MinhaApp::Application Tuesday, September 14, 2010
  95. 95. Rails 3 Internals Railtie > Engine > Application Inicializar Rails App Coordenar processos de boot Carregar plugins Carregar ActiveSupport Outros: database, logging, sessions Tuesday, September 14, 2010
  96. 96. Rails 3 Internals Tuesday, September 14, 2010
  97. 97. Rails 3 Internals Railtie - autoload Tuesday, September 14, 2010
  98. 98. Rails 3 Internals Railtie - autoload Tuesday, September 14, 2010
  99. 99. Rails 3 Internals Railtie - autoload Tuesday, September 14, 2010
  100. 100. Rails 3 Internals Railtie Tuesday, September 14, 2010
  101. 101. Rails 3 Internals Railtie Tuesday, September 14, 2010
  102. 102. Rails 3 Internals Railtie Tuesday, September 14, 2010
  103. 103. Rails 3 Internals Railtie Tuesday, September 14, 2010
  104. 104. Rails 3 Internals Railtie Tuesday, September 14, 2010
  105. 105. Rails 3 Internals Railtie Frameworks Rails > Rails Plugins Tuesday, September 14, 2010
  106. 106. Rails 3 Internals Railtie ... Plugins....ARel.... Tuesday, September 14, 2010
  107. 107. Rails 3 Internals Railtie ... Plugins....ARel.... require 'filtered_relation' require 'rails' module FilteredRelation class Railtie < Rails::Railtie railtie_name :filtered_relation end end Tuesday, September 14, 2010
  108. 108. Rails 3 Internals Railtie ... Plugins....ARel.... require 'filtered_relation' require 'rails' module FilteredRelation class Railtie < Rails::Railtie railtie_name :filtered_relation código end end Tuesday, September 14, 2010
  109. 109. Rails 3 Internals Links 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
  110. 110. Obrigado! Rails 3 Internals Conhecendo detalhes do framework que fazem a diferença. Anderson Leite @anderson_leite www.andersonleite.com.br Tuesday, September 14, 2010

×