• 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

30.52
/app/classes/query/modules/ordering.rb
1
# frozen_string_literal: true
2

3
module Query::Modules::Ordering
1✔
4
  def initialize_order
1✔
5
    # Let callers explicitly send in an order statement.
6
    # This is not sanitized or validated.
UNCOV
7
    if params[:order].present?
×
UNCOV
8
      self.order = params[:order]
×
UNCOV
9
      return
×
10
    end
11

UNCOV
12
    initialize_order_by_param
×
13
  end
14

15
  # Let queries define custom order spec in "order", but have explicitly
16
  # passed-in "order_by" parameter take precedence. If neither `order` nor
17
  # `order_by` is given, then fall back on the "default_order" finally.
18
  def initialize_order_by_param
1✔
UNCOV
19
    order_by = params[:order_by]
×
UNCOV
20
    return unless order_by || order.blank?
×
21

UNCOV
22
    order_by ||= default_order
×
UNCOV
23
    order_by = order_by.dup
×
UNCOV
24
    reverse = order_by.to_s.sub!(/^reverse_/, "")
×
UNCOV
25
    result = initialize_order_specs(order_by)
×
UNCOV
26
    self.order = reverse ? reverse_order(result) : result
×
27
  end
28

29
  def initialize_order_specs(order_by)
1✔
UNCOV
30
    sorting_method = "order_by_#{order_by}"
×
UNCOV
31
    unless ::Query::Modules::Ordering.private_method_defined?(
×
32
      sorting_method
33
    )
34
      raise(
×
35
        "Can't figure out how to sort #{model.name.pluralize} by :#{order_by}."
36
      )
37
    end
38

UNCOV
39
    send(sorting_method, model)
×
40
  end
41

42
  def reverse_order(order)
1✔
UNCOV
43
    order.gsub(/(\s)(ASC|DESC)(,|\Z)/) do
×
UNCOV
44
      Regexp.last_match(1) +
×
45
        (Regexp.last_match(2) == "ASC" ? "DESC" : "ASC") +
46
        Regexp.last_match(3)
47
    end
48
  end
49

50
  #####################
51

52
  private
1✔
53

54
  ####### methods dispatched from initialize_order_specs
55

56
  def order_by_accession_number(model)
1✔
UNCOV
57
    return unless model.column_names.include?("accession_number")
×
58

UNCOV
59
    "#{model.table_name}.accession_number ASC"
×
60
  end
61

62
  def order_by_box_area(_model)
1✔
UNCOV
63
    "locations.box_area DESC"
×
64
  end
65

66
  def order_by_code(_model)
1✔
UNCOV
67
    where << "herbaria.code != ''"
×
UNCOV
68
    "herbaria.code ASC"
×
69
  end
70

71
  def order_by_code_then_date(_model)
1✔
UNCOV
72
    "field_slips.code ASC, field_slips.created_at DESC, " \
×
73
    "field_slips.id DESC"
74
  end
75

76
  def order_by_code_then_name(_model)
1✔
UNCOV
77
    "IF(herbaria.code = '', '~', herbaria.code) ASC, herbaria.name ASC"
×
78
  end
79

80
  def order_by_confidence(model)
1✔
UNCOV
81
    if model == Image
×
UNCOV
82
      add_join(:observation_images, :observations)
×
UNCOV
83
      "observations.vote_cache DESC"
×
UNCOV
84
    elsif model == Observation
×
UNCOV
85
      "observations.vote_cache DESC"
×
86
    end
87
  end
88

89
  def order_by_contribution(model)
1✔
UNCOV
90
    "users.contribution DESC" if model == User
×
91
  end
92

93
  def order_by_copyright_holder(model)
1✔
UNCOV
94
    return unless model.column_names.include?("copyright_holder")
×
95

UNCOV
96
    "#{model.table_name}.copyright_holder ASC"
×
97
  end
98

99
  def order_by_created_at(model)
1✔
UNCOV
100
    return unless model.column_names.include?("created_at")
×
101

UNCOV
102
    "#{model.table_name}.created_at DESC"
×
103
  end
104

105
  def order_by_date(model)
1✔
UNCOV
106
    if model.column_names.include?("when")
×
UNCOV
107
      "#{model.table_name}.when DESC"
×
UNCOV
108
    elsif model.column_names.include?("created_at")
×
UNCOV
109
      "#{model.table_name}.created_at DESC"
×
110
    end
111
  end
112

113
  def order_by_herbarium_label(_model)
1✔
UNCOV
114
    "herbarium_records.initial_det ASC, " \
×
115
    "herbarium_records.accession_number ASC"
116
  end
117

118
  def order_by_herbarium_name(_model)
1✔
UNCOV
119
    add_join(:herbaria)
×
UNCOV
120
    "herbaria.name ASC"
×
121
  end
122

123
  # (for testing)
124
  def order_by_id(model)
1✔
UNCOV
125
    "#{model.table_name}.id ASC"
×
126
  end
127

128
  def order_by_image_quality(model)
1✔
UNCOV
129
    "images.vote_cache DESC" if model == Image
×
130
  end
131

132
  def order_by_initial_det(model)
1✔
UNCOV
133
    return unless model.column_names.include?("initial_det")
×
134

UNCOV
135
    "#{model.table_name}.initial_det ASC"
×
136
  end
137

138
  def order_by_last_login(model)
1✔
UNCOV
139
    return unless model.column_names.include?("last_login")
×
140

UNCOV
141
    "#{model.table_name}.last_login DESC"
×
142
  end
143

144
  def order_by_location(model)
1✔
UNCOV
145
    return unless model.column_names.include?("location_id")
×
146

147
    # Join Users with null locations, else join records with locations
UNCOV
148
    model == User ? add_join(:locations!) : add_join(:locations)
×
UNCOV
149
    order_locations_by_name
×
150
  end
151

152
  def order_by_login(model)
1✔
UNCOV
153
    "#{model.table_name}.login ASC" if model.column_names.include?("login")
×
154
  end
155

156
  def order_by_name(model)
1✔
UNCOV
157
    order_by_name_method = "order_#{model.name.underscore.pluralize}_by_name"
×
UNCOV
158
    if ::Query::Modules::Ordering.private_method_defined?(
×
159
      order_by_name_method
160
    )
UNCOV
161
      send(order_by_name_method)
×
162
    else
UNCOV
163
      order_other_models_by_name(model)
×
164
    end
165
  end
166

167
  def order_by_name_and_number(_model)
1✔
UNCOV
168
    "collection_numbers.name ASC, collection_numbers.number ASC"
×
169
  end
170

171
  def order_by_num_views(model)
1✔
UNCOV
172
    return unless model.column_names.include?("num_views")
×
173

UNCOV
174
    "#{model.table_name}.num_views DESC"
×
175
  end
176

177
  def order_by_observation(model)
1✔
UNCOV
178
    "observation_id DESC" if model.column_names.include?("observation_id")
×
179
  end
180

181
  def order_by_original_name(model)
1✔
UNCOV
182
    "images.original_name ASC" if model == Image
×
183
  end
184

185
  def order_by_owners_quality(model)
1✔
UNCOV
186
    return unless model == Image
×
187

UNCOV
188
    add_join(:image_votes)
×
UNCOV
189
    where << "image_votes.user_id = images.user_id"
×
UNCOV
190
    "image_votes.value DESC"
×
191
  end
192

193
  def order_by_owners_thumbnail_quality(model)
1✔
UNCOV
194
    return unless model == Observation
×
195

UNCOV
196
    add_join(:"images.thumb_image", :image_votes)
×
UNCOV
197
    where << "images.user_id = observations.user_id"
×
UNCOV
198
    where << "image_votes.user_id = observations.user_id"
×
UNCOV
199
    "image_votes.value DESC, " \
×
200
    "images.vote_cache DESC, " \
201
    "observations.vote_cache DESC"
