Class: Mongify::Database::Column
- Inherits:
-
Object
- Object
- Mongify::Database::Column
- 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. You can provide an :as if your :key is not an integer column
: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, :references => :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 collapse
- AVAILABLE_OPTIONS =
List of available options for a column
['references', 'ignore', 'rename_to', 'as', 'scale']
Instance Attribute Summary collapse
-
#options ⇒ Object
readonly
Returns the value of attribute options.
-
#sql_name ⇒ Object
readonly
Returns the value of attribute sql_name.
-
#type ⇒ Object
Returns the value of attribute type.
Class Method Summary collapse
-
.auto_detect(column) ⇒ Object
Auto detects if a column is an :key column or is a reference column.
Instance Method Summary collapse
-
#as ⇒ String
Used when trying to figure out how to convert a decimal value.
-
#as=(value) ⇒ Object
Sets option to either ‘string’ or ‘integer’, defults to ‘string’ for unknown values.
-
#as_integer? ⇒ Boolean
Returns true if :as was passed as integer.
-
#auto_detect? ⇒ Boolean
Returns true if column should be auto_detected (passed via options).
-
#ignored? ⇒ Boolean
Returns true if column is ignored.
-
#initialize(sql_name, type = :string, options = {}) ⇒ Column
constructor
A new instance of Column.
-
#key? ⇒ Boolean
Returns true if column is a :key type column.
-
#method_missing(meth, *args, &blk) ⇒ Object
Sets up a accessor method for an option.
-
#name ⇒ Object
Returns the no_sql record name.
-
#referenced? ⇒ Boolean
Returns true if the column is a reference column.
-
#renamed? ⇒ Boolean
Returns true if column is being renamed.
-
#scale ⇒ integer
Get the scale option for decimal to integer conversion column ‘total’, :decimal, :as => ‘integer’, :scale => 3.
-
#scale=(value) ⇒ Object
Set the scale option for decimal to integer conversion column ‘total’, :decimal, :as => ‘integer’, :scale => 3.
-
#to_print ⇒ Object
(also: #to_s)
Returns a string representation of the column as it would show in a translation file.
-
#translate(value) ⇒ Object
Returns a translated hash from a given value Example: @column = Column.new(“surname”, :string, :rename_to => ‘last_name’) @column.translate(“Smith”) # => => “Smith”.
-
#type_cast(value) ⇒ Object
Casts the value to a given type.
Constructor Details
#initialize(sql_name, type = :string, options = {}) ⇒ Column
Returns a new instance of Column.
96 97 98 99 100 101 102 103 104 105 |
# File 'lib/mongify/database/column.rb', line 96 def initialize(sql_name, type=:string, ={}) @sql_name = sql_name , type = type, nil if type.is_a?(Hash) self.type = type @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)
['rename_to'] = value
end
def rename_to
['rename_to']
end
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
# File 'lib/mongify/database/column.rb', line 153 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 <<-EOF def #{method_name}=(value) options['#{method_name}'] = value end EOF end unless self.class.method_defined?("#{method_name}=".to_sym) class_eval <<-EOF def #{method_name} options['#{method_name}'] end EOF end send(meth, *args, &blk) else super(meth, *args, &blk) end end |
Instance Attribute Details
#options ⇒ Object (readonly)
Returns the value of attribute options.
80 81 82 |
# File 'lib/mongify/database/column.rb', line 80 def @options end |
#sql_name ⇒ Object (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 |
#type ⇒ Object
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 94 |
# File 'lib/mongify/database/column.rb', line 86 def self.auto_detect(column) case column.sql_name.downcase when 'id' column.as = column.type column.type = :key when /(.*)_id/ column.references = $1.to_s.pluralize unless column.referenced? end end |
Instance Method Details
#as ⇒ String
Used when trying to figure out how to convert a decimal value
203 204 205 |
# File 'lib/mongify/database/column.rb', line 203 def as ['as'] ||= :string end |
#as=(value) ⇒ Object
Sets option to either ‘string’ or ‘integer’, defults to ‘string’ for unknown values
208 209 210 211 |
# File 'lib/mongify/database/column.rb', line 208 def as=(value) value = value.to_s.downcase.to_sym ['as'] = [:string, :integer].include?(value) ? value : :string end |
#as_integer? ⇒ Boolean
Returns true if :as was passed as integer
213 214 215 |
# File 'lib/mongify/database/column.rb', line 213 def as_integer? self.as == :integer end |
#auto_detect? ⇒ Boolean
Returns true if column should be auto_detected (passed via options)
192 193 194 |
# File 'lib/mongify/database/column.rb', line 192 def auto_detect? !!@auto_detect end |
#ignored? ⇒ Boolean
Returns true if column is ignored
197 198 199 |
# File 'lib/mongify/database/column.rb', line 197 def ignored? !!self.ignore end |
#key? ⇒ Boolean
Returns true if column is a :key type column
187 188 189 |
# File 'lib/mongify/database/column.rb', line 187 def key? self.type == :key end |
#name ⇒ Object
Returns the no_sql record name
114 115 116 |
# File 'lib/mongify/database/column.rb', line 114 def name @name ||= rename_to || sql_name end |
#referenced? ⇒ Boolean
Returns true if the column is a reference column
177 178 179 |
# File 'lib/mongify/database/column.rb', line 177 def referenced? !self.['references'].nil? end |
#renamed? ⇒ Boolean
Returns true if column is being renamed
182 183 184 |
# File 'lib/mongify/database/column.rb', line 182 def renamed? self.name != self.sql_name end |
#scale ⇒ integer
Get the scale option for decimal to integer conversion
column 'total', :decimal, :as => 'integer', :scale => 3
220 221 222 |
# File 'lib/mongify/database/column.rb', line 220 def scale ['scale'] ||= 0 end |
#scale=(value) ⇒ Object
Set the scale option for decimal to integer conversion
column 'total', :decimal, :as => 'integer', :scale => 3
226 227 228 |
# File 'lib/mongify/database/column.rb', line 226 def scale=(value) ['scale'] = value.to_i end |
#to_print ⇒ Object 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
134 135 136 137 138 139 140 141 142 |
# File 'lib/mongify/database/column.rb', line 134 def to_print "column \"#{sql_name}\", :#{type}".tap do |output| = .map do |k, v| next if v.nil? ":#{k} => #{v.is_a?(Symbol) ? ":#{v}" : %Q["#{v}"] }" end.compact output << ", #{.join(', ')}" unless .blank? end end |
#translate(value) ⇒ Object
122 123 124 125 126 127 128 129 130 |
# File 'lib/mongify/database/column.rb', line 122 def translate(value) return {} if ignored? case type when :key {"pre_mongified_id" => type_cast(value)} else {"#{self.name}" => type_cast(value)} end end |
#type_cast(value) ⇒ Object
Casts the value to a given type
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 |
# File 'lib/mongify/database/column.rb', line 231 def type_cast(value) return nil if value.nil? case type when :key then ['as'] == :string ? value.to_s : value.to_i #If :as is provided, check if it's string, otherwise integer when :string then value.to_s when :text then value.to_s when :integer then value.to_i when :float then value.to_f when :decimal value = ActiveRecord::Type::Decimal.new.type_cast_from_database(value) if as_integer? (value * (10 ** self.scale)).round.to_i else value.to_s end when :datetime then ActiveRecord::Type::DateTime.new.type_cast_from_database(value) when :timestamp then ActiveRecord::Type::DateTime.new.type_cast_from_database(value) when :time then ActiveRecord::Type::Time.new.type_cast_from_database(value) when :date then ActiveRecord::Type::DateTime.new.type_cast_from_database(value) when :binary then ActiveRecord::Type::Binary.new.type_cast_from_database(value) when :boolean then ActiveRecord::Type::Boolean.new.type_cast_from_database(value) else value.to_s end end |