SlideShare a Scribd company logo
1 of 136
Download to read offline
* #sor09
Ruby sittin’ on the Couch
About me


• Alexander Lang
• Upstream Agile GmbH, Berlin
  programmer, owner
• http://upstream-berlin.com
11/52
Web development w/
      Ruby
BDD
Buzzword Driven
 Development
TDD
  BDD
                                   “agile”
Pair Programming


          * all the f****** time
About me

• playing with CouchDB since 09/2008
• helped hack the CouchDB statistics module
  (with @janl)
• wrote Couch Potato
• working on smaller production apps
Who are you?
Who is in this room?
• Chris Anderson
• George Palmer
• Paul Carey
• Johan Sørensen
• Cheah Chu Yeow/Carlos Villela
Who is in this room?
• Chris Anderson (couchrest + couchapp)
• George Palmer (couch_foo)
• Paul Carey (relaxdb)
• Johan Sørensen (couchbject)
• Cheah Chu Yeow/Carlos Villela (activecouch)
Forget it!
Agenda

• CouchDB introduction
• The CouchDB example wiki
• The frameworks
• Conclusion: where to go from here?
• Q &A
CouchDB introduction
What is CouchDB?
Apache Project
   so it has to be good
Document oriented
    Database
Store/read any JSON
     document
Powerful map/reduce
 views for querying*
     * we’ll see what that is
Why CouchDB?
Buzzword
compliant
JavaScript
REST
HTTP interface
JSON
Map/Reduce
the thing that made Google rich
Fun !
No more SQL/Schema/
    Migrations
JavaScript views instead
Simple!
HTTP interface
can use existing
clients, libraries
It scales
just like Ruby :)
No locks,
instead MVCC
integrated replication
      (yes, multi master)
use existing load
balancer, proxies etc.
        HTTP ftw
and so on...
So how does Couch work?
JSON
{
    _id: “some UUID”,
    _rev: “MVCC key”,
    title: “page one”
    body: “this is page one.”,
    tags: [“ruby”, “couchdb”, “sor09”]
    metadata: {created_at: “2009/03/28 06:34:00”,
      author: “alex”}
}
HTTP API

• POST ‘/my_db’, {my_json}
• GET ‘/my_db/my_document_id’
• PUT ‘/my_db/my_document_id’,
  {new_json}
• DELETE ‘/my_db/my_document_id’
Map/Reduce views

• views are documens
• provide a map (and optional reduce
  function) written in JavaScript
• this creates an index over all documents
• query that index via GET
Map/Reduce views
{
    title: “page one”,
    tags: [“first”, important”]
}

{
    title: “page 2”,
    tags: [“funny”]
}
Map/Reduce views
{                                function(doc) {
    title: “page one”,
                                   emit(doc.title, doc.tags.length)
    tags: [“first”, important”]
                                 }
}

{
    title: “page 2”,
    tags: [“funny”]
}
Map/Reduce views
{                                function(doc) {
    title: “page one”,
                                   emit(doc.title, doc.tags.length)
    tags: [“first”, important”]
                                 }
}
                                              key        value
{
                                           “page one”      2
    title: “page 2”,
    tags: [“funny”]                         “page 2”       1
}
Map/Reduce views
{                                function(doc) {
    title: “page one”,
                                   emit(doc.title, doc.tags.length)
    tags: [“first”, important”]
                                 }
}
                                              key        value
{
                                           “page one”      2
    title: “page 2”,
    tags: [“funny”]                         “page 2”       1
}

               function(keys, values) {
                 return sum(values);
               }
Map/Reduce views
{                                function(doc) {
    title: “page one”,
                                   emit(doc.title, doc.tags.length)
    tags: [“first”, important”]
                                 }
}
                                              key        value
{
                                           “page one”      2
    title: “page 2”,
    tags: [“funny”]                         “page 2”       1
}

               function(keys, values) {
                 return sum(values);
                                                    3
               }
Query a View
Query a View

/my_db/_design/wiki/_view/tags_count
Query a View

/my_db/_design/wiki/_view/tags_count
/my_db/_design/wiki/_view/tags_count?reduce=false
Query a View

