module ActiveAttr::Attributes::ClassMethods

Public Instance Methods

attribute(name, options={}) click to toggle source

Defines an attribute

For each attribute that is defined, a getter and setter will be added as an instance method to the model. An {AttributeDefinition} instance will be added to result of the attributes class method.

@example Define an attribute.

attribute :name

@param (see AttributeDefinition#initialize)

@raise [DangerousAttributeError] if the attribute name conflicts with

existing methods

@return [AttributeDefinition] Attribute's definition

@since 0.2.0

# File lib/active_attr/attributes.rb, line 228
def attribute(name, options={})
  if dangerous_attribute_method_name = dangerous_attribute?(name)
    raise DangerousAttributeError, %{an attribute method named "#{dangerous_attribute_method_name}" would conflict with an existing method}
  else
    attribute! name, options
  end
end
attribute!(name, options={}) click to toggle source

Defines an attribute without checking for conflicts

Allows you to define an attribute whose methods will conflict with an existing method. For example, Ruby's Timeout library adds a timeout method to Object. Attempting to define a timeout attribute using .attribute will raise a {DangerousAttributeError}, but .attribute! will not.

@example Define a dangerous attribute.

attribute! :timeout

@param (see AttributeDefinition#initialize)

@return [AttributeDefinition] Attribute's definition

@since 0.6.0

# File lib/active_attr/attributes.rb, line 252
def attribute!(name, options={})
  AttributeDefinition.new(name, options).tap do |attribute_definition|
    attribute_name = attribute_definition.name.to_s
    # Force active model to generate attribute methods
    remove_instance_variable("@attribute_methods_generated") if instance_variable_defined?("@attribute_methods_generated")
    define_attribute_methods([attribute_definition.name]) unless attribute_names.include? attribute_name
    remove_instance_variable("@attribute_names") if instance_variable_defined?("@attribute_names")
    attributes[attribute_name] = attribute_definition
  end
end
attribute_names() click to toggle source

Returns an Array of attribute names as Strings

@example Get attribute names

Person.attribute_names

@return [Array<String>] The attribute names

@since 0.5.0

# File lib/active_attr/attributes.rb, line 271
def attribute_names
  @attribute_names ||= attributes.keys
end
attributes() click to toggle source

Returns a Hash of AttributeDefinition instances

@example Get attribute definitions

Person.attributes

@return [ActiveSupport::HashWithIndifferentAccess{String => ActiveAttr::AttributeDefinition}]

The Hash of AttributeDefinition instances

@since 0.2.0

# File lib/active_attr/attributes.rb, line 284
def attributes
  @attributes ||= ActiveSupport::HashWithIndifferentAccess.new
end
dangerous_attribute?(name) click to toggle source

Determine if a given attribute name is dangerous

Some attribute names can cause conflicts with existing methods on an object. For example, an attribute named “timeout” would conflict with the timeout method that Ruby's Timeout library mixes into Object.

@example Testing a harmless attribute

Person.dangerous_attribute? :name #=> false

@example Testing a dangerous attribute

Person.dangerous_attribute? :nil #=> "nil?"

@param name Attribute name

@return [false, String] False or the conflicting method name

@since 0.6.0

# File lib/active_attr/attributes.rb, line 306
def dangerous_attribute?(name)
  attribute_methods(name).detect do |method_name|
    allocate.respond_to?(method_name, true)
  end unless attribute_names.include? name.to_s
end
inspect() click to toggle source

Returns the class name plus its attribute names

@example Inspect the model's definition.

Person.inspect

@return [String] Human-readable presentation of the attributes

@since 0.2.0

# File lib/active_attr/attributes.rb, line 320
def inspect
  inspected_attributes = attribute_names.sort
  attributes_list = "(#{inspected_attributes.join(", ")})" unless inspected_attributes.empty?
  "#{name}#{attributes_list}"
end

Protected Instance Methods

attributes=(attributes) click to toggle source

Assign a set of attribute definitions, used when subclassing models

@param [Array<ActiveAttr::AttributeDefinition>] attributes The

Array of AttributeDefinition instances

@since 0.2.2

# File lib/active_attr/attributes.rb, line 334
def attributes=(attributes)
  @attributes = attributes
end
instance_method_already_implemented?(method_name) click to toggle source

Overrides ActiveModel::AttributeMethods to backport 3.2 fix

# File lib/active_attr/attributes.rb, line 339
def instance_method_already_implemented?(method_name)
  generated_attribute_methods.method_defined?(method_name)
end

Private Instance Methods

attribute_methods(name) click to toggle source

Expand an attribute name into its generated methods names

@since 0.6.0

# File lib/active_attr/attributes.rb, line 348
def attribute_methods(name)
  attribute_method_matchers.map { |matcher| matcher.method_name name }
end
inherited(subclass) click to toggle source

Ruby inherited hook to assign superclass attributes to subclasses

@since 0.2.2

Calls superclass method
# File lib/active_attr/attributes.rb, line 355
def inherited(subclass)
  super
  subclass.attributes = attributes.dup
end