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.

Polo: Desenvolvendo os problemas de inconsistência de dados em projetos Rails

263 views

Published on

Sabe aquele bug que só acontece em produção? Aquela tela que renderiza um pouco diferente porque tem aqueles dados diferentes que só existem no banco de dados de prod? Ou aquele usuário maluco que causou todos aqueles corner cases porque o input dele era muito diferente? Todo mundo já passou por esses problemas! E por que essas coisas acontecem? Uma das respostas é fácil: faltaram dados. Depois de muita dor de cabeça brigando com rake db:seeds, db:migrations, muito SQL e de abrir muito rails console em produção que eu resolvi que era hora de resolver esse problema de uma maneira diferente. Foi aí que eu criei o Polo. Uma ruby gem que automatiza a criação de dumps do seu banco de dados em produção e gera amostras pra você poder importar no seu ambiente de desenvolvimento. Não perca mais tempo quebrando a cabeça com dados inconsistentes, fazendo deploys para produção só pra testar um corner case, ou abrindo console do rails em produção e brincando com a morte.

Published in: Education
  • Be the first to comment

  • Be the first to like this

Polo: Desenvolvendo os problemas de inconsistência de dados em projetos Rails

  1. 1. POLO WORKINGWITHREALWORLDDATAIN DEVELOPMENT @nettofarah 1 / 39
  2. 2. nettofarah github.com/nettofarah @nettofarah http://bit.ly/polo-rb 2 / 39
  3. 3. RealWorldProductionDatain Development 3 / 39
  4. 4. BecauseManagingDataishard Especially across Different environments 4 / 39
  5. 5. Datain Rails.env.dev is... Ugly, Incomplete, Weird and Biased 5 / 39
  6. 6. SomeConsequencesofInconsistent Data 6 / 39
  7. 7. !"!",##misalignment,form validation,specialcharacters$$ 7 / 39
  8. 8. TheWorstConsequence 8 / 39
  9. 9. Rails.env.dev will look % 9 / 39
  10. 10. Buthowdopeoplesolvethese problems? 10 / 39
  11. 11. Wecantestitin PRODUCTION 11 / 39
  12. 12. Rails.env.staging ? 12 / 39
  13. 13. Custom db/migrations fordata 13 / 39
  14. 14. rake db:seed 14 / 39
  15. 15. CSVsandSpreadsheets 15 / 39
  16. 16. 16 / 39
  17. 17. SampleDatabaseSnapshots 17 / 39
  18. 18. Your good ol' ActiveRecord::Associations to .sql 18 / 39
  19. 19. POLOletsyouturnthis... 19 / 39
  20. 20. class Chef < ActiveRecord::Base has_many :recipes has_many :ingredients, through: :recipes end class Recipe < ActiveRecord::Base has_many :recipes_ingredients has_many :ingredients, through: :recipes_ingredients end class Ingredient < ActiveRecord::Base end class RecipesIngredient < ActiveRecord::Base belongs_to :recipe belongs_to :ingredient end 20 / 39
  21. 21. Intothis... 21 / 39
  22. 22. inserts = Polo.explore(Chef, 1) # Chef -> ActiveRecord::Base object # 1 -> Database ID. (Chef with ID 1) INSERT INTO `chefs` (`id`, `name`) VALUES (1, 'Netto') 22 / 39
  23. 23. Itworkswithassociationstoo 23 / 39
  24. 24. inserts = Polo.explore(Chef, 1, :recipes) # :recipes -> # ActiveRecord::Associations::HasManyAssociation # # a Chef has many Recipes INSERT INTO `chefs` (`id`, `name`) VALUES (1, 'Netto') INSERT INTO `recipes` (`id`, `title`, `num_steps`, `chef_id`) VALUES (1, 'Turkey Sandwich', NULL, 1) INSERT INTO `recipes` (`id`, `title`, `num_steps`, `chef_id`) VALUES (2, 'Cheese Burger', NULL, 1) 24 / 39
  25. 25. Italsoworkswithnested associations 25 / 39
  26. 26. inserts = Polo.explore(Chef, 1, { :recipes => :ingredients }) # { :recipes => :ingredients } -> # load every recipe and ingredientes ... INSERT INTO `recipes` (`id`, `title`, `num_steps`, `chef_id`) VALUES (1, 'Turkey Sandwich', NULL, 1) INSERT INTO `recipes` (`id`, `title`, `num_steps`, `chef_id`) VALUES (2, 'Cheese Burger', NULL, 1) INSERT INTO `recipes_ingredients` (`id`, `recipe_id`, `ingredient_id`) VALUES (1, 1, 1) INSERT INTO `recipes_ingredients` (`id`, `recipe_id`, `ingredient_id`) VALUES (2, 1, 2) ... INSERT INTO `ingredients` (`id`, `name`, `quantity`) VALUES (1, 'Turkey', 'a lot') INSERT INTO `ingredients` (`id`, `name`, `quantity`) VALUES (2, 'Cheese', '1 slice') ... 26 / 39
  27. 27. && Showmethemagic! 27 / 39
  28. 28. Collectalltheobjects lib/polo/collector.rb#L16 28 / 39
  29. 29. asn = ActiveSupport::Notifications # Extracted so this can fit in a slide asn.subscribed(collector, 'sql.active_record') do # Set up ActiveRecord::Preloader base_finder = @base_class. includes(@dependency_tree) .where(id: @id) # Store SELECTS in some global storage collect_sql(@base_class, base_finder.to_sql) end 29 / 39
  30. 30. '' TransformthemtoSQL lib/polo/sql_translator.rb#51 30 / 39
  31. 31. attributes = record.attributes keys = attributes.keys.map do |key| "`#{key}`" end values = attributes.map do |key, value| column = record.column_for_attribute(key) attribute = cast_attribute(record, column, value) connection.quote(attribute) end joined_keys = keys.join(', ') joined_values = values.join(', ') table_name = record.class.table_name "INSERT INTO `#{table_name}`" + " (#{joined_keys}) VALUES (#{joined_values})" 31 / 39
  32. 32. PROFIT!(( 32 / 39
  33. 33. Ineedyourhelp!)) 33 / 39
  34. 34. onGithub http://github.com/IFTTT/polo 34 / 39
  35. 35. PullRequests** 35 / 39
  36. 36. PostgreSQL,SQLiteandOracle support (advanced features only, basic usage still works) 36 / 39
  37. 37. ActiveRecord<3.2support 37 / 39
  38. 38. Checkoutsomeotherreallycool OpenSourceprojects http://ifttt.github.io 38 / 39
  39. 39. Questions? 39 / 39

×