/my_db/_design/wiki/_view/tags_count
/my_db/_design/wiki/_view/tags_count?reduce=false
/my_db/_design/wiki/_view/tags_count?limit=1
Query a View

/my_db/_design/wiki/_view/tags_count
/my_db/_design/wiki/_view/tags_count?reduce=false
/my_db/_design/wiki/_view/tags_count?limit=1
/my_db/_design/wiki/_view/tags_count?key=page one
Query a View

/my_db/_design/wiki/_view/tags_count
/my_db/_design/wiki/_view/tags_count?reduce=false
/my_db/_design/wiki/_view/tags_count?limit=1
/my_db/_design/wiki/_view/tags_count?key=page one
Query a View
Query a View
  ?key=‘page one’
Query a View
          ?key=‘page one’
?startkey=‘page 1’&endkey=’page 999’
Query a View
          ?key=‘page one’
?startkey=‘page 1’&endkey=’page 999’
      ?key=[‘composite’, ‘key’]
Query a View
           ?key=‘page one’
?startkey=‘page 1’&endkey=’page 999’
      ?key=[‘composite’, ‘key’]
       ?keys=[‘set’, ‘of’, ‘keys’]
Query a View
           ?key=‘page one’
?startkey=‘page 1’&endkey=’page 999’
      ?key=[‘composite’, ‘key’]
       ?keys=[‘set’, ‘of’, ‘keys’]
That is CouchDB
                 (the basics)


• upload documents via POST/PUT
• read documents via GET
• create indexes by providing map/reduce
  functions
• query views via GET, pass keys + other
  options
The CouchDB example wiki
Example Wiki
• ActiveRecord   • RelaxDB
• CouchRest      • Couch Potato
• ActiveCouch    • CouchOject
• CouchFoo       • CouchApp
• a wiki example app implemented in all
      frameworks I could find
   • + in ActiveRecord for comparison

DISCLAIMER: implementations are insecure, have
bugs and aren’t meant for production at all
http://github.com/langalex/couchdb_example_wiki
Example Wiki

• a few simple features
 • create a page
 • add new pages by clicking on a
    CamelCase link
 • list of pages
Example Wiki

• and a few special cases
 • keep history of each page, browse old
    versions
 • statistics: count occurrences of all words
    in all pages
Example Wiki

• creating pages is easy
• versioning, statistics harder
• views are the source of CouchDB’s power
let me show you how it works
          Example Wiki
ActiveRecord Wiki
routes.rb
map.resources :pages do |pages|
  pages.resources :versions
end

map.resources :statistics
map.root :controller => quot;pagesquot;, :action => 'show'
page.rb
class Page < ActiveRecord::Base
  acts_as_versioned

  def to_param
    title
  end
end
pages/show.html.erb
<%= <%= simple_format linkify(@page.body) %>
    simple_format linkify(@page.body) %>



  def linkify(text)
    text.gsub(/([A-Z][a-z]+([A-Z][a-z]+)+)/) do
      link_to($1, page_path($1))
    end
  end



replace CamelCase words with links to #show
pages_controller.rb

def show
  @page = Page.first unless params[:id]
  @page ||= Page.find_by_title params[:id]
  redirect_to new_page_path(:title => params[:id]) unless @page
end




           redirect to #new if no page found
statistics
  def self.word_counts
    Page.all.map(&:body).join(quot; quot;).split(/s
+/).grep(/w+/i).inject(Hash.new(0)) do |res,
word|
      res[word] += 1
      res
    end
  end
schema.rb
create_table   quot;page_versionsquot;, :force => true do |t|
  t.integer    quot;page_idquot;
  t.integer    quot;versionquot;
  t.text       quot;bodyquot;
  t.datetime   quot;created_atquot;
  t.datetime   quot;updated_atquot;
end

create_table   quot;pagesquot;, :force => true do |t|
  t.string     quot;titlequot;
  t.text       quot;bodyquot;
  t.datetime   quot;created_atquot;
  t.datetime   quot;updated_atquot;
  t.integer    quot;versionquot;,    :default => 1
