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

MushroomObserver / mushroom-observer / 14182296035

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

push

github

web-flow
Merge pull request #2859 from MushroomObserver/query-AR-comments

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%)

586.46 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
  # This filters misspellings only if the param was not passed.
71
  def filter_misspellings_for_name_queries
1✔
72
    return if model != Name || !params[:misspellings].nil?
46✔
73

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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