RailsのActiveRecord(実際はActiveModel)を使うとattr_accessor
で定義したアクセサとアサインされた値のキーバリューを#attributes
メソッドで取得できる。
RailsやActiveModelが無い環境の素のクラスでも#attributes
メソッドを使いたいので、やってみた結果。黒魔術。
module Hoge
module Concerns
# Add feature of #attributes, #attributes=, and .attributes to super class by orverriding Module.attr_accessor.
# ref. http://techblog.clara.jp/2014/09/ruby_attr_accessor/
module Attributes
def self.included(base)
base.extend(ClassMethods)
end
def attributes
self.class.attributes.map {|k| [k, self.instance_variable_get("@#{k}")] }.to_h
end
def to_h
self.class.attributes.select{|k| self.instance_variable_defined?("@#{k}") }.map {|k| [k, self.instance_variable_get("@#{k}")] }.to_h
end
def attributes=(attrs)
attrs.each do |k, v|
assign_attribute(k, v)
end
end
private
def assign_attribute(k, v)
if respond_to?("#{k}=")
public_send("#{k}=", v)
else
raise UnknownAttributeError, "attribute `#{k}` can not be assinged to #{self}"
end
end
public
module ClassMethods
def attributes
@attributes ||=
self.superclass.instance_variable_get("@attributes").try(:dup) || Set.new
end
private
def attr_accessor(*args)
self.attributes.merge args
super
end
end
end
end
end