Skip to content

Instantly share code, notes, and snippets.

@rummelonp
Created July 3, 2013 12:02
Show Gist options
  • Save rummelonp/5917339 to your computer and use it in GitHub Desktop.
Save rummelonp/5917339 to your computer and use it in GitHub Desktop.
Ruby で型チェック的な
# -*- coding: utf-8 -*-
require 'active_support/core_ext'
module TypeValidator
extend ActiveSupport::Concern
included do
def self.method_added(method_name)
if @last_types
types = @last_types
@last_types = nil
define_type_validator(method_name, *types)
end
end
def self.type(*types)
if types.first.is_a?(Symbol)
method_name = types.shift
define_type_validator(method_name, *types)
else
@last_types = types
end
end
private
def self.define_type_validator(method_name, *types)
without_method_name = "#{method_name}_without_type_validator"
with_method_name = "#{method_name}_with_type_validator"
define_method(with_method_name) do |*args|
types.each.with_index do |type, index|
unless type === args[index]
e = TypeError.new "#{(index + 1).ordinalize} argument type of `#{method_name}` must be a #{type}"
raise e rescue nil
e.set_backtrace(e.backtrace.slice(5, e.backtrace.size))
raise e
end
end
send(without_method_name, *args)
end
alias_method without_method_name, method_name
alias_method method_name, with_method_name
end
end
end
class Nyan
include TypeValidator
type String
def string(str) str end
type Integer
def integer(int) int end
def hash(hash) hash end
type :hash, Hash
end
def safe_puts(&block)
puts yield
rescue => e
puts "#{e.message}: #{e.backtrace.first}"
end
nyan = Nyan.new
safe_puts { nyan.string "str" }
safe_puts { nyan.string 1 }
safe_puts { nyan.integer 1 }
safe_puts { nyan.integer "str" }
safe_puts { nyan.hash({}) }
safe_puts { nyan.hash([]) }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment