Introduction To Moco

Loading...

Flash Player 9 (or above) is needed to view presentations.
We have detected that you do not have it on your computer. To install it, go here.

0 comments

Post a comment

    Post a comment
    Embed Video
    Edit your comment Cancel

    1 Favorite & 1 Event

    Introduction To Moco - Presentation Transcript

    1. Introduction to DBIx::MoCo Naoya Ito http://www.hatena.ne.jp/
    2. What is DBIx::MoCo?
      • “ Light and Fast Model Component”
        • O/R Mapper for MySQL and SQLite
    3. Features
      • Easy SQL operations like CDBI / ActiveRecord (Rails)‏
      • Ruby-like list operations
      • Transparent caching with Cache::* (usually with Cache::Memcached)‏
      • Test fixture
    4. Quick start
    5. Install
      • "cpan DBIx::MoCo"
        • You may need force install as of now.
    6. setup your own classes DBIx::MoCo DBIx::MoCo:: DataBase Bookmark:: MoCo Bookmark:: DataBase Bookmark:: User Bookmark:: Entry uses
    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. setup: 1. create DataBase class DBIx::MoCo DBIx::MoCo:: DataBase Bookmark:: DataBase
    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 "Bookmark::MoCo::User" sub moco (@) { my $model = shift; return __PACKAGE__ unless $model; $model = join '::', 'Bookmark::MoCo', $model; $model->require or die $@; $model; }
    10. setup: 2. create base class of your models DBIx::MoCo DBIx::MoCo:: DataBase Bookmark:: MoCo Bookmark:: DataBase uses
    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. setup: 3. create model classes DBIx::MoCo DBIx::MoCo:: DataBase Bookmark:: MoCo Bookmark:: DataBase Bookmark:: User Bookmark:: Entry uses
    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. SQL operations
    15. search()‏ my @entries = moco('Entry') ->search( where => "url like 'http://d.hatena.ne.jp/%'", order => 'entry_id desc', limit => 10, ); say $_->title for @entries;
    16. search() : placeholders my @entries = moco('Entry')->search( where => [ "url like ?", 'http://d.hatena.ne.jp/%' ], order => 'entry_id desc', limit => 10, ); say $_->title for @entries;
    17. search() : named placeholders my @entries = moco('Entry')->search( where => [ "url like :url and is_public = :is_public ", url => 'http://d.hatena.ne.jp/%', is_public => 1 ], order => 'entry_id desc', limit => 10, ); say $_->title for @entries;
    18. search() : where ... in (...)‏ ## SELECT * from entry where entry_id in (1, 2, 5, 6, 10)‏ my @entries = moco('Entry')->search( where => [ "entry_id in ( :entry_id )", entry_id => [1, 2, 5, 6, 10] , ], order => 'entry_id desc', ); say $_->title for @entries;
    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. List operations
    21. Ruby-like list operations ## Scalar context my $entries = moco('Entry')->search(...); say $entries ->size; say $entries ->collect(sub { $_->title })‏ ->join(" "); say $entries ->grep(sub { $_->is_public })‏ ->collect(sub { $_->num_of_bookmarks }} ->sum;
    22. Ruby-like methods
      • push, pop, shift, unshift, add, append, prepend
      • size
      • first, last
      • slice, zip
      • map, collect, each
      • grep
      • compact
      • flatten
      • delete, delete_if, delete_at
      • inject
      • find
      • join
      • reduce
      • sum
      • uniq
      • dup
      • dump
    23. List::RubyLike
      • google:github list-rubylike
    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. Using your own list class ## $entries is a Blog::Entry::List my $entries = moco('Entry')->search(...); say $entries ->to_json ;
    26. Relationships
    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. $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. 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. $bookmark->entry my $bookmark = moco('Bookmark')->retrieve; say $bookmark ->entry->title; say $bookmark ->owner->name
    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. 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. 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. inflate / deflate
    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. 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. 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. Transparent caching
    39. Transparent caching ## Just do it my $cache = Cache::Memcached->new({...}); Bookmark::MoCo->cache_object( $cache );
    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. NOTE: "session" is needed when you use caching feature or prefetching. Blog::MoCo->start_session; my $entry = moco('Entry')->retrieve(...); Blog::MoCo->end_session;
    42. Testing
    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. 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, "..."; is $entry->url, "...";
    45. Pros and Cons
    46. Pros
      • Simple and easy
      • List operations are very sexy.
      • Transparent caching is "DB に優しい "
      • Test fixture
    47. Cons
      • less document
      • some difficulties (especially in session and cache)‏
      • low test coverage
      • some bugs
    48. patches are welcome. jkondo at hatena ne jp (primary author)‏
    49. We're hiring! google: はてな 求人
    50. nice office.
    51. nice development environment.
    52. ところで ... (By the way)
    53. 勤務地は京都です (Our HQ is located at Kyoto.)
    54. Thank you!
    55. Any Questions?

    + Naoya ItoNaoya Ito, 2 years ago

    custom

    2834 views, 1 favs, 0 embeds more stats

    More info about this document

    © All Rights Reserved

    Go to text version

    • Total Views 2834
      • 2834 on SlideShare
      • 0 from embeds
    • Comments 0
    • Favorites 1
    • Downloads 9
    Most viewed embeds

    more

    All embeds

    less

    Flagged as inappropriate Flag as inappropriate
    Flag as inappropriate

    Select your reason for flagging this presentation as inappropriate. If needed, use the feedback form to let us know more details.

    Cancel
    File a copyright complaint
    Having problems? Go to our helpdesk?

    Categories

    Groups / Events