Class: TableSchema::Schema

Inherits:
Hash
  • Object
show all
Includes:
Helpers
Defined in:
lib/tableschema/schema.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Helpers

#deep_symbolize_keys, #get_class_for_type, #read_file, #type_class_lookup

Constructor Details

#initialize(descriptor, strict: false, case_insensitive_headers: false) ⇒ Schema

Returns a new instance of Schema.



11
12
13
14
15
16
17
18
19
20
# File 'lib/tableschema/schema.rb', line 11

def initialize(descriptor, strict: false, case_insensitive_headers: false)
  self.merge! deep_symbolize_keys(parse_schema(descriptor))
  @case_insensitive_headers = case_insensitive_headers
  @strict = strict
  load_fields!
  load_validator!
  expand!
  @strict == true ? validate! : validate
  self
end

Instance Attribute Details

#errorsObject (readonly)

Public



9
10
11
# File 'lib/tableschema/schema.rb', line 9

def errors
  @errors
end

Instance Method Details

#add_field(descriptor) ⇒ Object



61
62
63
64
65
66
67
68
69
# File 'lib/tableschema/schema.rb', line 61

def add_field(descriptor)
  self[:fields].push(descriptor)
  validate!
  descriptor
rescue TableSchema::SchemaException => e
  self[:fields].pop
  raise e if @strict
  nil
end

#cast_row(row, fail_fast: true) ⇒ Object



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/tableschema/schema.rb', line 78

def cast_row(row, fail_fast: true)
  errors = Set.new
  handle_error = lambda { |e| fail_fast == true ? raise(e) : errors << e }
  row = row.fields if row.class == CSV::Row
  if row.count != self.fields.count
    handle_error.call(TableSchema::ConversionError.new("The number of items to convert (#{row.count}) does not match the number of headers in the schema (#{self.fields.count})"))
  end

  self.fields.each_with_index do |field, i|
    begin
      row[i] = field.cast_value(row[i])
    rescue TableSchema::Exception => e
      handle_error.call(e)
    end
  end

  unless errors.empty?
    raise(TableSchema::MultipleInvalid.new("There were errors parsing the data", errors))
  end
  row
end

#descriptorObject



35
36
37
# File 'lib/tableschema/schema.rb', line 35

def descriptor
  self.to_h
end

#field_namesObject Also known as: headers



51
52
53
54
55
# File 'lib/tableschema/schema.rb', line 51

def field_names
  fields.map { |f| transform(f[:name]) }
rescue NoMethodError
  []
end

#fieldsObject



47
48
49
# File 'lib/tableschema/schema.rb', line 47

def fields
  self[:fields]
end

#foreign_keysObject



43
44
45
# File 'lib/tableschema/schema.rb', line 43

def foreign_keys
  self[:foreignKeys] || []
end

#get_constraints(field_name) ⇒ Object



117
118
119
# File 'lib/tableschema/schema.rb', line 117

def get_constraints(field_name)
  get_field(field_name)[:constraints] || {}
end

#get_field(field_name) ⇒ Object



57
58
59
# File 'lib/tableschema/schema.rb', line 57

def get_field(field_name)
  fields.find { |f| f[:name] == field_name }
end

#get_fields_by_type(type) ⇒ Object



135
136
137
# File 'lib/tableschema/schema.rb', line 135

def get_fields_by_type(type)
  fields.select { |f| f[:type] == type }
end

#get_type(field_name) ⇒ Object



113
114
115
# File 'lib/tableschema/schema.rb', line 113

def get_type(field_name)
  get_field(field_name)[:type]
end

#has_field?(field_name) ⇒ Boolean

Returns:



131
132
133
# File 'lib/tableschema/schema.rb', line 131

def has_field?(field_name)
  get_field(field_name) != nil
end

#missing_valuesObject



109
110
111
# File 'lib/tableschema/schema.rb', line 109

def missing_values
  self.fetch(:missingValues, TableSchema::DEFAULTS[:missing_values])
end

#primary_keyObject



39
40
41
# File 'lib/tableschema/schema.rb', line 39

def primary_key
  [self[:primaryKey]].flatten.reject { |k| k.nil? }
end

#remove_field(field_name) ⇒ Object



71
72
73
74
75
76
# File 'lib/tableschema/schema.rb', line 71

def remove_field(field_name)
  field = get_field(field_name)
  self[:fields].reject!{ |f| f.name == field_name }
  validate
  field
end

#required_headersObject



121
122
123
124
# File 'lib/tableschema/schema.rb', line 121

def required_headers
  fields.select { |f| f.fetch(:constraints, {}).fetch(:required, nil).to_s == 'true' }
        .map { |f| transform(f[:name]) }
end

#save(target) ⇒ Object



100
101
102
103
# File 'lib/tableschema/schema.rb', line 100

def save(target)
  File.open(target, "w") { |file| file << JSON.pretty_generate(self.descriptor) }
  true
end

#unique_headersObject



126
127
128
129
# File 'lib/tableschema/schema.rb', line 126

def unique_headers
  fields.select { |f| f.fetch(:constraints, {}).fetch(:unique, nil).to_s == 'true' }
        .map { |f| transform(f[:name]) }
end

#validateObject



22
23
24
25
26
27
# File 'lib/tableschema/schema.rb', line 22

def validate
  @errors = Set.new(JSON::Validator.fully_validate(@profile, self))
  check_primary_key
  check_foreign_keys
  @errors.empty?
end

#validate!Object

Raises:



29
30
31
32
33
# File 'lib/tableschema/schema.rb', line 29

def validate!
  validate
  raise SchemaException.new(@errors.first) unless @errors.empty?
  true
end