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

benwbrum / fromthepage / 13528664866

25 Feb 2025 06:48PM UTC coverage: 59.626% (-2.2%) from 61.822%
13528664866

Pull #4471

github

web-flow
Merge 279229e31 into 3b7156fe3
Pull Request #4471: Search test

1548 of 3188 branches covered (48.56%)

Branch coverage included in aggregate %.

84 of 457 new or added lines in 18 files covered. (18.38%)

1 existing line in 1 file now uncovered.

7065 of 11257 relevant lines covered (62.76%)

78.7 hits per line

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

81.6
/app/models/document_set.rb
1
# == Schema Information
2
#
3
# Table name: document_sets
4
#
5
#  id                         :integer          not null, primary key
6
#  default_orientation        :string(255)
7
#  description                :text(65535)
8
#  pct_completed              :integer
9
#  picture                    :string(255)
10
#  slug                       :string(255)
11
#  title                      :string(255)
12
#  visibility                 :integer          default("private"), not null
13
#  works_count                :integer          default(0)
14
#  created_at                 :datetime
15
#  updated_at                 :datetime
16
#  collection_id              :integer
17
#  next_untranscribed_page_id :integer
18
#  owner_user_id              :integer
19
#
20
# Indexes
21
#
22
#  index_document_sets_on_collection_id  (collection_id)
23
#  index_document_sets_on_owner_user_id  (owner_user_id)
24
#  index_document_sets_on_slug           (slug) UNIQUE
25
#
26
class DocumentSet < ApplicationRecord
1✔
27
  include DocumentSetStatistic
1✔
28
  include ElasticDelta
1✔
29

30
  extend FriendlyId
1✔
31
  friendly_id :slug_candidates, use: [:slugged, :history]
1✔
32
  before_save :uniquify_slug
1✔
33
  # validate :slug_uniqueness_across_objects
34

35
  mount_uploader :picture, PictureUploader
1✔
36

37
  belongs_to :owner, class_name: 'User', foreign_key: 'owner_user_id', optional: true
1✔
38
  belongs_to :collection, optional: true
1✔
39
  belongs_to :next_untranscribed_page, foreign_key: 'next_untranscribed_page_id', class_name: 'Page', optional: true
1✔
40

41
  has_many :document_set_works
1✔
42
  has_many :works, -> { order(:title) }, through: :document_set_works
419✔
43
  has_many :pages, through: :works
1✔
44
  has_many :articles, -> { distinct }, through: :works
11✔
45
  has_many :notes, -> { order(created_at: :desc) }, through: :works
39✔
46
  has_many :deeds, -> (document_set) {
1✔
47
    where(work_id: document_set.works.select(:id))
62✔
48
      .includes(:work)
49
      .reorder('deeds.created_at DESC')
50
  }, through: :collection, source: :deeds
51

52
  has_and_belongs_to_many :collaborators, class_name: 'User', join_table: :document_set_collaborators
1✔
53

54
  has_many :bulk_exports, dependent: :delete_all
1✔
55

56
  after_save :set_next_untranscribed_page
1✔
57

58
  validates :title, presence: true, length: { minimum: 3, maximum: 255 }
1✔
59
  validates :slug, format: { with: /[[:alpha:]]/ }
1✔
60

61
  scope :unrestricted, -> { where(visibility: [:public, :read_only]) }
151✔
62
  scope :restricted, -> { where(visibility: [:private]) }
86✔
63

64
  scope :carousel, -> {
1✔
65
    where(pct_completed: [nil, 1..90])
30✔
66
      .joins(:collection)
67
      .where.not(collections: { picture: nil })
68
      .where.not(description: [nil, ''])
69
      .unrestricted
70
      .reorder(Arel.sql('RAND()'))
71
  }
72
  scope :has_intro_block, -> { where.not(description: [nil, '']) }
2✔
73
  scope :not_near_complete, -> { where(pct_completed: [nil, 0..90]) }
1✔
74
  scope :not_empty, -> { where.not(works_count: [0, nil]) }
2✔
75

76
  scope :random_sample, ->(sample_size = 5) do
1✔
77
    carousel
×
78
    reorder(Arel.sql('RAND()')) unless sample_size > 1
×
79
    limit(sample_size).reorder(Arel.sql('RAND()'))
×
80
  end
81

82
  # Docsets get indexed alongside collections but have a prefix added to ID
83
  def as_indexed_json
1✔
84
    return {
NEW
85
      _id: "docset-#{self.id}",
×
86
      permissions_updated: 0,
87
      is_public: self.is_public,
88
      is_docset: true,
89
      intro_block: self.description,
90
      language: self.language,
91
      owner_user_id: self.owner_user_id,
92
      owner_display_name: self.owner&.display_name,
×
93
      collection_id: self.collection_id,
94
      slug: self.slug,
95
      title: self.title
96
    }
97
  end
98

99
  enum visibility: {
1✔
100
    private: 0,
101
    public: 1,
102
    read_only: 2
103
  }, _prefix: :visibility
104

105
  def show_to?(user)
1✔
106
    is_public? || user&.like_owner?(self) || user&.collaborator?(self)
80!
107
  end
108

109
  def intro_block
1✔
110
    description
119✔
111
  end
112

113
  def messageboards_enabled
1✔
114
    false
44✔
115
  end
116

117
  def messageboards_enabled?
1✔
118
    messageboards_enabled
44✔
119
  end
120

121
  def uniquify_slug
1✔
122
    self.slug = "#{slug}-set" if Collection.where(slug: slug).exists?
86!
123
  end
124

125
  delegate :metadata_coverages,          to: :collection
1✔
126
  delegate :enable_spellcheck,           to: :collection
1✔
127
  delegate :reviewers,                   to: :collection
1✔
128
  delegate :facet_configs,               to: :collection
1✔
129
  delegate :text_entry?,                 to: :collection
1✔
130
  delegate :metadata_entry?,             to: :collection
1✔
131
  delegate :metadata_only_entry?,        to: :collection
1✔
132
  delegate :text_and_metadata_entry?,    to: :collection
1✔
133
  delegate :hide_completed,              to: :collection
1✔
134
  delegate :review_workflow,             to: :collection
1✔
135
  delegate :review_type,                 to: :collection
1✔
136
  delegate :user_download,               to: :collection
1✔
137
  delegate :subjects_disabled,           to: :collection
1✔
138
  delegate :editor_buttons,              to: :collection
1✔
139
  delegate :categories,                  to: :collection
1✔
140
  delegate :active?,                     to: :collection
1✔
141
  delegate :footer_block,                to: :collection
1✔
142
  delegate :help,                        to: :collection
1✔
143
  delegate :link_help,                   to: :collection
1✔
144
  delegate :voice_recognition,           to: :collection
1✔
145
  delegate :language,                    to: :collection
1✔
146
  delegate :text_language,               to: :collection
1✔
147
  delegate :field_based,                 to: :collection
1✔
148
  delegate :transcription_fields,        to: :collection
1✔
149
  delegate :metadata_fields,             to: :collection
1✔
150
  delegate :description_instructions,    to: :collection
1✔
151
  delegate :facets_enabled?,             to: :collection
1✔
152
  delegate :api_access,                  to: :collection
1✔
153
  delegate :alphabetize_works,           to: :collection
1✔
154
  delegate :institution_signature,       to: :collection
1✔
155
  delegate :most_recent_deed_created_at, to: :collection
1✔
156

157
  def export_subject_index_as_csv
1✔
158
    subject_link = SubjectExporter::Exporter.new(self)
×
159

160
    subject_link.export
×
161
  end
162

163
  def export_subject_details_as_csv
1✔
164
    subjects = SubjectDetailsExporter::Exporter.new(self)
×
165

166
    subjects.export
×
167
  end
168

169
  def export_subject_distribution_as_csv(subject)
1✔
170
    subjects = SubjectDistributionExporter::Exporter.new(self, subject)
×
171

172
    subjects.export
×
173
  end
174

175
  def supports_document_sets
1✔
176
    false
28✔
177
  end
178

179
  def restricted
1✔
180
    visibility_private?
123✔
181
  end
182

183
  def picture_url(thumb = nil)
1✔
184
    if picture.blank?
16✔
185
      collection.picture.url(thumb)
13✔
186
    else
3✔
187
      picture.url(thumb)
3✔
188
    end
189
  end
190

191
  def set_next_untranscribed_page
1✔
192
    first_work = works.unrestricted.where.not(next_untranscribed_page_id: nil).order_by_incomplete.first
111✔
193
    first_page = first_work&.next_untranscribed_page
111✔
194
    page_id = first_page&.id
111✔
195

196
    update_columns(next_untranscribed_page_id: page_id)
111✔
197
  end
198

199
  def find_next_untranscribed_page_for_user(user)
1✔
200
    return nil unless has_untranscribed_pages?
4✔
201
    return next_untranscribed_page if user.can_transcribe?(next_untranscribed_page.work, self)
2!
202

203
    public = works.unrestricted
×
204
                  .where.not(next_untranscribed_page_id: nil)
205
                  .order_by_incomplete
206

207
    public&.first&.next_untranscribed_page
×
208
  end
209

210
  def has_untranscribed_pages?
1✔
211
    next_untranscribed_page.present?
78✔
212
  end
213

214
  def slug_candidates
1✔
215
    if self.slug
170✔
216
      [:slug]
64✔
217
    else
106✔
218
      [
219
        :title,
106✔
220
        [:title, :id]
221
      ]
222
    end
223
  end
224

225
  def should_generate_new_friendly_id?
1✔
226
    slug_changed? || super
173✔
227
  end
228

229
  def normalize_friendly_id(string)
1✔
230
    super.truncate(240, separator: '-', omission: '').gsub('_', '-')
170✔
231
  end
232

233
  def search_works(search)
1✔
234
    works.where('title LIKE ? OR searchable_metadata like ?', "%#{search}%", "%#{search}%")
×
235
  end
236

237
  def self.search(search)
1✔
238
    sql = "title like ? OR slug LIKE ? OR owner_user_id in (select id from \
5✔
239
           users where owner=1 and display_name like ?)"
240
    where(sql, "%#{search}%", "%#{search}%", "%#{search}%")
5✔
241
  end
242

243
  def default_orientation
1✔
244
    if !self[:default_orientation].nil?
13!
245
      self[:default_orientation]
✔
246
    elsif self[:field_based]
13!
247
      'ttb'
×
248
    else
13✔
249
      'ltr'
13✔
250
    end
251
  end
252

253
  def sc_collection
1✔
254
    # association does not exist for document sets
255
    nil
256
  end
257

258
  def user_help
1✔
259
    collection.owner.help
×
260
  end
261

262
  def is_public
1✔
263
    visibility_public?
33✔
264
  end
265

266
  def is_public?
1✔
267
    visibility_public?
120✔
268
  end
269

270
  public :user_help
1✔
271
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