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

MushroomObserver / mushroom-observer / 14145379140

29 Mar 2025 11:58AM UTC coverage: 84.27% (-9.7%) from 93.985%
14145379140

Pull #2808

github

nimmolo
Handle rss_log content filters with subqueries
Pull Request #2808: Convert Query to AR scopes

477 of 2306 new or added lines in 78 files covered. (20.69%)

1381 existing lines in 27 files now uncovered.

26562 of 31520 relevant lines covered (84.27%)

536.24 hits per line

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

60.54
/app/classes/query/scope_modules/ordering.rb
1
# frozen_string_literal: true
2

3
module Query::ScopeModules::Ordering
1✔
4
  def initialize_order
1✔
5
    by = params[:order_by]
2,111✔
6
    # Let queries define custom order spec in "order", but have explicitly
7
    # passed-in "by" parameter take precedence.  If neither is given, then
8
    # fall back on the "default_order" finally.
9
    return unless by || order.blank?
2,111✔
10
    return if by == "none"
2,111✔
11

12
    order_by ||= default_order
2,111✔
13
    order_by = order_by.dup.to_s
2,111✔
14
    reverse = order_by.sub!(/^reverse_/, "")
2,111✔
15
    initialize_order_specs(order_by)
2,111✔
16
    add_order_disambiguation
2,111✔
17
    @scopes = @scopes.reverse_order if reverse
2,111✔
18
  end
19

20
  def initialize_order_specs(order_by)
1✔
21
    return if params[:id_in_set].present?
2,111✔
22

23
    sorting_method = "order_by_#{order_by}"
1,929✔
24
    unless Query::ScopeModules::Ordering.private_method_defined?(sorting_method)
1,929✔
NEW
25
      raise(
×
26
        "Can't figure out how to sort #{model.name.pluralize} by :#{order_by}."
27
      )
28
    end
29
    send(sorting_method, model)
1,929✔
30
  end
31

32
  def add_order_disambiguation
1✔
33
    return if params[:id_in_set].present?
2,111✔
34

35
    @scopes = @scopes.order(model.arel_table[:id].desc)
1,929✔
36
  end
37

38
  #####################
39

40
  private
1✔
41

42
  ####### methods dispatched from initialize_order_specs
43

44
  def order_by_accession_number(model)
1✔
NEW
45
    return unless model == HerbariumRecord
×
46

NEW
47
    @scopes = @scopes.order(HerbariumRecord[:accession_number].asc)
×
48
  end
49

50
  def order_by_box_area(_model)
1✔
51
    # "locations.box_area DESC"
NEW
52
    @scopes = @scopes.order(Location[:box_area].desc)
×
53
  end
54

55
  def order_by_code(_model)
1✔
56
    # where << "herbaria.code != ''"
57
    # "herbaria.code ASC"
NEW
58
    @scopes = @scopes.where(Herbarium[:code].not_eq(nil)).
×
59
              order(Herbarium[:code].asc)
60
  end
61

62
  def order_by_code_then_date(_model)
1✔
63
    return unless model == FieldSlip
12✔
64

65
    # "field_slips.code ASC, field_slips.created_at DESC, " \
66
    # "field_slips.id DESC"
67
    @scopes = @scopes.order(FieldSlip[:code].asc, FieldSlip[:created_at].desc)
12✔
68
  end
69

70
  def order_by_code_then_name(_model)
1✔
71
    # "IF(herbaria.code = '', '~', herbaria.code) ASC, herbaria.name ASC"
NEW
72
    @scopes = @scopes.order(
×
73
      Herbarium[:code].eq(nil).
74
        when(true).then(Arel::Nodes.build_quoted("~")).
75
        when(false).then(Herbarium[:code]).asc, Herbarium[:name].asc
76
    )
77
  end
78

79
  def order_by_confidence(model)
1✔
NEW
80
    return unless [Image, Observation].include?(model)
×
81

82
    # add_join(:observation_images, :observations) if model == Image
NEW
83
    @scopes = @scopes.joins(observation_images: :observation) if model == Image
×
84
    # "observations.vote_cache DESC"
NEW
85
    @scopes = @scopes.order(Observation[:vote_cache].desc)
×
86
  end
87