end
AR Summary

• Page has_many PageVersions
• ugly schema with duplicated table
• acts_as_versioned does the magic for us
• statistics - ?!?
CouchDB Wiki
  How does it work?
The Page
{
    _id: “89765”,
    _rev: “lb7tlb”,
    type: “Page”,
    title: “page one”,
    body: “this is page one”
}
Page Versions
{
    _id: “765”,
    _rev: “lhjb97”
    type: “PageVersion”,
    title: “page one”,
    body: “this is page one”,
    version: 23,
    page_id: “89765”
}
All in one namespace
    {                                                                            {
        _id: “ 89765”,                           {
                                                                                     _id: “ 9753”,
                                                     _id: “97865”,
        _rev: “lb7tlb”,                                                              _rev: “lb7tlb”,
                                                     _rev: “lhjb97”
        type: “Page”,                                type: “PageVersion”,
                                                                                     type: “Page”,
                                                     title: “page one”,
        title: “page one”,                                                           title: “page one”,
                                                     body: “this is page one”,
        body: “this is page one”                     version: 23,
                                                                                     body: “this is page one”
                                                     page_id: “89765”
    }                  {
                                                                                 }
                                                  }
                           _id: “6437”,
                           _rev: “lhjb97”                                                     {
                           type: “PageVersion”,                                                   _id: “6367”,
                           title: “page one”,
{                                                           {                                     _rev: “lhjb97”
                           body: “this is page one”,                                              type: “PageVersion”,
    _id: “ 76538”,                                              _id: “ 8975763”,
                           version: 23,                                                           title: “page one”,
                           page_id: “89765”
    _rev: “lb7tlb”, }                                           _rev: “lb7tlb”,                   body: “this is page one”,
                                                                                                  version: 23,
    type: “Page”,                                               type: “Page”,                     page_id: “89765”
    title: “page one”,                                          title: “page one”,            }
    body: “this is page one”                                    body: “this is page one”
}                                                           }
Finding pages
function(doc) {                 key       value
  if(doc.type == “Page”) {
    emit(doc.title, doc);
                              “page 2”    {...}
  }
}
                             “page one”   {...}
Finding Page Versions
function(doc) {
  if(doc.type == “PageVersion”) {
    emit([doc.page_id, doc.version], doc);
  }
}                                key          value
                            [“ladsb7gi”, 1]   {...}
                            [“ladsb7gi”, 2]   {...}
                            [“nloh79d”, 1]    {...}
Finding Page Versions
                               key          value
                          [“ladsb7gi”, 1]   {...}
                          [“ladsb7gi”, 2]   {...}
                          [“nloh79d”, 1]    {...}


GET /mydb/_design/page_versions/_view/by_page? 
  startkey=[“ladsb7gi”, 1]&endkey=[“ ladsb7gi”,{}]
Counting Words - Map
Counting Words - Map



{body: “page one”}
 {body: “page 2”}
Counting Words - Map
function(doc) {
  if(doc.type == 'Page') {
    var words = doc.body.split(/W/);
    words.forEach(function(word) {
      if (word.length > 0) emit(word, 1);
});}}




{body: “page one”}
 {body: “page 2”}
Counting Words - Map
function(doc) {
  if(doc.type == 'Page') {
    var words = doc.body.split(/W/);
    words.forEach(function(word) {
      if (word.length > 0) emit(word, 1);
});}}

                                   key      value
                                  “page”      1
{body: “page one”}
                                  “page”      1
 {body: “page 2”}
                                  “one”       1
                                   “2”        1
Counting Words - reduce
Counting Words - reduce
 key     value
“page”     1
“page”     1
“one”      1
 “2”       1
Counting Words - reduce
  key          value
 “page”          1
 “page”          1
 “one”           1
  “2”            1


function(keys, values) {
  return sum(values);
}
Counting Words - reduce
  key          value
 “page”          1
 “page”          1
 “one”           1
  “2”            1
                            key     value
                           “page”    2
function(keys, values) {
  return sum(values);
                           “one”     1
}

                            “2”      1
CouchDB summary

