Compare commits

...
100 Commits
Author SHA1 Message Date
Daniel O'Connor c0eb49aebb Merge pull request #4678 from Growstuff/fix-photo-reindex-error-4629481995101950332
Fix NoMethodError: undefined method 'reindex' for class Photo in specs
2026-06-24 01:45:40 +09:30
google-labs-jules[bot]andCloCkWeRX abd5df606e Fix Photo.reindex errors in specs and controller
- Remove `Photo.reindex` calls from `spec/spec_helper.rb` and feature specs.
- Modify `LikesController` to conditionally call `reindex` only if the likeable object responds to it, preventing `NoMethodError` for non-indexed models like `Photo`.
- Remove unnecessary `:reindex` trait from photo factory call in `likeable_spec.rb`.

Co-authored-by: CloCkWeRX <365751+CloCkWeRX@users.noreply.github.com>
2026-06-23 14:22:47 +00:00
google-labs-jules[bot]andCloCkWeRX d6b9ededec Remove Photo.reindex calls from test suite
The Photo model is no longer using Searchkick/Elasticsearch, so calling
`Photo.reindex` causes a NoMethodError. This commit removes these calls
from `spec/spec_helper.rb` and feature specs, and removes the unused
`:reindex` trait from the photo factory call in `likeable_spec.rb`.

Co-authored-by: CloCkWeRX <365751+CloCkWeRX@users.noreply.github.com>
2026-06-23 14:00:08 +00:00
Daniel O'Connor 118e50ccfc Merge pull request #4677 from Growstuff/fix-docker-build-missing-ruby-version-8858247702805966576
Fix Docker build by copying .ruby-version before bundle install
2026-06-23 22:50:58 +09:30
google-labs-jules[bot]andCloCkWeRX 75fa206ff7 Copy .ruby-version before bundle install in Dockerfile
The Gemfile reads the .ruby-version file to determine the Ruby version.
If this file is not present during `bundle install`, the build fails.
This change ensures that .ruby-version is copied along with the Gemfile
and Gemfile.lock.