88
  def order_by_contribution(model)
1✔
NEW
89
    return unless model == User
×
90

91
    # "users.contribution DESC" if model == User
NEW
92
    @scopes = @scopes.order(User[:contribution].desc)
×
93
  end
94

95
  def order_by_copyright_holder(model)
1✔
NEW
96
    return unless model.column_names.include?("copyright_holder")
×
97

98
    # "#{model.table_name}.copyright_holder ASC"
NEW
99
    @scopes = @scopes.order(model.arel_table[:copyright_holder].asc)
×
100
  end
101

102
  def order_by_created_at(model)
1✔
103
    return unless model.column_names.include?("created_at")
298✔
104

105
    # "#{model.table_name}.created_at DESC"
106
    @scopes = @scopes.order(model.arel_table[:created_at].desc)
298✔
107
  end
108

109
  def order_by_date(model)
1✔
110
    if model.column_names.include?("when")
648✔
111
      # "#{model.table_name}.when DESC"
112
      @scopes = @scopes.order(model.arel_table[:when].desc)
648✔
NEW
113
    elsif model.column_names.include?("created_at")
×
114
      # "#{model.table_name}.created_at DESC"
NEW
115
      @scopes = @scopes.order(model.arel_table[:created_at].desc)
×
116
    end
117
  end
118

119
  def order_by_herbarium_label(_model)
1✔
120
    return unless model == HerbariumRecord
67✔
121

122
    # "herbarium_records.initial_det ASC, " \
123
    # "herbarium_records.accession_number ASC"
124
    @scopes = @scopes.order(HerbariumRecord[:initial_det].asc,
67✔
125
                            HerbariumRecord[:accession_number].asc)
126
  end
127

128
  def order_by_herbarium_name(_model)
1✔
NEW
129
    return unless model == HerbariumRecord
×
130

131
    # add_join(:herbaria)
132
    # "herbaria.name ASC"
NEW
133
    @scopes = @scopes.joins(:herbarium).order(Herbarium[:name].asc)
×
134
  end
135

136
  # (for testing)
137
  def order_by_id(model)
1✔
138
    # "#{model.table_name}.id ASC"
NEW
139
    @scopes = @scopes.order(model.arel_table[:id].asc)
×
140
  end
141

142
  def order_by_image_quality(model)
1✔
NEW
143
    return unless model == Image
×
144

145
    # "images.vote_cache DESC" if model == Image
NEW
146
    @scopes = @scopes.order(Image[:vote_cache].desc)
×
147
  end
148

149
  def order_by_initial_det(model)
1✔
NEW
150
    return unless model == HerbariumRecord
×
151

152
    # "#{model.table_name}.initial_det ASC"
NEW
153
    @scopes = @scopes.order(HerbariumRecord[:initial_det].asc)
×
154
  end
155

156
  def order_by_last_login(model)
1✔
NEW
157
    return unless model == User
×
158

159
    # "#{model.table_name}.last_login DESC"
NEW
160
    @scopes = @scopes.order(User[:last_login].desc)
×
161
  end
162

163
  def order_by_location(model)
1✔
NEW
164
    return unless model.column_names.include?("location_id")
×
165

166
    # Join Users with null locations, else join records with locations
NEW
167
    @scopes = if model == User
×
168
                # add_join(:locations!)
NEW
169
                @scopes.left_outer_joins(:location)
×
170
              else
171
                # add_join(:locations)
NEW
172
                @scopes.joins(:location)
×
173
              end
NEW
174
    order_locations_by_name
×
175
  end
176

177
  def order_by_login(model)
1✔
NEW
178
    return unless model == User
×
179

180
    # "#{model.table_name}.login ASC" if model.column_names.include?("login")
NEW
181
    @scopes = @scopes.order(User[:login].asc)
×
182
  end
183

184
  def order_by_name(model)
1✔
185
    order_by_name_method = "order_#{model.name.underscore.pluralize}_by_name"
680✔
186
    if ::Query::Modules::Ordering.private_method_defined?(
680✔
187
      order_by_name_method
188
    )
189
      send(order_by_name_method)
546✔
190
    else
191
      order_other_models_by_name(model)
134✔
192
    end
193
  end
194

195
  def order_by_name_and_number(_model)
1✔
196
    return unless model == CollectionNumber
44✔
197

198
    # "collection_numbers.name ASC, collection_numbers.number ASC"
199
    @scopes = @scopes.order(CollectionNumber[:name].asc,
44✔
200
                            CollectionNumber[:number].asc)
201
  end
202

203
  def order_by_num_views(model)
1✔
NEW
204
    return unless model.column_names.include?("num_views")
×
205

206
    # "#{model.table_name}.num_views DESC"
NEW
207
    @scopes = @scopes.order(model.arel_table[:num_views].desc)
×
208
  end
209

210
  def order_by_observation(model)
1✔
NEW
211
    return unless model.column_names.include?("observation_id")
×
212

213
    # "observation_id DESC" if model.column_names.include?("observation_id")
NEW
214
    @scopes = @scopes.order(Observation[:id].desc)
×
215
  end
216

217
  def order_by_original_name(model)
1✔
NEW
218
    return unless model == Image
×
219

220
    # "images.original_name ASC" if model == Image
NEW
221
    @scopes = @scopes.order(Image[:original_name].asc)
×
222
  end
223

224
  def order_by_owners_quality(model)
1✔
NEW
225
    return unless model == Image
×
226

227
    # add_join(:image_votes)
228
    # where << "image_votes.user_id = images.user_id"
229
    # "image_votes.value DESC"
NEW
230
    @scopes = @scopes.joins(:image_votes).
×
231
              where(ImageVote[:user_id].eq(Image[:user_id])).
232
              order(ImageVote[:value].desc)
233
  end
234

235
  # rubocop:disable Metrics/AbcSize
236
  def order_by_owners_thumbnail_quality(model)
1✔
NEW
237
    return unless model == Observation
×
238

239
    # add_join(:"images.thumb_image", :image_votes)
240
    # where << "images.user_id = observations.user_id"
241
    # where << "image_votes.user_id = observations.user_id"
242
    # "image_votes.value DESC, " \
243
    # "images.vote_cache DESC, " \
244
    # "observations.vote_cache DESC"
NEW
245
    @scopes = @scopes.joins(images: :image_votes).
×
246
              where(Observation[:thumb_image_id].eq(Image[:id])).
247
              where(Image[:user_id].eq(Observation[:user_id])).
248
              where(ImageVote[:user_id].eq(Observation[:user_id])).
249
              order(ImageVote[:value].desc, Image[:vote_cache].desc,
250
                    Observation[:vote_cache].desc)
251
  end
252
  # rubocop:enable Metrics/AbcSize
253

254
  def order_by_records(_model)
1✔
NEW
255
    return unless model == Herbarium
×
256

257
    # outer_join needed to show herbaria with no records
258
    # add_join(:herbarium_records!)
259
    # self.group = "herbaria.id"
260
    # "count(herbarium_records.id) DESC"
NEW
261
    @scopes = @scopes.left_outer_joins(:herbarium_records).
×
262
              group(Herbarium[:id]).order(HerbariumRecord[:id].count.desc)
263
  end
264

265
  def order_by_rss_log(model)
1✔
NEW
266
    return unless model.column_names.include?("rss_log_id")
×
267

268
    # use cached column if exists, and don't join
269
    # calling index method should include rss_logs
NEW
270
    @scopes = if model.column_names.include?("log_updated_at")
×
271
                # "#{model.table_name}.log_updated_at DESC"
NEW
272
                @scopes.order(model.arel_table[:log_updated_at].desc)
×
273
              else
274
                # add_join(:rss_logs)
275
                # "rss_logs.updated_at DESC"
NEW
276
                @scopes.joins(:rss_log).order(RssLog[:updated_at].desc)
×
277
              end
278
  end
279

280
  def order_by_summary(model)
1✔
NEW
281
    return unless model.column_names.include?("summary")
×
282

283
    # "#{model.table_name}.summary ASC"
NEW
284
    @scopes = @scopes.order(model.arel_table[:summary].asc)
×
285
  end
286

287
  def order_by_thumbnail_quality(model)
1✔
NEW
288
    return unless model == Observation
×
289

290
    # add_join(:"images.thumb_image")
291
    # "images.vote_cache DESC, observations.vote_cache DESC"
