Deep down fixtures

1b0973b64704738dbc8ce24d8382bb1f?s=47 Prathamesh
September 19, 2014

Deep down fixtures

Slides for talk given at RubyKaigi 2014

1b0973b64704738dbc8ce24d8382bb1f?s=128

Prathamesh

September 19, 2014
Tweet

Transcript

  1. 2.

    /rubykaigi2014/speakers/prathamesh.yml prathamesh: company: BigBinary role: Software Engineer hometown: Pune, India

    ruby_group: pune.rb github: prathamesh-sonpatki twitter: _cha1tanya interestes: <%= %w(ruby rails cricket emacs) %>
  2. 4.

    /india/rubyconfs.yml rubyconfindia: website: rubyconfindia.org location: Goa when: April 3rd and

    4th 2015 ! garden_city_ruby_conf: website: gardencityruby.org location: Banglore when: 10 January 2015 cfp: will open soon.. ! deccan_ruby_conf: website: deccanrubyconf.org location: pune when: Around June/July 2015**
  3. 7.

    Why? • We should know the tool before rejecting it

    • Fixtures are baked into Rails
  4. 8.

    Why? • We should know the tool before rejecting it

    • Fixtures are baked into Rails • Understanding what all things are possible with fixtures
  5. 9.

    Why? • We should know the tool before rejecting it

    • Fixtures are baked into Rails • Understanding what all things are possible with fixtures • Staying close to Rails stack
  6. 17.
  7. 18.

    Creating fixtures • As simple as writing .yml files •

    Needs thinking • Needs creativity(to make them memorable)
  8. 20.

    Protip: Key matters repo1: user_name: rails name: rails full_name: rails/rails

    language: ruby created_at: 2012-11-10 21:50:48.351554000 Z updated_at: 2012-11-10 21:50:48.351554000 Z issues_count: 0
  9. 21.

    Protip: Key matters repo1: user_name: rails name: rails full_name: rails/rails

    language: ruby created_at: 2012-11-10 21:50:48.351554000 Z updated_at: 2012-11-10 21:50:48.351554000 Z issues_count: 0 repo = repos(:repo1)
  10. 22.

    Protip: Key matters repo1: user_name: rails name: rails full_name: rails/rails

    language: ruby created_at: 2012-11-10 21:50:48.351554000 Z updated_at: 2012-11-10 21:50:48.351554000 Z issues_count: 0 repo = repos(:repo1)
  11. 23.

    Protip: Key matters rails_rails: user_name: rails name: rails full_name: rails/rails

    language: ruby created_at: 2012-11-10 21:50:48.351554000 Z updated_at: 2012-11-10 21:50:48.351554000 Z issues_count: 0 repo = repos(:rails_rails)
  12. 24.

    Protip:Don’t specify ids** rails_rails: id: 1 user_name: rails name: rails

    full_name: rails/rails language: ruby created_at: 2012-11-10 21:50:48.351554000 Z updated_at: 2012-11-10 21:50:48.351554000 Z issues_count: 0
  13. 25.
  14. 29.
  15. 30.
  16. 32.

    Loading fixtures ! • Read from yaml file • Convert

    into hash • Delete all existing data
  17. 34.

    Loading fixtures • Delete all existing data Fixture Delete (0.3ms)

    DELETE FROM "issue_assignments" Fixture Delete (0.3ms) DELETE FROM "issues" Fixture Delete (0.3ms) DELETE FROM "repo_subscriptions" Fixture Delete (0.3ms) DELETE FROM "repos" Fixture Delete (0.7ms) DELETE FROM "users"
  18. 36.

    Loading fixtures • Delete all existing data • Load data

    Fixture Insert (0.2ms) INSERT INTO "repo_subscriptions" ("user_name", "repo_name", "created_at", "updated_at", "last_sent_at", "email_limit", "id", "repo_id", "user_id") VALUES ('rails', 'rails', '2013-10-29 21:09:48.351554', '2013-10-29 21:09:48.351554', NULL, 5, 836719243, 603590727, 110871456)
  19. 42.

    Loading fixtures # /rails/activerecord/lib/active_record/connection_adapters/abstract/ database_statements.rb ! # Inserts the given

    fixture into the table. Overridden in adapters that # require something beyond a simple insert (eg. Oracle). def insert_fixture(fixture, table_name) columns = schema_cache.columns_hash(table_name) ! key_list = [] value_list = fixture.map do |name, value| key_list << quote_column_name(name) quote(value, columns[name]) end ! execute "INSERT INTO #{quote_table_name(table_name)} (#{key_list.join(', ')}) VALUES (#{value_list.join(', ')})", 'Fixture Insert' end
  20. 52.

    Identifying fixtures # Returns a consistent, platform-independent identifier for +label+.

    # Integer identifiers are values less than 2^30. UUIDs are RFC 4122 versio 5 SHA-1 hashes. def self.identify(label, column_type = :integer) if column_type == :uuid Digest::UUID.uuid_v5(Digest::UUID::OID_NAMESPACE, label.to_s) else Zlib.crc32(label.to_s) % MAX_ID end end
  21. 55.

    Associations schneems_to_triage: repo: issue_triage_sandbox user: schneems user_name: bemurphy repo_name: issue_triage_sandbox

    jroes_to_rails: repo: rails_rails user: jroes user_name: rails repo_name: rails !
  22. 56.

    Associations schneems_to_triage: repo: issue_triage_sandbox user: schneems user_name: bemurphy repo_name: issue_triage_sandbox

    jroes_to_rails: repo: rails_rails user: jroes user_name: rails repo_name: rails !
  23. 58.

    Setting a value to nil • A column with default

    value, but you need NULL • Many ways to do it
  24. 59.

    Setting a value to nil irb(main):001:0> require 'yaml' => true

    irb(main):002:0> YAML.load("--- \n:k: null\n") => {:k=>nil}
  25. 60.

    Setting a value to nil jroes_to_rails: repo: rails_rails user: jroes

    user_name: rails repo_name: rails created_at: 2013-10-29 21:09:48.351554000 Z updated_at: 2013-10-29 21:09:48.351554000 Z last_sent_at: NULL 60
  26. 61.

    Setting a value to nil irb(main):001:0> require 'yaml' => true

    irb(main):002:0> YAML.load("--- \n:k: \n") => {:k=>nil} irb(main):003:0>
  27. 62.

    Setting a value to nil jroes_to_rails: repo: rails_rails user: jroes

    user_name: rails repo_name: rails created_at: 2013-10-29 21:09:48.351554000 Z updated_at: 2013-10-29 21:09:48.351554000 Z last_sent_at:
  28. 63.
  29. 65.

    ERBin it up <% 1.upto(1000) do |i| %> issue_<%= i

    %>: name: rails_<%= i %> <% end %>
  30. 66.

    ERBin it up • Need to generate dynamic data •

    Sprinkle ERB in yaml files • Use with caution
  31. 68.

    Timestamps • Autofills standard timestamp columns if they are not

    present in fixture • Works only if model.record_timestamps is true(default is true)
  32. 69.

    Timestamps # /rails/activerecord/lib/active_record/fixtures.rb ! now = config.default_timezone == :utc ?

    Time.now.utc : Time.now now = now.to_s(:db) ! if model_class.record_timestamps timestamp_column_names.each do |c_name| row[c_name] = now unless row.key?(c_name) end end
  33. 70.

    Timestamps # /rails/activerecord/lib/active_record/fixtures.rb ! now = config.default_timezone == :utc ?

    Time.now.utc : Time.now now = now.to_s(:db) ! if model_class.record_timestamps timestamp_column_names.each do |c_name| row[c_name] = now unless row.key?(c_name) end end
  34. 71.

    Timestamps • Autofills standard timestamp columns if they are not

    present in fixture • Works only if model.record_timestamps is true(default is true) • created_at, updated_at, created_on, updated_on
  35. 75.
  36. 76.

    Label Interpolation # /rails/activerecord/lib/active_record/fixtures.rb ! # interpolate the fixture label

    row.each do |key, value| row[key] = value.gsub("$LABEL", label) if value.is_a? (String) end ! !
  37. 80.

    Database tricks** ! • now is special value in PostGreSQL

    • Shorthand that will be converted to date/time when read. • http://www.postgresql.org/docs/9.3/static/datatype- datetime.html#AEN5861
  38. 81.

    YAML Defaults issue_triage_sandbox: user_name: bemurphy name: issue_triage_sandbox full_name: bemurphy/issue_triage_sandbox language:

    ruby created_at: 2012-11-10 21:50:48.351554000 Z updated_at: 2012-11-10 21:50:48.351554000 Z issues_count: 1 ! rails_rails: user_name: rails name: rails full_name: rails/rails language: ruby created_at: 2012-11-10 21:50:48.351554000 Z updated_at: 2012-11-10 21:50:48.351554000 Z issues_count: 0
  39. 82.

    YAML Defaults issue_triage_sandbox: user_name: bemurphy name: issue_triage_sandbox full_name: bemurphy/issue_triage_sandbox language:

    ruby created_at: 2012-11-10 21:50:48.351554000 Z updated_at: 2012-11-10 21:50:48.351554000 Z issues_count: 1 ! rails_rails: user_name: rails name: rails full_name: rails/rails language: ruby created_at: 2012-11-10 21:50:48.351554000 Z updated_at: 2012-11-10 21:50:48.351554000 Z issues_count: 0
  40. 83.

    YAML Defaults DEFAULTS: &DEFAULTS language: ruby created_at: 2012-11-10 21:50:48.351554000 Z

    updated_at: 2012-11-10 21:50:48.351554000 Z ! issue_triage_sandbox: user_name: bemurphy name: issue_triage_sandbox full_name: bemurphy/issue_triage_sandbox <<: *DEFAULTS issues_count: 1 ! rails_rails: user_name: rails name: rails full_name: rails/rails <<: *DEFAULTS issues_count: 0
  41. 85.

    Ordered fixtures • By default fixtures are unordered • But

    sometimes, order is required • For eg. fork of a repo. Parent repo is needed before the repo can be forked.
  42. 86.

    Ordered fixtures rails_rails: id: 1 user_name: rails name: rails full_name:

    rails/rails language: ruby created_at: 2012-11-10 21:50:48.351554000 Z updated_at: 2012-11-10 21:50:48.351554000 Z issues_count: 0 parent_repo_id:
  43. 87.

    Ordered fixtures prathamesh_rails: id: 2 user_name: prathamesh-sonpatki name: rails full_name:

    prathamesh-sonpatki/rails language: ruby created_at: 2012-11-10 21:50:48.351554000 Z updated_at: 2012-11-10 21:50:48.351554000 Z issues_count: 0 parent_repo_id: 1
  44. 89.

    Ordered fixtures • OMAP YAML --- !omap - rails_rails: id:

    1 user_name: rails name: rails full_name: rails/rails ! - prathamesh_rails: id: 2 user_name: prathamesh-sonpatki name: rails full_name: prathamesh-sonpatki/rails
  45. 90.
  46. 91.

    Table name != Model name • set_fixture_class method • class

    method • accepts hash of filenames with key and class name as value • key should be name of fixture(or relative path) • value should be name of class