SlideShare una empresa de Scribd logo
1 de 136
Descargar para leer sin conexión
* #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

Más contenido relacionado

La actualidad más candente

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
 

La actualidad más candente (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 a 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 a 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
 

Último

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
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsPixlogix Infotech
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxLoriGlavin3
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfAddepto
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningLars Bell
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embeddingZilliz
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rick Flair
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxLoriGlavin3
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersRaghuram Pandurangan
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
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
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfLoriGlavin3
 
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
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 

Último (20)

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
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and Cons
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdf
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine Tuning
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embedding
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information Developers
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
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
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdf
 
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!
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 

Ruby sittin' on the Couch