Your SlideShare is downloading. ×
0
Introduction to DBIx::MoCo Naoya Ito http://www.hatena.ne.jp/
What is DBIx::MoCo? <ul><li>“ Light and Fast Model Component” </li></ul><ul><ul><li>O/R Mapper for MySQL and SQLite </li><...
Features <ul><li>Easy SQL operations like CDBI / ActiveRecord (Rails)‏ </li></ul><ul><li>Ruby-like list operations </li></...
Quick start
Install <ul><li>&quot;cpan DBIx::MoCo&quot; </li></ul><ul><ul><li>You may need force install as of now. </li></ul></ul>
setup your own classes DBIx::MoCo DBIx::MoCo:: DataBase Bookmark:: MoCo Bookmark:: DataBase Bookmark:: User Bookmark:: Ent...
setup: 1. create DataBase class package Bookmark::DataBase; use base qw/DBIx::MoCo::DataBase/; __PACKAGE__->dsn('dbi:mysql...
setup: 1. create DataBase class DBIx::MoCo DBIx::MoCo:: DataBase Bookmark:: DataBase
setup: 2. create base class of your models package Bookmark::MoCo; use base qw/DBIx::MoCo/; use UNIVERSAL::require; use Ex...
setup: 2. create base class of your models DBIx::MoCo DBIx::MoCo:: DataBase Bookmark:: MoCo Bookmark:: DataBase uses
setup: 3. create model classes package Bookmark::MoCo::Entry; use base qw/Bookmark::MoCo/; __PACKAGE__->table('entry'); __...
setup: 3. create model classes DBIx::MoCo DBIx::MoCo:: DataBase Bookmark:: MoCo Bookmark:: DataBase Bookmark:: User Bookma...
retrieve()‏ my $entry =  moco('Entry')>retrieve(url => $url); say $entry->entry_id; say $entry->title; say $entry->url; ##...
SQL operations
search()‏ my @entries = moco('Entry') ->search( where => &quot;url like 'http://d.hatena.ne.jp/%'&quot;, order => 'entry_i...
search() : placeholders my @entries = moco('Entry')->search( where => [ &quot;url like ?&quot;, 'http://d.hatena.ne.jp/%' ...
search() : named placeholders my @entries = moco('Entry')->search( where => [  &quot;url like  :url  and is_public =  :is_...
search() : where ... in (...)‏ ## SELECT * from entry where entry_id in (1, 2, 5, 6, 10)‏ my @entries = moco('Entry')->sea...
Create, Update, Delete ## create new record my $entry = moco('Entry')->create( url  => 'http://www.yahoo.co.jp/', title =>...
List operations
Ruby-like list operations ## Scalar context my $entries = moco('Entry')->search(...); say   $entries ->size; say   $entrie...
Ruby-like methods <ul><li>push, pop, shift, unshift, add, append, prepend </li></ul><ul><li>size </li></ul><ul><li>first, ...
List::RubyLike <ul><li>google:github list-rubylike </li></ul>
Using your own list class ## create your own list class of Blog::Entry package Blog::Entry::List; use base qw/DBIx::MoCo::...
Using your own list class ## $entries is a Blog::Entry::List my $entries = moco('Entry')->search(...); say $entries ->to_j...
Relationships
An entry has many bookmarks package Bookmark::MoCo::Entry; use Bookmark::MoCo; use base qw/Bookmark::MoCo/; __PACKAGE__->t...
$entry->bookmarks my $entry = moco('Entry')->retrieve_by_url(...); ## bookmarks() returns bookmarks of the entry my @bookm...
bookmarks has an entry and an owner package Bookmark::MoCo::Bookmark; use Bookmark::MoCo; use base qw/Bookmark::MoCo/; __P...
$bookmark->entry my $bookmark = moco('Bookmark')->retrieve; say $bookmark ->entry->title; say $bookmark ->owner->name
BTW: SQL is executed too many times ... my $entry = moco('Entry')->retrieve(...); say $entry->bookmarks->size;  ## 1,000 #...
A entry has many bookmarks  with owner  (prefetching)‏ my $entry = moco('Entry')->retrieve(...); say $entry->bookmarks->si...
Implicit prefetching package Bookmark::MoCo::Entry; use Bookmark::MoCo; use base qw/Bookmark::MoCo/; ... __PACKAGE__->has_...
inflate / deflate
inflate / deflate (explicitly) my $entry = moco('Entry')->retrieve(1); ## plain string say $entry->timestamp; ## timestamp...
inflate / deflate (implicitly) package Bookmark::MoCo::Entry; ... ## plain string __PACKAGE__-> inflate_column ( url  => '...
inflate_column() without builtin classes package Bookmark::MoCo::Entry; ... ## plain string __PACKAGE__-> inflate_column (...
Transparent caching
Transparent caching ## Just do it my $cache = Cache::Memcached->new({...}); Bookmark::MoCo->cache_object( $cache );
Transparent caching ## The entry object will be cached my $entry = moco('Entry')->retrieve(1); ## Cached object will be re...
NOTE: &quot;session&quot; is needed when you use caching feature or prefetching. Blog::MoCo->start_session; my $entry = mo...
Testing
Fixtures: building records for testing from YAML ## fixtures/entries.yml model: Bookmark::Entry records: first: id: 1 titl...
Writing tests with fixtures ## t/entry.t use  DBIx::MoCo::Fixture; use Bookmark::Entry; use Test::More tests => 2; ## load...
Pros and Cons
Pros <ul><li>Simple and easy </li></ul><ul><li>List operations are very sexy. </li></ul><ul><li>Transparent caching is &qu...
Cons <ul><li>less document </li></ul><ul><li>some difficulties (especially in session and cache)‏ </li></ul><ul><li>low te...
patches are welcome. jkondo at hatena ne jp  (primary author)‏
We're hiring! google: はてな 求人
nice office.
nice development environment.
ところで ... (By the way)
勤務地は京都です  (Our HQ is located at Kyoto.)
Thank you!
Any Questions?
Upcoming SlideShare
Loading in...5
×

Introduction To Moco

3,870

Published on

Published in: Business, Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
3,870
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
13
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Transcript of "Introduction To Moco"

  1. 1. Introduction to DBIx::MoCo Naoya Ito http://www.hatena.ne.jp/
  2. 2. What is DBIx::MoCo? <ul><li>“ Light and Fast Model Component” </li></ul><ul><ul><li>O/R Mapper for MySQL and SQLite </li></ul></ul>
  3. 3. Features <ul><li>Easy SQL operations like CDBI / ActiveRecord (Rails)‏ </li></ul><ul><li>Ruby-like list operations </li></ul><ul><li>Transparent caching with Cache::* (usually with Cache::Memcached)‏ </li></ul><ul><li>Test fixture </li></ul>
  4. 4. Quick start
  5. 5. Install <ul><li>&quot;cpan DBIx::MoCo&quot; </li></ul><ul><ul><li>You may need force install as of now. </li></ul></ul>
  6. 6. setup your own classes DBIx::MoCo DBIx::MoCo:: DataBase Bookmark:: MoCo Bookmark:: DataBase Bookmark:: User Bookmark:: Entry uses
  7. 7. setup: 1. create DataBase class package Bookmark::DataBase; use base qw/DBIx::MoCo::DataBase/; __PACKAGE__->dsn('dbi:mysql:dbname=bookmark'); __PACKAGE__->username(‘foo'); __PACKAGE__->password(‘bar'); 1;
  8. 8. setup: 1. create DataBase class DBIx::MoCo DBIx::MoCo:: DataBase Bookmark:: DataBase
  9. 9. setup: 2. create base class of your models package Bookmark::MoCo; use base qw/DBIx::MoCo/; use UNIVERSAL::require; use Expoter::Lite; our @EXPORT = qw/moco/; __PACKAGE__->db_object('Bookmark::DataBase'); ## moco('User') returns &quot;Bookmark::MoCo::User&quot; sub moco (@) { my $model = shift; return __PACKAGE__ unless $model; $model = join '::', 'Bookmark::MoCo', $model; $model->require or die $@; $model; }
  10. 10. setup: 2. create base class of your models DBIx::MoCo DBIx::MoCo:: DataBase Bookmark:: MoCo Bookmark:: DataBase uses
  11. 11. setup: 3. create model classes package Bookmark::MoCo::Entry; use base qw/Bookmark::MoCo/; __PACKAGE__->table('entry'); __PACKAGE__->primary_keys(qw/entry_id/); __PACKAGE__->unique_keys(qw/url/); __PACKAGE__->utf8_columns(qw/title/); 1;
  12. 12. setup: 3. create model classes DBIx::MoCo DBIx::MoCo:: DataBase Bookmark:: MoCo Bookmark:: DataBase Bookmark:: User Bookmark:: Entry uses
  13. 13. retrieve()‏ my $entry = moco('Entry')>retrieve(url => $url); say $entry->entry_id; say $entry->title; say $entry->url; ## retrieve_by_foo(...) equals retrieve(foo => ...)‏ $entry = moco('Entry')-> retrieve_by_url ($url); $entry = moco('Entry')-> retrieve_by_entry_id ($id);
  14. 14. SQL operations
  15. 15. search()‏ my @entries = moco('Entry') ->search( where => &quot;url like 'http://d.hatena.ne.jp/%'&quot;, order => 'entry_id desc', limit => 10, ); say $_->title for @entries;
  16. 16. search() : placeholders my @entries = moco('Entry')->search( where => [ &quot;url like ?&quot;, 'http://d.hatena.ne.jp/%' ], order => 'entry_id desc', limit => 10, ); say $_->title for @entries;
  17. 17. search() : named placeholders my @entries = moco('Entry')->search( where => [ &quot;url like :url and is_public = :is_public &quot;, url => 'http://d.hatena.ne.jp/%', is_public => 1 ], order => 'entry_id desc', limit => 10, ); say $_->title for @entries;
  18. 18. search() : where ... in (...)‏ ## SELECT * from entry where entry_id in (1, 2, 5, 6, 10)‏ my @entries = moco('Entry')->search( where => [ &quot;entry_id in ( :entry_id )&quot;, entry_id => [1, 2, 5, 6, 10] , ], order => 'entry_id desc', ); say $_->title for @entries;
  19. 19. Create, Update, Delete ## create new record my $entry = moco('Entry')->create( url => 'http://www.yahoo.co.jp/', title => 'Yahoo!'; ); ## update a column $entry->title('Yahoo! Japan'); ## save (in session)‏ ## If it is not in session, updates are automatically saved. $entry->save; ## delete the record $entry->delete;
  20. 20. List operations
  21. 21. Ruby-like list operations ## Scalar context my $entries = moco('Entry')->search(...); say $entries ->size; say $entries ->collect(sub { $_->title })‏ ->join(&quot; &quot;); say $entries ->grep(sub { $_->is_public })‏ ->collect(sub { $_->num_of_bookmarks }} ->sum;
  22. 22. Ruby-like methods <ul><li>push, pop, shift, unshift, add, append, prepend </li></ul><ul><li>size </li></ul><ul><li>first, last </li></ul><ul><li>slice, zip </li></ul><ul><li>map, collect, each </li></ul><ul><li>grep </li></ul><ul><li>compact </li></ul><ul><li>flatten </li></ul><ul><li>delete, delete_if, delete_at </li></ul><ul><li>inject </li></ul><ul><li>find </li></ul><ul><li>join </li></ul><ul><li>reduce </li></ul><ul><li>sum </li></ul><ul><li>uniq </li></ul><ul><li>dup </li></ul><ul><li>dump </li></ul>
  23. 23. List::RubyLike <ul><li>google:github list-rubylike </li></ul>
  24. 24. Using your own list class ## create your own list class of Blog::Entry package Blog::Entry::List; use base qw/DBIx::MoCo::List/; sub to_json { ... } ## setup list_class()‏ package Blog::Entry; ... __PACKAGE__->list_class('Blog::Entry::List');
  25. 25. Using your own list class ## $entries is a Blog::Entry::List my $entries = moco('Entry')->search(...); say $entries ->to_json ;
  26. 26. Relationships
  27. 27. An entry has many bookmarks package Bookmark::MoCo::Entry; use Bookmark::MoCo; use base qw/Bookmark::MoCo/; __PACKAGE__->table('entry'); ... __PACKAGE__->has_many( bookmarks => moco('Bookmark'), { key => 'entry_id', order => 'timestamp desc', }, );
  28. 28. $entry->bookmarks my $entry = moco('Entry')->retrieve_by_url(...); ## bookmarks() returns bookmarks of the entry my @bookmarks = $entry ->bookmarks; ## offset and limit (offset 10, limit 50)‏ @bookmarks = $entry->bookmarks (10, 50) ; ## Ruby-like list operations in scalar context print $entry->bookmarks(10, 50) ->grep(...)->size;
  29. 29. bookmarks has an entry and an owner package Bookmark::MoCo::Bookmark; use Bookmark::MoCo; use base qw/Bookmark::MoCo/; __PACKAGE__->table('bookmark'); ... __PACKAGE__->has_a( entry => moco('Entry'), { key => 'entry_id' } ); __PACKAGE__->has_a( owner => moco('User'), { key => 'user_id' } );
  30. 30. $bookmark->entry my $bookmark = moco('Bookmark')->retrieve; say $bookmark ->entry->title; say $bookmark ->owner->name
  31. 31. BTW: SQL is executed too many times ... my $entry = moco('Entry')->retrieve(...); say $entry->bookmarks->size; ## 1,000 ## oops, SQL is executed in 1,000 times. for ($entry->bookmarks) { say $_->owner->name ; }
  32. 32. A entry has many bookmarks with owner (prefetching)‏ my $entry = moco('Entry')->retrieve(...); say $entry->bookmarks->size; ## 1,000 ## bookmarks and owners will be retrieved at the same time. ## (SQL stetements are executed only 2 times.)‏ for ($entry->bookmarks(0, 0, {with => [qw/owner/]} )) { say $_->owner->name ; }
  33. 33. Implicit prefetching package Bookmark::MoCo::Entry; use Bookmark::MoCo; use base qw/Bookmark::MoCo/; ... __PACKAGE__->has_many( bookmarks => moco('Bookmark'), { key => 'entry_id', order => 'timestamp desc', with => [qw/owner/] }, );
  34. 34. inflate / deflate
  35. 35. inflate / deflate (explicitly) my $entry = moco('Entry')->retrieve(1); ## plain string say $entry->timestamp; ## timestamp column as DateTime object say $entry-> timestamp_as_DateTime ->hms; ## url column as URI object say $entry-> url_as_URI ->host;
  36. 36. inflate / deflate (implicitly) package Bookmark::MoCo::Entry; ... ## plain string __PACKAGE__-> inflate_column ( url => 'URI', timestamp => 'DateTime, ); package main; say moco('Entry')->retrieve(1)->url->host;
  37. 37. inflate_column() without builtin classes package Bookmark::MoCo::Entry; ... ## plain string __PACKAGE__-> inflate_column ( title => { inflate => sub { My::String->new(shift) } deflate => sub { shift->as_string } } );
  38. 38. Transparent caching
  39. 39. Transparent caching ## Just do it my $cache = Cache::Memcached->new({...}); Bookmark::MoCo->cache_object( $cache );
  40. 40. Transparent caching ## The entry object will be cached my $entry = moco('Entry')->retrieve(1); ## Cached object will be retrieved from memcached $entry = moco('Entry')->retrieve(1); ## both cache and database record will be updated $entry->title('foobar'); $entry->save;
  41. 41. NOTE: &quot;session&quot; is needed when you use caching feature or prefetching. Blog::MoCo->start_session; my $entry = moco('Entry')->retrieve(...); Blog::MoCo->end_session;
  42. 42. Testing
  43. 43. Fixtures: building records for testing from YAML ## fixtures/entries.yml model: Bookmark::Entry records: first: id: 1 title: Hatena Bookmark url: http://b.hatena.ne.jp/ second: id: 2 title: Yahoo! Japan url: http://www.yahoo.co.jp/
  44. 44. Writing tests with fixtures ## t/entry.t use DBIx::MoCo::Fixture; use Bookmark::Entry; use Test::More tests => 2; ## loading records from entries.yml, ## then returns them as objects. my $f = fixtures(qw/entries/); my $entry = $f->{entry}->{first}; is $entry->title, &quot;...&quot;; is $entry->url, &quot;...&quot;;
  45. 45. Pros and Cons
  46. 46. Pros <ul><li>Simple and easy </li></ul><ul><li>List operations are very sexy. </li></ul><ul><li>Transparent caching is &quot;DB に優しい &quot; </li></ul><ul><li>Test fixture </li></ul>
  47. 47. Cons <ul><li>less document </li></ul><ul><li>some difficulties (especially in session and cache)‏ </li></ul><ul><li>low test coverage </li></ul><ul><li>some bugs </li></ul>
  48. 48. patches are welcome. jkondo at hatena ne jp (primary author)‏
  49. 49. We're hiring! google: はてな 求人
  50. 50. nice office.
  51. 51. nice development environment.
  52. 52. ところで ... (By the way)
  53. 53. 勤務地は京都です (Our HQ is located at Kyoto.)
  54. 54. Thank you!
  55. 55. Any Questions?
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×