• no schema, arbitrary documents in one
  namespace
• still use foreign keys to implement
  associations
• create views instead of join tables
• views! views! views!
Show us the
frameworks already
What’s the framework’s job?
What’s the framework’s job?
      ActiveRecord
What’s the framework’s job?
         ActiveRecord

• map objects to relations and back
• do the whole SQL thing
What’s the framework’s job?
              ActiveRecord
schema                                   attribute auto
tracking                                   detection
          serialized attributes   pagination
  groups
                       JOINS unique    lazy loading
         caching
     • map objects to relations and back count
     • do the whole SQL thing           HABTM
                        create or update?
  has_many :through                   conditions
       eager association loading
connection DDL              :dependent => :destroy
What’s the framework’s job?
          ActiveRecord
           Page.all :include => :tags



SELECT pages.id ... JOIN tags ON ... WHERE ...
           ... [10 more lines] ...
What’s the framework’s job?
      ActiveRecord

      big fat abstraction


            SQL
What’s the framework’s job?
 ActiveCouchRelaxFooDBObject
What’s the framework’s job?
 ActiveCouchRelaxFooDBObject

      <#134 Page title=”page one”>




{type: “Page”, title: “page one”}
What’s the framework’s job?
 ActiveCouchRelaxFooDBObject


POST /mydb/, {title: “page one”, type: “Page”}

            GET /mydb/page-one
What’s the framework’s job?
 ActiveCouchRelaxFooDBObject


                          skinny
         CouchDB        abstraction
ActiveCouchRelaxFooDBObject


          ... are not *that* important
The frameworks

       CouchPoato        RelaxDB
                    CouchObject
ActiveCouch
                        CouchRest
    CouchFoo
CouchRest


• 2 in 1
• foundation for most
  other frameworks
Low level part

• relatively thin layer on top of RestClient
• store and retrieve JSON structures
• query views the Couch way
Class mapping part


• map Ruby classes to JSON documents
• CRUD
• declarative views with CouchDB
  semantics
RelaxDB

• CRUD + very basic associations
• automatic view generation via view_by
• a bit of support for custom views via
  RelaxDB::View
• CouchDB like view API
Couch Object

• last updated in 2007
• pretty low level - okay for learning
  the details of Couch the DIY way
• no update, no properties, no
  automatic view creation
Couch Potato
• CRUD, associations + JSON mapping
• built-in acts_as_versioned - 60 LOC but
  doing it by hand only requires 7
• ViewQuery class for creating/querying
  custom views
• AR like finders
CouchFoo

• takes ActiveRecord and makes it
  work with CouchDB
• if you (have) to migrate an AR
  app...
• doesn’t give you the power of
  CouchDB
ActiveCouch
• “Object Relational Mapper for [..]
  CouchDB”
• “Since, the Rubyists here at Wego are
  already very familiar with ActiveRecord
  semantics, care has been taken to ensure
  that ActiveCouch resembled it in many
  ways.”
ActiveCouch

• one database per model
• View class to upload #@!? views via Rake
  task
• no support for custom views
Use the source
CouchRest Wiki
Page CRUD
class Page < CouchRest::ExtendedDocument
  update_callback :after, :create_version

  property :title          can’t infer attributes from table
  property :body

  view_by :title
                         auto-generate simple views
  def create_version
    PageVersion.new(:page_id => id,
      :body => @body_was, :version => versions_count + 1).save!
  end
                                  create version on update
end
PageVersion

class PageVersion < CouchRest::ExtendedDocument
  property :body
  property :version
  property :page_id

  view_by [:page_id, :version]
end
Word Count
class WordCount < CouchRest::ExtendedDocument
  view_by :all, :map => quot;function(doc) {
     if(doc['couchrest-type'] == 'Page') {
       var words = doc.body.split(/W/);
       words.forEach(function(word) {
         if (word.length > 0) emit(word, 1);
       });
     }
  }quot;,
  :reduce => quot;function(keys, values) {
     return sum(values);
  }quot;
end
Querying Views
Page.by_title

Page.by_created_at(:limit => 1)

PageVersion.get params[:id]

