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

MushroomObserver / mushroom-observer / 14180706403

31 Mar 2025 08:21PM UTC coverage: 93.72% (-0.3%) from 93.997%
14180706403

Pull #2859

github

nimmolo
improve comments, names
Pull Request #2859: First Query conversion: Comments

179 of 272 new or added lines in 6 files covered. (65.81%)

5 existing lines in 1 file now uncovered.

27834 of 29699 relevant lines covered (93.72%)

610.56 hits per line

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

61.18
/app/classes/query/scope_modules/initialization.rb
1
# frozen_string_literal: true
2

3
# Helper methods for turning Query parameters into AR conditions.
4
module Query::ScopeModules::Initialization
1✔
5
  attr_accessor :scopes, :last_query
1✔
6

7
  def initialized?
1✔
8
    @initialized ? true : false
313✔
9
  end
10

11
  def initialize_query
1✔
12
    @initialized = true
46✔
13
    @scopes      = model
46✔
14
    initialize_scopes
46✔
15
    @last_query = sql
46✔
16
  end
17

18
  def sql
1✔
19
    initialize_query unless initialized?
71✔
20

21
    @sql = query.to_sql
71✔
22
  end
23

24
  def query
1✔
25
    initialize_query unless initialized?
71✔
26

27
    @query = scopes.all
71✔
28
  end
29

30
  def initialize_scopes
1✔
31
    initialize_parameter_set
46✔
32
    filter_misspellings_for_name_queries
46✔
33
    send_rss_log_content_filters_to_subqueries
46✔
34
    add_default_order_if_none_specified
46✔
35
  end
36

37
  # For transition only
38
  def initialize_non_nil_defaults; end
1✔
39

40
  def initialize_parameter_set
1✔
41
    sendable_params.each do |param, val|
46✔
42
      next if (param != :id_in_set && skippable_values.include?(val.to_s)) ||
58✔
43
              (param == :id_in_set && val.nil?) # keep empty array
58✔
44

45
      @scopes = if val.is_a?(Hash)
58✔
46
                  @scopes.send(param, **val)
5✔
47
                else
48
                  @scopes.send(param, val)
53✔
49
                end
50
    end
51
  end
52

53
  # We don't `compact` sendable_params, in order to keep empty arrays for
54
  # `:id_in_set`. We also do want `false` values, so we can't check `blank?`
55
  def skippable_values
1✔
56
    @skippable_values = ["[]", "{}", "", nil].freeze
50✔
57
  end
58

59
  # For RssLogs, remove any content filter params before passing to scopes
60
  # since they're already handled in subqueries above.
61
  # Otherwise, these are the `scope_parameters` defined in Query::Base.
62
  def sendable_params
1✔
63
    sendable = params.slice(*scope_parameters)
46✔
64
    return sendable unless model == RssLog
46✔
65

NEW
66
    sendable.except(*content_filter_parameters.keys)
×
67
  end
68

69
  # Most name queries are filtered to remove misspellings.
70
  def filter_misspellings_for_name_queries
1✔
71
    return if model != Name || !params[:misspellings].nil?
46✔
72

NEW
73
    @scopes = @scopes.with_correct_spelling
×
74
  end
75

76
  # In the case of RssLogs, send any content filter params to subqueries.
77
  # (Content filters may add params to RssLog queries that RssLog scopes
78
  # can't handle, because they're intended for one or more related models.)
79
  # Some params may go into more than one subquery if >1 `type` requested.
80
  def send_rss_log_content_filters_to_subqueries
1✔
81
    return if model != RssLog || !content_filters_present
46✔
82

NEW
83
    rss_logs_requested_filterable_types.each do |model|
×
NEW
84
      subquery_params = content_filter_subquery_params(model)
×
NEW
85
      if subquery_params.present?
×
NEW
86
        @scopes = @scopes.send(:"#{model.name.downcase}_query",
×
87
                               **subquery_params)
88
      end
89
    end
90
  end
91

92
  # Current types requested on the RssLog page that can have content filters
93
  # applied. Defaults to :all.
94
  def rss_logs_requested_filterable_types
1✔
NEW
95
    types = [:observation, :name, :location]
×
NEW
96
    active_types = case params[:type]
×
97
                   when nil, "", :all, "all"
NEW
98
                     types
×
99
                   when Array
NEW
100
                     params[:type]
×
101
                   when String
NEW
102
                     params[:type].split
×
103
                   end
NEW
104
    active_types.map { |type| type.to_s.camelize.constantize }
×
105
  end
106

107
  # Use Query::Filter.by_model to find any filters relevant to a model.
108
  def content_filter_subquery_params(model)
1✔
NEW
109
    Query::Filter.by_model(model).
×
110
      each_with_object({}) do |fltr, subquery_params|
NEW
111
        next if (val = params[fltr.sym]).to_s == ""
×
112

NEW
113
        subquery_params[fltr.sym] = val
×
114
      end
115
  end
116

117
  def content_filters_present
1✔
NEW
118
    @content_filters_present ||=
×
119
      params.slice(*content_filter_parameters.keys).compact.present?
120
  end
121

122
  def add_default_order_if_none_specified
1✔
123
    return if params[:order_by].present?
46✔
124

125
    @scopes = @scopes.order_by_default
23✔
126
  end
127

128
  # Make a value safe for SQL.
129
  def escape(val)
1✔
NEW
130
    model.connection.quote(val)
×
131
  end
132

133
  # Put together a list of ids for use in a "id IN (1,2,...)" condition.
134
  #
135
  #   set = clean_id_set(name.children)
136
  #   @where << "names.id IN (#{set})"
137
  #
138
  def clean_id_set(ids)
1✔
NEW
139
    set = limited_id_set(ids).map(&:to_s).join(",")
×
NEW
140
    set.presence || "-1"
×
141
  end
142

143
  # array of max of MO.query_max_array unique ids for use with Arel "in"
144
  #    where(<x>.in(limited_id_set(ids)))
145
  def limited_id_set(ids)
1✔
146
    ids.map(&:to_i).uniq[0, MO.query_max_array]
38✔
147
  end
148

149
  # Combine args into one parenthesized condition by ANDing them.
150
  def and_clause(*args)
1✔
NEW
151
    if args.length > 1
×
152
      # "(#{args.join(" AND ")})"
NEW
153
      starting = args.shift
×
NEW
154
      args.reduce(starting) { |result, arg| result.and(arg) }
×
155
    else
NEW
156
      args.first
×
157
    end
158
  end
159

160
  # Combine args into one parenthesized condition by ORing them.
161
  def or_clause(*args)
1✔
NEW
162
    if args.length > 1
×
163
      # "(#{args.join(" OR ")})"
NEW
164
      starting = args.shift
×
NEW
165
      args.reduce(starting) { |result, arg| result.or(arg) }
×
166
    else
NEW
167
      args.first
×
168
    end
169
  end
170

171
  # Add a join condition if it doesn't already exist.  There are two forms:
172
  #
173
  #   # Add join from root table to the given table:
174
  #   add_join(:observations)
175
  #     => join << :observations
176
  #
177
  #   # Add join from one table to another: (will create join from root to
178
  #   # first table if it doesn't already exist)
179
  #   add_join(:observations, :names)
180
  #     => join << {:observations => :names}
181
  #   add_join(:names, :descriptions)
182
  #     => join << {:observations => {:names => :descriptions}}
183
  #
184
  # def add_join(*)
185
  #   @join.add_leaf(*)
186
  # end
187

188
  # Same as add_join but can provide chain of more than two tables.
189
  # def add_joins(*args)
190
  #   if args.length == 1
191
  #     @join.add_leaf(args[0])
192
  #   elsif args.length > 1
193
  #     while args.length > 1
194
  #       @join.add_leaf(args[0], args[1])
195
  #       args.shift
196
  #     end
197
  #   end
198
  # end
199

200
  # Safely add to :where in +args+. Dups <tt>args[:where]</tt>,
201
  # casts it into an Array, and returns the new Array.
202
  def extend_where(args)
1✔
NEW
203
    extend_arg(args, :where)
×
204
  end
205

206
  # Safely add to :join in +args+.  Dups <tt>args[:join]</tt>, casts it into
207
  # an Array, and returns the new Array.
208
  def extend_join(args)
1✔
NEW
209
    extend_arg(args, :join)
×
210
  end
211

212
  # Safely add to +arg+ in +args+.  Dups <tt>args[arg]</tt>, casts it into
213
  # an Array, and returns the new Array.
214
  def extend_arg(args, arg)
1✔
NEW
215
    args[arg] = case old_arg = args[arg]
×
216
                when Symbol, String
NEW
217
                  [old_arg]
×
218
                when Array
NEW
219
                  old_arg.dup
×
220
                else
NEW
221
                  []
×
222
                end
223
  end
224
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