Module: ModelSchema::Dumper

Defined in:
lib/model_schema/dumper.rb

Class Method Summary collapse

Class Method Details

.dump_model_schema(opts) ⇒ Object

Dumps the model schema based on the given options (see option parsing above).



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
# File 'lib/model_schema/dumper.rb', line 51

def self.dump_model_schema(opts)
  model_info = parse_model_file(opts[:model])
  abort "Couldn't find class that extends Sequel::Model" if !model_info

  db = Sequel.connect(opts[:connection])
  db.extension(:schema_dumper)

  klass = Class.new(Sequel::Model(model_info[:table_name]))
  klass.db = db

  # dump table generator given by model_schema
  generator = klass.send(:table_generator)
  commands = [generator.dump_columns, generator.dump_constraints,
              generator.dump_indexes].reject{|s| s == ''}.join("\n\n")

  # account for indentation
  tab = opts[:tabbing] == 0 ? "\t" : ' ' * opts[:tabbing]
  schema_indentation = model_info[:indentation] + tab
  command_indentation = schema_indentation + tab

  commands = commands.lines.map {|l| l == "\n" ? l : command_indentation + l}.join
  commands = commands.gsub('=>', ' => ')

  dump_lines = ["#{schema_indentation}model_schema do\n",
                "#{commands}\n",
                "#{schema_indentation}end\n"]

  lines = model_info[:lines_before] + dump_lines + model_info[:lines_after]
  File.write(opts[:model], lines.join)
end

.parse_model_file(path) ⇒ Object

Parses the model file at the given path, returning a hash of the form:

:table_name => the model table name :lines_before => an array of lines before the expected model schema dump :lines_after => an array of lines after the expected model schema dump :indentation => the indentation (leading whitespace) of the model class

Returns nil if the file couldn’t be parsed.



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
# File 'lib/model_schema/dumper.rb', line 90

def self.parse_model_file(path)
  lines = File.read(path).lines

  lines.each_with_index do |line, index|
    match = SEQUEL_MODEL_REGEX.match(line)

    if match
      # extract table name as symbol
      table_name = match[1]
      if table_name[0] == ':'
        table_name = table_name[1..-1].to_sym
      else
        abort "Can't find a symbol table name on line: #{line}"
      end

      # indentation for model_schema block
      indentation = LEADING_WHITESPACE_REGEX.match(line)[0]

      return {
        :table_name => table_name.to_sym,
        :lines_before => lines[0..index],
        :lines_after => lines[(index + 1)..-1],
        :indentation => indentation,
      }
    end
  end

  nil
end

.run(args) ⇒ Object

Parses options and then dumps the model schema.



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
# File 'lib/model_schema/dumper.rb', line 9

def self.run(args)
  opts = {}
  opts[:tabbing] = 2

  parser = OptionParser.new do |p|
    p.banner = "Usage: dump_model_schema [options]"

    p.on('-m', '--model MODEL', 'Model file to dump schema in') do |model|
      opts[:model] = model
    end

    p.on('-c', '--connection CONNECTION',
         'Connection string for database') do |connection|
      opts[:connection] = connection
    end

    p.on('-t', '--tabbing TABBING', Integer,
              'Number of spaces for tabbing, or 0 for hard tabs') do |tabbing|
      opts[:tabbing] = tabbing
    end

    p.on('-v', '--version', 'Print version') do
      puts ModelSchema::VERSION
      exit
    end

    p.on('-h', '--help', 'Print help') do
      puts parser
      exit
    end
  end

  parser.parse(args)

  # model and connection are required
  abort 'Must provide a model file with -m or --model.' if !opts[:model]
  abort 'Must provide a connection string with -c or --connection.' if !opts[:connection]

  dump_model_schema(opts)
end