Page.by_title(:key => title, :limit => 1).first

WordCount.all
One more thing
CouchApp


• serve entire apps directly from CouchDB
• just JSON, HTML & JavaScript
What is CouchApp

• bunch of Ruby Python scripts to help with
  development/deployment
• data, CouchDB views, validations, shows,
  lists and assets in one database
AJAX apps
•   serve HTML, CSS as assets

•   do all the work in JavaScript

•   in the browser: GET from couch and append
    HTML, POST form data to CouchDB to
    update documents

•   in CouchDB: views to retrieve, compute data,
    validations
“real” apps

• lists
• shows
• server HTML, XML etc. from CouchDB
Conclusion
DON’T

use ActiveCouch
unless you understand why it is
the way it is

or Couch Potato
I’ll break all of its bones and APIS
DON’T


or CouchFoo
unless you want more power
than AR can give you
Conclusion


forgetting about the ActiveRecord way
is more important than what framework
Conclusion


think in documents & views,
not in records and associations
Conclusion


CouchDB is not about finding your
records, it’s about clever map/reduce
to get exactly what you want
What you want is


a thin abstraction
CouchDB semantics, not ActiveRecord
start simple with CouchREST or RelaxDB
and relax...




       time to relax
Resources
•   The CouchDB book
    http://books.couchdb.org/relax/

•   jchris CouchApp talk
    http://jchrisa.net/drl/CouchDB%20Talk%20at%20Vidoop/
    VidoopCouchTalk.pdf

•   janl CouchDB talk
    http://www.slideshare.net/bbcwebdev/introduction-into-couchdb-
    jan-lehnardt-presentation

•   The example wiki
    http://github.com/langalex/couchdb_example_wiki/

•   http://couch.io
    support, training, hosting, development
Questions?
• Email: alex@upstream-berlin.com
• Twitter: @langalex




                   time to relax

More Related Content

What's hot

DrupalCon Chicago Practical MongoDB and Drupal
DrupalCon Chicago Practical MongoDB and DrupalDrupalCon Chicago Practical MongoDB and Drupal
DrupalCon Chicago Practical MongoDB and DrupalDoug Green
 
XML Binding Language 2.0
XML Binding Language 2.0XML Binding Language 2.0
XML Binding Language 2.0Marcos Caceres
 
JQuery In Rails
JQuery In RailsJQuery In Rails
JQuery In RailsLouie Zhao
 
Doctrine MongoDB Object Document Mapper
Doctrine MongoDB Object Document MapperDoctrine MongoDB Object Document Mapper
Doctrine MongoDB Object Document MapperJonathan Wage
 
Learning the basics of the Drupal API
Learning the basics of the Drupal APILearning the basics of the Drupal API
Learning the basics of the Drupal APIAlexandru Badiu
 
ZendCon2010 Doctrine MongoDB ODM
ZendCon2010 Doctrine MongoDB ODMZendCon2010 Doctrine MongoDB ODM
ZendCon2010 Doctrine MongoDB ODMJonathan Wage
 
H T M L Help Sheet
H T M L  Help  SheetH T M L  Help  Sheet
H T M L Help Sheet51 lecture
 
What's new in the Drupal 7 API?
What's new in the Drupal 7 API?What's new in the Drupal 7 API?
What's new in the Drupal 7 API?Alexandru Badiu
 
Symfony2 from the Trenches
Symfony2 from the TrenchesSymfony2 from the Trenches
Symfony2 from the TrenchesJonathan Wage
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For BeginnersJonathan Wage
 
Aggregation in MongoDB
Aggregation in MongoDBAggregation in MongoDB
Aggregation in MongoDBKishor Parkhe
 
Symfony Day 2010 Doctrine MongoDB ODM
Symfony Day 2010 Doctrine MongoDB ODMSymfony Day 2010 Doctrine MongoDB ODM
Symfony Day 2010 Doctrine MongoDB ODMJonathan Wage
 

What's hot (18)

HTML5 - Pedro Rosa
HTML5 - Pedro RosaHTML5 - Pedro Rosa
HTML5 - Pedro Rosa
 
DrupalCon Chicago Practical MongoDB and Drupal
DrupalCon Chicago Practical MongoDB and DrupalDrupalCon Chicago Practical MongoDB and Drupal
DrupalCon Chicago Practical MongoDB and Drupal
 
Doctrine for NoSQL
Doctrine for NoSQLDoctrine for NoSQL
Doctrine for NoSQL
 
Doctrine and NoSQL
Doctrine and NoSQLDoctrine and NoSQL
Doctrine and NoSQL
 
IN4308 Lecture 3
IN4308 Lecture 3IN4308 Lecture 3
IN4308 Lecture 3
 
Jquery
JqueryJquery
Jquery
 
XML Binding Language 2.0
XML Binding Language 2.0XML Binding Language 2.0
XML Binding Language 2.0
 
JQuery In Rails
JQuery In RailsJQuery In Rails
JQuery In Rails
 
Intoduction to php restful web service
Intoduction to php  restful web serviceIntoduction to php  restful web service
Intoduction to php restful web service
 
Doctrine MongoDB Object Document Mapper
Doctrine MongoDB Object Document MapperDoctrine MongoDB Object Document Mapper
Doctrine MongoDB Object Document Mapper
 
Learning the basics of the Drupal API
Learning the basics of the Drupal APILearning the basics of the Drupal API
Learning the basics of the Drupal API
 
ZendCon2010 Doctrine MongoDB ODM
ZendCon2010 Doctrine MongoDB ODMZendCon2010 Doctrine MongoDB ODM
ZendCon2010 Doctrine MongoDB ODM
 
H T M L Help Sheet
H T M L  Help  SheetH T M L  Help  Sheet
H T M L Help Sheet
 
What's new in the Drupal 7 API?
What's new in the Drupal 7 API?What's new in the Drupal 7 API?
What's new in the Drupal 7 API?
 
Symfony2 from the Trenches
Symfony2 from the TrenchesSymfony2 from the Trenches
Symfony2 from the Trenches
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For Beginners
 
Aggregation in MongoDB
Aggregation in MongoDBAggregation in MongoDB
Aggregation in MongoDB
 
Symfony Day 2010 Doctrine MongoDB ODM
Symfony Day 2010 Doctrine MongoDB ODMSymfony Day 2010 Doctrine MongoDB ODM
Symfony Day 2010 Doctrine MongoDB ODM
 

Similar to Ruby sittin' on the Couch

Umleitung: a tiny mochiweb/CouchDB app
Umleitung: a tiny mochiweb/CouchDB appUmleitung: a tiny mochiweb/CouchDB app
Umleitung: a tiny mochiweb/CouchDB appLenz Gschwendtner
 
Rails GUI Development with Ext JS
Rails GUI Development with Ext JSRails GUI Development with Ext JS
Rails GUI Development with Ext JSMartin Rehfeld
 
Hacking with ruby2ruby
Hacking with ruby2rubyHacking with ruby2ruby
Hacking with ruby2rubyMarc Chung
 
development, ruby, conferences, frameworks, ruby on rails, confreaks, actsasc...
development, ruby, conferences, frameworks, ruby on rails, confreaks, actsasc...development, ruby, conferences, frameworks, ruby on rails, confreaks, actsasc...
development, ruby, conferences, frameworks, ruby on rails, confreaks, actsasc...ActsAsCon
 
Relaxing With CouchDB
Relaxing With CouchDBRelaxing With CouchDB
Relaxing With CouchDBleinweber
 
Migrating To Ruby1.9
Migrating To Ruby1.9Migrating To Ruby1.9
Migrating To Ruby1.9tomaspavelka
 
Functional programming using underscorejs
Functional programming using underscorejsFunctional programming using underscorejs
Functional programming using underscorejs偉格 高
 
jQuery Internals + Cool Stuff
jQuery Internals + Cool StuffjQuery Internals + Cool Stuff
jQuery Internals + Cool Stuffjeresig
 
jQuery Presentation to Rails Developers
jQuery Presentation to Rails DevelopersjQuery Presentation to Rails Developers
jQuery Presentation to Rails DevelopersYehuda Katz
 
