Your SlideShare is downloading. ×
Rails 3 Internals
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Rails 3 Internals

1,731

Published on

O Rails 3 foi finalmente anunciado e nele uma série de mudanças arquiteturais foram feitas. …

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
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
1,731
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
27
Comments
0
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 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. Rails 3 Internals Rails 3 Architectural changes Rails + Merb Tuesday, September 14, 2010
  • 3. Rails 3 Internals Rails 3 Modularidade Tuesday, September 14, 2010
  • 4. Rails 3 Internals ActiveRelation ActiveModel Railtie Tuesday, September 14, 2010
  • 5. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  • 6. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  • 7. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  • 8. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  • 9. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  • 10. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  • 11. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  • 12. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  • 13. Rails 3 Internals Tuesday, September 14, 2010
  • 14. Rails 3 Internals Diego Carrion ?? Tuesday, September 14, 2010
  • 15. Rails 3 Internals Diego Carrion ?? Tuesday, September 14, 2010
  • 16. Rails 3 Internals Diego Carrion ?? Tuesday, September 14, 2010
  • 17. Rails 3 Internals Diego Carrion ?? Tuesday, September 14, 2010
  • 18. Rails 3 Internals ActiveRelation # Rails 2 @models = Model.find(:all, :conditions => {:value => true} ) Tuesday, September 14, 2010
  • 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. 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. 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. 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. 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. 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. 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. 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. Rails 3 Internals ActiveRelation # Rails 3 @models = Model.where(:value => true).order(params[:order]).all Tuesday, September 14, 2010
  • 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. 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. 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. Rails 3 Internals ActiveRelation 1) internamente 2) minha app? Tuesday, September 14, 2010
  • 32. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  • 33. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  • 34. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  • 35. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  • 36. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  • 37. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  • 38. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  • 39. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  • 40. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  • 41. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  • 42. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  • 43. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  • 44. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  • 45. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  • 46. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  • 47. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  • 48. Rails 3 Internals ActiveRelation Tuesday, September 14, 2010
  • 49. Rails 3 Internals ActiveRelation Nova API (where, limit, having) Relation Encadeamento Tuesday, September 14, 2010
  • 50. Rails 3 Internals ActiveRelation querys dinâmicas class Post < ActiveRecord::Base belongs_to :usuario end Tuesday, September 14, 2010
  • 51. Rails 3 Internals ActiveRelation querys dinâmicas class Post < ActiveRecord::Base belongs_to :usuario texto end Tuesday, September 14, 2010
  • 52. Rails 3 Internals ActiveRelation querys dinâmicas class Post < ActiveRecord::Base belongs_to :usuario texto end > 1 ano Tuesday, September 14, 2010
  • 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. Rails 3 Internals ActiveRelation { :filter => { > rails 2 :conteudo => "texto", :comentarios => true, conditions :usuario_id => "1" } named scopes } Tuesday, September 14, 2010
  • 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. 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. Rails 3 Internals ActiveRelation class Post < ActiveRecord::Base belongs_to :user end Tuesday, September 14, 2010
  • 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. Rails 3 Internals Reflexão Tuesday, September 14, 2010
  • 79. Rails 3 Internals Reflexão Tuesday, September 14, 2010
  • 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. Rails 3 Internals ActiveRecord::Relation vs ARel Tuesday, September 14, 2010
  • 92. Rails 3 Internals Rails 3 > Modularidade Desacoplamento Tuesday, September 14, 2010
  • 93. Rails 3 Internals Rails 3 > Modularidade Opnionated ? Meta-framework ? Tuesday, September 14, 2010
  • 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. 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. Rails 3 Internals Tuesday, September 14, 2010
  • 97. Rails 3 Internals Railtie - autoload Tuesday, September 14, 2010
  • 98. Rails 3 Internals Railtie - autoload Tuesday, September 14, 2010
  • 99. Rails 3 Internals Railtie - autoload Tuesday, September 14, 2010
  • 100. Rails 3 Internals Railtie Tuesday, September 14, 2010
  • 101. Rails 3 Internals Railtie Tuesday, September 14, 2010
  • 102. Rails 3 Internals Railtie Tuesday, September 14, 2010
  • 103. Rails 3 Internals Railtie Tuesday, September 14, 2010
  • 104. Rails 3 Internals Railtie Tuesday, September 14, 2010
  • 105. Rails 3 Internals Railtie Frameworks Rails > Rails Plugins Tuesday, September 14, 2010
  • 106. Rails 3 Internals Railtie ... Plugins....ARel.... Tuesday, September 14, 2010
  • 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. 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. 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. 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

×