Class: Solargraph::Rails::Schema

Inherits:
Object
  • Object
show all
Defined in:
lib/solargraph/rails/schema.rb

Defined Under Namespace

Classes: ColumnData

Constant Summary collapse

RUBY_TYPES =
{
  decimal: 'BigDecimal',
  float: 'BigDecimal',
  integer: 'Integer',
  date: 'Date',
  datetime: 'ActiveSupport::TimeWithZone',
  string: 'String',
  boolean: 'Boolean',
  text: 'String',
  jsonb: 'Hash',
  json: 'Hash',
  bigint: 'Integer',
  uuid: 'String',
  inet: 'IPAddr',
  citext: 'String',
  binary: 'String',
  tsvector: 'String',
  timestamp: 'ActiveSupport::TimeWithZone'
}

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeSchema

Returns a new instance of Schema.



34
35
36
# File 'lib/solargraph/rails/schema.rb', line 34

def initialize
  @schema_present = File.exist?('db/schema.rb')
end

Class Method Details

.instanceObject



26
27
28
# File 'lib/solargraph/rails/schema.rb', line 26

def self.instance
  @instance ||= self.new
end

.resetObject



30
31
32
# File 'lib/solargraph/rails/schema.rb', line 30

def self.reset
  @instance = nil
end

Instance Method Details

#process(source_map, ns) ⇒ Object



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
# File 'lib/solargraph/rails/schema.rb', line 38

def process(source_map, ns)
  return [] unless @schema_present
  return [] unless Model.valid_filename?(source_map.filename)

  table = find_table(source_map, ns)

  return [] unless table

  pins = []
  table.each do |column, data|
    location = Util.build_location(data.ast, 'db/schema.rb')
    type = RUBY_TYPES[data.type.to_sym] || 'String'
    %w[% %_in_database %_before_last_save].each do |tpl|
      name = tpl.sub('%', column)
      pins << Util.build_public_method(ns, name, types: [type], location: location)
    end
    %w[%? %_changed? saved_change_to_%? will_save_change_to_%?].each do |tpl|
      name = tpl.sub('%', column)
      pins << Util.build_public_method(ns, name, types: ['Boolean'], location: location)
    end
    %w[%_change_to_be_saved saved_change_to_%].each do |tpl|
      name = tpl.sub('%', column)
      types = ["Array(#{type}, #{type})"]
      pins << Util.build_public_method(ns, name, types: types, location: location)
    end
    pins << Util.build_public_method(ns, "#{column}=", types: [type],
                                     params: { 'value' => [type] },
                                     location: location)

    # Note on this: its the starting step of dynamic filters. Technically, you can also do Model.find_by_col1_and_col2(val1, val2)
    # However, if we start suggestion all of those possibilities, it will simply be bad UX because of having too many suggestions
    pins << Util.build_public_method(ns, "find_by_#{column}", types: ['self', 'nil'],
                                    params: { 'value' => [type] },
                                    location: location,
                                    scope: :class)
  end

  if pins.any?
    Solargraph.logger.debug(
      "[Rails][Schema] added #{pins.map(&:name)} to #{ns.path}"
    )
  end
  pins
end