Aqua<br />A cool, clear drink of <br />Ruby object persistence<br />Kane Baccigalupi<br />RubyConf 09<br />
Aqua<br />A cool, clear drink of Ruby object persistence<br />Kane Baccigalupi<br />RubyConf ‘09<br />
Aqua<br />A cool, clear drink of Ruby object persistence<br />Got unemployment?<br />Relax with CouchDB<br />Kane Baccigal...
Aqua<br />A cool, clear drink of Ruby object persistence<br />ORMs are great,<br />but normalization is expensive.<br /># ...
Aqua<br />A cool, clear drink of Ruby object persistence<br />CouchDB + Ruby  ~= <br />CouchRest<br /># CouchRest<br />cla...
Aqua<br />A cool, clear drink of Ruby object persistence<br />CouchRest is different from ORMs because:<br />It allows col...
Aqua<br />A cool, clear drink of Ruby object persistence<br />What defines Ruby object state?<br />Instance variables <br ...
Aqua<br />A cool, clear drink of Ruby object persistence<br />Database abstractions<br />focus on databases<br /># DataMap...
Aqua<br />A cool, clear drink of Ruby object persistence<br />Aqua’s goal:<br />Focus on objects <br />object.commit!<br /...
Aqua<br />A cool, clear drink of Ruby object persistence<br />Because Ruby is awesome<br />class Event &lt; Range <br />at...
Aqua<br />A cool, clear drink of Ruby object persistence<br />How does Aqua work?<br />Kane Baccigalupi<br />RubyConf ‘09<...
Aqua<br />A cool, clear drink of Ruby object persistence<br />Just add Aqua<br />class User<br />aquatic<br /># ...<br />e...
Aqua<br />A cool, clear drink of Ruby object persistence<br />Just add Aqua<br />class User<br />aquatic<br /># ...<br />e...
Aqua<br />A cool, clear drink of Ruby object persistence<br />Behind the scene<br />user.commit!<br />Kane Baccigalupi<br ...
Aqua<br />A cool, clear drink of Ruby object persistence<br />Behind the scene<br />serialization<br />user.commit!<br />{...
Aqua<br />A cool, clear drink of Ruby object persistence<br />Behind the scene<br />serialization<br />user.commit!<br />{...
Aqua<br />A cool, clear drink of Ruby object persistence<br />Objects ~= Documents,<br />&& Documents ~= Hashes<br /># YAM...
Aqua<br />A cool, clear drink of Ruby object persistence<br />Sometimes state <br />should not hang around.<br />There is ...
Aqua<br />A cool, clear drink of Ruby object persistence<br />Going deeper with embedded objects …<br />class Address<br /...
Aqua<br />A cool, clear drink of Ruby object persistence<br />Ordinary objects<br />get serialized<br />inside aquatic<br ...
Aqua<br />A cool, clear drink of Ruby object persistence<br />Embedded aquatic objects are <br />saved by reference.<br />...
Aqua<br />A cool, clear drink of Ruby object persistence<br />Aqua::Stub~= Lazy Delegate<br /><ul><li>Gets the object from...
 Triggered by #method_missing
 Stubs/caches methods</li></ul>{<br />  &quot;class&quot;=&gt;&quot;User&quot;, <br />  &quot;ivars&quot;=&gt;{<br />    #...
Aqua<br />A cool, clear drink of Ruby object persistence<br />Stubbing methods in Aqua::Stub<br />{<br />  &quot;class&quo...
Aqua<br />A cool, clear drink of Ruby object persistence<br />Stubbed behavior<br />user.reload<br />friend = user.friends...
Aqua<br />A cool, clear drink of Ruby object persistence<br />Got Files?<br />{<br />  &quot;class&quot;=&gt;&quot;User&qu...
Aqua<br />A cool, clear drink of Ruby object persistence<br />Getting Objects:<br />The basics<br />User.load( some_id )<b...
Aqua<br />A cool, clear drink of Ruby object persistence<br />Indexed Searches<br />class User<br />aquatic<br />  # ...<b...
Aqua<br />A cool, clear drink of Ruby object persistence<br />What’s next?<br />More querying ease<br /><ul><li> Search on...
 Criteria pattern ???
 Custom dsl ???
Upcoming SlideShare
Loading in …5
×

A cool, clear drink of Ruby object persistence

4,278 views
3,664 views

Published on

Introduction to a proof of concept library 'Aqua' that uses CouchDB and other document oriented back ends to transparently persist Ruby objects.

Published in: Technology, Education
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
4,278
On SlideShare
0
From Embeds
0
Number of Embeds
13
Actions
Shares
0
Downloads
23
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

A cool, clear drink of Ruby object persistence

  1. Aqua<br />A cool, clear drink of <br />Ruby object persistence<br />Kane Baccigalupi<br />RubyConf 09<br />
  2. Aqua<br />A cool, clear drink of Ruby object persistence<br />Kane Baccigalupi<br />RubyConf ‘09<br />
  3. Aqua<br />A cool, clear drink of Ruby object persistence<br />Got unemployment?<br />Relax with CouchDB<br />Kane Baccigalupi<br />RubyConf ‘09<br />
  4. Aqua<br />A cool, clear drink of Ruby object persistence<br />ORMs are great,<br />but normalization is expensive.<br /># DataMapper<br />class Mammal<br /> include DataMapper::Resource<br /> property :my_id, Serial<br /> has n, :legs<br />end<br /># ActiveRecord<br />class Bird &lt; ActiveRecord::Base<br /> # properties defined by migration<br />has_many, :legs<br />end<br />Kane Baccigalupi<br />RubyConf ‘09<br />
  5. Aqua<br />A cool, clear drink of Ruby object persistence<br />CouchDB + Ruby ~= <br />CouchRest<br /># CouchRest<br />class Reptile &lt; CouchRest::ExtendedDocument<br />use_database MY_DB<br />unique_id :my_id<br /> property :legs # a collection!<br />end<br />Kane Baccigalupi<br />RubyConf ‘09<br />
  6. Aqua<br />A cool, clear drink of Ruby object persistence<br />CouchRest is different from ORMs because:<br />It allows collections<br />Models are hashes<br />Instance variables are discarded<br />Kane Baccigalupi<br />RubyConf ‘09<br />
  7. Aqua<br />A cool, clear drink of Ruby object persistence<br />What defines Ruby object state?<br />Instance variables <br />@my_variable<br />Fundamental data <br /> Hash key-values, Array values, etc.<br />Kane Baccigalupi<br />RubyConf ‘09<br />
  8. Aqua<br />A cool, clear drink of Ruby object persistence<br />Database abstractions<br />focus on databases<br /># DataMapper<br />class Mammal<br /> include DataMapper::Resource<br /> property :my_id, Serial<br /> has n, :legs<br />end<br /># ActiveRecord<br />class Bird &lt; ActiveRecord::Base<br /> # properties defined by schema<br />has_many, :legs<br />end<br /># CouchRest<br />class Reptile &lt; CouchRest::ExtendedDocument<br />use_database MY_DB<br />unique_id :my_id<br /> property :legs # a collection!<br />end<br />Kane Baccigalupi<br />RubyConf ‘09<br />
  9. Aqua<br />A cool, clear drink of Ruby object persistence<br />Aqua’s goal:<br />Focus on objects <br />object.commit!<br />Kane Baccigalupi<br />RubyConf ‘09<br />
  10. Aqua<br />A cool, clear drink of Ruby object persistence<br />Because Ruby is awesome<br />class Event &lt; Range <br />attr_accessor :name<br />end<br />rubyconf = Event.new(Date.parse(&apos;11/19/2009&apos;), Date.parse(&apos;11/21/2009&apos;))<br />rubyconf.name = &apos;RubyConf 09&apos;<br />rubyconf.include?(Date.parse(&apos;11/20/2009&apos;)) # true <br />Kane Baccigalupi<br />RubyConf ‘09<br />
  11. Aqua<br />A cool, clear drink of Ruby object persistence<br />How does Aqua work?<br />Kane Baccigalupi<br />RubyConf ‘09<br />
  12. Aqua<br />A cool, clear drink of Ruby object persistence<br />Just add Aqua<br />class User<br />aquatic<br /># ...<br />end<br />Kane Baccigalupi<br />RubyConf ‘09<br />
  13. Aqua<br />A cool, clear drink of Ruby object persistence<br />Just add Aqua<br />class User<br />aquatic<br /># ...<br />end<br />user = User.new<br /># ... More stuff happens to the user<br /># saving an object<br />user.commit! # commit without the ! also works but raises no errors.<br />Kane Baccigalupi<br />RubyConf ‘09<br />
  14. Aqua<br />A cool, clear drink of Ruby object persistence<br />Behind the scene<br />user.commit!<br />Kane Baccigalupi<br />RubyConf ‘09<br />
  15. Aqua<br />A cool, clear drink of Ruby object persistence<br />Behind the scene<br />serialization<br />user.commit!<br />{<br /> &quot;class&quot;=&gt;&quot;User&quot;, <br /> &quot;ivars&quot;=&gt;{<br /> &quot;@username&quot;=&gt;&quot;kane&quot;, <br /> &quot;@email&quot;=&gt;&quot;baccigalupi@gmail.com&quot;, <br /> &quot;@password&quot;=&gt;&quot;secret&quot;<br /> }<br />}<br />Kane Baccigalupi<br />RubyConf ‘09<br />
  16. Aqua<br />A cool, clear drink of Ruby object persistence<br />Behind the scene<br />serialization<br />user.commit!<br />{<br /> &quot;class&quot;=&gt;&quot;User&quot;, <br /> &quot;ivars&quot;=&gt;{<br /> &quot;@username&quot;=&gt;&quot;kane&quot;, <br /> &quot;@email&quot;=&gt;&quot;baccigalupi@gmail.com&quot;, <br /> &quot;@password&quot;=&gt;&quot;secret&quot;<br /> }<br />}<br />data post<br />Kane Baccigalupi<br />RubyConf ‘09<br />
  17. Aqua<br />A cool, clear drink of Ruby object persistence<br />Objects ~= Documents,<br />&& Documents ~= Hashes<br /># YAML for a Ruby User object<br />--- &id001 !ruby/object:User<br /> email: baccigalupi@gmail.com<br /> password: secret<br /> username: kane<br /># Aqua Serialization for same object<br />{<br /> &quot;class&quot;=&gt;&quot;User&quot;, <br /> &quot;ivars&quot;=&gt;{<br /> &quot;@username&quot;=&gt;&quot;kane&quot;, <br /> &quot;@email&quot;=&gt;&quot;baccigalupi@gmail.com&quot;, <br /> &quot;@password&quot;=&gt;&quot;secret&quot;<br /> }<br />} <br />Kane Baccigalupi<br />RubyConf ‘09<br />
  18. Aqua<br />A cool, clear drink of Ruby object persistence<br />Sometimes state <br />should not hang around.<br />There is a method for that. <br />class User<br /> aquatic<br />attr_accessor :username, :email, :password <br />hide_attributes :password<br />end<br />Kane Baccigalupi<br />RubyConf ‘09<br />
  19. Aqua<br />A cool, clear drink of Ruby object persistence<br />Going deeper with embedded objects …<br />class Address<br /># not an aquatic object, just plain ruby<br />attr_accessor :name, :street, :city, :state, :zip<br />end <br />address = Address.new<br /># . . . <br />user = User.new<br />user.addresses = [ address ]<br />Kane Baccigalupi<br />RubyConf ‘09<br />
  20. Aqua<br />A cool, clear drink of Ruby object persistence<br />Ordinary objects<br />get serialized<br />inside aquatic<br />objects<br />{<br /> &quot;class&quot;=&gt;&quot;User&quot;, <br /> &quot;ivars&quot;=&gt;{<br />&quot;@addresses&quot;=&gt;{<br /> &quot;class&quot;=&gt;&quot;Array&quot;, <br /> &quot;init&quot;=&gt;[{<br /> &quot;class&quot;=&gt;&quot;Address&quot;, <br /> &quot;ivars&quot;=&gt;{<br /> &quot;@city&quot;=&gt;&quot;San Francisco&quot;, <br /> &quot;@name&quot;=&gt;&quot;work&quot;, <br /> &quot;@street&quot;=&gt;&quot;P0 Box 58&quot;, <br /> &quot;@state&quot;=&gt;&quot;94102&quot;<br /> }<br /> }]<br /> }, <br /> &quot;@username&quot;=&gt;&quot;kane&quot;, <br /> &quot;@email&quot;=&gt;&quot;baccigalupi@gmail.com&quot;<br /> }<br />} <br />Kane Baccigalupi<br />RubyConf ‘09<br />
  21. Aqua<br />A cool, clear drink of Ruby object persistence<br />Embedded aquatic objects are <br />saved by reference.<br />{<br /> &quot;class&quot;=&gt;&quot;User&quot;, <br /> &quot;ivars&quot;=&gt;{<br /> # ...<br /> &quot;@friends&quot;=&gt;{<br /> &quot;class&quot;=&gt;&quot;Array&quot;, <br /> &quot;init&quot;=&gt;[{<br /> &quot;class&quot;=&gt;&quot;Aqua::Stub&quot;, <br /> &quot;init&quot;=&gt;{&quot;class&quot;=&gt;&quot;User&quot;, &quot;id&quot;=&gt;&quot;32&quot;}<br /> }]<br /> }<br /> }<br />}<br />class User<br />aquatic<br /># ...<br />def friends<br /> @friends ||= []<br /> end<br />end<br />user.friends &lt;&lt; alex<br /># where alex is another user object<br />Kane Baccigalupi<br />RubyConf ‘09<br />
  22. Aqua<br />A cool, clear drink of Ruby object persistence<br />Aqua::Stub~= Lazy Delegate<br /><ul><li>Gets the object from the db
  23. Triggered by #method_missing
  24. Stubs/caches methods</li></ul>{<br /> &quot;class&quot;=&gt;&quot;User&quot;, <br /> &quot;ivars&quot;=&gt;{<br /> # ...<br /> &quot;@friends&quot;=&gt;{<br /> &quot;class&quot;=&gt;&quot;Array&quot;, <br /> &quot;init&quot;=&gt;[{<br /> &quot;class&quot;=&gt;&quot;Aqua::Stub&quot;, <br /> &quot;init&quot;=&gt;{&quot;class&quot;=&gt;&quot;User&quot;, &quot;id&quot;=&gt;&quot;32&quot;}<br /> }]<br /> }<br /> }<br />}<br />Kane Baccigalupi<br />RubyConf ‘09<br />
  25. Aqua<br />A cool, clear drink of Ruby object persistence<br />Stubbing methods in Aqua::Stub<br />{<br /> &quot;class&quot;=&gt;&quot;User&quot;, <br /> &quot;ivars&quot;=&gt;{<br /> # ...<br /> &quot;@friends&quot;=&gt;{<br /> &quot;class&quot;=&gt;&quot;Array&quot;, <br /> &quot;init&quot;=&gt;[{<br /> &quot;class&quot;=&gt;&quot;Aqua::Stub&quot;, <br /> &quot;init&quot;=&gt;{<br /> &quot;class&quot;=&gt;&quot;User&quot;,<br /> &quot;id&quot;=&gt;&quot;32”,<br />&quot;methods&quot;=&gt;{&quot;username&quot;=&gt;&quot;alex&quot;},<br /> }<br /> }]<br /> }<br /> }<br />}<br />class User<br />aquatic :embed =&gt;<br />{ :stub =&gt; :username } <br /># ...<br />end<br />Kane Baccigalupi<br />RubyConf ‘09<br />
  26. Aqua<br />A cool, clear drink of Ruby object persistence<br />Stubbed behavior<br />user.reload<br />friend = user.friends.first<br />friend.class # Aqua::Stub<br />friend.username# ‘alex’<br /># username was cached<br />friend.email<br /># this triggers the database call <br /># for the friend object<br />Kane Baccigalupi<br />RubyConf ‘09<br />
  27. Aqua<br />A cool, clear drink of Ruby object persistence<br />Got Files?<br />{<br /> &quot;class&quot;=&gt;&quot;User&quot;, <br /> &quot;ivars&quot;=&gt;{<br /> # ...<br />&quot;@avatar&quot;=&gt;{<br /> &quot;class&quot;=&gt;&quot;Aqua::FileStub”<br /> &quot;init&quot;=&gt;{<br /> &quot;methods&quot;=&gt;{<br /> &quot;content_type&quot;=&gt;&quot;image/png&quot;,<br /> &quot;content_length&quot;=&gt;{<br /> &quot;class&quot;=&gt;&quot;Fixnum&quot;, &quot;init&quot;=&gt;&quot;26551”<br /> }<br /> }<br />&quot;id&quot;=&gt;&quot;image_attach.png&quot;<br /> }, <br /> }<br /> }<br />}<br />class User<br />aquatic<br /> # ...<br />attr_accessor :avatar<br />end<br />user.avatar = my_pic<br />Kane Baccigalupi<br />RubyConf ‘09<br />
  28. Aqua<br />A cool, clear drink of Ruby object persistence<br />Getting Objects:<br />The basics<br />User.load( some_id )<br />user.reload<br />Kane Baccigalupi<br />RubyConf ‘09<br />
  29. Aqua<br />A cool, clear drink of Ruby object persistence<br />Indexed Searches<br />class User<br />aquatic<br /> # ...<br />index_on :username<br />end<br />&quot; // javascript map function<br />function(doc) {<br /> if( doc[&apos;class&apos;] == &apos;User&apos; &&<br />doc[&apos;ivars&apos;] && doc[&apos;ivars&apos;][&apos;@username&apos;] ){<br /> emit( doc[&apos;ivars&apos;][&apos;@username&apos;], 1 ); <br /> }<br /> }<br />&quot;<br />User.query(:username, ’kane&apos;) # returns an array of all users named kane<br />Kane Baccigalupi<br />RubyConf ‘09<br />
  30. Aqua<br />A cool, clear drink of Ruby object persistence<br />What’s next?<br />More querying ease<br /><ul><li> Search on nested variables
  31. Criteria pattern ???
  32. Custom dsl ???
  33. Much coding love</li></ul>Kane Baccigalupi<br />RubyConf ‘09<br />
  34. Aqua<br />A cool, clear drink of Ruby object persistence<br />What’s next?<br />Mixins<br /><ul><li> Validations
  35. Attribute constraints for class, size, etc.
  36. Collections & relationships
  37. ActiveRecord conversion ???</li></ul>Kane Baccigalupi<br />RubyConf ‘09<br />
  38. Aqua<br />A cool, clear drink of Ruby object persistence<br />What’s next?<br />Serializing Code<br /><ul><li> Lambdas and Procs
  39. Singleton methods
  40. Classes (are objects too)</li></ul>Kane Baccigalupi<br />RubyConf ‘09<br />
  41. Aqua<br />A cool, clear drink of Ruby object persistence<br />What’s next?<br />Repository Layer<br /><ul><li>In memory
  42. Stores objects, not serializations
  43. commits objects as needed</li></ul>Kane Baccigalupi<br />RubyConf ‘09<br />
  44. Aqua<br />A cool, clear drink of Ruby object persistence<br />More Info<br />Rdocs: ruby-aqua.org<br />Get the gem: sudo gem install aqua<br />Explore the code: github.com/baccigalupi/aqua<br />Kane Baccigalupi<br />RubyConf ‘09<br />

×