Method: Templatable#templatable_attr
- Defined in:
- lib/classy/templatable.rb
#templatable_attr(*symbols) ⇒ Object
Defines one or more templatable attrs, which will add instance methods similar to Ruby’s standard attr_accessor method, and will also add class methods to set or get default values, as described above.
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/classy/templatable.rb', line 51 def templatable_attr (*symbols) symbols.each do |symbol| # define the instance setter method # define_method("#{symbol}=".to_sym) do |value| instance_variable_set("@#{symbol}", value) @@ever_been_set[self][symbol] = true end # define the instance getter method # define_method(symbol) do if @@ever_been_set[self][symbol] return instance_variable_get("@#{symbol}") elsif self.class.class_variable_defined?("@@#{symbol}") return self.class.class_exec { class_variable_get("@@#{symbol}") } else return nil end end class_exec do # define the class setter method # # We have to use this send hack, since define_method is private. # self.class.send(:define_method, "#{symbol}=".to_sym) do |value| class_variable_set("@@#{symbol}", value) end # define the class getter/setter method # # We want to be able to call this like a dsl as a setter, or like a # class method as a getter, so we need variable arity, which # define_method doesn't support. In order to use the standard `def` # with variable arity, eval'ing a string seems to be the only option. # # Oh man would I love for somebody to submit a patch to do this in a # less horrible way. # self.class.class_eval " def #{symbol} (value = nil) if value class_variable_set(\"@@#{symbol}\", value) end class_variable_get(\"@@#{symbol}\") if class_variable_defined?(\"@@#{symbol}\") end " end end end |