Class: Mongify::Database::Column

Inherits:
Object
  • Object
show all
Defined in:
lib/mongify/database/column.rb

Overview

A column that is used to access sql data and transform it into the no sql database

Structure

Structure for defining a column is as follows:

column "name", :type, {options}

Columns with no type given will be set to :string

Notes

Leaving a column out when defining a table will result in a copy of the information (as a string).

Types

Types of columns are supported:

:key                  # Columns that are primary keys need to be marked as :key type
:integer              # Will be converted to a integer
:float                # Will be converted to a float
:decimal              # Will be converted to a string *(you can change default behaviour read below)
:string               # Will be converted to a string
:text                 # Will be converted to a string
:datetime             # Will be converted to a Time format (DateTime is not currently supported in the Mongo ruby driver)
:date                 # Will be converted to a Time format (Date is not currently supported in the Mongo ruby driver)
:timestamps           # Will be converted to a Time format
:time                 # Will be converted to a Time format (the date portion of the Time object will be 2000-01-01)
:binary               # Will be converted to a string
:boolean              # Will be converted to a true or false values

Options

column "post_id", :integer, :referneces => :posts   # Referenced columns need to be marked as such, this will mean that they will be updated
                                                    # with the new BSON::ObjectID.

NOTE: if you rename the table 'posts', you should set the :references to the new name

column "name", :string, :ignore => true             # Ignoring a column will make the column NOT copy over to the new database

column "surname", :string, :rename_to => 'last_name'# Rename_to allows you to rename the column

column "post_id", :integer, :auto_detect => true    # Will run auto detect and make this column a :references => 'posts', :on => 'post_id' for you
                                                    # More used when reading a sql database, NOT recommended for use during processing of translation

For decimal columns you can specify a few options:

column "total",                                     # This is a default conversion setting.
       :decimal,
       :as => 'string'                              

column "total",                                     # You can specify to convert your decimal to integer
        :decimal,                                   # specifying scale will define how many decimal places to keep
        :as => 'integer',                           # Example: :scale => 2 will convert 123.4567 to 12346 in to mongodb
        :scale => 2

Decimal Storage

Unfortunately MongoDB Ruby Drivers doesn't support BigDecimal, so to ensure all data is stored correctly (without losing information) I've chosen to store as String, however you can overwrite this functionality in one of two ways: The reason you would want to do this, is to make this searchable via a query.

1) You can specify :as => 'integer', :scale => 2

column "total", :decimal, :as => 'integer', :scale => 2

#It would take a value of 123.456 and store it as an integer of value 12346

<b>2) You can specify your own custom conversion by doing a Table#before_save

Example:

table "invoice" do
  column "name", :string
  column "total", :decimal
  before_save do |row|
    row.total = (BigDecimal.new(row.total) * 1000).round
  end
end

This would take 123.456789 in the total column and convert it to an interger of value 123457 (and in your app you can convert it back to a decimal)

REMEMBER there is a limit on how big of an integer you can store in BSON/MongoDB (bsonspec.org/#/specification)

Constant Summary

AVAILABLE_OPTIONS =

List of available options for a column

['references', 'ignore', 'rename_to', 'as', 'scale']

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(sql_name, type = :string, options = {}) ⇒ Column

Returns a new instance of Column



95
96
97
98
99
100
101
102
103
104
# File 'lib/mongify/database/column.rb', line 95

def initialize(sql_name, type=:string, options={})
  @sql_name = sql_name
  options, type = type, nil if type.is_a?(Hash)
  self.type = type
  @options = options.stringify_keys
  @auto_detect = @options.delete('auto_detect')
  run_auto_detect!
  
  self
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(meth, *args, &blk) ⇒ Object

Sets up a accessor method for an option

def rename_to=(value)
  options['rename_to'] = value
end
def rename_to
  options['rename_to']
end


149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# File 'lib/mongify/database/column.rb', line 149

def method_missing(meth, *args, &blk)
  method_name = meth.to_s.gsub("=", '')
  if AVAILABLE_OPTIONS.include?(method_name)
    unless self.class.method_defined?(method_name.to_sym)
      class_eval "def \#{method_name}=(value)\noptions['\#{method_name}'] = value\nend\n"
    end
    unless self.class.method_defined?("#{method_name}=".to_sym)
      class_eval "def \#{method_name}\noptions['\#{method_name}']\nend\n"
    end
    send(meth, *args, &blk)
  else
    super(meth, *args, &blk)
  end
end

Instance Attribute Details

#optionsObject (readonly)

Returns the value of attribute options



80
81
82
# File 'lib/mongify/database/column.rb', line 80

def options
  @options
end

#sql_nameObject (readonly)

Returns the value of attribute sql_name



80
81
82
# File 'lib/mongify/database/column.rb', line 80

def sql_name
  @sql_name
end

#typeObject

Returns the value of attribute type



80
81
82
# File 'lib/mongify/database/column.rb', line 80

def type
  @type
end

Class Method Details

.auto_detect(column) ⇒ Object

Auto detects if a column is an :key column or is a reference column



86
87
88
89
90
91
92
93
# File 'lib/mongify/database/column.rb', line 86

def self.auto_detect(column)
  case column.sql_name.downcase
  when 'id'
    column.type = :key if column.type == :integer
  when /(.*)_id/
    column.references = $1.to_s.pluralize unless column.referenced? || column.type != :integer
  end
end

Instance Method Details

#asString

Used when trying to figure out how to convert a decimal value

Returns:

  • (String)

    passed option or defaults to 'string'



199
200
201
# File 'lib/mongify/database/column.rb', line 199

def as
  options['as'] ||= 'string'
end

#as=(value) ⇒ Object

Sets option to either 'string' or 'integer', defults to 'string' for unknown values

Parameters:

  • value, (String|Symbol)

    can be either 'string' or 'integer



204
205
206
207
# File 'lib/mongify/database/column.rb', line 204

def as=(value)
  value = value.to_s.downcase
  options['as'] = ['string', 'integer'].include?(value) ? value : 'string'
end

#as_integer?Boolean

Returns true if :as was passed as integer

Returns:

  • (Boolean)


209
210
211
# File 'lib/mongify/database/column.rb', line 209

def as_integer?
  self.as == 'integer'
end

#auto_detect?Boolean

Returns true if column should be auto_detected (passed via options)

Returns:

  • (Boolean)


188
189
190
# File 'lib/mongify/database/column.rb', line 188

def auto_detect?
  !!@auto_detect
end

#ignored?Boolean

Returns true if column is ignored

Returns:

  • (Boolean)


193
194
195
# File 'lib/mongify/database/column.rb', line 193

def ignored?
  !!self.ignore
end

#key?Boolean

Returns true if column is a :key type column

Returns:

  • (Boolean)


183
184
185
# File 'lib/mongify/database/column.rb', line 183

def key?
  self.type == :key
end

#nameObject

Returns the no_sql record name



113
114
115
# File 'lib/mongify/database/column.rb', line 113

def name
  @name ||= rename_to || sql_name
end

#referenced?Boolean

Returns true if the column is a reference column

Returns:

  • (Boolean)


173
174
175
# File 'lib/mongify/database/column.rb', line 173

def referenced?
  !self.options['references'].nil?
end

#renamed?Boolean

Returns true if column is being renamed

Returns:

  • (Boolean)


178
179
180
# File 'lib/mongify/database/column.rb', line 178

def renamed?
  self.name != self.sql_name
end

#scaleinteger

Get the scale option for decimal to integer conversion

column 'total', :decimal, :as => 'integer', :scale => 3

Returns:

  • (integer)

    passed option or 0



216
217
218
# File 'lib/mongify/database/column.rb', line 216

def scale
  options['scale'] ||= 0
end

#scale=(value) ⇒ Object

Set the scale option for decimal to integer conversion

column 'total', :decimal, :as => 'integer', :scale => 3

Parameters:

  • number (Integer)

    of decimal places to round off to



222
223
224
# File 'lib/mongify/database/column.rb', line 222

def scale=(value)
  options['scale'] = value.to_i
end

#to_printObject Also known as: to_s

Returns a string representation of the column as it would show in a translation file. Mainly used during print out of translation file



133
134
135
136
137
138
# File 'lib/mongify/database/column.rb', line 133

def to_print
  "column \"#{sql_name}\", :#{type}".tap do |output|
    output_options = options.map{|k, v| (v == nil) ? nil : ":#{k} => \"#{v}\""}.compact
    output << ", #{output_options.join(', ')}" unless output_options.blank?
  end
end

#translate(value) ⇒ Object

Returns a translated hash from a given value Example:

@column = Column.new("surname", :string, :rename_to => 'last_name')
@column.translate("Smith") # => {"last_name" => "Smith"}


121
122
123
124
125
126
127
128
129
# File 'lib/mongify/database/column.rb', line 121

def translate(value)
  return {} if ignored?
  case type
    when :key
      {"pre_mongified_id" => value.to_i}
    else
      {"#{self.name}" => type_cast(value)}
  end
end