class VagrantCloud::Data::Immutable

Immutable data class. This class adds extra functionality to the Data class like providing attribute methods which can be defined using the ‘attr_required` and `attr_optional` methods. Once an instance is created the data is immutable. For example:

class MyData < Immutable

attr_required :name
attr_optional :version

end

When creating a new instance, a name parameter must be provided, but a version parameter is optional, so both are valid:

instance = MyData.new(name: “testing”, version: “new-version”)

and

instance = MyData.new(name: “testing”)

but only providing the version is invalid:

instance = MyData.new(version: “new-version”) # -> Exception

Public Class Methods

attr_optional(*args) click to toggle source

Define attributes which are optional

# File lib/vagrant_cloud/data.rb, line 100
def self.attr_optional(*args)
  return @optional || [] if args.empty?
  sync do
    @optional ||= []
    if !args.empty?
      # Create any accessor method which do not yet exist
      args = args.map(&:to_sym) - @optional
      args.each do |argument_name|
        if !method_defined?(argument_name)
          define_method(argument_name) {
            send(:[], argument_name.to_sym)
          }
        end
      end
      @optional += args
    end
    @optional
  end
end
attr_required(*args) click to toggle source

Define attributes which are required

# File lib/vagrant_cloud/data.rb, line 79
def self.attr_required(*args)
  return @required || [] if args.empty?
  sync do
    @required ||= []
    if !args.empty?
      # Create any accessor methods which do not yet exist
      args = args.map(&:to_sym) - @required
      args.each do |argument_name|
        if !method_defined?(argument_name)
          define_method(argument_name) {
            send(:[], argument_name.to_sym)
          }
        end
      end
      @required += args
    end
    @required
  end
end
inherited(klass) click to toggle source

If inherited, set attribute information

# File lib/vagrant_cloud/data.rb, line 121
def self.inherited(klass)
  klass.attr_required(*attr_required)
  klass.attr_optional(*attr_optional)
  klass.class_variable_set(:@@lock, Mutex.new)
end
new(**opts) click to toggle source

Create a new instance

@return [Immutable]

Calls superclass method VagrantCloud::Data::new
# File lib/vagrant_cloud/data.rb, line 137
def initialize(**opts)
  super()
  self.class.attr_required.each do |attr|
    if !opts.key?(attr)
      raise ArgumentError, "Missing required parameter `#{attr}`"
    end
    data[attr.to_sym] = opts[attr].dup
  end
  self.class.attr_optional.each do |attr|
    if opts.key?(attr)
      data[attr.to_sym] = opts[attr].dup
    end
  end
  extras = opts.keys - (self.class.attr_required + self.class.attr_optional)
  if !extras.empty?
    raise ArgumentError, "Unknown parameters provided: #{extras.join(",")}"
  end
  freezer(@data)
end
sync() { || ... } click to toggle source

Synchronize action

# File lib/vagrant_cloud/data.rb, line 128
def self.sync
  @@lock.synchronize do
    yield
  end
end

Public Instance Methods

inspect() click to toggle source

@return [String]

# File lib/vagrant_cloud/data.rb, line 158
def inspect
  vars = (self.class.attr_required + self.class.attr_optional).map do |k|
    val = self.send(:[], k)
    next if val.nil? || val.to_s.empty?
    "#{k}=#{val.inspect}"
  end.compact.join(", ")
  "<#{self.class.name}:#{sprintf("%#x", object_id)} #{vars}>"
end

Protected Instance Methods

freezer(obj) click to toggle source

Freeze the given object and all nested objects that can be found

@return [Object]

# File lib/vagrant_cloud/data.rb, line 173
def freezer(obj)
  if obj.is_a?(Enumerable)
    obj.each do |item|
      freezer(item)
      item.freeze
    end
  end
  obj.freeze
end