Skip to content

Instantly share code, notes, and snippets.

@jgandt
Created February 17, 2012 21:43
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jgandt/1855631 to your computer and use it in GitHub Desktop.
Save jgandt/1855631 to your computer and use it in GitHub Desktop.
module ObjectifyFromHash
# Using this as a mix in we are able to maintain a meaningful class structure while exposing the hash keys as viable and visable methods.
# I had a lot more I wanted to do in my FileCopyTask, and I didn't feel that the objectification logic was correctly placed in my class.
# The really neat part about this is that you could extend an individual instance of an object and objectify it in place.
# You could do all sorts of other crazy things with definition of reader/writer/accessor permissions in the objectify call.
# This may be entirely useless and silly but I think it is a slightly better option than returning an object of the class Hashit/ObjectifyFromHash
OpenStruct is a viable alternative. However, I was unable to find a way to use the Plain class as a mixin.
# Thoughts? Comments? Need more of the code around what I'm doing? Is their an easier, clearer way (ActiveModel if working in rails)?
# .jpg
require 'objectify_from_hash'
class FileCopyTask
include ObjectifyFromHash
def initialize( file_copy_task_as_hash )
objectify file_copy_task_as_hash
end
# My implementation implements a method similar to this one. This is just a quick example
def find_a_source_file
# find a file in source dir with the proper file extension.
end
end
source_directory: copy_from_dir
destination_directory: copy_to_dir
module ObjectifyFromHash
def objectify( hash )
hash.each do |k,v|
self.instance_variable_set("@#{key}", value)
# tcocca was playing with this an noticed that manually defining the methods was both slow and silly. Thanks to Tom for this update: https://gist.github.com/tcocca
# Use attr_accessor if you want to allow read-write privileges on the variables.
self.class.send(:attr_accessor, key)
# Use attr_reader if you only want to allow READ privileges on the variables.
#self.class.send(:attr_reader, key)
# Use attr_writer if you only want to allow WRITE privileges on the variables.
#self.class.send(:attr_writer, key)
end
end
end
require 'file_copy_task'
# Now use it!
# load in a hash from a yaml
file_copy_task_hash = YAML::load( File.open('file_copy_task.yml')
# => { :source_directory => 'copy_from_dir', :destination_directory => 'copy_to_dir', :file_extension => '.txt' }
# Now lets make it a useable object
file_copy_task = FileCopyTask.new( file_copy_task )
# => hash keys have now been loaded as attribute accessors. huzzah. use 'em...
file_copy_task.source_directory
# => 'copy_from_dir'
file_copy_task.destination_directory = 'hey_look_a_new_destination_directory'
# => 'hey_look_a_new_destination_directory'
File.cp( file_copy_task.source_directory + file_copy_task.find_a_source_file, file_copy_task.destination_directory )
@tcocca
Copy link

tcocca commented May 3, 2012

Did you test it with the attr_reader / attr_accessor? Did you see the same speed results that I saw?

My guess is that attr_reader / attr_accessor are doing nothing but looking for instance variables with the same name as the method as opposed to define_method creating an actual method that is using a proc which is lazy loaded and is doing the exact same thing as attr_reader, just looking for / setting an ivar. If you end up investigating i'd love a more in depth answer (mine is just an assumption) but I agree, this is much clearer that the define_method and the massive speedup was a nice bonus!

@jgandt
Copy link
Author

jgandt commented May 9, 2012

I did test with attr_accessor. I found significant differences in execution time.

I have not yet jumped into Ruby core to discover the reason, but your explaination is reasonable.

My (very rudimentary) test rig is at https://github.com/jgandt/objectify_from_hash.

Thanks again for your input!

.jpg

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment