• Stars
    star
    146
  • Rank 252,855 (Top 5 %)
  • Language
    Ruby
  • License
    MIT License
  • Created over 15 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Implementation-agnostic git-like hashes and history for Ruby objects

Gibbler - v0.9

Git-like hashes and history for Ruby objects for Ruby 1.8, 1.9 and JRuby.

Check out the screencast created by Alex Peuchert.

Some things to keep in mind

  • Digest calculation may change between minor releases (as it did between 0.6 and 0.7)

  • Gibbler history is not suitable for very large objects since it keeps complete copies of the object in memory. This is a very early implementation of this feature so don’t rely on it for production code.

  • Don’t forget to enjoy your life!

Example 1 – Standalone Usage

require 'gibbler'

g = Gibbler.new 'id', 1001   # => f4fb3796ababa3788d1bded8fdc589ab1ccb1c3d
g.base(36)                   # => sm71s7eam4hm5jlsuzlqkbuktwpe5h9

g == 'f4fb3796ababa3788d1bded8fdc589ab1ccb1c3d'   # => true
g === 'f4fb379'              # => true

Example 2 – Mixins Usage

require 'gibbler/mixins'

"kimmy".gibbler              # => c8027100ecc54945ab15ddac529230e38b1ba6a1
:kimmy.gibbler               # => 52be7494a602d85ff5d8a8ab4ffe7f1b171587df

config = {}
config.gibbler               # => 4fdcadc66a38feb9c57faf3c5a18d5e76a6d29bf
config.gibbled?              # => false

config[:server] = {          
  :users => [:dave, :ali],   
  :ports => [22, 80, 443]    
}                            
config.gibbled?              # => true
config.gibbler               # => ef23d605f8c4fc80a8e580f9a0e8dab8426454a8

config[:server][:users] << :yanni

config.gibbler               # => 4c558a56bc2abf5f8a845a69e47ceb5e0003683f

config.gibbler.short         # => 4c558a56

config.gibbler.base36        # => 8x00l83jov4j80i9vfzpaxr9jag23wf

config.gibbler.base36.short  # => 8x00l83j

Example 3 – Object History

Gibbler can also keep track of the history of changes to an object. By default Gibbler supports history for Hash, Array, and String objects. The gibbler_commit method creates a clone of the current object and stores in an instance variable using the current hash digest as the key.

require 'gibbler/mixins'
require 'gibbler/history'

a = { :magic => :original }     
a.gibbler_commit             # => d7049916ddb25e6cc438b1028fb957e5139f9910

a[:magic] = :updated           
a.gibbler_commit             # => b668098e16d08898532bf3aa33ce2253a3a4150e

a[:magic] = :changed 
a.gibbler_commit             # => 0b11c377fccd44554a601e5d2b135c46dc1c4cb1

a.gibbler_history            # => d7049916, b668098e, 0b11c377

a.gibbler_revert! 'd7049916' # Return to a specific commit
a.gibbler                    # => d7049916ddb25e6cc438b1028fb957e5139f9910
a                            # => { :magic => :original }

a.delete :magic

a.gibbler_revert!            # Return to the previous commit
a.gibbler                    # => 0b11c377fccd44554a601e5d2b135c46dc1c4cb1
a                            # => { :magic => :changed }

a.gibbler_object 'b668098e'  # => { :magic => :updated }
a.gibbler_stamp              # => 2009-07-01 18:56:52 -0400

Example 4 – Method Aliases

If you have control over the namespaces of your objects, you can use the method aliases to tighten up your code a bit. The “gibbler” and “gibbled?” methods can be accessed via “digest” and “changed?”, respectively. (The reason they’re not enabled by default is to avoid conflicts.)

require 'gibbler/aliases'

"kimmy".digest               # => c8027100ecc54945ab15ddac529230e38b1ba6a1
:kimmy.digest                # => 52be7494a602d85ff5d8a8ab4ffe7f1b171587df

a = [:a, :b, :c]
a.digest                     # => e554061823b8f06367555d1ee4c25b4ffee61944
a << :d
a.changed?                   # => true

The history methods also have aliases which remove the “gibbler_” prefix.

require 'gibbler/aliases'
require 'gibbler/history'

a = { :magic => :original }     
a.commit                     
a.history                    
a.revert!                    
# etc...

Example 5 – Different Digest types

By default Gibbler creates SHA1 hashes. You can change this globally or per instance.

require 'gibbler/mixins'

Gibbler.digest_type = Digest::MD5

:kimmy.gibbler               # => 0c61ff17f46223f355759934154d5dcb

:kimmy.gibbler(Digest::SHA1) # => 52be7494a602d85ff5d8a8ab4ffe7f1b171587df

In Jruby, you can grab the digest types from the openssl library.

require 'openssl'

Gibbler.digest_type = OpenSSL::Digest::SHA256

:kimmy.gibbler               # => 1069428e6273cf329436c3dce9b680d4d4e229d7b7...

Example 6 – All your base

require 'gibbler/mixins'

