Last active
December 15, 2015 07:09
-
-
Save brianknapp/5221420 to your computer and use it in GitHub Desktop.
Obvious immutable entity with validation
This file contains hidden or 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
module Obvious | |
module EntityMixin | |
class << self | |
def included(base) | |
base.extend ClassMethods | |
end | |
end | |
module ClassMethods | |
attr_reader :shape | |
attr_reader :validations | |
def value name, type | |
name = name.to_sym | |
@shape ||= {} | |
@shape[name] = type | |
define_method(name) { @values[name] } | |
end | |
def validation name, method | |
name = "#{name}_validation".to_sym | |
@validations ||= [] | |
@validations << name | |
define_method(name) { instance_exec &method } | |
end | |
end | |
end | |
class Entity | |
include EntityMixin | |
def initialize input | |
shape = self.class.shape | |
validations = self.class.validations || [] | |
@values = {} | |
input.each do |k, v| | |
unless shape[k] | |
raise StandardError.new "Invalid input field: #{k}" | |
else | |
@values[k] = v | |
end | |
end | |
freeze | |
shape.each do |k, v| | |
unless @values[k].class == v | |
msg = "Validation Error: Invalid value for #{k}, should be a #{v}" | |
raise StandardError.new msg | |
end | |
end | |
validations.each { |method| send method } | |
end | |
def to_hash | |
hash = {} | |
@values.each do |k, v| | |
hash[k] = v | |
end | |
hash | |
end | |
end | |
end | |
class Thing < Obvious::Entity | |
value :foo, String | |
value :test, Fixnum | |
validation :something, Proc.new { | |
if foo != "hello world" | |
msg = "Validation Error: Invalid value for foo, should be 'hello world'" | |
raise StandardError.new msg | |
end | |
} | |
end | |
class Thing2 < Obvious::Entity | |
value :something, String | |
value :else, TrueClass | |
end | |
describe Thing do | |
it 'should be a thing' do | |
thing = Thing.new foo: 'hello world', test: 1 | |
puts thing.inspect | |
puts Thing.shape | |
puts thing.foo | |
puts thing.test | |
puts thing.to_hash | |
thing2 = Thing2.new something: 'funny', else: true | |
puts thing2.inspect | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment