Class: Monocle::View

Inherits:
Object
  • Object
show all
Defined in:
lib/monocle/view.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name) ⇒ View

Returns a new instance of View.



10
11
12
13
# File 'lib/monocle/view.rb', line 10

def initialize(name)
  @name = name
  @dependants = []
end

Instance Attribute Details

#dependantsObject

Returns the value of attribute dependants.



5
6
7
# File 'lib/monocle/view.rb', line 5

def dependants
  @dependants
end

#nameObject (readonly)

Returns the value of attribute name.



4
5
6
# File 'lib/monocle/view.rb', line 4

def name
  @name
end

Instance Method Details

#createObject



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/monocle/view.rb', line 27

def create
  debug "Creating #{name}..."
  execute create_command
  Migration.find_or_create_by version: slug
  dependants.each &:create
  true
rescue ActiveRecord::StatementInvalid => e
  # We may have another new view coming that this view depend on
  # if the relation name is included on our list of views, we create
  # that first and then retry
  if e.message =~ /PG::UndefinedTable/ &&
     e.message.scan(/relation \"(\w+)\" does not exist/) &&
     list.keys.include?($1.to_sym)
     warn "Can't create #{name} because it depends on #{$1}, creating that first..."
     list.fetch($1.to_sym).create
     retry
  else
    fail e
  end
end

#create_commandObject



88
89
90
# File 'lib/monocle/view.rb', line 88

def create_command
  @create_command ||= File.read(path_for_sql)
end

#dropObject



19
20
21
22
23
24
25
# File 'lib/monocle/view.rb', line 19

def drop
  debug "Dropping #{name}..."
  self.dependants = get_dependants_from_pg
  dependants.each &:drop
  execute drop_command
  true
end

#drop_commandObject



83
84
85
86
# File 'lib/monocle/view.rb', line 83

def drop_command
  _materialized = 'MATERIALIZED' if materialized?
  "DROP #{_materialized} VIEW IF EXISTS #{name};"
end

#exists?Boolean

Returns:

  • (Boolean)


96
97
98
# File 'lib/monocle/view.rb', line 96

def exists?
  execute(check_if_view_exists_sql).entries.map(&:values).flatten.first
end

#materialized?Boolean

Returns:

  • (Boolean)


15
16
17
# File 'lib/monocle/view.rb', line 15

def materialized?
  !!(@materialized ||= create_command =~ /MATERIALIZED VIEW/i)
end

#migrateObject



48
49
50
51
52
53
54
55
56
57
# File 'lib/monocle/view.rb', line 48

def migrate
  if versions.include?(slug)
    debug "Skipping #{name} as it's already up to date."
    true
  else
    status = drop && create
    info "#{name} migrated to #{slug}!"
    status
  end
end

#path_for_sqlObject



92
93
94
# File 'lib/monocle/view.rb', line 92

def path_for_sql
  @path_for_sql ||= File.join views_path, "#{name}.sql"
end

#refresh(concurrently: false) ⇒ Object



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/monocle/view.rb', line 59

def refresh(concurrently: false)
  # We don't refresh normal views
  return false unless materialized?
  _concurrently = " CONCURRENTLY" if concurrently
  execute "REFRESH MATERIALIZED VIEW#{_concurrently} #{name}"
  true
rescue ActiveRecord::StatementInvalid => e
  # This view is trying to select from a different view that hasn't been
  # populated.
  if e.message =~ /PG::ObjectNotInPrerequisiteState/ &&
     e.message.scan(/materialized view \"(\w+)\" has not been populated/) &&
     list.keys.include?($1.to_sym)
     warn "Can't refresh #{name} because it depends on #{$1} which hasn't been populated, refreshing that first..."
     list.fetch($1.to_sym).refresh
     retry
  else
    fail e
  end
end

#slugObject



79
80
81
# File 'lib/monocle/view.rb', line 79

def slug
  @slug ||= VersionGenerator.new(path_for_sql).generate
end