class PgSearch::Multisearch::Rebuilder

def additional_attributes?

def additional_attributes?
  model.pg_search_multisearchable_options.key?(:additional_attributes)
end

def base_model_name

def base_model_name
  connection.quote(model.base_class.name)
end

def columns

def columns
  Array(model.pg_search_multisearchable_options[:against])
end

def conditional?

def conditional?
  model.pg_search_multisearchable_options.key?(:if) || model.pg_search_multisearchable_options.key?(:unless)
end

def connection

def connection
  model.connection
end

def content_expressions

def content_expressions
  columns.map do |column|
    %{coalesce(:model_table.#{connection.quote_column_name(column)}::text, '')}
  end.join(" || ' ' || ")
end

def current_time

def current_time
  connection.quote(connection.quoted_date(@time_source.call))
end

def documents_table

def documents_table
  PgSearch::Document.quoted_table_name
end

def dynamic?

def dynamic?
  column_names = model.columns.map(&:name)
  columns.any? { |column| column_names.exclude?(column.to_s) }
end

def initialize(model, time_source = Time.method(:now))

def initialize(model, time_source = Time.method(:now))
  raise ModelNotMultisearchable, model unless model.respond_to?(:pg_search_multisearchable_options)
  @model = model
  @time_source = time_source
end

def model_name

def model_name
  connection.quote(model.name)
end

def model_table

def model_table
  model.quoted_table_name
end

def primary_key

def primary_key
  model.primary_key
end

def rebuild

def rebuild
  if model.respond_to?(:rebuild_pg_search_documents)
    model.rebuild_pg_search_documents
  elsif conditional? || dynamic? || additional_attributes?
    model.find_each(&:update_pg_search_document)
  else
    model.connection.execute(rebuild_sql)
  end
end

def rebuild_sql

def rebuild_sql
  replacements.inject(rebuild_sql_template) do |sql, key|
    sql.gsub ":#{key}", send(key)
  end
end

def rebuild_sql_template

def rebuild_sql_template
  <<~SQL.squish
    INSERT INTO :documents_table (searchable_type, searchable_id, content, created_at, updated_at)
      SELECT :base_model_name AS searchable_type,
             :model_table.#{primary_key} AS searchable_id,
             (
               :content_expressions
             ) AS content,
             :current_time AS created_at,
             :current_time AS updated_at
      FROM :model_table :sti_clause
  SQL
end

def replacements

def replacements
  %w[content_expressions base_model_name model_name model_table documents_table current_time sti_clause]
end

def sti_clause

def sti_clause
  clause = ""
  if model.column_names.include? model.inheritance_column
    clause = "WHERE"
    clause = "#{clause} #{model.inheritance_column} IS NULL OR" if model.base_class == model
    clause = "#{clause} #{model.inheritance_column} = #{model_name}"
  end
  clause
end