Module: ApiResource::Attributes::ClassMethods

Defined in:
lib/api_resource/attributes.rb

Instance Method Summary collapse

Instance Method Details

#attribute?(name) ⇒ Boolean

Returns true if the provided name is an attribute of this class

Parameters:

  • name (Symbol)

    The name of the potential attribute

Returns:

  • (Boolean)

    True if an attribute with the given name exists



226
227
228
# File 'lib/api_resource/attributes.rb', line 226

def attribute?(name)
  self.attribute_names.include?(name.to_sym)
end

#clear_attributesBoolean

Removes all attributes from this class but does NOT undefine their methods

Returns:

  • (Boolean)

    Always true



253
254
255
256
257
258
259
# File 'lib/api_resource/attributes.rb', line 253

def clear_attributes
  self.attribute_names.clear
  self.public_attribute_names.clear
  self.protected_attribute_names.clear

  true
end

#define_all_attributesBoolean

Wrapper method to define all of the attributes (public and protected) for this Class. This should be called with a locked mutex to prevent multiple threads from defining attributes at the same time

Returns:

  • (Boolean)

    true



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/api_resource/attributes.rb', line 88

def define_all_attributes
  if self.resource_definition["attributes"]
    # First we need to clear out the old values and clone them
    self.attribute_names = []
    self.public_attribute_names = []
    self.protected_attribute_names = []
    self.attribute_types = {}.with_indifferent_access
    # First define all public attributes
    define_attributes(
      *self.resource_definition['attributes']['public'],
      access_level: :public
    )
    # Then define all private attributes
    define_attributes(
      *self.resource_definition['attributes']['protected'],
      access_level: :protected
    )
  end
  true
end

#define_attribute_methods(attrs, access_level) ⇒ Boolean

Defines the attribute methods in a new module which is then included in this class. Meant to be called with a locked mutex

Parameters:

  • args (Array)

    List of attributes to define

  • access_level (Symbol)

    :protected or :public

Returns:

  • (Boolean)

    Always true



183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
# File 'lib/api_resource/attributes.rb', line 183

def define_attribute_methods(attrs, access_level)
  self.attribute_method_module.module_eval do
    attrs.each do |attr|
      # Normalize for attributes without types
      attr_name = Array.wrap(attr).first
      # Define reader and huh methods
      self.module_eval <<-EOE, __FILE__, __LINE__ + 1
        def #{attr_name}
          read_attribute(:#{attr_name})
        end

        def #{attr_name}?
          read_attribute(:#{attr_name}).present?
        end
      EOE
      # Define a writer if this is public
      if access_level == :public
        self.module_eval <<-EOE, __FILE__, __LINE__ + 1
          def #{attr_name}=(new_val)
            write_attribute(:#{attr_name}, new_val)
          end
        EOE
      end
    end
  end

  # Now we get all the attribute names as symbols
  # and define_attribute_methods for dirty tracking
  attrs = attrs.collect do |a|
    Array.wrap(a).first.to_sym
  end

  super(attrs)
  true
end

#define_attributes(*args) ⇒ Boolean

Sets up the attributes for this class, can be called multiple times to add more attributes. Again meant to be called with a locked mutex for thread safety

hash as a last parameter

Parameters:

  • *args (Array)

    List of attributes to define and optional

Returns:

  • (Boolean)

    Always true



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/api_resource/attributes.rb', line 118

def define_attributes(*args)
  options = args.extract_options!
  options[:access_level] ||= :public
  # Initialize each attribute
  args.each do |arg|
    self.initialize_attribute(
      Array.wrap(arg),
      options[:access_level]
    )
  end

  self.define_attribute_methods(
    args,
    options[:access_level]
  )
end

#initialize_attribute(attr, access_level) ⇒ Boolean

Adds the attribute into some internal data structures but does not define any methods for it

attribute name and optionally a type for that attribute the access level for this attribute

Parameters:

  • arg (Array)

    A 1 or 2 element array holding an

  • access_level (Symbol)

    Either :protected or :public based on

Returns:

  • (Boolean)

    Always true



145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/api_resource/attributes.rb', line 145

def initialize_attribute(attr, access_level)
  attr_name = attr[0].to_sym
  attr_type = (attr[1] || :unknown).to_sym

  # Look for the typecaster, raise an error if one is not found
  typecaster = self.typecasters[attr_type]
  if typecaster.nil?
    raise TypecasterNotFound, "#{attr_type} is an unknown type"
  end
  # Map the attribute name to the typecaster
  self.attribute_types[attr_name] = typecaster
  # Add the attribute to the proper list
  if access_level == :public
    if self.protected_attribute?(attr_name)
      raise ArgumentError, "Illegal change of attribute access level for #{attr_name}"
    end

    self.public_attribute_names << attr_name
  else
    if self.public_attribute?(attr_name)
      raise ArgumentError, "Illegal change of attribute access level for #{attr_name}"
    end

    self.protected_attribute_names << attr_name
  end
  self.attribute_names << attr_name
  true
end

#protected_attribute?(name) ⇒ Boolean

Returns true if the provided name is a protected attribute

Parameters:

  • name (Symbol)

    Name of the potential attribute

Returns:

  • (Boolean)

    True if a protected attribute with the given name exists



235
236
237
# File 'lib/api_resource/attributes.rb', line 235

def protected_attribute?(name)
  self.protected_attribute_names.include?(name.to_sym)
end

#public_attribute?(name) ⇒ Boolean

Returns true if the provided name is a public attribute

Parameters:

  • name (Symbol)

    Name of the potential attribute

Returns:

  • (Boolean)

    True if a public attribute with the given name exists



244
245
246
# File 'lib/api_resource/attributes.rb', line 244

def public_attribute?(name)
  self.public_attribute_names.include?(name.to_sym)
end