Co-authored-by: CloCkWeRX <365751+CloCkWeRX@users.noreply.github.com>
2026-06-23 13:06:53 +00:00
Daniel O'Connor 452b0c4eba Merge pull request #4674 from Growstuff/security-2026-06-23
Security fixes
2026-06-23 22:34:46 +09:30
Daniel O'Connor 7dd78359aa Merge pull request #4676 from Growstuff/dependabot/bundler/net-imap-0.6.4.1
Bump net-imap from 0.6.4 to 0.6.4.1
2026-06-23 22:34:33 +09:30
Daniel O'Connor 3af51f18dc Merge pull request #4675 from Growstuff/convert-photos-to-sql-4865766049333411151
Convert Photos controller to avoid elasticsearch
2026-06-23 21:51:39 +09:30
Daniel O'Connor b2248ee4ca Merge branch 'dev' into convert-photos-to-sql-4865766049333411151 2026-06-23 21:47:45 +09:30
dependabot[bot] bda4d98a1b Bump net-imap from 0.6.4 to 0.6.4.1
Bumps [net-imap](https://github.com/ruby/net-imap) from 0.6.4 to 0.6.4.1.
- [Release notes](https://github.com/ruby/net-imap/releases)
- [Commits](https://github.com/ruby/net-imap/compare/v0.6.4...v0.6.4.1)

---
updated-dependencies:
- dependency-name: net-imap
  dependency-version: 0.6.4.1
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-23 12:17:25 +00:00
google-labs-jules[bot]andCloCkWeRX 97e236f7e8 Convert Photos controller to plain SQL queries
- Refactored `PhotosController#index` to use ActiveRecord queries instead of Searchkick/Elasticsearch.
- Handled filtering by crop and planting via associations.
- Added eager loading for the photo owner to prevent N+1 queries.
- Decoupled the `Photo` model from Elasticsearch by removing the `SearchPhotos` concern.
- Deleted `app/models/concerns/search_photos.rb`.
- Updated controller and model specs to use standard ActiveRecord expectations.
- Cleaned up the photo factory by removing the now-obsolete `:reindex` trait.

Co-authored-by: CloCkWeRX <365751+CloCkWeRX@users.noreply.github.com>
2026-06-23 12:16:50 +00:00
Daniel O'Connor 92faca98fa Security fixes 2026-06-23 12:14:57 +00:00
Daniel O'Connor a9179618f5 Merge pull request #4673 from Growstuff/heroku-26
Heroku 26
2026-06-23 21:43:48 +09:30
Daniel O'Connor 217b3953ac Update docker rails version 2026-06-23 11:59:57 +00:00
Daniel O'Connor 9fe2294c7b Update to heroku-26 2026-06-23 11:54:38 +00:00
867c8b27fb Upgrade to Rails 8.0 (#4621)
* Upgrade application to Rails 8.0

- Updated Gemfile to rails ~> 8.0.0 and updated Gemfile.lock
- Set config.load_defaults 8.0 in config/application.rb
- Configured YAML as default_column_serializer for ActiveRecord serialization compatibility
- Added Faraday 2.x error constant compatibility shim in config/initializers/faraday_patch.rb
- Added Active Storage migrations and verified with db:migrate
- Added Rails 8 bin/dev and bin/rubocop scripts
- Maintained Ruby 3.4.9 compatibility in .ruby-version and Gemfile.lock

Co-authored-by: CloCkWeRX <365751+CloCkWeRX@users.noreply.github.com>

* Delete db/migrate/20241117032507_remove_not_null_on_active_storage_blobs_checksum.active_storage.rb

* Delete db/migrate/20241117032505_add_service_name_to_active_storage_blobs.active_storage.rb

* Delete db/migrate/20241117032506_create_active_storage_variant_records.active_storage.rb

* Delete config/initializers/faraday_patch.rb

* Update schema

* Fix conflicts

---------

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
2026-06-23 20:43:40 +09:30
Cesy c76a7f9b7d Merge pull request #4670 from Growstuff/dependabot/bundler/haml_lint-0.74.0
Bump haml_lint from 0.73.0 to 0.74.0
2026-06-23 10:04:48 +01:00
dependabot[bot] f6bfe339fa Bump haml_lint from 0.73.0 to 0.74.0
Bumps [haml_lint](https://github.com/sds/haml-lint) from 0.73.0 to 0.74.0.
- [Release notes](https://github.com/sds/haml-lint/releases)
- [Changelog](https://github.com/sds/haml-lint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sds/haml-lint/compare/v0.73.0...v0.74.0)

---
updated-dependencies:
- dependency-name: haml_lint
  dependency-version: 0.74.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-23 08:54:48 +00:00
Cesy c4a004c5a8 Merge pull request #4669 from Growstuff/dependabot/bundler/rubocop-capybara-3.0.0
Bump rubocop-capybara from 2.23.0 to 3.0.0
2026-06-23 09:52:15 +01:00
dependabot[bot] 60f498b064 Bump rubocop-capybara from 2.23.0 to 3.0.0
Bumps [rubocop-capybara](https://github.com/rubocop/rubocop-capybara) from 2.23.0 to 3.0.0.
- [Release notes](https://github.com/rubocop/rubocop-capybara/releases)
- [Changelog](https://github.com/rubocop/rubocop-capybara/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rubocop/rubocop-capybara/compare/v2.23.0...v3.0.0)

---
updated-dependencies:
- dependency-name: rubocop-capybara
  dependency-version: 3.0.0
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-23 08:44:35 +00:00
Cesy 45c8d42a33 Merge pull request #4668 from Growstuff/dependabot/bundler/rubocop-rails-2.35.5
Bump rubocop-rails from 2.35.4 to 2.35.5
2026-06-23 09:42:07 +01:00
dependabot[bot] b35216e5ce Bump rubocop-rails from 2.35.4 to 2.35.5
Bumps [rubocop-rails](https://github.com/rubocop/rubocop-rails) from 2.35.4 to 2.35.5.
- [Release notes](https://github.com/rubocop/rubocop-rails/releases)
- [Changelog](https://github.com/rubocop/rubocop-rails/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rubocop/rubocop-rails/compare/v2.35.4...v2.35.5)

---
updated-dependencies:
- dependency-name: rubocop-rails
  dependency-version: 2.35.5
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-22 07:06:43 +00:00
dependabot[bot] e4c9bc585c Bump faraday from 2.14.2 to 2.14.3 (#4665)
Bumps [faraday](https://github.com/lostisland/faraday) from 2.14.2 to 2.14.3.
- [Release notes](https://github.com/lostisland/faraday/releases)
- [Changelog](https://github.com/lostisland/faraday/blob/main/CHANGELOG.md)
- [Commits](https://github.com/lostisland/faraday/compare/v2.14.2...v2.14.3)

---
updated-dependencies:
- dependency-name: faraday
  dependency-version: 2.14.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-22 06:59:36 +09:30
dependabot[bot] bd89bb987f Bump actions/checkout from 6 to 7 (#4667)
Bumps [actions/checkout](https://github.com/actions/checkout) from 6 to 7.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-21 18:05:48 +09:30
dependabot[bot] 84c74aff4f Bump js-yaml from 4.1.1 to 4.2.0 (#4664)
Bumps [js-yaml](https://github.com/nodeca/js-yaml) from 4.1.1 to 4.2.0.
- [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nodeca/js-yaml/commits)

---
updated-dependencies:
- dependency-name: js-yaml
  dependency-version: 4.2.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-17 22:11:02 +09:30
dependabot[bot] c52447fab7 Bump aws-sdk-s3 from 1.225.1 to 1.226.0 (#4666)
Bumps [aws-sdk-s3](https://github.com/aws/aws-sdk-ruby) from 1.225.1 to 1.226.0.
- [Release notes](https://github.com/aws/aws-sdk-ruby/releases)
- [Changelog](https://github.com/aws/aws-sdk-ruby/blob/version-3/gems/aws-sdk-s3/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-ruby/commits)

---
updated-dependencies:
- dependency-name: aws-sdk-s3
  dependency-version: 1.226.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-17 22:10:38 +09:30
dependabot[bot] f7082bcf54 Bump msgpack from 1.8.1 to 1.8.3 (#4660)
Bumps [msgpack](https://github.com/msgpack/msgpack-ruby) from 1.8.1 to 1.8.3.
- [Changelog](https://github.com/msgpack/msgpack-ruby/blob/master/ChangeLog)
- [Commits](https://github.com/msgpack/msgpack-ruby/compare/v1.8.1...v1.8.3)

---
updated-dependencies:
- dependency-name: msgpack
  dependency-version: 1.8.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-16 18:42:02 +09:30
dependabot[bot] 2f839b0f22 Bump aws-sdk-s3 from 1.225.0 to 1.225.1 (#4661)
Bumps [aws-sdk-s3](https://github.com/aws/aws-sdk-ruby) from 1.225.0 to 1.225.1.
- [Release notes](https://github.com/aws/aws-sdk-ruby/releases)
- [Changelog](https://github.com/aws/aws-sdk-ruby/blob/version-3/gems/aws-sdk-s3/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-ruby/commits)

---
updated-dependencies:
- dependency-name: aws-sdk-s3
  dependency-version: 1.225.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-16 18:41:34 +09:30
dependabot[bot] 4a522d3967 Bump selenium-webdriver from 4.44.0 to 4.45.0 (#4662)
Bumps [selenium-webdriver](https://github.com/SeleniumHQ/selenium) from 4.44.0 to 4.45.0.
- [Release notes](https://github.com/SeleniumHQ/selenium/releases)
- [Changelog](https://github.com/SeleniumHQ/selenium/blob/trunk/rb/CHANGES)
- [Commits](https://github.com/SeleniumHQ/selenium/compare/selenium-4.44.0...selenium-4.45.0)

---
updated-dependencies:
- dependency-name: selenium-webdriver
  dependency-version: 4.45.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-16 18:41:15 +09:30
dependabot[bot] 05c3348324 Bump rubocop from 1.87.0 to 1.88.0 (#4663)
Bumps [rubocop](https://github.com/rubocop/rubocop) from 1.87.0 to 1.88.0.
- [Release notes](https://github.com/rubocop/rubocop/releases)
- [Changelog](https://github.com/rubocop/rubocop/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rubocop/rubocop/compare/v1.87.0...v1.88.0)

---
updated-dependencies:
- dependency-name: rubocop
  dependency-version: 1.88.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-16 18:41:01 +09:30
Cesy 51360a0c7c Merge pull request #4657 from Growstuff/dependabot/bundler/rubocop-rspec-3.10.2
Bump rubocop-rspec from 3.9.0 to 3.10.2
2026-06-10 09:13:23 +01:00
dependabot[bot] 3db100b75f Bump rubocop-rspec from 3.9.0 to 3.10.2
Bumps [rubocop-rspec](https://github.com/rubocop/rubocop-rspec) from 3.9.0 to 3.10.2.
- [Release notes](https://github.com/rubocop/rubocop-rspec/releases)
- [Changelog](https://github.com/rubocop/rubocop-rspec/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rubocop/rubocop-rspec/compare/v3.9.0...v3.10.2)

---
updated-dependencies:
- dependency-name: rubocop-rspec
  dependency-version: 3.10.2
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-08 12:37:30 +00:00
dependabot[bot] 1ddbecb22a Bump rubocop-rails from 2.35.3 to 2.35.4 (#4658)
Bumps [rubocop-rails](https://github.com/rubocop/rubocop-rails) from 2.35.3 to 2.35.4.
- [Release notes](https://github.com/rubocop/rubocop-rails/releases)
- [Changelog](https://github.com/rubocop/rubocop-rails/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rubocop/rubocop-rails/compare/v2.35.3...v2.35.4)

---
updated-dependencies:
- dependency-name: rubocop-rails
  dependency-version: 2.35.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-08 22:06:01 +09:30
dependabot[bot] 884b5bc3f6 Bump discard from 1.4.0 to 2.0.0 (#4651)
Bumps [discard](https://github.com/jhawthorn/discard) from 1.4.0 to 2.0.0.
- [Changelog](https://github.com/jhawthorn/discard/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jhawthorn/discard/compare/v1.4.0...v2.0.0)

---
updated-dependencies:
- dependency-name: discard
  dependency-version: 2.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-08 22:04:46 +09:30
dependabot[bot] 11b15420ed Bump rubocop from 1.86.2 to 1.87.0 (#4652)
Bumps [rubocop](https://github.com/rubocop/rubocop) from 1.86.2 to 1.87.0.
- [Release notes](https://github.com/rubocop/rubocop/releases)
- [Changelog](https://github.com/rubocop/rubocop/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rubocop/rubocop/compare/v1.86.2...v1.87.0)

---
updated-dependencies:
- dependency-name: rubocop
  dependency-version: 1.87.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-07 23:14:10 +09:30
dependabot[bot] 5540a86952 Bump aws-sdk-s3 from 1.224.0 to 1.225.0 (#4653)
Bumps [aws-sdk-s3](https://github.com/aws/aws-sdk-ruby) from 1.224.0 to 1.225.0.
- [Release notes](https://github.com/aws/aws-sdk-ruby/releases)
- [Changelog](https://github.com/aws/aws-sdk-ruby/blob/version-3/gems/aws-sdk-s3/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-ruby/commits)

---
updated-dependencies:
- dependency-name: aws-sdk-s3
  dependency-version: 1.225.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-07 22:20:23 +09:30
dependabot[bot] ccba9a7611 Bump bullet from 8.1.2 to 8.1.3 (#4654)
Bumps [bullet](https://github.com/flyerhzm/bullet) from 8.1.2 to 8.1.3.
- [Changelog](https://github.com/flyerhzm/bullet/blob/main/CHANGELOG.md)
- [Commits](https://github.com/flyerhzm/bullet/compare/8.1.2...8.1.3)

---
updated-dependencies:
- dependency-name: bullet
  dependency-version: 8.1.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-07 22:19:47 +09:30
dependabot[bot] 393994e3e4 Bump oj from 3.17.1 to 3.17.3 (#4655)
Bumps [oj](https://github.com/ohler55/oj) from 3.17.1 to 3.17.3.
- [Release notes](https://github.com/ohler55/oj/releases)
- [Changelog](https://github.com/ohler55/oj/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/ohler55/oj/compare/v3.17.1...v3.17.3)

---
updated-dependencies:
- dependency-name: oj
  dependency-version: 3.17.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-07 22:19:28 +09:30
dependabot[bot] 2ff98315a6 Bump msgpack from 1.8.0 to 1.8.1 (#4650)
Bumps [msgpack](https://github.com/msgpack/msgpack-ruby) from 1.8.0 to 1.8.1.
- [Changelog](https://github.com/msgpack/msgpack-ruby/blob/master/ChangeLog)
- [Commits](https://github.com/msgpack/msgpack-ruby/compare/v1.8.0...v1.8.1)

---
updated-dependencies:
- dependency-name: msgpack
  dependency-version: 1.8.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-03 13:08:09 +09:30
dependabot[bot] 4d2bc77731 Bump dalli from 5.0.4 to 5.0.5 (#4647)
Bumps [dalli](https://github.com/petergoldstein/dalli) from 5.0.4 to 5.0.5.
- [Changelog](https://github.com/petergoldstein/dalli/blob/main/CHANGELOG.md)
- [Commits](https://github.com/petergoldstein/dalli/compare/v5.0.4...v5.0.5)

---
updated-dependencies:
- dependency-name: dalli
  dependency-version: 5.0.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-29 10:52:43 +09:30
dependabot[bot] a32d7d11c9 Bump rubocop-rails from 2.35.2 to 2.35.3 (#4648)
Bumps [rubocop-rails](https://github.com/rubocop/rubocop-rails) from 2.35.2 to 2.35.3.
- [Release notes](https://github.com/rubocop/rubocop-rails/releases)
- [Changelog](https://github.com/rubocop/rubocop-rails/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rubocop/rubocop-rails/compare/v2.35.2...v2.35.3)

---
updated-dependencies:
- dependency-name: rubocop-rails
  dependency-version: 2.35.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-29 10:52:16 +09:30
dependabot[bot] 5c0746f136 Bump puma from 8.0.1 to 8.0.2 (#4649)
Bumps [puma](https://github.com/puma/puma) from 8.0.1 to 8.0.2.
- [Release notes](https://github.com/puma/puma/releases)
- [Changelog](https://github.com/puma/puma/blob/main/History.md)
- [Commits](https://github.com/puma/puma/compare/v8.0.1...v8.0.2)

---
updated-dependencies:
- dependency-name: puma
  dependency-version: 8.0.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-29 10:51:39 +09:30
dependabot[bot] 38736211ec Bump bullet from 8.1.1 to 8.1.2 (#4646)
Bumps [bullet](https://github.com/flyerhzm/bullet) from 8.1.1 to 8.1.2.
- [Changelog](https://github.com/flyerhzm/bullet/blob/main/CHANGELOG.md)
- [Commits](https://github.com/flyerhzm/bullet/compare/8.1.1...8.1.2)

---
updated-dependencies:
- dependency-name: bullet
  dependency-version: 8.1.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-29 03:04:12 +09:30
dependabot[bot] 2dc5dbac7d Bump aws-sdk-s3 from 1.222.0 to 1.224.0 (#4645)
Bumps [aws-sdk-s3](https://github.com/aws/aws-sdk-ruby) from 1.222.0 to 1.224.0.
- [Release notes](https://github.com/aws/aws-sdk-ruby/releases)
- [Changelog](https://github.com/aws/aws-sdk-ruby/blob/version-3/gems/aws-sdk-s3/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-ruby/commits)

---
updated-dependencies:
- dependency-name: aws-sdk-s3
  dependency-version: 1.224.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-25 13:23:23 +09:30
dependabot[bot] ee6d5cd84a Bump dalli from 5.0.2 to 5.0.4 (#4639)
Bumps [dalli](https://github.com/petergoldstein/dalli) from 5.0.2 to 5.0.4.
- [Changelog](https://github.com/petergoldstein/dalli/blob/main/CHANGELOG.md)
- [Commits](https://github.com/petergoldstein/dalli/compare/v5.0.2...v5.0.4)

---
updated-dependencies:
- dependency-name: dalli
  dependency-version: 5.0.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-20 13:09:42 +09:30
dependabot[bot] f1524c2b0c Bump rubocop-rails from 2.35.1 to 2.35.2 (#4643)
Bumps [rubocop-rails](https://github.com/rubocop/rubocop-rails) from 2.35.1 to 2.35.2.
- [Release notes](https://github.com/rubocop/rubocop-rails/releases)
- [Changelog](https://github.com/rubocop/rubocop-rails/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rubocop/rubocop-rails/compare/v2.35.1...v2.35.2)

---
updated-dependencies:
- dependency-name: rubocop-rails
  dependency-version: 2.35.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-20 13:09:26 +09:30
dependabot[bot] a6cb1cbb36 Bump rubocop-rails from 2.35.0 to 2.35.1 (#4642)
Bumps [rubocop-rails](https://github.com/rubocop/rubocop-rails) from 2.35.0 to 2.35.1.
- [Release notes](https://github.com/rubocop/rubocop-rails/releases)
- [Changelog](https://github.com/rubocop/rubocop-rails/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rubocop/rubocop-rails/compare/v2.35.0...v2.35.1)

---
updated-dependencies:
- dependency-name: rubocop-rails
  dependency-version: 2.35.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-19 19:54:54 +09:30
dependabot[bot] c0f6720a1e Bump oj from 3.17.0 to 3.17.1 (#4640)
Bumps [oj](https://github.com/ohler55/oj) from 3.17.0 to 3.17.1.
- [Release notes](https://github.com/ohler55/oj/releases)
- [Changelog](https://github.com/ohler55/oj/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/ohler55/oj/compare/v3.17.0...v3.17.1)

---
updated-dependencies:
- dependency-name: oj
  dependency-version: 3.17.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-19 18:41:08 +09:30
dependabot[bot] 04ea628f00 Bump faraday from 2.14.1 to 2.14.2 (#4641)
Bumps [faraday](https://github.com/lostisland/faraday) from 2.14.1 to 2.14.2.
- [Release notes](https://github.com/lostisland/faraday/releases)
- [Changelog](https://github.com/lostisland/faraday/blob/main/CHANGELOG.md)
- [Commits](https://github.com/lostisland/faraday/compare/v2.14.1...v2.14.2)

---
updated-dependencies:
- dependency-name: faraday
  dependency-version: 2.14.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-19 12:30:01 +09:30
dependabot[bot] cabac926cc Bump icalendar from 2.12.2 to 2.12.3 (#4635)
Bumps [icalendar](https://github.com/icalendar/icalendar) from 2.12.2 to 2.12.3.
- [Changelog](https://github.com/icalendar/icalendar/blob/main/CHANGELOG.md)
- [Commits](https://github.com/icalendar/icalendar/compare/v2.12.2...v2.12.3)

---
updated-dependencies:
- dependency-name: icalendar
  dependency-version: 2.12.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-15 12:59:47 +09:30
dependabot[bot] 0d375f6146 Bump rubocop from 1.86.1 to 1.86.2 (#4634)
Bumps [rubocop](https://github.com/rubocop/rubocop) from 1.86.1 to 1.86.2.
- [Release notes](https://github.com/rubocop/rubocop/releases)
- [Changelog](https://github.com/rubocop/rubocop/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rubocop/rubocop/compare/v1.86.1...v1.86.2)

---
updated-dependencies:
- dependency-name: rubocop
  dependency-version: 1.86.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-15 12:59:37 +09:30
dependabot[bot] be9e5ed6bf Bump aws-sdk-s3 from 1.221.0 to 1.222.0 (#4636)
Bumps [aws-sdk-s3](https://github.com/aws/aws-sdk-ruby) from 1.221.0 to 1.222.0.
- [Release notes](https://github.com/aws/aws-sdk-ruby/releases)
- [Changelog](https://github.com/aws/aws-sdk-ruby/blob/version-3/gems/aws-sdk-s3/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-ruby/commits)

---
updated-dependencies:
- dependency-name: aws-sdk-s3
  dependency-version: 1.222.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-15 12:42:57 +09:30
Daniel O'Connorandgoogle-labs-jules[bot] c8ea225b10 Ensure garden creation flash prompt is rendered as HTML (#4633)
Updated app/views/shared/_flash_messages.html.haml to use sanitize(content)
instead of = content. This ensures that HTML content in flash messages,
such as the prompt to add an activity after creating a garden, is
correctly rendered even if its html_safe status is lost during session
serialization.

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
2026-05-14 12:35:18 +09:30
dependabot[bot] a8b7c73111 Bump systeminformation from 5.31.5 to 5.31.6 (#4632)
Bumps [systeminformation](https://github.com/sebhildebrandt/systeminformation) from 5.31.5 to 5.31.6.
- [Release notes](https://github.com/sebhildebrandt/systeminformation/releases)
- [Changelog](https://github.com/sebhildebrandt/systeminformation/blob/master/CHANGELOG.md)
- [Commits](https://github.com/sebhildebrandt/systeminformation/compare/v5.31.5...v5.31.6)

---
updated-dependencies:
- dependency-name: systeminformation
  dependency-version: 5.31.6
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-14 11:37:29 +09:30
dependabot[bot] 61810dbee3 Bump selenium-webdriver from 4.43.0 to 4.44.0 (#4631)
Bumps [selenium-webdriver](https://github.com/SeleniumHQ/selenium) from 4.43.0 to 4.44.0.
- [Release notes](https://github.com/SeleniumHQ/selenium/releases)
- [Changelog](https://github.com/SeleniumHQ/selenium/blob/trunk/rb/CHANGES)
- [Commits](https://github.com/SeleniumHQ/selenium/compare/selenium-4.43.0...selenium-4.44.0)

---
updated-dependencies:
- dependency-name: selenium-webdriver
  dependency-version: 4.44.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-13 22:39:08 +09:30
1467ec9364 Add Wikidata climate attributes and integration to gardens (#4627)
* Add Wikidata integration for garden climate data

- Add location_wikidata_id, lowest_temp_c, and highest_temp_c to gardens.
- Implement WikidataService for fetching IDs and temperature properties.
- Map P6591 to highest_temp_c and P7422 to lowest_temp_c with unit conversion.
- Automatically populate Wikidata info on garden location change.
- Add manual "Fetch Wikidata info" button and opt-in prompt to garden show page.
- Update gardens_controller to permit new attributes and handle manual fetch.
- Update db/schema.rb manually to include new columns and migration version.

Co-authored-by: CloCkWeRX <365751+CloCkWeRX@users.noreply.github.com>

* Fix migration

* Improve display

---------

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
2026-05-12 18:07:35 +09:30
dependabot[bot] 37452a5513 Bump rubocop-rails from 2.34.3 to 2.35.0 (#4628)
Bumps [rubocop-rails](https://github.com/rubocop/rubocop-rails) from 2.34.3 to 2.35.0.
- [Release notes](https://github.com/rubocop/rubocop-rails/releases)
- [Changelog](https://github.com/rubocop/rubocop-rails/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rubocop/rubocop-rails/compare/v2.34.3...v2.35.0)

---
updated-dependencies:
- dependency-name: rubocop-rails
  dependency-version: 2.35.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-12 17:23:59 +09:30
dependabot[bot] e70297a83e Bump devise from 5.0.3 to 5.0.4 (#4629)
Bumps [devise](https://github.com/heartcombo/devise) from 5.0.3 to 5.0.4.
- [Release notes](https://github.com/heartcombo/devise/releases)
- [Changelog](https://github.com/heartcombo/devise/blob/main/CHANGELOG.md)
- [Commits](https://github.com/heartcombo/devise/compare/v5.0.3...v5.0.4)

---
updated-dependencies:
- dependency-name: devise
  dependency-version: 5.0.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-12 17:23:46 +09:30
Daniel O'Connorandgoogle-labs-jules[bot] d7a50f86b5 Allow collaborators to remove themselves from gardens (#4630)
- Update Ability to grant destroy permission to collaborators for their own record
- Add 'Leave garden' link to garden show page
- Add specs for garden collaborator permissions

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
2026-05-12 17:23:24 +09:30
dependabot[bot] ca7f56683c Bump aws-sdk-s3 from 1.220.0 to 1.221.0 (#4624)
Bumps [aws-sdk-s3](https://github.com/aws/aws-sdk-ruby) from 1.220.0 to 1.221.0.
- [Release notes](https://github.com/aws/aws-sdk-ruby/releases)
- [Changelog](https://github.com/aws/aws-sdk-ruby/blob/version-3/gems/aws-sdk-s3/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-ruby/commits)

---
updated-dependencies:
- dependency-name: aws-sdk-s3
  dependency-version: 1.221.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-10 10:38:49 +09:30
dependabot[bot]andCesy 0c00b866da Bump friendly_id from 5.6.0 to 5.7.0 (#4625)
Bumps [friendly_id](https://github.com/norman/friendly_id) from 5.6.0 to 5.7.0.
- [Release notes](https://github.com/norman/friendly_id/releases)
- [Changelog](https://github.com/norman/friendly_id/blob/master/Changelog.md)
- [Commits](https://github.com/norman/friendly_id/compare/v5.6.0...v5.7.0)

---
updated-dependencies:
- dependency-name: friendly_id
  dependency-version: 5.7.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Cesy <cesy.avon@gmail.com>
2026-05-10 10:38:23 +09:30
Cesy f50da4e0e0 Merge pull request #4626 from Growstuff/dependabot/npm_and_yarn/fast-uri-3.1.2 2026-05-09 06:46:38 +01:00
dependabot[bot] 31285b2bde Bump fast-uri from 3.1.0 to 3.1.2
Bumps [fast-uri](https://github.com/fastify/fast-uri) from 3.1.0 to 3.1.2.
- [Release notes](https://github.com/fastify/fast-uri/releases)
- [Commits](https://github.com/fastify/fast-uri/compare/v3.1.0...v3.1.2)

---
updated-dependencies:
- dependency-name: fast-uri
  dependency-version: 3.1.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-08 23:25:42 +00:00
dependabot[bot] ec5873fc88 Bump ip-address from 10.1.0 to 10.2.0 (#4623)
Bumps [ip-address](https://github.com/beaugunderson/ip-address) from 10.1.0 to 10.2.0.
- [Commits](https://github.com/beaugunderson/ip-address/commits)

---
updated-dependencies:
- dependency-name: ip-address
  dependency-version: 10.2.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-07 13:26:51 +09:30
Daniel O'Connor 555d5ddf15 Revert "Replace Sidekiq with Solid Queue (#4619)" (#4620)
This reverts commit 4659ac5464.
2026-05-04 18:15:17 +09:30
5ada7e7f77 Add crops search API endpoint (#4622)
* Add crops search API endpoint

- Added GET /api/v1/crops/search endpoint.
- Updated CropSearchService to support additional search options.
- Manually updated Swagger documentation in swagger/v1/swagger.json.
- Added request specs to verify the new endpoint.

Co-authored-by: CloCkWeRX <365751+CloCkWeRX@users.noreply.github.com>

* Add crops search API endpoint

- Added GET /api/v1/crops/search endpoint.
- Updated CropSearchService to support additional search options.
- Manually updated Swagger documentation in swagger/v1/swagger.json.
- Added request specs to verify the new endpoint.

Co-authored-by: CloCkWeRX <365751+CloCkWeRX@users.noreply.github.com>

---------

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
2026-05-04 18:12:36 +09:30
4659ac5464 Replace Sidekiq with Solid Queue (#4619)
* Replace Sidekiq with Solid Queue

This commit transitions the background job processing from Sidekiq to
Solid Queue.

Changes:
- Replaced `sidekiq` gem with `solid_queue` in Gemfile.
- Updated `development.rb` and `production.rb` to use `:solid_queue` as
  the queue adapter.
- Added Solid Queue database tables via a new migration.
- Configured Solid Queue in `config/queue.yml` and `config/recurring.yml`.
- Integrated Solid Queue supervisor as a Puma plugin in `config/puma.rb`.
- Removed separate worker process from `Procfile`.
- Removed Sidekiq-specific configuration files.
- Updated Gemfile.lock to support both `ruby` and `x86_64-linux` platforms.

Co-authored-by: CloCkWeRX <365751+CloCkWeRX@users.noreply.github.com>

* Fix regression in gemfiles

---------

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
2026-05-03 15:29:03 +09:30
3d63d12908 Improve read performance with caching and memoization (#4572)
* Improve read performance with caching and memoization

- Memoize `Crop#all_companions` and `Member#unread_count` in models
- Implement instance-level memoization in `CropsHelper#crop_or_parent`
- Add Rails caching for expensive aggregate queries in `Charts::CropsController`
- Add fragment caching for high-impact sections on the crop show page

Co-authored-by: CloCkWeRX <365751+CloCkWeRX@users.noreply.github.com>

* Fix header spec failure due to memoized unread_count

- Reset `@unread_count` in `spec/views/layouts/_header_spec.rb` to ensure the updated notification count is rendered correctly.

Co-authored-by: CloCkWeRX <365751+CloCkWeRX@users.noreply.github.com>

---------

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
2026-05-03 14:47:59 +09:30
035210197f Prompt for updated planting rating when harvesting (#4608)
* Update planting rating when recording a harvest

- Added virtual attribute `overall_rating` to `Harvest` model.
- Updated `HarvestsController` to permit `overall_rating` and synchronize it to the associated `Planting`.
- Added a rating range field (1-5) to the harvest form.
- Added controller tests to verify that the planting rating is updated.
- Refined feature tests for harvesting.

Co-authored-by: CloCkWeRX <365751+CloCkWeRX@users.noreply.github.com>

* I have updated the system to allow for recording a planting rating when a harvest is logged. Here is a summary of the changes:

- Added a virtual attribute `overall_rating` to the `Harvest` model.
- Updated `HarvestsController` to permit `overall_rating` and synchronize it to the associated `Planting`.
- Added a rating range field (1-5) to the harvest form.
- Added controller tests to verify that the planting rating is updated correctly.
- Updated feature tests to ensure the harvest form functions as expected.

Co-authored-by: CloCkWeRX <365751+CloCkWeRX@users.noreply.github.com>

* Update database.yml

* Apply suggestions from code review

Co-authored-by: Daniel O'Connor <daniel.oconnor@gmail.com>

* Adjust wording

* Change harvest modal

* Fix tests

---------

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
2026-05-03 14:47:00 +09:30
Daniel O'Connor 8a8fd6eabd Merge pull request #4575 from Growstuff/memoize-unread-count
Memoize unread messages count
2026-05-02 16:46:26 +09:30
Daniel O'Connor fe9fdd9147 Upgrade ERB (#4617) 2026-05-02 16:46:02 +09:30
Daniel O'Connor ee7b9ab39f Upgrade ERB 2026-05-02 07:03:30 +00:00
Daniel O'Connor 6aadb4d805 Merge pull request #4616 from Growstuff/rubocop-upgrade
Update rubocop_todo.yml
2026-05-02 16:28:50 +09:30
Daniel O'Connor a42682a59e Merge pull request #4614 from Growstuff/upgrade-ruby
Update to Ruby 3.4.9
2026-05-02 16:19:54 +09:30
Daniel O'Connor 6294c54139 Merge pull request #4615 from Growstuff/fix-sidekiq
Namespaces no longer supported in sidekiq
2026-05-02 16:07:59 +09:30
Daniel O'Connor c168e8e4c9 Update to 3.4.9 2026-05-02 06:36:27 +00:00
Daniel O'Connor 6ac438a07f Namespaces no longer supported in sidekiq 2026-05-02 06:35:23 +00:00
Daniel O'Connor 2380c662fe Merge pull request #4604 from Growstuff/harvest-reminders-16703221337897327633
Add Harvest Reminder Emails and Scheduled Task
2026-05-02 15:46:09 +09:30
4589839c64 Fix crops csv export 11894001552728801282 (#4613)
* Fix ArgumentError in Crops CSV export

This commit fixes a crash when exporting crops to CSV, caused by
accessing ActiveRecord methods and associations on Searchkick
HashWrapper objects.

Changes:
- In CropsController#index, use `load: true` (with preloaded
  associations) when the request format is CSV or RSS.
- In app/views/crops/index.csv.shaper, use individual `csv.cell` calls
  instead of `csv.cells` to correctly handle Searchkick results and
  explicitly access attributes.
- Added a controller test to verify CSV export functionality.

Co-authored-by: CloCkWeRX <365751+CloCkWeRX@users.noreply.github.com>

* Mark test pending

* Skip creator

---------

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
2026-05-02 15:39:36 +09:30
Daniel O'Connor 1f6f3c4dfd Merge pull request #4612 from Growstuff/fix-crops-csv-export-11894001552728801282
Fix ArgumentError in Crops CSV export
2026-05-02 15:31:10 +09:30
Daniel O'Connor 5a7f41537f Change plant_before formatting method to to_fs 2026-05-02 14:47:43 +09:30
Daniel O'Connor 1281795c97 Merge pull request #4609 from Growstuff/fix-csv-export-crash-4991917409830119333
Fix crash during CSV export of harvests and seeds
2026-05-02 14:42:39 +09:30
Daniel O'Connor c219d447cc Merge branch 'dev' into fix-csv-export-crash-4991917409830119333 2026-05-02 14:41:31 +09:30
Daniel O'Connor 1e3f86a349 Merge pull request #4611 from Growstuff/CloCkWeRX-patch-2
Fix seeds_count to correctly reference size
2026-05-02 14:17:51 +09:30
Daniel O'Connor 680afe02cc Merge pull request #4610 from Growstuff/associate-post-with-crop-5945795316503813050
Associate post with crop from crop show page
2026-05-02 13:42:01 +09:30
Daniel O'Connor 914cfe99c8 Fix seeds_count to correctly reference size 2026-05-02 13:39:34 +09:30
google-labs-jules[bot]andCloCkWeRX 4643fbd92e Associate post with crop from crop show page
Co-authored-by: CloCkWeRX <365751+CloCkWeRX@users.noreply.github.com>
2026-05-01 11:35:58 +00:00
google-labs-jules[bot]andCloCkWeRX 5ac709ffd1 Fix crash during CSV export of harvests and seeds
When using Searchkick with `load: false`, search results are returned
as HashResponse objects which do not support model associations or
standard Rails URL helpers that expect model instances.

This commit updates HarvestsController and SeedsController to
conditionally load ActiveRecord objects when CSV format is requested,
ensuring that the export templates can access the necessary associations.
Similar logic was also applied to CropsController.

Additionally, a typo in the Crops CSV shaper was fixed.

Co-authored-by: CloCkWeRX <365751+CloCkWeRX@users.noreply.github.com>
2026-05-01 11:30:22 +00:00
Daniel O'Connor 9833801a42 Merge pull request #4606 from Growstuff/dependabot/bundler/axe-core-rspec-4.11.3
Bump axe-core-rspec from 4.11.2 to 4.11.3
2026-05-01 18:17:28 +09:30
dependabot[bot] 4d1e8aede6 Bump axe-core-rspec from 4.11.2 to 4.11.3
Bumps [axe-core-rspec](https://github.com/dequelabs/axe-core-gems) from 4.11.2 to 4.11.3.
- [Release notes](https://github.com/dequelabs/axe-core-gems/releases)
- [Changelog](https://github.com/dequelabs/axe-core-gems/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/dequelabs/axe-core-gems/commits)

---
updated-dependencies:
- dependency-name: axe-core-rspec
  dependency-version: 4.11.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-01 07:49:38 +00:00
Daniel O'Connoranddependabot[bot] 24f41350a9 Bump rubocop-capybara from 2.22.1 to 2.23.0 (#4605)
Bumps [rubocop-capybara](https://github.com/rubocop/rubocop-capybara) from 2.22.1 to 2.23.0.
- [Release notes](https://github.com/rubocop/rubocop-capybara/releases)
- [Changelog](https://github.com/rubocop/rubocop-capybara/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rubocop/rubocop-capybara/compare/v2.22.1...v2.23.0)

---
updated-dependencies:
- dependency-name: rubocop-capybara
  dependency-version: 2.23.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-30 17:38:16 +09:30
dependabot[bot] 503ba716bb Bump rubocop-capybara from 2.22.1 to 2.23.0
Bumps [rubocop-capybara](https://github.com/rubocop/rubocop-capybara) from 2.22.1 to 2.23.0.
- [Release notes](https://github.com/rubocop/rubocop-capybara/releases)
- [Changelog](https://github.com/rubocop/rubocop-capybara/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rubocop/rubocop-capybara/compare/v2.22.1...v2.23.0)

---
updated-dependencies:
- dependency-name: rubocop-capybara
  dependency-version: 2.23.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-30 07:04:07 +00:00
google-labs-jules[bot]andCloCkWeRX e423e6ac79 Add weekly harvest reminder emails and scheduled task
- Added `send_harvest_reminder` preference to Member model and settings UI.
- Implemented `harvest_in_next_week?` in PredictHarvest concern.
- Created `harvest_reminder` email with localized templates.
- Added `growstuff:send_harvest_reminders` Rake task to run weekly.
- Refactored existing and new reminder tasks to use `deliver_later` for scalability.
- Added unit tests for prediction logic and mailer.
- Fixed a bug in the existing planting reminder task where it was using an uninitialized constant `Notifier`.

Co-authored-by: CloCkWeRX <365751+CloCkWeRX@users.noreply.github.com>
2026-04-30 04:09:26 +00:00
Daniel O'Connorandgoogle-labs-jules[bot] e63089e03b Remove deprecated config.read_encrypted_secrets from production.rb (#4603)
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
2026-04-30 12:54:17 +09:30
Daniel O'Connor 6ce347af82 Rename FUNDING.yml to .github/FUNDING.yml 2026-04-28 18:11:48 +09:30
Daniel O'Connor 64af597dec Add funding information 2026-04-28 18:10:50 +09:30
7160f50ac1 Refactor Activity model to remove Elasticsearch integration (#4576)
* Refactor Activity model to remove Elasticsearch integration

- Removed `SearchActivities` concern and Searchkick from `Activity` model.
- Implemented `Activity.homepage_records` using ActiveRecord with `DISTINCT ON` for PostgreSQL.
- Updated `ActivitiesController#index` to use ActiveRecord queries with eager loading and pagination.
- Added `active` scope to `Activity`.
- Added unit tests for `Activity` model.
- Deleted `app/models/concerns/search_activities.rb`.

Co-authored-by: CloCkWeRX <365751+CloCkWeRX@users.noreply.github.com>

* Fix NoMethodError: undefined method 'reindex' for class Activity

- Removed all calls to `Activity.reindex` in migrations, rake tasks, and spec helpers.
- These were causing failures after the removal of Searchkick from the Activity model.

Co-authored-by: CloCkWeRX <365751+CloCkWeRX@users.noreply.github.com>

* Fix ambiguous column id in homepage_records query

- Updated `Activity.homepage_records` to use `activities.id` instead of `id` in the subquery.
- This resolves the `PG::AmbiguousColumn: ERROR: column reference "id" is ambiguous` error.

Co-authored-by: CloCkWeRX <365751+CloCkWeRX@users.noreply.github.com>

* Fix ambiguous created_at in homepage_records query

- Use `unscoped` in the subquery for `Activity.homepage_records` to bypass the default scope from `Ownable` concern.
- This prevents the join with the `members` table in the subquery, which was causing `PG::AmbiguousColumn: ERROR: column reference "created_at" is ambiguous`.

Co-authored-by: CloCkWeRX <365751+CloCkWeRX@users.noreply.github.com>

* Complete refactoring of Activity model to remove Elasticsearch

- Removed SearchActivities concern and searchkick integration.
- Updated ActivitiesController#index to use ActiveRecord queries.
- Implemented performant Activity.homepage_records using DISTINCT ON (PostgreSQL).
- Added Activity.active scope.
- Added no-op Activity.reindex (class and instance methods) for backward compatibility.
- Cleaned up leftover reindex calls in rake tasks, migrations, and spec helpers.
- Added unit tests for new Activity model logic.
- Updated factories to include no-op reindex traits.

Co-authored-by: CloCkWeRX <365751+CloCkWeRX@users.noreply.github.com>

* Less eager loading

---------

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
2026-04-28 17:51:01 +09:30
Daniel O'Connor e748da9a1f Merge pull request #4601 from Growstuff/links-wrong
Fix links further
2026-04-28 13:34:11 +09:30
Daniel O'Connor 4ac0dcb05b Merge branch 'dev' of https://github.com/Growstuff/growstuff into links-wrong 2026-04-28 04:03:44 +00:00
Daniel O'Connor 60390fcc06 Fix links further 2026-04-28 04:03:27 +00:00
98 changed files with 1042 additions and 457 deletions

No files matched your search

+1 -1
View File
@@ -1,7 +1,7 @@
FROM mcr.microsoft.com/devcontainers/ruby:3.4-trixie
# Install Rails
RUN gem install rails:7.0.8
RUN gem install rails:8.0.5
# Default value to allow debug server to serve content over GitHub Codespace's port forwarding service
# The value is a comma-separated list of allowed domains
+1
View File
@@ -0,0 +1 @@
ko_fi: jennyscottthompson
+1 -1
View File
@@ -38,7 +38,7 @@ jobs:
steps:
- name: Checkout this repo
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: Configure sysctl limits
run: |
+1 -1
View File
@@ -38,7 +38,7 @@ jobs:
steps:
- name: Checkout this repo
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: Configure sysctl limits
run: |
@@ -38,7 +38,7 @@ jobs:
steps:
- name: Checkout this repo
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: Configure sysctl limits
run: |
+1 -1
View File
@@ -38,7 +38,7 @@ jobs:
steps:
- name: Checkout this repo
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: Configure sysctl limits
run: |
+1 -1
View File
@@ -38,7 +38,7 @@ jobs:
steps:
- name: Checkout this repo
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: Configure sysctl limits
run: |
+1 -1
View File
@@ -38,7 +38,7 @@ jobs:
steps:
- name: Checkout this repo
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: Configure sysctl limits
run: |
+1 -1
View File
@@ -38,7 +38,7 @@ jobs:
steps:
- name: Checkout this repo
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: Configure sysctl limits
run: |
+1 -1
View File
@@ -38,7 +38,7 @@ jobs:
steps:
- name: Checkout this repo
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: Configure sysctl limits
run: |
+1 -1
View File
@@ -38,7 +38,7 @@ jobs:
steps:
- name: Checkout this repo
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: Configure sysctl limits
run: |
+1 -1
View File
@@ -38,7 +38,7 @@ jobs:
steps:
- name: Checkout this repo
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: Configure sysctl limits
run: |
+1 -1
View File
@@ -38,7 +38,7 @@ jobs:
steps:
- name: Checkout this repo
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: Configure sysctl limits
run: |
+1 -1
View File
@@ -38,7 +38,7 @@ jobs:
steps:
- name: Checkout this repo
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: Configure sysctl limits
run: |
+1 -1
View File
@@ -38,7 +38,7 @@ jobs:
steps:
- name: Checkout this repo
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: Configure sysctl limits
run: |
+1 -1
View File
@@ -38,7 +38,7 @@ jobs:
steps:
- name: Checkout this repo
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: Configure sysctl limits
run: |
+2 -2
View File
@@ -6,7 +6,7 @@ jobs:
contributors:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- name: Install ruby version specified in .ruby-version
uses: ruby/setup-ruby@v1
with:
@@ -53,7 +53,7 @@ jobs:
steps:
- name: Checkout this repo
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: Configure sysctl limits
run: |
+1 -1
View File
@@ -14,7 +14,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
+146 -54
View File
@@ -1,25 +1,31 @@
# This configuration was generated by
# `rubocop --auto-gen-config`
# on 2026-04-25 16:44:38 UTC using RuboCop version 1.86.1.
# on 2026-05-02 06:53:56 UTC using RuboCop version 1.86.1.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
# versions of RuboCop, may require this file to be generated again.
# Offense count: 19
Capybara/NegationMatcherAfterVisit:
# Offense count: 407
# This cop supports safe autocorrection (--autocorrect).
Capybara/RSpec/HaveContent:
Enabled: false
# Offense count: 21
Capybara/RSpec/NegationMatcherAfterVisit:
Exclude:
- 'spec/features/admin/reverting_crops_spec.rb'
- 'spec/features/crops/crop_detail_page_spec.rb'
- 'spec/features/crops/crop_wranglers_spec.rb'
- 'spec/features/gardens/gardens_spec.rb'
- 'spec/features/members/blocking_spec.rb'
- 'spec/features/members/deletion_spec.rb'
- 'spec/features/members/following_spec.rb'
- 'spec/features/members/profile_spec.rb'
- 'spec/features/plantings/planting_a_crop_spec.rb'
# Offense count: 14
Capybara/SpecificMatcher:
Capybara/RSpec/SpecificMatcher:
Exclude:
- 'spec/features/footer_spec.rb'
- 'spec/features/gardens/adding_gardens_spec.rb'
@@ -28,7 +34,7 @@ Capybara/SpecificMatcher:
- 'spec/features/seeds/adding_seeds_spec.rb'
# Offense count: 1
Capybara/VisibilityMatcher:
Capybara/RSpec/VisibilityMatcher:
Exclude:
- 'spec/features/shared_examples/crop_suggest.rb'
@@ -63,7 +69,13 @@ FactoryBot/ExcessiveCreateList:
- 'spec/features/crops/show_spec.rb'
- 'spec/features/percy/percy_spec.rb'
# Offense count: 312
# Offense count: 1
# This cop supports safe autocorrection (--autocorrect).
Layout/EmptyLines:
Exclude:
- 'config/environments/production.rb'
# Offense count: 311
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle.
# SupportedHashRocketStyles: key, separator, table
@@ -81,7 +93,7 @@ Layout/HashAlignment:
- 'spec/requests/api/v1/activities_request_spec.rb'
- 'spec/requests/api/v1/members_request_spec.rb'
# Offense count: 5
# Offense count: 8
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: Max, AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, AllowRBSInlineAnnotation, AllowCopDirectives, AllowedPatterns, SplitStrings.
# URISchemes: http, https
@@ -89,9 +101,20 @@ Layout/LineLength:
Exclude:
- 'Gemfile'
- 'app/controllers/admin/versions_controller.rb'
- 'app/controllers/crops_controller.rb'
- 'app/models/concerns/predict_planting.rb'
- 'app/models/crop.rb'
- 'db/seeds.rb'
- 'lib/tasks/members.rake'
# Offense count: 3
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle, IndentationWidth.
# SupportedStyles: aligned, indented, indented_relative_to_receiver
Layout/MultilineMethodCallIndentation:
Exclude:
- 'app/models/activity.rb'
- 'app/models/concerns/predict_harvest.rb'
# Offense count: 1
# This cop supports safe autocorrection (--autocorrect).
@@ -99,23 +122,15 @@ Lint/AmbiguousOperatorPrecedence:
Exclude:
- 'app/controllers/activities_controller.rb'
# Offense count: 4
# Offense count: 3
# This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: RequireParenthesesForMethodChains.
Lint/AmbiguousRange:
Exclude:
- 'app/models/concerns/search_activities.rb'
- 'app/models/concerns/search_harvests.rb'
- 'app/models/concerns/search_plantings.rb'
- 'db/seeds.rb'
# Offense count: 1
# This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: AllowSafeAssignment.
Lint/AssignmentInCondition:
Exclude:
- 'app/helpers/crops_helper.rb'
# Offense count: 1
# Configuration parameters: AllowedMethods.
# AllowedMethods: enums
@@ -158,7 +173,7 @@ Lint/UselessConstantScoping:
Exclude:
- 'app/controllers/members_controller.rb'
# Offense count: 61
# Offense count: 65
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes.
Metrics/AbcSize:
Max: 295
@@ -180,12 +195,12 @@ Metrics/CollectionLiteralLength:
Exclude:
- 'lib/tasks/import.rake'
# Offense count: 10
# Offense count: 11
# Configuration parameters: AllowedMethods, AllowedPatterns.
Metrics/CyclomaticComplexity:
Max: 32
# Offense count: 82
# Offense count: 83
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
Metrics/MethodLength:
Max: 296
@@ -195,7 +210,7 @@ Metrics/MethodLength:
Metrics/ModuleLength:
Max: 144
# Offense count: 8
# Offense count: 10
# Configuration parameters: AllowedMethods, AllowedPatterns.
Metrics/PerceivedComplexity:
Max: 32
@@ -209,6 +224,16 @@ Naming/PredicateMethod:
- 'app/models/concerns/finishable.rb'
- 'app/models/seed.rb'
# Offense count: 1
# Configuration parameters: NamePrefix, ForbiddenPrefixes, AllowedMethods, MethodDefinitionMacros, UseSorbetSigs.
# NamePrefix: is_, has_, have_, does_
# ForbiddenPrefixes: is_, has_, have_, does_
# AllowedMethods: is_a?
# MethodDefinitionMacros: define_method, define_singleton_method
Naming/PredicatePrefix:
Exclude:
- 'app/models/member.rb'
# Offense count: 3
RSpec/AnyInstance:
Exclude:
@@ -221,34 +246,54 @@ RSpec/BeEq:
Exclude:
- 'spec/requests/api/v1/activities_request_spec.rb'
# Offense count: 1
# Offense count: 2
RSpec/BeforeAfterAll:
Exclude:
- 'spec/tasks/import_spec.rb'
- 'spec/tasks/members_spec.rb'
# Offense count: 298
# Offense count: 311
# Configuration parameters: Prefixes, AllowedPatterns.
# Prefixes: when, with, without
RSpec/ContextWording:
Enabled: false
# Offense count: 36
# Offense count: 2
# Configuration parameters: IgnoredMetadata.
RSpec/DescribeClass:
Exclude:
- 'spec/models/harvest_prediction_spec.rb'
- 'spec/tasks/members_spec.rb'
# Offense count: 37
# This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: SkipBlocks, EnforcedStyle, OnlyStaticConstants.
# SupportedStyles: described_class, explicit
RSpec/DescribedClass:
Exclude:
- 'spec/mailers/harvest_reminder_mailer_spec.rb'
- 'spec/models/like_spec.rb'
- 'spec/models/member_spec.rb'
- 'spec/services/timeline_service_spec.rb'
# Offense count: 146
# Offense count: 1
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: AllowConsecutiveOneLiners.
RSpec/EmptyLineAfterExample:
Exclude:
- 'spec/controllers/crops_controller_spec.rb'
# Offense count: 1
# This cop supports safe autocorrection (--autocorrect).
RSpec/EmptyLineAfterFinalLet:
Exclude:
- 'spec/controllers/crops_controller_spec.rb'
# Offense count: 161
# Configuration parameters: CountAsOne.
RSpec/ExampleLength:
Max: 27
# Offense count: 32
# Offense count: 1
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle.
@@ -283,27 +328,18 @@ RSpec/IncludeExamples:
- 'spec/views/photos/show.html.haml_spec.rb'
- 'spec/views/seeds/index.rss.haml_spec.rb'
# Offense count: 37
# Offense count: 2
# Configuration parameters: Max, AllowedIdentifiers, AllowedPatterns.
RSpec/IndexedLet:
Exclude:
- 'spec/controllers/harvests_controller_spec.rb'
- 'spec/controllers/plantings_controller_spec.rb'
- 'spec/features/crops/crop_photos_spec.rb'
- 'spec/features/members/list_spec.rb'
- 'spec/features/members/profile_spec.rb'
- 'spec/features/percy/percy_spec.rb'
- 'spec/features/planting_reminder_spec.rb'
- 'spec/features/timeline/index_spec.rb'
- 'spec/models/member_spec.rb'
- 'spec/views/forums/index.html.haml_spec.rb'
- 'spec/models/activity_spec.rb'
# Offense count: 719
# Offense count: 711
# Configuration parameters: AssignmentOnly.
RSpec/InstanceVariable:
Enabled: false
# Offense count: 41
# Offense count: 43
RSpec/LetSetup:
Enabled: false
@@ -318,7 +354,7 @@ RSpec/MessageChain:
Exclude:
- 'spec/models/member_spec.rb'
# Offense count: 23
# Offense count: 65
# Configuration parameters: .
# SupportedStyles: have_received, receive
RSpec/MessageSpies:
@@ -329,11 +365,11 @@ RSpec/MultipleDescribes:
Exclude:
- 'spec/features/crops/crop_wranglers_spec.rb'
# Offense count: 191
# Offense count: 235
RSpec/MultipleExpectations:
Max: 19
# Offense count: 166
# Offense count: 171
# Configuration parameters: AllowSubject.
RSpec/MultipleMemoizedHelpers:
Max: 16
@@ -344,24 +380,35 @@ RSpec/MultipleMemoizedHelpers:
RSpec/NamedSubject:
Enabled: false
# Offense count: 109
# Offense count: 112
# Configuration parameters: AllowedGroups.
RSpec/NestedGroups:
Max: 6
# Offense count: 407
# Offense count: 366
# Configuration parameters: AllowedPatterns.
# AllowedPatterns: ^expect_, ^assert_
RSpec/NoExpectationExample:
Enabled: false
# Offense count: 4
# Offense count: 9
RSpec/PendingWithoutReason:
Exclude:
- 'spec/features/members/blocking_spec.rb'
- 'spec/features/plantings/planting_a_crop_spec.rb'
- 'spec/features/seeds/misc_seeds_spec.rb'
- 'spec/features/unsubscribing_spec.rb'
- 'spec/models/ability_spec.rb'
- 'spec/requests/api/v1/gardens_request_spec.rb'
# Offense count: 5
# This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: Strict, EnforcedStyle, AllowedExplicitMatchers.
# SupportedStyles: inflected, explicit
RSpec/PredicateMatcher:
Exclude:
- 'spec/tasks/members_spec.rb'
# Offense count: 2
RSpec/RepeatedDescription:
Exclude:
@@ -386,18 +433,18 @@ RSpec/ScatteredSetup:
- 'spec/features/percy/percy_spec.rb'
- 'spec/features/plantings/prediction_spec.rb'
# Offense count: 1
# Offense count: 2
# Configuration parameters: CustomTransform, IgnoreMethods, IgnoreMetadata, InflectorPath, EnforcedInflector.
# SupportedInflectors: default, active_support
RSpec/SpecFilePathFormat:
Exclude:
- 'spec/controllers/member_controller_spec.rb'
- 'spec/mailers/harvest_reminder_mailer_spec.rb'
# Offense count: 3
# Offense count: 2
RSpec/StubbedMock:
Exclude:
- 'spec/controllers/garden_types_controller_spec.rb'
- 'spec/controllers/gardens_controller_spec.rb'
- 'spec/controllers/photos_controller_spec.rb'
- 'spec/models/member_spec.rb'
# Offense count: 1
@@ -414,6 +461,13 @@ RSpec/VerifiedDoubles:
- 'spec/controllers/gardens_controller_spec.rb'
- 'spec/views/devise/shared/_links_spec.rb'
# Offense count: 1
# This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: Inferences.
RSpecRails/InferredSpecType:
Exclude:
- 'spec/mailers/harvest_reminder_mailer_spec.rb'
# Offense count: 30
# Configuration parameters: Database.
# SupportedDatabases: mysql, postgresql
@@ -470,11 +524,25 @@ Rails/HasManyOrHasOneDependent:
- 'app/models/crop.rb'
- 'app/models/member.rb'
# Offense count: 7
Rails/HelperInstanceVariable:
Exclude:
- 'app/helpers/crops_helper.rb'
- 'app/helpers/plantings_helper.rb'
# Offense count: 1
Rails/I18nLocaleAssignment:
Exclude:
- 'spec/features/locale_spec.rb'
# Offense count: 5
Rails/I18nLocaleTexts:
Exclude:
- 'app/controllers/blocks_controller.rb'
- 'app/controllers/comments_controller.rb'
- 'app/controllers/messages_controller.rb'
- 'config/initializers/comfortable_mexican_sofa.rb'
# Offense count: 1
# Configuration parameters: IgnoreScopes.
Rails/InverseOf:
@@ -488,6 +556,12 @@ Rails/LexicallyScopedActionFilter:
- 'app/controllers/data_controller.rb'
- 'app/controllers/registrations_controller.rb'
# Offense count: 1
# This cop supports unsafe autocorrection (--autocorrect-all).
Rails/OrderArguments:
Exclude:
- 'app/models/activity.rb'
# Offense count: 2
Rails/OutputSafety:
Exclude:
@@ -614,7 +688,7 @@ Rake/MethodDefinitionInTask:
Exclude:
- 'lib/tasks/growstuff.rake'
# Offense count: 4
# Offense count: 5
# This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: EnforcedStyle, EnforcedStyleForClasses, EnforcedStyleForModules.
# SupportedStyles: nested, compact
@@ -623,10 +697,17 @@ Rake/MethodDefinitionInTask:
Style/ClassAndModuleChildren:
Exclude:
- 'app/controllers/admin/crops_controller.rb'
- 'config/initializers/rack_attack.rb'
- 'lib/actions/oauth_signup_action.rb'
- 'lib/haml/filters/escaped_markdown.rb'
- 'lib/haml/filters/growstuff_markdown.rb'
# Offense count: 1
# This cop supports unsafe autocorrection (--autocorrect-all).
Style/CollectionQuerying:
Exclude:
- 'app/models/member.rb'
# Offense count: 6
# This cop supports unsafe autocorrection (--autocorrect-all).
Style/CommentedKeyword:
@@ -657,12 +738,13 @@ Style/FloatDivision:
Exclude:
- 'app/models/concerns/predict_planting.rb'
# Offense count: 1
# Offense count: 2
# This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: EnforcedStyle.
# SupportedStyles: always, always_true, never
Style/FrozenStringLiteralComment:
Exclude:
- 'db/migrate/20260429132911_add_send_harvest_reminder_to_members.rb'
- 'spec/lib/haml/filters/growstuff_markdown_spec.rb'
# Offense count: 2
@@ -678,11 +760,14 @@ Style/IdenticalConditionalBranches:
Exclude:
- 'lib/actions/oauth_signup_action.rb'
# Offense count: 1
# This cop supports unsafe autocorrection (--autocorrect-all).
Style/MapIntoArray:
# Offense count: 4
# This cop supports safe autocorrection (--autocorrect).
Style/IfUnlessModifier:
Exclude:
- 'app/helpers/crops_helper.rb'
- 'app/models/concerns/predict_planting.rb'
- 'config/initializers/rack_attack.rb'
- 'lib/tasks/growstuff.rake'
# Offense count: 1
# This cop supports unsafe autocorrection (--autocorrect-all).
@@ -736,6 +821,13 @@ Style/RedundantArgument:
Exclude:
- 'app/helpers/application_helper.rb'
# Offense count: 3
# This cop supports safe autocorrection (--autocorrect).
Style/RedundantBegin:
Exclude:
- 'app/models/concerns/predict_harvest.rb'
- 'app/models/harvest.rb'
# Offense count: 4
# This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: SafeForConstants.
+1 -1
View File
@@ -1 +1 @@
3.4.8
3.4.9
+2 -2
View File
@@ -1,4 +1,4 @@
FROM ruby:3.4.8-trixie
FROM ruby:3.4.9-trixie
# Install system dependencies
RUN apt-get update -qq && \
@@ -25,7 +25,7 @@ ENV RAILS_ENV=production \
WORKDIR /app
# Install gems
COPY Gemfile Gemfile.lock ./
COPY Gemfile Gemfile.lock .ruby-version ./
RUN bundle config set --local deployment 'true' && \
bundle config set --local without 'development test' && \
bundle install --jobs 4 --retry 3
+1 -1
View File
@@ -5,7 +5,7 @@ source 'https://rubygems.org'
# Match ruby version in .ruby-version
ruby File.read('.ruby-version')
gem 'rails', '~> 7.2.0'
gem 'rails', '~> 8.0.0'
# Keeping old sprockets
# https://github.com/rails/sprockets-rails/issues/444#issuecomment-637817050
+106 -107
View File
@@ -33,49 +33,46 @@ GEM
GEM
remote: https://rubygems.org/
specs:
actioncable (7.2.3.1)
actionpack (= 7.2.3.1)
activesupport (= 7.2.3.1)
actioncable (8.0.5)
actionpack (= 8.0.5)
activesupport (= 8.0.5)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
zeitwerk (~> 2.6)
actionmailbox (7.2.3.1)
actionpack (= 7.2.3.1)
activejob (= 7.2.3.1)
activerecord (= 7.2.3.1)
activestorage (= 7.2.3.1)
activesupport (= 7.2.3.1)
actionmailbox (8.0.5)
actionpack (= 8.0.5)
activejob (= 8.0.5)
activerecord (= 8.0.5)
activestorage (= 8.0.5)
activesupport (= 8.0.5)
mail (>= 2.8.0)
actionmailer (7.2.3.1)
actionpack (= 7.2.3.1)
actionview (= 7.2.3.1)
activejob (= 7.2.3.1)
activesupport (= 7.2.3.1)
actionmailer (8.0.5)
actionpack (= 8.0.5)
actionview (= 8.0.5)
activejob (= 8.0.5)
activesupport (= 8.0.5)
mail (>= 2.8.0)
rails-dom-testing (~> 2.2)
actionpack (7.2.3.1)
actionview (= 7.2.3.1)
activesupport (= 7.2.3.1)
cgi
actionpack (8.0.5)
actionview (= 8.0.5)
activesupport (= 8.0.5)
nokogiri (>= 1.8.5)
racc
rack (>= 2.2.4, < 3.3)
rack (>= 2.2.4)
rack-session (>= 1.0.1)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6)
useragent (~> 0.16)
actiontext (7.2.3.1)
actionpack (= 7.2.3.1)
activerecord (= 7.2.3.1)
activestorage (= 7.2.3.1)
activesupport (= 7.2.3.1)
actiontext (8.0.5)
actionpack (= 8.0.5)
activerecord (= 8.0.5)
activestorage (= 8.0.5)
activesupport (= 8.0.5)
globalid (>= 0.6.0)
nokogiri (>= 1.8.5)
actionview (7.2.3.1)
activesupport (= 7.2.3.1)
actionview (8.0.5)
activesupport (= 8.0.5)
builder (~> 3.1)
cgi
erubi (~> 1.11)
rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6)
@@ -89,22 +86,22 @@ GEM
active_utils (3.6.0)
activesupport (>= 4.2)
i18n
activejob (7.2.3.1)
activesupport (= 7.2.3.1)
activejob (8.0.5)
activesupport (= 8.0.5)
globalid (>= 0.3.6)
activemodel (7.2.3.1)
activesupport (= 7.2.3.1)
activerecord (7.2.3.1)
activemodel (= 7.2.3.1)
activesupport (= 7.2.3.1)
activemodel (8.0.5)
activesupport (= 8.0.5)
activerecord (8.0.5)
activemodel (= 8.0.5)
activesupport (= 8.0.5)
timeout (>= 0.4.0)
activestorage (7.2.3.1)
actionpack (= 7.2.3.1)
activejob (= 7.2.3.1)
activerecord (= 7.2.3.1)
activesupport (= 7.2.3.1)
activestorage (8.0.5)
actionpack (= 8.0.5)
activejob (= 8.0.5)
activerecord (= 8.0.5)
activesupport (= 8.0.5)
marcel (~> 1.0)
activesupport (7.2.3.1)
activesupport (8.0.5)
base64
benchmark (>= 0.3)
bigdecimal
@@ -113,17 +110,18 @@ GEM
drb
i18n (>= 1.6, < 2)
logger (>= 1.4.2)
minitest (>= 5.1, < 6)
minitest (>= 5.1)
securerandom (>= 0.3)
tzinfo (~> 2.0, >= 2.0.5)
uri (>= 0.13.1)
addressable (2.9.0)
public_suffix (>= 2.0.2, < 8.0)
ast (2.4.3)
autoprefixer-rails (10.4.16.0)
execjs (~> 2)
aws-eventstream (1.4.0)
aws-partitions (1.1240.0)
aws-sdk-core (3.245.0)
aws-partitions (1.1261.0)
aws-sdk-core (3.252.0)
aws-eventstream (~> 1, >= 1.3.0)
aws-partitions (~> 1, >= 1.992.0)
aws-sigv4 (~> 1.9)
@@ -131,24 +129,24 @@ GEM
bigdecimal
jmespath (~> 1, >= 1.6.1)
logger
aws-sdk-kms (1.123.0)
aws-sdk-core (~> 3, >= 3.244.0)
aws-sdk-kms (1.129.0)
aws-sdk-core (~> 3, >= 3.248.0)
aws-sigv4 (~> 1.5)
aws-sdk-s3 (1.220.0)
aws-sdk-core (~> 3, >= 3.244.0)
aws-sdk-s3 (1.226.0)
aws-sdk-core (~> 3, >= 3.248.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.5)
aws-sigv4 (1.12.1)
aws-eventstream (~> 1, >= 1.0.2)
axe-core-api (4.11.2)
axe-core-api (4.11.3)
dumb_delegator
ostruct
virtus
axe-core-capybara (4.11.2)
axe-core-api (= 4.11.2)
axe-core-capybara (4.11.3)
axe-core-api (= 4.11.3)
dumb_delegator
axe-core-rspec (4.11.2)
axe-core-api (= 4.11.2)
axe-core-rspec (4.11.3)
axe-core-api (= 4.11.3)
dumb_delegator
ostruct
virtus
@@ -177,7 +175,7 @@ GEM
actionpack (>= 6.1)
activemodel (>= 6.1)
builder (3.3.0)
bullet (8.1.1)
bullet (8.1.3)
activesupport (>= 3.0.0)
uniform_notifier (~> 1.11)
byebug (13.0.0)
@@ -205,7 +203,6 @@ GEM
image_processing (~> 1.1)
marcel (~> 1.0.0)
ssrf_filter (~> 1.0)
cgi (0.5.1)
chartkick (5.2.1)
childprocess (5.1.0)
logger (~> 1.5)
@@ -221,7 +218,7 @@ GEM
coffee-script-source (1.12.2)
comfy_bootstrap_form (4.0.9)
rails (>= 5.0.0)
concurrent-ruby (1.3.6)
concurrent-ruby (1.3.7)
connection_pool (2.5.5)
crass (1.0.6)
crowdin-api (1.12.0)
@@ -236,7 +233,7 @@ GEM
csv_shaper (1.4.0)
activesupport (>= 3.0.0)
csv
dalli (5.0.2)
dalli (5.0.5)
logger
database_cleaner (2.1.0)
database_cleaner-active_record (>= 2, < 3)
@@ -247,15 +244,15 @@ GEM
date (3.5.1)
descendants_tracker (0.0.4)
thread_safe (~> 0.3, >= 0.3.1)
devise (5.0.3)
devise (5.0.4)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
railties (>= 7.0)
responders
warden (~> 1.2.3)
diff-lcs (1.6.2)
discard (1.4.0)
activerecord (>= 4.2, < 9.0)
discard (2.0.0)
activerecord (>= 7.0, < 9.0)
domain_name (0.6.20240107)
dotenv (3.2.0)
dotenv-rails (3.2.0)
@@ -276,7 +273,7 @@ GEM
elasticsearch-transport (7.0.0)
faraday
multi_json
erb (6.0.2)
erb (6.0.4)
erubi (1.13.1)
execjs (2.10.0)
factory_bot (6.5.5)
@@ -286,18 +283,18 @@ GEM
railties (>= 6.1.0)
faker (3.8.0)
i18n (>= 1.8.11, < 2)
faraday (2.14.1)
faraday (2.14.3)
faraday-net_http (>= 2.0, < 3.5)
json
logger
faraday-net_http (3.4.2)
faraday-net_http (3.4.4)
net-http (~> 0.5)
ffi (1.17.3)
ffi (1.17.3-x86_64-linux-gnu)
flickraw (0.9.10)
font-awesome-sass (5.15.1)
sassc (>= 1.11)
friendly_id (5.6.0)
friendly_id (5.7.0)
activerecord (>= 4.0.0)
gbifrb (0.2.0)
geocoder (1.8.6)
@@ -322,7 +319,7 @@ GEM
activesupport (>= 5.1)
haml (>= 4.0.6)
railties (>= 5.1)
haml_lint (0.73.0)
haml_lint (0.74.0)
haml (>= 5.0)
parallel (>= 1.10)
rainbow
@@ -339,7 +336,7 @@ GEM
csv
mini_mime (>= 1.0.0)
multi_xml (>= 0.5.2)
i18n (1.14.8)
i18n (1.15.2)
concurrent-ruby (~> 1.0)
i18n-tasks (1.1.2)
activesupport (>= 4.0.2)
@@ -355,7 +352,7 @@ GEM
terminal-table (>= 1.5.1)
i18n_data (1.1.0)
simple_po_parser (~> 1.1)
icalendar (2.12.2)
icalendar (2.12.3)
base64
ice_cube (~> 0.16)
logger
@@ -366,7 +363,7 @@ GEM
mini_magick (>= 4.9.5, < 5)
ruby-vips (>= 2.0.17, < 3)
io-console (0.8.2)
irb (1.17.0)
irb (1.18.0)
pp (>= 0.6.0)
prism (>= 1.3.0)
rdoc (>= 4.0.0)
@@ -376,7 +373,7 @@ GEM
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
json (2.19.3)
json (2.19.9)
json-schema (6.2.0)
addressable (~> 2.8)
bigdecimal (>= 3.1, < 5)
@@ -435,14 +432,16 @@ GEM
mini_magick (4.12.0)
mini_mime (1.1.5)
mini_portile2 (2.8.9)
minitest (5.27.0)
msgpack (1.8.0)
minitest (6.0.6)
drb (~> 2.0)
prism (~> 1.5)
msgpack (1.8.3)
multi_json (1.19.1)
multi_xml (0.8.1)
bigdecimal (>= 3.1, < 5)
net-http (0.9.1)
uri (>= 0.11.1)
net-imap (0.5.12)
net-imap (0.6.4.1)
date
net-protocol
net-pop (0.1.2)
@@ -453,13 +452,13 @@ GEM
net-protocol
netrc (0.11.0)
nio4r (2.7.5)
nokogiri (1.19.2)
nokogiri (1.19.4)
mini_portile2 (~> 2.8.2)
racc (~> 1.4)
nokogiri (1.19.2-x86_64-linux-gnu)
nokogiri (1.19.4-x86_64-linux-gnu)
racc (~> 1.4)
oauth (0.5.6)
oj (3.17.0)
oj (3.17.3)
bigdecimal (>= 3.0)
ostruct (>= 0.2)
omniauth (1.9.2)
@@ -477,7 +476,7 @@ GEM
paper_trail (17.0.0)
activerecord (>= 7.1)
request_store (~> 1.4)
parallel (2.0.1)
parallel (2.1.0)
parser (3.3.11.1)
ast (~> 2.4.1)
racc
@@ -498,7 +497,7 @@ GEM
date
stringio
public_suffix (7.0.5)
puma (8.0.1)
puma (8.0.2)
nio4r (~> 2.0)
query_diet (0.7.3)
racc (1.8.1)
@@ -517,20 +516,20 @@ GEM
rackup (1.0.1)
rack (< 3)
webrick
rails (7.2.3.1)
actioncable (= 7.2.3.1)
actionmailbox (= 7.2.3.1)
actionmailer (= 7.2.3.1)
actionpack (= 7.2.3.1)
actiontext (= 7.2.3.1)
actionview (= 7.2.3.1)
activejob (= 7.2.3.1)
activemodel (= 7.2.3.1)
activerecord (= 7.2.3.1)
activestorage (= 7.2.3.1)
activesupport (= 7.2.3.1)
rails (8.0.5)
actioncable (= 8.0.5)
actionmailbox (= 8.0.5)
actionmailer (= 8.0.5)
actionpack (= 8.0.5)
actiontext (= 8.0.5)
actionview (= 8.0.5)
activejob (= 8.0.5)
activemodel (= 8.0.5)
activerecord (= 8.0.5)
activestorage (= 8.0.5)
activesupport (= 8.0.5)
bundler (>= 1.15.0)
railties (= 7.2.3.1)
railties (= 8.0.5)
rails-controller-testing (1.0.5)
actionpack (>= 5.0.1.rc1)
actionview (>= 5.0.1.rc1)
@@ -542,18 +541,17 @@ GEM
rails-html-sanitizer (1.7.0)
loofah (~> 2.25)
nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
rails-i18n (7.0.10)
rails-i18n (8.1.0)
i18n (>= 0.7, < 2)
railties (>= 6.0.0, < 8)
railties (>= 8.0.0, < 9)
rails_12factor (0.0.3)
rails_serve_static_assets
rails_stdout_logging
rails_serve_static_assets (0.0.5)
rails_stdout_logging (0.0.5)
railties (7.2.3.1)
actionpack (= 7.2.3.1)
activesupport (= 7.2.3.1)
cgi
railties (8.0.5)
actionpack (= 8.0.5)
activesupport (= 8.0.5)
irb (~> 1.13)
rackup (>= 1.0.0)
rake (>= 12.2)
@@ -630,7 +628,7 @@ GEM
rswag-ui (2.17.0)
actionpack (>= 5.2, < 8.2)
railties (>= 5.2, < 8.2)
rubocop (1.86.1)
rubocop (1.88.0)
json (~> 2.3)
language_server-protocol (~> 3.17.0.2)
lint_roller (~> 1.1.0)
@@ -644,13 +642,13 @@ GEM
rubocop-ast (1.49.1)
parser (>= 3.3.7.2)
prism (~> 1.7)
rubocop-capybara (2.22.1)
rubocop-capybara (3.0.0)
lint_roller (~> 1.1)
rubocop (~> 1.72, >= 1.72.1)
rubocop (~> 1.81)
rubocop-factory_bot (2.28.0)
lint_roller (~> 1.1)
rubocop (~> 1.72, >= 1.72.1)
rubocop-rails (2.34.3)
rubocop-rails (2.35.5)
activesupport (>= 4.2.0)
lint_roller (~> 1.1)
rack (>= 1.1)
@@ -659,9 +657,10 @@ GEM
rubocop-rake (0.7.1)
lint_roller (~> 1.1)
rubocop (>= 1.72.1)
rubocop-rspec (3.9.0)
rubocop-rspec (3.10.2)
lint_roller (~> 1.1)
rubocop (~> 1.81)
regexp_parser (>= 2.0)
rubocop (~> 1.86, >= 1.86.2)
rubocop-rspec_rails (2.32.0)
lint_roller (~> 1.1)
rubocop (~> 1.72, >= 1.72.1)
@@ -670,7 +669,7 @@ GEM
ruby-units (4.1.0)
ruby-vips (2.2.1)
ffi (~> 1.12)
rubyzip (3.2.2)
rubyzip (3.4.0)
sass (3.7.4)
sass-listen (~> 4.0.0)
sass-listen (4.0.0)
@@ -690,7 +689,7 @@ GEM
activemodel (>= 6.1)
hashie
securerandom (0.4.1)
selenium-webdriver (4.43.0)
selenium-webdriver (4.45.0)
base64 (~> 0.2)
logger (~> 1.4)
rexml (~> 3.2, >= 3.2.5)
@@ -725,7 +724,7 @@ GEM
thread_safe (0.3.6)
tilt (2.7.0)
timecop (0.9.11)
timeout (0.5.0)
timeout (0.6.1)
tsort (0.2.0)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
@@ -846,7 +845,7 @@ DEPENDENCIES
rack-attack
rack-cors
rack-protection (>= 2.0.1)
rails (~> 7.2.0)
rails (~> 8.0.0)
rails-assets-leaflet.markercluster!
rails-controller-testing
rails_12factor
@@ -886,7 +885,7 @@ DEPENDENCIES
xmlrpc
RUBY VERSION
ruby 3.4.8p72
ruby 3.4.9
BUNDLED WITH
2.4.22
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "growstuff",
"stack": "heroku-18",
"stack": "heroku-26",
"description": "Open data project for small-scale food growers",
"scripts": {
"postdeploy": "bundle exec rails db:seed"
+5 -10
View File
@@ -4,21 +4,16 @@ class ActivitiesController < DataController
def index
@show_all = params[:all] == '1'
where = {}
where['active'] = true unless @show_all
@activities = Activity.includes(:owner).order(created_at: :desc)
@activities = @activities.active unless @show_all
if params[:member_slug].present?
@owner = Member.find_by!(slug: params[:member_slug])
where['owner_id'] = @owner.id
@activities = @activities.where(owner_id: @owner.id)
end
@activities = Activity.search(
where:,
page: params[:page],
limit: 30,
boost_by: [:created_at],
load: false
)
@activities = @activities.paginate(page: params[:page], per_page: 30)
@filename = "Growstuff-#{specifics}Activities-#{Time.zone.now.to_fs(:number)}.csv"
respond_with(@activities)
end
@@ -3,6 +3,36 @@
module Api
module V1
class CropsController < BaseController
def search
term = params[:term]
page = params.dig(:page, :number) || 1
per_page = params.dig(:page, :size) || Crop.per_page
search_results = CropSearchService.search(
term,
page: page,
per_page: per_page,
load: true
)
resources = search_results.map do |crop|
Api::V1::CropResource.new(crop, context)
end
serializer = JSONAPI::ResourceSerializer.new(Api::V1::CropResource)
data = resources.map do |resource|
serializer.object_hash(resource, {})
end
render json: {
data: data,
meta: {
record_count: search_results.total_count,
page_count: search_results.total_pages
}
}
end
end
end
end
+2 -2
View File
@@ -68,7 +68,7 @@ class ApplicationController < ActionController::Base
# profile stuff
:bio, :location, :latitude, :longitude,
# email settings
:show_email, :newsletter, :send_notification_email, :send_planting_reminder)
:show_email, :newsletter, :send_notification_email, :send_planting_reminder, :send_harvest_reminder)
end
devise_parameter_sanitizer.permit(:account_update) do |member|
@@ -80,7 +80,7 @@ class ApplicationController < ActionController::Base
:bio, :location, :latitude, :longitude,
:website_url, :instagram_handle, :facebook_handle, :bluesky_handle, :other_url,
# email settings
:show_email, :newsletter, :send_notification_email, :send_planting_reminder,
:show_email, :newsletter, :send_notification_email, :send_planting_reminder, :send_harvest_reminder,
# update password
:current_password)
end
+1 -1
View File
@@ -13,7 +13,7 @@ class CropsController < ApplicationController
@crops = Crop.search('*', boost_by: %i(plantings_count harvests_count),
limit: 100,
page: params[:page],
load: false)
load: (request.format.csv? || request.format.rss? ? { include: %i(parent scientific_names seeds harvests creator plantings) } : false))
@num_requested_crops = requested_crops.size if current_member
@filename = filename
respond_with @crops
+12 -1
View File
@@ -57,12 +57,23 @@ class GardensController < DataController
redirect_to(member_gardens_path(@garden.owner))
end
def fetch_wikidata
if @garden.populate_wikidata_info
@garden.save
flash[:notice] = "Wikidata information updated."
else
flash[:alert] = "Could not find Wikidata information for this location."
end
redirect_to @garden
end
private
def garden_params
params.require(:garden).permit(
:name, :slug, :description, :active,
:location, :latitude, :longitude, :area, :area_unit, :garden_type_id
:location, :latitude, :longitude, :area, :area_unit, :garden_type_id,
:location_wikidata_id, :lowest_temp_c, :highest_temp_c
)
end
end
+23 -7
View File
@@ -23,7 +23,7 @@ class HarvestsController < DataController
@harvests = Harvest.search('*', where:,
limit: 100,
page: params[:page],
load: false,
load: (request.format.csv? ? { include: %i(crop owner plant_part) } : false),
boost_by: [:created_at])
@filename = csv_filename
@@ -38,9 +38,9 @@ class HarvestsController < DataController
end
def new
@harvest = Harvest.new(harvested_at: Time.zone.today)
@planting = Planting.find_by(slug: params[:planting_slug]) if params[:planting_slug]
@crop = Crop.find_by(id: params[:crop_id])
@harvest = Harvest.new(new_harvest_params.merge(harvested_at: Time.zone.today))
@planting = @harvest.planting
@crop = @harvest.crop
respond_with(@harvest)
end
@@ -52,7 +52,7 @@ class HarvestsController < DataController
def create
@harvest.crop_id = @harvest.planting.crop_id if @harvest.planting_id
@harvest.harvested_at = Time.zone.now if @harvest.harvested_at.blank?
@harvest.save
update_planting_rating if @harvest.save
if params[:return] == 'planting'
respond_with(@harvest, location: @harvest.planting)
else
@@ -61,7 +61,7 @@ class HarvestsController < DataController
end
def update
@harvest.update(harvest_params)
update_planting_rating if @harvest.update(harvest_params)
respond_with(@harvest)
end
@@ -76,7 +76,17 @@ class HarvestsController < DataController
params.require(:harvest)
.permit(:planting_id, :crop_id, :harvested_at, :description,
:quantity, :unit, :weight_quantity, :weight_unit,
:plant_part_id, :slug, :si_weight)
:plant_part_id, :slug, :si_weight, :overall_rating)
.merge(owner_id: current_member.id)
end
def new_harvest_params
return {} unless params[:harvest]
params.require(:harvest)
.permit(:planting_id, :crop_id, :harvested_at, :description,
:quantity, :unit, :weight_quantity, :weight_unit,
:plant_part_id, :slug, :si_weight, :overall_rating)
.merge(owner_id: current_member.id)
end
@@ -103,4 +113,10 @@ class HarvestsController < DataController
@harvest.planting.update_harvest_days!
@harvest.crop.update_harvest_medians
end
def update_planting_rating
return if @harvest.planting.nil? || params[:harvest][:overall_rating].blank?
@harvest.planting.update(overall_rating: params[:harvest][:overall_rating])
end
end
+2 -2
View File
@@ -11,7 +11,7 @@ class LikesController < ApplicationController
likeable_id: params[:id]
)
if @like.likeable && @like.save
@like.likeable.reindex(refresh: true)
@like.likeable.reindex(refresh: true) if @like.likeable.respond_to?(:reindex)
success(@like, liked_by_member: true, status_code: :created)
else
failed(@like, message: t('messages.unable_to_like'))
@@ -26,7 +26,7 @@ class LikesController < ApplicationController
)
if @like&.destroy
@like.likeable.reindex(refresh: true)
@like.likeable.reindex(refresh: true) if @like.likeable.respond_to?(:reindex)
success(@like, liked_by_member: false, status_code: :ok)
else
failed(@like, message: t('messages.unable_to_unlike'))
+3 -2
View File
@@ -90,11 +90,12 @@ class MembersController < ApplicationController
EMAIL_TYPE_STRING = {
send_notification_email: "direct message notifications",
send_planting_reminder: "planting reminders"
send_planting_reminder: "planting reminders",
send_harvest_reminder: "harvest reminders"
}.freeze
def member_params
params.require(:member).permit(:login_name, :tos_agreement, :email, :newsletter)
params.require(:member).permit(:login_name, :tos_agreement, :email, :newsletter, :send_harvest_reminder)
end
def member_json_fields
+11 -19
View File
@@ -9,13 +9,17 @@ class PhotosController < ApplicationController
responders :flash
def index
@photos = Photo.search(
load: false,
boost_by: [:created_at],
where: index_where_clause,
page: params[:page],
limit: Photo.per_page
)
@photos = if @crop
@crop.photos
elsif @planting
@planting.photos
else
Photo.all
end
@photos = @photos.includes(:owner)
.order(created_at: :desc)
.paginate(page: params[:page], per_page: Photo.per_page)
respond_with(@photos)
end
@@ -114,18 +118,6 @@ class PhotosController < ApplicationController
end
end
def index_where_clause
if params[:crop_slug]
{ crops: @crop.id }
elsif params[:planting_id]
{ planting_id: @planting.id }
elsif params[:planting_slug]
{ plantings: @planting.id }
else
{}
end
end
def set_crop_and_planting
@crop = Crop.find params[:crop_slug] if params[:crop_slug]
@planting = Planting.find params[:planting_id] if params[:planting_id]
+4
View File
@@ -21,6 +21,10 @@ class PostsController < ApplicationController
def new
@post = Post.new
@forum = Forum.find_by(id: params[:forum_id])
if params[:crop_id]
@crop = Crop.friendly.find(params[:crop_id])
@post.body = "[#{@crop.name}](crop)"
end
respond_with(@post)
end
+1 -1
View File
@@ -30,7 +30,7 @@ class SeedsController < DataController
page: params[:page],
limit: 30,
boost_by: [:created_at],
load: false
load: (request.format.csv? ? { include: %i(crop owner) } : false)
)
respond_with(@seeds)
+13
View File
@@ -57,6 +57,19 @@ class NotifierMailer < ApplicationMailer
mail(to: @member.email, subject: @subject) if @member.send_planting_reminder
end
def harvest_reminder(member)
@member = member
@plantings = @member.plantings.active.select(&:harvest_in_next_week?)
@sitename = ENV.fetch('GROWSTUFF_SITE_NAME', nil)
@subject = I18n.t('notifier_mailer.harvest_reminder.subject', sitename: @sitename)
# Encrypting
message = { member_id: @member.id, type: :send_harvest_reminder }
@signed_message = verifier.generate(message)
mail(to: @member.email, subject: @subject) if @member.send_harvest_reminder
end
def new_crop_request(member, request)
@member = member
@request = request
+1
View File
@@ -123,6 +123,7 @@ class Ability
can :create, GardenCollaborator, garden: { owner_id: member.id }
can :update, GardenCollaborator, garden: { owner_id: member.id }
can :destroy, GardenCollaborator, garden: { owner_id: member.id }
can :destroy, GardenCollaborator, member_id: member.id
can :create, Activity
can :update, Activity, owner_id: member.id
+13 -1
View File
@@ -4,7 +4,6 @@ class Activity < ApplicationRecord
extend FriendlyId
include Ownable
include Finishable
include SearchActivities
include Likeable
belongs_to :garden, optional: true
@@ -46,4 +45,17 @@ class Activity < ApplicationRecord
def planting_slug
planting&.crop&.slug
end
scope :active, -> { where(finished: [false, nil]) }
def self.homepage_records(limit)
# Get the latest activity for each owner, then return the latest 'limit' of those
Activity.where(id: Activity.unscoped.select("DISTINCT ON (owner_id) id").order("owner_id, created_at DESC"))
.order(created_at: :desc)
.limit(limit)
end
def self.reindex(refresh: false); end
def reindex(refresh: false); end
end
+7 -1
View File
@@ -60,10 +60,16 @@ module PredictHarvest
def before_harvest_time?
first_harvest_predicted_at.present? &&
harvests.empty? &&
first_harvest_predicted_at.present? &&
first_harvest_predicted_at > Time.zone.today
end
def harvest_in_next_week?
first_harvest_predicted_at.present? &&
harvests.empty? &&
first_harvest_predicted_at >= Time.zone.today &&
first_harvest_predicted_at <= Time.zone.today + 7.days
end
def harvest_months
Rails.cache.fetch("#{cache_key_with_version}/harvest_months", expires_in: 5.minutes) do
neighbours_for_harvest_predictions.where.not(harvested_at: nil)
-66
View File
@@ -1,66 +0,0 @@
# frozen_string_literal: true
module SearchActivities
extend ActiveSupport::Concern
included do
searchkick merge_mappings: true,
settings: { number_of_shards: 1, number_of_replicas: 0 },
mappings: {
properties: {
active: { type: :boolean },
created_at: { type: :integer },
updated_at: { type: :integer },
due_date: { type: :date }
}
}
def search_data
{
slug:,
active:,
finished: finished?,
name:,
due_date:,
category:,
garden_id:,
garden_name: garden&.name,
garden_slug: garden&.garden_slug,
planting_id:,
planting_name: planting&.crop&.name,
planting_slug: planting&.slug,
description:,
# owner
owner_id:,
owner_login_name:,
owner_slug:,
# timestamps
created_at: created_at.to_i,
updated_at: updated_at.to_i
}
end
def self.homepage_records(limit)
records = []
owners = []
1..limit.times do
where = {
# photos_count: { gt: 0 },
owner_id: { not: owners }
}
one_record = search('*',
limit: 1,
where:,
boost_by: [:created_at],
load: false).first
return records if one_record.nil?
owners << one_record.owner_id
records << one_record
end
records
end
end
end
-37
View File
@@ -1,37 +0,0 @@
# frozen_string_literal: true
module SearchPhotos
extend ActiveSupport::Concern
included do
searchkick merge_mappings: true,
settings: { number_of_shards: 1, number_of_replicas: 0 },
mappings: {
properties: {
title: { type: :text },
created_at: { type: :integer }
}
}
def search_data
{
id:,
title:,
thumbnail_url:,
fullsize_url:,
# crops
crops: crops.pluck(:id),
# likes
liked_by_members_names:,
# owner
owner_id:,
owner_login_name:,
owner_slug:,
# counts
likes_count:,
created_at: created_at.to_i
}
end
end
end
+5 -3
View File
@@ -165,9 +165,11 @@ class Crop < ApplicationRecord
end
def all_companions
return companions unless parent
(companions + parent.all_companions).uniq
@all_companions ||= if parent
(companions + parent.all_companions).uniq
else
companions
end
end
before_destroy :destroy_reverse_companionships
+14
View File
@@ -21,6 +21,7 @@ class Garden < ApplicationRecord
after_validation :cleanup_area
after_validation :geocode
after_validation :empty_unwanted_geocodes
after_validation :populate_wikidata_info, if: :will_save_change_to_location?
after_save :mark_inactive_garden_plantings_as_finished
scope :active, -> { where(active: true) }
@@ -92,6 +93,19 @@ class Garden < ApplicationRecord
end
end
def populate_wikidata_info
return false if location.blank?
wd_id = WikidataService.find_wikidata_id(location)
return false if wd_id.blank?
self.location_wikidata_id = wd_id
temps = WikidataService.fetch_temps(wd_id)
self.highest_temp_c = temps[:highest_temp_c]
self.lowest_temp_c = temps[:lowest_temp_c]
true
end
protected
def strip_blanks
+2
View File
@@ -8,6 +8,8 @@ class Harvest < ApplicationRecord
include SearchHarvests
include Likeable
attr_accessor :overall_rating
friendly_id :harvest_slug, use: %i(slugged finders)
# Constants
+2 -1
View File
@@ -79,6 +79,7 @@ class Member < ApplicationRecord
scope :interesting, -> { confirmed.located.recently_signed_in.has_plantings }
scope :has_plantings, -> { joins(:plantings).group("members.id") }
scope :wants_reminders, -> { where(send_planting_reminder: true) }
scope :wants_harvest_reminders, -> { where(send_harvest_reminder: true) }
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
@@ -161,7 +162,7 @@ class Member < ApplicationRecord
end
def unread_count
receipts.where(is_read: false).count
@unread_count ||= receipts.where(is_read: false).count
end
def self.login_name_or_email(login)
-1
View File
@@ -3,7 +3,6 @@
class Photo < ApplicationRecord
include Likeable
include Ownable
include SearchPhotos
PHOTO_CAPABLE = %w(Garden Planting Harvest Seed Post Crop).freeze
+2 -2
View File
@@ -2,7 +2,7 @@
class CropSearchService
# Crop.search(string)
def self.search(query, page: 1, per_page: 12, current_member: nil)
def self.search(query, page: 1, per_page: 12, current_member: nil, **options)
search_params = {
page:,
per_page:,
@@ -12,7 +12,7 @@ class CropSearchService
includes: %i(scientific_names alternate_names),
misspellings: { edit_distance: 2 },
load: false
}
}.merge(options)
# prioritise crops the member has planted
search_params[:boost_where] = { planters_ids: current_member.id } if current_member
+74
View File
@@ -0,0 +1,74 @@
# frozen_string_literal: true
require 'net/http'
require 'json'
class WikidataService
CELSIUS_UNIT_ID = 'http://www.wikidata.org/entity/Q25267'
FAHRENHEIT_UNIT_ID = 'http://www.wikidata.org/entity/Q42289'
def self.find_wikidata_id(location_name)
return nil if location_name.blank?
uri = URI("https://www.wikidata.org/w/api.php?action=wbsearchentities&search=#{URI.encode_www_form_component(location_name)}&language=en&format=json")
req = Net::HTTP::Get.new(uri)
req['User-Agent'] = "Growstuff (https://www.growstuff.org; admin@growstuff.org)"
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
data = JSON.parse(response.body)
data.dig('search', 0, 'id')
rescue StandardError => e
Rails.logger.error "WikidataService.find_wikidata_id error: #{e.message}"
nil
end
def self.fetch_temps(wikidata_id)
return {} if wikidata_id.blank?
uri = URI("https://www.wikidata.org/w/api.php?action=wbgetentities&ids=#{wikidata_id}&props=claims&format=json")
req = Net::HTTP::Get.new(uri)
req['User-Agent'] = "Growstuff (https://www.growstuff.org; admin@growstuff.org)"
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
data = JSON.parse(response.body)
claims = data.dig('entities', wikidata_id, 'claims') || {}
highest_temp = extract_temp(claims['P6591'])
lowest_temp = extract_temp(claims['P7422'])
{
highest_temp_c: highest_temp,
lowest_temp_c: lowest_temp
}
rescue StandardError => e
Rails.logger.error "WikidataService.fetch_temps error: #{e.message}"
{}
end
def self.extract_temp(claim_data)
return nil if claim_data.blank?
# We take the first value
main_snak = claim_data.first&.dig('mainsnak')
return nil unless main_snak&.dig('datavalue', 'type') == 'quantity'
quantity_data = main_snak.dig('datavalue', 'value')
amount = quantity_data['amount'].to_f
unit = quantity_data['unit']
case unit
when CELSIUS_UNIT_ID
amount
when FAHRENHEIT_UNIT_ID
(amount - 32) * 5.0 / 9.0
else
nil
end
end
end
+1 -1
View File
@@ -3,7 +3,7 @@
- content_for :breadcrumbs do
- if @owner
%li.breadcrumb-item= link_to 'Activities', activities_path
%li.breadcrumb-item.active= link_to "#{@owner}'s activities", activities_path(@owner)
%li.breadcrumb-item.active= link_to "#{@owner}'s activities", member_activities_path(@owner)
- else
%li.breadcrumb-item.active= link_to 'Activities', activities_path
+3
View File
@@ -5,5 +5,8 @@
= render 'plantings/modal', planting: Planting.new(crop: crop, owner: current_member)
= render 'harvests/modal', harvest: Harvest.new(crop: @crop, owner: current_member)
= render 'seeds/modal', seed: Seed.new(crop: @crop, owner: current_member)
= link_to new_post_path(crop_id: crop.slug), class: 'btn', id: 'post-button' do
= post_icon
Post
- if active_plantings.any?
= render 'plantings/failed_modal', crop: crop, active_plantings: active_plantings
+1 -1
View File
@@ -17,7 +17,7 @@
%li.list-group-item= link_to "View all #{crop.name} harvests", crop_harvests_path(crop), class: 'card-link'
- if crop.approved?
- if current_member
%li.list-group-item= link_to "Harvest #{crop.name}", new_harvest_path(crop_id: crop.id), class: 'btn btn-block'
%li.list-group-item= link_to "Harvest #{crop.name}", new_harvest_path(harvest: { crop_id: crop.id }), class: 'btn btn-block'
- else
%li.list-group-item.active
= icon 'fas', 'user'
+1 -1
View File
@@ -6,7 +6,7 @@
Nobody has posted about #{crop.name.pluralize} yet.
%p
- if can? :create, Post
= link_to "Post something", new_post_path, class: 'btn btn-default'
= link_to "Post something", new_post_path(crop_id: crop.slug), class: 'btn btn-default'
- else
= render partial: "shared/signin_signup",
locals: { to: "post your tips and experiences growing #{crop.name.pluralize}" }
+9 -8
View File
@@ -44,8 +44,10 @@ csv.headers *all_headers
@crops.each do |c|
csv.row c do |csv, crop|
csv.cells :id, :name, :en_wikipedia_url
csv.cell :growstuff_url, crop_url(c)
csv.cell :id, c.id
csv.cell :name, c.name
csv.cell :en_wikipedia_url, c.en_wikipedia_url
csv.cell :growstuff_url, crop_url(slug: c.slug)
if c.scientific_names.any?
csv.cell :default_scientific_name, c.default_scientific_name
@@ -58,10 +60,10 @@ csv.headers *all_headers
end
csv.cell :plantings_count, c.plantings_count || 0
csv.cell :seeds_count, c.seeds.size[]
csv.cell :seeds_count, c.seeds.size
csv.cell :harvests_count, c.harvests.size
# Sunniness
# Sunniness
sunniness = c.sunniness
sunniness_rec = sunniness.max_by{|k,v| v}
@@ -74,7 +76,7 @@ csv.headers *all_headers
# Planted from
planted_from = c.planted_from
planted_from = c.planted_from
planted_from_rec = planted_from.max_by{|k,v| v}
if planted_from_rec
csv.cell :plant_from_recommendation, planted_from_rec[0]
@@ -105,12 +107,11 @@ csv.headers *all_headers
csv.cell col, harvested_plant_parts[pp] || 0
end
csv.cell :added_by_member_id, c.creator.id
csv.cell :added_by_member_name, c.creator.to_s
csv.cell :added_by_member_id, c.creator&.id
csv.cell :added_by_member_name, c.creator&.to_s
csv.cell :date_added, c.created_at.to_fs(:db)
csv.cell :last_modified, c.updated_at.to_fs(:db)
csv.cell :license, "CC-BY-SA Growstuff http://growstuff.org/"
end
end
+5 -4
View File
@@ -36,10 +36,11 @@
= cute_icon
= render 'predictions', crop: @crop
- if @crop.all_companions.any?
%section.companions
%h2 Companions
- @crop.all_companions.each do |companion|
= render 'crops/tiny', crop: companion
- cache [@crop, 'companions'] do
%section.companions
%h2 Companions
- @crop.all_companions.each do |companion|
= render 'crops/tiny', crop: companion
- if crop_or_parent(@crop, :en_youtube_url).present?
%section.youtube
@@ -28,6 +28,12 @@
= f.check_box :send_planting_reminder
Receive regular reminders to track your planting and harvesting.
.form-group
.col-md-offset-2.col-md-8.checkbox
%label
= f.check_box :send_harvest_reminder
Receive regular reminders of upcoming harvests.
.form-group
.col-md-offset-2.col-md-8.checkbox
%label
+27
View File
@@ -102,6 +102,8 @@
%strong Collaborators:
- if can?(:create, GardenCollaborator.new(garden: @garden))
= link_to "Manage", garden_garden_collaborators_path(@garden)
- elsif current_member.present? && (collab = @garden.garden_collaborators.find_by(member: current_member))
= link_to "Leave garden", garden_garden_collaborator_path(@garden, collab), method: :delete, class: 'text-danger', data: { confirm: 'Are you sure you want to leave this garden?' }
- if @garden.garden_collaborators.any?
%ul
- @garden.garden_collaborators.each do |collabator|
@@ -122,6 +124,31 @@
%strong Garden type:
= @garden.garden_type.name
- if @garden.location_wikidata_id.present?
%hr
%p
%small
Data about this location from
= link_to "wikidata", "https://www.wikidata.org/wiki/#{@garden.location_wikidata_id}", target: '_blank', rel: 'noopener noreferrer'
%p
%strong Highest temperature:
- if @garden.highest_temp_c.present?
= "#{ @garden.highest_temp_c.round(1) }°C"
- else
Not known
%p
%strong Lowest temperature:
- if @garden.lowest_temp_c.present?
= "#{ @garden.lowest_temp_c.round(1) }°C"
- else
Not known
- elsif can?(:edit, @garden) && @garden.location.present?
.alert.alert-info
%p Wikidata information is missing for this location.
= button_to "Fetch Wikidata info", fetch_wikidata_garden_path(@garden), method: :post, class: 'btn btn-info btn-sm'
.card
.card-header
%h4 #{@garden.owner}'s gardens
+11
View File
@@ -52,6 +52,17 @@
= f.select(:weight_unit, Harvest::WEIGHT_UNITS_VALUES, { include_blank: false }, class: 'form-control')
= f.text_area :description, rows: 6, label: 'Notes'
- if @planting.present?
.row
.col-md-12
= f.range_field :overall_rating, min: 1, max: 5, value: @planting.overall_rating, include_blank: 'Leave blank', label: 'Overall Rating - Planting', list: "rating-list", title: "How well is the planting going?"
%datalist{"id": "rating-list"}
%option{"value": "1"} Poor
%option{"value": "2"}
%option{"value": "3"}
%option{"value": "4"}
%option{"value": "5"} Great
.card-footer
.text-right= f.submit 'Save'
+4 -2
View File
@@ -13,7 +13,7 @@
.index-cards
- harvest.crop.plant_parts.order(:name).each do |plant_part|
.card
= link_to harvests_path(harvest: {planting_id: harvest.planting_id, crop_id: harvest.crop_id, plant_part_id: plant_part.id}), method: :post do
= link_to new_harvest_path(harvest: {planting_id: harvest.planting_id, crop_id: harvest.crop_id, plant_part_id: plant_part.id}) do
.card-title.text-center
%h3= plant_part_icon(plant_part.name)
%h3= plant_part.name
@@ -22,10 +22,12 @@
%h6 All Plant parts
%nav.nav
- PlantPart.all.order(:name).each do |plant_part|
= link_to harvests_path(harvest: {planting_id: harvest.planting_id, crop_id: harvest.crop_id, plant_part_id: plant_part.id}), method: :post, class: 'nav-link border' do
= link_to new_harvest_path(harvest: {planting_id: harvest.planting_id, crop_id: harvest.crop_id, plant_part_id: plant_part.id}), class: 'nav-link border' do
= plant_part_icon(plant_part.name)
= plant_part
%a.btn#modalHarvestButton{"data-bs-target" => "#modelHarvestForm", "data-bs-toggle" => "modal", href: ""}
= harvest_icon
Record harvest
+1 -1
View File
@@ -4,7 +4,7 @@
- content_for :breadcrumbs do
- if @owner
%li.breadcrumb-item= link_to 'Harvests', harvests_path
%li.breadcrumb-item.active= link_to "#{@owner}'s harvests", harvests_path(@owner)
%li.breadcrumb-item.active= link_to "#{@owner}'s harvests", member_harvests_path(@owner)
- else
%li.breadcrumb-item.active= link_to "Harvests", harvests_path
.row
+1
View File
@@ -1,5 +1,6 @@
%h2= t('.recently_planted')
- Planting.homepage_records(6).each do |planting|
- next unless planting['thumbnail_url'].present?
= link_to planting_path(slug: planting['slug']), class: 'list-group-item list-group-item-action flex-column align-items-start' do
.d-flex.w-100.justify-content-between.homepage--list-item
%p.mb-2
@@ -0,0 +1,33 @@
%p Hello #{@member.login_name},
%h2= t('notifier_mailer.harvest_reminder.heading')
%p= t('notifier_mailer.harvest_reminder.intro')
%ul
- @plantings.each do |planting|
%li
= render 'planting', planting: planting
(Predicted harvest date: #{planting.first_harvest_predicted_at.to_date})
%p
Harvested anything lately?
= link_to "Track your harvests here.", new_harvest_url, class: 'btn'
%p
Track and predict your entire garden, and keep your garden records up to date at
= link_to member_gardens_url(@member), class: 'btn' do
your garden overview
and on
= link_to member_url(@member) do
your profile page
%h4
See you soon on #{@sitename}!
= render partial: 'signature'
%hr/
%p
Don't want to get these emails any more?
= link_to t('notifier_mailer.harvest_reminder.unsubscribe'), unsubscribe_member_url(message: @signed_message)
+1 -1
View File
@@ -4,7 +4,7 @@
- content_for :breadcrumbs do
- if @owner
%li.breadcrumb-item= link_to 'Plantings', plantings_path
%li.breadcrumb-item.active= link_to "#{@owner}'s plantings", plantings_path(@owner)
%li.breadcrumb-item.active= link_to "#{@owner}'s plantings", member_plantings_path(@owner)
- else
%li.breadcrumb-item.active= link_to 'Plantings', plantings_path
+1 -1
View File
@@ -32,7 +32,7 @@ csv.headers :id,
csv.cell :quantity
csv.cell :plant_before, s.plant_before ? s.plant_before.to_s(:db) : ''
csv.cell :plant_before, s.plant_before ? s.plant_before.to_fs(:db) : ''
csv.cell :tradable_to
csv.cell :from_location, s.owner.location
+1 -1
View File
@@ -1,7 +1,7 @@
- content_for :breadcrumbs do
- if @owner
%li.breadcrumb-item= link_to 'Seeds', seeds_path
%li.breadcrumb-item.active= link_to "#{@owner}'s seeds", seeds_path(@owner)
%li.breadcrumb-item.active= link_to "#{@owner}'s seeds", member_seeds_path(@owner)
- else
%li.breadcrumb-item.active= link_to 'Seeds', seeds_path
+1 -1
View File
@@ -3,4 +3,4 @@
%button.close{ type: "button", "data-bs-dismiss" => "alert" }
%span{ "aria-hidden" => true } &times;
%span.sr-only Close
= content
= sanitize(content)
Executable
+2
View File
@@ -0,0 +1,2 @@
#!/usr/bin/env ruby
exec "./bin/rails", "server", *ARGV
Executable
+8
View File
@@ -0,0 +1,8 @@
#!/usr/bin/env ruby
require "rubygems"
require "bundler/setup"
# explicit rubocop config increases performance slightly while avoiding config confusion.
ARGV.unshift("--config", File.expand_path("../.rubocop.yml", __dir__))
load Gem.bin_path("rubocop", "rubocop")
+5 -1
View File
@@ -14,7 +14,11 @@ Bundler.require(*Rails.groups)
module Growstuff
class Application < Rails::Application
# Initialize configuration defaults for originally generated Rails version.
config.load_defaults 7.0
config.load_defaults 8.0
# Rails 7.1+ requires a coder for `serialize`.
# We set YAML as the default for compatibility with gems like Mexican Sofa.
config.active_record.default_column_serializer = YAML
I18n.config.enforce_available_locales = true
-4
View File
@@ -16,10 +16,6 @@ Rails.application.configure do
config.consider_all_requests_local = false
config.action_controller.perform_caching = true
# Attempt to read encrypted secrets from `config/secrets.yml.enc`.
# Requires an encryption key in `ENV["RAILS_MASTER_KEY"]` or
# `config/secrets.yml.key`.
config.read_encrypted_secrets = true
# Disable serving static files from the `/public` folder by default since
# Apache or NGINX already handles this.
+2 -2
View File
@@ -3,9 +3,9 @@
# config/initializers/sidekiq.rb
Sidekiq.configure_server do |config|
config.redis = { url: 'redis://localhost:6379/0', namespace: "app3_sidekiq_#{Rails.env}" }
config.redis = { url: 'redis://localhost:6379/0' }
end
Sidekiq.configure_client do |config|
config.redis = { url: 'redis://localhost:6379/0', namespace: "app3_sidekiq_#{Rails.env}" }
config.redis = { url: 'redis://localhost:6379/0' }
end
+6
View File
@@ -456,3 +456,9 @@ en:
all: Not authorized to %{action} %{subject}.
read:
notification: You must be signed in to view notifications.
notifier_mailer:
harvest_reminder:
subject: "Upcoming harvests in your garden - %{sitename}"
heading: "Upcoming harvests in your garden"
intro: "Based on our predictions, the following plantings in your garden are likely to be ready for harvest within the next week:"
unsubscribe: "Unsubscribe from harvest reminders"
+2
View File
@@ -32,6 +32,7 @@ Rails.application.routes.draw do
resources :gardens, concerns: :has_photos, param: :slug do
get 'timeline' => 'charts/gardens#timeline', constraints: { format: 'json' }
post 'fetch_wikidata' => 'gardens#fetch_wikidata', on: :member
resources :garden_collaborators
end
@@ -157,6 +158,7 @@ Rails.application.routes.draw do
namespace :api do
namespace :v1 do
jsonapi_resources :activities
get "crops/search", to: "crops#search"
jsonapi_resources :crops
jsonapi_resources :gardens
jsonapi_resources :harvests
@@ -15,7 +15,5 @@ class AddActivities < ActiveRecord::Migration[7.1]
end
add_column :members, :activities_count, :integer
Activity.reindex
end
end
@@ -0,0 +1,7 @@
class AddWikidataAndTempsToGardens < ActiveRecord::Migration[7.2]
def change
add_column :gardens, :location_wikidata_id, :string
add_column :gardens, :lowest_temp_c, :float
add_column :gardens, :highest_temp_c, :float
end
end
@@ -0,0 +1,5 @@
class AddSendHarvestReminderToMembers < ActiveRecord::Migration[7.2]
def change
add_column :members, :send_harvest_reminder, :boolean, default: true, null: false
end
end
+6 -2
View File
@@ -10,9 +10,9 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[7.2].define(version: 2025_12_01_045000) do
ActiveRecord::Schema[8.0].define(version: 2026_04_29_132911) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
enable_extension "pg_catalog.plpgsql"
create_table "active_storage_attachments", force: :cascade do |t|
t.string "name", null: false
@@ -631,6 +631,9 @@ ActiveRecord::Schema[7.2].define(version: 2025_12_01_045000) do
t.decimal "area"
t.string "area_unit"
t.integer "garden_type_id"
t.string "location_wikidata_id"
t.float "lowest_temp_c"
t.float "highest_temp_c"
t.index ["garden_type_id"], name: "index_gardens_on_garden_type_id"
t.index ["owner_id"], name: "index_gardens_on_owner_id"
t.index ["slug"], name: "index_gardens_on_slug", unique: true
@@ -786,6 +789,7 @@ ActiveRecord::Schema[7.2].define(version: 2025_12_01_045000) do
t.string "facebook_handle"
t.string "bluesky_handle"
t.string "other_url"
t.boolean "send_harvest_reminder", default: true, null: false
t.index ["confirmation_token"], name: "index_members_on_confirmation_token", unique: true
t.index ["discarded_at"], name: "index_members_on_discarded_at"
t.index ["email"], name: "index_members_on_email", unique: true
+17 -2
View File
@@ -48,8 +48,23 @@ namespace :growstuff do
# Heroku scheduler only lets us run things daily, so this checks
# Send on Monday
if Time.zone.today.wday == 1
Member.confirmed.wants_reminders.each do |m|
Notifier.planting_reminder(m).deliver_now! unless m.plantings.active.empty?
Member.confirmed.wants_reminders.find_each do |m|
NotifierMailer.planting_reminder(m).deliver_later unless m.plantings.active.empty?
end
end
end
desc "Send harvest reminder email"
# usage: rake growstuff:send_harvest_reminders
task send_harvest_reminders: :environment do
# Heroku scheduler only lets us run things daily, so this checks
# Send on Wednesday
if Time.zone.today.wday == 3
Member.confirmed.wants_harvest_reminders.find_each do |m|
if m.plantings.active.any?(&:harvest_in_next_week?)
NotifierMailer.harvest_reminder(m).deliver_later
end
end
end
end
-1
View File
@@ -7,6 +7,5 @@ namespace :search do
Planting.reindex
Harvest.reindex
Seed.reindex
Activity.reindex
end
end
+15
View File
@@ -73,6 +73,21 @@ describe CropsController do
end
end
describe "GET CSV" do
let!(:tomato) { create(:tomato, en_wikipedia_url: "https://en.wikipedia.org/wiki/Tomato") }
before do
Crop.reindex
get :index, format: "csv"
end
it { is_expected.to be_successful }
it { expect(response.content_type).to eq("text/csv; charset=utf-8") }
it "contains tomato", pending: "not properly functional" do
expect(assigns(:crops)).not_to be_empty
expect(response.body).to include("tomato")
end
end
describe 'CREATE' do
subject { put :create, params: crop_params }
@@ -115,6 +115,21 @@ describe HarvestsController, :search do
it { expect(Harvest.last.planting.id).to eq(planting.id) }
end
describe "updates planting rating" do
let(:planting) { create(:planting, owner_id: member.id, garden: member.gardens.first) }
it "updates the planting rating when provided" do
post :create, params: {
harvest: valid_attributes.merge(
planting_id: planting.id,
crop_id: planting.crop_id,
overall_rating: 4
)
}
expect(planting.reload.overall_rating).to eq(4)
end
end
end
describe "with invalid params" do
@@ -171,6 +186,18 @@ describe HarvestsController, :search do
it { expect(response).to redirect_to(harvest) }
end
describe "updates planting rating" do
let(:planting) { create(:planting, owner_id: member.id, garden: member.gardens.first) }
let(:harvest) do
create(:harvest, valid_attributes.merge(planting_id: planting.id, crop_id: planting.crop_id))
end
it "updates the planting rating when provided" do
put :update, params: { slug: harvest.to_param, harvest: { overall_rating: 3 } }
expect(planting.reload.overall_rating).to eq(3)
end
end
end
describe "with invalid params" do
+7 -13
View File
@@ -2,15 +2,14 @@
require 'rails_helper'
describe PhotosController, :search do
describe PhotosController do
login_member
describe 'GET index' do
describe 'all photos' do
let!(:photo) { create(:photo, :reindex) }
let!(:photo) { create(:photo) }
before do
Photo.reindex
get :index
end
@@ -21,28 +20,23 @@ describe PhotosController, :search do
end
describe '#index crop photos' do
let!(:photo) { create(:photo, :reindex, owner: member, title: 'no assocations photo') }
let!(:crop_photo) { create(:photo, :reindex, owner: member, title: 'photos of planting') }
let!(:planting) { create(:planting, :reindex, crop:, owner: member) }
let!(:crop) { create(:crop, :reindex) }
let!(:photo) { create(:photo, owner: member, title: 'no assocations photo') }
let!(:crop_photo) { create(:photo, owner: member, title: 'photos of planting') }
let!(:crop) { create(:crop) }
let!(:planting) { create(:planting, crop:, owner: member) }
before do
planting.photos << crop_photo
Photo.reindex
get :index, params: { crop_slug: crop.to_param }
end
describe "find photos by crop" do
it "has indexed the photos of this crop" do
expect(Photo.search).to include crop_photo
end
it "assigns crop" do
expect(assigns(:crop)).to eq crop
end
it { expect(assigns(:photos).size).to eq 1 }
it { expect(assigns(:photos).first.crops).to include crop.id }
it { expect(assigns(:photos).first.crops).to include crop }
it { expect(assigns(:photos).first.id).to eq crop_photo.id }
end
end
+14
View File
@@ -10,6 +10,20 @@ describe PostsController do
{ author_id: member.id, subject: "blah", body: "blah blah" }
end
describe '#new' do
let(:crop) { create(:crop, name: 'Bush Bean') }
it 'pre-populates the body when crop_id is present' do
get :new, params: { crop_id: crop.slug }
expect(assigns(:post).body).to eq("[#{crop.name}](crop)")
end
it 'does not pre-populate the body when crop_id is absent' do
get :new
expect(assigns(:post).body).to be_nil
end
end
describe '#index' do
before do
create_list(:post, 100)
+4
View File
@@ -21,5 +21,9 @@ FactoryBot.define do
description { "Stake tomato" }
planting
end
trait :reindex do
# Activity is not using elasticsearch anymore, so we don't need to reindex
end
end
end
-5
View File
@@ -19,10 +19,5 @@ FactoryBot.define do
license_url { nil }
end
trait :reindex do
after(:create) do |photo, _evaluator|
photo.reindex(refresh: true)
end
end
end
end
+4
View File
@@ -21,5 +21,9 @@ FactoryBot.define do
factory :forum_post do
forum
end
trait :reindex do
# Post is not using elasticsearch, but this trait is used in some tests
end
end
end
@@ -54,6 +54,8 @@ describe "Harvesting a crop", :js, :search do
visit crop_path(maize)
click_link "Record harvest"
click_link plant_part.name
# We then navigate to the new_harvest_path, and save.
click_button "Save"
end
it { expect(page).to have_content "harvest was successfully created." }
@@ -69,9 +71,22 @@ describe "Harvesting a crop", :js, :search do
click_link plant_part.name
end
it { expect(page).to have_content "harvest was successfully created." }
it { expect(page).to have_content planting.garden.name }
it { expect(page).to have_content "maize" }
it "saves" do
# We then navigate to the new_harvest_path, and save.
click_button "Save"
expect(page).to have_content "harvest was successfully created."
expect(page).to have_content planting.garden.name
expect(page).to have_content "maize"
end
it "updates the planting rating" do
find_by_id('harvest_overall_rating').set 4
click_button "Save"
expect(page).to have_content "harvest was successfully created."
expect(planting.reload.overall_rating).to eq 4
end
end
context "Editing a harvest" do
-1
View File
@@ -28,7 +28,6 @@ describe "home page", :search do
Planting.reindex
Seed.reindex
Harvest.reindex
Photo.reindex
visit root_path
end
+1 -5
View File
@@ -6,14 +6,10 @@ describe 'Likeable', :js, :search do
let(:another_member) { create(:london_member) }
let!(:post) { create(:post, :reindex, author: member) }
let!(:activity) { create(:activity, :reindex, owner: member) }
let!(:photo) { create(:photo, :reindex, owner: member) }
let!(:photo) { create(:photo, owner: member) }
let!(:harvest) { create(:harvest, :reindex, owner: member) }
let!(:planting) { create(:planting, :reindex, owner: member) }
before do
Photo.reindex
end
include_context 'signed in member'
shared_examples 'object can be liked' do
@@ -0,0 +1,28 @@
# frozen_string_literal: true
require 'rails_helper'
describe NotifierMailer, type: :mailer do
let(:member) { create(:member) }
let(:mail) { NotifierMailer.harvest_reminder(member) }
it "has a greeting" do
expect(mail.body.encoded).to match "Hello"
end
context "when member has upcoming harvests" do
let(:crop) { create(:crop, median_days_to_first_harvest: 20) }
let!(:planting) { create(:planting, owner: member, crop: crop, planted_at: 15.days.ago) }
let(:plantings) { [planting] }
it "lists the upcoming harvest" do
expect(mail.body.encoded).to match "Upcoming harvests in your garden"
expect(mail.body.encoded).to match planting.crop.name
expect(mail.body.encoded).to match (Time.zone.today + 5.days).to_date.to_s
end
it "has an unsubscribe link" do
expect(mail.body.encoded).to match "Unsubscribe from harvest reminders"
end
end
end
+42
View File
@@ -0,0 +1,42 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe Activity do
describe '.homepage_records' do
let(:member1) { create(:member) }
let(:member2) { create(:member) }
it 'returns the latest activities per owner' do
create(:activity, owner: member1, created_at: 2.days.ago)
latest_activity1 = create(:activity, owner: member1, created_at: 1.day.ago)
latest_activity2 = create(:activity, owner: member2, created_at: Time.current)
records = described_class.homepage_records(10)
expect(records).to contain_exactly(latest_activity1, latest_activity2)
end
it 'respects the limit' do
create(:activity, owner: member1)
create(:activity, owner: member2)
records = described_class.homepage_records(1)
expect(records.length).to eq(1)
end
end
describe 'active scope' do
it 'returns activities that are not finished' do
active_activity = create(:activity, finished: false)
finished_activity = create(:activity, finished: true)
expect(described_class.active).to include(active_activity)
expect(described_class.active).not_to include(finished_activity)
end
it 'treats nil finished as active' do
activity = create(:activity, finished: nil)
expect(described_class.active).to include(activity)
end
end
end
@@ -0,0 +1,32 @@
# frozen_string_literal: true
require 'rails_helper'
require 'cancan/matchers'
describe Ability do
let(:member) { create(:member) }
let(:ability) { described_class.new(member) }
context 'garden collaborators' do
let(:garden) { create(:garden) }
let(:garden_collaborator) { create(:garden_collaborator, garden: garden, member: member) }
let(:other_member) { create(:member) }
let(:other_garden_collaborator) { create(:garden_collaborator, garden: garden, member: other_member) }
it 'can remove themselves as a collaborator' do
expect(ability).to be_able_to(:destroy, garden_collaborator)
end
it 'cannot remove others as a collaborator if not garden owner' do
expect(ability).not_to be_able_to(:destroy, other_garden_collaborator)
end
context 'as garden owner' do
let(:garden) { create(:garden, owner: member) }
it 'can remove others as a collaborator' do
expect(ability).to be_able_to(:destroy, other_garden_collaborator)
end
end
end
end
+41
View File
@@ -0,0 +1,41 @@
# frozen_string_literal: true
require 'rails_helper'
describe "Harvest prediction logic" do
let(:crop) { create(:crop, median_days_to_first_harvest: 20) }
let(:planting) { create(:planting, crop: crop) }
describe "#harvest_in_next_week?" do
it "is true if predicted harvest is in 5 days" do
planting.planted_at = 15.days.ago
expect(planting.harvest_in_next_week?).to be true
end
it "is true if predicted harvest is today" do
planting.planted_at = 20.days.ago
expect(planting.harvest_in_next_week?).to be true
end
it "is true if predicted harvest is in 7 days" do
planting.planted_at = 13.days.ago
expect(planting.harvest_in_next_week?).to be true
end
it "is false if predicted harvest is in 8 days" do
planting.planted_at = 12.days.ago
expect(planting.harvest_in_next_week?).to be false
end
it "is false if predicted harvest was yesterday" do
planting.planted_at = 21.days.ago
expect(planting.harvest_in_next_week?).to be false
end
it "is false if there are already harvests" do
planting.planted_at = 15.days.ago
create(:harvest, planting: planting, owner: planting.owner, crop: planting.crop, harvested_at: 1.day.ago)
expect(planting.harvest_in_next_week?).to be false
end
end
end
+1 -33
View File
@@ -3,7 +3,7 @@
require 'rails_helper'
describe Photo do
let(:photo) { create(:photo, :reindex, owner: member) }
let(:photo) { create(:photo, owner: member) }
let(:member) { create(:member) }
it_behaves_like "it is likeable"
@@ -237,36 +237,4 @@ describe Photo do
end
end
describe 'Elastic search indexing', :search do
let!(:planting) { create(:planting, :reindex, owner: photo.owner) }
let!(:crop) { create(:crop, :reindex) }
before do
planting.photos << photo
described_class.reindex
described_class.searchkick_index.refresh
end
describe "finds all photos in search index" do
it "finds just one" do
expect(described_class.search.count).to eq 1
end
it "finds the matching photo" do
expect(described_class.search).to include photo
end
it "retrieves crops from ES" do
expect(described_class.search(load: false).first.crops).to eq [planting.crop.id]
end
end
it "finds photos by owner in search index" do
expect(described_class.search(where: { owner_id: planting.owner_id })).to include photo
end
it "finds photos by crop in search index" do
expect(described_class.search(where: { crops: planting.crop.id })).to include photo
end
end
end
+35
View File
@@ -0,0 +1,35 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe 'Crops Search' do
subject { JSON.parse response.body }
let(:headers) { { 'Accept' => 'application/vnd.api+json' } }
let!(:cabbage) { create(:crop, name: 'Cabbage', approval_status: 'approved') }
let!(:apple) { create(:crop, name: 'Apple', approval_status: 'approved') }
describe 'GET /api/v1/crops/search' do
before do
Crop.reindex
end
it 'returns crops matching the search term' do
get '/api/v1/crops/search', params: { term: 'Cabbage' }, headers: headers
expect(response).to have_http_status(:ok)
expect(subject['data'].size).to eq(1)
expect(subject['data'].first['attributes']['name']).to eq('Cabbage')
end
it 'returns empty data if no crops match' do
get '/api/v1/crops/search', params: { term: 'NonExistent' }, headers: headers
expect(response).to have_http_status(:ok)
expect(subject['data']).to be_empty
end
it 'includes meta information' do
get '/api/v1/crops/search', params: { term: 'Cabbage' }, headers: headers
expect(subject['meta']).to include('record_count' => 1, 'page_count' => 1)
end
end
end
-2
View File
@@ -47,10 +47,8 @@ RSpec.configure do |config|
# reindex models
Crop.reindex
Harvest.reindex
Photo.reindex
Planting.reindex
Seed.reindex
Activity.reindex
end
config.before(:suite) do
+12 -6
View File
@@ -90,13 +90,19 @@ describe 'layouts/_header.html.haml', type: "view" do
expect(rendered).to have_content 'Inbox'
expect(rendered).not_to match(/Inbox \d+/)
end
end
context 'has notifications' do
it 'shows inbox count' do
create(:notification, recipient: @member)
render
expect(rendered).to have_content 'Inbox 1'
end
context 'logged in, has notifications' do
before do
@member = create(:member)
create(:notification, recipient: @member)
sign_in @member
controller.stub(:current_user) { @member }
end
it 'shows inbox count' do
render
rendered.should have_content 'Inbox 1'
end
end
end
+79
View File
@@ -9,6 +9,85 @@
"/crops": {
"get": {
"summary": "crops List",
"/crops/search": {
"get": {
"summary": "crops Search",
"tags": [
"crops"
],
"produces": [
"application/vnd.api+json"
],
"parameters": [
{
"name": "term",
"in": "query",
"type": "string",
"description": "Search term",
"required": true
},
{
"name": "page[number]",
"in": "query",
"type": "string",
"description": "Page num",
"required": false
},
{
"name": "page[size]",
"in": "query",
"type": "string",
"description": "Page size",
"required": false
}
],
"responses": {
"200": {
"description": "Get search results",
"schema": {
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "ID"
},
"type": {
"type": "string",
"description": "Type"
},
"attributes": {
"type": "object",
"properties": {
"name": {
"type": "string"
}
}
}
}
}
},
"meta": {
"type": "object",
"properties": {
"record_count": {
"type": "integer"
},
"page_count": {
"type": "integer"
}
}
}
}
}
}
}
}
},
"tags": [
"crops"
],
+12 -12
View File
@@ -735,9 +735,9 @@ fast-levenshtein@^2.0.6:
integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==
fast-uri@^3.0.1:
version "3.1.0"
resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.1.0.tgz#66eecff6c764c0df9b762e62ca7edcfb53b4edfa"
integrity sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==
version "3.1.2"
resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.1.2.tgz#8af3d4fc9d3e71b11572cc2673b514a7d1a8c8ec"
integrity sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==
fastq@^1.6.0:
version "1.20.1"
@@ -915,9 +915,9 @@ inherits@2, inherits@~2.0.3:
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
ip-address@^10.0.1:
version "10.1.0"
resolved "https://registry.yarnpkg.com/ip-address/-/ip-address-10.1.0.tgz#d8dcffb34d0e02eb241427444a6e23f5b0595aa4"
integrity sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==
version "10.2.0"
resolved "https://registry.yarnpkg.com/ip-address/-/ip-address-10.2.0.tgz#805fc178b20c518bd4c8548b24fe30892d7f3206"
integrity sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==
is-arrayish@^0.2.1:
version "0.2.1"
@@ -964,9 +964,9 @@ js-tokens@^4.0.0:
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
js-yaml@^4.1.0:
version "4.1.1"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.1.tgz#854c292467705b699476e1a2decc0c8a3458806b"
integrity sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==
version "4.2.0"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.2.0.tgz#2bd9e85682dd91bd469afb809d816043b3d49524"
integrity sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==
dependencies:
argparse "^2.0.1"
@@ -1396,9 +1396,9 @@ supports-preserve-symlinks-flag@^1.0.0:
integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
systeminformation@^5.25.11:
version "5.31.5"
resolved "https://registry.yarnpkg.com/systeminformation/-/systeminformation-5.31.5.tgz#e839fa6b40620a8bee010eb9d9d55c2d5f7042c8"
integrity sha512-5SyLdip4/3alxD4Kh+63bUQTJmu7YMfYQTC+koZy7X73HgNqZSD2P4wOZQWtUncvPvcEmnfIjCoygN4MRoEejQ==
version "5.31.6"
resolved "https://registry.yarnpkg.com/systeminformation/-/systeminformation-5.31.6.tgz#2da4979a7262974fd068a3a306ded30aed6127c0"
integrity sha512-Uv2b2uGGM6ns+26czgW2cYRabYdnswM0ddSOOlryHOaelzsmDSet1iM/NT7VOYxW8x/BW+HkY+b1Ve2pLTSGSA==
to-regex-range@^5.0.1:
version "5.0.1"