Class: MSFL::Datasets::Base

Inherits:
Object
  • Object
show all
Includes:
Validators::Definitions::HashKey
Defined in:
lib/msfl/datasets/base.rb

Direct Known Subclasses

Animal, Car, Movie, Person

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Validators::Definitions::HashKey

#all_logical_operators?, #all_operators?, #any_operators?, #binary_operators, #foreign_operators, #hash_key_operators, #logical_operators, #operator?, #partial_operators, #valid_hash_key?, #valid_hash_keys

Class Method Details

.dataset_from(dataset_name) ⇒ MSFL::Datasets::Base, Nil

Returns a new instance of the specified dataset.

Parameters:

  • dataset_name (Symbol)

    the name of the dataset to instantiate

Returns:

  • (MSFL::Datasets::Base, Nil)

    a new instance of the specified dataset, if it can be found, otherwise nil



49
50
51
52
53
# File 'lib/msfl/datasets/base.rb', line 49

def self.dataset_from(dataset_name)
  klass = MSFL::Datasets::Base.registered_datasets[dataset_name]
  dataset = klass.new if klass
  dataset ||= nil
end

.register_dataset(dataset = nil, opts = {}) ⇒ Object

TODO:

add tests

Register a MSFL::Dataset as a registered dataset so that other code can reference the dataset using its name as a symbol, instead of having to pass around the class name.

If no arguments are provided it registers the current class and sets its name to the class name downcased The dataset being registered can be overridden. The dataset name (how one refers to the dataset as a symbol)

can also be overridden.

@meta-spinach

Parameters:

  • dataset (Class) (defaults to: nil)

    optionally specify a dataset to register (use this when registration occurs outside of a dataset’s class scope)

  • opts (Hash) (defaults to: {})

    options notable option: :name (it allows you to override the dataset name)



33
34
35
36
37
38
39
40
41
42
# File 'lib/msfl/datasets/base.rb', line 33

def self.register_dataset(dataset = nil, opts = {})
  dataset ||= self
  dataset_name = opts[:name] if opts.has_key?(:name)
  dataset_name ||= dataset.name
  dataset_name.slice! "MSFL::Datasets::"
  dataset_name.downcase!
  registered_datasets = MSFL::Datasets::Base.registered_datasets
  registered_datasets[dataset_name.to_sym] = dataset
  MSFL::Datasets::Base.registered_datasets = registered_datasets
end

.registered_datasetsObject



10
11
12
# File 'lib/msfl/datasets/base.rb', line 10

def registered_datasets
  @registered_datasets ||= {}
end

.registered_datasets=(registered_datasets) ⇒ Object



14
15
16
# File 'lib/msfl/datasets/base.rb', line 14

def registered_datasets=(registered_datasets)
  @registered_datasets = registered_datasets
end

Instance Method Details

#fieldsArray<Symbol>

The descendant class MUST override this method otherwise all field validations will fail

The method defines an array of symbols, indicating what fields are supported for the Dataset

Returns:

  • (Array<Symbol>)

    the fields in the dataset

Raises:

  • (NoMethodError)


60
61
62
# File 'lib/msfl/datasets/base.rb', line 60

def fields
  raise NoMethodError, "Descendants of MSFL::Datasets::Base are required to implement the #fields method"
end

#foreignsObject

The descendant class SHOULD override this method, in future versions of MSFL it is execpted to become a MUST for descendants to override.

The method defines an array of symbols, indicating the names of foreign datasets that this data set supports filtering on

Example a Person might have a foreign of :location where the Location dataset should be loaded and used for evaluating filters inside of the foreign (this prevents having to duplicate expression semantics across many datasets - the Location semantics are defined only in the Location dataset and loaded in when needed by other datasets)



90
91
92
# File 'lib/msfl/datasets/base.rb', line 90

def foreigns
  []
end

#has_field?(field_name) ⇒ Bool

Returns true if the specified field is valid directly or through a foreign dataset

Parameters:

  • field_name (Symbol)

    the name of the field to check and see if the dataset supports it

Returns:

  • (Bool)

    true if the field is supported by the dataset



68
69
70
71
72
73
74
75
76
77
# File 'lib/msfl/datasets/base.rb', line 68

def has_field?(field_name)
  direct_fields = self.fields
  foreigns.each do |f|
    foreign_dataset = self.class.dataset_from f
    if foreign_dataset
      direct_fields.concat foreign_dataset.fields
    end
  end
  direct_fields.include? field_name
end

#has_operator?(operator) ⇒ Bool

If the dataset supports the operator this method returns true

Parameters:

  • operator (Symbol)

    the operator to check if the dataset supports it

Returns:

  • (Bool)

    true if the dataset supports the operator



107
108
109
110
111
112
113
114
115
116
# File 'lib/msfl/datasets/base.rb', line 107

def has_operator?(operator)
  ops = operators
  foreigns.each do |f|
    foreign_dataset = self.class.dataset_from f
    if foreign_dataset
      ops.concat foreign_dataset.operators
    end
  end
  ops.include? operator
end

#operator_conforms?(operator, field) ⇒ Bool

Method not implemented at this time

This method returns true if the operator is supported for the specified field by the dataset. While this is not currently implemented, the intent is that a hash of fields (as keys) would map to Arrays<Symbol> (as values) and then this method would validate that the operator argument meets this contract.

Parameters:

  • operator (Symbol)

    the operator that needs to be checked for conformity

  • field (Symbol)

    which field should the operator be checked against

Returns:

  • (Bool)

    true if the operator conforms, false otherwise



167
168
169
# File 'lib/msfl/datasets/base.rb', line 167

def operator_conforms?(operator, field)
  true
end

#operatorsArray<Symbol>

The descendant class may override this method to control the operators that are supported for the dataset

- Note that this can only be used to reduce the number of supported operators (you can't add new operators
  here, without first adding them to MSFL::Validators::Definitions::HashKey#hash_key_operators)

Returns:

  • (Array<Symbol>)

    the operators supported in the dataset



99
100
101
# File 'lib/msfl/datasets/base.rb', line 99

def operators
  hash_key_operators
end

#type_conforms?(obj, field) ⇒ Boolean

Method not implemented at this time Returns true if the object conforms to the types supported by the indicated field While not currently implemented the intent is that the descendant Dataset would specify a hash of supported types for each field and this method would then cross reference that list.

Parameters:

  • obj (Object)

    the object that should be type checked based on the field argument

  • field (Symbol)

    which field should the object be checked for conformity

Returns:

  • (Boolean)


142
143
144
# File 'lib/msfl/datasets/base.rb', line 142

def type_conforms?(obj, field)
  true
end

#validate_operator_conforms(operator, field, errors) ⇒ Array

This method returns the errors argument. The errors argument is unchanged if operator conformity validation passes, otherwise an error is added to errors.

Parameters:

  • operator (Symbol)

    the operator that we want to know if the particular field supports it

  • field (Symbol)

    which field should the operator be checked for conformity

  • errors (Array)

    an array of validation errors - empty indicates that no errors have been encountered

Returns:

  • (Array)

    errors merged with any validation errors encountered in validating the set



153
154
155
156
# File 'lib/msfl/datasets/base.rb', line 153

def validate_operator_conforms(operator, field, errors)
  errors << "Dataset operator conformity validation failed for operator: #{operator} against field: #{field}" unless operator_conforms?(operator, field)
  errors
end

#validate_type_conforms(obj, field, errors) ⇒ Array

This method returns the errors argument. The errors argument is unchanged if type conformity validation passes, otherwise an error is added to errors.

@example:

foo.investors_validate_type_conforms("abc", :total_funding) => # there is one more error in errors
  # because the type of total_funding must be an integer

Parameters:

  • obj (Object)

    the object that should be type checked based on the field argument

  • field (Symbol)

    which field should the object be checked for conformity

  • errors (Array)

    an array of validation errors - empty indicates that no errors have been encountered

Returns:

  • (Array)

    errors merged with any validation errors encountered in validating the set



130
131
132
133
# File 'lib/msfl/datasets/base.rb', line 130

def validate_type_conforms(obj, field, errors)
  errors << "Dataset type conformity validation failed for obj: #{obj} against field: #{field}" unless type_conforms?(obj, field)
  errors
end

#validate_value_conforms(value, field, errors) ⇒ Array

This method returns the errors argument. The errors argument is unchanged if value conformity validation passes, otherwise an error is added to errors.

@example:

foo.investors_value_conforms(-6000, :total_funding) => # there is one more error in errors
  # because the funding cannot be negative

@example:

foo.investors_value_conforms(12345, :total_funding) => # errors is unchanged

Parameters:

  • value (Object)

    the precoerced value (the value must be correctly typed) that should be checked for validity based on the field, if the value does not conform an exception will be raised

  • field (Symbol)

    which field should the value be checked for conformity

  • errors (Array)

    an array of validation errors - empty indicates that no errors have been encountered

Returns:

  • (Array)

    errors merged with any validation errors encountered in validating the set



189
190
191
192
# File 'lib/msfl/datasets/base.rb', line 189

def validate_value_conforms(value, field, errors)
  errors << "Dataset value conformity validation failed for value: #{value} against field: #{field}" unless value_conforms?(value, field, errors)
  errors
end

#value_conforms?(value, field, errors = []) ⇒ Bool

Method not implemented at this time

This method returns true if the value is supported for the specified field by the dataset. While this is not currently implemented, the intent is that a hash of fields (as keys) would map to an Array of validation constraints. These constraints would then be executed against the value and if all are successful the value would be considered to have passed.

It is likely that the methods invoked from the Array of validation constraints would actually return an Array of errors encountered, this method would then concat that Array into the errors array. If the encountered errors array is empty the method would return true, and false otherwise.

Parameters:

  • value (Object)

    the object to on which to perform validation

  • field (Symbol)

    the field the object should be validated against

  • errors (Array) (defaults to: [])

    the array of errors from prior validations

Returns:

  • (Bool)

    true if no new errors are encountered, false otherwise



209
210
211
# File 'lib/msfl/datasets/base.rb', line 209

def value_conforms?(value, field, errors = [])
  true
end