Created
June 26, 2019 05:55
-
-
Save EvgenyKungurov/2a3a44bc20b591e7adc38f86861f761a to your computer and use it in GitHub Desktop.
Use attributes with history and type class protection
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
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