module ActiveFedora::Attributes

def [](key)

def [](key)
  if assoc = self.association(key.to_sym)
    # This is for id attributes stored in the rdf graph.
    assoc.reader
  elsif self.class.properties.key?(key.to_s)
    # Use the generated method so that single value assetions are single
    self.send(key)
  else
    # The attribute is a delegate to a datastream
    array_reader(key)
  end
end

def []=(key, value)

def []=(key, value)
  raise ReadOnlyRecord if readonly?
  if assoc = self.association(key.to_sym)
    # This is for id attributes stored in the rdf graph.
    assoc.replace(value)
  elsif self.class.properties.key?(key.to_s)
    # The attribute is stored in the RDF graph for this object
    self.send(key.to_s+"=", value)
  else
    # The attribute is a delegate to a datastream
    array_setter(key, value)
  end
end

def array_reader(field, *args)

def array_reader(field, *args)
  raise UnknownAttributeError, "#{self.class} does not have an attribute `#{field}'" unless self.class.delegated_attributes.key?(field)
  val = self.class.delegated_attributes[field].reader(self, *args)
  self.class.multiple?(field) ? val : val.first
end

def array_setter(field, args)

def array_setter(field, args)
  raise UnknownAttributeError, "#{self.class} does not have an attribute `#{field}'" unless self.class.delegated_attributes.key?(field)
  if self.class.multiple?(field)
    if args.present? && !args.respond_to?(:each)
      raise ArgumentError, "You attempted to set the attribute `#{field}' on `#{self.class}' to a scalar value. However, this attribute is declared as being multivalued."
    end
  elsif args.respond_to?(:each) # singular
    raise ArgumentError, "You attempted to set the attribute `#{field}' on `#{self.class}' to an enumerable value. However, this attribute is declared as being singular."
  end
  self.class.delegated_attributes[field].writer(self, args)
end

def attribute_method?(attr_name) #:nodoc:

:nodoc:
causes a load of all the datastreams.
the callback methods seem to trigger this, which means just initing an object (after_init)
override activemodel so it doesn't trigger a load of all the attributes.
def attribute_method?(attr_name) #:nodoc:
  respond_to_without_attributes?(:attributes) && self.class.delegated_attributes.include?(attr_name)
end

def attribute_names

def attribute_names
  self.class.attribute_names
end

def attributes

def attributes
  attribute_names.each_with_object({"id" => id}) {|key, hash| hash[key] = self[key] }
end

def attributes=(properties)

def attributes=(properties)
  sanitize_for_mass_assignment(properties).each do |k, v|
    respond_to?(:"#{k}=") ? send(:"#{k}=", v) : raise(UnknownAttributeError, "#{self.class} does not have an attribute `#{k}'")
  end
end

def clear_changed_attributes

def clear_changed_attributes
  @previously_changed = changes
  @changed_attributes.clear
end

def inspect

Calling inspect may trigger a bunch of datastream loads, but it's mainly for debugging, so no worries.
def inspect
  values = ["id: #{id.inspect}"]
  values << self.class.attribute_names.map { |attr| "#{attr}: #{self[attr].inspect}" }
  "#<#{self.class} #{values.flatten.join(', ')}>"
end

def local_attributes

def local_attributes
  self.class.local_attributes
end

def mark_as_changed(field)

def mark_as_changed(field)
  self.send("#{field}_will_change!")
end

def value_has_changed?(field, new_value)

Returns:
  • (Boolean) - true if there is an reader method and it returns a
def value_has_changed?(field, new_value)
  new_value != array_reader(field)
end