Module: OrderAlready

Defined in:
lib/order_already.rb,
lib/order_already/version.rb

Overview

In the spirit of Browse Everything and Questioning Authority, the Order Already module provides a simple interface for ordering properties that have an indeterminate persistence order (looking at you Fedora Commons and RDF N-Triples).

To do this, we take liberties with the persistence layer’s values (e.g. we prepend an index and delimiter to the given value). You may not feel comfortable with this solution, because you are munging your data’s

Defined Under Namespace

Modules: InputOrderSerializer Classes: Error

Constant Summary collapse

VERSION =
"0.3.2"

Class Method Summary collapse

Class Method Details

.for(*attributes, serializer: InputOrderSerializer) ⇒ Module

Note:

In testing, you need to use ‘prepend` instead of `include`; but that may be a function of my specs.

Returns a module that wraps the attr_accessor methods for the given :attributes. In using a module, we have access to ‘super`; which is super convenient! The module will also add a `#attribute_is_ordered_already?` method.

Examples:

class MyRecord
  attr_reader :creators
  def creators=(values)
    # We're going to "persist" these in an "arbitrarily different" way than what the user
    # provided.
    @creators = Array(values).reverse
  end
  prepend OrderAlready.for(:creators)
end

class OtherRecord
  attr_accessor :subjects
  # Assumes there's an Alphabetizer constant that responds to .serialize and .deserialize
  prepend OrderAlready.for(:subjects, serializer: Alphabetizer)
end

Parameters:

  • attributes (Array<Symbol>)

    the name of the attributes/properties you want to order.

  • serializer (#serialize, #deserialize) (defaults to: InputOrderSerializer)

    the service class responsible for serializing the data. Want to auto-alphabetize? Use a different serializer than the default.

Returns:

  • (Module)

    a module that wraps the attr_accessor methods for the given :attributes. In using a module, we have access to ‘super`; which is super convenient! The module will also add a `#attribute_is_ordered_already?` method.



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/order_already.rb', line 45

def self.for(*attributes, serializer: InputOrderSerializer)
  # Capturing the named attributes to create a local binding; this helps ensure we have that
  # available in the later :attribute_is_ordered_already? method definition.
  ordered_attributes = attributes.map(&:to_sym)

  # By creating a module, we have access to `super`.
  Module.new do
    ordered_attributes.each do |attribute|
      define_method(attribute) do
        serializer.deserialize(super())
      end

      define_method("#{attribute}=") do |values|
        super(serializer.serialize(values))
      end
    end

    define_method(:attribute_is_ordered_already?) do |attribute|
      ordered_attributes.include?(attribute.to_sym)
    end

    define_method(:already_ordered_attributes) do
      ordered_attributes
    end
  end
end