Skip to content

Instantly share code, notes, and snippets.

@shanna
Created February 12, 2010 06:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shanna/302386 to your computer and use it in GitHub Desktop.
Save shanna/302386 to your computer and use it in GitHub Desktop.
# Used in 0.9.something but not in 0.10.something so far.
# Could probably replace the hook code with chainable save code these days?
require 'digest/md5'
require 'digest/sha1'
require 'dm-core'
require 'zlib'
module DataMapper
module Types
# Before saving/validating digest multiple properties.
#--
# TODO: Really should check each property for dirtyness and re-digest
# on read if required.
class Digest < DataMapper::Type
module InstanceMethods
def self.included(model)
model.class_eval <<-EOS, __FILE__, __LINE__
before(:valid?, :digest) if method_defined?(:valid?)
before(:save, :digest)
EOS
end
def digest
properties.each do |property|
type = property.type
type.respond_to?(:digest_map) || next
type.digest_map.empty? and raise("Empty property list for digest #{property.name}")
composite = type.digest_map.map do |p|
cp = properties[p] || raise("Unknown property #{p} for digest #{property.name}")
cp.value(attribute_get(p))
end.compact.join
attribute_set(property.name, type.digest(composite, property))
end
true
end
end
def self.inherited(target)
target.instance_variable_set("@primitive", self.primitive)
target.instance_variable_set("@length", self.length)
end
def self.digest_map
@digest_map ||= []
end
def self.digest_map=(value)
@digest_map = value
end
def self.new(*names)
klass = Class.new(self)
klass.digest_map = names
klass
end
def self.digest(value, property)
value
end
def self.bind(property)
property.model.send(:include, InstanceMethods)
end
class CRC32 < Digest
primitive Integer
def self.digest(value, property)
Zlib.crc32(value.to_s).to_i
end
end
class SHA1 < Digest
primitive String
length 40
def self.digest(value, property)
::Digest::SHA1.hexdigest(value.to_s)
end
end
class MD5 < Digest
primitive String
length 32
def self.digest(value, property)
::Digest::MD5.hexdigest(value.to_s)
end
end
end # Digest
end # Types
end # DataMapper
# Example:
class MyModel
include DataMapper::Resource
property :id, Digest::Sha1.new(:name, :url), :key => true, :writer => :potected
property :name, String
property :url, String, :length => 250
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment