Compare commits

..

36 Commits

Author SHA1 Message Date
Daniel O'Connor
13e8e2747b Merge branch 'dev' into Style/SoleNestedConditional 2024-07-13 15:14:57 +09:30
Daniel O'Connor
de6241b728 Style/SoleNestedConditional 2024-07-13 05:19:31 +00:00
Daniel O'Connor
5b5adad6ab Merge branch 'dev' into ruby32-rubocop 2024-07-13 14:47:27 +09:30
Daniel O'Connor
269e1d274a Regenerate 2024-07-13 05:03:38 +00:00
Daniel O'Connor
327eaf7a03 More rubocop 2024-07-13 04:57:20 +00:00
Daniel O'Connor
c73d23fa80 Rubocop 2024-07-13 04:55:09 +00:00
Daniel O'Connor
a1e73f4b19 Update rubocop 2024-07-13 04:52:16 +00:00
Daniel O'Connor
212ed17d60 Regenerate 2024-07-13 04:50:26 +00:00
Daniel O'Connor
943929b769 3 space indent 2024-07-13 04:40:43 +00:00
Daniel O'Connor
1f220164bb Pin to 2.4.22 2024-07-13 04:38:00 +00:00
Daniel O'Connor
fc0c428799 Merge branch 'dev' into ruby32 2024-07-13 13:56:44 +09:30
Daniel O'Connor
653776ae6b Fix spec 2024-07-13 04:14:34 +00:00
Daniel O'Connor
ba7d9e6905 Update spec 2024-07-13 03:55:13 +00:00
Daniel O'Connor
f8aff18492 Fix spec 2024-07-13 03:53:41 +00:00
Daniel O'Connor
8bfa81990c Update .devcontainer/.env 2024-07-13 13:06:02 +09:30
Daniel O'Connor
4ed7ea32b5 Merge branch 'dev' into ruby32 2024-07-13 13:04:28 +09:30
Daniel O'Connor
44f864eace Merge branch 'dev' into ruby32 2024-01-27 00:40:07 +10:30
Daniel O'Connor
a762a87d58 Update .env 2024-01-22 00:06:05 +10:30
Daniel O'Connor
4ea77fb52f Update app/views/plantings/index.rss.haml 2024-01-22 00:03:34 +10:30
Daniel O'Connor
56348b1a8e Merge branch 'dev' into ruby32 2024-01-21 19:06:27 +10:30
Daniel O'Connor
82971d773c Update app/views/members/show.html.haml 2023-08-20 16:58:19 +09:30
Daniel O'Connor
3af5b4a53a Merge branch 'dev' into ruby32 2023-08-20 16:57:15 +09:30
Daniel O'Connor
75571a485d Swap to will paginate successor for bootstrap 2023-08-20 02:35:02 +00:00
Daniel O'Connor
8a9137e62e Fix deprecation warning by explicitly calling to_fs 2023-08-20 02:30:00 +00:00
Daniel O'Connor
ec3c010410 Fix deprecation warning by explicitly calling to_fs 2023-08-20 02:25:09 +00:00
Daniel O'Connor
2bfd077190 Fix deprecation warning by explicitly calling to_fs 2023-08-20 02:23:01 +00:00
Daniel O'Connor
b7a7b03029 Merge branch 'dev' into ruby32 2023-08-20 11:30:13 +09:30
Daniel O'Connor
7a470f9fac Appease codeclimate for the nth time 2023-08-11 07:07:50 +00:00
Daniel O'Connor
1dc98da520 Adjust ownership 2023-08-11 07:05:02 +00:00
Daniel O'Connor
1540a3c1e1 Merge branch 'remove-js-routes' into ruby32 2023-08-11 06:54:58 +00:00
Daniel O'Connor
fb322a6a80 Remove 2023-08-11 06:54:42 +00:00
Daniel O'Connor
b15f39dd09 Merge branch 'remove-js-routes' into ruby32 2023-08-11 06:53:44 +00:00
Daniel O'Connor
54211a8cef Remove js-routes 2023-08-11 06:51:39 +00:00
Daniel O'Connor
e55b85c559 Upgrade to js-routes 2. Put all js routes into a global namespace. 2023-08-11 06:36:48 +00:00
Daniel O'Connor
121548df57 Fix creation 2023-08-11 05:56:30 +00:00
Daniel O'Connor
1918884540 Ruby 3.2/Bundler 2.4 2023-08-11 05:45:54 +00:00
309 changed files with 4180 additions and 7501 deletions

47
.codeclimate.yml Normal file
View File

@@ -0,0 +1,47 @@
plugins:
brakeman:
enabled: false # codeclimate's brakeman is stuck in rails 5 rules
bundler-audit:
enabled: true
coffeelint:
enabled: true
duplication:
enabled: true
config:
languages:
- ruby
- javascript
editorconfig:
enabled: true
eslint:
enabled: true
fixme:
enabled: true
haml-lint:
enabled: true
nodesecurity:
enabled: true
rubocop:
enabled: true
channel: "rubocop-1-11"
scss-lint:
enabled: true
shellcheck:
enabled: true
ratings:
paths:
- "**.rb"
- "**.ru"
- "**.js"
- "**.coffee"
- "**.scss"
- "**.haml"
- Gemfile.lock
exclude_paths:
- config/
- db/
- spec/
- public/
- app/assets/stylesheets/bootstrap-accessibility.css
- app/assets/javascripts/bootstrap*
- app/assets/stylesheets/leaflet_overrides.scss

View File

@@ -1,2 +1,2 @@
# Ruby version # Ruby version
VARIANT=3.3.4 VARIANT=3.2.4

View File

@@ -1,4 +1,4 @@
FROM mcr.microsoft.com/devcontainers/ruby:1-3.3-bullseye FROM mcr.microsoft.com/devcontainers/ruby:0-3.2-bullseye
# Install Rails # Install Rails
RUN gem install rails:7.0.8 RUN gem install rails:7.0.8
@@ -29,5 +29,4 @@ RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
# Make sure this is writable as https://github.com/rubygems/rubygems/issues/6272 was removed # Make sure this is writable as https://github.com/rubygems/rubygems/issues/6272 was removed
RUN su root -c "mkdir -p /usr/local/rvm/gems/default/cache/bundler/" RUN su root -c "mkdir -p /usr/local/rvm/gems/default/cache/bundler/"
RUN su root -c "mkdir -p /usr/local/rvm/gems/default/bundler/gems/" RUN su root -c "mkdir -p /usr/local/rvm/gems/default/bundler/gems/"
RUN su root -c "chown -R vscode:rvm /usr/local/rvm/gems/" RUN su root -c "chmod -R 777 /usr/local/rvm/gems/"
RUN su root -c "chmod -R 0755 /usr/local/rvm/gems/"

View File

@@ -7,10 +7,53 @@ updates:
time: "07:00" time: "07:00"
open-pull-requests-limit: 20 open-pull-requests-limit: 20
versioning-strategy: lockfile-only versioning-strategy: lockfile-only
ignore:
- dependency-name: active_median
versions:
- "< 0.2.2, >= 0.2.1.a"
- dependency-name: rubocop
versions:
- "< 0.63, >= 0.62.a"
- dependency-name: rubocop
versions:
- "< 0.64, >= 0.63.a"
- dependency-name: sidekiq
versions:
- 5.2.4
- dependency-name: oj
versions:
- 3.11.4
- dependency-name: listen
versions:
- 3.5.0
- dependency-name: rspec-rails
versions:
- 4.1.0
- 5.0.0
- dependency-name: searchkick
versions:
- 4.4.3
- dependency-name: rswag-api
versions:
- 2.3.3
- dependency-name: rswag-specs
versions:
- 2.3.3
- dependency-name: rswag-ui
versions:
- 2.3.3
- dependency-name: timecop
versions:
- 0.9.3
- dependency-name: puma
versions:
- 5.2.0
- dependency-name: capybara
versions:
- 3.35.1
- package-ecosystem: github-actions - package-ecosystem: github-actions
directory: "/" directory: "/"
schedule: schedule:
interval: daily interval: daily
time: "07:00" time: "07:00"
open-pull-requests-limit: 10 open-pull-requests-limit: 10

40
.github/workflows/brakeman-analysis.yml vendored Normal file
View File

@@ -0,0 +1,40 @@
# This workflow integrates Brakeman with GitHub's Code Scanning feature
# Brakeman is a static analysis security vulnerability scanner for Ruby on Rails applications
name: Brakeman Scan
# This section configures the trigger for the workflow. Feel free to customize depending on your convention
on:
pull_request:
branches: [ dev ]
jobs:
brakeman-scan:
name: Brakeman Scan
runs-on: ubuntu-latest
steps:
# Checkout the repository to the GitHub Actions runner
- name: Checkout
uses: actions/checkout@v4
# Customize the ruby version depending on your needs
- name: Setup Ruby
uses: ruby/setup-ruby@v1
- name: Setup Brakeman
env:
BRAKEMAN_VERSION: '5.1.1' # SARIF support is provided in Brakeman version 4.10+
run: |
gem install brakeman --version $BRAKEMAN_VERSION
# Execute Brakeman CLI and generate a SARIF output with the security issues identified during the analysis
- name: Scan
continue-on-error: true
run: |
brakeman -f sarif -o output.sarif.json .
# Upload the SARIF file generated in the previous step
- name: Upload SARIF
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: output.sarif.json

View File

@@ -1,109 +0,0 @@
name: CI Features - Admin
on: [pull_request]
jobs:
rspec:
runs-on: ubuntu-latest
services:
db:
image: postgres
env:
##
# The Postgres service fails its docker health check unless you
# specify these environment variables
#
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: growstuff_test
ports: ['5432:5432']
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
env:
APP_DOMAIN_NAME: localhost:3000
APP_PROTOCOL: http
CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
DATABASE_URL: postgres://postgres:postgres@localhost:5432/growstuff_test
DEVISE_SECRET_KEY: secret
ELASTIC_SEARCH_VERSION: "7.5.1-amd64"
GROWSTUFF_EMAIL: "noreply@test.growstuff.org"
GROWSTUFF_FLICKR_KEY: secretkey"
GROWSTUFF_FLICKR_SECRET: secretsecret
GROWSTUFF_SITE_NAME: "Growstuff (travis)"
RAILS_ENV: test
RAILS_SECRET_TOKEN: supersecret
steps:
- name: Checkout this repo
uses: actions/checkout@v5
- name: Configure sysctl limits
run: |
sudo swapoff -a
sudo sysctl -w vm.swappiness=1
sudo sysctl -w fs.file-max=262144
sudo sysctl -w vm.max_map_count=262144
- name: Start Elasticsearch
uses: elastic/elastic-github-actions/elasticsearch@master
with:
stack-version: 7.5.1
##
# Cache Yarn modules
#
# See https://github.com/actions/cache/blob/master/examples.md#node---yarn for details
#
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- name: Setup yarn cache
uses: actions/cache@v4
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Install required OS packages
run: |
sudo apt-get -y install libpq-dev google-chrome-stable
- name: Install NodeJS
uses: actions/setup-node@v5
with:
node-version: '12'
- name: Install Ruby (version given by .ruby-version) and Bundler
uses: ruby/setup-ruby@v1
with:
bundler-cache: true
- name: Install required JS packages
run: yarn install
- name: install chrome
run: sudo apt-get install google-chrome-stable
- name: Prepare database for testing
run: bundle exec rails db:prepare
- name: precompile assets
run: bundle exec rails assets:precompile
- name: index into elastic search
run: bundle exec rails search:reindex
- name: Run rspec (admin/)
run: bundle exec rspec spec/features/admin/ -fd -t ~@flaky
- name: Upload screenshots
if: failure()
uses: actions/upload-artifact@v4
with:
name: screenshots
path: tmp/screenshots

View File

@@ -1,109 +0,0 @@
name: CI Features - Comments
on: [pull_request]
jobs:
rspec:
runs-on: ubuntu-latest
services:
db:
image: postgres
env:
##
# The Postgres service fails its docker health check unless you
# specify these environment variables
#
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: growstuff_test
ports: ['5432:5432']
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
env:
APP_DOMAIN_NAME: localhost:3000
APP_PROTOCOL: http
CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
DATABASE_URL: postgres://postgres:postgres@localhost:5432/growstuff_test
DEVISE_SECRET_KEY: secret
ELASTIC_SEARCH_VERSION: "7.5.1-amd64"
GROWSTUFF_EMAIL: "noreply@test.growstuff.org"
GROWSTUFF_FLICKR_KEY: secretkey"
GROWSTUFF_FLICKR_SECRET: secretsecret
GROWSTUFF_SITE_NAME: "Growstuff (travis)"
RAILS_ENV: test
RAILS_SECRET_TOKEN: supersecret
steps:
- name: Checkout this repo
uses: actions/checkout@v5
- name: Configure sysctl limits
run: |
sudo swapoff -a
sudo sysctl -w vm.swappiness=1
sudo sysctl -w fs.file-max=262144
sudo sysctl -w vm.max_map_count=262144
- name: Start Elasticsearch
uses: elastic/elastic-github-actions/elasticsearch@master
with:
stack-version: 7.5.1
##
# Cache Yarn modules
#
# See https://github.com/actions/cache/blob/master/examples.md#node---yarn for details
#
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- name: Setup yarn cache
uses: actions/cache@v4
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Install required OS packages
run: |
sudo apt-get -y install libpq-dev google-chrome-stable
- name: Install NodeJS
uses: actions/setup-node@v5
with:
node-version: '12'
- name: Install Ruby (version given by .ruby-version) and Bundler
uses: ruby/setup-ruby@v1
with:
bundler-cache: true
- name: Install required JS packages
run: yarn install
- name: install chrome
run: sudo apt-get install google-chrome-stable
- name: Prepare database for testing
run: bundle exec rails db:prepare
- name: precompile assets
run: bundle exec rails assets:precompile
- name: index into elastic search
run: bundle exec rails search:reindex
- name: Run rspec (comments/)
run: bundle exec rspec spec/features/comments/ -fd -t ~@flaky
- name: Upload screenshots
if: failure()
uses: actions/upload-artifact@v4
with:
name: screenshots
path: tmp/screenshots

View File

@@ -1,109 +0,0 @@
name: CI Features - Conversations
on: [pull_request]
jobs:
rspec:
runs-on: ubuntu-latest
services:
db:
image: postgres
env:
##
# The Postgres service fails its docker health check unless you
# specify these environment variables
#
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: growstuff_test
ports: ['5432:5432']
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
env:
APP_DOMAIN_NAME: localhost:3000
APP_PROTOCOL: http
CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
DATABASE_URL: postgres://postgres:postgres@localhost:5432/growstuff_test
DEVISE_SECRET_KEY: secret
ELASTIC_SEARCH_VERSION: "7.5.1-amd64"
GROWSTUFF_EMAIL: "noreply@test.growstuff.org"
GROWSTUFF_FLICKR_KEY: secretkey"
GROWSTUFF_FLICKR_SECRET: secretsecret
GROWSTUFF_SITE_NAME: "Growstuff (travis)"
RAILS_ENV: test
RAILS_SECRET_TOKEN: supersecret
steps:
- name: Checkout this repo
uses: actions/checkout@v5
- name: Configure sysctl limits
run: |
sudo swapoff -a
sudo sysctl -w vm.swappiness=1
sudo sysctl -w fs.file-max=262144
sudo sysctl -w vm.max_map_count=262144
- name: Start Elasticsearch
uses: elastic/elastic-github-actions/elasticsearch@master
with:
stack-version: 7.5.1
##
# Cache Yarn modules
#
# See https://github.com/actions/cache/blob/master/examples.md#node---yarn for details
#
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- name: Setup yarn cache
uses: actions/cache@v4
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Install required OS packages
run: |
sudo apt-get -y install libpq-dev google-chrome-stable
- name: Install NodeJS
uses: actions/setup-node@v5
with:
node-version: '12'
- name: Install Ruby (version given by .ruby-version) and Bundler
uses: ruby/setup-ruby@v1
with:
bundler-cache: true
- name: Install required JS packages
run: yarn install
- name: install chrome
run: sudo apt-get install google-chrome-stable
- name: Prepare database for testing
run: bundle exec rails db:prepare
- name: precompile assets
run: bundle exec rails assets:precompile
- name: index into elastic search
run: bundle exec rails search:reindex
- name: Run rspec (conversations/)
run: bundle exec rspec spec/features/conversations/ -fd -t ~@flaky
- name: Upload screenshots
if: failure()
uses: actions/upload-artifact@v4
with:
name: screenshots
path: tmp/screenshots

View File

@@ -1,109 +0,0 @@
name: CI Features - Crops
on: [pull_request]
jobs:
rspec:
runs-on: ubuntu-latest
services:
db:
image: postgres
env:
##
# The Postgres service fails its docker health check unless you
# specify these environment variables
#
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: growstuff_test
ports: ['5432:5432']
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
env:
APP_DOMAIN_NAME: localhost:3000
APP_PROTOCOL: http
CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
DATABASE_URL: postgres://postgres:postgres@localhost:5432/growstuff_test
DEVISE_SECRET_KEY: secret
ELASTIC_SEARCH_VERSION: "7.5.1-amd64"
GROWSTUFF_EMAIL: "noreply@test.growstuff.org"
GROWSTUFF_FLICKR_KEY: secretkey"
GROWSTUFF_FLICKR_SECRET: secretsecret
GROWSTUFF_SITE_NAME: "Growstuff (travis)"
RAILS_ENV: test
RAILS_SECRET_TOKEN: supersecret
steps:
- name: Checkout this repo
uses: actions/checkout@v5
- name: Configure sysctl limits
run: |
sudo swapoff -a
sudo sysctl -w vm.swappiness=1
sudo sysctl -w fs.file-max=262144
sudo sysctl -w vm.max_map_count=262144
- name: Start Elasticsearch
uses: elastic/elastic-github-actions/elasticsearch@master
with:
stack-version: 7.5.1
##
# Cache Yarn modules
#
# See https://github.com/actions/cache/blob/master/examples.md#node---yarn for details
#
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- name: Setup yarn cache
uses: actions/cache@v4
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Install required OS packages
run: |
sudo apt-get -y install libpq-dev google-chrome-stable
- name: Install NodeJS
uses: actions/setup-node@v5
with:
node-version: '12'
- name: Install Ruby (version given by .ruby-version) and Bundler
uses: ruby/setup-ruby@v1
with:
bundler-cache: true
- name: Install required JS packages
run: yarn install
- name: install chrome
run: sudo apt-get install google-chrome-stable
- name: Prepare database for testing
run: bundle exec rails db:prepare
- name: precompile assets
run: bundle exec rails assets:precompile
- name: index into elastic search
run: bundle exec rails search:reindex
- name: Run rspec (crops/)
run: bundle exec rspec spec/features/crops/ -fd -t ~@flaky
- name: Upload screenshots
if: failure()
uses: actions/upload-artifact@v4
with:
name: screenshots
path: tmp/screenshots

View File

@@ -1,109 +0,0 @@
name: CI Features - Gardens
on: [pull_request]
jobs:
rspec:
runs-on: ubuntu-latest
services:
db:
image: postgres
env:
##
# The Postgres service fails its docker health check unless you
# specify these environment variables
#
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: growstuff_test
ports: ['5432:5432']
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
env:
APP_DOMAIN_NAME: localhost:3000
APP_PROTOCOL: http
CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
DATABASE_URL: postgres://postgres:postgres@localhost:5432/growstuff_test
DEVISE_SECRET_KEY: secret
ELASTIC_SEARCH_VERSION: "7.5.1-amd64"
GROWSTUFF_EMAIL: "noreply@test.growstuff.org"
GROWSTUFF_FLICKR_KEY: secretkey"
GROWSTUFF_FLICKR_SECRET: secretsecret
GROWSTUFF_SITE_NAME: "Growstuff (travis)"
RAILS_ENV: test
RAILS_SECRET_TOKEN: supersecret
steps:
- name: Checkout this repo
uses: actions/checkout@v5
- name: Configure sysctl limits
run: |
sudo swapoff -a
sudo sysctl -w vm.swappiness=1
sudo sysctl -w fs.file-max=262144
sudo sysctl -w vm.max_map_count=262144
- name: Start Elasticsearch
uses: elastic/elastic-github-actions/elasticsearch@master
with:
stack-version: 7.5.1
##
# Cache Yarn modules
#
# See https://github.com/actions/cache/blob/master/examples.md#node---yarn for details
#
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- name: Setup yarn cache
uses: actions/cache@v4
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Install required OS packages
run: |
sudo apt-get -y install libpq-dev google-chrome-stable
- name: Install NodeJS
uses: actions/setup-node@v5
with:
node-version: '12'
- name: Install Ruby (version given by .ruby-version) and Bundler
uses: ruby/setup-ruby@v1
with:
bundler-cache: true
- name: Install required JS packages
run: yarn install
- name: install chrome
run: sudo apt-get install google-chrome-stable
- name: Prepare database for testing
run: bundle exec rails db:prepare
- name: precompile assets
run: bundle exec rails assets:precompile
- name: index into elastic search
run: bundle exec rails search:reindex
- name: Run rspec (gardens/)
run: bundle exec rspec spec/features/gardens/ -fd -t ~@flaky
- name: Upload screenshots
if: failure()
uses: actions/upload-artifact@v4
with:
name: screenshots
path: tmp/screenshots

View File

@@ -1,109 +0,0 @@
name: CI Features - Harvests
on: [pull_request]
jobs:
rspec:
runs-on: ubuntu-latest
services:
db:
image: postgres
env:
##
# The Postgres service fails its docker health check unless you
# specify these environment variables
#
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: growstuff_test
ports: ['5432:5432']
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
env:
APP_DOMAIN_NAME: localhost:3000
APP_PROTOCOL: http
CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
DATABASE_URL: postgres://postgres:postgres@localhost:5432/growstuff_test
DEVISE_SECRET_KEY: secret
ELASTIC_SEARCH_VERSION: "7.5.1-amd64"
GROWSTUFF_EMAIL: "noreply@test.growstuff.org"
GROWSTUFF_FLICKR_KEY: secretkey"
GROWSTUFF_FLICKR_SECRET: secretsecret
GROWSTUFF_SITE_NAME: "Growstuff (travis)"
RAILS_ENV: test
RAILS_SECRET_TOKEN: supersecret
steps:
- name: Checkout this repo
uses: actions/checkout@v5
- name: Configure sysctl limits
run: |
sudo swapoff -a
sudo sysctl -w vm.swappiness=1
sudo sysctl -w fs.file-max=262144
sudo sysctl -w vm.max_map_count=262144
- name: Start Elasticsearch
uses: elastic/elastic-github-actions/elasticsearch@master
with:
stack-version: 7.5.1
##
# Cache Yarn modules
#
# See https://github.com/actions/cache/blob/master/examples.md#node---yarn for details
#
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- name: Setup yarn cache
uses: actions/cache@v4
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Install required OS packages
run: |
sudo apt-get -y install libpq-dev google-chrome-stable
- name: Install NodeJS
uses: actions/setup-node@v5
with:
node-version: '12'
- name: Install Ruby (version given by .ruby-version) and Bundler
uses: ruby/setup-ruby@v1
with:
bundler-cache: true
- name: Install required JS packages
run: yarn install
- name: install chrome
run: sudo apt-get install google-chrome-stable
- name: Prepare database for testing
run: bundle exec rails db:prepare
- name: precompile assets
run: bundle exec rails assets:precompile
- name: index into elastic search
run: bundle exec rails search:reindex
- name: Run rspec (harvests/)
run: bundle exec rspec spec/features/harvests/ -fd -t ~@flaky
- name: Upload screenshots
if: failure()
uses: actions/upload-artifact@v4
with:
name: screenshots
path: tmp/screenshots

View File

@@ -1,109 +0,0 @@
name: CI Features - Home
on: [pull_request]
jobs:
rspec:
runs-on: ubuntu-latest
services:
db:
image: postgres
env:
##
# The Postgres service fails its docker health check unless you
# specify these environment variables
#
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: growstuff_test
ports: ['5432:5432']
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
env:
APP_DOMAIN_NAME: localhost:3000
APP_PROTOCOL: http
CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
DATABASE_URL: postgres://postgres:postgres@localhost:5432/growstuff_test
DEVISE_SECRET_KEY: secret
ELASTIC_SEARCH_VERSION: "7.5.1-amd64"
GROWSTUFF_EMAIL: "noreply@test.growstuff.org"
GROWSTUFF_FLICKR_KEY: secretkey"
GROWSTUFF_FLICKR_SECRET: secretsecret
GROWSTUFF_SITE_NAME: "Growstuff (travis)"
RAILS_ENV: test
RAILS_SECRET_TOKEN: supersecret
steps:
- name: Checkout this repo
uses: actions/checkout@v5
- name: Configure sysctl limits
run: |
sudo swapoff -a
sudo sysctl -w vm.swappiness=1
sudo sysctl -w fs.file-max=262144
sudo sysctl -w vm.max_map_count=262144
- name: Start Elasticsearch
uses: elastic/elastic-github-actions/elasticsearch@master
with:
stack-version: 7.5.1
##
# Cache Yarn modules
#
# See https://github.com/actions/cache/blob/master/examples.md#node---yarn for details
#
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- name: Setup yarn cache
uses: actions/cache@v4
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Install required OS packages
run: |
sudo apt-get -y install libpq-dev google-chrome-stable
- name: Install NodeJS
uses: actions/setup-node@v5
with:
node-version: '12'
- name: Install Ruby (version given by .ruby-version) and Bundler
uses: ruby/setup-ruby@v1
with:
bundler-cache: true
- name: Install required JS packages
run: yarn install
- name: install chrome
run: sudo apt-get install google-chrome-stable
- name: Prepare database for testing
run: bundle exec rails db:prepare
- name: precompile assets
run: bundle exec rails assets:precompile
- name: index into elastic search
run: bundle exec rails search:reindex
- name: Run rspec (home/)
run: bundle exec rspec spec/features/home/ -fd -t ~@flaky
- name: Upload screenshots
if: failure()
uses: actions/upload-artifact@v4
with:
name: screenshots
path: tmp/screenshots

View File

@@ -1,109 +0,0 @@
name: CI Features - Members
on: [pull_request]
jobs:
rspec:
runs-on: ubuntu-latest
services:
db:
image: postgres
env:
##
# The Postgres service fails its docker health check unless you
# specify these environment variables
#
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: growstuff_test
ports: ['5432:5432']
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
env:
APP_DOMAIN_NAME: localhost:3000
APP_PROTOCOL: http
CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
DATABASE_URL: postgres://postgres:postgres@localhost:5432/growstuff_test
DEVISE_SECRET_KEY: secret
ELASTIC_SEARCH_VERSION: "7.5.1-amd64"
GROWSTUFF_EMAIL: "noreply@test.growstuff.org"
GROWSTUFF_FLICKR_KEY: secretkey"
GROWSTUFF_FLICKR_SECRET: secretsecret
GROWSTUFF_SITE_NAME: "Growstuff (travis)"
RAILS_ENV: test
RAILS_SECRET_TOKEN: supersecret
steps:
- name: Checkout this repo
uses: actions/checkout@v5
- name: Configure sysctl limits
run: |
sudo swapoff -a
sudo sysctl -w vm.swappiness=1
sudo sysctl -w fs.file-max=262144
sudo sysctl -w vm.max_map_count=262144
- name: Start Elasticsearch
uses: elastic/elastic-github-actions/elasticsearch@master
with:
stack-version: 7.5.1
##
# Cache Yarn modules
#
# See https://github.com/actions/cache/blob/master/examples.md#node---yarn for details
#
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- name: Setup yarn cache
uses: actions/cache@v4
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Install required OS packages
run: |
sudo apt-get -y install libpq-dev google-chrome-stable
- name: Install NodeJS
uses: actions/setup-node@v5
with:
node-version: '12'
- name: Install Ruby (version given by .ruby-version) and Bundler
uses: ruby/setup-ruby@v1
with:
bundler-cache: true
- name: Install required JS packages
run: yarn install
- name: install chrome
run: sudo apt-get install google-chrome-stable
- name: Prepare database for testing
run: bundle exec rails db:prepare
- name: precompile assets
run: bundle exec rails assets:precompile
- name: index into elastic search
run: bundle exec rails search:reindex
- name: Run rspec (members/)
run: bundle exec rspec spec/features/members/ -fd -t ~@flaky
- name: Upload screenshots
if: failure()
uses: actions/upload-artifact@v4
with:
name: screenshots
path: tmp/screenshots

View File

@@ -1,109 +0,0 @@
name: CI Features - Admin
on: [pull_request]
jobs:
rspec:
runs-on: ubuntu-latest
services:
db:
image: postgres
env:
##
# The Postgres service fails its docker health check unless you
# specify these environment variables
#
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: growstuff_test
ports: ['5432:5432']
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
env:
APP_DOMAIN_NAME: localhost:3000
APP_PROTOCOL: http
CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
DATABASE_URL: postgres://postgres:postgres@localhost:5432/growstuff_test
DEVISE_SECRET_KEY: secret
ELASTIC_SEARCH_VERSION: "7.5.1-amd64"
GROWSTUFF_EMAIL: "noreply@test.growstuff.org"
GROWSTUFF_FLICKR_KEY: secretkey"
GROWSTUFF_FLICKR_SECRET: secretsecret
GROWSTUFF_SITE_NAME: "Growstuff (travis)"
RAILS_ENV: test
RAILS_SECRET_TOKEN: supersecret
steps:
- name: Checkout this repo
uses: actions/checkout@v5
- name: Configure sysctl limits
run: |
sudo swapoff -a
sudo sysctl -w vm.swappiness=1
sudo sysctl -w fs.file-max=262144
sudo sysctl -w vm.max_map_count=262144
- name: Start Elasticsearch
uses: elastic/elastic-github-actions/elasticsearch@master
with:
stack-version: 7.5.1
##
# Cache Yarn modules
#
# See https://github.com/actions/cache/blob/master/examples.md#node---yarn for details
#
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- name: Setup yarn cache
uses: actions/cache@v4
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Install required OS packages
run: |
sudo apt-get -y install libpq-dev google-chrome-stable
- name: Install NodeJS
uses: actions/setup-node@v5
with:
node-version: '12'
- name: Install Ruby (version given by .ruby-version) and Bundler
uses: ruby/setup-ruby@v1
with:
bundler-cache: true
- name: Install required JS packages
run: yarn install
- name: install chrome
run: sudo apt-get install google-chrome-stable
- name: Prepare database for testing
run: bundle exec rails db:prepare
- name: precompile assets
run: bundle exec rails assets:precompile
- name: index into elastic search
run: bundle exec rails search:reindex
- name: Run rspec (places/)
run: bundle exec rspec spec/features/places/ -fd
- name: Upload screenshots
if: failure()
uses: actions/upload-artifact@v4
with:
name: screenshots
path: tmp/screenshots

View File

@@ -1,109 +0,0 @@
name: CI Features - Plantings
on: [pull_request]
jobs:
rspec:
runs-on: ubuntu-latest
services:
db:
image: postgres
env:
##
# The Postgres service fails its docker health check unless you
# specify these environment variables
#
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: growstuff_test
ports: ['5432:5432']
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
env:
APP_DOMAIN_NAME: localhost:3000
APP_PROTOCOL: http
CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
DATABASE_URL: postgres://postgres:postgres@localhost:5432/growstuff_test
DEVISE_SECRET_KEY: secret
ELASTIC_SEARCH_VERSION: "7.5.1-amd64"
GROWSTUFF_EMAIL: "noreply@test.growstuff.org"
GROWSTUFF_FLICKR_KEY: secretkey"
GROWSTUFF_FLICKR_SECRET: secretsecret
GROWSTUFF_SITE_NAME: "Growstuff (travis)"
RAILS_ENV: test
RAILS_SECRET_TOKEN: supersecret
steps:
- name: Checkout this repo
uses: actions/checkout@v5
- name: Configure sysctl limits
run: |
sudo swapoff -a
sudo sysctl -w vm.swappiness=1
sudo sysctl -w fs.file-max=262144
sudo sysctl -w vm.max_map_count=262144
- name: Start Elasticsearch
uses: elastic/elastic-github-actions/elasticsearch@master
with:
stack-version: 7.5.1
##
# Cache Yarn modules
#
# See https://github.com/actions/cache/blob/master/examples.md#node---yarn for details
#
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- name: Setup yarn cache
uses: actions/cache@v4
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Install required OS packages
run: |
sudo apt-get -y install libpq-dev google-chrome-stable
- name: Install NodeJS
uses: actions/setup-node@v5
with:
node-version: '12'
- name: Install Ruby (version given by .ruby-version) and Bundler
uses: ruby/setup-ruby@v1
with:
bundler-cache: true
- name: Install required JS packages
run: yarn install
- name: install chrome
run: sudo apt-get install google-chrome-stable
- name: Prepare database for testing
run: bundle exec rails db:prepare
- name: precompile assets
run: bundle exec rails assets:precompile
- name: index into elastic search
run: bundle exec rails search:reindex
- name: Run rspec (plantings/)
run: bundle exec rspec spec/features/plantings/ -fd
- name: Upload screenshots
if: failure()
uses: actions/upload-artifact@v4
with:
name: screenshots
path: tmp/screenshots

View File

@@ -1,109 +0,0 @@
name: CI Features - Posts
on: [pull_request]
jobs:
rspec:
runs-on: ubuntu-latest
services:
db:
image: postgres
env:
##
# The Postgres service fails its docker health check unless you
# specify these environment variables
#
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: growstuff_test
ports: ['5432:5432']
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
env:
APP_DOMAIN_NAME: localhost:3000
APP_PROTOCOL: http
CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
DATABASE_URL: postgres://postgres:postgres@localhost:5432/growstuff_test
DEVISE_SECRET_KEY: secret
ELASTIC_SEARCH_VERSION: "7.5.1-amd64"
GROWSTUFF_EMAIL: "noreply@test.growstuff.org"
GROWSTUFF_FLICKR_KEY: secretkey"
GROWSTUFF_FLICKR_SECRET: secretsecret
GROWSTUFF_SITE_NAME: "Growstuff (travis)"
RAILS_ENV: test
RAILS_SECRET_TOKEN: supersecret
steps:
- name: Checkout this repo
uses: actions/checkout@v5
- name: Configure sysctl limits
run: |
sudo swapoff -a
sudo sysctl -w vm.swappiness=1
sudo sysctl -w fs.file-max=262144
sudo sysctl -w vm.max_map_count=262144
- name: Start Elasticsearch
uses: elastic/elastic-github-actions/elasticsearch@master
with:
stack-version: 7.5.1
##
# Cache Yarn modules
#
# See https://github.com/actions/cache/blob/master/examples.md#node---yarn for details
#
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- name: Setup yarn cache
uses: actions/cache@v4
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Install required OS packages
run: |
sudo apt-get -y install libpq-dev google-chrome-stable
- name: Install NodeJS
uses: actions/setup-node@v5
with:
node-version: '12'
- name: Install Ruby (version given by .ruby-version) and Bundler
uses: ruby/setup-ruby@v1
with:
bundler-cache: true
- name: Install required JS packages
run: yarn install
- name: install chrome
run: sudo apt-get install google-chrome-stable
- name: Prepare database for testing
run: bundle exec rails db:prepare
- name: precompile assets
run: bundle exec rails assets:precompile
- name: index into elastic search
run: bundle exec rails search:reindex
- name: Run rspec (posts/)
run: bundle exec rspec spec/features/posts/ -fd
- name: Upload screenshots
if: failure()
uses: actions/upload-artifact@v4
with:
name: screenshots
path: tmp/screenshots

View File

@@ -1,109 +0,0 @@
name: CI Features - Seeds
on: [pull_request]
jobs:
rspec:
runs-on: ubuntu-latest
services:
db:
image: postgres
env:
##
# The Postgres service fails its docker health check unless you
# specify these environment variables
#
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: growstuff_test
ports: ['5432:5432']
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
env:
APP_DOMAIN_NAME: localhost:3000
APP_PROTOCOL: http
CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
DATABASE_URL: postgres://postgres:postgres@localhost:5432/growstuff_test
DEVISE_SECRET_KEY: secret
ELASTIC_SEARCH_VERSION: "7.5.1-amd64"
GROWSTUFF_EMAIL: "noreply@test.growstuff.org"
GROWSTUFF_FLICKR_KEY: secretkey"
GROWSTUFF_FLICKR_SECRET: secretsecret
GROWSTUFF_SITE_NAME: "Growstuff (travis)"
RAILS_ENV: test
RAILS_SECRET_TOKEN: supersecret
steps:
- name: Checkout this repo
uses: actions/checkout@v5
- name: Configure sysctl limits
run: |
sudo swapoff -a
sudo sysctl -w vm.swappiness=1
sudo sysctl -w fs.file-max=262144
sudo sysctl -w vm.max_map_count=262144
- name: Start Elasticsearch
uses: elastic/elastic-github-actions/elasticsearch@master
with:
stack-version: 7.5.1
##
# Cache Yarn modules
#
# See https://github.com/actions/cache/blob/master/examples.md#node---yarn for details
#
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- name: Setup yarn cache
uses: actions/cache@v4
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Install required OS packages
run: |
sudo apt-get -y install libpq-dev google-chrome-stable
- name: Install NodeJS
uses: actions/setup-node@v5
with:
node-version: '12'
- name: Install Ruby (version given by .ruby-version) and Bundler
uses: ruby/setup-ruby@v1
with:
bundler-cache: true
- name: Install required JS packages
run: yarn install
- name: install chrome
run: sudo apt-get install google-chrome-stable
- name: Prepare database for testing
run: bundle exec rails db:prepare
- name: precompile assets
run: bundle exec rails assets:precompile
- name: index into elastic search
run: bundle exec rails search:reindex
- name: Run rspec (seeds/)
run: bundle exec rspec spec/features/seeds/ -fd -t ~@flaky
- name: Upload screenshots
if: failure()
uses: actions/upload-artifact@v4
with:
name: screenshots
path: tmp/screenshots

View File

@@ -1,109 +0,0 @@
name: CI Features - Timeline
on: [pull_request]
jobs:
rspec:
runs-on: ubuntu-latest
services:
db:
image: postgres
env:
##
# The Postgres service fails its docker health check unless you
# specify these environment variables
#
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: growstuff_test
ports: ['5432:5432']
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
env:
APP_DOMAIN_NAME: localhost:3000
APP_PROTOCOL: http
CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
DATABASE_URL: postgres://postgres:postgres@localhost:5432/growstuff_test
DEVISE_SECRET_KEY: secret
ELASTIC_SEARCH_VERSION: "7.5.1-amd64"
GROWSTUFF_EMAIL: "noreply@test.growstuff.org"
GROWSTUFF_FLICKR_KEY: secretkey"
GROWSTUFF_FLICKR_SECRET: secretsecret
GROWSTUFF_SITE_NAME: "Growstuff (travis)"
RAILS_ENV: test
RAILS_SECRET_TOKEN: supersecret
steps:
- name: Checkout this repo
uses: actions/checkout@v5
- name: Configure sysctl limits
run: |
sudo swapoff -a
sudo sysctl -w vm.swappiness=1
sudo sysctl -w fs.file-max=262144
sudo sysctl -w vm.max_map_count=262144
- name: Start Elasticsearch
uses: elastic/elastic-github-actions/elasticsearch@master
with:
stack-version: 7.5.1
##
# Cache Yarn modules
#
# See https://github.com/actions/cache/blob/master/examples.md#node---yarn for details
#
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- name: Setup yarn cache
uses: actions/cache@v4
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Install required OS packages
run: |
sudo apt-get -y install libpq-dev google-chrome-stable
- name: Install NodeJS
uses: actions/setup-node@v5
with:
node-version: '12'
- name: Install Ruby (version given by .ruby-version) and Bundler
uses: ruby/setup-ruby@v1
with:
bundler-cache: true
- name: Install required JS packages
run: yarn install
- name: install chrome
run: sudo apt-get install google-chrome-stable
- name: Prepare database for testing
run: bundle exec rails db:prepare
- name: precompile assets
run: bundle exec rails assets:precompile
- name: index into elastic search
run: bundle exec rails search:reindex
- name: Run rspec (timeline/)
run: bundle exec rspec spec/features/timeline/ -fd -t ~@flaky
- name: Upload screenshots
if: failure()
uses: actions/upload-artifact@v4
with:
name: screenshots
path: tmp/screenshots

View File

@@ -1,118 +0,0 @@
name: CI Features
on: [pull_request]
jobs:
rspec:
runs-on: ubuntu-latest
services:
db:
image: postgres
env:
##
# The Postgres service fails its docker health check unless you
# specify these environment variables
#
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: growstuff_test
ports: ['5432:5432']
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
env:
APP_DOMAIN_NAME: localhost:3000
APP_PROTOCOL: http
CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
DATABASE_URL: postgres://postgres:postgres@localhost:5432/growstuff_test
DEVISE_SECRET_KEY: secret
ELASTIC_SEARCH_VERSION: "7.5.1-amd64"
GROWSTUFF_EMAIL: "noreply@test.growstuff.org"
GROWSTUFF_FLICKR_KEY: secretkey"
GROWSTUFF_FLICKR_SECRET: secretsecret
GROWSTUFF_SITE_NAME: "Growstuff (travis)"
RAILS_ENV: test
RAILS_SECRET_TOKEN: supersecret
steps:
- name: Checkout this repo
uses: actions/checkout@v5
- name: Configure sysctl limits
run: |
sudo swapoff -a
sudo sysctl -w vm.swappiness=1
sudo sysctl -w fs.file-max=262144
sudo sysctl -w vm.max_map_count=262144
- name: Start Elasticsearch
uses: elastic/elastic-github-actions/elasticsearch@master
with:
stack-version: 7.5.1
##
# Cache Yarn modules
#
# See https://github.com/actions/cache/blob/master/examples.md#node---yarn for details
#
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- name: Setup yarn cache
uses: actions/cache@v4
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Install required OS packages
run: |
sudo apt-get -y install libpq-dev google-chrome-stable
- name: Install NodeJS
uses: actions/setup-node@v5
with:
node-version: '12'
- name: Install Ruby (version given by .ruby-version) and Bundler
uses: ruby/setup-ruby@v1
with:
bundler-cache: true
- name: Install required JS packages
run: yarn install
- name: install chrome
run: sudo apt-get install google-chrome-stable
- name: Prepare database for testing
run: bundle exec rails db:prepare
- name: precompile assets
run: bundle exec rails assets:precompile
- name: index into elastic search
run: bundle exec rails search:reindex
- name: Run rspec (*_spec)
run: bundle exec rspec spec/features/*_spec.rb -fd
- name: Run rspec (percy/)
run: bundle exec rspec spec/features/percy/ -fd
- name: Run rspec (photos/)
run: bundle exec rspec spec/features/photos/ -fd
- name: Run rspec (rss/)
run: bundle exec rspec spec/features/rss/ -fd
- name: Upload screenshots
if: failure()
uses: actions/upload-artifact@v4
with:
name: screenshots
path: tmp/screenshots

View File

@@ -6,7 +6,7 @@ jobs:
contributors: contributors:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v4
- name: Install ruby version specified in .ruby-version - name: Install ruby version specified in .ruby-version
uses: ruby/setup-ruby@v1 uses: ruby/setup-ruby@v1
with: with:
@@ -53,7 +53,7 @@ jobs:
steps: steps:
- name: Checkout this repo - name: Checkout this repo
uses: actions/checkout@v5 uses: actions/checkout@v4
- name: Configure sysctl limits - name: Configure sysctl limits
run: | run: |
@@ -89,7 +89,7 @@ jobs:
sudo apt-get -y install libpq-dev google-chrome-stable sudo apt-get -y install libpq-dev google-chrome-stable
- name: Install NodeJS - name: Install NodeJS
uses: actions/setup-node@v5 uses: actions/setup-node@v4
with: with:
node-version: '12' node-version: '12'
@@ -106,25 +106,17 @@ jobs:
- name: Prepare database for testing - name: Prepare database for testing
run: bundle exec rails db:prepare run: bundle exec rails db:prepare
- name: precompile assets
run: bundle exec rails assets:precompile
- name: index into elastic search
run: bundle exec rails search:reindex
- name: Run rspec (report results to Percy.io and CodeClimate)
run: bundle exec rspec spec -fd
- name: Run rspec (lib) - name: Report to code climate
run: bundle exec rspec spec/lib/ -fd --fail-fast run: |
gem install codeclimate-test-reporter
- name: Run rspec (services) codeclimate-test-reporter
run: bundle exec rspec spec/services/ -fd --fail-fast
- name: Run rspec (models)
run: bundle exec rspec spec/models/ -fd --fail-fast
- name: Run rspec (controllers)
run: bundle exec rspec spec/controllers/ -fd --fail-fast
- name: Run rspec (views)
run: bundle exec rspec spec/views/ -fd --fail-fast
- name: Run rspec (routing)
run: bundle exec rspec spec/routing/ -fd --fail-fast
- name: Run rspec (request)
run: bundle exec rspec spec/requests/ -fd --fail-fast

View File

@@ -1,5 +1,5 @@
inherit_from: .rubocop_todo.yml inherit_from: .rubocop_todo.yml
plugins: require:
- rubocop-factory_bot - rubocop-factory_bot
- rubocop-capybara - rubocop-capybara
- rubocop-rails - rubocop-rails
@@ -11,7 +11,7 @@ AllCops:
Exclude: Exclude:
- 'db/schema.rb' - 'db/schema.rb'
- 'vendor/**/*' - 'vendor/**/*'
TargetRailsVersion: 7.1 TargetRailsVersion: 7.0
Rails: Rails:
Enabled: true Enabled: true

View File

@@ -1,30 +1,25 @@
# This configuration was generated by # This configuration was generated by
# `rubocop --auto-gen-config` # `rubocop --auto-gen-config`
# on 2025-09-07 08:46:49 UTC using RuboCop version 1.80.2. # on 2024-07-13 05:22:30 UTC using RuboCop version 1.65.0.
# The point is for the user to remove these configuration records # The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base. # one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new # Note that changes in the inspected code, or installation of new
# versions of RuboCop, may require this file to be generated again. # versions of RuboCop, may require this file to be generated again.
# Offense count: 2 # Offense count: 231
# Configuration parameters: EnforcedStyle.
# SupportedStyles: link_or_button, strict
Capybara/ClickLinkOrButtonStyle:
Enabled: false
# Offense count: 84
# This cop supports safe autocorrection (--autocorrect). # This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: TreatCommentsAsGroupSeparators, ConsiderPunctuation. # Configuration parameters: EnforcedStyle.
Bundler/OrderedGems: # SupportedStyles: have_no, not_to
Exclude: Capybara/NegationMatcher:
- 'Gemfile' Enabled: false
# Offense count: 18 # Offense count: 39
Capybara/NegationMatcherAfterVisit:
Exclude:
- 'spec/features/crops/crop_detail_page_spec.rb'
- 'spec/features/crops/crop_wranglers_spec.rb'
- 'spec/features/gardens/gardens_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: 34
# This cop supports safe autocorrection (--autocorrect). # This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: DefaultSelector. # Configuration parameters: DefaultSelector.
Capybara/RSpec/HaveSelector: Capybara/RSpec/HaveSelector:
@@ -37,6 +32,7 @@ Capybara/RSpec/HaveSelector:
- 'spec/features/plantings/planting_a_crop_spec.rb' - 'spec/features/plantings/planting_a_crop_spec.rb'
- 'spec/features/seeds/adding_seeds_spec.rb' - 'spec/features/seeds/adding_seeds_spec.rb'
- 'spec/features/shared_examples/crop_suggest.rb' - 'spec/features/shared_examples/crop_suggest.rb'
- 'spec/helpers/application_helper_spec.rb'
- 'spec/support/feature_helpers.rb' - 'spec/support/feature_helpers.rb'
- 'spec/views/posts/show.html.haml_spec.rb' - 'spec/views/posts/show.html.haml_spec.rb'
@@ -67,7 +63,8 @@ FactoryBot/AssociationStyle:
# Offense count: 3 # Offense count: 3
# This cop supports unsafe autocorrection (--autocorrect-all). # This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: EnforcedStyle, ExplicitOnly. # Configuration parameters: AutoCorrect, Include, EnforcedStyle, ExplicitOnly.
# Include: **/*_spec.rb, **/spec/**/*, **/test/**/*, **/features/support/factories/**/*.rb
# SupportedStyles: create_list, n_times # SupportedStyles: create_list, n_times
FactoryBot/CreateList: FactoryBot/CreateList:
Exclude: Exclude:
@@ -76,44 +73,71 @@ FactoryBot/CreateList:
- 'spec/views/posts/index.html.haml_spec.rb' - 'spec/views/posts/index.html.haml_spec.rb'
# Offense count: 4 # Offense count: 4
# Configuration parameters: MaxAmount. # Configuration parameters: Include, MaxAmount.
# Include: **/*_spec.rb, **/spec/**/*, **/test/**/*, **/features/support/factories/**/*.rb
FactoryBot/ExcessiveCreateList: FactoryBot/ExcessiveCreateList:
Exclude: Exclude:
- 'spec/controllers/posts_controller_spec.rb' - 'spec/controllers/posts_controller_spec.rb'
- 'spec/features/crops/show_spec.rb' - 'spec/features/crops/show_spec.rb'
- 'spec/features/percy/percy_spec.rb' - 'spec/features/percy/percy_spec.rb'
# Offense count: 1144 # Offense count: 1127
# This cop supports unsafe autocorrection (--autocorrect-all). # This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: Include.
# Include: **/*_spec.rb, **/spec/**/*, **/test/**/*, **/features/support/factories/**/*.rb
FactoryBot/SyntaxMethods: FactoryBot/SyntaxMethods:
Enabled: false Enabled: false
# Offense count: 2 # Offense count: 1
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyleAlignWith.
# SupportedStylesAlignWith: either, start_of_block, start_of_line
Layout/BlockAlignment:
Exclude:
- 'spec/factories/activity.rb'
# Offense count: 1
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: AllowForAlignment.
Layout/CommentIndentation:
Exclude:
- 'config/environments/production.rb'
# Offense count: 6
# This cop supports safe autocorrection (--autocorrect).
Layout/EmptyLineAfterMagicComment:
Exclude:
- 'config/initializers/application_controller_renderer.rb'
- 'config/initializers/backtrace_silencers.rb'
- 'config/initializers/content_security_policy.rb'
- 'config/initializers/mime_types.rb'
- 'config/initializers/new_framework_defaults_5_2.rb'
- 'db/migrate/20240218053122_add_slug_to_activity.rb'
# Offense count: 5
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EmptyLineBetweenMethodDefs, EmptyLineBetweenClassDefs, EmptyLineBetweenModuleDefs, DefLikeMacros, AllowAdjacentOneLineDefs, NumberOfEmptyLines.
Layout/EmptyLineBetweenDefs:
Exclude:
- 'db/migrate/20171129041341_create_photographings.rb'
- 'db/migrate/20190130090437_add_crop_to_photographings.rb'
# Offense count: 1
# This cop supports safe autocorrection (--autocorrect). # This cop supports safe autocorrection (--autocorrect).
Layout/EmptyLines: Layout/EmptyLines:
Exclude: Exclude:
- 'Gemfile' - 'spec/models/ability_spec.rb'
# Offense count: 7
# This cop supports safe autocorrection (--autocorrect).
Layout/EmptyLinesAfterModuleInclusion:
Exclude:
- 'app/models/forum.rb'
- 'app/models/garden_type.rb'
- 'app/models/member.rb'
- 'app/models/plant_part.rb'
- 'app/models/role.rb'
- 'app/models/seed.rb'
# Offense count: 2 # Offense count: 2
# This cop supports safe autocorrection (--autocorrect). # This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: AllowForAlignment, AllowBeforeTrailingComments, ForceEqualSignAlignment. # Configuration parameters: EnforcedStyle.
Layout/ExtraSpacing: # SupportedStyles: empty_lines, no_empty_lines
Layout/EmptyLinesAroundBlockBody:
Exclude: Exclude:
- 'app/controllers/registrations_controller.rb' - 'lib/tasks/gardens.rake'
- 'config/initializers/mailboxer.rb' - 'spec/rails_helper.rb'
# Offense count: 4 # Offense count: 2
# This cop supports safe autocorrection (--autocorrect). # This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle. # Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle.
# SupportedHashRocketStyles: key, separator, table # SupportedHashRocketStyles: key, separator, table
@@ -121,43 +145,70 @@ Layout/ExtraSpacing:
# SupportedLastArgumentHashStyles: always_inspect, always_ignore, ignore_implicit, ignore_explicit # SupportedLastArgumentHashStyles: always_inspect, always_ignore, ignore_implicit, ignore_explicit
Layout/HashAlignment: Layout/HashAlignment:
Exclude: Exclude:
- 'app/controllers/activities_controller.rb' - 'app/models/concerns/search_activities.rb'
- 'lib/tasks/wikidata.rake' - 'app/models/concerns/search_plantings.rb'
# Offense count: 1 # Offense count: 10
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle.
# SupportedStyles: space, no_space
Layout/LineContinuationSpacing:
Exclude:
- 'app/mailers/notifier_mailer.rb'
- 'app/models/seed.rb'
- 'lib/tasks/growstuff.rake'
- 'spec/features/rss/plantings_spec.rb'
- 'spec/features/rss/posts_spec.rb'
- 'spec/features/rss/seeds_spec.rb'
- 'spec/models/seed_spec.rb'
# Offense count: 9
# This cop supports safe autocorrection (--autocorrect). # This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle, IndentationWidth. # Configuration parameters: EnforcedStyle, IndentationWidth.
# SupportedStyles: aligned, indented # SupportedStyles: aligned, indented
Layout/LineEndStringConcatenationIndentation: Layout/LineEndStringConcatenationIndentation:
Exclude: Exclude:
- 'app/mailers/notifier_mailer.rb'
- 'app/models/seed.rb' - 'app/models/seed.rb'
- 'lib/tasks/growstuff.rake'
- 'spec/features/rss/plantings_spec.rb'
- 'spec/features/rss/posts_spec.rb'
- 'spec/features/rss/seeds_spec.rb'
# Offense count: 3 # Offense count: 3
# This cop supports safe autocorrection (--autocorrect). # This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: Max, AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, IgnoreCopDirectives, AllowedPatterns, SplitStrings. # Configuration parameters: Max, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns.
# URISchemes: http, https # URISchemes: http, https
Layout/LineLength: Layout/LineLength:
Exclude: Exclude:
- 'app/models/concerns/predict_planting.rb' - 'app/helpers/crops_helper.rb'
- 'app/models/member.rb'
- 'db/seeds.rb' - 'db/seeds.rb'
- 'spec/requests/plantings_spec.rb'
# Offense count: 1 # Offense count: 1
# This cop supports safe autocorrection (--autocorrect). # This cop supports safe autocorrection (--autocorrect).
Layout/RescueEnsureAlignment: # Configuration parameters: EnforcedStyle.
# SupportedStyles: final_newline, final_blank_line
Layout/TrailingEmptyLines:
Exclude: Exclude:
- 'app/helpers/event_helper.rb' - 'spec/features/admin/newsletter_spec.rb'
# Offense count: 1 # Offense count: 2
# This cop supports safe autocorrection (--autocorrect). # This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: AllowForAlignment, EnforcedStyleForExponentOperator, EnforcedStyleForRationalLiterals. # Configuration parameters: AllowInHeredoc.
# SupportedStylesForExponentOperator: space, no_space Layout/TrailingWhitespace:
# SupportedStylesForRationalLiterals: space, no_space
Layout/SpaceAroundOperators:
Exclude: Exclude:
- 'config/initializers/mailboxer.rb' - 'spec/factories/activity.rb'
# Offense count: 4 # Offense count: 3
# This cop supports safe autocorrection (--autocorrect).
Lint/AmbiguousOperatorPrecedence:
Exclude:
- 'db/seeds.rb'
- 'spec/helpers/gardens_helper_spec.rb'
- 'spec/helpers/seeds_helper_spec.rb'
# Offense count: 3
# This cop supports unsafe autocorrection (--autocorrect-all). # This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: RequireParenthesesForMethodChains. # Configuration parameters: RequireParenthesesForMethodChains.
Lint/AmbiguousRange: Lint/AmbiguousRange:
@@ -165,20 +216,14 @@ Lint/AmbiguousRange:
- 'app/models/concerns/search_activities.rb' - 'app/models/concerns/search_activities.rb'
- 'app/models/concerns/search_harvests.rb' - 'app/models/concerns/search_harvests.rb'
- 'app/models/concerns/search_plantings.rb' - 'app/models/concerns/search_plantings.rb'
- 'db/seeds.rb'
# Offense count: 2 # Offense count: 2
# Configuration parameters: IgnoreLiteralBranches, IgnoreConstantBranches, IgnoreDuplicateElseBranch. # Configuration parameters: IgnoreLiteralBranches, IgnoreConstantBranches.
Lint/DuplicateBranch: Lint/DuplicateBranch:
Exclude: Exclude:
- 'app/models/harvest.rb' - 'app/models/harvest.rb'
- 'lib/actions/oauth_signup_action.rb' - 'lib/actions/oauth_signup_action.rb'
# Offense count: 1
Lint/DuplicateMethods:
Exclude:
- 'app/models/planting.rb'
# Offense count: 8 # Offense count: 8
# Configuration parameters: AllowComments, AllowEmptyLambdas. # Configuration parameters: AllowComments, AllowEmptyLambdas.
Lint/EmptyBlock: Lint/EmptyBlock:
@@ -197,6 +242,12 @@ Lint/RedundantCopDisableDirective:
Exclude: Exclude:
- 'db/migrate/20230313015323_create_active_storage_tables.active_storage.rb' - 'db/migrate/20230313015323_create_active_storage_tables.active_storage.rb'
# Offense count: 2
# This cop supports unsafe autocorrection (--autocorrect-all).
Lint/RedundantDirGlobSort:
Exclude:
- 'spec/rails_helper.rb'
# Offense count: 1 # Offense count: 1
# Configuration parameters: AllowComments, AllowNil. # Configuration parameters: AllowComments, AllowNil.
Lint/SuppressedException: Lint/SuppressedException:
@@ -204,18 +255,14 @@ Lint/SuppressedException:
- 'lib/tasks/testing.rake' - 'lib/tasks/testing.rake'
# Offense count: 7 # Offense count: 7
# This cop supports safe autocorrection (--autocorrect). # This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: AutoCorrect.
Lint/UselessAssignment: Lint/UselessAssignment:
Exclude: Exclude:
- 'config.rb' - 'config.rb'
- 'config/compass.rb' - 'config/compass.rb'
# Offense count: 1 # Offense count: 52
Lint/UselessConstantScoping:
Exclude:
- 'app/controllers/members_controller.rb'
# Offense count: 55
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes. # Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes.
Metrics/AbcSize: Metrics/AbcSize:
Max: 151 Max: 151
@@ -224,42 +271,33 @@ Metrics/AbcSize:
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns, inherit_mode. # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns, inherit_mode.
# AllowedMethods: refine # AllowedMethods: refine
Metrics/BlockLength: Metrics/BlockLength:
Max: 116 Max: 115
# Offense count: 9 # Offense count: 7
# Configuration parameters: CountComments, CountAsOne. # Configuration parameters: CountComments, CountAsOne.
Metrics/ClassLength: Metrics/ClassLength:
Max: 181 Max: 183
# Offense count: 8 # Offense count: 6
# Configuration parameters: AllowedMethods, AllowedPatterns. # Configuration parameters: AllowedMethods, AllowedPatterns.
Metrics/CyclomaticComplexity: Metrics/CyclomaticComplexity:
Max: 32 Max: 32
# Offense count: 73 # Offense count: 71
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns. # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
Metrics/MethodLength: Metrics/MethodLength:
Max: 128 Max: 127
# Offense count: 2 # Offense count: 2
# Configuration parameters: CountComments, CountAsOne. # Configuration parameters: CountComments, CountAsOne.
Metrics/ModuleLength: Metrics/ModuleLength:
Max: 132 Max: 125
# Offense count: 7 # Offense count: 5
# Configuration parameters: AllowedMethods, AllowedPatterns. # Configuration parameters: AllowedMethods, AllowedPatterns.
Metrics/PerceivedComplexity: Metrics/PerceivedComplexity:
Max: 32 Max: 32
# Offense count: 2
# Configuration parameters: Mode, AllowedMethods, AllowedPatterns, AllowBangMethods, WaywardPredicates.
# AllowedMethods: call
# WaywardPredicates: nonzero?
Naming/PredicateMethod:
Exclude:
- 'app/models/concerns/finishable.rb'
- 'app/models/seed.rb'
# Offense count: 3 # Offense count: 3
RSpec/AnyInstance: RSpec/AnyInstance:
Exclude: Exclude:
@@ -284,6 +322,7 @@ RSpec/DescribedClass:
# Offense count: 13 # Offense count: 13
# This cop supports unsafe autocorrection (--autocorrect-all). # This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: AutoCorrect.
RSpec/EmptyExampleGroup: RSpec/EmptyExampleGroup:
Exclude: Exclude:
- 'spec/controllers/authentications_controller_spec.rb' - 'spec/controllers/authentications_controller_spec.rb'
@@ -306,10 +345,10 @@ RSpec/EmptyLineAfterExample:
Exclude: Exclude:
- 'spec/models/ability_spec.rb' - 'spec/models/ability_spec.rb'
# Offense count: 137 # Offense count: 140
# Configuration parameters: CountAsOne. # Configuration parameters: CountAsOne.
RSpec/ExampleLength: RSpec/ExampleLength:
Max: 27 Max: 25
# Offense count: 32 # Offense count: 32
RSpec/ExpectInHook: RSpec/ExpectInHook:
@@ -334,6 +373,7 @@ RSpec/HookArgument:
# Offense count: 2 # Offense count: 2
# This cop supports safe autocorrection (--autocorrect). # This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: AutoCorrect.
RSpec/HooksBeforeExamples: RSpec/HooksBeforeExamples:
Exclude: Exclude:
- 'spec/features/crops/creating_a_crop_spec.rb' - 'spec/features/crops/creating_a_crop_spec.rb'
@@ -354,12 +394,12 @@ RSpec/IndexedLet:
- 'spec/models/member_spec.rb' - 'spec/models/member_spec.rb'
- 'spec/views/forums/index.html.haml_spec.rb' - 'spec/views/forums/index.html.haml_spec.rb'
# Offense count: 719 # Offense count: 720
# Configuration parameters: AssignmentOnly. # Configuration parameters: AssignmentOnly.
RSpec/InstanceVariable: RSpec/InstanceVariable:
Enabled: false Enabled: false
# Offense count: 42 # Offense count: 40
RSpec/LetSetup: RSpec/LetSetup:
Enabled: false Enabled: false
@@ -385,14 +425,14 @@ RSpec/MultipleDescribes:
Exclude: Exclude:
- 'spec/features/crops/crop_wranglers_spec.rb' - 'spec/features/crops/crop_wranglers_spec.rb'
# Offense count: 149 # Offense count: 152
RSpec/MultipleExpectations: RSpec/MultipleExpectations:
Max: 19 Max: 19
# Offense count: 147 # Offense count: 138
# Configuration parameters: AllowSubject. # Configuration parameters: AllowSubject.
RSpec/MultipleMemoizedHelpers: RSpec/MultipleMemoizedHelpers:
Max: 20 Max: 14
# Offense count: 133 # Offense count: 133
# Configuration parameters: EnforcedStyle, IgnoreSharedExamples. # Configuration parameters: EnforcedStyle, IgnoreSharedExamples.
@@ -400,12 +440,12 @@ RSpec/MultipleMemoizedHelpers:
RSpec/NamedSubject: RSpec/NamedSubject:
Enabled: false Enabled: false
# Offense count: 110 # Offense count: 111
# Configuration parameters: AllowedGroups. # Configuration parameters: AllowedGroups.
RSpec/NestedGroups: RSpec/NestedGroups:
Max: 6 Max: 6
# Offense count: 407 # Offense count: 403
# Configuration parameters: AllowedPatterns. # Configuration parameters: AllowedPatterns.
# AllowedPatterns: ^expect_, ^assert_ # AllowedPatterns: ^expect_, ^assert_
RSpec/NoExpectationExample: RSpec/NoExpectationExample:
@@ -436,13 +476,15 @@ RSpec/RepeatedExampleGroupBody:
# Offense count: 6 # Offense count: 6
# This cop supports safe autocorrection (--autocorrect). # This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: AutoCorrect.
RSpec/ScatteredSetup: RSpec/ScatteredSetup:
Exclude: Exclude:
- 'spec/features/percy/percy_spec.rb' - 'spec/features/percy/percy_spec.rb'
- 'spec/features/plantings/prediction_spec.rb' - 'spec/features/plantings/prediction_spec.rb'
# Offense count: 1 # Offense count: 1
# Configuration parameters: CustomTransform, IgnoreMethods, IgnoreMetadata. # Configuration parameters: Include, CustomTransform, IgnoreMethods, IgnoreMetadata.
# Include: **/*_spec.rb
RSpec/SpecFilePathFormat: RSpec/SpecFilePathFormat:
Exclude: Exclude:
- 'spec/controllers/member_controller_spec.rb' - 'spec/controllers/member_controller_spec.rb'
@@ -456,6 +498,8 @@ RSpec/StubbedMock:
# Offense count: 1 # Offense count: 1
# This cop supports unsafe autocorrection (--autocorrect-all). # This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: EnforcedStyle.
# SupportedStyles: constant, string
RSpec/VerifiedDoubleReference: RSpec/VerifiedDoubleReference:
Exclude: Exclude:
- 'spec/models/member_spec.rb' - 'spec/models/member_spec.rb'
@@ -485,36 +529,30 @@ RSpecRails/HaveHttpStatus:
RSpecRails/InferredSpecType: RSpecRails/InferredSpecType:
Enabled: false Enabled: false
# Offense count: 1 # Offense count: 28
# This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: Database, Include.
# Configuration parameters: NilOrEmpty, NotPresent, UnlessPresent.
Rails/Blank:
Exclude:
- 'lib/tasks/wikidata.rake'
# Offense count: 29
# Configuration parameters: Database.
# SupportedDatabases: mysql, postgresql # SupportedDatabases: mysql, postgresql
# Include: db/**/*.rb
Rails/BulkChangeTable: Rails/BulkChangeTable:
Enabled: false Enabled: false
# Offense count: 4 # Offense count: 4
# Configuration parameters: Include.
# Include: db/**/*.rb
Rails/CreateTableWithTimestamps: Rails/CreateTableWithTimestamps:
Exclude: Exclude:
- 'db/migrate/20150201052245_create_cms.rb' - 'db/migrate/20150201052245_create_cms.rb'
- 'db/migrate/20171022032108_all_the_predictions.rb' - 'db/migrate/20171022032108_all_the_predictions.rb'
# Offense count: 3 # Offense count: 1
# This cop supports unsafe autocorrection (--autocorrect-all). # This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: EnforcedStyle, AllowToTime. # Configuration parameters: EnforcedStyle, AllowToTime.
# SupportedStyles: strict, flexible # SupportedStyles: strict, flexible
Rails/Date: Rails/Date:
Exclude: Exclude:
- 'app/controllers/activities_controller.rb'
- 'app/mailers/notifier_mailer.rb' - 'app/mailers/notifier_mailer.rb'
- 'app/models/concerns/search_seeds.rb'
# Offense count: 12 # Offense count: 11
# This cop supports unsafe autocorrection (--autocorrect-all). # This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: AllowedMethods, AllowedPatterns. # Configuration parameters: AllowedMethods, AllowedPatterns.
# AllowedMethods: order, limit, select, lock # AllowedMethods: order, limit, select, lock
@@ -525,40 +563,41 @@ Rails/FindEach:
- 'db/migrate/20171129041341_create_photographings.rb' - 'db/migrate/20171129041341_create_photographings.rb'
- 'db/migrate/20190130090437_add_crop_to_photographings.rb' - 'db/migrate/20190130090437_add_crop_to_photographings.rb'
- 'db/migrate/20191119030244_cms_tags.rb' - 'db/migrate/20191119030244_cms_tags.rb'
- 'lib/tasks/wikidata.rake'
# Offense count: 2 # Offense count: 2
# Configuration parameters: Include.
# Include: app/models/**/*.rb
Rails/HasAndBelongsToMany: Rails/HasAndBelongsToMany:
Exclude: Exclude:
- 'app/models/member.rb' - 'app/models/member.rb'
- 'app/models/role.rb' - 'app/models/role.rb'
# Offense count: 5 # Offense count: 5
# Configuration parameters: Include.
# Include: app/models/**/*.rb
Rails/HasManyOrHasOneDependent: Rails/HasManyOrHasOneDependent:
Exclude: Exclude:
- 'app/models/member.rb' - 'app/models/member.rb'
# Offense count: 1 # Offense count: 1
# Configuration parameters: Include.
# Include: spec/**/*.rb, test/**/*.rb
Rails/I18nLocaleAssignment: Rails/I18nLocaleAssignment:
Exclude: Exclude:
- 'spec/features/locale_spec.rb' - 'spec/features/locale_spec.rb'
# Offense count: 37 # Offense count: 33
Rails/I18nLocaleTexts: Rails/I18nLocaleTexts:
Enabled: false Enabled: false
# Offense count: 3 # Offense count: 3
# Configuration parameters: Include.
# Include: app/controllers/**/*.rb, app/mailers/**/*.rb
Rails/LexicallyScopedActionFilter: Rails/LexicallyScopedActionFilter:
Exclude: Exclude:
- 'app/controllers/data_controller.rb' - 'app/controllers/data_controller.rb'
- 'app/controllers/registrations_controller.rb' - 'app/controllers/registrations_controller.rb'
# Offense count: 1
# This cop supports unsafe autocorrection (--autocorrect-all).
Rails/OrderArguments:
Exclude:
- 'app/models/crop.rb'
# Offense count: 2 # Offense count: 2
Rails/OutputSafety: Rails/OutputSafety:
Exclude: Exclude:
@@ -573,13 +612,15 @@ Rails/PluralizationGrammar:
# Offense count: 4 # Offense count: 4
# This cop supports unsafe autocorrection (--autocorrect-all). # This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: Include.
# Include: **/Rakefile, **/*.rake
Rails/RakeEnvironment: Rails/RakeEnvironment:
Exclude: Exclude:
- 'lib/tasks/hooks.rake' - 'lib/tasks/hooks.rake'
- 'lib/tasks/i18n.rake' - 'lib/tasks/i18n.rake'
- 'lib/tasks/testing.rake' - 'lib/tasks/testing.rake'
# Offense count: 8 # Offense count: 9
# This cop supports unsafe autocorrection (--autocorrect-all). # This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: AllowedReceivers. # Configuration parameters: AllowedReceivers.
# AllowedReceivers: ActionMailer::Preview, ActiveSupport::TimeZone # AllowedReceivers: ActionMailer::Preview, ActiveSupport::TimeZone
@@ -590,6 +631,7 @@ Rails/RedundantActiveRecordAllMethod:
- 'app/controllers/forums_controller.rb' - 'app/controllers/forums_controller.rb'
- 'app/controllers/plant_parts_controller.rb' - 'app/controllers/plant_parts_controller.rb'
- 'app/controllers/scientific_names_controller.rb' - 'app/controllers/scientific_names_controller.rb'
- 'app/services/openfarm_service.rb'
- 'spec/features/percy/percy_spec.rb' - 'spec/features/percy/percy_spec.rb'
- 'spec/models/harvest_spec.rb' - 'spec/models/harvest_spec.rb'
@@ -604,6 +646,8 @@ Rails/RedundantPresenceValidationOnBelongsTo:
# Offense count: 15 # Offense count: 15
# This cop supports unsafe autocorrection (--autocorrect-all). # This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: Include.
# Include: spec/controllers/**/*.rb, spec/requests/**/*.rb, test/controllers/**/*.rb, test/integration/**/*.rb
Rails/ResponseParsedBody: Rails/ResponseParsedBody:
Exclude: Exclude:
- 'spec/controllers/api/v1/plantings_controller_spec.rb' - 'spec/controllers/api/v1/plantings_controller_spec.rb'
@@ -617,31 +661,29 @@ Rails/ResponseParsedBody:
- 'spec/requests/api/v1/seeds_request_spec.rb' - 'spec/requests/api/v1/seeds_request_spec.rb'
# Offense count: 9 # Offense count: 9
# Configuration parameters: Include.
# Include: db/**/*.rb
Rails/ReversibleMigration: Rails/ReversibleMigration:
Exclude: Exclude:
- 'db/migrate/20130326092227_change_planted_at_to_date.rb' - 'db/migrate/20130326092227_change_planted_at_to_date.rb'
- 'db/migrate/20191119020643_upgrade_cms.rb' - 'db/migrate/20191119020643_upgrade_cms.rb'
# Offense count: 3 # Offense count: 2
# This cop supports unsafe autocorrection (--autocorrect-all). # This cop supports unsafe autocorrection (--autocorrect-all).
Rails/RootPathnameMethods: Rails/RootPathnameMethods:
Exclude: Exclude:
- 'app/controllers/crops_controller.rb' - 'app/controllers/crops_controller.rb'
- 'app/helpers/icons_helper.rb' - 'app/helpers/icons_helper.rb'
- 'config/application.rb'
# Offense count: 2
# Configuration parameters: ForbiddenMethods, AllowedMethods.
# ForbiddenMethods: decrement!, decrement_counter, increment!, increment_counter, insert, insert!, insert_all, insert_all!, toggle!, touch, touch_all, update_all, update_attribute, update_column, update_columns, update_counters, upsert, upsert_all
Rails/SkipsModelValidations:
Exclude:
- 'db/migrate/20240810160538_set_default_language_for_existing_alternate_names.rb'
# Offense count: 21 # Offense count: 21
# Configuration parameters: Include.
# Include: db/**/*.rb
Rails/ThreeStateBooleanColumn: Rails/ThreeStateBooleanColumn:
Enabled: false Enabled: false
# Offense count: 6 # Offense count: 6
# Configuration parameters: Include.
# Include: app/models/**/*.rb
Rails/UniqueValidationWithoutIndex: Rails/UniqueValidationWithoutIndex:
Exclude: Exclude:
- 'app/models/follow.rb' - 'app/models/follow.rb'
@@ -659,13 +701,12 @@ Rails/WhereEquals:
- 'app/models/harvest.rb' - 'app/models/harvest.rb'
- 'app/models/planting.rb' - 'app/models/planting.rb'
# Offense count: 3 # Offense count: 2
# This cop supports unsafe autocorrection (--autocorrect-all). # This cop supports unsafe autocorrection (--autocorrect-all).
Rails/WhereRange: Rails/WhereRange:
Exclude: Exclude:
- 'app/models/concerns/predict_planting.rb' - 'app/models/concerns/predict_planting.rb'
- 'app/models/garden.rb' - 'app/models/garden.rb'
- 'app/models/seed.rb'
# Offense count: 1 # Offense count: 1
Rake/MethodDefinitionInTask: Rake/MethodDefinitionInTask:
@@ -674,16 +715,22 @@ Rake/MethodDefinitionInTask:
# Offense count: 3 # Offense count: 3
# This cop supports unsafe autocorrection (--autocorrect-all). # This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: EnforcedStyle, EnforcedStyleForClasses, EnforcedStyleForModules. # Configuration parameters: EnforcedStyle.
# SupportedStyles: nested, compact # SupportedStyles: nested, compact
# SupportedStylesForClasses: ~, nested, compact
# SupportedStylesForModules: ~, nested, compact
Style/ClassAndModuleChildren: Style/ClassAndModuleChildren:
Exclude: Exclude:
- 'lib/actions/oauth_signup_action.rb' - 'lib/actions/oauth_signup_action.rb'
- 'lib/haml/filters/escaped_markdown.rb' - 'lib/haml/filters/escaped_markdown.rb'
- 'lib/haml/filters/growstuff_markdown.rb' - 'lib/haml/filters/growstuff_markdown.rb'
# Offense count: 1
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: Keywords, RequireColon.
# Keywords: TODO, FIXME, OPTIMIZE, HACK, REVIEW, NOTE
Style/CommentAnnotation:
Exclude:
- 'spec/features/seeds/adding_seeds_spec.rb'
# Offense count: 6 # Offense count: 6
# This cop supports unsafe autocorrection (--autocorrect-all). # This cop supports unsafe autocorrection (--autocorrect-all).
Style/CommentedKeyword: Style/CommentedKeyword:
@@ -693,23 +740,13 @@ Style/CommentedKeyword:
- 'spec/models/photo_spec.rb' - 'spec/models/photo_spec.rb'
- 'spec/models/planting_spec.rb' - 'spec/models/planting_spec.rb'
# Offense count: 1 # Offense count: 37
# This cop supports safe autocorrection (--autocorrect). # This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle. # Configuration parameters: AllowedVars.
# SupportedStyles: trailing_conditional, ternary Style/FetchEnvVar:
Style/EmptyStringInsideInterpolation: Enabled: false
Exclude:
- 'app/helpers/auto_suggest_helper.rb'
# Offense count: 1 # Offense count: 3
# This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: EnforcedStyle.
# SupportedStyles: left_coerce, right_coerce, single_coerce, fdiv
Style/FloatDivision:
Exclude:
- 'app/models/concerns/predict_planting.rb'
# Offense count: 11
# This cop supports unsafe autocorrection (--autocorrect-all). # This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: EnforcedStyle. # Configuration parameters: EnforcedStyle.
# SupportedStyles: always, always_true, never # SupportedStyles: always, always_true, never
@@ -717,34 +754,50 @@ Style/FrozenStringLiteralComment:
Exclude: Exclude:
- 'config/initializers/new_framework_defaults_6_0.rb' - 'config/initializers/new_framework_defaults_6_0.rb'
- 'db/migrate/20200801084007_add_foreign_key_constraint_to_active_storage_attachments_for_blob_id.active_storage.rb' - 'db/migrate/20200801084007_add_foreign_key_constraint_to_active_storage_attachments_for_blob_id.active_storage.rb'
- 'db/migrate/20240716120000_add_social_media_to_members.rb'
- 'db/migrate/20240716120001_rename_other_handle_to_other_url_in_members.rb'
- 'db/migrate/20240929041435_create_garden_collaborators.rb'
- 'db/migrate/20250810120000_make_notifications_polymorphic.rb'
- 'db/migrate/20250824081313_change_comments_polymorphic.rb'
- 'db/migrate/20250901105232_add_source_to_seeds.rb'
- 'db/migrate/20250901110545_add_indexes_crops.rb'
- 'db/migrate/20250901130830_add_overall_rating_plantings.rb'
- 'spec/lib/haml/filters/growstuff_markdown_spec.rb' - 'spec/lib/haml/filters/growstuff_markdown_spec.rb'
# Offense count: 2 # Offense count: 3
# This cop supports unsafe autocorrection (--autocorrect-all). # This cop supports unsafe autocorrection (--autocorrect-all).
Style/GlobalStdStream: Style/GlobalStdStream:
Exclude: Exclude:
- 'config/environments/production.rb' - 'config/environments/production.rb'
- 'lib/tasks/gbif.rake' - 'lib/tasks/gbif.rake'
- 'lib/tasks/openfarm.rake'
# Offense count: 1
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: MinBodyLength, AllowConsecutiveConditionals.
Style/GuardClause:
Exclude:
- 'app/controllers/activities_controller.rb'
# Offense count: 5
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle, EnforcedShorthandSyntax, UseHashRocketsWithSymbolValues, PreferHashRocketsForNonAlnumEndingSymbols.
# SupportedStyles: ruby19, hash_rockets, no_mixed_keys, ruby19_no_mixed_keys
# SupportedShorthandSyntax: always, never, either, consistent, either_consistent
Style/HashSyntax:
Exclude:
- 'app/models/csv_importer.rb'
- 'spec/requests/api/v1/gardens_request_spec.rb'
- 'spec/requests/api/v1/plantings_request_spec.rb'
# Offense count: 5
# This cop supports safe autocorrection (--autocorrect).
Style/IfUnlessModifier:
Exclude:
- 'app/controllers/activities_controller.rb'
- 'app/controllers/application_controller.rb'
- 'bin/setup'
- 'spec/features/shared_examples/crop_suggest.rb'
# Offense count: 1 # Offense count: 1
# This cop supports unsafe autocorrection (--autocorrect-all). # This cop supports unsafe autocorrection (--autocorrect-all).
Style/HashFetchChain: # Configuration parameters: AllowedMethods.
# AllowedMethods: nonzero?
Style/IfWithBooleanLiteralBranches:
Exclude: Exclude:
- 'app/models/concerns/open_farm_data.rb' - 'app/controllers/gardens_controller.rb'
# Offense count: 2
# This cop supports unsafe autocorrection (--autocorrect-all).
Style/IdenticalConditionalBranches:
Exclude:
- 'lib/actions/oauth_signup_action.rb'
# Offense count: 1 # Offense count: 1
# This cop supports unsafe autocorrection (--autocorrect-all). # This cop supports unsafe autocorrection (--autocorrect-all).
@@ -768,19 +821,16 @@ Style/MutableConstant:
# Offense count: 1 # Offense count: 1
# This cop supports safe autocorrection (--autocorrect). # This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle, MinBodyLength, AllowConsecutiveConditionals. Style/NegatedIfElseCondition:
# SupportedStyles: skip_modifier_ifs, always
Style/Next:
Exclude: Exclude:
- 'lib/tasks/wikidata.rake' - 'app/helpers/crops_helper.rb'
# Offense count: 5 # Offense count: 4
# This cop supports unsafe autocorrection (--autocorrect-all). # This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: EnforcedStyle, AllowedMethods, AllowedPatterns. # Configuration parameters: EnforcedStyle, AllowedMethods, AllowedPatterns.
# SupportedStyles: predicate, comparison # SupportedStyles: predicate, comparison
Style/NumericPredicate: Style/NumericPredicate:
Exclude: Exclude:
- 'app/helpers/crops_helper.rb'
- 'app/helpers/harvests_helper.rb' - 'app/helpers/harvests_helper.rb'
- 'app/helpers/plantings_helper.rb' - 'app/helpers/plantings_helper.rb'
- 'app/models/concerns/predict_planting.rb' - 'app/models/concerns/predict_planting.rb'
@@ -790,14 +840,22 @@ Style/OpenStructUse:
Exclude: Exclude:
- 'spec/helpers/event_helper_spec.rb' - 'spec/helpers/event_helper_spec.rb'
# Offense count: 3 # Offense count: 2
# Configuration parameters: AllowedMethods. # Configuration parameters: AllowedMethods.
# AllowedMethods: respond_to_missing? # AllowedMethods: respond_to_missing?
Style/OptionalBooleanParameter: Style/OptionalBooleanParameter:
Exclude: Exclude:
- 'app/helpers/application_helper.rb'
- 'app/models/concerns/member_newsletter.rb' - 'app/models/concerns/member_newsletter.rb'
# Offense count: 5
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle.
# SupportedStyles: same_as_string_literals, single_quotes, double_quotes
Style/QuotedSymbols:
Exclude:
- 'app/models/seed.rb'
- 'spec/controllers/crops_controller_spec.rb'
# Offense count: 1 # Offense count: 1
# This cop supports unsafe autocorrection (--autocorrect-all). # This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: Methods. # Configuration parameters: Methods.
@@ -805,6 +863,12 @@ Style/RedundantArgument:
Exclude: Exclude:
- 'app/helpers/application_helper.rb' - 'app/helpers/application_helper.rb'
# Offense count: 1
# This cop supports safe autocorrection (--autocorrect).
Style/RedundantConstantBase:
Exclude:
- 'config.ru'
# Offense count: 4 # Offense count: 4
# This cop supports unsafe autocorrection (--autocorrect-all). # This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: SafeForConstants. # Configuration parameters: SafeForConstants.
@@ -812,76 +876,36 @@ Style/RedundantFetchBlock:
Exclude: Exclude:
- 'config/puma.rb' - 'config/puma.rb'
# Offense count: 1
# This cop supports unsafe autocorrection (--autocorrect-all).
Style/RedundantInterpolation:
Exclude:
- 'app/helpers/buttons_helper.rb'
# Offense count: 3 # Offense count: 3
# This cop supports safe autocorrection (--autocorrect). # This cop supports safe autocorrection (--autocorrect).
Style/RedundantRegexpEscape: Style/RedundantRegexpArgument:
Exclude: Exclude:
- 'app/models/member.rb' - 'db/migrate/20191119030244_cms_tags.rb'
# Offense count: 2
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle, AllowInnerSlashes.
# SupportedStyles: slashes, percent_r, mixed
Style/RegexpLiteral:
Exclude:
- 'app/models/member.rb'
# Offense count: 1 # Offense count: 1
# This cop supports safe autocorrection (--autocorrect). # This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle. # Configuration parameters: AllowMultipleReturnValues.
# SupportedStyles: implicit, explicit Style/RedundantReturn:
Style/RescueStandardError:
Exclude: Exclude:
- 'lib/tasks/wikidata.rake'
# Offense count: 4
# Configuration parameters: Max.
Style/SafeNavigationChainLength:
Exclude:
- 'app/models/ability.rb'
# Offense count: 2
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: AllowModifier.
Style/SoleNestedConditional:
Exclude:
- 'app/controllers/application_controller.rb'
- 'app/controllers/messages_controller.rb' - 'app/controllers/messages_controller.rb'
# Offense count: 28 # Offense count: 24
# This cop supports unsafe autocorrection (--autocorrect-all). # This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: Mode. # Configuration parameters: Mode.
Style/StringConcatenation: Style/StringConcatenation:
Exclude: Exclude:
- 'app/controllers/messages_controller.rb' - 'app/controllers/messages_controller.rb'
- 'app/helpers/application_helper.rb'
- 'app/helpers/buttons_helper.rb' - 'app/helpers/buttons_helper.rb'
- 'app/models/photo.rb'
- 'config/initializers/rswag_api.rb' - 'config/initializers/rswag_api.rb'
- 'spec/helpers/gardens_helper_spec.rb' - 'spec/helpers/gardens_helper_spec.rb'
- 'spec/helpers/seeds_helper_spec.rb' - 'spec/helpers/seeds_helper_spec.rb'
# Offense count: 1 # Offense count: 2
# This cop supports safe autocorrection (--autocorrect). # This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle. Style/SuperArguments:
# SupportedStyles: single_quotes, double_quotes
Style/StringLiteralsInInterpolation:
Exclude: Exclude:
- 'config/initializers/mailboxer.rb' - 'app/controllers/omniauth_callbacks_controller.rb'
- 'lib/haml/filters/escaped_markdown.rb'
# Offense count: 1
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: .
# SupportedStyles: percent, brackets
Style/SymbolArray:
EnforcedStyle: percent
MinSize: 3
# Offense count: 1 # Offense count: 1
# This cop supports unsafe autocorrection (--autocorrect-all). # This cop supports unsafe autocorrection (--autocorrect-all).

View File

@@ -1 +1 @@
3.3.8 3.2.2

View File

@@ -12,7 +12,6 @@ submit the change with your pull request.
- Miles Gould / [pozorvlak](https://github.com/pozorvlak) - Miles Gould / [pozorvlak](https://github.com/pozorvlak)
- Mackenzie Morgan / [maco](https://github.com/maco) - Mackenzie Morgan / [maco](https://github.com/maco)
- Brenda Wallace / [br3nda](https://github.com/br3nda) - Brenda Wallace / [br3nda](https://github.com/br3nda)
- Daniel O'Connor / [CloCkWeRX](https://github.com/CloCkWeRX)
## Contributors ## Contributors
@@ -69,6 +68,7 @@ submit the change with your pull request.
- Jym Paul Carandang / [jacarandang](https://github.com/jacarandang) - Jym Paul Carandang / [jacarandang](https://github.com/jacarandang)
- Anthony Atkinson / [sha1sum](https://github.com/sha1sum) - Anthony Atkinson / [sha1sum](https://github.com/sha1sum)
- Terence Conquest / [twconquest](https://github.com/twconquest) - Terence Conquest / [twconquest](https://github.com/twconquest)
- Daniel O'Connor / [CloCkWeRX](https://github.com/CloCkWeRX)
- DV Dasari / [dv2](https://github.com/dv2) - DV Dasari / [dv2](https://github.com/dv2)
- Eric Tillberg / [Thrillberg](https://github.com/Thrillberg) - Eric Tillberg / [Thrillberg](https://github.com/Thrillberg)
- Lucas Nogueira / [lucasnogueira](https://github.com/lucasnogueira) - Lucas Nogueira / [lucasnogueira](https://github.com/lucasnogueira)
@@ -95,11 +95,10 @@ submit the change with your pull request.
- Ítalo Pires / [italopires](https://github.com/italopires) - Ítalo Pires / [italopires](https://github.com/italopires)
- Bennett Zink / [bennett-zink](https://github.com/bennett-zink) - Bennett Zink / [bennett-zink](https://github.com/bennett-zink)
- Dominick Thornton / [domthor](https://github.com/domthor) - Dominick Thornton / [domthor](https://github.com/domthor)
## Bots ## Bots
### Security and Dependency Updates ### Security and Dependency Updates
- `codefactor-io[bot]` - `codefactor-io[bot]`
- DeppBot / [deppbot](https://github.com/deppbot) - DeppBot / [deppbot](https://github.com/deppbot)
- `dependabot[bot]` [dependabot](https://github.com/dependabot-bot) / [dependabot-preview](https://github.com/apps/dependabot-preview) - `dependabot[bot]` [dependabot](https://github.com/dependabot-bot) / [dependabot-preview](https://github.com/apps/dependabot-preview)
- [google-labs-jules[bot]](https://github.com/apps/google-labs-jules)

16
Gemfile
View File

@@ -5,13 +5,13 @@ source 'https://rubygems.org'
# Match ruby version in .ruby-version # Match ruby version in .ruby-version
ruby File.read('.ruby-version') ruby File.read('.ruby-version')
gem 'rails', '~> 7.2.0' gem 'rails', '~> 7.1.0'
# Keeping old sprockets # Keeping old sprockets
# https://github.com/rails/sprockets-rails/issues/444#issuecomment-637817050 # https://github.com/rails/sprockets-rails/issues/444#issuecomment-637817050
gem "sprockets", "<4" gem "sprockets", "<4"
gem 'bundler', '>= 2.4.22' gem 'bundler', '>= 2.3.10'
gem 'coffee-rails' gem 'coffee-rails'
gem 'haml' gem 'haml'
@@ -91,9 +91,10 @@ gem 'bootstrap-datepicker-rails'
# DRY-er easier bootstrap 4 forms # DRY-er easier bootstrap 4 forms
gem "bootstrap_form", ">= 4.5.0" gem "bootstrap_form", ">= 4.5.0"
# For connecting to other services (eg Flickr) # For connecting to other services (eg Twitter)
gem 'omniauth', '~> 1.3' gem 'omniauth', '~> 1.3'
gem 'omniauth-flickr', '>= 0.0.15' gem 'omniauth-flickr', '>= 0.0.15'
gem 'omniauth-twitter'
# Pretty charts # Pretty charts
gem "chartkick" gem "chartkick"
@@ -174,10 +175,10 @@ group :development, :test do
gem 'rubocop-rspec_rails' gem 'rubocop-rspec_rails'
gem 'webrat' # provides HTML matchers for view tests gem 'webrat' # provides HTML matchers for view tests
gem 'crowdin-cli' # for translations
gem 'dotenv-rails' gem 'dotenv-rails'
# cli utils # cli utils
gem 'haml-i18n-extractor', require: false
gem 'haml_lint', '>= 0.25.1', require: false # Checks haml files for goodness gem 'haml_lint', '>= 0.25.1', require: false # Checks haml files for goodness
gem 'i18n-tasks', require: false # adds tests for finding missing and unused translations gem 'i18n-tasks', require: false # adds tests for finding missing and unused translations
gem 'rspectre', require: false # finds unused code in specs gem 'rspectre', require: false # finds unused code in specs
@@ -187,18 +188,15 @@ end
group :test do group :test do
gem 'axe-core-capybara' gem 'axe-core-capybara'
gem 'axe-core-rspec' gem 'axe-core-rspec'
gem 'codeclimate-test-reporter', require: false
gem 'rails-controller-testing' gem 'rails-controller-testing'
gem 'selenium-webdriver' gem 'selenium-webdriver'
gem 'timecop' gem 'timecop'
gem 'vcr' gem 'vcr'
gem "rspec-rebound"
gem "percy-capybara", "~> 5.0.0"
end end
group :travis do group :travis do
gem 'platform-api' gem 'platform-api'
end end
gem "percy-capybara", "~> 5.0.0"
gem "i18n_data", "~> 1.1"

View File

@@ -33,46 +33,51 @@ GEM
GEM GEM
remote: https://rubygems.org/ remote: https://rubygems.org/
specs: specs:
actioncable (7.2.2.2) actioncable (7.1.3.4)
actionpack (= 7.2.2.2) actionpack (= 7.1.3.4)
activesupport (= 7.2.2.2) activesupport (= 7.1.3.4)
nio4r (~> 2.0) nio4r (~> 2.0)
websocket-driver (>= 0.6.1) websocket-driver (>= 0.6.1)
zeitwerk (~> 2.6) zeitwerk (~> 2.6)
actionmailbox (7.2.2.2) actionmailbox (7.1.3.4)
actionpack (= 7.2.2.2) actionpack (= 7.1.3.4)
activejob (= 7.2.2.2) activejob (= 7.1.3.4)
activerecord (= 7.2.2.2) activerecord (= 7.1.3.4)
activestorage (= 7.2.2.2) activestorage (= 7.1.3.4)
activesupport (= 7.2.2.2) activesupport (= 7.1.3.4)
mail (>= 2.8.0) mail (>= 2.7.1)
actionmailer (7.2.2.2) net-imap
actionpack (= 7.2.2.2) net-pop
actionview (= 7.2.2.2) net-smtp
activejob (= 7.2.2.2) actionmailer (7.1.3.4)
activesupport (= 7.2.2.2) actionpack (= 7.1.3.4)
mail (>= 2.8.0) actionview (= 7.1.3.4)
activejob (= 7.1.3.4)
activesupport (= 7.1.3.4)
mail (~> 2.5, >= 2.5.4)
net-imap
net-pop
net-smtp
rails-dom-testing (~> 2.2) rails-dom-testing (~> 2.2)
actionpack (7.2.2.2) actionpack (7.1.3.4)
actionview (= 7.2.2.2) actionview (= 7.1.3.4)
activesupport (= 7.2.2.2) activesupport (= 7.1.3.4)
nokogiri (>= 1.8.5) nokogiri (>= 1.8.5)
racc racc
rack (>= 2.2.4, < 3.2) rack (>= 2.2.4)
rack-session (>= 1.0.1) rack-session (>= 1.0.1)
rack-test (>= 0.6.3) rack-test (>= 0.6.3)
rails-dom-testing (~> 2.2) rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6) rails-html-sanitizer (~> 1.6)
useragent (~> 0.16) actiontext (7.1.3.4)
actiontext (7.2.2.2) actionpack (= 7.1.3.4)
actionpack (= 7.2.2.2) activerecord (= 7.1.3.4)
activerecord (= 7.2.2.2) activestorage (= 7.1.3.4)
activestorage (= 7.2.2.2) activesupport (= 7.1.3.4)
activesupport (= 7.2.2.2)
globalid (>= 0.6.0) globalid (>= 0.6.0)
nokogiri (>= 1.8.5) nokogiri (>= 1.8.5)
actionview (7.2.2.2) actionview (7.1.3.4)
activesupport (= 7.2.2.2) activesupport (= 7.1.3.4)
builder (~> 3.1) builder (~> 3.1)
erubi (~> 1.11) erubi (~> 1.11)
rails-dom-testing (~> 2.2) rails-dom-testing (~> 2.2)
@@ -80,69 +85,64 @@ GEM
active_link_to (1.0.5) active_link_to (1.0.5)
actionpack actionpack
addressable addressable
active_median (0.6.0) active_median (0.4.1)
activesupport (>= 7.1) activesupport (>= 6.1)
active_record_union (1.3.0) active_record_union (1.3.0)
activerecord (>= 4.0) activerecord (>= 4.0)
active_utils (3.6.0) active_utils (3.4.1)
activesupport (>= 4.2) activesupport (>= 4.2)
i18n i18n
activejob (7.2.2.2) activejob (7.1.3.4)
activesupport (= 7.2.2.2) activesupport (= 7.1.3.4)
globalid (>= 0.3.6) globalid (>= 0.3.6)
activemodel (7.2.2.2) activemodel (7.1.3.4)
activesupport (= 7.2.2.2) activesupport (= 7.1.3.4)
activerecord (7.2.2.2) activerecord (7.1.3.4)
activemodel (= 7.2.2.2) activemodel (= 7.1.3.4)
activesupport (= 7.2.2.2) activesupport (= 7.1.3.4)
timeout (>= 0.4.0) timeout (>= 0.4.0)
activestorage (7.2.2.2) activestorage (7.1.3.4)
actionpack (= 7.2.2.2) actionpack (= 7.1.3.4)
activejob (= 7.2.2.2) activejob (= 7.1.3.4)
activerecord (= 7.2.2.2) activerecord (= 7.1.3.4)
activesupport (= 7.2.2.2) activesupport (= 7.1.3.4)
marcel (~> 1.0) marcel (~> 1.0)
activesupport (7.2.2.2) activesupport (7.1.3.4)
base64 base64
benchmark (>= 0.3)
bigdecimal bigdecimal
concurrent-ruby (~> 1.0, >= 1.3.1) concurrent-ruby (~> 1.0, >= 1.0.2)
connection_pool (>= 2.2.5) connection_pool (>= 2.2.5)
drb drb
i18n (>= 1.6, < 2) i18n (>= 1.6, < 2)
logger (>= 1.4.2)
minitest (>= 5.1) minitest (>= 5.1)
securerandom (>= 0.3) mutex_m
tzinfo (~> 2.0, >= 2.0.5) tzinfo (~> 2.0)
addressable (2.8.7) addressable (2.8.6)
public_suffix (>= 2.0.2, < 7.0) public_suffix (>= 2.0.2, < 6.0)
ast (2.4.3) ast (2.4.2)
autoprefixer-rails (10.4.16.0) autoprefixer-rails (10.4.16.0)
execjs (~> 2) execjs (~> 2)
axe-core-api (4.10.3) axe-core-api (4.9.1)
dumb_delegator dumb_delegator
ostruct
virtus virtus
axe-core-capybara (4.10.3) axe-core-capybara (4.9.1)
axe-core-api (= 4.10.3) axe-core-api (= 4.9.1)
dumb_delegator dumb_delegator
axe-core-rspec (4.10.3) axe-core-rspec (4.9.1)
axe-core-api (= 4.10.3) axe-core-api (= 4.9.1)
dumb_delegator dumb_delegator
ostruct
virtus virtus
axiom-types (0.1.1) axiom-types (0.1.1)
descendants_tracker (~> 0.0.4) descendants_tracker (~> 0.0.4)
ice_nine (~> 0.11.0) ice_nine (~> 0.11.0)
thread_safe (~> 0.3, >= 0.3.1) thread_safe (~> 0.3, >= 0.3.1)
base64 (0.3.0) base64 (0.2.0)
bcrypt (3.1.20) bcrypt (3.1.20)
benchmark (0.4.1)
better_errors (2.10.1) better_errors (2.10.1)
erubi (>= 1.0.0) erubi (>= 1.0.0)
rack (>= 0.9.0) rack (>= 0.9.0)
rouge (>= 1.0.0) rouge (>= 1.0.0)
bigdecimal (3.2.3) bigdecimal (3.1.8)
bluecloth (2.2.0) bluecloth (2.2.0)
bonsai-elasticsearch-rails (7.0.1) bonsai-elasticsearch-rails (7.0.1)
elasticsearch-model (< 8) elasticsearch-model (< 8)
@@ -156,10 +156,10 @@ GEM
actionpack (>= 6.1) actionpack (>= 6.1)
activemodel (>= 6.1) activemodel (>= 6.1)
builder (3.3.0) builder (3.3.0)
bullet (8.0.8) bullet (7.1.6)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
uniform_notifier (~> 1.11) uniform_notifier (~> 1.11)
byebug (12.0.0) byebug (11.1.3)
cancancan (3.6.1) cancancan (3.6.1)
capybara (3.40.0) capybara (3.40.0)
addressable addressable
@@ -183,8 +183,10 @@ GEM
image_processing (~> 1.1) image_processing (~> 1.1)
marcel (~> 1.0.0) marcel (~> 1.0.0)
ssrf_filter (~> 1.0) ssrf_filter (~> 1.0)
chartkick (5.2.0) chartkick (5.0.7)
childprocess (5.0.0) childprocess (5.0.0)
codeclimate-test-reporter (1.0.9)
simplecov (<= 0.13)
coderay (1.1.3) coderay (1.1.3)
coercible (1.0.0) coercible (1.0.0)
descendants_tracker (~> 0.0.1) descendants_tracker (~> 0.0.1)
@@ -197,29 +199,20 @@ GEM
coffee-script-source (1.12.2) coffee-script-source (1.12.2)
comfy_bootstrap_form (4.0.9) comfy_bootstrap_form (4.0.9)
rails (>= 5.0.0) rails (>= 5.0.0)
concurrent-ruby (1.3.5) concurrent-ruby (1.3.3)
connection_pool (2.5.4) connection_pool (2.4.1)
crass (1.0.6) crass (1.0.6)
crowdin-api (1.12.0) csv (3.3.0)
open-uri (>= 0.1.0, < 0.2.0) csv_shaper (1.3.2)
rest-client (>= 2.0.0, < 2.2.0)
crowdin-cli (0.2.2)
crowdin-api (>= 0.2.0)
gli (>= 2.7.0)
i18n (>= 0.6.4)
rubyzip (>= 1.0.0)
csv (3.3.1)
csv_shaper (1.4.0)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
csv
dalli (3.2.8) dalli (3.2.8)
database_cleaner (2.1.0) database_cleaner (2.0.2)
database_cleaner-active_record (>= 2, < 3) database_cleaner-active_record (>= 2, < 3)
database_cleaner-active_record (2.2.0) database_cleaner-active_record (2.1.0)
activerecord (>= 5.a) activerecord (>= 5.a)
database_cleaner-core (~> 2.0.0) database_cleaner-core (~> 2.0.0)
database_cleaner-core (2.0.1) database_cleaner-core (2.0.1)
date (3.4.1) date (3.3.4)
descendants_tracker (0.0.4) descendants_tracker (0.0.4)
thread_safe (~> 0.3, >= 0.3.1) thread_safe (~> 0.3, >= 0.3.1)
devise (4.9.4) devise (4.9.4)
@@ -228,16 +221,16 @@ GEM
railties (>= 4.1.0) railties (>= 4.1.0)
responders responders
warden (~> 1.2.3) warden (~> 1.2.3)
diff-lcs (1.6.2) diff-lcs (1.5.1)
discard (1.4.0) discard (1.3.0)
activerecord (>= 4.2, < 9.0) activerecord (>= 4.2, < 8)
domain_name (0.6.20240107) docile (1.1.5)
dotenv (3.1.8) dotenv (3.1.2)
dotenv-rails (3.1.8) dotenv-rails (3.1.2)
dotenv (= 3.1.8) dotenv (= 3.1.2)
railties (>= 6.1) railties (>= 6.1)
drb (2.2.3) drb (2.2.1)
dumb_delegator (1.1.0) dumb_delegator (1.0.0)
elasticsearch (7.0.0) elasticsearch (7.0.0)
elasticsearch-api (= 7.0.0) elasticsearch-api (= 7.0.0)
elasticsearch-transport (= 7.0.0) elasticsearch-transport (= 7.0.0)
@@ -251,25 +244,22 @@ GEM
elasticsearch-transport (7.0.0) elasticsearch-transport (7.0.0)
faraday faraday
multi_json multi_json
erb (5.0.2) erubi (1.13.0)
erubi (1.13.1)
erubis (2.7.0) erubis (2.7.0)
excon (1.2.5) excon (0.110.0)
logger execjs (2.9.1)
execjs (2.10.0) factory_bot (6.4.5)
factory_bot (6.5.5) activesupport (>= 5.0.0)
activesupport (>= 6.1.0) factory_bot_rails (6.4.3)
factory_bot_rails (6.5.1) factory_bot (~> 6.4)
factory_bot (~> 6.5) railties (>= 5.0.0)
railties (>= 6.1.0) faker (3.4.1)
faker (3.5.2)
i18n (>= 1.8.11, < 2) i18n (>= 1.8.11, < 2)
faraday (2.13.4) faraday (2.10.0)
faraday-net_http (>= 2.0, < 3.5) faraday-net_http (>= 2.0, < 3.2)
json
logger logger
faraday-net_http (3.4.1) faraday-net_http (3.1.0)
net-http (>= 0.5.0) net-http
ffi (1.16.3) ffi (1.16.3)
flickraw (0.9.10) flickraw (0.9.10)
font-awesome-sass (5.15.1) font-awesome-sass (5.15.1)
@@ -277,14 +267,12 @@ GEM
friendly_id (5.5.1) friendly_id (5.5.1)
activerecord (>= 4.0.0) activerecord (>= 4.0.0)
gbifrb (0.2.0) gbifrb (0.2.0)
geocoder (1.8.5) geocoder (1.8.3)
base64 (>= 0.1.0) base64 (>= 0.1.0)
csv (>= 3.0.0) csv (>= 3.0.0)
gibbon (1.2.1) gibbon (1.2.1)
httparty httparty
multi_json (>= 1.9.0) multi_json (>= 1.9.0)
gli (2.22.2)
ostruct
globalid (1.2.1) globalid (1.2.1)
activesupport (>= 6.1) activesupport (>= 6.1)
gravatar-ultimate (2.0.0) gravatar-ultimate (2.0.0)
@@ -294,37 +282,37 @@ GEM
temple (>= 0.8.2) temple (>= 0.8.2)
thor thor
tilt tilt
haml-i18n-extractor (0.5.9)
activesupport
haml
highline
tilt
trollop (= 1.16.2)
haml-rails (2.1.0) haml-rails (2.1.0)
actionpack (>= 5.1) actionpack (>= 5.1)
activesupport (>= 5.1) activesupport (>= 5.1)
haml (>= 4.0.6) haml (>= 4.0.6)
railties (>= 5.1) railties (>= 5.1)
haml_lint (0.66.0) haml_lint (0.58.0)
haml (>= 5.0) haml (>= 5.0)
parallel (~> 1.10) parallel (~> 1.10)
rainbow rainbow
rubocop (>= 1.0) rubocop (>= 1.0)
sysexits (~> 1.1) sysexits (~> 1.1)
hashie (5.0.0) hashie (5.0.0)
heroics (0.1.3) heroics (0.1.2)
base64
erubis (~> 2.0) erubis (~> 2.0)
excon excon
moneta moneta
multi_json (>= 1.9.2) multi_json (>= 1.9.2)
webrick webrick
highline (3.1.2) highline (3.0.1)
reline httparty (0.21.0)
http-accept (1.7.0)
http-cookie (1.0.8)
domain_name (~> 0.5)
httparty (0.22.0)
csv
mini_mime (>= 1.0.0) mini_mime (>= 1.0.0)
multi_xml (>= 0.5.2) multi_xml (>= 0.5.2)
i18n (1.14.7) i18n (1.14.5)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
i18n-tasks (1.0.15) i18n-tasks (1.0.14)
activesupport (>= 4.0.2) activesupport (>= 4.0.2)
ast (>= 2.1.0) ast (>= 2.1.0)
erubi erubi
@@ -333,32 +321,25 @@ GEM
parser (>= 3.2.2.1) parser (>= 3.2.2.1)
rails-i18n rails-i18n
rainbow (>= 2.2.2, < 4.0) rainbow (>= 2.2.2, < 4.0)
ruby-progressbar (~> 1.8, >= 1.8.1)
terminal-table (>= 1.5.1) terminal-table (>= 1.5.1)
i18n_data (1.1.0) icalendar (2.10.1)
simple_po_parser (~> 1.1)
icalendar (2.11.2)
base64
ice_cube (~> 0.16) ice_cube (~> 0.16)
logger ice_cube (0.16.4)
ostruct
ice_cube (0.17.0)
ice_nine (0.11.2) ice_nine (0.11.2)
image_processing (1.12.2) image_processing (1.12.2)
mini_magick (>= 4.9.5, < 5) mini_magick (>= 4.9.5, < 5)
ruby-vips (>= 2.0.17, < 3) ruby-vips (>= 2.0.17, < 3)
io-console (0.8.1) io-console (0.7.2)
irb (1.15.2) irb (1.13.2)
pp (>= 0.6.0)
rdoc (>= 4.0.0) rdoc (>= 4.0.0)
reline (>= 0.4.2) reline (>= 0.4.2)
jquery-rails (4.6.0) jquery-rails (4.6.0)
rails-dom-testing (>= 1, < 3) rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0) railties (>= 4.2.0)
thor (>= 0.14, < 2.0) thor (>= 0.14, < 2.0)
json (2.13.2) json (2.7.2)
json-schema (5.1.0) json-schema (4.1.1)
addressable (~> 2.8) addressable (>= 2.8)
jsonapi-resources (0.10.7) jsonapi-resources (0.10.7)
activerecord (>= 4.1) activerecord (>= 4.1)
concurrent-ruby concurrent-ruby
@@ -367,21 +348,20 @@ GEM
kgio (2.11.4) kgio (2.11.4)
kramdown (2.4.0) kramdown (2.4.0)
rexml rexml
language_server-protocol (3.17.0.5) language_server-protocol (3.17.0.3)
launchy (3.0.1) launchy (3.0.0)
addressable (~> 2.8) addressable (~> 2.8)
childprocess (~> 5.0) childprocess (~> 5.0)
leaflet-rails (1.9.5) leaflet-rails (1.9.4)
actionpack (>= 4.2.0) actionpack (>= 4.2.0)
railties (>= 4.2.0) railties (>= 4.2.0)
letter_opener (1.10.0) letter_opener (1.10.0)
launchy (>= 2.2, < 4) launchy (>= 2.2, < 4)
lint_roller (1.1.0)
listen (3.9.0) listen (3.9.0)
rb-fsevent (~> 0.10, >= 0.10.3) rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10) rb-inotify (~> 0.9, >= 0.9.10)
logger (1.7.0) logger (1.6.0)
loofah (2.24.1) loofah (2.22.0)
crass (~> 1.0.2) crass (~> 1.0.2)
nokogiri (>= 1.12.0) nokogiri (>= 1.12.0)
mail (2.8.1) mail (2.8.1)
@@ -400,45 +380,39 @@ GEM
railties (>= 3.2) railties (>= 3.2)
matrix (0.4.2) matrix (0.4.2)
memcachier (0.0.2) memcachier (0.0.2)
method_source (1.1.0) method_source (1.0.0)
mime-types (3.7.0)
logger
mime-types-data (~> 3.2025, >= 3.2025.0507)
mime-types-data (3.2025.0805)
mimemagic (0.4.3) mimemagic (0.4.3)
nokogiri (~> 1) nokogiri (~> 1)
rake rake
mini_magick (4.12.0) mini_magick (4.12.0)
mini_mime (1.1.5) mini_mime (1.1.5)
mini_portile2 (2.8.9) mini_portile2 (2.8.7)
minitest (5.25.5) minitest (5.24.1)
moneta (1.0.0) moneta (1.0.0)
msgpack (1.8.0) msgpack (1.7.2)
multi_json (1.15.0) multi_json (1.15.0)
multi_xml (0.7.1) multi_xml (0.6.0)
bigdecimal (~> 3.1) mutex_m (0.2.0)
net-http (0.6.0) net-http (0.4.1)
uri uri
net-imap (0.5.9) net-imap (0.4.11)
date date
net-protocol net-protocol
net-pop (0.1.2) net-pop (0.1.2)
net-protocol net-protocol
net-protocol (0.2.2) net-protocol (0.2.2)
timeout timeout
net-smtp (0.5.1) net-smtp (0.5.0)
net-protocol net-protocol
netrc (0.11.0) nio4r (2.7.3)
nio4r (2.7.4) nokogiri (1.16.6)
nokogiri (1.18.9)
mini_portile2 (~> 2.8.2) mini_portile2 (~> 2.8.2)
racc (~> 1.4) racc (~> 1.4)
nokogiri (1.18.9-x86_64-linux-gnu) nokogiri (1.16.6-x86_64-linux)
racc (~> 1.4) racc (~> 1.4)
oauth (0.5.6) oauth (0.5.6)
oj (3.16.11) oj (3.16.4)
bigdecimal (>= 3.0) bigdecimal (>= 3.0)
ostruct (>= 0.2)
omniauth (1.9.2) omniauth (1.9.2)
hashie (>= 3.4.6) hashie (>= 3.4.6)
rack (>= 1.6.2, < 3) rack (>= 1.6.2, < 3)
@@ -448,38 +422,33 @@ GEM
omniauth-oauth (1.1.0) omniauth-oauth (1.1.0)
oauth oauth
omniauth (~> 1.0) omniauth (~> 1.0)
open-uri (0.1.0) omniauth-twitter (1.4.0)
omniauth-oauth (~> 1.1)
rack
orm_adapter (0.5.0) orm_adapter (0.5.0)
ostruct (0.6.3) parallel (1.25.1)
parallel (1.27.0) parser (3.3.4.0)
parser (3.3.9.0)
ast (~> 2.4.1) ast (~> 2.4.1)
racc racc
percy-capybara (5.0.0) percy-capybara (5.0.0)
capybara (>= 3) capybara (>= 3)
pg (1.6.2) pg (1.5.6)
pg (1.6.2-x86_64-linux) platform-api (3.7.0)
platform-api (3.8.0)
heroics (~> 0.1.1) heroics (~> 0.1.1)
moneta (~> 1.0.0) moneta (~> 1.0.0)
rate_throttle_client (~> 0.1.0) rate_throttle_client (~> 0.1.0)
popper_js (2.11.8) popper_js (2.11.8)
pp (0.6.2) pry (0.14.2)
prettyprint
prettyprint (0.2.0)
prism (1.4.0)
pry (0.15.2)
coderay (~> 1.1) coderay (~> 1.1)
method_source (~> 1.0) method_source (~> 1.0)
psych (5.2.6) psych (5.1.2)
date
stringio stringio
public_suffix (6.0.1) public_suffix (5.0.5)
puma (7.0.3) puma (6.4.2)
nio4r (~> 2.0) nio4r (~> 2.0)
query_diet (0.7.2) query_diet (0.7.1)
racc (1.8.1) racc (1.8.0)
rack (2.2.17) rack (2.2.9)
rack-cors (2.0.2) rack-cors (2.0.2)
rack (>= 2.0.0) rack (>= 2.0.0)
rack-protection (3.2.0) rack-protection (3.2.0)
@@ -487,37 +456,37 @@ GEM
rack (~> 2.2, >= 2.2.4) rack (~> 2.2, >= 2.2.4)
rack-session (1.0.2) rack-session (1.0.2)
rack (< 3) rack (< 3)
rack-test (2.2.0) rack-test (2.1.0)
rack (>= 1.3) rack (>= 1.3)
rackup (1.0.1) rackup (1.0.0)
rack (< 3) rack (< 3)
webrick webrick
rails (7.2.2.2) rails (7.1.3.4)
actioncable (= 7.2.2.2) actioncable (= 7.1.3.4)
actionmailbox (= 7.2.2.2) actionmailbox (= 7.1.3.4)
actionmailer (= 7.2.2.2) actionmailer (= 7.1.3.4)
actionpack (= 7.2.2.2) actionpack (= 7.1.3.4)
actiontext (= 7.2.2.2) actiontext (= 7.1.3.4)
actionview (= 7.2.2.2) actionview (= 7.1.3.4)
activejob (= 7.2.2.2) activejob (= 7.1.3.4)
activemodel (= 7.2.2.2) activemodel (= 7.1.3.4)
activerecord (= 7.2.2.2) activerecord (= 7.1.3.4)
activestorage (= 7.2.2.2) activestorage (= 7.1.3.4)
activesupport (= 7.2.2.2) activesupport (= 7.1.3.4)
bundler (>= 1.15.0) bundler (>= 1.15.0)
railties (= 7.2.2.2) railties (= 7.1.3.4)
rails-controller-testing (1.0.5) rails-controller-testing (1.0.5)
actionpack (>= 5.0.1.rc1) actionpack (>= 5.0.1.rc1)
actionview (>= 5.0.1.rc1) actionview (>= 5.0.1.rc1)
activesupport (>= 5.0.1.rc1) activesupport (>= 5.0.1.rc1)
rails-dom-testing (2.3.0) rails-dom-testing (2.2.0)
activesupport (>= 5.0.0) activesupport (>= 5.0.0)
minitest minitest
nokogiri (>= 1.6) nokogiri (>= 1.6)
rails-html-sanitizer (1.6.2) rails-html-sanitizer (1.6.0)
loofah (~> 2.21) loofah (~> 2.21)
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) nokogiri (~> 1.14)
rails-i18n (7.0.10) rails-i18n (7.0.9)
i18n (>= 0.7, < 2) i18n (>= 0.7, < 2)
railties (>= 6.0.0, < 8) railties (>= 6.0.0, < 8)
rails_12factor (0.0.3) rails_12factor (0.0.3)
@@ -525,123 +494,108 @@ GEM
rails_stdout_logging rails_stdout_logging
rails_serve_static_assets (0.0.5) rails_serve_static_assets (0.0.5)
rails_stdout_logging (0.0.5) rails_stdout_logging (0.0.5)
railties (7.2.2.2) railties (7.1.3.4)
actionpack (= 7.2.2.2) actionpack (= 7.1.3.4)
activesupport (= 7.2.2.2) activesupport (= 7.1.3.4)
irb (~> 1.13) irb
rackup (>= 1.0.0) rackup (>= 1.0.0)
rake (>= 12.2) rake (>= 12.2)
thor (~> 1.0, >= 1.2.2) thor (~> 1.0, >= 1.2.2)
zeitwerk (~> 2.6) zeitwerk (~> 2.6)
rainbow (3.1.1) rainbow (3.1.1)
raindrops (0.20.1) raindrops (0.20.0)
rake (13.3.0) rake (13.2.1)
rate_throttle_client (0.1.2) rate_throttle_client (0.1.2)
rb-fsevent (0.11.2) rb-fsevent (0.11.2)
rb-inotify (0.10.1) rb-inotify (0.10.1)
ffi (~> 1.0) ffi (~> 1.0)
rdoc (6.14.2) rdoc (6.7.0)
erb
psych (>= 4.0.0) psych (>= 4.0.0)
recaptcha (5.21.1) recaptcha (5.17.0)
redis-client (0.23.2) redis-client (0.22.2)
connection_pool connection_pool
regexp_parser (2.11.2) regexp_parser (2.9.2)
reline (0.6.2) reline (0.5.9)
io-console (~> 0.5) io-console (~> 0.5)
responders (3.1.1) responders (3.1.1)
actionpack (>= 5.2) actionpack (>= 5.2)
railties (>= 5.2) railties (>= 5.2)
rest-client (2.1.0) rexml (3.3.1)
http-accept (>= 1.7.0, < 2.0) strscan
http-cookie (>= 1.0.2, < 2.0)
mime-types (>= 1.16, < 4.0)
netrc (~> 0.8)
rexml (3.4.2)
rouge (4.1.2) rouge (4.1.2)
rspec (3.13.0) rspec (3.13.0)
rspec-core (~> 3.13.0) rspec-core (~> 3.13.0)
rspec-expectations (~> 3.13.0) rspec-expectations (~> 3.13.0)
rspec-mocks (~> 3.13.0) rspec-mocks (~> 3.13.0)
rspec-activemodel-mocks (1.3.0) rspec-activemodel-mocks (1.2.0)
activemodel (>= 3.0) activemodel (>= 3.0)
activesupport (>= 3.0) activesupport (>= 3.0)
rspec-mocks (>= 2.99, < 4.0) rspec-mocks (>= 2.99, < 4.0)
rspec-core (3.13.5) rspec-core (3.13.0)
rspec-support (~> 3.13.0) rspec-support (~> 3.13.0)
rspec-expectations (3.13.5) rspec-expectations (3.13.1)
diff-lcs (>= 1.2.0, < 2.0) diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0) rspec-support (~> 3.13.0)
rspec-mocks (3.13.5) rspec-mocks (3.13.1)
diff-lcs (>= 1.2.0, < 2.0) diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0) rspec-support (~> 3.13.0)
rspec-rails (8.0.2) rspec-rails (6.1.3)
actionpack (>= 7.2) actionpack (>= 6.1)
activesupport (>= 7.2) activesupport (>= 6.1)
railties (>= 7.2) railties (>= 6.1)
rspec-core (~> 3.13) rspec-core (~> 3.13)
rspec-expectations (~> 3.13) rspec-expectations (~> 3.13)
rspec-mocks (~> 3.13) rspec-mocks (~> 3.13)
rspec-support (~> 3.13) rspec-support (~> 3.13)
rspec-rebound (0.2.1) rspec-support (3.13.1)
rspec-core (~> 3.3) rspectre (0.1.0)
rspec-support (3.13.4) parser (>= 3.2.2.1)
rspectre (0.2.0) rspec (~> 3.9)
parser (>= 3.3.7.1) rswag-api (2.13.0)
prism (~> 1.3) activesupport (>= 3.1, < 7.2)
rspec (~> 3.10) railties (>= 3.1, < 7.2)
rswag-api (2.16.0) rswag-specs (2.13.0)
activesupport (>= 5.2, < 8.1) activesupport (>= 3.1, < 7.2)
railties (>= 5.2, < 8.1) json-schema (>= 2.2, < 5.0)
rswag-specs (2.16.0) railties (>= 3.1, < 7.2)
activesupport (>= 5.2, < 8.1)
json-schema (>= 2.2, < 6.0)
railties (>= 5.2, < 8.1)
rspec-core (>= 2.14) rspec-core (>= 2.14)
rswag-ui (2.16.0) rswag-ui (2.13.0)
actionpack (>= 5.2, < 8.1) actionpack (>= 3.1, < 7.2)
railties (>= 5.2, < 8.1) railties (>= 3.1, < 7.2)
rubocop (1.80.2) rubocop (1.65.0)
json (~> 2.3) json (~> 2.3)
language_server-protocol (~> 3.17.0.2) language_server-protocol (>= 3.17.0)
lint_roller (~> 1.1.0)
parallel (~> 1.10) parallel (~> 1.10)
parser (>= 3.3.0.2) parser (>= 3.3.0.2)
rainbow (>= 2.2.2, < 4.0) rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 2.9.3, < 3.0) regexp_parser (>= 2.4, < 3.0)
rubocop-ast (>= 1.46.0, < 2.0) rexml (>= 3.2.5, < 4.0)
rubocop-ast (>= 1.31.1, < 2.0)
ruby-progressbar (~> 1.7) ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 4.0) unicode-display_width (>= 2.4.0, < 3.0)
rubocop-ast (1.46.0) rubocop-ast (1.31.3)
parser (>= 3.3.7.2) parser (>= 3.3.1.0)
prism (~> 1.4) rubocop-capybara (2.21.0)
rubocop-capybara (2.22.1) rubocop (~> 1.41)
lint_roller (~> 1.1) rubocop-factory_bot (2.26.1)
rubocop (~> 1.72, >= 1.72.1) rubocop (~> 1.61)
rubocop-factory_bot (2.27.1) rubocop-rails (2.25.1)
lint_roller (~> 1.1)
rubocop (~> 1.72, >= 1.72.1)
rubocop-rails (2.33.3)
activesupport (>= 4.2.0) activesupport (>= 4.2.0)
lint_roller (~> 1.1)
rack (>= 1.1) rack (>= 1.1)
rubocop (>= 1.75.0, < 2.0) rubocop (>= 1.33.0, < 2.0)
rubocop-ast (>= 1.44.0, < 2.0) rubocop-ast (>= 1.31.1, < 2.0)
rubocop-rake (0.7.1) rubocop-rake (0.6.0)
lint_roller (~> 1.1) rubocop (~> 1.0)
rubocop (>= 1.72.1) rubocop-rspec (3.0.2)
rubocop-rspec (3.7.0) rubocop (~> 1.61)
lint_roller (~> 1.1) rubocop-rspec_rails (2.30.0)
rubocop (~> 1.72, >= 1.72.1) rubocop (~> 1.61)
rubocop-rspec_rails (2.31.0) rubocop-rspec (~> 3, >= 3.0.1)
lint_roller (~> 1.1)
rubocop (~> 1.72, >= 1.72.1)
rubocop-rspec (~> 3.5)
ruby-progressbar (1.13.0) ruby-progressbar (1.13.0)
ruby-units (4.1.0) ruby-units (4.0.3)
ruby-vips (2.2.1) ruby-vips (2.2.1)
ffi (~> 1.12) ffi (~> 1.12)
rubyzip (3.0.1) rubyzip (2.3.2)
sass (3.7.4) sass (3.7.4)
sass-listen (~> 4.0.0) sass-listen (~> 4.0.0)
sass-listen (4.0.0) sass-listen (4.0.0)
@@ -655,26 +609,29 @@ GEM
sprockets (> 3.0) sprockets (> 3.0)
sprockets-rails sprockets-rails
tilt tilt
scout_apm (5.7.1) scout_apm (5.3.8)
parser parser
searchkick (5.3.1) searchkick (5.3.1)
activemodel (>= 6.1) activemodel (>= 6.1)
hashie hashie
securerandom (0.4.1) selenium-webdriver (4.22.0)
selenium-webdriver (4.35.0)
base64 (~> 0.2) base64 (~> 0.2)
logger (~> 1.4) logger (~> 1.4)
rexml (~> 3.2, >= 3.2.5) rexml (~> 3.2, >= 3.2.5)
rubyzip (>= 1.2.2, < 4.0) rubyzip (>= 1.2.2, < 3.0)
websocket (~> 1.0) websocket (~> 1.0)
sidekiq (7.3.9) sidekiq (7.3.0)
base64 concurrent-ruby (< 2)
connection_pool (>= 2.3.0) connection_pool (>= 2.3.0)
logger logger
rack (>= 2.2.4) rack (>= 2.2.4)
redis-client (>= 0.22.2) redis-client (>= 0.22.2)
simple_po_parser (1.1.6) simplecov (0.13.0)
sprockets (3.7.5) docile (~> 1.1.0)
json (>= 1.8, < 3)
simplecov-html (~> 0.10.0)
simplecov-html (0.10.2)
sprockets (3.7.3)
base64 base64
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
rack (> 1, < 3) rack (> 1, < 3)
@@ -683,34 +640,32 @@ GEM
activesupport (>= 5.2) activesupport (>= 5.2)
sprockets (>= 3.0.0) sprockets (>= 3.0.0)
ssrf_filter (1.1.2) ssrf_filter (1.1.2)
stringio (3.1.7) stringio (3.1.1)
strscan (3.1.0)
sysexits (1.2.0) sysexits (1.2.0)
temple (0.10.4) temple (0.10.3)
terminal-table (4.0.0) terminal-table (3.0.2)
unicode-display_width (>= 1.1.1, < 4) unicode-display_width (>= 1.1.1, < 3)
terser (1.2.6) terser (1.2.3)
execjs (>= 0.3.0, < 3) execjs (>= 0.3.0, < 3)
thor (1.4.0) thor (1.3.1)
thread_safe (0.3.6) thread_safe (0.3.6)
tilt (2.6.1) tilt (2.3.0)
timecop (0.9.10) timecop (0.9.10)
timeout (0.4.3) timeout (0.4.1)
trollop (1.16.2)
tzinfo (2.0.6) tzinfo (2.0.6)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
unicode-display_width (3.1.5) unicode-display_width (2.5.0)
unicode-emoji (~> 4.0, >= 4.0.4)
unicode-emoji (4.0.4)
unicorn (6.1.0) unicorn (6.1.0)
kgio (~> 2.6) kgio (~> 2.6)
raindrops (~> 0.7) raindrops (~> 0.7)
uniform_notifier (1.17.0) uniform_notifier (1.16.0)
uri (1.0.3) uri (0.13.0)
useragent (0.16.11)
validate_url (1.0.15) validate_url (1.0.15)
activemodel (>= 3.0.0) activemodel (>= 3.0.0)
public_suffix public_suffix
vcr (6.3.1) vcr (6.2.0)
base64
virtus (2.0.0) virtus (2.0.0)
axiom-types (~> 0.1) axiom-types (~> 0.1)
coercible (~> 1.0) coercible (~> 1.0)
@@ -721,10 +676,9 @@ GEM
nokogiri (>= 1.2.0) nokogiri (>= 1.2.0)
rack (>= 1.0) rack (>= 1.0)
rack-test (>= 0.5.3) rack-test (>= 0.5.3)
webrick (1.9.1) webrick (1.8.1)
websocket (1.2.11) websocket (1.2.10)
websocket-driver (0.8.0) websocket-driver (0.7.6)
base64
websocket-extensions (>= 0.1.0) websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5) websocket-extensions (0.1.5)
will_paginate (4.0.1) will_paginate (4.0.1)
@@ -734,7 +688,7 @@ GEM
webrick webrick
xpath (3.2.0) xpath (3.2.0)
nokogiri (~> 1.8) nokogiri (~> 1.8)
zeitwerk (2.7.3) zeitwerk (2.6.16)
PLATFORMS PLATFORMS
ruby ruby
@@ -753,16 +707,16 @@ DEPENDENCIES
bootstrap-datepicker-rails bootstrap-datepicker-rails
bootstrap_form (>= 4.5.0) bootstrap_form (>= 4.5.0)
bullet bullet
bundler (>= 2.4.22) bundler (>= 2.3.10)
byebug byebug
cancancan cancancan
capybara capybara
capybara-email capybara-email
capybara-screenshot capybara-screenshot
chartkick chartkick
codeclimate-test-reporter
coffee-rails coffee-rails
comfortable_mexican_sofa! comfortable_mexican_sofa!
crowdin-cli
csv_shaper csv_shaper
dalli dalli
database_cleaner database_cleaner
@@ -781,11 +735,11 @@ DEPENDENCIES
gibbon (~> 1.2.0) gibbon (~> 1.2.0)
gravatar-ultimate gravatar-ultimate
haml haml
haml-i18n-extractor
haml-rails haml-rails
haml_lint (>= 0.25.1) haml_lint (>= 0.25.1)
hashie (>= 3.5.3) hashie (>= 3.5.3)
i18n-tasks i18n-tasks
i18n_data (~> 1.1)
icalendar icalendar
jquery-rails jquery-rails
jquery-ui-rails! jquery-ui-rails!
@@ -803,6 +757,7 @@ DEPENDENCIES
oj oj
omniauth (~> 1.3) omniauth (~> 1.3)
omniauth-flickr (>= 0.0.15) omniauth-flickr (>= 0.0.15)
omniauth-twitter
percy-capybara (~> 5.0.0) percy-capybara (~> 5.0.0)
pg pg
platform-api platform-api
@@ -811,7 +766,7 @@ DEPENDENCIES
query_diet query_diet
rack-cors rack-cors
rack-protection (>= 2.0.1) rack-protection (>= 2.0.1)
rails (~> 7.2.0) rails (~> 7.1.0)
rails-assets-leaflet.markercluster! rails-assets-leaflet.markercluster!
rails-controller-testing rails-controller-testing
rails_12factor rails_12factor
@@ -820,7 +775,6 @@ DEPENDENCIES
responders responders
rspec-activemodel-mocks rspec-activemodel-mocks
rspec-rails rspec-rails
rspec-rebound
rspectre rspectre
rswag-api rswag-api
rswag-specs rswag-specs
@@ -850,7 +804,7 @@ DEPENDENCIES
xmlrpc xmlrpc
RUBY VERSION RUBY VERSION
ruby 3.3.8p144 ruby 3.2.2p53
BUNDLED WITH BUNDLED WITH
2.4.22 2.4.22

View File

@@ -1,6 +1,7 @@
# 🌱 Growstuff # 🌱 Growstuff
![Build status](https://github.com/Growstuff/growstuff/workflows/CI/badge.svg) ![Build status](https://github.com/Growstuff/growstuff/workflows/CI/badge.svg)
[![Code Climate](https://codeclimate.com/github/Growstuff/growstuff/badges/gpa.svg)](https://codeclimate.com/github/Growstuff/growstuff)
Welcome to the Growstuff project. Welcome to the Growstuff project.
@@ -17,9 +18,7 @@ encourage participation from people of all backgrounds and skill levels.
## Want to contribute? ## Want to contribute?
Don't ask to ask, the best way to get started is to fork the project, start a codespace and get hacking. Don't ask to ask, the best way to get started is to fork the project, start a codespace and get hacking.
Dive on in and submit your PRs! Dive on in and submit your PRs.
Vibe Coding is more than okay, just make sure you indicate if you have done so and ensure there are tests.
## Important links ## Important links
@@ -37,10 +36,6 @@ frontend features. We welcome contributions -- see
* To set up your development environment, see [Getting started](https://github.com/Growstuff/growstuff/wiki/New-contributor-guide). * To set up your development environment, see [Getting started](https://github.com/Growstuff/growstuff/wiki/New-contributor-guide).
* You may also be interested in our [API](https://github.com/Growstuff/growstuff/wiki/API). * You may also be interested in our [API](https://github.com/Growstuff/growstuff/wiki/API).
### For Home Automation enthusiasts
https://github.com/Growstuff/homeassistant-growstuff/
## For designers, writers, researchers, data wranglers, and other contributors ## For designers, writers, researchers, data wranglers, and other contributors
There are heaps of ways to get involved and contribute no matter what There are heaps of ways to get involved and contribute no matter what
@@ -68,3 +63,5 @@ For more information about this project, contact [info@growstuff.org](mailto:inf
Security Issues: If you find an authorization bypass or data breach, please contact our maintainers directly at [maintainers@growstuff.org](mailto:maintainers@growstuff.org). Security Issues: If you find an authorization bypass or data breach, please contact our maintainers directly at [maintainers@growstuff.org](mailto:maintainers@growstuff.org).
You can also contact us on [Twitter](http://twitter.com/growstufforg/) or
[Facebook](https://www.facebook.com/pages/Growstuff/1531133417099494) or [Github](https://github.com/Growstuff/growstuff/issues)..

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -1,19 +1,11 @@
$(document).ready(function() { $(document).ready(function() {
$('.like-btn').show(); $('.like-btn').show();
/** $('.post-like').on('ajax:success', function(event, data) {
* Handles the result of an ajax call and updates UI var likeButton = $('#post-' + data.id + ' .post-like');
* var likeBadge = $('#post-'+ data.id + ' .like-badge');
* @param {object} data JSON data from ajax response
* @param {string} type object type (ie: post, activity, etc)
*/
var likeableSuccess = function(data, type) {
var target = '.' + type + '-' + data.id;
var objectClass = type.charAt(0).toUpperCase() + type.slice(1);
var likeButton = $(target + ' .' + type + '-like');
var likeBadge = $(target + ' .like-badge');
$(target + ' .like-count').text(data.like_count); $('#post-' + data.id + ' .like-count').text(data.like_count);
if (data.liked_by_member) { if (data.liked_by_member) {
likeBadge.addClass('liked'); likeBadge.addClass('liked');
likeButton.data('method', 'delete'); likeButton.data('method', 'delete');
@@ -22,26 +14,11 @@ $(document).ready(function() {
} else { } else {
likeBadge.removeClass('liked'); likeBadge.removeClass('liked');
likeButton.data('method', 'post'); likeButton.data('method', 'post');
likeButton.attr('href', '/likes.json?type=' + objectClass + '&id=' + data.id); likeButton.attr('href', '/likes.json?type=Post&id=' + data.id);
likeButton.text('Like'); likeButton.text('Like');
} }
};
$('.post-like').on('ajax:success', function(event, data) {
likeableSuccess(data, 'post');
}); });
$('.activity-like').on('ajax:success', function(event, data) {
likeableSuccess(data, 'activity');
});
$('.planting-like').on('ajax:success', function(event, data) {
likeableSuccess(data, 'planting');
});
$('.harvest-like').on('ajax:success', function(event, data) {
likeableSuccess(data, 'harvest');
});
$('.photo-like').on('ajax:success', function(event, data) { $('.photo-like').on('ajax:success', function(event, data) {
var likeBadge = $('#photo-'+ data.id + ' .like-badge'); var likeBadge = $('#photo-'+ data.id + ' .like-badge');

View File

@@ -1,13 +1,7 @@
.crop-icon { .crop-icon {
height: 1em; height: 1em;
} }
.card-footer {
.btn-group-vertical {
.btn {
text-wrap: initial
}
}
}
.crop-thumbnail { .crop-thumbnail {
.text { .text {
bottom: 0; bottom: 0;

View File

@@ -1,8 +1,6 @@
// stats shown on homepage. eg. "999 members..." // stats shown on homepage. eg. "999 members..."
.stats { .stats {
a { font-weight: bold;
font-weight: bold;
}
} }
.crops, .crops,

View File

@@ -33,6 +33,13 @@
} }
} }
.location-not-set {
background-image: image-url("location-not-set.en.png");
background-position: center;
background-repeat: no-repeat;
height: 250px;
width: 100%;
}
.card { .card {
.badge-location { .badge-location {
background-color: darken($blue, 10%); background-color: darken($blue, 10%);

View File

@@ -47,13 +47,4 @@
margin-left: auto; margin-left: auto;
} }
} }
.card-footer {
max-height: 2em;
-webkit-line-clamp: 1;
overflow: hidden;
text-overflow: ellipsis;
margin-bottom: 0.5em;
padding-top: 0;
}
} }

View File

@@ -30,7 +30,3 @@
@import "predictions"; @import "predictions";
@import "homepage"; @import "homepage";
@import "maps"; @import "maps";
@view-transition {
navigation: auto;
}

View File

@@ -10,33 +10,9 @@
width: 100%; width: 100%;
} }
#navbarSupportedContent { .navbar .nav > li {
ul {
flex-direction: column-reverse;
flex-wrap: nowrap;
li.nav-item {
display: block;
a {
display: grid;
grid-template-columns: 2em 1fr 2em;
}
a.dropdown-toggle::after {
width: 100%;
text-align: right;
}
}
}
}
.crop-actions {
flex-direction: column;
width: 100%;
a {
margin: auto;
display: block; display: block;
} }
}
.navbar .navbar-form { .navbar .navbar-form {
padding-left: 0; padding-left: 0;

View File

@@ -8,10 +8,6 @@ body {
font-family: $default-font; font-family: $default-font;
} }
.navbar {
flex-wrap: nowrap;
align-items: flex-start
}
.navbar-brand { .navbar-brand {
.site-name { .site-name {
font-family: "Modak", cursive; font-family: "Modak", cursive;
@@ -20,7 +16,7 @@ body {
} }
img { img {
height: 100%; height: 60px;
} }
} }
@@ -132,8 +128,6 @@ section {
border-radius: 5%; border-radius: 5%;
margin: 0.5em 0.5em 0.5em 0; margin: 0.5em 0.5em 0.5em 0;
width: 200px; width: 200px;
align-items: stretch;
justify-content: space-between;
.img-card { .img-card {
border-top-left-radius: 5%; border-top-left-radius: 5%;
@@ -370,6 +364,9 @@ ul.thumbnail-buttons {
h1 { h1 {
font-size: 400%; font-size: 400%;
} }
.stats a {
color: $black;
}
// signup widget on homepage // signup widget on homepage
.signup { .signup {

View File

@@ -29,13 +29,8 @@ class ActivitiesController < DataController
def new def new
@activity = Activity.new( @activity = Activity.new(
owner: current_member, owner: current_member
due_date: Date.today
) )
@activity.name = params[:name] if params[:name]
@activity.description = params[:description] if params[:description]
@activity.category = params[:category] if params[:category]
@activity.due_date = params[:due_date] if params[:due_date]
if params[:garden_id] if params[:garden_id]
@activity.garden = Garden.find_by( @activity.garden = Garden.find_by(
owner: current_member, owner: current_member,
@@ -67,17 +62,7 @@ class ActivitiesController < DataController
end end
def update def update
if @activity.update(activity_params) @activity.update(activity_params)
if activity_params[:finished].present?
link = new_activity_path(
name: @activity.name,
garden_id: @activity.garden_id,
planting_id: @activity.planting_id,
due_date: 2.weeks.from_now.to_date
)
flash[:notice] = t('activities.finished_prompt_html', link: link).html_safe
end
end
respond_with @activity respond_with @activity
end end
@@ -96,8 +81,8 @@ class ActivitiesController < DataController
end end
def specifics def specifics
return if @owner.blank? if @owner.present?
"#{@owner.to_param}-"
"#{@owner.to_param}-" end
end end
end end

View File

@@ -57,6 +57,6 @@ class AlternateNamesController < ApplicationController
private private
def alternate_name_params def alternate_name_params
params.require(:alternate_name).permit(:crop_id, :name, :creator_id, :language) params.require(:alternate_name).permit(:crop_id, :name, :creator_id)
end end
end end

View File

@@ -1,8 +0,0 @@
# frozen_string_literal: true
module Api
module V1
class ActivitiesController < BaseController
end
end
end

View File

@@ -4,40 +4,6 @@ module Api
module V1 module V1
class BaseController < JSONAPI::ResourceController class BaseController < JSONAPI::ResourceController
abstract abstract
protect_from_forgery with: :null_session
before_action :authenticate_member_from_token!
before_action :enforce_member_for_write_operations!, only: %i(create update destroy)
rescue_from CanCan::AccessDenied do
head :forbidden
end
def context
{
current_user: current_user,
current_ability: current_ability,
controller: self,
action: params[:action]
}
end
private
attr_reader :current_user
def enforce_member_for_write_operations!
head :unauthorized unless current_user
end
def authenticate_member_from_token!
authenticate_with_http_token do |token, _options|
auth = Authentication.find_by(token: token, provider: 'api')
if auth.present?
@current_user = auth.member
return true
end
end
end
end end
end end
end end

View File

@@ -3,7 +3,9 @@
class ApplicationController < ActionController::Base class ApplicationController < ActionController::Base
protect_from_forgery protect_from_forgery
# Working from codespaces, we want to turn off validation # Working from codespaces, we want to turn off validation
skip_before_action :verify_authenticity_token if Rails.env.development? && ENV['CODESPACE_NAME'] if Rails.env.development? && ENV['CODESPACE_NAME']
skip_before_action :verify_authenticity_token
end
include ApplicationHelper include ApplicationHelper
@@ -12,13 +14,13 @@ class ApplicationController < ActionController::Base
rescue_from ActiveRecord::RecordNotFound, with: :not_found rescue_from ActiveRecord::RecordNotFound, with: :not_found
def store_location def store_location
unless request.path.in?(["/members/sign_in", if !(request.path.in?(["/members/sign_in",
"/members/sign_up", "/members/sign_up",
"/members/password/new", "/members/password/new",
"/members/password/edit", "/members/password/edit",
"/members/confirmation", "/members/confirmation",
"/members/sign_out"]) || request.xhr? "/members/sign_out"]) || request.xhr?) && (request.format == :html)
store_location_for(:member, request.fullpath) if request.format == :html store_location_for(:member, request.fullpath)
end end
end end
@@ -78,7 +80,6 @@ class ApplicationController < ActionController::Base
:tos_agreement, :tos_agreement,
# profile stuff # profile stuff
:bio, :location, :latitude, :longitude, :bio, :location, :latitude, :longitude,
:website_url, :instagram_handle, :facebook_handle, :bluesky_handle, :other_url,
# email settings # email settings
:show_email, :newsletter, :send_notification_email, :send_planting_reminder, :show_email, :newsletter, :send_notification_email, :send_planting_reminder,
# update password # update password

View File

@@ -13,55 +13,43 @@ class CommentsController < ApplicationController
end end
def new def new
@commentable = find_commentable
@comment = Comment.new @comment = Comment.new
if @commentable @post = Post.find_by(id: params[:post_id])
@comments = @commentable.comments
if @post
@comments = @post.comments
respond_with(@comments) respond_with(@comments)
else else
redirect_to(request.referer || root_url, redirect_to(request.referer || root_url,
alert: "Can't post a comment on a non-existent commentable") alert: "Can't post a comment on a non-existent post")
end end
end end
def edit def edit
# TODO: Why does this need a collection of comments? @comments = @comment.post.comments
@comments = @comment.commentable.comments
@commentable = @comment.commentable
end end
def create def create
@comment = Comment.new(comment_params) @comment = Comment.new(comment_params)
@commentable = @comment.commentable
@comment.author = current_member @comment.author = current_member
@comment.save @comment.save
respond_with @comment, location: @commentable respond_with @comment, location: @comment.post
end end
def update def update
@comment.update(body: comment_params['body']) @comment.update(body: comment_params['body'])
respond_with @comment, location: @comment.commentable respond_with @comment, location: @comment.post
end end
def destroy def destroy
@commentable = @comment.commentable @post = @comment.post
@comment.destroy @comment.destroy
respond_with(@commentable) respond_with(@post)
end end
private private
def find_commentable
return unless params[:comment]
if params[:comment][:commentable_type] == 'Photo'
Photo.find(params[:comment][:commentable_id])
elsif params[:comment][:commentable_type] == 'Post'
Post.find(params[:comment][:commentable_id])
end
end
def comment_params def comment_params
params.require(:comment).permit(:body, :commentable_id, :commentable_type) params.require(:comment).permit(:body, :post_id)
end end
end end

View File

@@ -39,6 +39,12 @@ class CropsController < ApplicationController
respond_with @crops respond_with @crops
end end
def openfarm
@crop = Crop.find(params[:crop_slug])
@crop.update_openfarm_data!
respond_with @crop, location: @crop
end
def gbif def gbif
@crop = Crop.find(params[:crop_slug]) @crop = Crop.find(params[:crop_slug])
@crop.update_gbif_data! @crop.update_gbif_data!
@@ -107,12 +113,7 @@ class CropsController < ApplicationController
@crop.approval_status = "pending" @crop.approval_status = "pending"
end end
if Crop.transaction { @crop.save && save_crop_names } notify_wranglers if Crop.transaction { @crop.save && save_crop_names }
notify_wranglers
else
@crop.alternate_names.build
@crop.scientific_names.build
end
respond_with @crop respond_with @crop
end end
@@ -131,6 +132,7 @@ class CropsController < ApplicationController
if @crop.approval_status_changed?(from: "pending", to: "approved") if @crop.approval_status_changed?(from: "pending", to: "approved")
notifier.deliver_now! notifier.deliver_now!
@crop.update_openfarm_data!
@crop.update_gbif_data! @crop.update_gbif_data!
end end
else else
@@ -159,7 +161,7 @@ class CropsController < ApplicationController
end end
def save_crop_names def save_crop_names
AlternateName.create!(names_params(:alt_name).map { |n| { name: n, creator_id: current_member.id, crop_id: @crop.id, language: "EN" } }) AlternateName.create!(names_params(:alt_name).map { |n| { name: n, creator_id: current_member.id, crop_id: @crop.id } })
ScientificName.create!(names_params(:sci_name).map { |n| { name: n, creator_id: current_member.id, crop_id: @crop.id } }) ScientificName.create!(names_params(:sci_name).map { |n| { name: n, creator_id: current_member.id, crop_id: @crop.id } })
end end
@@ -174,26 +176,26 @@ class CropsController < ApplicationController
def recreate_names(param_name, name_type) def recreate_names(param_name, name_type)
return if params[param_name].blank? return if params[param_name].blank?
@crop.send("#{name_type}_names").each(&:destroy) destroy_names(name_type)
params[param_name].each_value do |value| params[param_name].each_value do |value|
next if value.empty? create_name!(name_type, value) unless value.empty?
if name_type == 'alternate'
@crop.send("#{name_type}_names").create!(name: value, creator_id: current_member.id, language: "EN")
else
@crop.send("#{name_type}_names").create!(name: value, creator_id: current_member.id)
end
end end
end end
def destroy_names(name_type)
@crop.send("#{name_type}_names").each(&:destroy)
end
def create_name!(name_type, value)
@crop.send("#{name_type}_names").create!(name: value, creator_id: current_member.id)
end
def crop_params def crop_params
params.require(:crop).permit( params.require(:crop).permit(
:name, :en_wikipedia_url, :name, :en_wikipedia_url,
:parent_id, :perennial, :parent_id, :perennial,
:request_notes, :reason_for_rejection, :request_notes, :reason_for_rejection,
:rejection_notes, :rejection_notes,
:row_spacing, :spread, :height,
:sowing_method, :sun_requirements, :growing_degree_days,
scientific_names_attributes: %i(scientific_name _destroy id) scientific_names_attributes: %i(scientific_name _destroy id)
) )
end end
@@ -209,12 +211,12 @@ class CropsController < ApplicationController
def crop_json_fields def crop_json_fields
{ {
include: { include: {
plantings: { plantings: {
include: { include: {
owner: { only: %i(id login_name location latitude longitude) } owner: { only: %i(id login_name location latitude longitude) }
} }
}, },
scientific_names: { only: [:name] }, alternate_names: { only: %i(name language) } scientific_names: { only: [:name] }, alternate_names: { only: [:name] }
} }
} }
end end

View File

@@ -1,87 +0,0 @@
# frozen_string_literal: true
class GardenCollaboratorsController < ApplicationController
before_action :authenticate_member!, except: %i(index show)
before_action :load_garden
load_and_authorize_resource id_param: :slug
respond_to :html
responders :flash
def index
@garden_collaborators = @garden.garden_collaborators.paginate(page: params[:page])
respond_with(@garden_collaborators)
end
def show
@garden_collaborator = GardenCollaborator.find(params[:garden_collaborator_id])
respond_with(@garden_collaborator)
end
def new
@garden_collaborator = GardenCollaborator.new(garden: @garden)
authorize! :create, @garden_collaborator
respond_with(@garden_collaborator)
end
def edit
@garden_collaborator = GardenCollaborator.find(params[:id])
authorize! :update, @garden_collaborator
respond_with(@garden_collaborator)
end
def create
@garden_collaborator = GardenCollaborator.new(garden: @garden)
authorize! :create, @garden_collaborator
@member = Member.find_by(slug: params[:garden_collaborator][:member_slug])
@garden_collaborator.member = @member
if @garden_collaborator.save
redirect_to garden_garden_collaborators_path(@garden)
else
respond_with(@garden_collaborator)
end
end
def update
@garden_collaborator = GardenCollaborator.find(params[:id])
authorize! :update, @garden_collaborator
@member = Member.find_by(slug: params[:garden_collaborator][:member_slug])
@garden_collaborator.member = @member
@garden_collaborator.save
respond_with(@garden_collaborator)
end
def destroy
@garden_collaborator = GardenCollaborator.find(params[:id])
authorize! :destroy, @garden_collaborator
if @garden_collaborator.destroy
redirect_to garden_garden_collaborators_path(@garden)
else
respond_with(@garden_collaborator)
end
end
private
def load_garden
@garden = Garden.find_by(slug: params[:garden_slug])
end
def garden_collaborator_params
params.require(:garden_collaborator).permit(
:member_slug
)
end
end

View File

@@ -4,23 +4,19 @@ class GardensController < DataController
def index def index
@owner = Member.find_by(slug: params[:member_slug]) @owner = Member.find_by(slug: params[:member_slug])
@show_all = params[:all] == '1' @show_all = params[:all] == '1'
@show_jump_to = params[:member_slug].present? || false @show_jump_to = params[:member_slug].present? ? true : false
@gardens = @gardens.includes(:owner) @gardens = @gardens.includes(:owner)
@gardens = @gardens.active unless @show_all @gardens = @gardens.active unless @show_all
if @owner.present? @gardens = @gardens.where(owner: @owner) if @owner.present?
@gardens = @gardens.left_joins(:garden_collaborators)
@gardens = @gardens.where(owner: @owner).or(@gardens.where(garden_collaborators: { member: @owner }))
end
@gardens = @gardens.where.not(members: { confirmed_at: nil }) @gardens = @gardens.where.not(members: { confirmed_at: nil })
.order(:name).paginate(page: params[:page]) .order(:name).paginate(page: params[:page])
respond_with(@gardens) respond_with(@gardens)
end end
def show def show
@current_plantings = @garden.plantings.current.where.not(failed: true).includes(:crop, :owner).order(planted_at: :desc) @current_plantings = @garden.plantings.current.includes(:crop, :owner).order(planted_at: :desc)
@current_activities = @garden.activities.current.includes(:owner).order(created_at: :desc) @current_activities = @garden.activities.current.includes(:owner).order(created_at: :desc)
@finished_activities = @garden.activities.finished.includes(:owner).order(created_at: :desc)
@finished_plantings = @garden.plantings.finished.includes(:crop) @finished_plantings = @garden.plantings.finished.includes(:crop)
@suggested_companions = Crop.approved.where( @suggested_companions = Crop.approved.where(
id: CropCompanion.where(crop_a_id: @current_plantings.select(:crop_id)).select(:crop_b_id) id: CropCompanion.where(crop_a_id: @current_plantings.select(:crop_id)).select(:crop_b_id)
@@ -39,10 +35,7 @@ class GardensController < DataController
def create def create
@garden.owner_id = current_member.id @garden.owner_id = current_member.id
if @garden.save flash[:notice] = I18n.t('gardens.created') if @garden.save
link = new_activity_path(name: 'Weed the garden bed', garden_id: @garden.id, due_date: 2.weeks.from_now.to_date)
flash[:notice] = t('gardens.created_prompt_html', link: link).html_safe
end
respond_with(@garden) respond_with(@garden)
end end

View File

@@ -16,6 +16,7 @@ class MembersController < ApplicationController
def show def show
@member = Member.confirmed.kept.find_by!(slug: params[:slug]) @member = Member.confirmed.kept.find_by!(slug: params[:slug])
@twitter_auth = @member.auth('twitter')
@flickr_auth = @member.auth('flickr') @flickr_auth = @member.auth('flickr')
@posts = @member.posts @posts = @member.posts
@@ -60,7 +61,7 @@ class MembersController < ApplicationController
end end
def unsubscribe def unsubscribe
verifier = ActiveSupport::MessageVerifier.new(ENV.fetch('RAILS_SECRET_TOKEN', nil)) verifier = ActiveSupport::MessageVerifier.new(ENV['RAILS_SECRET_TOKEN'])
decrypted_message = verifier.verify(params[:message]) decrypted_message = verifier.verify(params[:message])
@member = Member.find(decrypted_message[:member_id]) @member = Member.find(decrypted_message[:member_id])

View File

@@ -8,11 +8,9 @@ class MessagesController < ApplicationController
end end
def show def show
if (@message = Message.find_by(id: params[:id])) && (@conversation = @message.conversation) if (@message = Message.find_by(id: params[:id])) && (@conversation = @message.conversation) && @conversation.is_participant?(current_member)
if @conversation.is_participant?(current_member) redirect_to conversation_path(@conversation, box: @box, anchor: "message_" + @message.id.to_s)
redirect_to conversation_path(@conversation, box: @box, anchor: "message_" + @message.id.to_s) return
return
end
end end
redirect_to conversations_path(box: @box) redirect_to conversations_path(box: @box)
end end
@@ -21,7 +19,7 @@ class MessagesController < ApplicationController
return if params[:recipient_id].blank? return if params[:recipient_id].blank?
@recipient = Member.find_by(id: params[:recipient_id]) @recipient = Member.find_by(id: params[:recipient_id])
nil if @recipient.nil? return if @recipient.nil?
end end
def create def create

View File

@@ -28,7 +28,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
@authentication = action.establish_authentication(auth, member) @authentication = action.establish_authentication(auth, member)
if action.member_created? if action.member_created?
raise "Invalid provider" unless %w(flickr).index(auth['provider'].to_s) raise "Invalid provider" unless %w(twitter flickr).index(auth['provider'].to_s)
session["devise.#{auth['provider']}_data"] = request.env["omniauth.auth"] session["devise.#{auth['provider']}_data"] = request.env["omniauth.auth"]
sign_in member sign_in member
@@ -41,7 +41,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
def after_sign_in_path_for(resource) def after_sign_in_path_for(resource)
if resource.tos_agreement if resource.tos_agreement
super super(resource)
else else
finish_signup_path(resource) finish_signup_path(resource)
end end

View File

@@ -21,7 +21,6 @@ class PhotosController < ApplicationController
def show def show
@crops = Crop.distinct.joins(:photo_associations).where(photo_associations: { photo: @photo }) @crops = Crop.distinct.joins(:photo_associations).where(photo_associations: { photo: @photo })
@comment = Comment.new(commentable: @photo)
respond_with(@photo) respond_with(@photo)
end end

View File

@@ -37,7 +37,6 @@ class PlantingsController < DataController
@photos = @planting.photos.includes(:owner).order(date_taken: :desc) @photos = @planting.photos.includes(:owner).order(date_taken: :desc)
@harvests = Harvest.search(where: { planting_id: @planting.id }) @harvests = Harvest.search(where: { planting_id: @planting.id })
@current_activities = @planting.activities.current.includes(:owner).order(created_at: :desc) @current_activities = @planting.activities.current.includes(:owner).order(created_at: :desc)
@finished_activities = @planting.activities.finished.includes(:owner).order(created_at: :desc)
@matching_seeds = matching_seeds @matching_seeds = matching_seeds
@crop = @planting.crop @crop = @planting.crop
@@ -83,12 +82,7 @@ class PlantingsController < DataController
end end
def update def update
if @planting.update(planting_params) @planting.update(planting_params)
if planting_params[:finished].present? && @planting.garden.plantings.current.empty?
link = new_activity_path(name: 'Cultivate soil', garden_id: @planting.garden_id)
flash[:notice] = t('plantings.finished_prompt_html', link: link).html_safe
end
end
respond_with @planting respond_with @planting
end end
@@ -97,32 +91,6 @@ class PlantingsController < DataController
respond_with @planting, location: @planting.garden respond_with @planting, location: @planting.garden
end end
def transplant
# The `load_and_authorize_resource` in DataController will handle finding the
# planting and authorizing the action.
# We still need to authorize the new garden
new_garden = Garden.find(params[:garden_id])
authorize! :update, new_garden
# Mark original planting as finished
@planting.update(finished: true, finished_at: Time.zone.now)
# Create a new planting
new_planting = @planting.dup
new_planting.garden = new_garden
new_planting.slug = nil # let friendly_id generate a new slug
new_planting.finished = false
new_planting.finished_at = nil
if new_planting.save
redirect_to edit_planting_path(new_planting), notice: 'Planting was successfully transplanted.'
else
# if the save fails, we should probably roll back the finishing of the original planting
@planting.update(finished: false, finished_at: nil)
redirect_to @planting, alert: "There was an error transplanting the planting: #{new_planting.errors.full_messages.to_sentence}"
end
end
private private
def update_crop_medians def update_crop_medians
@@ -139,7 +107,7 @@ class PlantingsController < DataController
:crop_id, :description, :garden_id, :planted_at, :crop_id, :description, :garden_id, :planted_at,
:parent_seed_id, :parent_seed_id,
:quantity, :sunniness, :planted_from, :finished, :quantity, :sunniness, :planted_from, :finished,
:finished_at, :failed, :overall_rating :finished_at
) )
end end

View File

@@ -6,7 +6,8 @@ class RegistrationsController < Devise::RegistrationsController
prepend_before_action :check_captcha, only: [:create] # Change this to be any actions you want to protect with recaptcha. prepend_before_action :check_captcha, only: [:create] # Change this to be any actions you want to protect with recaptcha.
def edit def edit
@flickr_auth = current_member.auth('flickr') @twitter_auth = current_member.auth('twitter')
@flickr_auth = current_member.auth('flickr')
render "edit" render "edit"
end end
@@ -38,12 +39,6 @@ class RegistrationsController < Devise::RegistrationsController
end end
end end
def regenerate_api_token
current_member.regenerate_api_token
set_flash_message :notice, :api_token_regenerated
redirect_to edit_member_registration_path + '#apps'
end
def destroy def destroy
if @member.valid_password?(params.require(:member)[:current_password]) if @member.valid_password?(params.require(:member)[:current_password])
@member.discard @member.discard

View File

@@ -19,8 +19,6 @@ class SeedsController < DataController
where['parent_planting'] = @planting.id where['parent_planting'] = @planting.id
end end
where['tradeable_to'] = params[:tradeable_to] if params[:tradeable_to].present?
@show_all = (params[:all] == '1') @show_all = (params[:all] == '1')
where['finished'] = false unless @show_all where['finished'] = false unless @show_all
@@ -43,7 +41,6 @@ class SeedsController < DataController
def new def new
@seed = Seed.new @seed = Seed.new
@seed.source = 'my own seed saving'
if params[:planting_slug] if params[:planting_slug]
@planting = Planting.find_by(slug: params[:planting_slug]) @planting = Planting.find_by(slug: params[:planting_slug])
@@ -57,8 +54,6 @@ class SeedsController < DataController
def create def create
@seed = Seed.new(seed_params) @seed = Seed.new(seed_params)
@seed.source ||= 'my own seed saving'
@seed.finished ||= false
@seed.owner = current_member @seed.owner = current_member
@seed.crop = @seed.parent_planting.crop if @seed.parent_planting @seed.crop = @seed.parent_planting.crop if @seed.parent_planting
flash[:notice] = "Successfully added #{@seed.crop} seed to your stash." if @seed.save flash[:notice] = "Successfully added #{@seed.crop} seed to your stash." if @seed.save
@@ -86,7 +81,7 @@ class SeedsController < DataController
:crop_id, :description, :quantity, :plant_before, :crop_id, :description, :quantity, :plant_before,
:parent_planting_id, :saved_at, :parent_planting_id, :saved_at,
:days_until_maturity_min, :days_until_maturity_max, :days_until_maturity_min, :days_until_maturity_max,
:organic, :gmo, :source, :organic, :gmo,
:heirloom, :tradable_to, :slug, :heirloom, :tradable_to, :slug,
:finished, :finished_at :finished, :finished_at
) )

View File

@@ -21,32 +21,6 @@ module ApplicationHelper
classes classes
end end
# Similar to Rails' time_ago_in_words, but gives a more standard
# output like "in 3 days" or "5 months ago".
# Also handles the case where from_time is a Date and to_time is a Date
# (in which case it just says "today" if they're the same date).
#
# NOTE: This is similar to distance_of_time_in_words but different enough
# that I think it's worth having a separate helper for it.
#
# from_time - the starting time (Time or Date)
# to_time - the ending time (Time or Date). Default: now (Time.zone.now)
# include_seconds - whether to include seconds in the calculation
#
# Returns a string like "in 3 days" or "5 months ago"
def standard_time_distance(from_time, to_time = 0, include_seconds = false)
return 'today' if from_time.is_a?(Date) && (from_time == to_time)
return 'now' if from_time == to_time
return "#{distance_of_time_in_words(from_time, to_time, include_seconds:)} ago" if from_time < to_time
"in #{distance_of_time_in_words(from_time, to_time, include_seconds:)}"
end
def count_github_contibutors
File.open(Rails.root.join('CONTRIBUTORS.md')).readlines.grep(/^-/).size
end
# Produces a cache key for uniquely identifying cached fragments. # Produces a cache key for uniquely identifying cached fragments.
def cache_key_for(klass, identifier = "all") def cache_key_for(klass, identifier = "all")
count = klass.count count = klass.count
@@ -54,6 +28,12 @@ module ApplicationHelper
"#{klass.name.downcase.pluralize}/#{identifier}-#{count}-#{max_updated_at}" "#{klass.name.downcase.pluralize}/#{identifier}-#{count}-#{max_updated_at}"
end end
def required_field_help_text
asterisk = tag.span('*', class: ['red'])
text = tag.em('denotes a required field')
tag.div(asterisk + ' '.html_safe + text, class: ['margin-bottom'])
end
# A helper to replace the complex template compilation mess # A helper to replace the complex template compilation mess
# of HAML, Tilt, and dynamic compilation with interpolated ruby. # of HAML, Tilt, and dynamic compilation with interpolated ruby.
def markdownify(text) def markdownify(text)
@@ -76,6 +56,7 @@ module ApplicationHelper
uri.query = "&width=#{size}&height=#{size}" if uri.host == 'graph.facebook.com' uri.query = "&width=#{size}&height=#{size}" if uri.host == 'graph.facebook.com'
# TODO: Assess twitter - https://dev.twitter.com/overview/general/user-profile-images-and-banners
# TODO: Assess flickr - https://www.flickr.com/services/api/misc.buddyicons.html # TODO: Assess flickr - https://www.flickr.com/services/api/misc.buddyicons.html
return uri.to_s return uri.to_s

View File

@@ -13,7 +13,7 @@ module AutoSuggestHelper
resource = resource.class.name.downcase resource = resource.class.name.downcase
source_path = Rails.application.routes.url_helpers.send("search_#{source}s_path", format: :json) source_path = Rails.application.routes.url_helpers.send("search_#{source}s_path", format: :json)
%( %(
<input id="#{source}" class="auto-suggest #{options[:class]}" #{options[:required] ? 'required="required"' : ''} <input id="#{source}" class="auto-suggest #{options[:class]}"
type="text" value="#{default}" data-source-url="#{source_path}", type="text" value="#{default}" data-source-url="#{source_path}",
placeholder="e.g. lettuce"> placeholder="e.g. lettuce">
<noscript class="text-warning"> <noscript class="text-warning">

View File

@@ -2,7 +2,6 @@
module ButtonsHelper module ButtonsHelper
include IconsHelper include IconsHelper
def garden_plant_something_button(garden, classes: "btn btn-default") def garden_plant_something_button(garden, classes: "btn btn-default")
return unless can? :edit, garden return unless can? :edit, garden
@@ -53,7 +52,7 @@ module ButtonsHelper
link_to t('buttons.mark_as_inactive'), link_to t('buttons.mark_as_inactive'),
garden_path(garden, garden: { active: 0 }), garden_path(garden, garden: { active: 0 }),
method: :put, class: classes, method: :put, class: classes,
data: { confirm: I18n.t('gardens.confirm_deactivate') } data: { confirm: 'All plantings associated with this garden will be marked as finished. Are you sure?' }
end end
def create_button(model_to_create, path, icon, label) def create_button(model_to_create, path, icon, label)
@@ -88,19 +87,6 @@ module ButtonsHelper
edit_button(edit_activity_path(activity), classes:) edit_button(edit_activity_path(activity), classes:)
end end
def activity_copy_button(activity, classes: 'btn')
link_to new_activity_path(
name: activity.name,
description: activity.description,
category: activity.category,
garden_id: activity.garden_id,
planting_id: activity.planting_id,
due_date: activity.due_date
), class: classes do
copy_icon + ' ' + t('buttons.copy')
end
end
def activity_finish_button(activity, classes: 'btn btn-default btn-secondary') def activity_finish_button(activity, classes: 'btn btn-default btn-secondary')
return unless can?(:edit, activity) || activity.finished return unless can?(:edit, activity) || activity.finished
@@ -111,7 +97,7 @@ module ButtonsHelper
end end
def planting_finish_button(planting, classes: 'btn btn-default btn-secondary') def planting_finish_button(planting, classes: 'btn btn-default btn-secondary')
return unless can?(:edit, planting) || planting.finished || planting.failed return unless can?(:edit, planting) || planting.finished
link_to planting_path(slug: planting.slug, planting: { finished: 1 }), link_to planting_path(slug: planting.slug, planting: { finished: 1 }),
method: :put, class: "#{classes} append-date" do method: :put, class: "#{classes} append-date" do
@@ -119,15 +105,6 @@ module ButtonsHelper
end end
end end
def planting_failed_button(planting, classes: 'btn btn-default btn-secondary')
return unless can?(:edit, planting) || planting.finished || planting.failed
link_to planting_path(slug: planting.slug, planting: { failed: 1 }),
method: :put, class: "#{classes}" do
finished_icon + ' ' + t('buttons.mark_as_failed')
end
end
def seed_finish_button(seed, classes: 'btn btn-default') def seed_finish_button(seed, classes: 'btn btn-default')
return unless can?(:create, Planting) && seed.active return unless can?(:create, Planting) && seed.active
@@ -145,7 +122,7 @@ module ButtonsHelper
end end
def planting_save_seeds_button(planting, classes: 'btn btn-default') def planting_save_seeds_button(planting, classes: 'btn btn-default')
return unless can?(:edit, planting) && !planting.failed? return unless can?(:edit, planting)
link_to new_planting_seed_path(planting_slug: planting.slug), class: classes do link_to new_planting_seed_path(planting_slug: planting.slug), class: classes do
seed_icon + ' ' + t('buttons.save_seeds') seed_icon + ' ' + t('buttons.save_seeds')

View File

@@ -7,14 +7,14 @@ module CropsHelper
return "You don't have any seeds of this crop." if seeds.none? return "You don't have any seeds of this crop." if seeds.none?
if total_quantity == 0 if total_quantity != 0
"You have an unknown quantity of seeds of this crop."
else
"You have #{total_quantity} #{Seed.model_name.human(count: total_quantity)} of this crop." "You have #{total_quantity} #{Seed.model_name.human(count: total_quantity)} of this crop."
else
"You have an unknown quantity of seeds of this crop."
end end
end end
def crop_ebay_seeds_url(crop) def crop_ebay_seeds_url(crop)
"https://www.ebay.com/sch/i.html?_nkw=#{CGI.escape crop.name}" "https://rover.ebay.com/rover/1/705-53470-19255-0/1?icep_ff3=9&pub=5575213277&toolid=10001&campid=5337940151&customid=&icep_uq=#{CGI.escape crop.name}&icep_sellerId=&icep_ex_kw=&icep_sortBy=12&icep_catId=181003&icep_minPrice=&icep_maxPrice=&ipn=psmain&icep_vectorid=229515&kwid=902099&mtid=824&kw=lg"
end end
end end

View File

@@ -7,8 +7,6 @@ module EventHelper
def event_description(event) def event_description(event)
render "#{event.event_type.pluralize}/description", event_model: resolve_model(event) render "#{event.event_type.pluralize}/description", event_model: resolve_model(event)
rescue ActionView::MissingTemplate
"#{event.event_type.humanize.downcase}d"
end end
def resolve_model(event) def resolve_model(event)

View File

@@ -59,10 +59,6 @@ module IconsHelper
image_icon 'delete' image_icon 'delete'
end end
def copy_icon
icon('far', 'copy')
end
def add_photo_icon def add_photo_icon
image_icon 'add-photo' image_icon 'add-photo'
end end

View File

@@ -43,14 +43,6 @@ module PlantingsHelper
(planting.first_harvest_predicted_at - Time.zone.today).to_i (planting.first_harvest_predicted_at - Time.zone.today).to_i
end end
# Returns a list of gardens the planting can be transplanted to
# based on the planting's owner.
def transplantable_gardens_by_owner(planting)
garden_ids = planting.owner.gardens.select(:id).to_a + GardenCollaborator.where(member_id: planting.owner.id).select(:garden_id).to_a
Garden.active.where.not(id: planting.garden_id).where(id: garden_ids)
end
def days_from_now_to_last_harvest(planting) def days_from_now_to_last_harvest(planting)
return unless planting.planted_at.present? && planting.last_harvest_predicted_at.present? return unless planting.planted_at.present? && planting.last_harvest_predicted_at.present?

View File

@@ -2,15 +2,15 @@
class NotifierMailer < ApplicationMailer class NotifierMailer < ApplicationMailer
# include NotificationsHelper # include NotificationsHelper
default from: "Growstuff <#{ENV.fetch('GROWSTUFF_EMAIL', nil)}>" default from: "Growstuff <#{ENV['GROWSTUFF_EMAIL']}>"
def verifier def verifier
unless ENV['RAILS_SECRET_TOKEN'] unless ENV['RAILS_SECRET_TOKEN']
raise "RAILS_SECRET_TOKEN environment variable" \ raise "RAILS_SECRET_TOKEN environment variable"\
"not set - have you created config/application.yml?" "not set - have you created config/application.yml?"
end end
ActiveSupport::MessageVerifier.new(ENV.fetch('RAILS_SECRET_TOKEN', nil)) ActiveSupport::MessageVerifier.new(ENV['RAILS_SECRET_TOKEN'])
end end
def notify(notification) def notify(notification)
@@ -27,7 +27,7 @@ class NotifierMailer < ApplicationMailer
def planting_reminder(member) def planting_reminder(member)
@member = member @member = member
@sitename = ENV.fetch('GROWSTUFF_SITE_NAME', nil) @sitename = ENV['GROWSTUFF_SITE_NAME']
@late = [] @late = []
@super_late = [] @super_late = []

View File

@@ -108,42 +108,16 @@ class Ability
can :create, Planting can :create, Planting
can :update, Planting, garden: { owner_id: member.id }, crop: { approval_status: 'approved' } can :update, Planting, garden: { owner_id: member.id }, crop: { approval_status: 'approved' }
can :destroy, Planting, garden: { owner_id: member.id }, crop: { approval_status: 'approved' } can :destroy, Planting, garden: { owner_id: member.id }, crop: { approval_status: 'approved' }
can :update, Planting do |planting|
planting.garden.garden_collaborators.where(member_id: member.id).any?
end
can :transplant, Planting, garden: { owner_id: member.id }
can :transplant, Planting do |planting|
planting.garden.garden_collaborators.where(member_id: member.id).any?
end
can :destroy, Planting do |planting|
planting.garden.garden_collaborators.where(member_id: member.id).any?
end
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 :create, Activity can :create, Activity
can :update, Activity, owner_id: member.id can :update, Activity, owner_id: member.id
can :destroy, Activity, owner_id: member.id can :destroy, Activity, owner_id: member.id
can :update, Activity do |activity|
activity.garden&.garden_collaborators&.where(member_id: member.id)&.any?
end
can :destroy, Activity do |activity|
activity.garden&.garden_collaborators&.where(member_id: member.id)&.any?
end
can :create, Harvest can :create, Harvest
can :update, Harvest, owner_id: member.id can :update, Harvest, owner_id: member.id
can :destroy, Harvest, owner_id: member.id can :destroy, Harvest, owner_id: member.id
can :update, Harvest, owner_id: member.id, planting: { owner_id: member.id } can :update, Harvest, owner_id: member.id, planting: { owner_id: member.id }
can :destroy, Harvest, owner_id: member.id, planting: { owner_id: member.id } can :destroy, Harvest, owner_id: member.id, planting: { owner_id: member.id }
can :update, Harvest do |harvest|
harvest.planting&.garden&.garden_collaborators&.where(member_id: member.id)&.any?
end
can :destroy, Harvest do |harvest|
harvest.planting&.garden&.garden_collaborators&.where(member_id: member.id)&.any?
end
can :create, Photo can :create, Photo
can :update, Photo, owner_id: member.id can :update, Photo, owner_id: member.id

View File

@@ -5,7 +5,6 @@ class Activity < ApplicationRecord
include Ownable include Ownable
include Finishable include Finishable
include SearchActivities include SearchActivities
include Likeable
belongs_to :garden, optional: true belongs_to :garden, optional: true
belongs_to :planting, optional: true belongs_to :planting, optional: true
@@ -30,20 +29,4 @@ class Activity < ApplicationRecord
def to_s def to_s
name name
end end
def garden_name
garden&.name
end
def garden_slug
garden&.slug
end
def planting_name
planting&.crop&.name
end
def planting_slug
planting&.crop&.slug
end
end end

View File

@@ -5,7 +5,6 @@ class AlternateName < ApplicationRecord
belongs_to :creator, class_name: 'Member', inverse_of: :created_alternate_names belongs_to :creator, class_name: 'Member', inverse_of: :created_alternate_names
validates :name, presence: true validates :name, presence: true
validates :crop, presence: true validates :crop, presence: true
validates :language, presence: true
after_commit :reindex after_commit :reindex

View File

@@ -2,27 +2,26 @@
class Comment < ApplicationRecord class Comment < ApplicationRecord
belongs_to :author, class_name: 'Member', inverse_of: :comments belongs_to :author, class_name: 'Member', inverse_of: :comments
belongs_to :commentable, polymorphic: true, counter_cache: true belongs_to :post, counter_cache: true
# validates :body, presence: true
scope :post_order, -> { order(created_at: :asc) } # for display on post page scope :post_order, -> { order(created_at: :asc) } # for display on post page
after_create do after_create do
recipient = commentable.author.id recipient = post.author.id
sender = author.id sender = author.id
# don't send notifications to yourself # don't send notifications to yourself
if recipient != sender if recipient != sender
Notification.create( Notification.create(
recipient_id: recipient, recipient_id: recipient,
sender_id: sender, sender_id: sender,
subject: "#{author} commented on #{commentable.subject}", subject: "#{author} commented on #{post.subject}",
body:, body:,
notifiable: commentable post_id: post.id
) )
end end
end end
def to_s def to_s
"#{author.login_name} commented on #{commentable.subject}" "#{author.login_name} commented on #{post.subject}"
end end
end end

View File

@@ -8,12 +8,7 @@ module Finishable
scope :current, -> { where.not(finished: true) } scope :current, -> { where.not(finished: true) }
def active def active
# Plantings can fail. At the moment, activities and seeds cannot. !finished
if respond_to?(:failed)
!finished && !failed
else
!finished
end
end end
end end
end end

View File

@@ -9,8 +9,8 @@ module MemberFlickr
if @flickr.nil? if @flickr.nil?
flickr_auth = auth('flickr') flickr_auth = auth('flickr')
if flickr_auth if flickr_auth
FlickRaw.api_key = ENV.fetch('GROWSTUFF_FLICKR_KEY', nil) FlickRaw.api_key = ENV['GROWSTUFF_FLICKR_KEY']
FlickRaw.shared_secret = ENV.fetch('GROWSTUFF_FLICKR_SECRET', nil) FlickRaw.shared_secret = ENV['GROWSTUFF_FLICKR_SECRET']
@flickr = FlickRaw::Flickr.new @flickr = FlickRaw::Flickr.new
@flickr.access_token = flickr_auth.token @flickr.access_token = flickr_auth.token
@flickr.access_secret = flickr_auth.secret @flickr.access_secret = flickr_auth.secret

View File

@@ -4,10 +4,22 @@ module OpenFarmData
extend ActiveSupport::Concern extend ActiveSupport::Concern
included do included do
def update_openfarm_data!
OpenfarmService.new.update_crop(self)
end
def of_photo def of_photo
fetch_attr('main_image_path') fetch_attr('main_image_path')
end end
def height
fetch_attr('height')
end
def spread
fetch_attr('spread')
end
def svg_icon def svg_icon
icon = fetch_attr('svg_icon') icon = fetch_attr('svg_icon')
return icon if icon.present? return icon if icon.present?
@@ -23,18 +35,38 @@ module OpenFarmData
fetch_attr('description') fetch_attr('description')
end end
def row_spacing
fetch_attr('row_spacing')
end
def common_names def common_names
fetch_attr('common_names') fetch_attr('common_names')
end end
def guides_count
fetch_attr('guides_count')
end
def binomial_name def binomial_name
fetch_attr('binomial_name') fetch_attr('binomial_name')
end end
def sowing_method
fetch_attr('sowing_method')
end
def main_image_path def main_image_path
fetch_attr('main_image_path') fetch_attr('main_image_path')
end end
def sun_requirements
fetch_attr('sun_requirements')
end
def growing_degree_days
fetch_attr('growing_degree_days')
end
def processing_pictures def processing_pictures
fetch_attr('processing_pictures') fetch_attr('processing_pictures')
end end

View File

@@ -38,7 +38,7 @@ module PredictHarvest
# status # status
def harvest_time? def harvest_time?
return false if crop.perennial || finished || failed return false if crop.perennial || finished
# We have harvests but haven't finished # We have harvests but haven't finished
harvests.size.positive? || harvests.size.positive? ||

View File

@@ -8,12 +8,12 @@ module PredictPlanting
before_save :calculate_lifespan before_save :calculate_lifespan
def calculate_lifespan def calculate_lifespan
self.lifespan = (planted_at.present? && finished_at.present? && !failed? ? finished_at - planted_at : nil) self.lifespan = (planted_at.present? && finished_at.present? ? finished_at - planted_at : nil)
end end
# dates # dates
def finish_predicted_at def finish_predicted_at
if planted_at.blank? || failed? if planted_at.blank?
nil nil
elsif crop.median_lifespan.present? elsif crop.median_lifespan.present?
planted_at + crop.median_lifespan.days planted_at + crop.median_lifespan.days
@@ -34,18 +34,15 @@ module PredictPlanting
end end
def actual_lifespan def actual_lifespan
return unless planted_at.present? && finished_at.present? && !failed? return unless planted_at.present? && finished_at.present?
(finished_at - planted_at).to_i (finished_at - planted_at).to_i
end end
def age_in_days def age_in_days
return if planted_at.blank? return if planted_at.blank?
return if failed?
known_last_day ||= finished_at || Time.zone.today known_last_day ||= finished_at || Time.zone.today
known_last_day = Time.zone.today if known_last_day > Time.zone.today
(known_last_day - planted_at).to_i (known_last_day - planted_at).to_i
end end
@@ -53,9 +50,9 @@ module PredictPlanting
Rails.cache.fetch("#{cache_key_with_version}/percentage_grown", expires_in: 8.hours) do Rails.cache.fetch("#{cache_key_with_version}/percentage_grown", expires_in: 8.hours) do
if finished? if finished?
100 100
elsif !planted? || failed? elsif !planted?
0 0
elsif crop.perennial || (finish_predicted_at.nil? && finished_at.nil?) # This covers future dated finished_at that hasn't occurrred yet. elsif crop.perennial || finish_predicted_at.nil?
nil nil
else else
calculate_percentage_grown calculate_percentage_grown
@@ -74,7 +71,7 @@ module PredictPlanting
end end
def late? def late?
crop.annual? && !finished && !failed && crop.annual? && !finished &&
planted_at.present? && planted_at.present? &&
finish_predicted_at.present? && finish_predicted_at.present? &&
finish_predicted_at <= Time.zone.today finish_predicted_at <= Time.zone.today
@@ -94,9 +91,9 @@ module PredictPlanting
private private
def calculate_percentage_grown def calculate_percentage_grown
return 0 if age_in_days.to_i < 0 return 0 if age_in_days < 0
percent = (age_in_days.to_f / expected_lifespan.to_f) * 100 percent = (age_in_days / expected_lifespan.to_f) * 100
(percent > 100 ? 100 : percent) (percent > 100 ? 100 : percent)
end end
end end

View File

@@ -9,9 +9,7 @@ module SearchActivities
mappings: { mappings: {
properties: { properties: {
active: { type: :boolean }, active: { type: :boolean },
created_at: { type: :integer }, created_at: { type: :integer }
updated_at: { type: :integer },
due_date: { type: :date }
} }
} }
@@ -25,10 +23,8 @@ module SearchActivities
category:, category:,
garden_id:, garden_id:,
garden_name: garden&.name, garden_name: garden&.name,
garden_slug: garden&.garden_slug,
planting_id:, planting_id:,
planting_name: planting&.crop&.name, planting_name: planting&.crop&.name,
planting_slug: planting&.slug,
description:, description:,
# owner # owner
@@ -48,7 +44,7 @@ module SearchActivities
1..limit.times do 1..limit.times do
where = { where = {
# photos_count: { gt: 0 }, # photos_count: { gt: 0 },
owner_id: { not: owners } owner_id: { not: owners }
} }
one_record = search('*', one_record = search('*',
limit: 1, limit: 1,

View File

@@ -30,8 +30,7 @@ module SearchPlantings
quantity:, quantity:,
sunniness:, sunniness:,
garden_id:, garden_id:,
garden_slug: garden&.garden_slug, garden_name: garden&.name,
garden_name: garden&.name,
description:, description:,
first_harvest_predicted_at:, first_harvest_predicted_at:,

View File

@@ -59,8 +59,7 @@ module SearchSeeds
search('*', limit:, search('*', limit:,
where: { where: {
finished: false, finished: false,
tradable: true, tradable: true
_or: [{ plant_before: nil }, { plant_before: { lt: Date.today } }]
}, },
boost_by: [:created_at], boost_by: [:created_at],
load: false) load: false)

View File

@@ -90,7 +90,7 @@ class Crop < ApplicationRecord
def popular_plant_parts def popular_plant_parts
PlantPart.joins(:harvests) PlantPart.joins(:harvests)
.where("crop_id = ?", id) .where("crop_id = ?", id)
.order(count_harvests_id: :desc) .order("count_harvests_id DESC")
.group("plant_parts.id", "plant_parts.name") .group("plant_parts.id", "plant_parts.name")
.count("harvests.id") .count("harvests.id")
end end

View File

@@ -59,7 +59,7 @@ class CsvImporter
alternate_names.split(/,\s*/).each do |name| alternate_names.split(/,\s*/).each do |name|
altname = AlternateName.find_by(name:, crop: @crop) altname = AlternateName.find_by(name:, crop: @crop)
altname ||= AlternateName.create! name:, crop: @crop, language: "EN", creator: cropbot altname ||= AlternateName.create! name: name, crop: @crop, creator: cropbot
@crop.alternate_names << altname @crop.alternate_names << altname
end end
end end

View File

@@ -10,8 +10,7 @@ class Follow < ApplicationRecord
recipient_id: followed_id, recipient_id: followed_id,
sender_id: follower_id, sender_id: follower_id,
subject: "#{follower.login_name} is now following you", subject: "#{follower.login_name} is now following you",
body: "#{follower.login_name} just followed you on #{ENV.fetch('GROWSTUFF_SITE_NAME', nil)}. ", body: "#{follower.login_name} just followed you on #{ENV['GROWSTUFF_SITE_NAME']}. "
notifiable: self
) )
end end
end end

View File

@@ -5,13 +5,11 @@ class Garden < ApplicationRecord
include Geocodable include Geocodable
include PhotoCapable include PhotoCapable
include Ownable include Ownable
friendly_id :garden_slug, use: %i(slugged finders) friendly_id :garden_slug, use: %i(slugged finders)
has_many :plantings, dependent: :destroy has_many :plantings, dependent: :destroy
has_many :crops, through: :plantings has_many :crops, through: :plantings
has_many :activities, dependent: :destroy has_many :activities, dependent: :destroy
has_many :garden_collaborators, dependent: :destroy
belongs_to :garden_type, optional: true belongs_to :garden_type, optional: true
@@ -45,7 +43,6 @@ class Garden < ApplicationRecord
.where.not(gardens: { latitude: nil }) .where.not(gardens: { latitude: nil })
.where.not(gardens: { longitude: nil }) .where.not(gardens: { longitude: nil })
} }
AREA_UNITS_VALUES = { AREA_UNITS_VALUES = {
"square metres" => "square metre", "square metres" => "square metre",
"square feet" => "square foot", "square feet" => "square foot",

View File

@@ -1,24 +0,0 @@
# frozen_string_literal: true
class GardenCollaborator < ApplicationRecord
belongs_to :member
belongs_to :garden
validates :member_id, uniqueness: { scope: :garden }
validate :not_garden_owner
def not_garden_owner
return unless member
return unless garden
errors.add(:member_id, "cannot be the garden owner") if garden.owner == member
end
def member_slug
@member&.slug
end
def member_slug=(_slug)
member_slug
end
end

View File

@@ -6,7 +6,6 @@ class Harvest < ApplicationRecord
include PhotoCapable include PhotoCapable
include Ownable include Ownable
include SearchHarvests include SearchHarvests
include Likeable
friendly_id :harvest_slug, use: %i(slugged finders) friendly_id :harvest_slug, use: %i(slugged finders)
@@ -153,10 +152,7 @@ class Harvest < ApplicationRecord
def owner_must_match_planting def owner_must_match_planting
return if planting.blank? # only check if we are linked to a planting return if planting.blank? # only check if we are linked to a planting
return if owner == planting.owner || planting.garden.garden_collaborators.where(member_id: owner).any? errors.add(:owner, "of harvest must be the same as planting") unless owner == planting.owner
errors.add(:owner,
"of harvest must be the same as planting, or a collaborator on that garden")
end end
def harvest_must_be_after_planting def harvest_must_be_after_planting

View File

@@ -24,20 +24,6 @@ class Member < ApplicationRecord
has_many :notifications, foreign_key: 'recipient_id', inverse_of: :recipient has_many :notifications, foreign_key: 'recipient_id', inverse_of: :recipient
has_many :sent_notifications, foreign_key: 'sender_id', inverse_of: :sender, class_name: "Notification" has_many :sent_notifications, foreign_key: 'sender_id', inverse_of: :sender, class_name: "Notification"
has_many :authentications, dependent: :destroy has_many :authentications, dependent: :destroy
has_one :api_token, -> { where(provider: 'api') }, class_name: 'Authentication', dependent: :destroy
def api_token?
api_token.present?
end
def regenerate_api_token
api_token.destroy if api_token?
create_api_token(
provider: 'api',
uid: id,
token: SecureRandom.hex(16)
)
end
has_many :photos, inverse_of: :owner has_many :photos, inverse_of: :owner
has_many :likes, dependent: :destroy has_many :likes, dependent: :destroy
@@ -105,9 +91,6 @@ class Member < ApplicationRecord
uniqueness: { uniqueness: {
case_sensitive: false case_sensitive: false
} }
validates :website_url, format: { with: /\Ahttps?:\/\//, message: "must start with http:// or https://" }, allow_blank: true
validates :other_url, format: { with: /\Ahttps?:\/\//, message: "must start with http:// or https://" }, allow_blank: true
validates :instagram_handle, :facebook_handle, :bluesky_handle, format: { without: %r{\Ahttps?:\/\/|\/}, message: "should be a handle, not a URL" }, allow_blank: true
# #
# Triggers # Triggers

View File

@@ -3,7 +3,7 @@
class Notification < ApplicationRecord class Notification < ApplicationRecord
belongs_to :sender, class_name: 'Member', inverse_of: :sent_notifications belongs_to :sender, class_name: 'Member', inverse_of: :sent_notifications
belongs_to :recipient, class_name: 'Member', inverse_of: :notifications belongs_to :recipient, class_name: 'Member', inverse_of: :notifications
belongs_to :notifiable, polymorphic: true belongs_to :post, optional: true
validates :subject, length: { maximum: 255 } validates :subject, length: { maximum: 255 }

View File

@@ -8,7 +8,6 @@ class Photo < ApplicationRecord
PHOTO_CAPABLE = %w(Garden Planting Harvest Seed Post Crop).freeze PHOTO_CAPABLE = %w(Garden Planting Harvest Seed Post Crop).freeze
has_many :photo_associations, dependent: :delete_all, inverse_of: :photo has_many :photo_associations, dependent: :delete_all, inverse_of: :photo
has_many :comments, as: :commentable, dependent: :destroy
# This doesn't work, ActiveRecord tries to use the polymoriphic photographable # This doesn't work, ActiveRecord tries to use the polymoriphic photographable
# relationship instead. # relationship instead.
@@ -46,8 +45,7 @@ class Photo < ApplicationRecord
flickr = owner.flickr flickr = owner.flickr
info = flickr.photos.getInfo(photo_id: source_id) info = flickr.photos.getInfo(photo_id: source_id)
licenses = flickr.photos.licenses.getInfo licenses = flickr.photos.licenses.getInfo
license = licenses.find { |l| l.id.to_i == info.license.to_i } license = licenses.find { |l| l.id == info.license }
Rails.logger.error("Cannot find license: " + [info.license, licenses].inspect) unless license
{ {
title: calculate_title(info), title: calculate_title(info),
license_name: license.name, license_name: license.name,
@@ -85,14 +83,6 @@ class Photo < ApplicationRecord
"#{title} by #{owner.login_name}" "#{title} by #{owner.login_name}"
end end
def subject
title
end
def author
owner
end
def flickr_photo_id def flickr_photo_id
source_id if source == 'flickr' source_id if source == 'flickr'
end end

View File

@@ -8,7 +8,6 @@ class Planting < ApplicationRecord
include PredictPlanting include PredictPlanting
include PredictHarvest include PredictHarvest
include SearchPlantings include SearchPlantings
include Likeable
friendly_id :planting_slug, use: %i(slugged finders) friendly_id :planting_slug, use: %i(slugged finders)
@@ -43,8 +42,7 @@ class Planting < ApplicationRecord
.where.not(gardens: { latitude: nil }) .where.not(gardens: { latitude: nil })
.where.not(gardens: { longitude: nil }) .where.not(gardens: { longitude: nil })
} }
scope :active, -> { where(finished: false, failed: false).where('finished_at IS NULL OR finished_at < ?', Time.zone.now) } scope :active, -> { where('finished <> true').where('finished_at IS NULL OR finished_at < ?', Time.zone.now) }
scope :failed, -> { where(failed: true) }
scope :annual, -> { joins(:crop).where(crops: { perennial: false }) } scope :annual, -> { joins(:crop).where(crops: { perennial: false }) }
scope :perennial, -> { joins(:crop).where(crops: { perennial: true }) } scope :perennial, -> { joins(:crop).where(crops: { perennial: true }) }
scope :interesting, -> { has_photos.one_per_owner.order(planted_at: :desc) } scope :interesting, -> { has_photos.one_per_owner.order(planted_at: :desc) }
@@ -62,7 +60,6 @@ class Planting < ApplicationRecord
to: :crop, prefix: true to: :crop, prefix: true
delegate :login_name, :slug, :location, to: :owner, prefix: true delegate :login_name, :slug, :location, to: :owner, prefix: true
delegate :slug, to: :planting, prefix: true delegate :slug, to: :planting, prefix: true
delegate :slug, :name, to: :garden, prefix: true
delegate :annual?, :perennial?, :svg_icon, to: :crop delegate :annual?, :perennial?, :svg_icon, to: :crop
delegate :location, :longitude, :latitude, to: :garden delegate :location, :longitude, :latitude, to: :garden
@@ -73,7 +70,6 @@ class Planting < ApplicationRecord
validates :crop, presence: true, approved: { message: "must be present and exist in our database" } validates :crop, presence: true, approved: { message: "must be present and exist in our database" }
validate :finished_must_be_after_planted validate :finished_must_be_after_planted
validate :owner_must_match_garden_owner validate :owner_must_match_garden_owner
validate :cannot_be_finished_and_failed
validates :quantity, allow_nil: true, numericality: { validates :quantity, allow_nil: true, numericality: {
only_integer: true, greater_than_or_equal_to: 0 only_integer: true, greater_than_or_equal_to: 0
} }
@@ -83,9 +79,6 @@ class Planting < ApplicationRecord
validates :planted_from, allow_blank: true, inclusion: { validates :planted_from, allow_blank: true, inclusion: {
in: PLANTED_FROM_VALUES, message: "%<value>s is not a valid planting method" in: PLANTED_FROM_VALUES, message: "%<value>s is not a valid planting method"
} }
validates :overall_rating, allow_blank: true, numericality: {
only_integer: true, greater_than_or_equal_to: 1, less_than_or_equal_to: 5
}
def planting_slug def planting_slug
[ [
@@ -101,11 +94,7 @@ class Planting < ApplicationRecord
end end
def finished? def finished?
(finished || (finished_at.present? && finished_at <= Time.zone.today)) && !failed? finished || (finished_at.present? && finished_at <= Time.zone.today)
end
def failed?
failed
end end
def planted? def planted?
@@ -129,10 +118,6 @@ class Planting < ApplicationRecord
private private
def cannot_be_finished_and_failed
errors.add(:failed, "can't be true if planting is also finished") if finished && failed
end
# check that any finished_at date occurs after planted_at # check that any finished_at date occurs after planted_at
def finished_must_be_after_planted def finished_must_be_after_planted
return unless planted_at && finished_at # only check if we have both return unless planted_at && finished_at # only check if we have both
@@ -141,9 +126,6 @@ class Planting < ApplicationRecord
end end
def owner_must_match_garden_owner def owner_must_match_garden_owner
return if owner == garden.owner || garden.garden_collaborators.where(member_id: owner).any? errors.add(:owner, "must be the same as garden") unless owner == garden.owner
errors.add(:owner,
"must be the same as garden, or a collaborator on that garden")
end end
end end

View File

@@ -3,7 +3,6 @@
class Post < ApplicationRecord class Post < ApplicationRecord
extend FriendlyId extend FriendlyId
include Likeable include Likeable
friendly_id :author_date_subject, use: %i(slugged finders) friendly_id :author_date_subject, use: %i(slugged finders)
include PhotoCapable include PhotoCapable
@@ -11,10 +10,9 @@ class Post < ApplicationRecord
# Relationships # Relationships
belongs_to :author, class_name: 'Member', inverse_of: :posts belongs_to :author, class_name: 'Member', inverse_of: :posts
belongs_to :forum, optional: true belongs_to :forum, optional: true
has_many :comments, as: :commentable, dependent: :destroy has_many :comments, dependent: :destroy
has_many :crop_posts, dependent: :delete_all has_many :crop_posts, dependent: :delete_all
has_many :crops, through: :crop_posts has_many :crops, through: :crop_posts
has_many :notifications, as: :notifiable, dependent: :destroy
after_create :send_notification after_create :send_notification
# #
@@ -97,7 +95,6 @@ class Post < ApplicationRecord
Notification.create( Notification.create(
recipient_id:, recipient_id:,
sender_id: sender, sender_id: sender,
notifiable: self,
subject: "#{author} mentioned you in their post #{subject}", subject: "#{author} mentioned you in their post #{subject}",
body: body:
) )

View File

@@ -12,8 +12,6 @@ class Seed < ApplicationRecord
ORGANIC_VALUES = ['certified organic', 'non-certified organic', 'conventional/non-organic', 'unknown'].freeze ORGANIC_VALUES = ['certified organic', 'non-certified organic', 'conventional/non-organic', 'unknown'].freeze
GMO_VALUES = ['certified GMO-free', 'non-certified GMO-free', 'GMO', 'unknown'].freeze GMO_VALUES = ['certified GMO-free', 'non-certified GMO-free', 'GMO', 'unknown'].freeze
HEIRLOOM_VALUES = %w(heirloom hybrid unknown).freeze HEIRLOOM_VALUES = %w(heirloom hybrid unknown).freeze
SOURCE_VALUES = ['seed catalogue', 'retail outlet', 'seed bank or similar institution',
'traded from another person', 'my own seed saving', 'other/unknown'].freeze
# #
# Relationships # Relationships
@@ -35,20 +33,17 @@ class Seed < ApplicationRecord
validates :days_until_maturity_max, allow_nil: true, validates :days_until_maturity_max, allow_nil: true,
numericality: { only_integer: true, greater_than_or_equal_to: 0 } numericality: { only_integer: true, greater_than_or_equal_to: 0 }
validates :tradable_to, allow_blank: false, validates :tradable_to, allow_blank: false,
inclusion: { in: TRADABLE_TO_VALUES, message: "You may only trade seed nowhere, " \ inclusion: { in: TRADABLE_TO_VALUES, message: "You may only trade seed nowhere, "\
"locally, nationally, or internationally" } "locally, nationally, or internationally" }
validates :organic, allow_blank: false, validates :organic, allow_blank: false,
inclusion: { in: ORGANIC_VALUES, message: "You must say whether the seeds " \ inclusion: { in: ORGANIC_VALUES, message: "You must say whether the seeds "\
"are organic or not, or that you don't know" } "are organic or not, or that you don't know" }
validates :gmo, allow_blank: false, validates :gmo, allow_blank: false,
inclusion: { in: GMO_VALUES, message: "You must say whether the seeds are " \ inclusion: { in: GMO_VALUES, message: "You must say whether the seeds are "\
"genetically modified or not, or that you don't know" } "genetically modified or not, or that you don't know" }
validates :heirloom, allow_blank: false, validates :heirloom, allow_blank: false,
inclusion: { in: HEIRLOOM_VALUES, message: "You must say whether the seeds" \ inclusion: { in: HEIRLOOM_VALUES, message: "You must say whether the seeds"\
"are heirloom, hybrid, or unknown" } "are heirloom, hybrid, or unknown" }
validates :source, allow_blank: true,
inclusion: { in: SOURCE_VALUES, message: "You must say where the seeds are from," \
"or that you don't know" }
# #
# Delegations # Delegations
@@ -61,10 +56,9 @@ class Seed < ApplicationRecord
default_scope { joins(:owner).merge(Member.kept) } # Ensure owner exists default_scope { joins(:owner).merge(Member.kept) } # Ensure owner exists
scope :tradable, -> { where.not(tradable_to: 'nowhere') } scope :tradable, -> { where.not(tradable_to: 'nowhere') }
scope :interesting, -> { tradable.has_location } scope :interesting, -> { tradable.has_location }
scope :has_location, -> { joins(:owner).where.not('members.location': nil) } scope :has_location, -> { joins(:owner).where.not("members.location": nil) }
scope :recent, -> { order(created_at: :desc) } scope :recent, -> { order(created_at: :desc) }
scope :active, -> { where('finished <> true').where('finished_at IS NULL OR finished_at < ?', Time.zone.now) } scope :active, -> { where('finished <> true').where('finished_at IS NULL OR finished_at < ?', Time.zone.now) }
scope :expired, -> { active.where('plant_before < ?', Time.zone.today) }
def tradable def tradable
tradable_to != 'nowhere' tradable_to != 'nowhere'

View File

@@ -1,29 +0,0 @@
# frozen_string_literal: true
module Api
module V1
class ActivityResource < BaseResource
before_create do
@model.owner = context[:current_user]
end
has_one :owner, class_name: 'Member'
has_one :garden
has_one :planting
attribute :name
attribute :description
attribute :category
attribute :finished
attribute :due_date
filter :owner
filter :owner_id
filter :garden
filter :garden_id
filter :planting
filter :planting_id
filter :category
end
end
end

View File

@@ -3,7 +3,8 @@
module Api module Api
module V1 module V1
class CropResource < BaseResource class CropResource < BaseResource
immutable # TODO: Re-evaluate this later immutable
filter :approval_status, default: 'approved' filter :approval_status, default: 'approved'
has_many :plantings has_many :plantings

View File

@@ -3,22 +3,13 @@
module Api module Api
module V1 module V1
class GardenResource < BaseResource class GardenResource < BaseResource
before_create do immutable
@model.owner = context[:current_user]
end
has_one :owner, class_name: 'Member' has_one :owner, class_name: 'Member'
has_many :plantings has_many :plantings
has_many :photos has_many :photos
attribute :name attribute :name
filter :owner
filter :owner_id
filter :active
filter :garden_type
filter :location
filter :slug
end end
end end
end end

View File

@@ -3,17 +3,11 @@
module Api module Api
module V1 module V1
class HarvestResource < BaseResource class HarvestResource < BaseResource
before_save do immutable
@model.owner = context[:current_user]
@model.crop_id = @model.planting.crop_id if @model.planting_id
@model.harvested_at = Time.zone.now if @model.harvested_at.blank?
@model.plant_part = PlantPart.first
end
has_one :crop has_one :crop
has_one :planting has_one :planting
has_one :owner, class_name: 'Member' has_one :owner, class_name: 'Member'
# has_one :plant_part
has_many :photos has_many :photos
attribute :harvested_at attribute :harvested_at
@@ -22,15 +16,6 @@ module Api
attribute :weight_quantity attribute :weight_quantity
attribute :weight_unit attribute :weight_unit
attribute :si_weight attribute :si_weight
filter :owner
filter :owner_id
filter :crop
filter :crop_id
filter :planting
filter :planting_id
filter :plant_part
filter :harvested_at
end end
end end
end end

View File

@@ -3,10 +3,7 @@
module Api module Api
module V1 module V1
class PhotoResource < BaseResource class PhotoResource < BaseResource
immutable # TODO: Re-evaluate this. immutable
before_create do
@model.owner = context[:current_user]
end
has_one :owner, class_name: 'Member' has_one :owner, class_name: 'Member'
has_many :plantings has_many :plantings

View File

@@ -3,9 +3,7 @@
module Api module Api
module V1 module V1
class PlantingResource < BaseResource class PlantingResource < BaseResource
before_create do immutable
@model.owner = context[:current_user]
end
has_one :garden has_one :garden
has_one :crop has_one :crop
@@ -15,7 +13,6 @@ module Api
attribute :slug attribute :slug
attribute :planted_at attribute :planted_at
attribute :failed
attribute :finished attribute :finished
attribute :finished_at attribute :finished_at
attribute :quantity attribute :quantity
@@ -38,13 +35,11 @@ module Api
filter :owner filter :owner
filter :owner_id filter :owner_id
filter :finished filter :finished
filter :active, apply: ->(records, _value, _options) { records.active }
filter :failed, apply: ->(records, _value, _options) { records.failed }
filter :sunniness
filter :perennial, apply: ->(records, _value, _options) { records.perennial }
attribute :percentage_grown attribute :percentage_grown
delegate :percentage_grown, to: :@model def percentage_grown
@model.percentage_grown
end
attribute :crop_name attribute :crop_name
attribute :crop_slug attribute :crop_slug

View File

@@ -3,9 +3,7 @@
module Api module Api
module V1 module V1
class SeedResource < BaseResource class SeedResource < BaseResource
before_create do immutable
@model.owner = context[:current_user]
end
has_one :owner, class_name: 'Member' has_one :owner, class_name: 'Member'
has_one :crop has_one :crop
@@ -19,15 +17,6 @@ module Api
attribute :organic attribute :organic
attribute :gmo attribute :gmo
attribute :heirloom attribute :heirloom
filter :owner
filter :owner_id
filter :crop
filter :crop_id
filter :tradable_to
filter :organic
filter :gmo
filter :heirloom
end end
end end
end end

View File

@@ -1,16 +1,6 @@
# frozen_string_literal: true # frozen_string_literal: true
class BaseResource < JSONAPI::Resource class BaseResource < JSONAPI::Resource
immutable
abstract abstract
[:create, :update, :remove].each do |action|
set_callback action, :before, :authorize
end
# Check authorisation for write operations.
# NOTE: At a later time, we may require API tokens for READ operations.
def authorize
# context[:action] is simply context[:controller].params[:action]
context[:current_ability].authorize! context[:action].to_sym, @model
end
end end

View File

@@ -0,0 +1,108 @@
# frozen_string_literal: true
BASE = 'https://openfarm.cc/api/v1/'
# BASE = 'http://127.0.0.1:3000/api/v1/'
class OpenfarmService
def initialize
@cropbot = Member.find_by(login_name: 'cropbot')
end
def import!
Crop.all.order(updated_at: :desc).each do |crop|
Rails.logger.debug { "#{crop.id}, #{crop.name}" }
update_crop(crop) if crop.valid?
end
end
def update_crop(crop)
openfarm_record = fetch(crop.name)
if openfarm_record.present? && openfarm_record.is_a?(String)
Rails.logger.info(openfarm_record)
elsif openfarm_record.present? && openfarm_record.fetch('data', false)
crop.update! openfarm_data: openfarm_record.fetch('data', false)
save_companions(crop, openfarm_record)
save_photos(crop)
else
Rails.logger.debug "\tcrop not found on Open Farm"
crop.update!(openfarm_data: false)
end
end
def save_companions(crop, openfarm_record)
companions = openfarm_record.fetch('data').fetch('relationships').fetch('companions').fetch('data')
crops = openfarm_record.fetch('included', []).select { |rec| rec["type"] == 'crops' }
CropCompanion.transaction do
companions.each do |com|
companion_crop_hash = crops.detect { |c| c.fetch('id') == com.fetch('id') }
companion_crop_name = companion_crop_hash.fetch('attributes').fetch('name').downcase
companion_crop = Crop.where('lower(name) = ?', companion_crop_name).first
companion_crop = Crop.create!(name: companion_crop_name, requester: @cropbot, approval_status: "pending") if companion_crop.nil?
crop.companions << companion_crop unless crop.companions.where(id: companion_crop.id).any?
end
end
end
def save_photos(crop)
pictures = fetch_pictures(crop.name)
pictures.each do |picture|
data = picture.fetch('attributes')
Rails.logger.debug(data)
next unless data.fetch('image_url').start_with? 'http'
next if Photo.find_by(source_id: picture.fetch('id'), source: 'openfarm')
photo = Photo.new(
source_id: picture.fetch('id'),
source: 'openfarm',
owner: @cropbot,
thumbnail_url: data.fetch('thumbnail_url'),
fullsize_url: data.fetch('image_url'),
title: 'Open Farm photo',
license_name: 'No rights reserved',
link_url: "https://openfarm.cc/en/crops/#{name_to_slug(crop.name)}"
)
if photo.valid?
Photo.transaction do
photo.save
PhotoAssociation.find_or_create_by! photo:, photographable: crop
end
Rails.logger.debug { "\t saved photo #{photo.id} #{photo.source_id}" }
else
Rails.logger.warn "Photo not valid"
end
end
end
def fetch(name)
conn.get("crops/#{name_to_slug(name)}.json").body
rescue NoMethodError
Rails.logger.debug "error fetching crop"
Rails.logger.debug "BODY: "
Rails.logger.debug body
end
def name_to_slug(name)
CGI.escape(name.gsub(' ', '-').downcase)
end
def fetch_all(page)
conn.get("crops.json?page=#{page}").body.fetch('data', {})
end
def fetch_pictures(name)
body = conn.get("crops/#{name_to_slug(name)}/pictures.json").body
body.fetch('data', false)
rescue StandardError
Rails.logger.debug "Error fetching photos"
Rails.logger.debug []
end
private
def conn
Faraday.new BASE do |conn|
conn.response :json, content_type: /\bjson$/
conn.adapter Faraday.default_adapter
end
end
end

View File

@@ -18,20 +18,10 @@ class TimelineService
.union_all(photos_query) .union_all(photos_query)
.union_all(seeds_query) .union_all(seeds_query)
.union_all(activities_query) .union_all(activities_query)
.union_all(likes_query)
.where.not(event_at: nil) .where.not(event_at: nil)
.order(event_at: :desc) .order(event_at: :desc)
end end
def self.likes_query
Like
.select("likes.id",
"'like' as event_type",
"likes.created_at as event_at",
"likes.member_id as owner_id",
"null as crop_id")
end
def self.activities_query def self.activities_query
Activity.select( Activity.select(
:id, :id,

View File

@@ -1,9 +1,8 @@
- if can?(:edit, activity) - if can?(:edit, activity)
%span.dropdown.activity-actions .dropdown.activity-actions
%a#activity-actions-button.btn.btn-info.dropdown-toggle{"aria-expanded" => "false", "aria-haspopup" => "true", "data-bs-toggle" => "dropdown", type: "button", href: '#'} Actions %a#activity-actions-button.btn.btn-info.dropdown-toggle{"aria-expanded" => "false", "aria-haspopup" => "true", "data-bs-toggle" => "dropdown", type: "button", href: '#'} Actions
.dropdown-menu.dropdown-menu-xs{"aria-labelledby" => "planting-actions-button"} .dropdown-menu.dropdown-menu-xs{"aria-labelledby" => "planting-actions-button"}
= activity_edit_button(activity, classes: 'dropdown-item') = activity_edit_button(activity, classes: 'dropdown-item')
= activity_copy_button(activity, classes: 'dropdown-item')
- if activity.active - if activity.active
= activity_finish_button(activity, classes: 'dropdown-item') = activity_finish_button(activity, classes: 'dropdown-item')
.dropdown-divider .dropdown-divider

View File

@@ -20,24 +20,16 @@
- if can? :destroy, activity - if can? :destroy, activity
.dropdown-divider .dropdown-divider
= delete_button(activity, classes: 'dropdown-item text-danger') = delete_button(activity, classes: 'dropdown-item text-danger')
.card-body = link_to activity_path(slug: activity.slug) do
= link_to activity_path(slug: activity.slug) do .card-body.text-center
%h4= activity.name %h4= activity.name
- if activity.due_date .text-center= activity.description
%small.due-date{title: activity.due_date} - if activity.garden
= standard_time_distance(activity.due_date.to_date, Time.zone.now.to_date) .text-center= activity.garden
%div - if activity.planting
%small.text-justify{title: activity.description}= activity.description.truncate(150) .text-center= activity.planting
%p
%ul.list-unstyled
- if activity.garden_name && activity.garden_slug
%li
%small= link_to activity.garden_name, garden_path(slug: activity.garden_slug)
- if activity.planting_name && activity.planting_slug
%li
%small= link_to activity.planting_name, planting_path(slug: activity.planting_slug)
.card-footer .card-footer
%small.chip.member-chip .float-right
= link_to member_path(slug: activity.owner_slug) do %span.chip.member-chip
= activity.owner_login_name = link_to member_path(slug: activity.owner_slug) do
= activity.owner_login_name

View File

@@ -6,6 +6,7 @@
%strong=yield :title %strong=yield :title
= bootstrap_form_for(@activity) do |f| = bootstrap_form_for(@activity) do |f|
.card-body .card-body
= required_field_help_text
- if @activity.errors.any? - if @activity.errors.any?
#error_explanation #error_explanation
%h2 %h2
@@ -27,27 +28,27 @@
.row .row
.col-md-4 .col-md-4
= f.collection_radio_buttons(:garden_id, @activity.owner.gardens.active.order_by_name, = f.collection_radio_buttons(:garden_id, @activity.owner.gardens.active,
:id, :name, :id, :name,
label: 'Is this for a specific garden?') label: 'Is this for a specific garden?')
= link_to "Add a garden.", new_garden_path = link_to "Add a garden.", new_garden_path
.col-md-4 .col-md-4
= f.collection_radio_buttons(:planting_id, @activity.owner.plantings.active.recent, = f.collection_radio_buttons(:planting_id, @activity.owner.plantings.active,
:id, :crop_name, :id, :crop_name,
label: 'Is this for a specific planting?') label: 'Is this for a specific planting?')
= link_to "Add a planting.", new_planting_path = link_to "Add a planting.", new_planting_path
.col-md-4 .col-md-4
= f.date_field :due_date, = f.text_field :due_date,
value: @activity.due_date ? @activity.due_date.to_fs(:ymd) : '', value: @activity.due_date ? @activity.due_date.to_fs(:ymd) : '',
label: 'When?' class: 'add-datepicker', label: 'When?'
%hr %hr
.row .row
.col-md-6 .col-md-6
= f.check_box :finished, label: t('buttons.mark_as_finished') = f.check_box :finished, label: 'Mark as finished'
%span.help-block= t('.finish_helper') %span.help-block= t('.finish_helper')
.card-footer .card-footer

View File

@@ -22,17 +22,19 @@
%small.text-muted= @activity.category %small.text-muted= @activity.category
%tt %tt
= @activity.due_date = @activity.due_date
- if @activity.description.present?
:markdown
#{strip_tags markdownify(@activity.description)}
= render 'likes/likes', object: @activity
= render 'activities/actions', activity: @activity
.col-md-4.col-xs-12 .col-md-4.col-xs-12
= render 'activities/owner', planting: @activity = render 'activities/owner', planting: @activity
.col-md-8.col-xs-12 .col-md-8.col-xs-12
- if @activity.description.present?
= cute_icon
.card
.card-header
%h2 Description
.card-body
:markdown
#{strip_tags markdownify(@activity.description)}
- if @activity.garden - if @activity.garden
%section.gardens %section.gardens
@@ -46,3 +48,4 @@
.col-md-4.col-xs-12 .col-md-4.col-xs-12
= render 'activities/actions', activity: @activity

View File

@@ -31,8 +31,7 @@
= f.label :name, class: 'control-label col-md-2' = f.label :name, class: 'control-label col-md-2'
.col-md-8 .col-md-8
= f.text_field :name, class: 'form-control' = f.text_field :name, class: 'form-control'
.col-md-8
= f.select :language, I18nData.languages.map {|code, name| [name.split(";").first, code] }, class: 'form-control'
.form-group .form-group
.form-actions.col-md-offset-2.col-md-8 .form-actions.col-md-offset-2.col-md-8
= f.submit 'Save', class: 'btn btn-primary' = f.submit 'Save', class: 'btn btn-primary'

Some files were not shown because too many files have changed in this diff Show More