NEW
292
    @scopes = @scopes.joins(:images).
×
293
              where(Observation[:thumb_image_id].eq(Image[:id])).
294
              order(Image[:vote_cache].desc, Observation[:vote_cache].desc)
295
  end
296

297
  def order_by_title(model)
1✔
298
    return unless model.column_names.include?("title")
74✔
299

300
    # "#{model.table_name}.title ASC" if model.column_names.include?("title")
301
    @scopes = @scopes.order(model.arel_table[:title].asc)
74✔
302
  end
303

304
  def order_by_updated_at(model)
1✔
305
    return unless model.column_names.include?("updated_at")
83✔
306

307
    # "#{model.table_name}.updated_at DESC"
308
    @scopes = @scopes.order(model.arel_table[:updated_at].desc)
83✔
309
  end
310

311
  def order_by_url(model)
1✔
312
    return unless model == ExternalLink
23✔
313

314
    # "external_links.url ASC" if model == ExternalLink
315
    @scopes = @scopes.order(ExternalLink[:url].asc)
23✔
316
  end
317

318
  def order_by_user(_model)
1✔
319
    # add_join(:users)
320
    # 'IF(users.name = "" OR users.name IS NULL, users.login, users.name) ASC'
NEW
321
    @scopes = @scopes.joins(:user).
×
322
              order(User[:name].
323
                    when(nil).then(User[:login]).when("").then(User[:login]).
324
                    else(User[:name]).asc)
325
  end
326

327
  def order_by_where(model)
1✔
NEW
328
    return unless model.column_names.include?("where")
×
329

330
    # "#{model.table_name}.where ASC" if model.column_names.include?("where")
NEW
331
    @scopes = @scopes.order(model.arel_table[:where].asc)
×
332
  end
333

334
  ####### methods dispatched from order_by_name
335

336
  def order_images_by_name
1✔
337
    # add_join(:observation_images, :observations)
338
    # add_join(:observations, :names)
339
    # self.group = "images.id"
340
    # "MIN(names.sort_name) ASC, images.when DESC"
NEW
341
    @scopes = @scopes.joins(observation_images: { observation: :name }).
×
342
              group(Image[:id]).
343
              order(Name[:sort_name].min.asc, Image[:when].desc)
344
  end
345

346
  def order_location_descriptions_by_name
1✔
347
    # add_join(:locations)
348
    # "locations.name ASC, location_descriptions.created_at ASC"
349
    @scopes = @scopes.joins(:location).
44✔
350
              order(Location[:name].asc, LocationDescription[:created_at].asc)
351
  end
352

353
  def order_locations_by_name
1✔
354
    @scopes = if User.current_location_format == "scientific"
128✔
355
                # "locations.scientific_name ASC"
356
                @scopes.order(Location[:scientific_name].asc)
1✔
357
              else
358
                # "locations.name ASC"
359
                @scopes.order(Location[:name].asc)
127✔
360
              end
361
  end
362

363
  def order_name_descriptions_by_name
1✔
364
    # add_join(:names)
365
    # "names.sort_name ASC, name_descriptions.created_at ASC"
366
    @scopes = @scopes.joins(:name).
58✔
367
              order(Name[:sort_name].asc, NameDescription[:created_at].asc)
368
  end
369

370
  def order_names_by_name
1✔
371
    # "names.sort_name ASC"
372
    @scopes = @scopes.order(Name[:sort_name].asc)
316✔
373
  end
374

375
  def order_observations_by_name
1✔
376
    # add_join(:names)
377
    # "names.sort_name ASC, observations.when DESC"
NEW
378
    @scopes = @scopes.joins(:name).
×
379
              order(Name[:sort_name].asc, Observation[:when].desc)
380
  end
381

382
  def order_other_models_by_name(model)
1✔
383
    if model.column_names.include?("name")
134✔
384
      # "#{model.table_name}.name ASC"
385
      @scopes = @scopes.order(model.arel_table[:name].asc)
134✔
NEW
386
    elsif model.column_names.include?("title")
×
387
      # "#{model.table_name}.title ASC"
NEW
388
      @scopes = @scopes.order(model.arel_table[:title].asc)
×
389
    end
390
  end
391
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