:kimmy.gibbler               # => 52be7494a602d85ff5d8a8ab4ffe7f1b171587df
:kimmy.gibbler.base(16)      # => 52be7494a602d85ff5d8a8ab4ffe7f1b171587df
:kimmy.gibbler.base(36)      # => 9nydr6mpv6w4k8ngo3jtx0jz1n97h7j

:kimmy.gibbler.base(10)      # => 472384540402900668368761869477227308873774630879
:kimmy.gibbler.to_i          # => 472384540402900668368761869477227308873774630879

Example 7 – Global secret

Gibbler can prepend all digest inputs with a global secret. You can set this once per project to ensure your project’s digests are unique.

require 'gibbler/mixins'

:kimmy.gibbler               # => 52be7494a602d85ff5d8a8ab4ffe7f1b171587df

Gibbler.secret = "sUp0r5ekRu7"

:kimmy.gibbler               # => 6c5f5aff4d809cec7e7da091214a35a2698489f8

Supported Classes

Gibbler methods are available only to the classes which explicitly include them (see RDocs for details on which classes are supported by default). You can also extend custom objects:

class FullHouse
  include Gibbler::Complex
  attr_accessor :roles
end

a = FullHouse.new
a.gibbler                    # => 4192d4cb59975813f117a51dcd4454ac16df6703

a.roles = [:jesse, :joey, :danny, :kimmy, :michelle, :dj, :stephanie]
a.gibbler                    # => 6ea546919dc4caa2bab69799b71d48810a1b48fa

Gibbler::Complex creates a digest based on the name of the class and the names and values of the instance variables. See the RDocs for other Gibbler::* types.

If you want to support all Ruby objects, add the following to your application:

class Object
  include Gibbler::String
end

Gibbler::String creates a digest based on the name of the class and the output of the to_s method. This is a reasonable default for most objects however any object that includes the object address in to_s (e.g. “Object:0x0x4ac9f0…”) will produce unreliable digests (because the address can change).

As of 0.7 all Proc objects have the same digest: 12075835e94be34438376cd7a54c8db7e746f15d.

Known Issues

  • gibbler or gibbled? must be called at least once before gibbled? will be able to return a useful value (otherwise there is no previous digest value to compare to)

  • Digests for Bignum objects are different between Ruby and JRuby. Why?

  • Digests for Proc objects are different between Ruby 1.8 and 1.9 because Proc.arity returns different values and 1.8 has no lambda? method.

Installation

Via Rubygems:

$ gem install gibbler

or via download:

What People Are Saying

  • “nice approach - everything is an object, every object is ‘gittish’” – @olgen_morten

  • “gibbler is just awesome” – @TomK32

  • “wie cool ist Gibbler eigentlich?” – @we5

  • “it’s nice idea and implementation!” – HristoHristov

More Info

Thanks

  • Kalin Harvey (krrh) for the early feedback and artistic direction.

  • Alex Peuchert (aaalex) for creating the screencast.

Credits

License

See: LICENSE.txt

More Repositories

1

redis-dump

Backup and restore your Redis data to and from JSON.
Ruby
795
star
2

rye

Safe, parallel access to Unix shells from Ruby
Ruby
232
star
3

storable

Marshal Ruby classes into and out of multiple formats (yaml, json, csv, tsv)
Ruby
31
star
4

scruffy

An unofficial fork of the Ruby graphing library with sexy defaults for hi-res charts. (NOT MAINTAINED)
Ruby
31
star
5

sysinfo

All your system-independent infoz in one handy (Ruby) class
Ruby
23
star
6

otto

Auto-define your rack-apps in plaintext.
Ruby
19
star
7

tryouts

Ruby tests that read like documentation.
Ruby
19
star
8

net-scp

Pure Ruby implementation of the SCP protocol
Ruby
15
star
9

caesars

Rapid and delicious DSL prototyping in Ruby (NOT MAINTAINED)
Ruby
14
star
10

benelux

A mad timeline for your Ruby codes.
Ruby
6
star
11

attic

A place for Ruby objects to hide instance variables
Ruby
5
star
12

delano.github.com

I'm ❤️ building healthy, high-performing teams.
HTML
4
star
13

bluth

A simple queuing system built on Redis (with worker and scheduler daemons!)
Ruby
4
star
14

saxony

Parse gigantic XML files with pleasure and without running out of memory. (NOT MAINTAINED)
Ruby
3
star
15

uri-redis

URI support for Redis connection settings
Ruby
3
star
16

jerkstore

A database alternative for mostly-read applications NOT MAINTAINED
Ruby
3
star
17

hexoid

Generate Ruby style object ids
Ruby
3
star
18

insults

An insulting Ruby library.
Ruby
2
star
19

familia

A little help with Redis.
Ruby
2
star
20

data-all

A Perl module that provides access to data in many formats from many places
Perl
2
star
21

mrbelvedere

Basic operational stats for web apps. IN PROGRESS
Ruby
2
star
22

delanotes

The Delano Entertainment System
Ruby
2
star
23

annoy

Like your annoying friend that asks you questions all the time.
Ruby
2
star