Skip to content

Instantly share code, notes, and snippets.

@ahoward
Created May 1, 2014 18:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ahoward/f82215d6f593375931fe to your computer and use it in GitHub Desktop.
Save ahoward/f82215d6f593375931fe to your computer and use it in GitHub Desktop.
module SafeAttr
def SafeAttr.included(other)
other.send(:extend, SafeAttr::ClassMethods)
super
end
module ClassMethods
def code_for(name, options = {})
code = []
unless options[:read] == false
code.push(<<-__
def #{ name }
(class << self; self; end).instance_variable_get("@#{ name }")
end
__
)
end
unless options[:write] == false
code.push(<<-__
def #{ name }=(value)
(class << self; self; end).instance_variable_set("@#{ name }", value)
end
__
)
end
code.join("\n\n")
end
def sattr_reader(*names)
names.flatten.compact.map{|name| module_eval(code_for(name, :write => false))}
end
def sattr_writer(*names)
names.flatten.compact.map{|name| module_eval(code_for(name, :read => false))}
end
def sattr_accessor(*names)
names.flatten.compact.map{|name| module_eval(code_for(name))}
end
alias_method :sattr, :sattr_accessor
end
end
class Doc
include SafeAttr
attr_accessor :a
sattr :b
end
doc = Doc.new
doc.a = 40
doc.b = 2
p doc #=> #<Doc:0x007fc1da8b94f0 @a=40>
p doc.instance_variables #=> [:@a]
p(doc.a + doc.b) #=> 42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment