Created
October 23, 2011 14:44
-
-
Save 7even/1307430 to your computer and use it in GitHub Desktop.
Struct instantiated with a hash
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Kernel.module_eval do | |
def HashStruct(*attributes) | |
Class.new do | |
# keeping keys array in class | |
@keys = attributes.map(&:to_sym) | |
class << self | |
attr_reader :keys | |
end | |
# passing keys to the child class if inherited | |
define_singleton_method :inherited do |child| | |
child.instance_variable_set :@keys, attributes.map(&:to_sym) | |
end | |
# accesors for all attributes | |
attr_accessor *attributes | |
# constructor that takes a hash of values | |
# absent keys are filled with nil values | |
# extra keys raise an ArgumentError | |
def initialize(hash) | |
# uncommenting this line allows to pass a hash with String keys to Klass.new | |
# but requires ActiveSupport::HashWithIndifferentAccess | |
# hash = hash.with_indifferent_access | |
self.class.keys.each do |attr_name| | |
var_name = "@#{attr_name}" | |
var_value = hash.delete(attr_name) | |
instance_variable_set(var_name, var_value) | |
end | |
raise ArgumentError, "Attributes #{hash.keys.inspect} unknown" unless hash.empty? | |
end | |
end | |
end | |
end | |
User = HashStruct(:name, :email) | |
puts "User class has keys: #{User.keys}" | |
u1 = User.new(name: 'Vasya', email: '[email protected]') | |
puts "name: '#{u1.name}', email: '#{u1.email}'" | |
u2 = User.new(name: 'ololo') | |
puts "name: '#{u2.name}', email: '#{u2.email}'" | |
begin | |
u3 = User.new(name: 'trololo', avatar: 'trollface.jpg') | |
rescue ArgumentError => e | |
puts "ArgumentError: '#{e}'" | |
end | |
class Book < HashStruct(:name, :author) | |
end | |
b1 = Book.new(name: 'The Lord of the Rings', author: 'JRRT') | |
puts "name: '#{b1.name}', author: '#{b1.author}'" | |
b2 = Book.new(author: 'Petya') | |
puts "name: '#{b2.name}', author: '#{b2.author}'" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment