1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 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
|
module DBF
# The Schema module is mixin for the Table class
module Schema
FORMATS = [:activerecord, :json, :sequel].freeze
OTHER_DATA_TYPES = {
'Y' => ':decimal, :precision => 15, :scale => 4',
'D' => ':date',
'T' => ':datetime',
'L' => ':boolean',
'M' => ':text',
'B' => ':binary'
}.freeze
# Generate an ActiveRecord::Schema
#
# xBase data types are converted to generic types as follows:
# - Number columns with no decimals are converted to :integer
# - Number columns with decimals are converted to :float
# - Date columns are converted to :datetime
# - Logical columns are converted to :boolean
# - Memo columns are converted to :text
# - Character columns are converted to :string and the :limit option is set
# to the length of the character column
#
# Example:
# create_table "mydata" do |t|
# t.column :name, :string, :limit => 30
# t.column :last_update, :datetime
# t.column :is_active, :boolean
# t.column :age, :integer
# t.column :notes, :text
# end
#
# @param format [Symbol] format Valid options are :activerecord and :json
# @param table_only [Boolean]
# @return [String]
def schema(format = :activerecord, table_only: false)
schema_method_name = schema_name(format)
send(schema_method_name, table_only: table_only)
rescue NameError
raise ArgumentError, ":#{format} is not a valid schema. Valid schemas are: #{FORMATS.join(', ')}."
end
def schema_name(format) # :nodoc:
"#{format}_schema"
end
def activerecord_schema(*) # :nodoc:
s = "ActiveRecord::Schema.define do\n"
s << " create_table \"#{name}\" do |t|\n"
columns.each do |column|
s << " t.column #{activerecord_schema_definition(column)}"
end
s << " end\nend"
s
end
def sequel_schema(table_only: false) # :nodoc:
s = ''
s << "Sequel.migration do\n" unless table_only
s << " change do\n " unless table_only
s << " create_table(:#{name}) do\n"
columns.each do |column|
s << " column #{sequel_schema_definition(column)}"
end
s << " end\n"
s << " end\n" unless table_only
s << "end\n" unless table_only
s
end
def json_schema(*) # :nodoc:
columns.map(&:to_hash).to_json
end
# ActiveRecord schema definition
#
# @param column [DBF::Column]
# @return [String]
def activerecord_schema_definition(column)
"\"#{column.underscored_name}\", #{schema_data_type(column, :activerecord)}\n"
end
# Sequel schema definition
#
# @param column [DBF::Column]
# @return [String]
def sequel_schema_definition(column)
":#{column.underscored_name}, #{schema_data_type(column, :sequel)}\n"
end
def schema_data_type(column, format = :activerecord) # :nodoc:
case column.type
when 'N', 'F', 'I'
number_data_type(column)
when 'Y', 'D', 'T', 'L', 'M', 'B'
OTHER_DATA_TYPES[column.type]
else
string_data_format(format, column)
end
end
def number_data_type(column)
column.decimal > 0 ? ':float' : ':integer'
end
def string_data_format(format, column)
if format == :sequel
":varchar, :size => #{column.length}"
else
":string, :limit => #{column.length}"
end
end
end
end
|