Skip to content

Instantly share code, notes, and snippets.

@estum
Created December 3, 2014 20:23
Show Gist options
  • Save estum/ca391a784efbc68ccb40 to your computer and use it in GitHub Desktop.
Save estum/ca391a784efbc68ccb40 to your computer and use it in GitHub Desktop.
Ruby's Struct subclass with splats support
#= SplatStruct
# `Struct` subclass with splats support
#
# SampleClass = SplatStruct.new(:a, :b, [:c]) do |klass|
# def avgc
# Rational(c.inject(:+), c.length).to_f
# end
# end
#
# object = SampleClass.new(1,2,3,4,5)
# # => { :a => 1, :b => 2, :c => [3, 4, 5] }
class SplatStruct < Struct
class << self
def new(*member_names, &block)
splat_members = {}
sstruct_name = member_names[0] if member_names.is_a?(Symbol)
member_names.each.with_index do |member, index|
next unless member.is_a? Array
splat_members[member.first] = index - (sstruct_name.nil? ? 0 : 1)
member_names[index] = member.first
end
sstruct = super *member_names, &block
sstruct.instance_variable_set :@_splat_members, splat_members
sstruct
end
end
def self.splat_members
instance_variable_get :@_splat_members
end
def initialize(*args)
self.class.splat_members.values.each {|index| args << args.slice!(index..-1) }
super *args
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment