Class: PaperTrailDiff::VersionAssociationCandidateScope

Inherits:
Object
  • Object
show all
Defined in:
lib/paper_trail_diff/version_association_candidate_scope.rb,
sig/generated/paper_trail_diff/version_association_candidate_scope.rbs

Overview

Selects association activity from a boundary forward plus the state at that boundary.

Instance Method Summary collapse

Constructor Details

#initialize(version_class, start_at, end_at: nil) ⇒ VersionAssociationCandidateScope

: (untyped, untyped, ?end_at: untyped) -> void

Parameters:

  • (Object)
  • (Object)
  • end_at: (Object) (defaults to: nil)


8
9
10
11
12
# File 'lib/paper_trail_diff/version_association_candidate_scope.rb', line 8

def initialize(version_class, start_at, end_at: nil)
  @version_class = version_class
  @start_at = start_at
  @end_at = end_at
end

Instance Method Details

#activity_condition(columns, start_at, connection) ⇒ String

: (Hash[Symbol, String], String, untyped) -> String

Parameters:

  • (Hash[Symbol, String])
  • (String)
  • (Object)

Returns:

  • (String)


82
83
84
85
86
87
88
# File 'lib/paper_trail_diff/version_association_candidate_scope.rb', line 82

def activity_condition(columns, start_at, connection)
  created_at = columns.fetch(:outer_created_at)
  condition = "#{created_at} >= #{start_at}"
  return condition unless @end_at

  "(#{condition} AND #{created_at} <= #{connection.quote(@end_at)})"
end

#call(relation) ⇒ Object

: (untyped) -> untyped

Parameters:

  • (Object)

Returns:

  • (Object)


15
16
17
18
19
# File 'lib/paper_trail_diff/version_association_candidate_scope.rb', line 15

def call(relation)
  return relation unless @start_at

  relation.where(candidate_condition)
end

#candidate_conditionString

: () -> String

Returns:

  • (String)


39
40
41
# File 'lib/paper_trail_diff/version_association_candidate_scope.rb', line 39

def candidate_condition
  with_connection { |connection| condition_sql(connection) }
end

#column(connection, table, name) ⇒ String

: (untyped, String, String) -> String

Parameters:

  • (Object)
  • (String)
  • (String)

Returns:

  • (String)


91
92
93
# File 'lib/paper_trail_diff/version_association_candidate_scope.rb', line 91

def column(connection, table, name)
  "#{table}.#{connection.quote_column_name(name)}"
end

#compact_sql(sql) ⇒ String

: (String) -> String

Parameters:

  • (String)

Returns:

  • (String)


96
97
98
# File 'lib/paper_trail_diff/version_association_candidate_scope.rb', line 96

def compact_sql(sql)
  sql.gsub(/\s+/, ' ').strip
end

#condition_sql(connection) ⇒ String

: (untyped) -> String

Parameters:

  • (Object)

Returns:

  • (String)


44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/paper_trail_diff/version_association_candidate_scope.rb', line 44

def condition_sql(connection) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
  outer = connection.quote_table_name(@version_class.table_name)
  later = connection.quote_table_name('paper_trail_diff_later_versions')
  start_at = connection.quote(@start_at)
  columns = quoted_columns(connection, outer, later)
  compact_sql(<<~SQL)
    (
      #{activity_condition(columns, start_at, connection)}
      OR (
        #{columns.fetch(:outer_created_at)} < #{start_at}
        AND #{columns.fetch(:outer_event)} != #{connection.quote('destroy')}
        AND NOT EXISTS (
          SELECT 1
            FROM #{outer} #{later}
           WHERE #{columns.fetch(:later_item_type)} = #{columns.fetch(:outer_item_type)}
             AND #{columns.fetch(:later_item_id)} = #{columns.fetch(:outer_item_id)}
             AND #{columns.fetch(:later_created_at)} < #{start_at}
             AND #{columns.fetch(:later_created_at)} > #{columns.fetch(:outer_created_at)}
        )
      )
    )
  SQL
end

#quoted_columns(connection, outer, later) ⇒ Hash[Symbol, String]

: (untyped, String, String) -> Hash[Symbol, String]

Parameters:

  • (Object)
  • (String)
  • (String)

Returns:

  • (Hash[Symbol, String])


69
70
71
72
73
74
75
76
77
78
79
# File 'lib/paper_trail_diff/version_association_candidate_scope.rb', line 69

def quoted_columns(connection, outer, later)
  {
    outer_created_at: column(connection, outer, 'created_at'),
    outer_event: column(connection, outer, 'event'),
    outer_item_type: column(connection, outer, 'item_type'),
    outer_item_id: column(connection, outer, 'item_id'),
    later_created_at: column(connection, later, 'created_at'),
    later_item_type: column(connection, later, 'item_type'),
    later_item_id: column(connection, later, 'item_id')
  }
end

#with_connection {|arg0| ... } ⇒ String

Only quoting helpers are needed, so the connection is borrowed for the duration of building the condition rather than checked out permanently, which Active Record 7.2 and newer can deprecate. Active Record 7.1 has no with_connection and reaches the same connection through the accessor. : () { (untyped) -> String } -> String

Yields:

Yield Parameters:

  • arg0 (Object)

Yield Returns:

  • (String)

Returns:

  • (String)


32
33
34
35
36
# File 'lib/paper_trail_diff/version_association_candidate_scope.rb', line 32

def with_connection(&block)
  return @version_class.with_connection(&block) if @version_class.respond_to?(:with_connection)

  block.call(@version_class.connection)
end