SlideShare a Scribd company logo
1 of 26
Download to read offline
Redis and Ruby




Brian Kaney
IRC / github / twitter / quora / etc : bkaney
Developer at Vermonster <vermonster.com>
Haven't we heard Redis Talks
                  Before?
●   Yes, Redis is popular
●   Why is this different?
    ●   Not covering Resque, Caching, Sessions or even
        Pub/Sub
    ●   Usage of Redis to store Ruby objects
    ●   Why would you want to do that?
Quick Redis 101 - Datatypes
●   Keys are strings, no need to quote
●   Strings
●   Integers (not really- INCR is a string operation)
●   Lists
●   Sets
●   Sorted Sets (sets with a score)
●   http://redis.oi (interactive terminal; website
    written in cuba.io, incidentally)
Let's talk Ruby
●   Ruby has strings, hashes, arrays..
●   And hashes are many times used as data
    storage for Ruby objects..
●   Wouldn't it be nice to use Redis to persist Ruby
    objects?
Redis-rb
●   Download and install redis   http://redis.io/download
●   Install ruby gem
    $ gem install redis
●   Connection
    require 'redis'
    db = Redis.new
Ruby Serialization                        *
●   Suppose a simple hash
     movie = Hash[
         :name, 'Top Gun',
         :genre, 'Action'
     ]


●   Might be represented in redis as:
    db.hmset 'movie:1', 'name', 'Top Gun', 'genre', 'Action'
Auto-increment ID
●   Notice incrementing in the key name
    db.hmset 'movie:1', 'name', 'Top Gun', 'genre', 'Action'



●   Create tooling to track id's, we can use INCR
    def get_pk(item, db)
       pk = db.incr "#{item}:pk"
       "#{item}:#{pk}"
    end


    db.hmset get_pk('movies', db), 'name', 'Top Gun', ...
References
●   A reference, like in AR 'belongs_to'

●   Could be implemented similarly:
    db.hmset 'character:1', 'movie_id', 'movie:1'
Has Many
●   Embed as one of the keys
# Make a few jets
db.hmset 'jet:1', 'manufacturer', 'Grumman', 'model', 'F-14'

db.hmset 'jet:2', 'manufacturer', 'Northrop', 'model', 'F-5'



# Make our movie
db.hmset 'movie:1', 'jets', %w(jet:1 jet:2).to_json
Has Many (set)
●   But that's not really “redisy”
●   How about conceiving a new key name and creating a set?
    # Make a few jets
    db.hmset 'jet:1', 'manufacturer', 'Grumman', 'model', 'F-14'
    db.hmset 'jet:2', 'manufacturer', 'Northrop', 'model', 'F-5'


    # Make our movie
    db.hmset 'movie:1', 'name', 'Top Gun', 'genre', 'Action'


    # Add to a key to represent the set of jets
    db.sadd 'movie:1:jets', 'jet:1'
    db.sadd 'movie:1:jets', 'jet:2'
Find / Indexing
●   Finding items, need an index.
●   Indexes could be sets with prescribed keys.
    # Create a few movies
    db.hmset 'movie:1', 'name', 'Top Gun', 'genre', 'Action'
    db.hmset 'movie:2', 'name', 'Top Gun', 'genre', 'Action'
    db.hmset 'movie:3', 'name', 'Airplane', 'genre', 'Comedy'



    # Create an index on 'genre'
    db.sadd 'movie:index:genre:Action', 'movie:1'
    db.sadd 'movie:index:genre:Action', 'movie:2'
    db.sadd 'movie:index:genre:Comedy', 'movie:3'
Yikes!
We need a Key Strategy
●   Among other things...
Nest
●   Very simple convention
       <klass.underscore>:<identifier>
       movie:1
       jet:10
       character:iceman


●   https://github.com/soveran/nest/blob/master/lib/nest.rb
We need tooling to manage
             relationships
●   Nest gives nice convention for key, but what
    about sets, lists, references, indexes,
    collections, validation, callbacks, etc...

