Class: Linkage::Data Abstract

Inherits:
Object
  • Object
show all
Defined in:
lib/linkage/data.rb

Overview

This class is abstract.

Superclass to Field and Function.

Direct Known Subclasses

Field, Function

Constant Summary collapse

TYPE_CONVERSION_TREE =

A “tree” used to find compatible types.

{
  TrueClass => [Integer],
  Integer => [Bignum, Float],
  Bignum => [BigDecimal],
  Float => [BigDecimal],
  BigDecimal => [String],
  String => nil,
  DateTime => nil,
  Date => nil,
  Time => nil,
  File => nil
}

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name) ⇒ Data

Returns a new instance of Data.



28
29
30
# File 'lib/linkage/data.rb', line 28

def initialize(name)
  @name = name
end

Instance Attribute Details

#datasetObject (readonly)

Returns the value of attribute dataset.



26
27
28
# File 'lib/linkage/data.rb', line 26

def dataset
  @dataset
end

#nameObject (readonly)

Returns the value of attribute name.



22
23
24
# File 'lib/linkage/data.rb', line 22

def name
  @name
end

Instance Method Details

#collationObject



40
41
42
# File 'lib/linkage/data.rb', line 40

def collation
  nil
end

#database_typeObject



44
45
46
47
# File 'lib/linkage/data.rb', line 44

def database_type
  ds = dataset
  ds ? ds.database_type : nil
end

#merge(other, new_name = nil) ⇒ Linkage::MergeField

Create a merge field that can hold data from two data sources. If the fields have different types, the resulting type is determined via a type-conversion tree.

Parameters:

Returns:



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/linkage/data.rb', line 59

def merge(other, new_name = nil)
  schema_1 = self.ruby_type
  db_type_1 = self.database_type
  schema_2 = other.ruby_type
  db_type_2 = other.database_type
  if schema_1 == schema_2 && db_type_1 == db_type_2
    result = schema_1
  else
    type_1 = schema_1[:type]
    opts_1 = schema_1[:opts] || {}
    type_2 = schema_2[:type]
    opts_2 = schema_2[:opts] || {}
    result_type = type_1
    result_opts = schema_1[:opts] ? schema_1[:opts].dup : {}

    # type
    if type_1 != type_2
      result_type = first_common_type(type_1, type_2)
      if result_type.nil?
        raise "Can't merge #{type_1} (#{name}) with #{type_2} (#{other.name})"
      end
    end

    # text
    if opts_1[:text] != opts_2[:text]
      # This can only be of type String.
      result_opts[:text] = true
      result_opts.delete(:size)
    end

    # size
    if !result_opts[:text] && opts_1[:size] != opts_2[:size]
      types = [type_1, type_2].uniq
      if types.length == 1 && types[0] == BigDecimal
        # Two decimals
        if opts_1.has_key?(:size) && opts_2.has_key?(:size)
          s_1 = opts_1[:size]
          s_2 = opts_2[:size]
          result_opts[:size] = [ s_1[0] > s_2[0] ? s_1[0] : s_2[0] ]

          if s_1[1] && s_2[1]
            result_opts[:size][1] = s_1[1] > s_2[1] ? s_1[1] : s_2[1]
          else
            result_opts[:size][1] = s_1[1] ? s_1[1] : s_2[1]
          end
        else
          result_opts[:size] = opts_1.has_key?(:size) ? opts_1[:size] : opts_2[:size]
        end
      elsif types.include?(String) && types.include?(BigDecimal)
        # Add one to the precision of the BigDecimal (for the dot)
        if opts_1.has_key?(:size) && opts_2.has_key?(:size)
          s_1 = opts_1[:size].is_a?(Array) ? opts_1[:size][0] + 1 : opts_1[:size]
          s_2 = opts_2[:size].is_a?(Array) ? opts_2[:size][0] + 1 : opts_2[:size]
          result_opts[:size] = s_1 > s_2 ? s_1 : s_2
        elsif opts_1.has_key?(:size)
          result_opts[:size] = opts_1[:size].is_a?(Array) ? opts_1[:size][0] + 1 : opts_1[:size]
        elsif opts_2.has_key?(:size)
          result_opts[:size] = opts_2[:size].is_a?(Array) ? opts_2[:size][0] + 1 : opts_2[:size]
        end
      else
        # Treat as two strings
        if opts_1.has_key?(:size) && opts_2.has_key?(:size)
          result_opts[:size] = opts_1[:size] > opts_2[:size] ? opts_1[:size] : opts_2[:size]
        elsif opts_1.has_key?(:size)
          result_opts[:size] = opts_1[:size]
        else
          result_opts[:size] = opts_2[:size]
        end
      end
    end

    # fixed
    if opts_1[:fixed] != opts_2[:fixed]
      # This can only be of type String.
      result_opts[:fixed] = true
    end

    # collation
    if opts_1[:collate] != opts_2[:collate] || db_type_1 != db_type_2
      result_opts.delete(:collate)
    end

    result = {:type => result_type}
    result[:opts] = result_opts  unless result_opts.empty?
  end

  if new_name
    name = new_name.to_sym
  else
    name = self.name == other.name ? self.name : :"#{self.name}_#{other.name}"
  end
  MergeField.new(name, result, db_type_1 == db_type_2 ? db_type_1 : nil)
end

#ruby_typeObject

Raises:

  • (NotImplementedError)


32
33
34
# File 'lib/linkage/data.rb', line 32

def ruby_type
  raise NotImplementedError
end

#static?Boolean

Returns:

  • (Boolean)

Raises:

  • (NotImplementedError)


49
50
51
# File 'lib/linkage/data.rb', line 49

def static?
  raise NotImplementedError
end

#to_exprObject

Raises:

  • (NotImplementedError)


36
37
38
# File 'lib/linkage/data.rb', line 36

def to_expr
  raise NotImplementedError
end