Quick Upload

Loading...
Flash Player 9 (or above) is needed to view slideshows. We have detected that you do not have it on your computer.To install it, go here
Post to Twitter Post to Twitter
Share on Facebook
Myspace Hi5 Friendster Xanga LiveJournal Facebook Blogger Tagged Typepad Freewebs BlackPlanet gigya icons

Demystifying DBIx::Class

from jshirley, 5 months ago Add as contact

375 views | 0 comments | 0 favorites | 1 embeds (Stats)

Desc: These are the slides to my talk I gave at the June 2008 talk at the Portland Perl Monger's Meeting.
The focus of the talk was on demystifying DBIx::Class, and is followed by the example located at http://our.coldhardcode.com/svn/misc/DBIC-Beer/

Embed customize close
 

Categories

Finance

Groups/Events

More Info

This slideshow is Public

Views: 375 Comments: 0 Favorites: 0 Downloads: 10

View Details: 373 on Slideshare 2 from embeds
Most viewed embeds (Top 5): More
All Embeds: Less
Flagged as inappropriate Flag as inappropriate

Flag as inappropriate

Select your reason for flagging this slideshow as inappropriate.

If needed, use the feedback form to let us know more details.

Slideshow Transcript

  1. Slide 1: Demystifying DBIx::Class Jay Shirley <jshirley@coldhardcode.com> http://our.coldhardcode.com/svn/DBIC-Beer
  2. Slide 2: Mystic?
  3. Slide 3: Why are ORMs scary?
  4. Slide 4: Why are ORMs scary? • Enterprise-y
  5. Slide 5: Why are ORMs scary? • Enterprise-y • Loss of control
  6. Slide 6: Why are ORMs scary? • Enterprise-y • Loss of control • History (Class::DBI)
  7. Slide 7: Why are ORMs scary? • Enterprise-y • Loss of control • History (Class::DBI) • (A triumph of multiple inheritance)
  8. Slide 8: Retort.
  9. Slide 9: Enterprise-y
  10. Slide 10: Enterprise-y • Enterprise = Java
  11. Slide 11: Enterprise-y • Enterprise = Java • DBIx::Class is written in perl
  12. Slide 12: Loss of Control
  13. Slide 13: Loss of Control • Still programmatic
  14. Slide 14: Loss of Control • Still programmatic • Use SQL::Abstract rather than SQL
  15. Slide 15: Loss of Control • Still programmatic • Use SQL::Abstract rather than SQL • Same thing
  16. Slide 16: Loss of Control • Still programmatic • Use SQL::Abstract rather than SQL • Same thing • (except patches welcome)
  17. Slide 17: Class::DBI
  18. Slide 18: Class::DBI Sorry Schwern
  19. Slide 19: Why DBIx::Class? • I like it. You’ll see why. • TIMTOWDI: • Rose::DB • Alzabo
  20. Slide 20: Objects • Relations are only a third of an ORM
  21. Slide 21: Objects • Relations are only a third of an ORM • What’s an object?
  22. Slide 22: Objects • Relations are only a third of an ORM • What’s an object? • Database columns
  23. Slide 23: Objects • Relations are only a third of an ORM • What’s an object? • Database columns • Table
  24. Slide 24: Objects • Relations are only a third of an ORM • What’s an object? • Database columns • Table • Indexes
  25. Slide 25: A Use Case
  26. Slide 26: Beer
  27. Slide 27: Yes, Beer.
  28. Slide 28: Or... • Beer has many distributers • Beer has many reviews • Beer belongs to a brewer
  29. Slide 29: Which means... package Beer::Schema::Beer; use base 'DBIx::Class'; __PACKAGE__->load_components( qw|Core| ); __PACKAGE__->table('beer'); __PACKAGE__->add_columns( 'pk1' => { data_type => 'integer', size => 16, is_nullable => 0, is_auto_increment => 1 }, 'name' => { data_type => 'varchar', size => 128, is_nullable => 0 }, 'brewer_pk1' => { data_type => 'integer', size => 16, is_nullable => 0, is_foreign_key => 1 }, ); __PACKAGE__->set_primary_key('pk1'); 1;
  30. Slide 30: And indexes: __PACKAGE__->add_unique_index(...);
  31. Slide 31: That gives you: • Deployable SQL (CREATE TABLE, etc) • The foundation for relationships: • $beer->brewer # DTRT
  32. Slide 32: Managing Relations • A beer is: • made by a brewer • distributed by distributers • reviewed by people
  33. Slide 33: Simple Relationships belongs_to is the opposite end of has_many
  34. Slide 34: Simple Relationships belongs_to is the opposite end of has_many has_one, might_have means just that
  35. Slide 35: Simple Relationships belongs_to is the opposite end of has_many has_one, might_have means just that many_to_many gets complicated
  36. Slide 36: Creating a relation __PACKAGE__->belongs_to( ‘brewer’, # Accessor ‘Beer::Schema::Brewer’, # Related Class ‘brewer_pk1’ # My Column );
  37. Slide 37: For simplicity... Brewers, Distributors and Beers are all easy All the same, except Beer has a brewer (brewer_pk1)
  38. Slide 38: Using it (Manager) use Beer::Schema; my $schema = Beer::Schema ->connect( $dsn );
  39. Slide 39: $schema # Fetch a result set my $rs = $schema->resultset(‘Beer’);
  40. Slide 40: Result Sets # Everything is a result set. $rs->count; # How many Beers?
  41. Slide 41: Everything is a Result Set $rs2 = $rs->search({ name => ‘Stout’ }); $rs2->count; # It chains together.
  42. Slide 42: Chained Result Sets are what make DBIC Great
  43. Slide 43: Result Sets return Result Sets $rs->search->search->search- >search->search->search ->search- >search->search->search->search- >search ->search->search->search- >search->search->search ->search- >search->search->search->search- >search ->search->search->search- >search->search->search ->search- >search->search->search->search- >search;
  44. Slide 44: Why? $rs ->search({ $long_query }) ->search({ $more_filters }) ->search({ $even_more });
  45. Slide 45: Actual Use: sub active_members { # All profiles that have purchased a membership. my $query = $rs->search( { 'purchase.saved_object_key' => 'membership', 'membership.expiration_date' => \\'>= NOW()' }, { join => { profile_transactions => { 'transaction' => { 'link_transaction_purchase' => { 'purchase' => 'membership' } } }, }, prefetch => [ 'state', 'country', { profile_transactions => { 'transaction' => { 'link_transaction_purchase' => { 'purchase' => 'membership' } } }, } ], group_by => [ qw/membership_id/ ] } ); }
  46. Slide 46: In SQL: SELECT ... FROM table_profiles me LEFT JOIN profile_transaction profile_transactions ON ( profile_transactions.profile_id = me.profile_id ) JOIN nasa_transactions transaction ON ( transaction.transaction_id = profile_transactions.transaction_id ) LEFT JOIN link_trans_pp link_transaction_purchase ON ( link_transaction_purchase.transaction_id = transaction.transaction_id ) JOIN purchased_products purchase ON ( purchase.purchased_id = link_transaction_purchase.purchased_id ) JOIN nasa_membership membership ON ( membership.membership_id = purchase.saved_product_id ) JOIN state_lookup state ON ( state.state_lookup_id = me.state ) JOIN country_lookup country ON ( country.country_lookup_id = me.country_id ) WHERE ( membership.expiration_date >= NOW() AND purchase.saved_object_key = 'membership' )
  47. Slide 47: Now: my $query = $schema->resultset(‘Profile’)->active_members; $query->count; # How many? $query->search({ first_name => ‘Bob’ }); # All matching members named Bob $query->search({ first_name => ‘Bob’ })->count; while ( my $profile = $query->next ) { $profile->cars; # Get all of this persons cars } # Clean, no ugly SQL
  48. Slide 48: Pretty.
  49. Slide 49: Even More: Managing your schema
  50. Slide 50: Create Table Statements $schema->create_ddl_dir( [ 'SQLite', 'MySQL', ‘PostgreSQL’ ], $VERSION, \"$destination\" );
  51. Slide 51: SQLite CREATE TABLE beer ( pk1 INTEGER PRIMARY KEY NOT NULL, name varchar(128) NOT NULL, brewer_pk1 integer(16) NOT NULL );
  52. Slide 52: DROP TABLE IF EXISTS `beer`; MySQL -- -- Table: `beer` -- CREATE TABLE `beer` ( `pk1` integer(16) NOT NULL auto_increment, `name` varchar(128) NOT NULL, `brewer_pk1` integer(16) NOT NULL, INDEX (`pk1`), INDEX (`brewer_pk1`), PRIMARY KEY (`pk1`), CONSTRAINT `beer_fk_brewer_pk1` FOREIGN KEY (`brewer_pk1`) REFERENCES `brewer` (`pk1`) ON DELETE CASCADE ON UPDATE CASCADE ) Type=InnoDB;
  53. Slide 53: PostgreSQL -- -- Table: beer -- DROP TABLE beer CASCADE; CREATE TABLE beer ( pk1 bigserial NOT NULL, name character varying(128) NOT NULL, brewer_pk1 bigint NOT NULL, PRIMARY KEY (pk1) );
  54. Slide 54: Get a working database $schema->deploy; # Yes, it is this simple.
  55. Slide 55: And now for tests