●   Enter Ohm

●   https://github.com/soveran/ohm
Ohm: Redis-Ruby Object Hash Mapper
●   Ohm models for movies, characters and jets.
    (see code)
Using Ohm (example)
(code)
Devops - AOF
●   AOF is a newish strategy for managing data.
●   Configuration (redis.conf):
        appendonly yes
        appendfilename appendonly.aof
●   Process to save is:
    ●   issue 'BGREWRITEAOF'
    ●   loop until complete
●   Process to load is:
    ●   stop redis
    ●   copy AOF file to prescribed location (redis.conf)
    ●   loop until loading is complete
Devops – AOF save
  %x{ echo "BGREWRITEAOF" | redis-cli }
  loop do
        sleep 1
        puts " * Waiting for aof to save..."
       save_status = %x{ echo "INFO" | redis-cli | grep
bgrewriteaof_in_progress }[/:([0-9])/,1]
        break if save_status == "0"
  end
  puts "DONE!"
Devops – AOF load
  loop do
        sleep 1
        puts " * Waiting for aof to load..."
       load_status = %x{ echo "INFO" | redis-cli | grep
loading }[/:([0-9])/,1]
        break if load_status == "0"
  end
  puts "DONE"
Devops - Sockets
●   Faster, no TCP overhead
●   Configuration (redis.conf)
      # port 6379
      unixsocket /tmp/redis.sock
●   Redis-cli
      $ redis-cli -s /tmp/redis.sock
●   Redis.rb
      Redis.new(:path => '/tmp/redis.sock')
Ohm::Contrib
    https://github.com/sinefunc/ohm-contrib
●   Ohm::Boundaries
●   Ohm::Callbacks
●   Ohm::Timestamping
●   Ohm::ToHash
●   Ohm::WebValidations
●   Ohm::NumberValidations
●   Ohm::ExtraValidations
●   Ohm::Typecast
●   Ohm::Locking
Ohm::Contrib is hacky
ruby-1.9.2-p180 :016 > os = Ohm::Types::String.new "key"; s = "key"
ruby-1.9.2-p180 :018 > os == s
 => true
ruby-1.9.2-p180 :019 > os === s
 => true
ruby-1.9.2-p180 :020 > hsh = { os => 'foo' }
 => {"key"=>"foo"}
ruby-1.9.2-p180 :021 > hsh[os]
 => "foo"
ruby-1.9.2-p180 :022 > hsh[s]
 => nil
Hacks - Overriding redis_id
require 'ohm'
class Ohm
 class Model
  # initialize: added ability to pass redis_id and have it define the actual Ohm ID. (new? is broken in Ohm, BTW)
  alias_method :initialize_without_redis_id, :initialize
  def initialize_with_redis_id(args={})
   @redis_id = args.delete(:redis_id)
   initialize_without_redis_id(args)
  end
  alias_method :initialize, :initialize_with_redis_id


  def initialize_id
   @id ||= (@redis_id || self.class.key[:id].incr.to_s)
  end
  private :initialize_id
end
Hacks – Adding list/set by id
●    Default to have the Ohm saved, use <<
●    We wanted to pass in id, since we prescribed them anyway.
class List
     def push_id(model_id)
      key.rpush(model_id)
     end
    end
    class Set
     def push_id(model_id)
      key.sadd(model_id)
     end
    end
Thanks

More Related Content

What's hot

COSCUP2012: How to write a bash script like the python?
COSCUP2012: How to write a bash script like the python?COSCUP2012: How to write a bash script like the python?
COSCUP2012: How to write a bash script like the python?
Lloyd Huang
 
Empacotamento e backport de aplicações em debian
Empacotamento e backport de aplicações em debianEmpacotamento e backport de aplicações em debian
Empacotamento e backport de aplicações em debian
Andre Ferraz
 
Using Node.js to Build Great Streaming Services - HTML5 Dev Conf
Using Node.js to  Build Great  Streaming Services - HTML5 Dev ConfUsing Node.js to  Build Great  Streaming Services - HTML5 Dev Conf
Using Node.js to Build Great Streaming Services - HTML5 Dev Conf
Tom Croucher
 

What's hot (20)

Nodejs a-practical-introduction-oredev
Nodejs a-practical-introduction-oredevNodejs a-practical-introduction-oredev
Nodejs a-practical-introduction-oredev
 
Node.js in production
Node.js in productionNode.js in production
Node.js in production
 
Nodejs - A-quick-tour-v3
Nodejs - A-quick-tour-v3Nodejs - A-quick-tour-v3
Nodejs - A-quick-tour-v3
 
Rust: Systems Programming for Everyone
Rust: Systems Programming for EveryoneRust: Systems Programming for Everyone
Rust: Systems Programming for Everyone
 
Nodejs - A quick tour (v4)
Nodejs - A quick tour (v4)Nodejs - A quick tour (v4)
Nodejs - A quick tour (v4)
 
Nodejs - Should Ruby Developers Care?
Nodejs - Should Ruby Developers Care?Nodejs - Should Ruby Developers Care?
Nodejs - Should Ruby Developers Care?
 
Perl Memory Use 201207 (OUTDATED, see 201209 )
Perl Memory Use 201207 (OUTDATED, see 201209 )Perl Memory Use 201207 (OUTDATED, see 201209 )
Perl Memory Use 201207 (OUTDATED, see 201209 )
 
Node.js - A practical introduction (v2)
Node.js  - A practical introduction (v2)Node.js  - A practical introduction (v2)
Node.js - A practical introduction (v2)
 
Nodejs - A quick tour (v5)
Nodejs - A quick tour (v5)Nodejs - A quick tour (v5)
Nodejs - A quick tour (v5)
 
Node.js - A Quick Tour II
Node.js - A Quick Tour IINode.js - A Quick Tour II
Node.js - A Quick Tour II
 
Introduction to redis - version 2
Introduction to redis - version 2Introduction to redis - version 2
Introduction to redis - version 2
 
COSCUP2012: How to write a bash script like the python?
COSCUP2012: How to write a bash script like the python?COSCUP2012: How to write a bash script like the python?
COSCUP2012: How to write a bash script like the python?
 
Node.js - As a networking tool
Node.js - As a networking toolNode.js - As a networking tool
Node.js - As a networking tool
 
Dirty - How simple is your database?
Dirty - How simple is your database?Dirty - How simple is your database?
Dirty - How simple is your database?
 
Empacotamento e backport de aplicações em debian
Empacotamento e backport de aplicações em debianEmpacotamento e backport de aplicações em debian
Empacotamento e backport de aplicações em debian
 
Redis acc
Redis accRedis acc
Redis acc
 
GlusterFS As an Object Storage
GlusterFS As an Object StorageGlusterFS As an Object Storage
GlusterFS As an Object Storage
 
Nginx-lua
Nginx-luaNginx-lua
Nginx-lua
 
Using Node.js to Build Great Streaming Services - HTML5 Dev Conf
Using Node.js to  Build Great  Streaming Services - HTML5 Dev ConfUsing Node.js to  Build Great  Streaming Services - HTML5 Dev Conf
Using Node.js to Build Great Streaming Services - HTML5 Dev Conf
 
Comredis
ComredisComredis
Comredis
 

Similar to Serializing Ruby Objects in Redis

Similar to Serializing Ruby Objects in Redis (20)

Redis and its many use cases
Redis and its many use casesRedis and its many use cases
Redis and its many use cases
 
Toolbox of a Ruby Team
Toolbox of a Ruby TeamToolbox of a Ruby Team
Toolbox of a Ruby Team
 
Gem That (2009)
Gem That (2009)Gem That (2009)
Gem That (2009)
 
RHCSA EX200 - Summary
RHCSA EX200 - SummaryRHCSA EX200 - Summary
RHCSA EX200 - Summary
 
