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

pulibrary / oawaiver / 40ca2f09-e694-44a5-b909-7cce179b9e67

11 Jul 2024 05:42PM UTC coverage: 0.0% (-80.4%) from 80.383%
40ca2f09-e694-44a5-b909-7cce179b9e67

push

circleci

jrgriffiniii
Trying to expand the RSpec test suite for EmployeesController#ajax_search

0 of 1206 relevant lines covered (0.0%)

0.0 hits per line

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

0.0
/app/models/employee.rb
1
# frozen_string_literal: true
2

3
require "csv"
×
4

5
class Employee < ApplicationRecord
×
6
  # USE THIS when searching for all employees / all employees in a department
7
  # this number should be big greater than both
8
  # * the number of employees with a given common name
9
  # * the number of employees in a given department
10
  @@MAX_EMPLOYEE_MATCH = 200
×
11

12
  self.per_page = 20
×
13

14
  before_validation :clean_strings
×
15
  before_validation :derive_attr_values
×
16
  before_validation :format_unique_id
×
17

18
  validates_presence_of :first_name, :last_name, :unique_id, :netid, :department
×
19
  validates_presence_of :preferred_name, allow_blank: false
×
20
  validates_uniqueness_of :netid, case_sensitive: false
×
21

22
  validates_uniqueness_of :email, case_sensitive: false
×
23
  validates_format_of :email, with: URI::MailTo::EMAIL_REGEXP
×
24

25
  validates_uniqueness_of :unique_id, message: "id has already been taken"
×
26
  validates_format_of :unique_id,
×
27
                      with: /\b\d{9}\z/,
×
28
                      message: "id must be 9 digits"
×
29

30
  # derive preferred_name from first and last_name if it is nil
31
  def derive_attr_values
×
32
    self.preferred_name = "#{last_name}, #{first_name}" if preferred_name.nil?
×
33
  end
×
34

35
  # pad unique+id with 0 if it has less than 9 characters
36
  def format_unique_id
×
37
    uid = self[:unique_id]
×
38
    begin
×
39
      if uid.class == Integer
×
40
        uid = format("%09d", uid)
×
41
      elsif uid.class == String
×
42
        len = uid.length
×
43
        uid = "000000000".slice(0, 9 - uid.length) + uid if len < 9
×
44
      end
×
45
      self.unique_id = uid
×
46
    rescue StandardError => e
×
47
      logger.debug("format_unique_id #{uid} failed with #{e.message}")
×
48
    end
×
49
    self
×
50
  end
×
51

52
  def full_name
×
53
    "#{last_name}, #{first_name}"
×
54
  end
×
55

56
  # ---------------------
57
  # search/solr
58
  # ---------------------
59
  def all_names
×
60
    [first_name, last_name, preferred_name]
×
61
  end
×
62

63
  def order_by_name
×
64
    "#{last_name}, #{first_name} #{id}"
×
65
  end
×
66

67
  searchable do
×
68
    text :department, stored: true
×
69
    string :order_by_name, multiple: false, stored: true
×
70
    text :all_names, stored: true
×
71
  end
×
72

73
  # Reindex using Sunspot
74
  # This is ported from https://github.com/sunspot/sunspot/blob/v2.5.0/sunspot_rails/lib/sunspot/rails/searchable.rb#L257
75
  # Please see https://github.com/sunspot/sunspot/issues/1008
76
  def self.solr_index(opts = {})
×
77
    options = {
×
78
      batch_size: Sunspot.config.indexing.default_batch_size,
×
79
      batch_commit: true,
×
80
      include: sunspot_options[:include],
×
81
      start: opts.delete(:first_id)
×
82
    }.merge(opts)
×
83

84
    if options[:batch_size].to_i.positive?
×
85
      batch_counter = 0
×
86
      batch_options = options.slice(:batch_size, :start)
×
87
      batch_size = batch_options[:batch_size]
×
88

89
      includes(options[:include]).find_in_batches(batch_size: batch_size) do |records|
×
90
        solr_benchmark(options[:batch_size], batch_counter += 1) do
×
91
          Sunspot.index(records.select(&:indexable?))
×
92
          Sunspot.commit if options[:batch_commit]
×
93
        end
×
94
      end
×
95
    else
×
96
      Sunspot.index! includes(options[:include]).select(&:indexable?)
×
97
    end
×
98

99
    # perform a final commit if not committing in batches
100
    Sunspot.commit unless options[:batch_commit]
×
101
  end
×
102

103
  # get all employees with a matching first, last or preferred_name
104
  # return Sunspot::Search object
105
  def self.all_by_name(word)
×
106
    search_by_field(:all_names, word, nil, @@MAX_EMPLOYEE_MATCH)
×
107
  end
×
108

109
  # get all employees with a matching first, last or preferred_name
110
  # paginate results according to given page and per_page parameters
111
  # return Sunspot::Search object
112
  def self.search_by_name(word, page = nil, per_page = nil)
×
113
    search_by_field(:all_names, word, page, per_page)
×
114
  end
×
115

116
  # search for employees from the given department
117
  # paginate results according to given page and per_page parameters
118
  # return Sunspot::Search object
119
  def self.all_by_department(word)
×
120
    search_by_field(:department, word, nil, @@MAX_EMPLOYEE_MATCH)
×
121
  end
×
122

123
  # search for employees from the given department
124
  # paginate results according to given page and per_page parameters
125
  # return Sunspot::Search object
126
  def self.search_by_department(word, page = nil, per_page = nil)
×
127
    search_by_field(:department, word, page, per_page)
×
128
  end
×
129

130
  def self.search_by_field(field, word, page, per_page)
×
131
    per_page ||= self.per_page
×
132
    Employee.search do
×
133
      fulltext word, fields: [field]
×
134
      order_by :order_by_name
×
135
      paginate page: page, per_page: per_page
×
136
    end
×
137
  end
×
138

139
  def self.convert_str(str)
×
140
    str.chars.reject { |c| c.chr == "\u0000" }.join
×
141
  end
×
142

143
  # deletes all existing employees and loads new employees from the given file (.csv format)
144
  # returns { :loaded => number of employees :failed => hash of line numbers to errors
145
  def self.loadCsv(filename, logger)
×
146
    cognosCrossWalk = {
×
147
      "[Firstname]" => :first_name,
×
148
      "[Lastname]" => :last_name,
×
149
      "[KnownAs]" => :preferred_name,
×
150
      "[Department]" => :department,
×
151
      "[Proprietary_ID]" => :unique_id,
×
152
      "[Email]" => :email,
×
153
      "[Username]" => :netid
×
154
    }
×
155

156
    logger.debug "Start loading '#{filename}'"
×
157
    loaded = 0
×
158
    skipped = 0
×
159
    failed = {}
×
160

161
    ActiveRecord::Base.transaction(requires_new: true) do
×
162
      Employee.destroy_all
×
163

164
      headers = nil
×
165
      i = 0
×
166
      CSV.foreach(filename, col_sep: "\t", encoding: "IBM437") do |row|
×
167
        i += 1
×
168
        logger.debug "#{i} #{row}"
×
169

170
        if headers.nil?
×
171
          headers = []
×
172
          row.each do |h|
×
173
            headers << convert_str(h)
×
174
          end
×
175
          logger.info "#{headers.length} Column headers: #{headers.join(',')}"
×
176
          next
×
177
        end
×
178

179
        attrs = {}
×
180
        (0..row.length - 1).each do |c|
×
181
          val = convert_str(row[c])
×
182
          # puts "#{i} #{c}: #{val} #{headers[c]}"
183
          attrs[cognosCrossWalk[headers[c]]] = val if cognosCrossWalk[headers[c]] && val && !val.strip.empty?
×
184
        end
×
185
        logger.debug attrs.inspect
×
186
        if attrs.empty?
×
187
          skipped += 1
×
188
          next
×
189
        end
×
190
        employee = Employee.create(attrs)
×
191
        if employee.save
×
192
          loaded += 1
×
193
          logger.info "Employee.loadCsv #{filename} line #{i}: loaded #{employee}"
×
194
        else
×
195
          failed[i] = [employee.errors.messages]
×
196
          logger.error "Employee.loadCsv #{filename} line: #{i}: #{failed[i]}"
×
197
        end
×
198
      end
×
199

200
      logger.info " Loaded #{loaded} employee records; Failed to read #{failed.length} lines, Skipped #{skipped} lines"
×
201

202
      unless failed.empty?
×
203
        logger.error "Rolling back all changes"
×
204
        raise ActiveRecord::Rollback
×
205
      end
×
206
    end
×
207
    logger.debug "Stop loading '#{filename}'"
×
208

209
    Employee.reindex unless failed.empty?
×
210

211
    { loaded: loaded, failed: failed, skipped: skipped }
×
212
  end
×
213

214
  private
×
215

216
  def to_s
×
217
    "#<Employee::#{preferred_name} #{netid} #{unique_id}>"
×
218
  end
×
219

220
  # ---------------------
221
  # utils
222
  # ---------------------
223
  def clean_strings
×
224
    if changed? || id.nil?
×
225
      attributes.each do |n, _v|
×
226
        self[n] = nil if self[n] == ""
×
227
        self[n] = self[n].gsub(/\s+/, " ").strip if !self[n].nil? && (self[n].class == String)
×
228
      end
×
229
    end
×
230
    self
×
231
  end
×
232
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

© 2025 Coveralls, Inc