MongoDB Aggregation Framework
MongoDB Aggregation FrameworkMongoDB Aggregation Framework
MongoDB Aggregation FrameworkCaserta
 
Merb Pluming - The Router
Merb Pluming - The RouterMerb Pluming - The Router
Merb Pluming - The Routercarllerche
 
The Dom Scripting Toolkit J Query
The Dom Scripting Toolkit J QueryThe Dom Scripting Toolkit J Query
The Dom Scripting Toolkit J QueryQConLondon2008
 
What's up with Prototype and script.aculo.us?
What's up with Prototype and script.aculo.us?What's up with Prototype and script.aculo.us?
What's up with Prototype and script.aculo.us?Christophe Porteneuve
 
Network Automation: Ansible 102
Network Automation: Ansible 102Network Automation: Ansible 102
Network Automation: Ansible 102APNIC
 

Similar to Ruby sittin' on the Couch (20)

CouchDB
CouchDBCouchDB
CouchDB
 
Umleitung: a tiny mochiweb/CouchDB app
Umleitung: a tiny mochiweb/CouchDB appUmleitung: a tiny mochiweb/CouchDB app
Umleitung: a tiny mochiweb/CouchDB app
 
Rails GUI Development with Ext JS
Rails GUI Development with Ext JSRails GUI Development with Ext JS
Rails GUI Development with Ext JS
 
Hacking with ruby2ruby
Hacking with ruby2rubyHacking with ruby2ruby
Hacking with ruby2ruby
 
Rails <form> Chronicle
Rails <form> ChronicleRails <form> Chronicle
Rails <form> Chronicle
 
development, ruby, conferences, frameworks, ruby on rails, confreaks, actsasc...
development, ruby, conferences, frameworks, ruby on rails, confreaks, actsasc...development, ruby, conferences, frameworks, ruby on rails, confreaks, actsasc...
development, ruby, conferences, frameworks, ruby on rails, confreaks, actsasc...
 
Relaxing With CouchDB
Relaxing With CouchDBRelaxing With CouchDB
Relaxing With CouchDB
 
Migrating To Ruby1.9
Migrating To Ruby1.9Migrating To Ruby1.9
Migrating To Ruby1.9
 
Couchdb
CouchdbCouchdb
Couchdb
 
Functional programming using underscorejs
Functional programming using underscorejsFunctional programming using underscorejs
Functional programming using underscorejs
 
jQuery Internals + Cool Stuff
jQuery Internals + Cool StuffjQuery Internals + Cool Stuff
jQuery Internals + Cool Stuff
 
Rack Middleware
Rack MiddlewareRack Middleware
Rack Middleware
 
Couchdb
CouchdbCouchdb
Couchdb
 
Capistrano2
Capistrano2Capistrano2
Capistrano2
 
jQuery Presentation to Rails Developers
jQuery Presentation to Rails DevelopersjQuery Presentation to Rails Developers
jQuery Presentation to Rails Developers
 
MongoDB Aggregation Framework
MongoDB Aggregation FrameworkMongoDB Aggregation Framework
MongoDB Aggregation Framework
 
Merb Pluming - The Router
Merb Pluming - The RouterMerb Pluming - The Router
Merb Pluming - The Router
 
The Dom Scripting Toolkit J Query
The Dom Scripting Toolkit J QueryThe Dom Scripting Toolkit J Query
The Dom Scripting Toolkit J Query
 
What's up with Prototype and script.aculo.us?
What's up with Prototype and script.aculo.us?What's up with Prototype and script.aculo.us?
What's up with Prototype and script.aculo.us?
 
Network Automation: Ansible 102
Network Automation: Ansible 102Network Automation: Ansible 102
Network Automation: Ansible 102
 

Recently uploaded

Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piececharlottematthew16
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machinePadma Pradeep
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...Fwdays
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clashcharlottematthew16
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyAlfredo García Lavilla
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Manik S Magar
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 

Recently uploaded (20)

Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piece
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machine
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clash
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easy
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptxE-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 

Ruby sittin' on the Couch