202
  end
203

204
  def order_by_records(_model)
1✔
205
    # outer_join needed to show herbaria with no records
UNCOV
206
    add_join(:herbarium_records!)
×
UNCOV
207
    self.group = "herbaria.id"
×
UNCOV
208
    "count(herbarium_records.id) DESC"
×
209
  end
210

211
  def order_by_rss_log(model)
1✔
UNCOV
212
    return unless model.column_names.include?("rss_log_id")
×
213

214
    # use cached column if exists, and don't join
215
    # calling index method should include rss_logs
UNCOV
216
    if model.column_names.include?("log_updated_at")
×
UNCOV
217
      "#{model.table_name}.log_updated_at DESC"
×
218
    else
UNCOV
219
      add_join(:rss_logs)
×
UNCOV
220
      "rss_logs.updated_at DESC"
×
221
    end
222
  end
223

224
  def order_by_summary(model)
1✔
UNCOV
225
    return unless model.column_names.include?("summary")
×
226

UNCOV
227
    "#{model.table_name}.summary ASC"
×
228
  end
229

230
  def order_by_thumbnail_quality(model)
1✔
UNCOV
231
    return unless model == Observation
×
232

UNCOV
233
    add_join(:"images.thumb_image")
×
UNCOV
234
    "images.vote_cache DESC, observations.vote_cache DESC"
×
235
  end
236

237
  def order_by_title(model)
1✔
UNCOV
238
    "#{model.table_name}.title ASC" if model.column_names.include?("title")
×
239
  end
240

241
  def order_by_updated_at(model)
1✔
UNCOV
242
    return unless model.column_names.include?("updated_at")
×
243

UNCOV
244
    "#{model.table_name}.updated_at DESC"
×
245
  end
246

247
  def order_by_url(model)
1✔
UNCOV
248
    "external_links.url ASC" if model == ExternalLink
×
249
  end
250

251
  def order_by_user(_model)
1✔
UNCOV
252
    add_join(:users)
×
UNCOV
253
    'IF(users.name = "" OR users.name IS NULL, users.login, users.name) ASC'
×
254
  end
255

256
  def order_by_where(model)
1✔
UNCOV
257
    "#{model.table_name}.where ASC" if model.column_names.include?("where")
×
258
  end
259

260
  ####### methods dispatched from order_by_name
261

262
  def order_images_by_name
1✔
UNCOV
263
    add_join(:observation_images, :observations)
×
UNCOV
264
    add_join(:observations, :names)
×
UNCOV
265
    self.group = "images.id"
×
UNCOV
266
    "MIN(names.sort_name) ASC, images.when DESC"
×
267
  end
268

269
  def order_location_descriptions_by_name
1✔
UNCOV
270
    add_join(:locations)
×
UNCOV
271
    "locations.name ASC, location_descriptions.created_at ASC"
×
272
  end
273

274
  def order_locations_by_name
1✔
UNCOV
275
    if User.current_location_format == "scientific"
×
UNCOV
276
      "locations.scientific_name ASC"
×
277
    else
UNCOV
278
      "locations.name ASC"
×
279
    end
280
  end
281

282
  def order_name_descriptions_by_name
1✔
UNCOV
283
    add_join(:names)
×
UNCOV
284
    "names.sort_name ASC, name_descriptions.created_at ASC"
×
285
  end
286

287
  def order_names_by_name
1✔
UNCOV
288
    "names.sort_name ASC"
×
289
  end
290

291
  def order_observations_by_name
1✔
UNCOV
292
    add_join(:names)
×
UNCOV
293
    "names.sort_name ASC, observations.when DESC"
×
294
  end
295

296
  def order_other_models_by_name(model)
1✔
UNCOV
297
    if model.column_names.include?("name")
×
UNCOV
298
      "#{model.table_name}.name ASC"
×
UNCOV
299
    elsif model.column_names.include?("title")
×
UNCOV
300
      "#{model.table_name}.title ASC"
×
301
    end
302
  end
303
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