Skip to content

Instantly share code, notes, and snippets.

@davybrion
Created September 15, 2012 14:44
Show Gist options
  • Save davybrion/3728289 to your computer and use it in GitHub Desktop.
Save davybrion/3728289 to your computer and use it in GitHub Desktop.
code snippets for "Using NHibernate To Persist And Query Ruby Objects" post, part III
class ObjectFactory
def self.create_from_nhibernate_hash(hashtable)
entity_name = hashtable[NHibernator::TYPE_KEY_NAME.to_clr_string]
entity = const_get(entity_name.to_sym).new
entity.hydrate_from hashtable
entity
end
def self.create_proxy_from_nhibernate_hash(hashtable, entity_name, id)
proxy = const_get("#{entity_name}Proxy".to_sym).new
proxy.hydrate_from hashtable, id
proxy
end
def self.create_multiple_from_nhibernate_list(list)
entities = []
# TODO: differentiate between proxies and normal entities in the list
list.each { |hash| entities << create_from_nhibernate_hash(hash) }
entities
end
end
TYPE_KEY_NAME = "$type$"
def self.each_writeable_accessor_of(klass, &block)
setters = klass.public_instance_methods(true).select { |name| name =~ /\w=$/ }
setters.each { |setter| yield setter }
end
def self.initialize(session_factory)
all_class_metadata = session_factory.get_all_class_metadata
all_class_metadata.keys.each do |key|
metadata = all_class_metadata[key]
realclass = Object::const_get(key)
realclass.send :include, NHibernator
create_proxy_class_for realclass, metadata.identifier_property_name
end
end
def self.create_proxy_class_for(klass, identifier_name)
proxyclass = Class.new(klass)
Object::const_set "#{klass.name}Proxy", proxyclass
proxyclass.class_eval do
define_method identifier_name do
@id
end
def hydrate_from(hashtable, id)
@nhibernate_values = hashtable
@id = id
end
end
each_writeable_accessor_of(klass) do |setter|
proxyclass.class_eval do
define_method setter do |value|
# execute the getter to force NH's lazy proxymap to fetch the data
send setter.to_s.chop
super value
end
end
end
end
def self.include(base)
# everything you do within this method will be executed whenever
# this module is included in a class... the base parameter is
# the class that included the module
# ...
end
each_writeable_accessor_of(base) do |setter|
getter = setter.to_s.chop
base.class_eval do
undef_method getter
undef_method setter
define_method getter do
return nil if @nhibernate_values.nil?
value = @nhibernate_values[getter.to_clr_string]
return value unless value.is_a? System::Collections::IEnumerable
# TODO: cache the WrappedList instance
WrappedList.new(value)
end
define_method setter do |value|
@nhibernate_values = System::Collections::Hashtable.new if @nhibernate_values.nil?
@nhibernate_values[setter.to_s.chop.to_clr_string] = value
end
end
end
base.send :include, System::Collections::IDictionary
base.class_eval do
def nhibernate_values
@nhibernate_values
end
def hydrate_from(hashtable)
@nhibernate_values = hashtable
referenced_entities = Hash.new
hashtable.keys.each do |key|
value = hashtable[key.to_clr_string]
if value.is_a? System::Collections::IDictionary
if value.is_a? System::Collections::Hashtable
referenced_entity = ObjectFactory.create_from_nhibernate_hash(value)
else
type = value.hibernate_lazy_initializer.entity_name
id = value.hibernate_lazy_initializer.identifier
referenced_entity = ObjectFactory.create_proxy_from_nhibernate_hash(value, type, id)
end
referenced_entities[key] = referenced_entity
end
end
referenced_entities.keys.each { |key| send "#{key}=", referenced_entities[key] }
end
def Equals(other)
self == other
end
def GetHashCode
hash
end
def ==(other)
return false if other.nil?
return @nhibernate_values.Equals(other) if other.is_a? System::Collections::IDictionary
return false unless other.respond_to? :nhibernate_values
other.nhibernate_values.Equals(@nhibernate_values)
end
def hash
@nhibernate_values.GetHashCode()
end
def [](key)
self.send key
end
def []=(key, value)
self.send "#{key}=", value
end
end
class WrappedList
include System::Collections::IList
def initialize(list)
@list = list
end
def each(&block)
@list.each do |item|
if item.respond_to? :nhibernate_values
yield item
else
yield ObjectFactory.create_from_nhibernate_hash(item)
end
end
end
def GetEnumerator
WrappedListEnumerator.new(self)
end
def add(item)
@list.add item
end
def clear
@list.clear
end
def contains(item)
@list.contains item
end
def count
@list.count
end
def remove(item)
original_count = count
if item.respond_to? :nhibernate_values
@list.remove item.nhibernate_values
else
@list.remove item
end
original_count != count
end
def is_read_only
@list.is_read_only
end
def index_of(item)
@list.index_of item
end
def insert(index, item)
@list.insert index, item
end
def remove_at(index)
@list.remove_at index
end
def [](index)
item = @list[index]
return item if item.respond_to? :nhibernate_values
ObjectFactory.create_from_nhibernate_hash(item)
end
def []=(index, item)
@list[index] = item
end
def Equals(other)
self == other
end
def GetHashCode
hash
end
def ==(other)
return false if other.nil?
@list.Equals(other)
end
def hash
GetHashCode
end
end
class WrappedListEnumerator
include System::Collections::IEnumerator
def initialize(wrappedlist)
@wrappedlist = wrappedlist
reset
end
def reset
@current_index = -1
end
def current
@wrappedlist[@current_index]
end
def move_next
@current_index += 1
return false if @current_index >= @wrappedlist.count
true
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment