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

MushroomObserver / mushroom-observer / 26631654446
97%
main: 97%

Build:
Build:
LAST BUILD BRANCH: nimmo-account-preferences-phlex
DEFAULT BRANCH: main
Ran 29 May 2026 10:21AM UTC
Jobs 1
Files 1036
Run time 2min
Badge
Embed ▾
README BADGES
x

If you need to use a raster PNG badge, change the '.svg' to '.png' in the link

Markdown

Textile

RDoc

HTML

Rst

29 May 2026 10:16AM UTC coverage: 96.508%. Remained the same
26631654446

Pull #4390

github

nimmolo
SpeciesList: sync_projects on the model; controller becomes a thin caller

Moves the per-project add/remove logic from
`SpeciesListsController#update_projects` (+ its `change_project_species_lists`
helper) into a new `SpeciesList#sync_projects(submitted_project_ids,
user:)` method. The controller stays in charge of `flash_notice` (which
the model has no business doing) but the relationship logic — what's
"desired" vs. "current," which projects are even toggleable for the
given user, mutating the join through `Project#add_species_list` /
`#remove_species_list` — now lives on the model where it can be
unit-tested directly.

```ruby
# In SpeciesList:
def sync_projects(submitted_project_ids, user:)
  # Returns [[project, :added | :removed], …] for the caller to flash.
end

# In SpeciesListsController:
def update_projects(spl, submitted_ids)
  changes = spl.sync_projects(submitted_ids, user: @user)
  changes.each { |project, change| flash_project_change(project, change) }
  return if changes.empty?

  flash_notice(:species_list_show_manage_observations_too.t)
end
```

`change_project_species_lists` (the per-change flash + mutation helper)
deletes; the per-change flash collapses into a tiny
`flash_project_change(project, change)`.

Net diff: controller -32 lines, model +34 lines, tests +70 lines.

## Why

Two reasons.

1. Pulling the relationship logic off the controller stops the
   controller from quietly growing every time we need to nudge how
   project sync works. The controller was already at
   `# rubocop:disable Metrics/ClassLength` after #4389; this trims a
   bit and pushes future changes to the right place.
2. Testing the sync semantics from the controller required hitting
   the full HTTP flow (login, params, flash assertions). On the model
   it's straight-up `list.sync_projects([id.to_s], user: user)`
   followed by `assert_includes(list.reload.projects, project)`. The
   5 new model tests cover: nil submission (no-op),
   empty-submission-rem... (continued)
Pull Request #4390: SpeciesList#sync_projects: move project-sync logic to the model

22 of 22 new or added lines in 2 files covered. (100.0%)

39521 of 40951 relevant lines covered (96.51%)

672.87 hits per line

Jobs
ID Job ID Ran Files Coverage
1 26631654446.1 29 May 2026 10:21AM UTC 1036
96.51
GitHub Action Run
Source Files on build 26631654446
  • Tree
  • List 1036
  • Changed 2
  • Source Changed 2
  • Coverage Changed 2
Coverage ∆ File Lines Relevant Covered Missed Hits/Line
  • Back to Repo
  • Github Actions Build #26631654446
  • Pull Request #4390
  • PR Base - main (#26631317870)
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