Feb 2018 Spinnaker Meetup Reddit Presentation
Feb 2018 Spinnaker Meetup Reddit PresentationFeb 2018 Spinnaker Meetup Reddit Presentation
Feb 2018 Spinnaker Meetup Reddit Presentation
 
Ruby C extensions at the Ruby drink-up of Sophia, April 2012
Ruby C extensions at the Ruby drink-up of Sophia, April 2012Ruby C extensions at the Ruby drink-up of Sophia, April 2012
Ruby C extensions at the Ruby drink-up of Sophia, April 2012
 
Smalltalk on rubinius
Smalltalk on rubiniusSmalltalk on rubinius
Smalltalk on rubinius
 
Practical Testing of Ruby Core
Practical Testing of Ruby CorePractical Testing of Ruby Core
Practical Testing of Ruby Core
 
Introduction to NodeJS with LOLCats
Introduction to NodeJS with LOLCatsIntroduction to NodeJS with LOLCats
Introduction to NodeJS with LOLCats
 
[EXTENDED] Ceph, Docker, Heroku Slugs, CoreOS and Deis Overview
[EXTENDED] Ceph, Docker, Heroku Slugs, CoreOS and Deis Overview[EXTENDED] Ceph, Docker, Heroku Slugs, CoreOS and Deis Overview
[EXTENDED] Ceph, Docker, Heroku Slugs, CoreOS and Deis Overview
 
Boxen: How to Manage an Army of Laptops
Boxen: How to Manage an Army of LaptopsBoxen: How to Manage an Army of Laptops
Boxen: How to Manage an Army of Laptops
 
Perl - laziness, impatience, hubris, and one liners
Perl - laziness, impatience, hubris, and one linersPerl - laziness, impatience, hubris, and one liners
Perl - laziness, impatience, hubris, and one liners
 
One-Liners to Rule Them All
One-Liners to Rule Them AllOne-Liners to Rule Them All
One-Liners to Rule Them All
 
Ruby on Rails Presentation
Ruby on Rails PresentationRuby on Rails Presentation
Ruby on Rails Presentation
 
Automate with Ansible basic (2/e, English)
Automate with Ansible basic (2/e, English)Automate with Ansible basic (2/e, English)
Automate with Ansible basic (2/e, English)
 
Docker, c'est bonheur !
Docker, c'est bonheur !Docker, c'est bonheur !
Docker, c'est bonheur !
 
Crafting Beautiful CLI Applications in Ruby
Crafting Beautiful CLI Applications in RubyCrafting Beautiful CLI Applications in Ruby
Crafting Beautiful CLI Applications in Ruby
 
Node.js - The New, New Hotness
Node.js - The New, New HotnessNode.js - The New, New Hotness
Node.js - The New, New Hotness
 
Ansible - Swiss Army Knife Orchestration
Ansible - Swiss Army Knife OrchestrationAnsible - Swiss Army Knife Orchestration
Ansible - Swiss Army Knife Orchestration
 
Rocket Fuelled Cucumbers
Rocket Fuelled CucumbersRocket Fuelled Cucumbers
Rocket Fuelled Cucumbers
 

More from Brian Kaney (6)

Continuous Delivery
Continuous DeliveryContinuous Delivery
Continuous Delivery
 
Rest
RestRest
Rest
 
Newer Yankee Workshop - NoSQL
Newer Yankee Workshop -  NoSQLNewer Yankee Workshop -  NoSQL
Newer Yankee Workshop - NoSQL
 
Build-a-Gem Workshop
Build-a-Gem WorkshopBuild-a-Gem Workshop
Build-a-Gem Workshop
 
Build-a-Gem Workshop
Build-a-Gem WorkshopBuild-a-Gem Workshop
Build-a-Gem Workshop
 
Bostonrb Amazon Talk
Bostonrb Amazon TalkBostonrb Amazon Talk
Bostonrb Amazon Talk
 

Recently uploaded

Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
WSO2
 

Recently uploaded (20)

Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
 
Quantum Leap in Next-Generation Computing
Quantum Leap in Next-Generation ComputingQuantum Leap in Next-Generation Computing
Quantum Leap in Next-Generation Computing
 
AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)
AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)
AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Six Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal OntologySix Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal Ontology
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with Milvus
 
AI in Action: Real World Use Cases by Anitaraj
AI in Action: Real World Use Cases by AnitarajAI in Action: Real World Use Cases by Anitaraj
AI in Action: Real World Use Cases by Anitaraj
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
WSO2 Micro Integrator for Enterprise Integration in a Decentralized, Microser...
WSO2 Micro Integrator for Enterprise Integration in a Decentralized, Microser...WSO2 Micro Integrator for Enterprise Integration in a Decentralized, Microser...
WSO2 Micro Integrator for Enterprise Integration in a Decentralized, Microser...
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot ModelMcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
 
Modernizing Legacy Systems Using Ballerina
Modernizing Legacy Systems Using BallerinaModernizing Legacy Systems Using Ballerina
Modernizing Legacy Systems Using Ballerina
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 
Introduction to use of FHIR Documents in ABDM
Introduction to use of FHIR Documents in ABDMIntroduction to use of FHIR Documents in ABDM
Introduction to use of FHIR Documents in ABDM
 

Serializing Ruby Objects in Redis

  • 1. Redis and Ruby Brian Kaney IRC / github / twitter / quora / etc : bkaney Developer at Vermonster <vermonster.com>
  • 2. Haven't we heard Redis Talks Before? ● Yes, Redis is popular ● Why is this different? ● Not covering Resque, Caching, Sessions or even Pub/Sub ● Usage of Redis to store Ruby objects ● Why would you want to do that?
  • 3. Quick Redis 101 - Datatypes ● Keys are strings, no need to quote ● Strings ● Integers (not really- INCR is a string operation) ● Lists ● Sets ● Sorted Sets (sets with a score) ● http://redis.oi (interactive terminal; website written in cuba.io, incidentally)
  • 4. Let's talk Ruby ● Ruby has strings, hashes, arrays.. ● And hashes are many times used as data storage for Ruby objects.. ● Wouldn't it be nice to use Redis to persist Ruby objects?
  • 5. Redis-rb ● Download and install redis http://redis.io/download ● Install ruby gem $ gem install redis ● Connection require 'redis' db = Redis.new
  • 6. Ruby Serialization * ● Suppose a simple hash movie = Hash[ :name, 'Top Gun', :genre, 'Action' ] ● Might be represented in redis as: db.hmset 'movie:1', 'name', 'Top Gun', 'genre', 'Action'
  • 7. Auto-increment ID ● Notice incrementing in the key name db.hmset 'movie:1', 'name', 'Top Gun', 'genre', 'Action' ● Create tooling to track id's, we can use INCR def get_pk(item, db) pk = db.incr "#{item}:pk" "#{item}:#{pk}" end db.hmset get_pk('movies', db), 'name', 'Top Gun', ...
  • 8. References ● A reference, like in AR 'belongs_to' ● Could be implemented similarly: db.hmset 'character:1', 'movie_id', 'movie:1'
  • 9. Has Many ● Embed as one of the keys # Make a few jets db.hmset 'jet:1', 'manufacturer', 'Grumman', 'model', 'F-14' db.hmset 'jet:2', 'manufacturer', 'Northrop', 'model', 'F-5' # Make our movie db.hmset 'movie:1', 'jets', %w(jet:1 jet:2).to_json
  • 10. Has Many (set) ● But that's not really “redisy” ● How about conceiving a new key name and creating a set? # Make a few jets db.hmset 'jet:1', 'manufacturer', 'Grumman', 'model', 'F-14' db.hmset 'jet:2', 'manufacturer', 'Northrop', 'model', 'F-5' # Make our movie db.hmset 'movie:1', 'name', 'Top Gun', 'genre', 'Action' # Add to a key to represent the set of jets db.sadd 'movie:1:jets', 'jet:1' db.sadd 'movie:1:jets', 'jet:2'
  • 11. Find / Indexing ● Finding items, need an index. ● Indexes could be sets with prescribed keys. # Create a few movies db.hmset 'movie:1', 'name', 'Top Gun', 'genre', 'Action' db.hmset 'movie:2', 'name', 'Top Gun', 'genre', 'Action' db.hmset 'movie:3', 'name', 'Airplane', 'genre', 'Comedy' # Create an index on 'genre' db.sadd 'movie:index:genre:Action', 'movie:1' db.sadd 'movie:index:genre:Action', 'movie:2' db.sadd 'movie:index:genre:Comedy', 'movie:3'
  • 13. We need a Key Strategy ● Among other things...
  • 14. Nest ● Very simple convention <klass.underscore>:<identifier> movie:1 jet:10 character:iceman ● https://github.com/soveran/nest/blob/master/lib/nest.rb
  • 15. We need tooling to manage relationships ● Nest gives nice convention for key, but what about sets, lists, references, indexes, collections, validation, callbacks, etc... ● Enter Ohm ● https://github.com/soveran/ohm
  • 16. Ohm: Redis-Ruby Object Hash Mapper ● Ohm models for movies, characters and jets. (see code)
  • 18. Devops - AOF ● AOF is a newish strategy for managing data. ● Configuration (redis.conf): appendonly yes appendfilename appendonly.aof ● Process to save is: ● issue 'BGREWRITEAOF' ● loop until complete ● Process to load is: ● stop redis ● copy AOF file to prescribed location (redis.conf) ● loop until loading is complete
  • 19. Devops – AOF save %x{ echo "BGREWRITEAOF" | redis-cli } loop do sleep 1 puts " * Waiting for aof to save..." save_status = %x{ echo "INFO" | redis-cli | grep bgrewriteaof_in_progress }[/:([0-9])/,1] break if save_status == "0" end puts "DONE!"
  • 20. Devops – AOF load loop do sleep 1 puts " * Waiting for aof to load..." load_status = %x{ echo "INFO" | redis-cli | grep loading }[/:([0-9])/,1] break if load_status == "0" end puts "DONE"
  • 21. Devops - Sockets ● Faster, no TCP overhead ● Configuration (redis.conf) # port 6379 unixsocket /tmp/redis.sock ● Redis-cli $ redis-cli -s /tmp/redis.sock ● Redis.rb Redis.new(:path => '/tmp/redis.sock')
  • 22. Ohm::Contrib https://github.com/sinefunc/ohm-contrib ● Ohm::Boundaries ● Ohm::Callbacks ● Ohm::Timestamping ● Ohm::ToHash ● Ohm::WebValidations ● Ohm::NumberValidations ● Ohm::ExtraValidations ● Ohm::Typecast ● Ohm::Locking
  • 23. Ohm::Contrib is hacky ruby-1.9.2-p180 :016 > os = Ohm::Types::String.new "key"; s = "key" ruby-1.9.2-p180 :018 > os == s => true ruby-1.9.2-p180 :019 > os === s => true ruby-1.9.2-p180 :020 > hsh = { os => 'foo' } => {"key"=>"foo"} ruby-1.9.2-p180 :021 > hsh[os] => "foo" ruby-1.9.2-p180 :022 > hsh[s] => nil
  • 24. Hacks - Overriding redis_id require 'ohm' class Ohm class Model # initialize: added ability to pass redis_id and have it define the actual Ohm ID. (new? is broken in Ohm, BTW) alias_method :initialize_without_redis_id, :initialize def initialize_with_redis_id(args={}) @redis_id = args.delete(:redis_id) initialize_without_redis_id(args) end alias_method :initialize, :initialize_with_redis_id def initialize_id @id ||= (@redis_id || self.class.key[:id].incr.to_s) end private :initialize_id end
  • 25. Hacks – Adding list/set by id ● Default to have the Ohm saved, use << ● We wanted to pass in id, since we prescribed them anyway. class List def push_id(model_id) key.rpush(model_id) end end class Set def push_id(model_id) key.sadd(model_id) end end