Class: Brick::SalesforceMigrationsGenerator

Inherits:
Rails::Generators::Base
  • Object
show all
Includes:
FancyGets
Defined in:
lib/generators/brick/salesforce_migrations_generator.rb

Overview

Auto-generates migration files

Instance Method Summary collapse

Instance Method Details

#brick_salesforce_migrationsObject



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
# File 'lib/generators/brick/salesforce_migrations_generator.rb', line 17

def brick_salesforce_migrations
  ::Brick.apply_double_underscore_patch
  # ::Brick.mode = :on
  # ActiveRecord::Base.establish_connection

  # Runs at the end of parsing Salesforce WSDL, and uses the discovered tables and columns to create migrations
  relations = nil
  end_document_proc = lambda do |salesforce_tables|
    # p [:end_document]
    mig_path, is_insert_versions, is_delete_versions = ::Brick::MigrationBuilder.check_folder
    return unless mig_path

    # Generate a list of tables that can be chosen
    table_names = salesforce_tables.keys
    chosen = gets_list(list: table_names, chosen: table_names.dup)

    soap_data_types = {
      'tns:ID' => 'string',
      'xsd:string' => 'string',
      'xsd:dateTime' => 'datetime',
      'xsd:boolean' => 'boolean',
      'xsd:double' => 'float',
      'xsd:int' => 'integer',
      'xsd:date' => 'date',
      'xsd:anyType' => 'string', # Don't fully know on this
      'xsd:long' => 'bigint',
      'xsd:base64Binary' => 'bytea',
      'xsd:time' => 'time'
    }
    fk_idx = 0
    # Build out a '::Brick.relations' hash that represents this Salesforce schema
    relations = chosen.each_with_object({}) do |tbl_name, s|
                  tbl = salesforce_tables[tbl_name]
                  # Build out columns and foreign keys
                  cols = { 'id'=>['string', nil, false, true] }
                  fks = {}
                  tbl[:cols].each do |col|
                    next if col[:name] == 'Id'

                    dt = soap_data_types[col[:data_type]] || 'string'
                    cols[col[:name]] = [dt, nil, col[:nillable], false]
                    if (ref_to = col[:fk_reference_to])
                      fk_hash = {
                        is_bt: true,
                        fk: col[:name],
                        assoc_name: "#{col[:name]}_bt",
                        inverse_table: ref_to
                      }
                      fks["fk_salesforce_#{fk_idx += 1}"] = fk_hash
                    end
                  end
                  # Put it all into a relation entry, named the same as the table
                  s[tbl_name] = {
                    pkey: { "#{tbl_name}_pkey" => ['id'] },
                    cols: cols,
                    fks: fks
                  }
                end
    # Build but do not have foreign keys established yet, and do not put version entries info the schema_migrations table
    ::Brick::MigrationBuilder.generate_migrations(chosen, mig_path, is_insert_versions, is_delete_versions, relations,
                                                  do_fks_last: 'Separate', do_schema_migrations: false)
  end
  parser = Nokogiri::XML::SAX::Parser.new(::Brick::SalesforceSchema.new(end_document_proc))
  # The WSDL file must have a .xml extension, and can be in any folder in the project
  # Alternatively the user can supply this option on the command line
  @wsdl_file = nil if @wsdl_file == ''
  loop do
    break if (@wsdl_file ||= gets_list(Dir['**/*.xml'] + ['* Cancel *'])) == '* Cancel *'

    parser.parse(File.read(@wsdl_file))

    if relations.length > 300
      puts "A Salesforce installation generally has hundreds to a few thousand tables, and many are empty.
In order to more easily navigate just those tables that have content, you might want to add this
to brick.rb:
  ::Brick.omit_empty_tables_in_dropdown = true"
    end
    break
  rescue Errno::ENOENT
    puts "File \"#{@wsdl_file}\" is not found."
    @wsdl_file = nil
  end
end