Class: CFA::BaseModel

Inherits:
Object
  • Object
show all
Defined in:
lib/cfa/base_model.rb

Overview

A base class for models. Represents a configuration file as an object with domain-specific attributes/methods. For persistent storage, use load and save, Non-responsibilities: actual storage and parsing (both delegated). There is no caching involved.

Class Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(parser, file_path, file_handler: nil) ⇒ BaseModel

Returns a new instance of BaseModel.

Parameters:

  • parser (.parse, .serialize, .empty)

    parser that can convert object to string and vice versa. It have to provide methods ‘string #serialize(object)`, `object #parse(string)` and `object #empty` For example see AugeasParser

  • file_path (String)

    expected path passed to file_handler

  • file_handler (.read, .write) (defaults to: nil)

    an object able to read/write a string. It has to provide methods ‘string read(string)` and `write(string, string)`. For an example see MemoryFile. If unspecified or nil, default_file_handler is asked.



23
24
25
26
27
28
29
# File 'lib/cfa/base_model.rb', line 23

def initialize(parser, file_path, file_handler: nil)
  @file_handler = file_handler || BaseModel.default_file_handler
  @parser = parser
  @file_path = file_path
  @loaded = false
  self.data = parser.empty
end

Class Attribute Details

.default_file_handlerObject

Gets default file handler used when nil passed as file_handler in constructor



82
83
84
# File 'lib/cfa/base_model.rb', line 82

def self.default_file_handler
  @default_file_handler ||= File
end

Class Method Details

.attributes(attrs) ⇒ Object

Generates accessors for trivial key-value attributes

Examples:

Usage

class FooModel < CFA::BaseModel
  attributes(
    server:        "server",
    read_timeout:  "ReadTimeout",
    write_timeout: "WriteTimeout"
  )
  ...
end

Parameters:

  • attrs (Hash{Symbol => String})

    mapping of methods to file keys



105
106
107
108
109
110
111
112
113
114
115
# File 'lib/cfa/base_model.rb', line 105

def self.attributes(attrs)
  attrs.each_pair do |method_name, key|
    define_method(method_name) do
      tree_value_plain(generic_get(key))
    end

    define_method(:"#{method_name.to_s}=") do |value|
      tree_value_change(key, value)
    end
  end
end

Instance Method Details

#generic_get(key, tree = data) ⇒ Object

Note:

prefer to use specialized methods of children

powerfull method that gets unformatted any value in config.



71
72
73
# File 'lib/cfa/base_model.rb', line 71

def generic_get(key, tree = data)
  tree[key]
end

#generic_set(key, value, tree = data) ⇒ Object

Note:

prefer to use specialized methods of children

powerfull method that sets any value in config. It try to be smart to at first modify existing value, then replace commented out code and if even that doesn’t work, then append it at the end



64
65
66
67
# File 'lib/cfa/base_model.rb', line 64

def generic_set(key, value, tree = data)
  modify(key, value, tree) || uncomment(key, value, tree) ||
    add_new(key, value, tree)
end

#loadvoid

This method returns an undefined value.

Reads a String using file_handler and parses it with parser, storing the result in data.

Raises:

  • a file_handler specific error. If file_path does not exist or permission is not sufficient it may raise an error depending on the used file handler.

  • a parser specific error. If the parsed String is malformed, then depending on the used parser it may raise an error.



54
55
56
57
58
# File 'lib/cfa/base_model.rb', line 54

def load
  @parser.file_name = @file_path if @parser.respond_to?(:file_name=)
  self.data = @parser.parse(@file_handler.read(@file_path))
  @loaded = true
end

#loaded?Boolean

Returns if configuration was already loaded

Returns:

  • (Boolean)


76
77
78
# File 'lib/cfa/base_model.rb', line 76

def loaded?
  @loaded
end

#save(changes_only: false) ⇒ void

This method returns an undefined value.

Serializes data using parser and writes the resulting String using file_handler.

Raises:

  • a file_handler specific error if file_path cannot be written e.g. due to missing permissions or living on a read only device.

  • a parser specific error. If data contain invalid values then parser may raise an error. A properly written BaseModel subclass should prevent that by preventing insertion of such values in the first place.



40
41
42
43
44
# File 'lib/cfa/base_model.rb', line 40

def save(changes_only: false)
  merge_changes if changes_only
  @parser.file_name = @file_path if @parser.respond_to?(:file_name=)
  @file_handler.write(@file_path, @parser.serialize(data))
end