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

benwbrum / fromthepage / 17387282326

01 Sep 2025 09:13PM UTC coverage: 64.405%. Remained the same
17387282326

push

github

web-flow
4857 - Require rubocop step in CI (#4858)

* 4857 - Require rubocop step in CI

* 4865 - Organize gemfiles

1790 of 3303 branches covered (54.19%)

Branch coverage included in aggregate %.

839 of 1497 new or added lines in 133 files covered. (56.05%)

43 existing lines in 29 files now uncovered.

7928 of 11786 relevant lines covered (67.27%)

103.82 hits per line

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

70.11
/app/controllers/document_sets_controller.rb
1
class DocumentSetsController < ApplicationController
1✔
2
  DEFAULT_WORKS_PER_PAGE = 15
1✔
3

4
  before_action :authorized?
1✔
5
  before_action :set_document_set, only: [ :show, :edit, :update, :destroy ]
1✔
6

7
  respond_to :html
1✔
8

9
  def transfer_form
1✔
10
  end
11

12
  def transfer
1✔
13
    source_set = @collection.document_sets.where(slug: params[:source_set]).first
×
14
    target_set = @collection.document_sets.where(slug: params[:target_set]).first
×
15

16
    if source_set == target_set
×
17
      flash[:error] = t('.source_and_target_can_not_be_the_same')
×
NEW
18
      render action: 'transfer_form', layout: false
×
19
      flash.clear
×
20
    else
×
21
      if params[:status_filter] == 'all'
×
22
        works = source_set.works
×
23
      else
×
24
        works = source_set.works.joins(:work_statistic).where('work_statistics.complete' => 100)
×
25
      end
26

27
      works.each do |work|
×
28
        unless work.document_sets.include? target_set
×
29
          work.document_sets << target_set
×
30
        end
31
        if params[:transfer_type] == 'move'
×
32
          work.document_sets.delete(source_set)
×
33
        end
34
      end
35

NEW
36
      ajax_redirect_to document_sets_path(collection_id: @collection)
×
37
    end
38
  end
39

40
  def index
1✔
41
    page = params[:page].presence || 1
14✔
42

43
    if params[:search]
14✔
44
      @works = @collection.search_works(params[:search]).order(:title).paginate(page: page, per_page: 20)
1✔
45
    else
13✔
46
      @works = @collection.works.order(:title).paginate(page: page, per_page: 20)
13✔
47
    end
48
  end
49

50
  def show
1✔
51
    @collection = @document_set.collection
×
52
  end
53

54
  def new
1✔
55
    @document_set = DocumentSet.new
3✔
56
    @document_set.collection = @collection
3✔
57
    respond_with(@document_set)
3✔
58
  end
59

60
  def edit
1✔
61
    respond_with(@document_set)
×
62
  end
63

64
  def edit_set_collaborators
1✔
65
    @collaborators = @document_set.collaborators
3✔
66
    @noncollaborators = User.where.not(id: @collaborators.select(:id)).order(:display_name).limit(100)
3✔
67
  end
68

69
  def search_collaborators
1✔
70
    query = "%#{params[:term].to_s.downcase}%"
×
NEW
71
    excluded_ids = @document_set.collaborators.pluck(:id) + [ @document_set.owner.id ]
×
72
    users = User.where('LOWER(real_name) LIKE :search OR LOWER(email) LIKE :search', search: query)
×
73
                .where.not(id: excluded_ids)
74
                .limit(100)
75

76
    render json: { results: users.map { |u| { text: "#{u.display_name} #{u.email}", id: u.id } } }
×
77
  end
78

79
  def create
1✔
80
    @document_set = DocumentSet.new(document_set_params)
3✔
81
    if current_user.account_type != 'Staff'
3✔
82
      @document_set.owner = current_user
3✔
83
    else
×
NEW
84
      extant_collection = current_user.all_owner_collections.detect { |c| c.owner.account_type != 'Staff' }
×
85
      @document_set.owner = extant_collection.owner
×
86
    end
87
    if @document_set.save
3✔
88
      flash[:notice] = t('.document_created')
3✔
89
      ajax_redirect_to collection_settings_path(@document_set.owner, @document_set)
3✔
90
    else
×
91
      render action: 'new'
×
92
    end
93
  end
94

95
  def assign_works
1✔
96
    set_work_map = params.to_unsafe_hash[:work_assignment]
1✔
97
    set_work_map&.each_key do |work_id|
1!
98
      work = @collection.works.find(work_id)
7✔
99
      work.document_sets.clear
7✔
100
      set_work_map[work_id].each_pair do |set_id, add_set|
7✔
101
        work.document_sets << @collection.document_sets.find(set_id) if add_set == 'true'
14✔
102
      end
103
    end
104

105
    # set next untranscribed page for each set now that works may have been added or removed
106
    @collection.document_sets.each(&:set_next_untranscribed_page)
1✔
107

108
    redirect_to action: :index, collection_id: @collection.id, page: params[:page]
1✔
109
  end
110

111
  def assign_to_set
1✔
112
    unless @collection
×
113
      @collection = DocumentSet.friendly.find(params[:collection_id])
×
114
    end
NEW
115
    new_ids = params[:work].keys.map { |id| id.to_i }
×
116
    ids = @collection.work_ids + new_ids
×
117
    @collection.work_ids = ids
×
118
    @collection.save!
×
119
    redirect_to collection_works_list_path(@collection.owner, @collection)
×
120
  end
121

122
  def update_works
1✔
123
    document_set = DocumentSet.friendly.find(update_works_params[:document_set_id])
3✔
124
    @result = DocumentSet::UpdateWorks.new(
3✔
125
      document_set: document_set,
126
      work_params: update_works_params[:works]
127
    ).call
128

129
    respond_to(&:turbo_stream)
3✔
130
  end
131

132
  def remove_from_set
1✔
133
    @collection = DocumentSet.friendly.find(params[:collection_id])
×
NEW
134
    ids = params[:work].keys.map { |id| id.to_i }
×
135
    new_ids = @collection.work_ids - ids
×
136
    @collection.work_ids = new_ids
×
137
    @collection.save!
×
138
    redirect_to collection_works_list_path(@collection.owner, @collection)
×
139
  end
140

141
  def update
1✔
142
    @result = DocumentSet::Update.new(
9✔
143
      document_set: @document_set,
144
      document_set_params: document_set_params,
145
      user: current_user
146
    ).call
147

148
    @document_set = @result.document_set
9✔
149

150
    respond_to do |format|
9✔
151
      template = case params[:scope]
9✔
152
      when 'edit_privacy'
2✔
153
                   @collaborators = @document_set.collaborators
2✔
154
                   @works_to_restrict_count = works_to_restrict_count
2✔
155
                   'document_sets/update_privacy'
2✔
156
      else
7✔
157
                   'document_sets/update_general'
7✔
158
      end
159

160
      format.turbo_stream { render template }
18✔
161
    end
162
  end
163

164
  def settings
1✔
165
    @document_set ||= @collection
9✔
166
  end
167

168
  def settings_privacy
1✔
169
    @document_set ||= @collection
3✔
170
    @collaborators = @document_set.collaborators
3✔
171
    @works_to_restrict_count = works_to_restrict_count
3✔
172
  end
173

174
  def settings_works
1✔
175
    filtered_set_works
5✔
176
    @document_set ||= @collection
5✔
177

178
    respond_to do |format|
5✔
179
      format.html
5✔
180
      format.turbo_stream
5✔
181
    end
182
  end
183

184
  def add_set_collaborator
1✔
185
    collaborator = User.find(params[:collaborator_id])
2✔
186
    @collection.collaborators << collaborator
2✔
187
    if collaborator.notification.add_as_collaborator && SMTP_ENABLED
2✔
188
      begin
1✔
189
        UserMailer.collection_collaborator(collaborator, @collection).deliver!
1✔
190
      rescue StandardError => e
191
        print "SMTP Failed: Exception: #{e.message}"
×
192
      end
193
    end
194

195
    redirect_to collection_edit_set_collaborators_path(@collection.owner, @collection, @document_set)
2✔
196
  end
197

198
  def remove_set_collaborator
1✔
199
    collaborator = User.find(params[:collaborator_id])
×
200
    @collection.collaborators.delete(collaborator)
×
201

202
    redirect_to collection_edit_set_collaborators_path(@collection.owner, @collection, @document_set)
×
203
  end
204

205
  def destroy
1✔
206
    @document_set.destroy
3✔
207
    redirect_to action: 'index', collection_id: @document_set.collection_id
3✔
208
  end
209

210
  private
1✔
211

212
  def authorized?
1✔
213
    unless user_signed_in? && @collection && current_user.like_owner?(@collection)
59✔
214
      ajax_redirect_to dashboard_path
1✔
215
    end
216
  end
217

218
  def set_document_set
1✔
219
    unless (defined? @document_set) && @document_set
12✔
220
      id = params[:document_set_id] || params[:id]
9✔
221
      @document_set = DocumentSet.friendly.find(id)
9✔
222
    end
223
  end
224

225
  def document_set_params
1✔
226
    params.require(:document_set).permit(:visibility, :owner_user_id, :collection_id, :title, :description, :picture, :slug)
12✔
227
  end
228

229
  def filtered_set_works
1✔
230
    @ordering = (params[:order] || 'ASC').downcase.to_sym
5✔
231
    @ordering = [ :asc, :desc ].include?(@ordering) ? @ordering : :desc
5!
232

233
    set_works = @collection.works
5✔
234
    collection_works = @collection.collection.works
5✔
235

236
    works_scope = if params[:show] == 'included'
5✔
237
                    set_works
1✔
238
    elsif params[:show] == 'not_included'
4✔
239
                    collection_works.where.not(id: set_works.select(:id))
1✔
240
    else
3✔
241
                    collection_works
3✔
242
    end
243

244
    works_scope = works_scope.includes(:work_statistic).reorder(title: @ordering)
5✔
245

246
    if params[:search]
5✔
247
      query = "%#{params[:search].to_s.downcase}%"
1✔
248
      works_scope = works_scope.where(
1✔
249
        'LOWER(works.title) LIKE :search OR LOWER(works.searchable_metadata) like :search',
250
        search: "%#{query}%"
251
      )
252
    end
253

254
    works_scope = works_scope.distinct.paginate(page: params[:page], per_page: DEFAULT_WORKS_PER_PAGE)
5✔
255
    @works = works_scope
5✔
256
    @set_work_ids = set_works.pluck(:id)
5✔
257
  end
258

259
  def update_works_params
1✔
260
    params.permit(:document_set_id, works: {})
6✔
261
  end
262

263
  def works_to_restrict_count
1✔
264
    @document_set.works
5✔
265
                 .joins(:work_statistic)
266
                 .where(work_statistics: { complete: 100 }, restrict_scribes: false)
267
                 .count
268
  end
269
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