Skip to content

Instantly share code, notes, and snippets.

@EvgenyKungurov
Created June 26, 2019 05:55
Show Gist options
  • Save EvgenyKungurov/2a3a44bc20b591e7adc38f86861f761a to your computer and use it in GitHub Desktop.
Save EvgenyKungurov/2a3a44bc20b591e7adc38f86861f761a to your computer and use it in GitHub Desktop.
Use attributes with history and type class protection
module Acessors
def self.included(klass_receiver)
klass_receiver.extend AttrAccessorWithHistory::ClassMethods
klass_receiver.extend StrongAttrAcessor::ClassMethods
klass_receiver.include AttrAccessorWithHistory::InstanceMethods
end
module AttrAccessorWithHistory
module ClassMethods
def attr_accessor_with_history(*args)
args.each do |arg|
attr_accessor_with_history_getter(arg)
create_history_method(arg)
attr_accessor_with_history_setter(arg)
end
end
private
def attr_accessor_with_history_getter(arg)
attr_reader arg
end
def attr_accessor_with_history_setter(arg)
define_method "#{arg}=" do |value|
instance_variable_set("@#{arg}", value)
add_to_history(arg, value)
end
end
def create_history_method(arg)
define_method "#{arg}_history" do
instance_variable_get("@#{arg}_history") ||
instance_variable_set("@#{arg}_history", [])
end
end
end
module InstanceMethods
private
def add_to_history(arg, value)
history = send("#{arg}_history")
history.push(value) unless history.last == value
end
end
end
module StrongAttrAcessor
module ClassMethods
def strong_attr_acessor(hash)
hash.each_pair do |key, value|
strong_attr_acessor_getter(key)
strong_attr_acessor_setter(key, value)
end
end
def strong_attr_acessor_getter(arg)
attr_reader arg
end
def strong_attr_acessor_setter(key, kind_of)
raise "Attribute '#{key}' must be kind of #{kind_of}" unless key.is_a? kind_of
define_method "#{key}=" do |value|
instance_variable_set("@#{arg}", value)
end
end
end
end
end
class Test
include Acessors
attr_accessor_with_history :one
strong_attr_acessor two: String
end
test = Test.new
test.one = 'Goga'
test.one = 'Zora'
puts test.one_history
test.two = 'Hello'
test.two = :hello
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment