• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

MushroomObserver / mushroom-observer / 14145714091

29 Mar 2025 12:39PM UTC coverage: 84.27% (-9.7%) from 93.985%
14145714091

Pull #2808

github

web-flow
Merge 0843c72fa into 6655216a6
Pull Request #2808: Convert Query to AR scopes

472 of 2300 new or added lines in 78 files covered. (20.52%)

1381 existing lines in 27 files now uncovered.

26557 of 31514 relevant lines covered (84.27%)

537.23 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/app/classes/query/modules/sql.rb
1
# frozen_string_literal: true
2

UNCOV
3
module Query::Modules::Sql
×
UNCOV
4
  attr_accessor :last_query
×
5

6
  # Build query for <tt>model.find_by_sql</tt> -- i.e. one that returns all
7
  # fields from the table in question, instead just the id.
UNCOV
8
  def sql_select_all_columns(args = {})
×
UNCOV
9
    sql(args.merge(select: "DISTINCT #{model.table_name}.*"))
×
UNCOV
10
  end
×
11

12
  # Build query, allowing the caller to override/augment the standard
13
  # parameters.
UNCOV
14
  def sql(args = {})
×
UNCOV
15
    initialize_query unless initialized?
×
16

UNCOV
17
    our_select  = args[:select] || selects
×
UNCOV
18
    our_join    = join.dup
×
UNCOV
19
    our_join += args[:join] if args[:join].is_a?(Array)
×
UNCOV
20
    our_join << args[:join] if args[:join].is_a?(Hash)
×
UNCOV
21
    our_join << args[:join] if args[:join].is_a?(Symbol)
×
UNCOV
22
    our_tables = tables.dup
×
UNCOV
23
    our_tables += args[:tables] if args[:tables].is_a?(Array)
×
UNCOV
24
    our_tables << args[:tables] if args[:tables].is_a?(Symbol)
×
UNCOV
25
    our_from    = calc_from_clause(our_join, our_tables)
×
UNCOV
26
    our_where   = where.dup
×
UNCOV
27
    our_where += args[:where] if args[:where].is_a?(Array)
×
UNCOV
28
    our_where << args[:where] if args[:where].is_a?(String)
×
UNCOV
29
    our_where = calc_where_clause(our_where)
×
UNCOV
30
    our_group = args[:group] || group
×
UNCOV
31
    our_order = args[:order] || order
×
UNCOV
32
    our_order = reverse_order(order) if our_order == :reverse
×
UNCOV
33
    our_limit = args[:limit]
×
34

35
    # Tack id at end of order to disambiguate the order.
36
    # (I despise programs that render random results!)
UNCOV
37
    if our_order.present? &&
×
UNCOV
38
       !our_order.match(/\.id( |$)/)
×
UNCOV
39
      our_order += ", #{model.table_name}.id DESC"
×
UNCOV
40
    end
×
41

UNCOV
42
    sql = %(
×
UNCOV
43
      SELECT #{our_select}
×
UNCOV
44
      FROM #{our_from}
×
UNCOV
45
    )
×
UNCOV
46
    sql += "  WHERE #{our_where}\n"    if our_where.present?
×
UNCOV
47
    sql += "  GROUP BY #{our_group}\n" if our_group.present?
×
UNCOV
48
    sql += "  ORDER BY #{our_order}\n" if our_order.present?
×
UNCOV
49
    sql += "  LIMIT #{our_limit}\n"    if our_limit.present?
×
50

UNCOV
51
    @last_query = sql
×
UNCOV
52
    sql
×
UNCOV
53
  end
×
54

55
  # Format list of conditions for WHERE clause.
UNCOV
56
  def calc_where_clause(our_where = where)
×
UNCOV
57
    ands = our_where.uniq.map do |x|
×
58
      # Make half-assed attempt to cut down on proliferating parens...
UNCOV
59
      if x.match(/^\(.*\)$/) || !x.match(/ or /i)
×
UNCOV
60
        x
×
UNCOV
61
      else
×
UNCOV
62
        "(#{x})"
×
UNCOV
63
      end
×
UNCOV
64
    end
×
UNCOV
65
    ands.join(" AND ")
×
UNCOV
66
  end
×
67

68
  # Extract and format list of tables names from join tree for FROM clause.
UNCOV
69
  def calc_from_clause(our_join = join, our_tables = tables)
×
UNCOV
70
    implicits = [model.table_name] + our_tables
×
UNCOV
71
    result = implicits.uniq.map { |x| "`#{x}`" }.join(", ")
×
UNCOV
72
    if our_join
×
UNCOV
73
      result += " "
×
UNCOV
74
      result += calc_join_conditions(model.table_name, our_join).join(" ")
×
UNCOV
75
    end
×
UNCOV
76
    result
×
UNCOV
77
  end
×
78

79
  # Extract a complete list of tables being used by this query.  (Combines
80
  # this table (+model.table_name+) with tables from +join+ with custom-joined
81
  # tables from +tables+.)
UNCOV
82
  def table_list(our_join = join, our_tables = tables)
×
UNCOV
83
    flatten_joins([model.table_name] + our_join + our_tables, false).uniq
×
UNCOV
84
  end
×
85

86
  # Flatten join "tree" into a simple Array of Strings.  Set +keep_qualifiers+
87
  # to +false+ to tell it to remove the ".column" qualifiers on ambiguous
88
  # table join specs.
UNCOV
89
  def flatten_joins(arg = join, keep_qualifiers = true)
×
UNCOV
90
    result = []
×
UNCOV
91
    case arg
×
UNCOV
92
    when Hash
×
UNCOV
93
      arg.each do |key, val|
×
UNCOV
94
        key = key.to_s.sub(/\..*/, "") unless keep_qualifiers
×
UNCOV
95
        result << key.to_s
×
UNCOV
96
        result += flatten_joins(val)
×
UNCOV
97
      end
×
98
    # elsif arg.is_a?(Array)
UNCOV
99
    when Array
×
UNCOV
100
      result += arg.map { |x| flatten_joins(x) }.flatten
×
UNCOV
101
    else
×
UNCOV
102
      arg = arg.to_s.sub(/\..*/, "") unless keep_qualifiers
×
UNCOV
103
      result << arg.to_s
×
UNCOV
104
    end
×
UNCOV
105
    result
×
UNCOV
106
  end
×
107

108
  # Figure out which additional conditions we need to connect all the joined
109
  # tables.  Note, +to+ can be an Array and/or tree-like Hash of dependencies.
110
  # (I believe it is identical to how :include is done in ActiveRecord#find.)
UNCOV
111
  def calc_join_conditions(from, to, done = [from.to_s])
×
UNCOV
112
    result = []
×
UNCOV
113
    from = from.to_s
×
UNCOV
114
    case to
×
UNCOV
115
    when Hash
×
UNCOV
116
      to.each do |key, val|
×
UNCOV
117
        result += calc_join_condition(from, key.to_s, done)
×
UNCOV
118
        result += calc_join_conditions(key.to_s, val, done)
×
UNCOV
119
      end
×
UNCOV
120
    when Array
×
UNCOV
121
      result += to.map { |x| calc_join_conditions(from, x, done) }.flatten
×
UNCOV
122
    else
×
UNCOV
123
      result += calc_join_condition(from, to.to_s, done)
×
UNCOV
124
    end
×
UNCOV
125
    result
×
UNCOV
126
  end
×
UNCOV
127
end
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc