Method: Class#cattr_writer

Defined in:
motion/core_ext/class/attribute_accessors.rb

#cattr_writer(*syms) ⇒ Object

Defines a class attribute if it’s not defined and creates a writer method to allow assignment to the attribute.

class Person
  cattr_writer :hair_colors
end

Person.hair_colors = [:brown, :black]
Person.class_variable_get("@@hair_colors") # => [:brown, :black]
Person.new.hair_colors = [:blonde, :red]
Person.class_variable_get("@@hair_colors") # => [:blonde, :red]

The attribute name must be a valid method name in Ruby.

class Person
  cattr_writer :"1_Badname "
end
# => NameError: invalid attribute name

If you want to opt out the instance writer method, pass instance_writer: false or instance_accessor: false.

class Person
  cattr_writer :hair_colors, instance_writer: false
end

Person.new.hair_colors = [:blonde, :red] # => NoMethodError

Also, you can pass a block to set up the attribute with a default value.

class Person
  cattr_writer :hair_colors do
    [:brown, :black, :blonde, :red]
  end
end

Person.class_variable_get("@@hair_colors") # => [:brown, :black, :blonde, :red]


91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'motion/core_ext/class/attribute_accessors.rb', line 91

def cattr_writer(*syms)
  options = syms.extract_options!
  syms.each do |sym|
    raise NameError.new('invalid attribute name') unless sym =~ /^[_A-Za-z]\w*$/
    class_exec do
      unless class_variable_defined?("@@#{sym}")
        class_variable_set("@@#{sym}", nil)
      end

      define_singleton_method "#{sym}=" do |obj|
        class_variable_set("@@#{sym}", obj)
      end
    end

    unless options[:instance_writer] == false || options[:instance_accessor] == false
      class_exec do
        define_method "#{sym}=" do |obj|
          self.class.class_variable_set("@@#{sym}", obj)
        end
      end
    end
    send("#{sym}=", yield) if block_given?
  end
end