Compare commits

..

12 Commits

Author SHA1 Message Date
Daniel O'Connor
2a6f826c1d Other safe corrections 2025-09-07 08:54:27 +00:00
Daniel O'Connor
ef1ff9d519 Layout 2025-09-07 08:52:25 +00:00
Daniel O'Connor
84c71c75eb Layout/HashAlignment 2025-09-07 08:51:01 +00:00
Daniel O'Connor
a91b357408 Layout/EmptyLinesAfterModuleInclusion 2025-09-07 08:49:54 +00:00
Daniel O'Connor
514d271638 Update rubocop 2025-09-07 08:48:02 +00:00
Daniel O'Connor
8ab94bae67 Update rubocop_todo 2025-09-07 08:47:03 +00:00
Daniel O'Connor
c6e57ca3ed Rubocop autocorrections 2025-09-07 08:41:26 +00:00
Daniel O'Connor
c3cdf8cb77 Rubocop safe autocorrections 2025-09-07 08:40:52 +00:00
Daniel O'Connor
82bcb00fa1 Rubocop safe autocorrections 2025-09-07 08:40:05 +00:00
Daniel O'Connor
aec2bb67e9 Rubocop autocorrections 2025-09-07 08:39:23 +00:00
Daniel O'Connor
60765d5ebf Rubocop autocorrections 2025-09-07 08:38:00 +00:00
Daniel O'Connor
baca600f45 Fix warnings 2025-09-07 08:37:15 +00:00
157 changed files with 3014 additions and 8369 deletions

View File

@@ -27,7 +27,7 @@ services:
command: sleep infinity
db:
image: postgres:17
image: postgres:latest
restart: unless-stopped
volumes:
- postgres-data:/var/lib/postgresql/data

View File

@@ -38,7 +38,7 @@ jobs:
steps:
- name: Checkout this repo
uses: actions/checkout@v6
uses: actions/checkout@v5
- name: Configure sysctl limits
run: |
@@ -74,7 +74,7 @@ jobs:
sudo apt-get -y install libpq-dev google-chrome-stable
- name: Install NodeJS
uses: actions/setup-node@v6
uses: actions/setup-node@v5
with:
node-version: '12'
@@ -103,7 +103,7 @@ jobs:
- name: Upload screenshots
if: failure()
uses: actions/upload-artifact@v5
uses: actions/upload-artifact@v4
with:
name: screenshots
path: tmp/screenshots

View File

@@ -38,7 +38,7 @@ jobs:
steps:
- name: Checkout this repo
uses: actions/checkout@v6
uses: actions/checkout@v5
- name: Configure sysctl limits
run: |
@@ -74,7 +74,7 @@ jobs:
sudo apt-get -y install libpq-dev google-chrome-stable
- name: Install NodeJS
uses: actions/setup-node@v6
uses: actions/setup-node@v5
with:
node-version: '12'
@@ -103,7 +103,7 @@ jobs:
- name: Upload screenshots
if: failure()
uses: actions/upload-artifact@v5
uses: actions/upload-artifact@v4
with:
name: screenshots
path: tmp/screenshots

View File

@@ -38,7 +38,7 @@ jobs:
steps:
- name: Checkout this repo
uses: actions/checkout@v6
uses: actions/checkout@v5
- name: Configure sysctl limits
run: |
@@ -74,7 +74,7 @@ jobs:
sudo apt-get -y install libpq-dev google-chrome-stable
- name: Install NodeJS
uses: actions/setup-node@v6
uses: actions/setup-node@v5
with:
node-version: '12'
@@ -103,7 +103,7 @@ jobs:
- name: Upload screenshots
if: failure()
uses: actions/upload-artifact@v5
uses: actions/upload-artifact@v4
with:
name: screenshots
path: tmp/screenshots

View File

@@ -38,7 +38,7 @@ jobs:
steps:
- name: Checkout this repo
uses: actions/checkout@v6
uses: actions/checkout@v5
- name: Configure sysctl limits
run: |
@@ -74,7 +74,7 @@ jobs:
sudo apt-get -y install libpq-dev google-chrome-stable
- name: Install NodeJS
uses: actions/setup-node@v6
uses: actions/setup-node@v5
with:
node-version: '12'
@@ -103,7 +103,7 @@ jobs:
- name: Upload screenshots
if: failure()
uses: actions/upload-artifact@v5
uses: actions/upload-artifact@v4
with:
name: screenshots
path: tmp/screenshots

View File

@@ -38,7 +38,7 @@ jobs:
steps:
- name: Checkout this repo
uses: actions/checkout@v6
uses: actions/checkout@v5
- name: Configure sysctl limits
run: |
@@ -74,7 +74,7 @@ jobs:
sudo apt-get -y install libpq-dev google-chrome-stable
- name: Install NodeJS
uses: actions/setup-node@v6
uses: actions/setup-node@v5
with:
node-version: '12'
@@ -103,7 +103,7 @@ jobs:
- name: Upload screenshots
if: failure()
uses: actions/upload-artifact@v5
uses: actions/upload-artifact@v4
with:
name: screenshots
path: tmp/screenshots

View File

@@ -38,7 +38,7 @@ jobs:
steps:
- name: Checkout this repo
uses: actions/checkout@v6
uses: actions/checkout@v5
- name: Configure sysctl limits
run: |
@@ -74,7 +74,7 @@ jobs:
sudo apt-get -y install libpq-dev google-chrome-stable
- name: Install NodeJS
uses: actions/setup-node@v6
uses: actions/setup-node@v5
with:
node-version: '12'
@@ -103,7 +103,7 @@ jobs:
- name: Upload screenshots
if: failure()
uses: actions/upload-artifact@v5
uses: actions/upload-artifact@v4
with:
name: screenshots
path: tmp/screenshots

View File

@@ -38,7 +38,7 @@ jobs:
steps:
- name: Checkout this repo
uses: actions/checkout@v6
uses: actions/checkout@v5
- name: Configure sysctl limits
run: |
@@ -74,7 +74,7 @@ jobs:
sudo apt-get -y install libpq-dev google-chrome-stable
- name: Install NodeJS
uses: actions/setup-node@v6
uses: actions/setup-node@v5
with:
node-version: '12'
@@ -103,7 +103,7 @@ jobs:
- name: Upload screenshots
if: failure()
uses: actions/upload-artifact@v5
uses: actions/upload-artifact@v4
with:
name: screenshots
path: tmp/screenshots

View File

@@ -38,7 +38,7 @@ jobs:
steps:
- name: Checkout this repo
uses: actions/checkout@v6
uses: actions/checkout@v5
- name: Configure sysctl limits
run: |
@@ -74,7 +74,7 @@ jobs:
sudo apt-get -y install libpq-dev google-chrome-stable
- name: Install NodeJS
uses: actions/setup-node@v6
uses: actions/setup-node@v5
with:
node-version: '12'
@@ -103,7 +103,7 @@ jobs:
- name: Upload screenshots
if: failure()
uses: actions/upload-artifact@v5
uses: actions/upload-artifact@v4
with:
name: screenshots
path: tmp/screenshots

View File

@@ -38,7 +38,7 @@ jobs:
steps:
- name: Checkout this repo
uses: actions/checkout@v6
uses: actions/checkout@v5
- name: Configure sysctl limits
run: |
@@ -74,7 +74,7 @@ jobs:
sudo apt-get -y install libpq-dev google-chrome-stable
- name: Install NodeJS
uses: actions/setup-node@v6
uses: actions/setup-node@v5
with:
node-version: '12'
@@ -103,7 +103,7 @@ jobs:
- name: Upload screenshots
if: failure()
uses: actions/upload-artifact@v5
uses: actions/upload-artifact@v4
with:
name: screenshots
path: tmp/screenshots

View File

@@ -38,7 +38,7 @@ jobs:
steps:
- name: Checkout this repo
uses: actions/checkout@v6
uses: actions/checkout@v5
- name: Configure sysctl limits
run: |
@@ -74,7 +74,7 @@ jobs:
sudo apt-get -y install libpq-dev google-chrome-stable
- name: Install NodeJS
uses: actions/setup-node@v6
uses: actions/setup-node@v5
with:
node-version: '12'
@@ -103,7 +103,7 @@ jobs:
- name: Upload screenshots
if: failure()
uses: actions/upload-artifact@v5
uses: actions/upload-artifact@v4
with:
name: screenshots
path: tmp/screenshots

View File

@@ -38,7 +38,7 @@ jobs:
steps:
- name: Checkout this repo
uses: actions/checkout@v6
uses: actions/checkout@v5
- name: Configure sysctl limits
run: |
@@ -74,7 +74,7 @@ jobs:
sudo apt-get -y install libpq-dev google-chrome-stable
- name: Install NodeJS
uses: actions/setup-node@v6
uses: actions/setup-node@v5
with:
node-version: '12'
@@ -103,7 +103,7 @@ jobs:
- name: Upload screenshots
if: failure()
uses: actions/upload-artifact@v5
uses: actions/upload-artifact@v4
with:
name: screenshots
path: tmp/screenshots

View File

@@ -38,7 +38,7 @@ jobs:
steps:
- name: Checkout this repo
uses: actions/checkout@v6
uses: actions/checkout@v5
- name: Configure sysctl limits
run: |
@@ -74,7 +74,7 @@ jobs:
sudo apt-get -y install libpq-dev google-chrome-stable
- name: Install NodeJS
uses: actions/setup-node@v6
uses: actions/setup-node@v5
with:
node-version: '12'
@@ -103,7 +103,7 @@ jobs:
- name: Upload screenshots
if: failure()
uses: actions/upload-artifact@v5
uses: actions/upload-artifact@v4
with:
name: screenshots
path: tmp/screenshots

View File

@@ -38,7 +38,7 @@ jobs:
steps:
- name: Checkout this repo
uses: actions/checkout@v6
uses: actions/checkout@v5
- name: Configure sysctl limits
run: |
@@ -74,7 +74,7 @@ jobs:
sudo apt-get -y install libpq-dev google-chrome-stable
- name: Install NodeJS
uses: actions/setup-node@v6
uses: actions/setup-node@v5
with:
node-version: '12'
@@ -103,7 +103,7 @@ jobs:
- name: Upload screenshots
if: failure()
uses: actions/upload-artifact@v5
uses: actions/upload-artifact@v4
with:
name: screenshots
path: tmp/screenshots

View File

@@ -38,7 +38,7 @@ jobs:
steps:
- name: Checkout this repo
uses: actions/checkout@v6
uses: actions/checkout@v5
- name: Configure sysctl limits
run: |
@@ -74,7 +74,7 @@ jobs:
sudo apt-get -y install libpq-dev google-chrome-stable
- name: Install NodeJS
uses: actions/setup-node@v6
uses: actions/setup-node@v5
with:
node-version: '12'
@@ -112,7 +112,7 @@ jobs:
- name: Upload screenshots
if: failure()
uses: actions/upload-artifact@v5
uses: actions/upload-artifact@v4
with:
name: screenshots
path: tmp/screenshots

View File

@@ -6,7 +6,7 @@ jobs:
contributors:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v5
- name: Install ruby version specified in .ruby-version
uses: ruby/setup-ruby@v1
with:
@@ -53,7 +53,7 @@ jobs:
steps:
- name: Checkout this repo
uses: actions/checkout@v6
uses: actions/checkout@v5
- name: Configure sysctl limits
run: |
@@ -89,7 +89,7 @@ jobs:
sudo apt-get -y install libpq-dev google-chrome-stable
- name: Install NodeJS
uses: actions/setup-node@v6
uses: actions/setup-node@v5
with:
node-version: '12'

View File

@@ -1,18 +1,30 @@
# This configuration was generated by
# `rubocop --auto-gen-config`
# on 2024-07-13 05:47:38 UTC using RuboCop version 1.65.0.
# on 2025-09-07 08:46:49 UTC using RuboCop version 1.80.2.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
# versions of RuboCop, may require this file to be generated again.
# Offense count: 231
# Configuration parameters: EnforcedStyle.
# SupportedStyles: link_or_button, strict
Capybara/ClickLinkOrButtonStyle:
Enabled: false
# Offense count: 2
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: TreatCommentsAsGroupSeparators, ConsiderPunctuation.
Bundler/OrderedGems:
Exclude:
- 'Gemfile'
# Offense count: 39
# Offense count: 18
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).
# Configuration parameters: DefaultSelector.
Capybara/RSpec/HaveSelector:
@@ -25,7 +37,6 @@ Capybara/RSpec/HaveSelector:
- 'spec/features/plantings/planting_a_crop_spec.rb'
- 'spec/features/seeds/adding_seeds_spec.rb'
- 'spec/features/shared_examples/crop_suggest.rb'
- 'spec/helpers/application_helper_spec.rb'
- 'spec/support/feature_helpers.rb'
- 'spec/views/posts/show.html.haml_spec.rb'
@@ -56,8 +67,7 @@ FactoryBot/AssociationStyle:
# Offense count: 3
# This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: AutoCorrect, Include, EnforcedStyle, ExplicitOnly.
# Include: **/*_spec.rb, **/spec/**/*, **/test/**/*, **/features/support/factories/**/*.rb
# Configuration parameters: EnforcedStyle, ExplicitOnly.
# SupportedStyles: create_list, n_times
FactoryBot/CreateList:
Exclude:
@@ -66,31 +76,29 @@ FactoryBot/CreateList:
- 'spec/views/posts/index.html.haml_spec.rb'
# Offense count: 4
# Configuration parameters: Include, MaxAmount.
# Include: **/*_spec.rb, **/spec/**/*, **/test/**/*, **/features/support/factories/**/*.rb
# Configuration parameters: MaxAmount.
FactoryBot/ExcessiveCreateList:
Exclude:
- 'spec/controllers/posts_controller_spec.rb'
- 'spec/features/crops/show_spec.rb'
- 'spec/features/percy/percy_spec.rb'
# Offense count: 1127
# Offense count: 1144
# This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: Include.
# Include: **/*_spec.rb, **/spec/**/*, **/test/**/*, **/features/support/factories/**/*.rb
FactoryBot/SyntaxMethods:
Enabled: false
# Offense count: 2
# Offense count: 3
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: Max, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns.
# Configuration parameters: Max, AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, IgnoreCopDirectives, AllowedPatterns, SplitStrings.
# URISchemes: http, https
Layout/LineLength:
Exclude:
- 'app/helpers/crops_helper.rb'
- 'app/models/concerns/predict_planting.rb'
- 'app/models/member.rb'
- 'db/seeds.rb'
# Offense count: 3
# Offense count: 4
# This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: RequireParenthesesForMethodChains.
Lint/AmbiguousRange:
@@ -98,14 +106,20 @@ Lint/AmbiguousRange:
- 'app/models/concerns/search_activities.rb'
- 'app/models/concerns/search_harvests.rb'
- 'app/models/concerns/search_plantings.rb'
- 'db/seeds.rb'
# Offense count: 2
# Configuration parameters: IgnoreLiteralBranches, IgnoreConstantBranches.
# Configuration parameters: IgnoreLiteralBranches, IgnoreConstantBranches, IgnoreDuplicateElseBranch.
Lint/DuplicateBranch:
Exclude:
- 'app/models/harvest.rb'
- 'lib/actions/oauth_signup_action.rb'
# Offense count: 1
Lint/DuplicateMethods:
Exclude:
- 'app/models/planting.rb'
# Offense count: 8
# Configuration parameters: AllowComments, AllowEmptyLambdas.
Lint/EmptyBlock:
@@ -124,12 +138,6 @@ Lint/RedundantCopDisableDirective:
Exclude:
- '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
# Configuration parameters: AllowComments, AllowNil.
Lint/SuppressedException:
@@ -137,14 +145,18 @@ Lint/SuppressedException:
- 'lib/tasks/testing.rake'
# Offense count: 7
# This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: AutoCorrect.
# This cop supports safe autocorrection (--autocorrect).
Lint/UselessAssignment:
Exclude:
- 'config.rb'
- 'config/compass.rb'
# Offense count: 52
# Offense count: 1
Lint/UselessConstantScoping:
Exclude:
- 'app/controllers/members_controller.rb'
# Offense count: 55
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes.
Metrics/AbcSize:
Max: 151
@@ -153,33 +165,42 @@ Metrics/AbcSize:
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns, inherit_mode.
# AllowedMethods: refine
Metrics/BlockLength:
Max: 115
Max: 116
# Offense count: 7
# Offense count: 9
# Configuration parameters: CountComments, CountAsOne.
Metrics/ClassLength:
Max: 188
Max: 181
# Offense count: 6
# Offense count: 8
# Configuration parameters: AllowedMethods, AllowedPatterns.
Metrics/CyclomaticComplexity:
Max: 32
# Offense count: 71
# Offense count: 73
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
Metrics/MethodLength:
Max: 127
Max: 128
# Offense count: 2
# Configuration parameters: CountComments, CountAsOne.
Metrics/ModuleLength:
Max: 125
Max: 132
# Offense count: 5
# Offense count: 7
# Configuration parameters: AllowedMethods, AllowedPatterns.
Metrics/PerceivedComplexity:
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
RSpec/AnyInstance:
Exclude:
@@ -204,7 +225,6 @@ RSpec/DescribedClass:
# Offense count: 13
# This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: AutoCorrect.
RSpec/EmptyExampleGroup:
Exclude:
- 'spec/controllers/authentications_controller_spec.rb'
@@ -220,17 +240,10 @@ RSpec/EmptyExampleGroup:
- 'spec/views/photos/edit.html.haml_spec.rb'
- 'spec/views/posts/_single.html.haml_spec.rb'
# Offense count: 1
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: AllowConsecutiveOneLiners.
RSpec/EmptyLineAfterExample:
Exclude:
- 'spec/models/ability_spec.rb'
# Offense count: 140
# Offense count: 137
# Configuration parameters: CountAsOne.
RSpec/ExampleLength:
Max: 25
Max: 27
# Offense count: 32
RSpec/ExpectInHook:
@@ -245,17 +258,8 @@ RSpec/ExpectInHook:
- 'spec/features/plantings/planting_a_crop_spec.rb'
- 'spec/features/shared_examples/append_date.rb'
# Offense count: 1
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle.
# SupportedStyles: implicit, each, example
RSpec/HookArgument:
Exclude:
- 'spec/requests/api/v1/plantings_request_spec.rb'
# Offense count: 2
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: AutoCorrect.
RSpec/HooksBeforeExamples:
Exclude:
- 'spec/features/crops/creating_a_crop_spec.rb'
@@ -276,21 +280,15 @@ RSpec/IndexedLet:
- 'spec/models/member_spec.rb'
- 'spec/views/forums/index.html.haml_spec.rb'
# Offense count: 720
# Offense count: 719
# Configuration parameters: AssignmentOnly.
RSpec/InstanceVariable:
Enabled: false
# Offense count: 40
# Offense count: 42
RSpec/LetSetup:
Enabled: false
# Offense count: 1
# This cop supports safe autocorrection (--autocorrect).
RSpec/MatchArray:
Exclude:
- 'spec/models/post_spec.rb'
# Offense count: 2
RSpec/MessageChain:
Exclude:
@@ -307,14 +305,14 @@ RSpec/MultipleDescribes:
Exclude:
- 'spec/features/crops/crop_wranglers_spec.rb'
# Offense count: 152
# Offense count: 149
RSpec/MultipleExpectations:
Max: 19
# Offense count: 138
# Offense count: 147
# Configuration parameters: AllowSubject.
RSpec/MultipleMemoizedHelpers:
Max: 20
Max: 14
# Offense count: 133
# Configuration parameters: EnforcedStyle, IgnoreSharedExamples.
@@ -322,12 +320,12 @@ RSpec/MultipleMemoizedHelpers:
RSpec/NamedSubject:
Enabled: false
# Offense count: 111
# Offense count: 110
# Configuration parameters: AllowedGroups.
RSpec/NestedGroups:
Max: 6
# Offense count: 403
# Offense count: 407
# Configuration parameters: AllowedPatterns.
# AllowedPatterns: ^expect_, ^assert_
RSpec/NoExpectationExample:
@@ -358,15 +356,13 @@ RSpec/RepeatedExampleGroupBody:
# Offense count: 6
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: AutoCorrect.
RSpec/ScatteredSetup:
Exclude:
- 'spec/features/percy/percy_spec.rb'
- 'spec/features/plantings/prediction_spec.rb'
# Offense count: 1
# Configuration parameters: Include, CustomTransform, IgnoreMethods, IgnoreMetadata.
# Include: **/*_spec.rb
# Configuration parameters: CustomTransform, IgnoreMethods, IgnoreMetadata.
RSpec/SpecFilePathFormat:
Exclude:
- 'spec/controllers/member_controller_spec.rb'
@@ -380,8 +376,6 @@ RSpec/StubbedMock:
# Offense count: 1
# This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: EnforcedStyle.
# SupportedStyles: constant, string
RSpec/VerifiedDoubleReference:
Exclude:
- 'spec/models/member_spec.rb'
@@ -411,30 +405,36 @@ RSpecRails/HaveHttpStatus:
RSpecRails/InferredSpecType:
Enabled: false
# Offense count: 28
# Configuration parameters: Database, Include.
# Offense count: 1
# This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: NilOrEmpty, NotPresent, UnlessPresent.
Rails/Blank:
Exclude:
- 'lib/tasks/wikidata.rake'
# Offense count: 29
# Configuration parameters: Database.
# SupportedDatabases: mysql, postgresql
# Include: db/**/*.rb
Rails/BulkChangeTable:
Enabled: false
# Offense count: 4
# Configuration parameters: Include.
# Include: db/**/*.rb
Rails/CreateTableWithTimestamps:
Exclude:
- 'db/migrate/20150201052245_create_cms.rb'
- 'db/migrate/20171022032108_all_the_predictions.rb'
# Offense count: 1
# Offense count: 3
# This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: EnforcedStyle, AllowToTime.
# SupportedStyles: strict, flexible
Rails/Date:
Exclude:
- 'app/controllers/activities_controller.rb'
- 'app/mailers/notifier_mailer.rb'
- 'app/models/concerns/search_seeds.rb'
# Offense count: 11
# Offense count: 12
# This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: AllowedMethods, AllowedPatterns.
# AllowedMethods: order, limit, select, lock
@@ -445,64 +445,55 @@ Rails/FindEach:
- 'db/migrate/20171129041341_create_photographings.rb'
- 'db/migrate/20190130090437_add_crop_to_photographings.rb'
- 'db/migrate/20191119030244_cms_tags.rb'
- 'lib/tasks/wikidata.rake'
# Offense count: 2
# Configuration parameters: Include.
# Include: app/models/**/*.rb
Rails/HasAndBelongsToMany:
Exclude:
- 'app/models/member.rb'
- 'app/models/role.rb'
# Offense count: 5
# Configuration parameters: Include.
# Include: app/models/**/*.rb
Rails/HasManyOrHasOneDependent:
Exclude:
- 'app/models/member.rb'
# Offense count: 1
# Configuration parameters: Include.
# Include: spec/**/*.rb, test/**/*.rb
Rails/I18nLocaleAssignment:
Exclude:
- 'spec/features/locale_spec.rb'
# Offense count: 33
# Offense count: 37
Rails/I18nLocaleTexts:
Enabled: false
# Offense count: 3
# Configuration parameters: Include.
# Include: app/controllers/**/*.rb, app/mailers/**/*.rb
Rails/LexicallyScopedActionFilter:
Exclude:
- 'app/controllers/data_controller.rb'
- 'app/controllers/registrations_controller.rb'
# Offense count: 1
# This cop supports unsafe autocorrection (--autocorrect-all).
Rails/OrderArguments:
Exclude:
- 'app/models/crop.rb'
# Offense count: 2
Rails/OutputSafety:
Exclude:
- 'app/helpers/auto_suggest_helper.rb'
- 'app/helpers/gardens_helper.rb'
# Offense count: 1
# This cop supports safe autocorrection (--autocorrect).
Rails/PluralizationGrammar:
Exclude:
- 'spec/requests/plantings_spec.rb'
# Offense count: 4
# This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: Include.
# Include: **/Rakefile, **/*.rake
Rails/RakeEnvironment:
Exclude:
- 'lib/tasks/hooks.rake'
- 'lib/tasks/i18n.rake'
- 'lib/tasks/testing.rake'
# Offense count: 9
# Offense count: 8
# This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: AllowedReceivers.
# AllowedReceivers: ActionMailer::Preview, ActiveSupport::TimeZone
@@ -513,7 +504,6 @@ Rails/RedundantActiveRecordAllMethod:
- 'app/controllers/forums_controller.rb'
- 'app/controllers/plant_parts_controller.rb'
- 'app/controllers/scientific_names_controller.rb'
- 'app/services/openfarm_service.rb'
- 'spec/features/percy/percy_spec.rb'
- 'spec/models/harvest_spec.rb'
@@ -528,8 +518,6 @@ Rails/RedundantPresenceValidationOnBelongsTo:
# Offense count: 15
# 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:
Exclude:
- 'spec/controllers/api/v1/plantings_controller_spec.rb'
@@ -543,29 +531,31 @@ Rails/ResponseParsedBody:
- 'spec/requests/api/v1/seeds_request_spec.rb'
# Offense count: 9
# Configuration parameters: Include.
# Include: db/**/*.rb
Rails/ReversibleMigration:
Exclude:
- 'db/migrate/20130326092227_change_planted_at_to_date.rb'
- 'db/migrate/20191119020643_upgrade_cms.rb'
# Offense count: 2
# Offense count: 3
# This cop supports unsafe autocorrection (--autocorrect-all).
Rails/RootPathnameMethods:
Exclude:
- 'app/controllers/crops_controller.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
# Configuration parameters: Include.
# Include: db/**/*.rb
Rails/ThreeStateBooleanColumn:
Enabled: false
# Offense count: 6
# Configuration parameters: Include.
# Include: app/models/**/*.rb
Rails/UniqueValidationWithoutIndex:
Exclude:
- 'app/models/follow.rb'
@@ -583,12 +573,13 @@ Rails/WhereEquals:
- 'app/models/harvest.rb'
- 'app/models/planting.rb'
# Offense count: 2
# Offense count: 3
# This cop supports unsafe autocorrection (--autocorrect-all).
Rails/WhereRange:
Exclude:
- 'app/models/concerns/predict_planting.rb'
- 'app/models/garden.rb'
- 'app/models/seed.rb'
# Offense count: 1
Rake/MethodDefinitionInTask:
@@ -597,8 +588,10 @@ Rake/MethodDefinitionInTask:
# Offense count: 3
# This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: EnforcedStyle.
# Configuration parameters: EnforcedStyle, EnforcedStyleForClasses, EnforcedStyleForModules.
# SupportedStyles: nested, compact
# SupportedStylesForClasses: ~, nested, compact
# SupportedStylesForModules: ~, nested, compact
Style/ClassAndModuleChildren:
Exclude:
- 'lib/actions/oauth_signup_action.rb'
@@ -614,7 +607,15 @@ Style/CommentedKeyword:
- 'spec/models/photo_spec.rb'
- 'spec/models/planting_spec.rb'
# Offense count: 3
# Offense count: 1
# 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).
# Configuration parameters: EnforcedStyle.
# SupportedStyles: always, always_true, never
@@ -622,23 +623,34 @@ Style/FrozenStringLiteralComment:
Exclude:
- '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/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'
# Offense count: 3
# Offense count: 2
# This cop supports unsafe autocorrection (--autocorrect-all).
Style/GlobalStdStream:
Exclude:
- 'config/environments/production.rb'
- 'lib/tasks/gbif.rake'
- 'lib/tasks/openfarm.rake'
# Offense count: 1
# This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: AllowedMethods.
# AllowedMethods: nonzero?
Style/IfWithBooleanLiteralBranches:
Style/HashFetchChain:
Exclude:
- 'app/controllers/gardens_controller.rb'
- 'app/models/concerns/open_farm_data.rb'
# Offense count: 2
# This cop supports unsafe autocorrection (--autocorrect-all).
Style/IdenticalConditionalBranches:
Exclude:
- 'lib/actions/oauth_signup_action.rb'
# Offense count: 1
# This cop supports unsafe autocorrection (--autocorrect-all).
@@ -676,11 +688,12 @@ Style/OpenStructUse:
Exclude:
- 'spec/helpers/event_helper_spec.rb'
# Offense count: 2
# Offense count: 3
# Configuration parameters: AllowedMethods.
# AllowedMethods: respond_to_missing?
Style/OptionalBooleanParameter:
Exclude:
- 'app/helpers/application_helper.rb'
- 'app/models/concerns/member_newsletter.rb'
# Offense count: 1
@@ -697,6 +710,26 @@ Style/RedundantFetchBlock:
Exclude:
- 'config/puma.rb'
# Offense count: 1
# This cop supports unsafe autocorrection (--autocorrect-all).
Style/RedundantInterpolation:
Exclude:
- 'app/helpers/buttons_helper.rb'
# Offense count: 1
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle.
# SupportedStyles: implicit, explicit
Style/RescueStandardError:
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.
@@ -705,17 +738,35 @@ Style/SoleNestedConditional:
- 'app/controllers/application_controller.rb'
- 'app/controllers/messages_controller.rb'
# Offense count: 24
# Offense count: 28
# This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: Mode.
Style/StringConcatenation:
Exclude:
- 'app/controllers/messages_controller.rb'
- 'app/helpers/application_helper.rb'
- 'app/helpers/buttons_helper.rb'
- 'app/models/photo.rb'
- 'config/initializers/rswag_api.rb'
- 'spec/helpers/gardens_helper_spec.rb'
- 'spec/helpers/seeds_helper_spec.rb'
# Offense count: 1
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle.
# SupportedStyles: single_quotes, double_quotes
Style/StringLiteralsInInterpolation:
Exclude:
- 'config/initializers/mailboxer.rb'
# Offense count: 1
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: .
# SupportedStyles: percent, brackets
Style/SymbolArray:
EnforcedStyle: percent
MinSize: 3
# Offense count: 1
# This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: AllowMethodsWithArguments, AllowedMethods, AllowedPatterns, AllowComments.

View File

@@ -187,12 +187,12 @@ end
group :test do
gem 'axe-core-capybara'
gem 'axe-core-rspec'
gem "percy-capybara", "~> 5.0.0"
gem 'rails-controller-testing'
gem "rspec-rebound"
gem 'selenium-webdriver'
gem 'timecop'
gem 'vcr'
gem "rspec-rebound"
gem "percy-capybara", "~> 5.0.0"
end
group :travis do
@@ -200,8 +200,3 @@ group :travis do
end
gem "i18n_data", "~> 1.1"
gem "paper_trail", "~> 17.0"
gem 'sitemap_generator'
gem 'aws-sdk-s3', '~> 1', '>= 1.114.0'

View File

@@ -33,49 +33,47 @@ GEM
GEM
remote: https://rubygems.org/
specs:
actioncable (7.2.3)
actionpack (= 7.2.3)
activesupport (= 7.2.3)
actioncable (7.2.2.2)
actionpack (= 7.2.2.2)
activesupport (= 7.2.2.2)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
zeitwerk (~> 2.6)
actionmailbox (7.2.3)
actionpack (= 7.2.3)
activejob (= 7.2.3)
activerecord (= 7.2.3)
activestorage (= 7.2.3)
activesupport (= 7.2.3)
actionmailbox (7.2.2.2)
actionpack (= 7.2.2.2)
activejob (= 7.2.2.2)
activerecord (= 7.2.2.2)
activestorage (= 7.2.2.2)
activesupport (= 7.2.2.2)
mail (>= 2.8.0)
actionmailer (7.2.3)
actionpack (= 7.2.3)
actionview (= 7.2.3)
activejob (= 7.2.3)
activesupport (= 7.2.3)
actionmailer (7.2.2.2)
actionpack (= 7.2.2.2)
actionview (= 7.2.2.2)
activejob (= 7.2.2.2)
activesupport (= 7.2.2.2)
mail (>= 2.8.0)
rails-dom-testing (~> 2.2)
actionpack (7.2.3)
actionview (= 7.2.3)
activesupport (= 7.2.3)
cgi
actionpack (7.2.2.2)
actionview (= 7.2.2.2)
activesupport (= 7.2.2.2)
nokogiri (>= 1.8.5)
racc
rack (>= 2.2.4, < 3.3)
rack (>= 2.2.4, < 3.2)
rack-session (>= 1.0.1)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6)
useragent (~> 0.16)
actiontext (7.2.3)
actionpack (= 7.2.3)
activerecord (= 7.2.3)
activestorage (= 7.2.3)
activesupport (= 7.2.3)
actiontext (7.2.2.2)
actionpack (= 7.2.2.2)
activerecord (= 7.2.2.2)
activestorage (= 7.2.2.2)
activesupport (= 7.2.2.2)
globalid (>= 0.6.0)
nokogiri (>= 1.8.5)
actionview (7.2.3)
activesupport (= 7.2.3)
actionview (7.2.2.2)
activesupport (= 7.2.2.2)
builder (~> 3.1)
cgi
erubi (~> 1.11)
rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6)
@@ -84,27 +82,27 @@ GEM
addressable
active_median (0.6.0)
activesupport (>= 7.1)
active_record_union (1.4.0)
activerecord (>= 6.0)
active_utils (3.6.0)
active_record_union (1.3.0)
activerecord (>= 4.0)
active_utils (3.5.0)
activesupport (>= 4.2)
i18n
activejob (7.2.3)
activesupport (= 7.2.3)
activejob (7.2.2.2)
activesupport (= 7.2.2.2)
globalid (>= 0.3.6)
activemodel (7.2.3)
activesupport (= 7.2.3)
activerecord (7.2.3)
activemodel (= 7.2.3)
activesupport (= 7.2.3)
activemodel (7.2.2.2)
activesupport (= 7.2.2.2)
activerecord (7.2.2.2)
activemodel (= 7.2.2.2)
activesupport (= 7.2.2.2)
timeout (>= 0.4.0)
activestorage (7.2.3)
actionpack (= 7.2.3)
activejob (= 7.2.3)
activerecord (= 7.2.3)
activesupport (= 7.2.3)
activestorage (7.2.2.2)
actionpack (= 7.2.2.2)
activejob (= 7.2.2.2)
activerecord (= 7.2.2.2)
activesupport (= 7.2.2.2)
marcel (~> 1.0)
activesupport (7.2.3)
activesupport (7.2.2.2)
base64
benchmark (>= 0.3)
bigdecimal
@@ -121,34 +119,15 @@ GEM
ast (2.4.3)
autoprefixer-rails (10.4.16.0)
execjs (~> 2)
aws-eventstream (1.4.0)
aws-partitions (1.1189.0)
aws-sdk-core (3.239.2)
aws-eventstream (~> 1, >= 1.3.0)
aws-partitions (~> 1, >= 1.992.0)
aws-sigv4 (~> 1.9)
base64
bigdecimal
jmespath (~> 1, >= 1.6.1)
logger
aws-sdk-kms (1.118.0)
aws-sdk-core (~> 3, >= 3.239.1)
aws-sigv4 (~> 1.5)
aws-sdk-s3 (1.205.0)
aws-sdk-core (~> 3, >= 3.234.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.5)
aws-sigv4 (1.12.1)
aws-eventstream (~> 1, >= 1.0.2)
axe-core-api (4.11.0)
axe-core-api (4.10.3)
dumb_delegator
ostruct
virtus
axe-core-capybara (4.11.0)
axe-core-api (= 4.11.0)
axe-core-capybara (4.10.3)
axe-core-api (= 4.10.3)
dumb_delegator
axe-core-rspec (4.11.0)
axe-core-api (= 4.11.0)
axe-core-rspec (4.10.3)
axe-core-api (= 4.10.3)
dumb_delegator
ostruct
virtus
@@ -158,12 +137,12 @@ GEM
thread_safe (~> 0.3, >= 0.3.1)
base64 (0.3.0)
bcrypt (3.1.20)
benchmark (0.5.0)
benchmark (0.4.1)
better_errors (2.10.1)
erubi (>= 1.0.0)
rack (>= 0.9.0)
rouge (>= 1.0.0)
bigdecimal (3.3.1)
bigdecimal (3.2.2)
bluecloth (2.2.0)
bonsai-elasticsearch-rails (7.0.1)
elasticsearch-model (< 8)
@@ -177,7 +156,7 @@ GEM
actionpack (>= 6.1)
activemodel (>= 6.1)
builder (3.3.0)
bullet (8.1.0)
bullet (8.0.8)
activesupport (>= 3.0.0)
uniform_notifier (~> 1.11)
byebug (12.0.0)
@@ -204,8 +183,7 @@ GEM
image_processing (~> 1.1)
marcel (~> 1.0.0)
ssrf_filter (~> 1.0)
cgi (0.5.0)
chartkick (5.2.1)
chartkick (5.2.0)
childprocess (5.0.0)
coderay (1.1.3)
coercible (1.0.0)
@@ -220,7 +198,7 @@ GEM
comfy_bootstrap_form (4.0.9)
rails (>= 5.0.0)
concurrent-ruby (1.3.5)
connection_pool (2.5.5)
connection_pool (2.5.3)
crass (1.0.6)
crowdin-api (1.12.0)
open-uri (>= 0.1.0, < 0.2.0)
@@ -230,7 +208,7 @@ GEM
gli (>= 2.7.0)
i18n (>= 0.6.4)
rubyzip (>= 1.0.0)
csv (3.3.5)
csv (3.3.1)
csv_shaper (1.4.0)
activesupport (>= 3.0.0)
csv
@@ -241,7 +219,7 @@ GEM
activerecord (>= 5.a)
database_cleaner-core (~> 2.0.0)
database_cleaner-core (2.0.1)
date (3.5.0)
date (3.4.1)
descendants_tracker (0.0.4)
thread_safe (~> 0.3, >= 0.3.1)
devise (4.9.4)
@@ -273,20 +251,20 @@ GEM
elasticsearch-transport (7.0.0)
faraday
multi_json
erb (6.0.0)
erb (5.0.2)
erubi (1.13.1)
erubis (2.7.0)
excon (1.2.5)
logger
execjs (2.10.0)
factory_bot (6.5.5)
factory_bot (6.5.4)
activesupport (>= 6.1.0)
factory_bot_rails (6.5.1)
factory_bot_rails (6.5.0)
factory_bot (~> 6.5)
railties (>= 6.1.0)
faker (3.5.2)
i18n (>= 1.8.11, < 2)
faraday (2.14.0)
faraday (2.13.4)
faraday-net_http (>= 2.0, < 3.5)
json
logger
@@ -299,7 +277,7 @@ GEM
friendly_id (5.5.1)
activerecord (>= 4.0.0)
gbifrb (0.2.0)
geocoder (1.8.6)
geocoder (1.8.5)
base64 (>= 0.1.0)
csv (>= 3.0.0)
gibbon (1.2.1)
@@ -307,21 +285,21 @@ GEM
multi_json (>= 1.9.0)
gli (2.22.2)
ostruct
globalid (1.3.0)
globalid (1.2.1)
activesupport (>= 6.1)
gravatar-ultimate (2.0.0)
activesupport (>= 2.3.14)
rack
haml (7.0.2)
haml (6.3.0)
temple (>= 0.8.2)
thor
tilt
haml-rails (3.0.0)
haml-rails (2.1.0)
actionpack (>= 5.1)
activesupport (>= 5.1)
haml (>= 4.0.6)
railties (>= 5.1)
haml_lint (0.67.0)
haml_lint (0.66.0)
haml (>= 5.0)
parallel (~> 1.10)
rainbow
@@ -346,21 +324,20 @@ GEM
multi_xml (>= 0.5.2)
i18n (1.14.7)
concurrent-ruby (~> 1.0)
i18n-tasks (1.1.2)
i18n-tasks (1.0.15)
activesupport (>= 4.0.2)
ast (>= 2.1.0)
erubi
highline (>= 3.0.0)
highline (>= 2.0.0)
i18n
parser (>= 3.2.2.1)
prism
rails-i18n
rainbow (>= 2.2.2, < 4.0)
ruby-progressbar (~> 1.8, >= 1.8.1)
terminal-table (>= 1.5.1)
i18n_data (1.1.0)
simple_po_parser (~> 1.1)
icalendar (2.12.1)
icalendar (2.11.2)
base64
ice_cube (~> 0.16)
logger
@@ -371,19 +348,17 @@ GEM
mini_magick (>= 4.9.5, < 5)
ruby-vips (>= 2.0.17, < 3)
io-console (0.8.1)
irb (1.15.3)
irb (1.15.2)
pp (>= 0.6.0)
rdoc (>= 4.0.0)
reline (>= 0.4.2)
jmespath (1.6.2)
jquery-rails (4.6.1)
jquery-rails (4.6.0)
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
json (2.16.0)
json-schema (6.0.0)
json (2.13.2)
json-schema (5.1.0)
addressable (~> 2.8)
bigdecimal (~> 3.1)
jsonapi-resources (0.10.7)
activerecord (>= 4.1)
concurrent-ruby
@@ -409,8 +384,7 @@ GEM
loofah (2.24.1)
crass (~> 1.0.2)
nokogiri (>= 1.12.0)
mail (2.9.0)
logger
mail (2.8.1)
mini_mime (>= 0.1.1)
net-imap
net-pop
@@ -437,7 +411,7 @@ GEM
mini_magick (4.12.0)
mini_mime (1.1.5)
mini_portile2 (2.8.9)
minitest (5.26.2)
minitest (5.25.5)
moneta (1.0.0)
msgpack (1.8.0)
multi_json (1.15.0)
@@ -445,7 +419,7 @@ GEM
bigdecimal (~> 3.1)
net-http (0.6.0)
uri
net-imap (0.5.12)
net-imap (0.5.9)
date
net-protocol
net-pop (0.1.2)
@@ -455,14 +429,14 @@ GEM
net-smtp (0.5.1)
net-protocol
netrc (0.11.0)
nio4r (2.7.5)
nokogiri (1.18.10)
nio4r (2.7.4)
nokogiri (1.18.9)
mini_portile2 (~> 2.8.2)
racc (~> 1.4)
nokogiri (1.18.10-x86_64-linux-gnu)
nokogiri (1.18.9-x86_64-linux-gnu)
racc (~> 1.4)
oauth (0.5.6)
oj (3.16.12)
oj (3.16.11)
bigdecimal (>= 3.0)
ostruct (>= 0.2)
omniauth (1.9.2)
@@ -477,11 +451,8 @@ GEM
open-uri (0.1.0)
orm_adapter (0.5.0)
ostruct (0.6.3)
paper_trail (17.0.0)
activerecord (>= 7.1)
request_store (~> 1.4)
parallel (1.27.0)
parser (3.3.10.0)
parser (3.3.9.0)
ast (~> 2.4.1)
racc
percy-capybara (5.0.0)
@@ -493,22 +464,22 @@ GEM
moneta (~> 1.0.0)
rate_throttle_client (~> 0.1.0)
popper_js (2.11.8)
pp (0.6.3)
pp (0.6.2)
prettyprint
prettyprint (0.2.0)
prism (1.6.0)
prism (1.4.0)
pry (0.15.2)
coderay (~> 1.1)
method_source (~> 1.0)
psych (5.2.6)
date
stringio
public_suffix (6.0.2)
puma (7.1.0)
public_suffix (6.0.1)
puma (7.0.0)
nio4r (~> 2.0)
query_diet (0.7.3)
query_diet (0.7.2)
racc (1.8.1)
rack (2.2.21)
rack (2.2.17)
rack-cors (2.0.2)
rack (>= 2.0.0)
rack-protection (3.2.0)
@@ -521,20 +492,20 @@ GEM
rackup (1.0.1)
rack (< 3)
webrick
rails (7.2.3)
actioncable (= 7.2.3)
actionmailbox (= 7.2.3)
actionmailer (= 7.2.3)
actionpack (= 7.2.3)
actiontext (= 7.2.3)
actionview (= 7.2.3)
activejob (= 7.2.3)
activemodel (= 7.2.3)
activerecord (= 7.2.3)
activestorage (= 7.2.3)
activesupport (= 7.2.3)
rails (7.2.2.2)
actioncable (= 7.2.2.2)
actionmailbox (= 7.2.2.2)
actionmailer (= 7.2.2.2)
actionpack (= 7.2.2.2)
actiontext (= 7.2.2.2)
actionview (= 7.2.2.2)
activejob (= 7.2.2.2)
activemodel (= 7.2.2.2)
activerecord (= 7.2.2.2)
activestorage (= 7.2.2.2)
activesupport (= 7.2.2.2)
bundler (>= 1.15.0)
railties (= 7.2.3)
railties (= 7.2.2.2)
rails-controller-testing (1.0.5)
actionpack (>= 5.0.1.rc1)
actionview (>= 5.0.1.rc1)
@@ -554,44 +525,39 @@ GEM
rails_stdout_logging
rails_serve_static_assets (0.0.5)
rails_stdout_logging (0.0.5)
railties (7.2.3)
actionpack (= 7.2.3)
activesupport (= 7.2.3)
cgi
railties (7.2.2.2)
actionpack (= 7.2.2.2)
activesupport (= 7.2.2.2)
irb (~> 1.13)
rackup (>= 1.0.0)
rake (>= 12.2)
thor (~> 1.0, >= 1.2.2)
tsort (>= 0.2)
zeitwerk (~> 2.6)
rainbow (3.1.1)
raindrops (0.20.1)
rake (13.3.1)
rake (13.3.0)
rate_throttle_client (0.1.2)
rb-fsevent (0.11.2)
rb-inotify (0.10.1)
ffi (~> 1.0)
rdoc (6.16.1)
rdoc (6.14.2)
erb
psych (>= 4.0.0)
tsort
recaptcha (5.21.1)
recaptcha (5.20.1)
redis-client (0.23.2)
connection_pool
regexp_parser (2.11.3)
reline (0.6.3)
regexp_parser (2.11.2)
reline (0.6.2)
io-console (~> 0.5)
request_store (1.7.0)
rack (>= 1.4)
responders (3.2.0)
actionpack (>= 7.0)
railties (>= 7.0)
responders (3.1.1)
actionpack (>= 5.2)
railties (>= 5.2)
rest-client (2.1.0)
http-accept (>= 1.7.0, < 2.0)
http-cookie (>= 1.0.2, < 2.0)
mime-types (>= 1.16, < 4.0)
netrc (~> 0.8)
rexml (3.4.4)
rexml (3.4.1)
rouge (4.1.2)
rspec (3.13.0)
rspec-core (~> 3.13.0)
@@ -601,7 +567,7 @@ GEM
activemodel (>= 3.0)
activesupport (>= 3.0)
rspec-mocks (>= 2.99, < 4.0)
rspec-core (3.13.6)
rspec-core (3.13.5)
rspec-support (~> 3.13.0)
rspec-expectations (3.13.5)
diff-lcs (>= 1.2.0, < 2.0)
@@ -619,23 +585,23 @@ GEM
rspec-support (~> 3.13)
rspec-rebound (0.2.1)
rspec-core (~> 3.3)
rspec-support (3.13.6)
rspec-support (3.13.4)
rspectre (0.2.0)
parser (>= 3.3.7.1)
prism (~> 1.3)
rspec (~> 3.10)
rswag-api (2.17.0)
activesupport (>= 5.2, < 8.2)
railties (>= 5.2, < 8.2)
rswag-specs (2.17.0)
activesupport (>= 5.2, < 8.2)
json-schema (>= 2.2, < 7.0)
railties (>= 5.2, < 8.2)
rswag-api (2.16.0)
activesupport (>= 5.2, < 8.1)
railties (>= 5.2, < 8.1)
rswag-specs (2.16.0)
activesupport (>= 5.2, < 8.1)
json-schema (>= 2.2, < 6.0)
railties (>= 5.2, < 8.1)
rspec-core (>= 2.14)
rswag-ui (2.17.0)
actionpack (>= 5.2, < 8.2)
railties (>= 5.2, < 8.2)
rubocop (1.81.7)
rswag-ui (2.16.0)
actionpack (>= 5.2, < 8.1)
railties (>= 5.2, < 8.1)
rubocop (1.80.2)
json (~> 2.3)
language_server-protocol (~> 3.17.0.2)
lint_roller (~> 1.1.0)
@@ -643,19 +609,19 @@ GEM
parser (>= 3.3.0.2)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 2.9.3, < 3.0)
rubocop-ast (>= 1.47.1, < 2.0)
rubocop-ast (>= 1.46.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 4.0)
rubocop-ast (1.48.0)
rubocop-ast (1.46.0)
parser (>= 3.3.7.2)
prism (~> 1.4)
rubocop-capybara (2.22.1)
lint_roller (~> 1.1)
rubocop (~> 1.72, >= 1.72.1)
rubocop-factory_bot (2.28.0)
rubocop-factory_bot (2.27.1)
lint_roller (~> 1.1)
rubocop (~> 1.72, >= 1.72.1)
rubocop-rails (2.34.2)
rubocop-rails (2.33.3)
activesupport (>= 4.2.0)
lint_roller (~> 1.1)
rack (>= 1.1)
@@ -664,10 +630,10 @@ GEM
rubocop-rake (0.7.1)
lint_roller (~> 1.1)
rubocop (>= 1.72.1)
rubocop-rspec (3.8.0)
rubocop-rspec (3.7.0)
lint_roller (~> 1.1)
rubocop (~> 1.81)
rubocop-rspec_rails (2.32.0)
rubocop (~> 1.72, >= 1.72.1)
rubocop-rspec_rails (2.31.0)
lint_roller (~> 1.1)
rubocop (~> 1.72, >= 1.72.1)
rubocop-rspec (~> 3.5)
@@ -675,7 +641,7 @@ GEM
ruby-units (4.1.0)
ruby-vips (2.2.1)
ffi (~> 1.12)
rubyzip (3.2.1)
rubyzip (3.0.1)
sass (3.7.4)
sass-listen (~> 4.0.0)
sass-listen (4.0.0)
@@ -689,13 +655,13 @@ GEM
sprockets (> 3.0)
sprockets-rails
tilt
scout_apm (5.8.0)
scout_apm (5.7.1)
parser
searchkick (5.3.1)
activemodel (>= 6.1)
hashie
securerandom (0.4.1)
selenium-webdriver (4.38.0)
selenium-webdriver (4.35.0)
base64 (~> 0.2)
logger (~> 1.4)
rexml (~> 3.2, >= 3.2.5)
@@ -708,8 +674,6 @@ GEM
rack (>= 2.2.4)
redis-client (>= 0.22.2)
simple_po_parser (1.1.6)
sitemap_generator (6.3.0)
builder (~> 3.0)
sprockets (3.7.5)
base64
concurrent-ruby (~> 1.0)
@@ -719,7 +683,7 @@ GEM
activesupport (>= 5.2)
sprockets (>= 3.0.0)
ssrf_filter (1.1.2)
stringio (3.1.8)
stringio (3.1.7)
sysexits (1.2.0)
temple (0.10.4)
terminal-table (4.0.0)
@@ -730,17 +694,16 @@ GEM
thread_safe (0.3.6)
tilt (2.6.1)
timecop (0.9.10)
timeout (0.4.4)
tsort (0.2.0)
timeout (0.4.3)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
unicode-display_width (3.2.0)
unicode-emoji (~> 4.1)
unicode-emoji (4.1.0)
unicode-display_width (3.1.5)
unicode-emoji (~> 4.0, >= 4.0.4)
unicode-emoji (4.0.4)
unicorn (6.1.0)
kgio (~> 2.6)
raindrops (~> 0.7)
uniform_notifier (1.18.0)
uniform_notifier (1.17.0)
uri (1.0.3)
useragent (0.16.11)
validate_url (1.0.15)
@@ -758,7 +721,7 @@ GEM
nokogiri (>= 1.2.0)
rack (>= 1.0)
rack-test (>= 0.5.3)
webrick (1.9.2)
webrick (1.9.1)
websocket (1.2.11)
websocket-driver (0.8.0)
base64
@@ -781,7 +744,6 @@ DEPENDENCIES
active_median
active_record_union
active_utils
aws-sdk-s3 (~> 1, >= 1.114.0)
axe-core-capybara
axe-core-rspec
better_errors
@@ -841,7 +803,6 @@ DEPENDENCIES
oj
omniauth (~> 1.3)
omniauth-flickr (>= 0.0.15)
paper_trail (~> 17.0)
percy-capybara (~> 5.0.0)
pg
platform-api
@@ -877,7 +838,6 @@ DEPENDENCIES
searchkick
selenium-webdriver
sidekiq
sitemap_generator
sprockets (< 4)
terser
timecop

View File

@@ -25,6 +25,7 @@ Vibe Coding is more than okay, just make sure you indicate if you have done so a
* [Issues](https://github.com/orgs/Growstuff/projects/1) (features we're
working on, known bugs, etc)
* [![Gitter](https://badges.gitter.im/Growstuff/growstuff.svg)](https://gitter.im/Growstuff/growstuff?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
* [Wiki](https://github.com/Growstuff/growstuff/wiki) (general documentation, etc.)
## For coders

View File

@@ -16,27 +16,3 @@
.homepage--list-item {
height: 100px;
}
.releases {
.card {
.card-header {
}
.card-body {
h2 {
background-color: transparent;
color: black;
box-shadow: none;
}
img {
border: 0.5em solid #111;
margin-left: 5%;
margin-right: 5%;
width: 90%;
}
ul {
margin-bottom: 1em;
margin-top: 1em;
}
}
}
}

View File

@@ -24,17 +24,6 @@ class ActivitiesController < DataController
end
def show
if @activity.finished? && @activity.owner == current_member && (@activity.updated_at + 2.weeks) > Time.now
@repeat_link = new_activity_path(
name: @activity.name,
garden_id: @activity.garden_id,
planting_id: @activity.planting_id,
category: @activity.category,
description: @activity.description,
due_date: 2.weeks.from_now.to_date
)
end
respond_with @activity
end
@@ -43,10 +32,6 @@ class ActivitiesController < DataController
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]
@activity.garden = Garden.find_by(
owner: current_member,
@@ -73,21 +58,7 @@ class ActivitiesController < DataController
def create
@activity = Activity.new(activity_params)
@activity.owner = current_member
@activity.due_date ||= Date.today
if @activity.save
if params[:repeat_times].to_i > 0
repeat_times = params[:repeat_times].to_i
repeat_weeks = params[:repeat_weeks].to_i
repeat_times.times do |i|
new_activity = @activity.dup
new_activity.due_date = @activity.due_date + (i + 1) * repeat_weeks.weeks
new_activity.save
end
end
end
@activity.save
respond_with @activity
end
@@ -106,8 +77,7 @@ class ActivitiesController < DataController
def activity_params
params.require(:activity).permit(
:name, :description, :category, :finished,
:garden_id, :planting_id, :due_date,
:repeat_times, :repeat_weeks
:garden_id, :planting_id, :due_date
)
end

View File

@@ -1,40 +0,0 @@
# frozen_string_literal: true
module Admin
class CropCompanionsController < AdminController
before_action :set_crop
def index
@crop_companions = @crop.crop_companions
end
def new
@crop_companion = @crop.crop_companions.new
end
def create
@crop_companion = @crop.crop_companions.new(crop_companion_params)
if @crop_companion.save
redirect_to admin_crop_crop_companions_path(@crop), notice: 'Companion was successfully created.'
else
render :new
end
end
def destroy
@crop_companion = @crop.crop_companions.find(params[:id])
@crop_companion.destroy
redirect_to admin_crop_crop_companions_path(@crop), notice: 'Companion was successfully destroyed.'
end
private
def set_crop
@crop = Crop.find_by!(slug: params[:crop_slug])
end
def crop_companion_params
params.require(:crop_companion).permit(:crop_b_id, :source_url)
end
end
end

View File

@@ -1,19 +0,0 @@
# frozen_string_literal: true
class Admin::CropsController < ApplicationController
before_action :authenticate_member!
before_action :authorize_admin!
def index
@versions = PaperTrail::Version.where(item_type: 'Crop').order(created_at: :desc).limit(100)
member_ids = @versions.map(&:whodunnit).compact.map(&:to_i)
@members = Member.where(id: member_ids).index_by(&:id)
@crop_wranglers = Role.crop_wranglers
end
private
def authorize_admin!
authorize! :wrangle, Crop
end
end

View File

@@ -1,24 +0,0 @@
# frozen_string_literal: true
module Admin
class VersionsController < ApplicationController
before_action :authenticate_member!
before_action :authorize_admin!
def revert
@version = PaperTrail::Version.find(params[:id])
@object = @version.reify
if @object.save
redirect_to admin_crops_path, notice: "Reverted to version from #{@version.created_at.strftime('%B %d, %Y')}"
else
redirect_to admin_crops_path, alert: "Could not revert to version from #{@version.created_at.strftime('%B %d, %Y')}. Errors: #{@object.errors.full_messages.to_sentence}"
end
end
private
def authorize_admin!
authorize! :wrangle, Crop
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
class BaseController < JSONAPI::ResourceController
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

View File

@@ -73,8 +73,6 @@ class CropsController < ApplicationController
format.html do
@posts = @crop.posts.order(created_at: :desc).paginate(page: params[:page])
@companions = @crop.companions.approved
member_ids = @crop.versions.map(&:whodunnit).compact.map(&:to_i)
@version_members = Member.where(id: member_ids).index_by(&:id)
end
format.svg do
icon_data = @crop.svg_icon.presence || File.read(Rails.root.join("app/assets/images/icons/sprout.svg"))
@@ -149,34 +147,6 @@ class CropsController < ApplicationController
respond_with @crop
end
def data_improvement
@active_tab = params[:tab] || 'photos'
@crops = case @active_tab
when 'photos'
Crop.approved.where(photo_associations_count: 0).order(plantings_count: :desc)
when 'descriptions'
Crop.approved.where(description: [nil, '']).order(plantings_count: :desc)
when 'youtube'
Crop.approved.where(en_youtube_url: [nil, '']).order(plantings_count: :desc)
when 'alternate_names'
Crop.approved.left_joins(:alternate_names).where(alternate_names: { id: nil }).order(plantings_count: :desc)
when 'wikidata'
crops_with_wikidata = Crop.joins(:scientific_names).where.not(scientific_names: { wikidata_id: nil }).distinct
Crop.approved.where.not(id: crops_with_wikidata).order(plantings_count: :desc)
when 'row_spacing'
Crop.approved.where(row_spacing: nil).order(plantings_count: :desc)
when 'sun_requirements'
Crop.approved.where(sun_requirements: [nil, '']).order(plantings_count: :desc)
when 'height'
Crop.approved.where(height: nil).order(plantings_count: :desc)
when 'public_food_key'
Crop.approved.where(public_food_key: [nil, '']).order(plantings_count: :desc)
else
Crop.none
end
end
private
def notifier
@@ -218,14 +188,10 @@ class CropsController < ApplicationController
def crop_params
params.require(:crop).permit(
:name, :en_wikipedia_url, :en_youtube_url,
:name, :en_wikipedia_url,
:parent_id, :perennial,
:request_notes, :reason_for_rejection,
:rejection_notes,
:description,
:public_food_key,
:row_spacing, :spread, :height,
:sowing_method, :sun_requirements, :growing_degree_days,
scientific_names_attributes: %i(scientific_name _destroy id)
)
end

View File

@@ -20,7 +20,6 @@ class GardensController < DataController
def show
@current_plantings = @garden.plantings.current.where.not(failed: true).includes(:crop, :owner).order(planted_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)
@suggested_companions = Crop.approved.where(
id: CropCompanion.where(crop_a_id: @current_plantings.select(:crop_id)).select(:crop_b_id)
@@ -39,10 +38,7 @@ class GardensController < DataController
def create
@garden.owner_id = current_member.id
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
flash[:notice] = I18n.t('gardens.created') if @garden.save
respond_with(@garden)
end

View File

@@ -37,7 +37,6 @@ class PlantingsController < DataController
@photos = @planting.photos.includes(:owner).order(date_taken: :desc)
@harvests = Harvest.search(where: { planting_id: @planting.id })
@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
@crop = @planting.crop
@@ -46,12 +45,6 @@ class PlantingsController < DataController
.where.not(id: @planting.id)
.includes(:owner, :crop, :garden)
.limit(6)
if @planting.finished? && @planting.garden.plantings.current.none? && (@planting.updated_at + 2.weeks) > Time.zone.now
@cultivate_soil_link = new_activity_path(name: 'Cultivate soil', garden_id: @planting.garden_id, category: "Soil Cultivation",
description: "Recently finished #{@planting.crop.name} planting. Prepare for next planting.")
end
respond_with @planting
end

View File

@@ -38,12 +38,6 @@ class RegistrationsController < Devise::RegistrationsController
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
if @member.valid_password?(params.require(:member)[:current_password])
@member.discard

View File

@@ -74,7 +74,7 @@ class ScientificNamesController < ApplicationController
end
def scientific_name_params
params.require(:scientific_name).permit(:crop_id, :name, :gbif_key, :wikidata_id)
params.require(:scientific_name).permit(:crop_id, :name, :gbif_key)
end
def gbif_service

View File

@@ -1,6 +1,5 @@
# frozen_string_literal: true
require 'nokogiri'
module ApplicationHelper
def parse_date(str)
str ||= '' # Date.parse barfs on nil
@@ -39,9 +38,9 @@ module ApplicationHelper
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
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:)}"
'in ' + distance_of_time_in_words(from_time, to_time, include_seconds:)
end
def count_github_contibutors
@@ -120,22 +119,4 @@ module ApplicationHelper
def og_description(description)
strip_tags(description).split(' ')[0..20].join(' ')
end
def github_releases
return [] if Rails.env.test?
feed_url = 'https://github.com/Growstuff/growstuff/releases.atom'
Rails.cache.fetch(feed_url, expires_in: 1.day) do
response = Faraday.get(feed_url)
doc = Nokogiri::XML(response.body)
doc.xpath('//xmlns:entry').first(2).map do |entry|
{
title: entry.xpath('xmlns:title').text,
content: entry.xpath('xmlns:content').text,
link: entry.xpath('xmlns:link/@href').text,
updated: entry.xpath('xmlns:updated').text
}
end
end
end
end

View File

@@ -85,20 +85,7 @@ module ButtonsHelper
end
def activity_edit_button(activity, classes: "btn btn-raised btn-info")
edit_button(edit_activity_path(slug: activity.slug), classes:)
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
edit_button(edit_activity_path(activity), classes:)
end
def activity_finish_button(activity, classes: 'btn btn-default btn-secondary')

View File

@@ -1,19 +1,6 @@
# frozen_string_literal: true
module CropsHelper
def crop_or_parent(crop, attribute)
default = crop.send(attribute)
return default if default.present?
parent = crop
while parent = parent.parent
return parent.send(attribute) if parent&.send(attribute).present?
end
# For scopes, arrays, etc return the empty value
default
end
def display_seed_availability(member, crop)
seeds = member.seeds.where(crop:)
total_quantity = seeds.where.not(quantity: nil).sum(:quantity)
@@ -30,63 +17,4 @@ module CropsHelper
def crop_ebay_seeds_url(crop)
"https://www.ebay.com/sch/i.html?_nkw=#{CGI.escape crop.name}"
end
def youtube_video_id(url)
return unless url
regex = %r{(?:youtube(?:-nocookie)?\.com/(?:[^/\n\s]+/\S+/|(?:v|e(?:mbed)?)/|\S*?[?&]v=)|youtu\.be/)([a-zA-Z0-9_-]{11})}
match = url.match(regex)
match[1] if match
end
def crop_jsonld_data(crop, full_attributes: true)
same_as_urls = [crop.en_wikipedia_url]
crop.scientific_names.each do |scientific_name|
same_as_urls << "https://www.wikidata.org/wiki/#{scientific_name.wikidata_id}" if scientific_name.wikidata_id.present?
end
subject_of_entities = []
if full_attributes
if crop.en_youtube_url.present?
subject_of_entities << {
'@type': "VideoObject",
url: crop.en_youtube_url
}
end
crop.posts.each do |post|
subject_of_entities << {
'@type': "SocialMediaPosting",
url: post_url(post),
author: {
'@type': 'Person',
name: post.author.login_name
},
'datePublished': post.created_at
}
end
images = []
crop.photos.each do |photo|
images << photo.fullsize_url
end
end
# TODO: Review plantings, seeds, harvests as a subtype of social media post or event that ended? Or creative work?
# has_many :plantings, dependent: :destroy
# has_many :seeds, dependent: :destroy
# has_many :harvests, dependent: :destroy
{
'@context': "https://schema.org",
'@type': "BioChemEntity",
name: crop.name,
taxonomicRange: crop.scientific_names.map(&:name),
description: crop.description,
sameAs: same_as_urls,
alternateName: crop.alternate_names.map(&:name),
subjectOf: subject_of_entities,
image: images
}.compact
end
end

View File

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

View File

@@ -76,7 +76,6 @@ class Ability
if member.role? :crop_wrangler
can :wrangle, Crop
can :manage, Crop
can :manage, CropCompanion
can :manage, ScientificName
can :manage, AlternateName
can :openfarm, Crop

View File

@@ -30,20 +30,4 @@ class Activity < ApplicationRecord
def to_s
name
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

View File

@@ -1,8 +0,0 @@
# frozen_string_literal: true
class AustralianFoodClassificationData < ApplicationRecord
belongs_to :crop,
foreign_key: :public_food_key,
primary_key: :public_food_key,
inverse_of: :australian_food_classification_data
end

View File

@@ -8,6 +8,14 @@ module OpenFarmData
fetch_attr('main_image_path')
end
def height
fetch_attr('height')
end
def spread
fetch_attr('spread')
end
def svg_icon
icon = fetch_attr('svg_icon')
return icon if icon.present?
@@ -19,6 +27,14 @@ module OpenFarmData
fetch_attr('tags_array')
end
def description
fetch_attr('description')
end
def row_spacing
fetch_attr('row_spacing')
end
def common_names
fetch_attr('common_names')
end
@@ -27,10 +43,22 @@ module OpenFarmData
fetch_attr('binomial_name')
end
def sowing_method
fetch_attr('sowing_method')
end
def main_image_path
fetch_attr('main_image_path')
end
def sun_requirements
fetch_attr('sun_requirements')
end
def growing_degree_days
fetch_attr('growing_degree_days')
end
def processing_pictures
fetch_attr('processing_pictures')
end
@@ -39,6 +67,6 @@ module OpenFarmData
def fetch_attr(key)
return if openfarm_data.blank?
openfarm_data.dig('attributes', key)
openfarm_data.fetch('attributes', {}).fetch(key, nil)
end
end

View File

@@ -1,7 +1,6 @@
# frozen_string_literal: true
class Crop < ApplicationRecord
has_paper_trail
extend FriendlyId
include PhotoCapable
include OpenFarmData
@@ -28,10 +27,6 @@ class Crop < ApplicationRecord
has_many :companions, through: :crop_companions, source: :crop_b, class_name: 'Crop'
has_many :crop_posts, dependent: :delete_all
has_many :posts, through: :crop_posts, dependent: :delete_all
has_one :australian_food_classification_data,
foreign_key: :public_food_key,
primary_key: :public_food_key,
inverse_of: :crop
accepts_nested_attributes_for :scientific_names, allow_destroy: true, reject_if: :all_blank
@@ -60,12 +55,6 @@ class Crop < ApplicationRecord
message: 'is not a valid English Wikipedia URL'
},
if: :approved?
validates :en_youtube_url,
format: {
with: %r{\A(?:https?://)?(?:www\.)?(?:youtube(?:-nocookie)?\.com/(?:(?:v|e(?:mbed)?)/|\S*?[?&]v=)|youtu\.be/)[a-zA-Z0-9_-]{11}(?:[?&]\S*)?\z},
message: 'is not a valid YouTube URL'
},
allow_blank: true
validates :name, uniqueness: { scope: :approval_status }, if: :pending?
def to_s
@@ -164,20 +153,8 @@ class Crop < ApplicationRecord
where(["lower(crops.name) = :value", { value: name.downcase }])
end
def all_companions
return companions unless parent
(companions + parent.all_companions).uniq
end
before_destroy :destroy_reverse_companionships
private
def destroy_reverse_companionships
CropCompanion.where(crop_b: self).destroy_all
end
def count_uses_of_property(col_name)
plantings.unscoped
.where(crop_id: id)

View File

@@ -26,20 +26,6 @@ class Member < ApplicationRecord
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 :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 :likes, dependent: :destroy
@@ -109,8 +95,7 @@ class Member < ApplicationRecord
}
validates :website_url, format: { with: %r{\Ahttps?://}, message: "must start with http:// or https://" }, allow_blank: true
validates :other_url, format: { with: %r{\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
validates :instagram_handle, :facebook_handle, :bluesky_handle, format: { without: %r{\Ahttps?://|/}, message: "should be a handle, not a URL" }, allow_blank: true
#
# Triggers

View File

@@ -47,7 +47,7 @@ class Photo < ApplicationRecord
info = flickr.photos.getInfo(photo_id: source_id)
licenses = flickr.photos.licenses.getInfo
license = licenses.find { |l| l.id.to_i == info.license.to_i }
Rails.logger.error("Cannot find license: #{[info.license, licenses].inspect}") unless license
Rails.logger.error("Cannot find license: " + [info.license, licenses].inspect) unless license
{
title: calculate_title(info),
license_name: license.name,

View File

@@ -25,8 +25,6 @@ class Planting < ApplicationRecord
has_many :harvests, dependent: :destroy
has_many :activities, dependent: :destroy
scope :current, -> { where.not(finished: true).where.not(failed: true) }
#
# Ancestry of food
belongs_to :parent_seed, class_name: 'Seed', # parent,

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', always_include_linkage_data: true
has_one :garden, always_include_linkage_data: true
has_one :planting, always_include_linkage_data: true
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 V1
class CropResource < BaseResource
immutable # TODO: Re-evaluate this later
immutable
filter :approval_status, default: 'approved'
has_many :plantings
@@ -12,7 +13,7 @@ module Api
has_many :photos
has_one :parent, class_name: 'Crop', always_include_linkage_data: true
has_one :parent, class_name: 'Crop'
attribute :name
attribute :en_wikipedia_url

View File

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

View File

@@ -3,17 +3,11 @@
module Api
module V1
class HarvestResource < BaseResource
before_save do
@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
immutable
has_one :crop, always_include_linkage_data: true
has_one :planting, always_include_linkage_data: true
has_one :owner, class_name: 'Member', always_include_linkage_data: true
# has_one :plant_part
has_one :crop
has_one :planting
has_one :owner, class_name: 'Member'
has_many :photos
attribute :harvested_at
@@ -22,15 +16,6 @@ module Api
attribute :weight_quantity
attribute :weight_unit
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

View File

@@ -9,7 +9,6 @@ module Api
has_many :plantings, foreign_key: 'owner_id'
has_many :harvests, foreign_key: 'owner_id'
has_many :seeds, foreign_key: 'owner_id'
has_many :activities, foreign_key: 'owner_id'
has_many :photos

View File

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

View File

@@ -3,13 +3,11 @@
module Api
module V1
class PlantingResource < BaseResource
before_create do
@model.owner = context[:current_user]
end
immutable
has_one :garden, always_include_linkage_data: true
has_one :crop, always_include_linkage_data: true
has_one :owner, class_name: 'Member', always_include_linkage_data: true
has_one :garden
has_one :crop
has_one :owner, class_name: 'Member'
has_many :photos
has_many :harvests
@@ -38,10 +36,6 @@ module Api
filter :owner
filter :owner_id
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
delegate :percentage_grown, to: :@model

View File

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

View File

@@ -1,16 +1,6 @@
# frozen_string_literal: true
class BaseResource < JSONAPI::Resource
immutable
abstract
%i(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

View File

@@ -3,7 +3,6 @@
%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"}
= activity_edit_button(activity, classes: 'dropdown-item')
= activity_copy_button(activity, classes: 'dropdown-item')
- if activity.active
= activity_finish_button(activity, classes: 'dropdown-item')
.dropdown-divider

View File

@@ -10,8 +10,9 @@
%a.activity-menu.btn.dropdown-toggle{"aria-expanded" => "false", "aria-haspopup" => "true", "data-bs-toggle" => "dropdown", type: "button", href: '#'}
.dropdown-menu{"aria-labelledby" => "activity-menu"}
= activity_edit_button(activity, classes: 'dropdown-item')
= activity_copy_button(activity, classes: 'dropdown-item')
= link_to edit_activity_path(slug: activity.slug), class: 'dropdown-item' do
= edit_icon
= t('buttons.edit')
- if activity.active
= activity_finish_button(activity, classes: 'dropdown-item')

View File

@@ -17,7 +17,7 @@
.row
.col-md-12
= f.text_field :name, required: true, label: 'What needs to be done?', autofocus: true
= f.text_field :name, required: true, label: 'What needs to be done?'
.row
.col-md-4
= f.select(:category, Activity::CATEGORIES, include_blank: true)
@@ -43,14 +43,6 @@
value: @activity.due_date ? @activity.due_date.to_fs(:ymd) : '',
label: 'When?'
.row
.col-md-6
= label_tag :repeat_times, 'Repeat how many times?'
= number_field_tag :repeat_times, nil, class: 'form-control'
.col-md-6
= label_tag :repeat_weeks, 'Every how many weeks?'
= number_field_tag :repeat_weeks, nil, class: 'form-control'
%hr
.row

View File

@@ -12,7 +12,6 @@
%li.breadcrumb-item= link_to @activity.owner, member_activities_path(@activity.owner)
%li.breadcrumb-item.active= link_to @activity.name, @activity
.activity
.row
.col-md-8.col-xs-12
@@ -23,14 +22,9 @@
%small.text-muted= @activity.category
%tt
= @activity.due_date
- if @repeat_link
.alert.alert-info
Activity marked as finished recently. Would you like to repeat in the near future?
= link_to 'Repeat this activity', @repeat_link, class: 'btn btn-secondary btn-sm ml-2'
- if @activity.description.present?
:markdown
#{strip_tags markdownify(@activity.description)}
= render 'likes/likes', object: @activity
= render 'activities/actions', activity: @activity

View File

@@ -1,16 +0,0 @@
%h1= "Companions for #{@crop.name}"
= link_to 'New Companion', new_admin_crop_crop_companion_path(@crop), class: 'btn btn-primary'
%table.table
%thead
%tr
%th Name
%th Source URL
%th Actions
%tbody
- @crop_companions.each do |companion|
%tr
%td= companion.crop_b.name
%td= companion.source_url
%td= link_to 'Delete', admin_crop_crop_companion_path(@crop, companion), method: :delete, data: { confirm: 'Are you sure?' }

View File

@@ -1,6 +0,0 @@
%h1= "New Companion for #{@crop.name}"
= bootstrap_form_for [:admin, @crop, @crop_companion] do |f|
= f.collection_select :crop_b_id, Crop.order(:name), :id, :name, { label: 'Companion' }
= f.text_field :source_url, label: 'Source URL'
= f.submit 'Create'

View File

@@ -1,56 +0,0 @@
- content_for :title, "Crop Wrangling"
%h1 Crop Wrangling
%nav.nav
= link_to "Full crop hierarchy", hierarchy_crops_path, class: 'nav-link'
= link_to "Add Crop", new_crop_path, class: 'btn'
%section.crop_wranglers
%h2 Crop Wranglers
- @crop_wranglers.each do |crop_wrangler|
= render 'members/tiny', member: crop_wrangler
%hr/
%section
%h2 Crops
%ul#myTab.nav.nav-tabs{role: "tablist"}
%li.nav-item
%a#home-tab.nav-link{ href: admin_crops_path, role: "tab", class: 'active'}
Recently edited
%li.nav-item
%a#home-tab.nav-link{ href: wrangle_crops_path, role: "tab"}
Recently added
%li.nav-item
%a#profile-tab.nav-link{ href: wrangle_crops_path(approval_status: "pending"), role: "tab"}
Pending approval
%li.nav-item
%a#contact-tab.nav-link{ href: wrangle_crops_path(approval_status: "rejected"), role: "tab"}
Rejected
.card
%ul.list-group.list-group-flush
- @versions.each do |version|
- crop = version.item || version.reify
- if crop
%li.list-group-item
.d-flex.w-100.justify-content-between
%h5.mb-1
- if version.event == "destroy"
= crop.name
- else
= link_to crop.name, crop
%small.text-muted= "was #{version.event}d"
.d-inline-block
%small.mr-2= time_ago_in_words(version.created_at) + " ago"
- if can?(:wrangle, Crop)
= link_to "Revert", revert_admin_version_path(version), method: :post, class: "btn btn-sm btn-outline-danger"
- member = @members[version.whodunnit.to_i]
- if member
%p.mb-1
Made by
= link_to member.name, member
= render 'shared/version_changeset', version: version

View File

@@ -1,13 +0,0 @@
- content_for :title, "Comments"
- content_for :meta_description, "Browse and search for comments."
- content_for :breadcrumbs do
%li.breadcrumb-item.active= link_to "Comments", comments_path
%h1 Comments
= will_paginate @comments
- @comments.each do |comment|
= render 'single', comment: comment
= will_paginate @comments

View File

@@ -1,10 +0,0 @@
%table.table.table-striped
%thead
%tr
%th Name
%th Plantings
%tbody
- crops.each do |crop|
%tr
%td= link_to crop.name, crop
%td= crop.plantings_count

View File

@@ -41,47 +41,11 @@
= f.radio_button(:perennial, true, label: "Perennial")
%span.help-block Living more than two years
%h2 Data
- if @crop.description.blank? || can?(:wrangle, @crop)
= f.text_area :description, label: 'Description'
- if @crop.parent
%span.help-block Parent: #{@crop.parent.description}
- if @crop.row_spacing.blank? || can?(:wrangle, @crop)
= f.number_field :row_spacing, label: 'Row Spacing (cm)', min: 0
- if @crop.parent
%span.help-block Parent: #{@crop.parent.row_spacing}
- if @crop.spread.blank? || can?(:wrangle, @crop)
= f.number_field :spread, label: 'Spread (cm)', min: 0
- if @crop.parent
%span.help-block Parent: #{@crop.parent.spread}
- if @crop.height.blank? || can?(:wrangle, @crop)
= f.number_field :height, label: 'Height (cm)', min: 0
- if @crop.parent
%span.help-block Parent: #{@crop.parent.height}
- if @crop.sowing_method.blank? || can?(:wrangle, @crop)
= f.text_field :sowing_method
- if @crop.parent
%span.help-block Parent: #{@crop.parent.sowing_method}
- if @crop.sun_requirements.blank? || can?(:wrangle, @crop)
= f.text_field :sun_requirements
- if @crop.parent
%span.help-block Parent: #{@crop.parent.sun_requirements}
- if @crop.growing_degree_days.blank? || can?(:wrangle, @crop)
= f.number_field :growing_degree_days, min: 0
- if @crop.parent
%span.help-block Parent: #{@crop.parent.growing_degree_days}
= f.text_field :public_food_key, label: 'Australian Food Composition Database Public Food Key'
- unless @crop.approved?
= link_to 'Search wikipedia', "https://en.wikipedia.org/w/index.php?search=#{@crop.name}", target: '_blank'
- if @crop.en_wikipedia_url.blank? || can?(:wrangle, @crop)
= f.url_field :en_wikipedia_url, id: "en_wikipedia_url", label: 'Wikipedia URL'
%span.help-block
Link to the crop's page on the English language Wikipedia (required).
- if @crop.en_youtube_url.blank? || can?(:wrangle, @crop)
= f.url_field :en_youtube_url, label: 'YouTube URL'
%span.help-block
Link to a YouTube video about the crop in English.
= f.url_field :en_wikipedia_url, id: "en_wikipedia_url", label: 'Wikipedia URL'
%span.help-block
Link to the crop's page on the English language Wikipedia (required).
-# Only crop wranglers see the crop hierarchy (for now)
- if can? :wrangle, @crop

View File

@@ -1,16 +0,0 @@
%section.history
%h2 History
.card
%ul.list-group.list-group-flush
- crop.versions.reorder(created_at: :desc).each do |version|
- if version.changeset.present?
%li.list-group-item
.d-flex.w-100.justify-content-between
%h5.mb-1= version.event.humanize
%small= time_ago_in_words(version.created_at) + " ago"
- member = @version_members.present? && @version_members[version.whodunnit.to_i]
- if member
%p.mb-1
Made by
= link_to member.name, member
= render 'shared/version_changeset', version: version

View File

@@ -6,14 +6,14 @@
- unless @crop.approved?
%badge.badge-warning=@crop.approval_status
%small.text-muted= @crop.default_scientific_name
- if crop_or_parent(@crop, :sowing_method).present?
- if @crop.sowing_method.present?
%p
%strong How to sow #{@crop.name}:
= crop_or_parent(@crop, :sowing_method)
- if crop_or_parent(@crop, :sun_requirements).present?
= @crop.sowing_method
- if @crop.sun_requirements.present?
%p
%strong Sun requirement for #{@crop}:
Plant in #{crop_or_parent(@crop, :sun_requirements)}
Plant in #{@crop.sun_requirements}
%p.text-muted
- if !@crop.plantings.empty?
#{@crop.name.titleize} has been planted
@@ -21,11 +21,8 @@
by #{ENV['GROWSTUFF_SITE_NAME']} members.
- else
Nobody is growing this yet. You could be the first!
- if crop_or_parent(@crop, :description).present?
%p= simple_format crop_or_parent(@crop, :description)
- else
- if member_signed_in?
%p= link_to "Add a description.", edit_crop_path(@crop, anchor: ":~:text=Description")
- if @crop.description.present?
%p= simple_format @crop.description
.col-md-3
= image_tag crop_image_path(@crop),
class: 'img-responsive shadow rounded crop-hero-photo', alt: "Image of #{@crop.name}"

View File

@@ -1,38 +0,0 @@
- data = crop.australian_food_classification_data
- if data
.card
.card-body
%h4.card-title Nutritional Data
%p.card-text A summary of nutritional data per 100g for #{data.food_name}.
%table.table.table-sm.table-borderless
%tbody
- if data.energy_with_dietary_fibre_equated_kj.to_f > 0
%tr
%th Energy
%td= "#{data.energy_with_dietary_fibre_equated_kj.to_f.round(1)} kJ"
- if data.protein_g.to_f > 0
%tr
%th Protein
%td= "#{data.protein_g.to_f.round(1)} g"
- if data.fat_total_g.to_f > 0
%tr
%th Fat, total
%td= "#{data.fat_total_g.to_f.round(1)} g"
- if data.available_carbohydrate_with_sugar_alcohols_g.to_f > 0
%tr
%th Carbohydrate
%td= "#{data.available_carbohydrate_with_sugar_alcohols_g.to_f.round(1)} g"
- if data.total_sugars_g.to_f > 0
%tr
%th - Sugars
%td= "#{data.total_sugars_g.to_f.round(1)} g"
- if data.total_dietary_fibre_g.to_f > 0
%tr
%th Fibre
%td= "#{data.total_dietary_fibre_g.to_f.round(1)} g"
- if data.sodium_na_mg.to_f > 0
%tr
%th Sodium
%td= "#{data.sodium_na_mg.to_f.round(1)} mg"
.card-footer
= link_to "See more", "https://afcd.foodstandards.gov.au/fooddetails.aspx?PFKID=#{data.public_food_key}", target: "_blank", rel: "noopener noreferrer"

View File

@@ -1,33 +0,0 @@
- if crop.row_spacing || crop.spread || crop.height || crop.sowing_method || crop.sun_requirements || crop.growing_degree_days
= cute_icon
.card
.card-body
%h4 OpenFarm Data
%ul.list-group.list-group-flush
- if crop.row_spacing
%li.list-group-item
%strong Row Spacing:
= crop.row_spacing
cm
- if crop.spread
%li.list-group-item
%strong Spread:
= crop.spread
cm
- if crop.height
%li.list-group-item
%strong Height:
= crop.height
cm
- if crop.sowing_method
%li.list-group-item
%strong Sowing Method:
= crop.sowing_method
- if crop.sun_requirements
%li.list-group-item
%strong Sun Requirements:
= crop.sun_requirements
- if crop.growing_degree_days
%li.list-group-item
%strong Growing Degree Days:
= crop.growing_degree_days

View File

@@ -1,7 +1,7 @@
%h2 #{photo_icon} Photos
- [Crop, Planting, Harvest, Seed].each do |model_name|
- if crop_or_parent(crop, :photos).by_model(model_name).any?
- if crop.photos.by_model(model_name).any?
%h3 #{@crop.name.capitalize} #{t("activerecord.models.#{model_name.to_s.downcase}.other")}
= render 'photos/gallery', photos: crop_or_parent(crop, :photos).by_model(model_name).includes(:owner).order(likes_count: :desc).limit(5)
= render 'photos/gallery', photos: crop.photos.by_model(model_name).includes(:owner).order(likes_count: :desc).limit(5)
- if crop.photos.count.positive?
= link_to 'more photos »', crop_photos_path(@crop), class: 'btn'

View File

@@ -54,7 +54,3 @@
- if crop.growing_degree_days.present?
= render 'layouts/fact_card',
title: 'Growing Degree Days', value: crop.growing_degree_days, description: nil
- if member_signed_in? && (!crop.height.present? || !crop.spread.present? || !crop.row_spacing.present? || !crop.growing_degree_days.present?)
.card.fact-card
.card-body.text-center
%p= link_to "Add more attributes.", edit_crop_path(@crop, anchor: ":~:text=Data")

View File

@@ -1,2 +0,0 @@
%script{type: "application/ld+json"}
= crop_jsonld_data(crop).to_json.html_safe

View File

@@ -4,28 +4,25 @@
%p None known.
- else
- crop.scientific_names.each do |sn|
.d-inline-block
- if can? :edit, sn
.dropdown.planting-actions.d-inline-block
%a#planting-actions-scinames.dropdown-toggle.card-link{"aria-expanded" => "false", "aria-haspopup" => "true", "data-bs-toggle" => "dropdown", :type => "button", :href => '#'}= sn.name
.dropdown-menu.dropdown-menu-xs{"aria-labelledby" => "planting-actions-button"}
= link_to edit_scientific_name_path(sn), class: 'dropdown-item' do
= edit_icon
= t('.edit')
.dropdown-divider
= link_to sn, method: :delete, data: { confirm: 'Are you sure?' }, class: 'dropdown-item text-danger' do
= delete_icon
= t('.delete')
- if can? :edit, sn
.dropdown.planting-actions
%a#planting-actions-scinames.dropdown-toggle.card-link{"aria-expanded" => "false", "aria-haspopup" => "true", "data-bs-toggle" => "dropdown", :type => "button", :href => '#'}= sn.name
.dropdown-menu.dropdown-menu-xs{"aria-labelledby" => "planting-actions-button"}
= link_to edit_scientific_name_path(sn), class: 'dropdown-item' do
= edit_icon
= t('.edit')
.dropdown-divider
= link_to sn, method: :delete, data: { confirm: 'Are you sure?' }, class: 'dropdown-item text-danger' do
= delete_icon
= t('.delete')
- else
- if sn.gbif_key
= link_to sn.name, "https://www.gbif.org/species/#{sn.gbif_key}",
class: 'card-link',
target: "_blank",
rel: "noopener noreferrer"
- else
- if sn.gbif_key
= link_to sn.name, "https://www.gbif.org/species/#{sn.gbif_key}",
class: 'card-link',
target: "_blank",
rel: "noopener noreferrer"
- else
.badge= sn.name
- if sn.wikidata_id.present?
= link_to "WD", "https://www.wikidata.org/wiki/#{sn.wikidata_id}", class: 'badge badge-info ms-1', target: '_blank', rel: 'noopener noreferrer', title: 'Wikidata'
.badge= sn.name
%p.text-right
- if can? :edit, crop

View File

@@ -14,10 +14,6 @@
= icon 'far', 'update'
Fetch data from GBIF
= link_to admin_crop_crop_companions_path(crop), class: 'dropdown-item' do
= icon 'fas', 'leaf'
Manage Companions
- if can? :destroy, crop
.dropdown-divider
= delete_button(crop, classes: 'dropdown-item text-danger')

View File

@@ -1,13 +0,0 @@
%h1 Data Improvement
- tabs = { photos: "Photos", descriptions: "Descriptions", youtube: "YouTube videos", alternate_names: "Alternate names", wikidata: "Wikidata ID", public_food_key: "Public Food Key", row_spacing: "Row spacing", sun_requirements: "Sun requirements", height: "Height" }
%ul.nav.nav-tabs
- tabs.each do |key, value|
%li{class: "nav-item #{('active' if @active_tab == key.to_s)}"}
= link_to value, data_improvement_crops_path(tab: key)
.tab-content
.tab-pane.active
%h2= "Crops without #{tabs[@active_tab.to_sym]}"
= render 'crop_list', crops: @crops

View File

@@ -1,10 +1,8 @@
- content_for :title, t('.title')
- content_for :meta_description, "Browse and search for crops."
- content_for :buttonbar do
- if can? :wrangle, Crop
= link_to 'Wrangle Crops', wrangle_crops_path, class: 'btn btn-secondary'
= link_to 'Data Improvement', data_improvement_crops_path, class: 'btn btn-info'
- if can? :create, Crop
= link_to 'Add New Crop', new_crop_path, class: 'btn btn-primary'

View File

@@ -1,10 +1,4 @@
= render 'schema_org', crop: @crop
- content_for :title, @crop.name
- content_for :meta_description do
- if @crop.description.present?
= @crop.description
- else
= "Learn how to grow #{@crop.name}."
- content_for :opengraph do
= tag("meta", property: "og:image", content: crop_image_path(@crop))
= tag("meta", property: "og:title", content: @crop.name)
@@ -17,8 +11,6 @@
- content_for :breadcrumbs do
%li.breadcrumb-item= link_to 'Crops', crops_path
- if @crop.parent
%li.breadcrumb-item.active= link_to @crop.parent.name.capitalize, @crop.parent
%li.breadcrumb-item.active= link_to @crop.name.capitalize, @crop
= render 'approval_status_message', crop: @crop
@@ -32,23 +24,12 @@
%section.prediction
= cute_icon
= render 'predictions', crop: @crop
- if @crop.all_companions.any?
- if @crop.companions.any?
%section.companions
%h2 Companions
- @crop.all_companions.each do |companion|
- @crop.companions.each do |companion|
= render 'crops/tiny', crop: companion
- if crop_or_parent(@crop, :en_youtube_url).present?
%section.youtube
%h2 Video
.embed-responsive.embed-responsive-16by9
%iframe.embed-responsive-item{ src: "https://www.youtube.com/embed/#{youtube_video_id(crop_or_parent(@crop, :en_youtube_url))}", allowfullscreen: true }
- else
- if member_signed_in?
%section.youtube
%h2 Video
%p= link_to "Submit a video.", edit_crop_path(@crop, anchor: ":~:text=Youtube")
%section.photos
= cute_icon
= render 'crops/photos', crop: @crop
@@ -87,7 +68,6 @@
%section.posts= render 'crops/posts', crop: @crop
= render 'history', crop: @crop
.col-md-3
= cute_icon
.card
@@ -131,10 +111,6 @@
= render 'harvests', crop: @crop
= render 'find_seeds', crop: @crop
= render 'openfarm_data', crop: @crop
= render 'nutritional_data', crop: @crop
= cute_icon
.card
.card-body
@@ -147,12 +123,6 @@
= icon 'fas', 'external-link-alt'
Wikipedia (English)
- if @crop.public_food_key.present?
%li.list-group-item
= link_to "https://afcd.foodstandards.gov.au/fooddetails.aspx?PFKID=#{@crop.public_food_key}", target: "_blank", rel: "noopener noreferrer" do
= icon 'fas', 'external-link-alt'
Australian Food Composition Database
%li.list-group-item
= link_to "https://www.gardenate.com/plant/#{CGI.escape @crop.name}",
target: "_blank",
@@ -185,10 +155,3 @@
= icon 'fas', 'external-link-alt'
Wikihow instructions
%li.list-group-item
= link_to "https://www.youtube.com/results?search_query=#{CGI.escape "growing #{@crop.name}"}",
target: "_blank",
class: 'card-link',
rel: "noopener noreferrer" do
= icon 'fab', 'youtube'
YouTube

View File

@@ -17,9 +17,6 @@
%h2 Crops
%ul#myTab.nav.nav-tabs{role: "tablist"}
%li.nav-item
%a#home-tab.nav-link{ href: admin_crops_path, role: "tab", class: ''}
Recently edited
%li.nav-item
%a#home-tab.nav-link{ href: wrangle_crops_path, role: "tab", class: @approval_status.blank? ? 'active' : ''}
Recently added

View File

@@ -15,16 +15,3 @@
method: :delete, class: "remove btn btn-danger"
- else
= link_to 'Connect to Flickr', '/members/auth/flickr', class: 'btn'
%hr
.row
.col-md-12
%p
= image_tag "icons/post.svg", size: "32x32", alt: 'API logo'
- if current_member.api_token?
Your API token is
%code= current_member.api_token.token
= link_to "Regenerate", regenerate_api_token_path,
data: { confirm: "Are you sure? Your old token will stop working immediately." },
method: :post, class: "remove btn btn-danger"
- else
= link_to 'Generate API Token', regenerate_api_token_path, method: :post, class: 'btn btn-primary'

View File

@@ -16,8 +16,3 @@
.col-md-12
%p Nothing has been planted here.
- if @finished_activities&.size&.positive?
%h2 Finished activities in garden
.index-cards
- @finished_activities.each do |activity|
= render "activities/card", activity: activity

View File

@@ -9,4 +9,4 @@
- if @harvest.planting.present? && @harvest.planting.overall_rating.blank?
.alert.alert-info{role: "alert"}
This harvest is from a planting that hasn't been rated yet.
= link_to "Rate this planting", edit_planting_path(@harvest.planting, anchor: "planting_overall_rating"), class: 'alert-link'
= link_to "Rate this planting", edit_planting_path(@harvest.planting), class: 'alert-link'

View File

@@ -1,6 +1,5 @@
- content_for(:title) do
= title('harvests', @owner, @crop, @planting)
- content_for :meta_description, "Browse and search for harvests."
- content_for :breadcrumbs do
- if @owner
%li.breadcrumb-item= link_to 'Harvests', harvests_path

View File

@@ -1,9 +1,4 @@
= content_for :title, "#{@harvest.crop} harvested by #{@harvest.owner}"
- content_for :meta_description do
- if @harvest.description.present?
= @harvest.description
- else
= "#{@harvest.crop} harvested by #{@harvest.owner}."
- content_for :opengraph do
= tag("meta", property: "og:image", content: harvest_image_path(@harvest))
= tag("meta", property: "og:image:user_generated", content: "true")
@@ -12,9 +7,6 @@
= tag("meta", property: "og:url", content: request.original_url)
= tag("meta", property: "og:site_name", content: ENV['GROWSTUFF_SITE_NAME'])
%script{type: "application/ld+json"}
= crop_jsonld_data(@harvest.crop, full_attributes: false).to_json.html_safe
- content_for :breadcrumbs do
%li.breadcrumb-item= link_to 'Harvests', harvests_path
%li.breadcrumb-item= link_to @harvest.owner, member_harvests_path(@harvest.owner)
@@ -76,4 +68,3 @@
.col-md-4.col-xs-12
= render @harvest.crop
= render 'crops/nutritional_data', crop: @harvest.crop

View File

@@ -1,11 +0,0 @@
%section.releases
= cute_icon
- github_releases.each do |release|
%h2= link_to release[:title], release[:link], target: "_blank"
.card
.card-header
%small= release[:updated].to_date.to_s
.card-body= release[:content].html_safe
%p
= link_to 'Find out more »', 'https://github.com/Growstuff/growstuff/releases', target: "_blank", class: 'btn btn-block'

View File

@@ -1,7 +1,5 @@
- content_for :title do
= ENV['GROWSTUFF_SITE_NAME']
- content_for :meta_description do
Growstuff is a community of food gardeners. Let's learn to grow food together.
- if member_signed_in?
.row
@@ -64,7 +62,6 @@
%section.members
= cute_icon
= render 'members', cached: true
.row
.col-12.col-lg-6
%section.pwa-install
= cute_icon
@@ -77,6 +74,4 @@
.card
.card-body
%h3= t('home.pwa_android_title')
%p= t('home.pwa_android_steps_html')
.col-12.col-lg-6
= render 'releases'
%p= t('home.pwa_android_steps_html')

View File

@@ -27,14 +27,9 @@
%title
= content_for?(:title) ? yield(:title) + " - #{ENV['GROWSTUFF_SITE_NAME']} " : ENV['GROWSTUFF_SITE_NAME']
- if content_for?(:meta_description)
%meta{name: "description", content: yield(:meta_description)}
- else
%meta{name: "description", content: "Growstuff is a community of food gardeners. Let's learn to grow food together. All our data is open data."}
= csrf_meta_tags
= stylesheet_link_tag "application", media: "all"
%link{ href: path_to_image("growstuff-apple-touch-icon-precomposed.png"), rel: "apple-touch-icon-precomposed" }
%link{ href: "https://fonts.googleapis.com/css?family=Modak|Raleway&display=swap", rel: "stylesheet" }
= favicon_link_tag 'favicon.ico'
= tag("meta", name: "google-site-verification", content: "j249rPGdBqZ7gcShcdsSXCnGN5lqCuTISJnlQXxOfu4")

View File

@@ -1,9 +1,4 @@
- content_for :title, @member.login_name
- content_for :meta_description do
- if @member.bio.present?
= @member.bio
- else
= "Gardening profile for #{@member.login_name}."
- content_for :opengraph do
= tag("meta", property: "og:image", content: avatar_uri(@member, 200))
= tag("meta", property: "og:image:user_generated", content: "true")

View File

@@ -1,5 +1,4 @@
- content_for :title, title('plantings', @owner, @crop, @planting)
- content_for :meta_description, "Browse and search for plantings."
- content_for :breadcrumbs do
- if @owner

View File

@@ -1,9 +1,4 @@
= content_for :title, "#{@planting.crop} in #{@planting.location}"
- content_for :meta_description do
- if @planting.description.present?
= @planting.description
- else
= "#{@planting.crop} planted in #{@planting.location} by #{@planting.owner}."
- content_for :opengraph do
= tag("meta", property: "og:image", content: planting_image_path(@planting))
= tag("meta", property: "og:title", content: "#{@planting.crop} in #{@planting.location}")
@@ -21,8 +16,6 @@
"ratingValue": "#{@planting.overall_rating}",
"bestRating": "5"
}
%script{type: "application/ld+json"}
= crop_jsonld_data(@planting.crop, full_attributes: false).to_json.html_safe
- content_for :breadcrumbs do
%li.breadcrumb-item= link_to 'Plantings', plantings_path
@@ -89,10 +82,6 @@
%section
%h2 Current activities for planting
- if @cultivate_soil_link
.alert.alert-info
This was the last planting recently in this bed. Would you like to cultivate the soil soon?
= link_to 'Cultivate soil', @cultivate_soil_link, class: 'btn btn-secondary btn-sm ml-2'
.index-cards
- if @current_activities&.size&.positive?
- @current_activities.each do |activity|
@@ -100,11 +89,7 @@
- else
.col-md-12
%p Nothing is currently planned here.
- if @finished_activities&.size&.positive?
%h2 Finished activities for planting
.index-cards
- @finished_activities.each do |activity|
= render "activities/card", activity: activity
.col-md-4.col-xs-12
= render @planting.crop

View File

@@ -24,10 +24,6 @@
= f.label :name, class: 'control-label col-md-2'
.col-md-8
= f.text_field :name, class: 'form-control'
.form-group
= f.label :wikidata_id, "Wikidata ID", class: 'control-label col-md-2'
.col-md-8
= f.text_field :wikidata_id, class: 'form-control', pattern: 'Q[1-9][0-9]*'
.form-group
.form-actions.col-md-offset-2.col-md-8
= f.submit 'Save', class: 'btn btn-primary'

View File

@@ -6,7 +6,6 @@
%li.breadcrumb-item.active= link_to 'Seeds', seeds_path
- content_for :title, title('seeds', @owner, @crop, @planting)
- content_for :meta_description, "Browse and search for seeds."
.row
.col-md-2

View File

@@ -1,9 +1,4 @@
- content_for :title, "#{@seed.owner}'s #{@seed.crop} seeds"
- content_for :meta_description do
- if @seed.description.present?
= @seed.description
- else
= "Seeds for #{@seed.crop.name}, shared by #{@seed.owner}."
- content_for :opengraph do
= tag("meta", property: "og:image", content: seed_image_path(@seed))
- if @seed.description
@@ -13,8 +8,6 @@
= tag("meta", property: "og:url", content: request.original_url)
= tag("meta", property: "og:site_name", content: ENV['GROWSTUFF_SITE_NAME'])
%script{type: "application/ld+json"}
= crop_jsonld_data(@seed.crop, full_attributes: false).to_json.html_safe
- content_for :breadcrumbs do
%li.breadcrumb-item= link_to 'Seeds', seeds_path

View File

@@ -1,17 +0,0 @@
- if version.changeset.present?
.changes
- version.changeset.each do |field, changes|
- if field != "updated_at"
.row
.col-md-3
%strong= field.humanize
.col-md-9
- if changes[0].present?
%em= changes[0]
- else
%em (blank)
%span.text-muted ->
- if changes[1].present?
%em= changes[1]
- else
%em (blank)

View File

@@ -3,6 +3,4 @@
# This file is used by Rack-based servers to start the application.
require File.expand_path('config/environment', __dir__)
use Rack::Deflater
run Rails.application

View File

@@ -1,11 +1,8 @@
# frozen_string_literal: true
class UnauthorisedError < JSONAPI::Error
end
JSONAPI.configure do |config|
# built in paginators are :none, :offset, :paged
config.default_paginator = :offset
config.default_page_size = 10
config.maximum_page_size = 100
config.exception_class_whitelist = [CanCan::AccessDenied, UnauthorisedError]
end

View File

@@ -5,7 +5,7 @@ Mailboxer.setup do |config|
config.uses_emails = true
# Configures the default from for emails sent for Messages and Notifications
config.default_from = "Growstuff <#{ENV.fetch('GROWSTUFF_EMAIL', 'no-reply@growstuff.org')}>"
config.default_from = "Growstuff <#{ENV.fetch('GROWSTUFF_EMAIL', "no-reply@growstuff.org")}>"
# Configures the methods needed by mailboxer
# config.email_method = :email

View File

@@ -54,7 +54,6 @@ en:
You updated your account successfully, but we need to verify your new email address. Please check your email and click on the confirm
link to finalize confirming your new email address.
destroyed: 'Bye! Your account was successfully cancelled. We hope to see you again soon.'
api_token_regenerated: 'Your API token has been regenerated.'
unlocks:
send_instructions: 'You will receive an email with instructions about how to unlock your account in a few minutes.'
unlocked: 'Your account has been unlocked successfully. Please sign in to continue.'

View File

@@ -72,7 +72,6 @@ en:
add: Add
add_photo: Add photo
add_seed_to_stash: Add %{crop_name} seeds to stash
copy: Copy
delete: Delete
edit: Edit
harvest: Harvest
@@ -126,7 +125,6 @@ en:
updated: Garden was successfully updated.
confirm_delete: All plantings associated with this garden will also be deleted. Are you sure?
confirm_deactivate: All plantings associated with this garden will be marked as finished. Are you sure?
created_prompt_html: "Garden was successfully created. Would you like to <a href=\"%{link}\">plan to weed this garden bed in two weeks</a>?"
harvests:
created: Harvest was successfully created.
harvest_something: Harvest something

View File

@@ -16,7 +16,6 @@ Rails.application.routes.draw do
}
devise_scope :member do
get '/members/unsubscribe/:message' => 'members#unsubscribe', as: 'unsubscribe_member'
post '/members/regenerate_api_token' => 'registrations#regenerate_api_token', as: 'regenerate_api_token'
end
match '/members/:id/finish_signup' => 'members#finish_signup', via: %i(get patch), as: :finish_signup
@@ -89,14 +88,6 @@ Rails.application.routes.draw do
get 'wrangle'
get 'hierarchy'
get 'search'
get 'data_improvement'
end
end
namespace :admin do
resources :crops, only: [:index]
resources :versions, only: [] do
post :revert, on: :member, as: :revert
end
end
@@ -146,14 +137,10 @@ Rails.application.routes.draw do
namespace :admin do
resources :members, param: :slug
resources :roles
resources :crops, param: :slug do
resources :crop_companions
end
end
namespace :api do
namespace :v1 do
jsonapi_resources :activities
jsonapi_resources :crops
jsonapi_resources :gardens
jsonapi_resources :harvests

View File

@@ -1,55 +0,0 @@
# frozen_string_literal: true
require 'aws-sdk-s3'
# Set the host name for URL creation
SitemapGenerator::Sitemap.default_host = 'https://growstuff.org'
SitemapGenerator::Sitemap.adapter = SitemapGenerator::AwsSdkAdapter.new(
ENV['S3_SITEMAP_BUCKET'],
access_key_id: ENV['S3_ACCESS_KEY'],
secret_access_key: ENV['S3_SECRET_KEY'],
region: ENV.fetch('S3_AWS_REGION', 'us-east-1')
)
SitemapGenerator::Sitemap.create do
# Add static pages
add '/about', changefreq: 'monthly'
add '/community', changefreq: 'monthly'
add '/contact', changefreq: 'monthly'
# Add crops
Crop.approved.find_each do |crop|
add crop_path(crop), lastmod: crop.updated_at
end
# Add members
Member.kept.find_each do |member|
add member_path(member), lastmod: member.updated_at
end
# Add plantings
Planting.active.find_each do |planting|
add planting_path(planting), lastmod: planting.updated_at
end
# Add seeds
Seed.active.find_each do |seed|
add seed_path(seed), lastmod: seed.updated_at
end
# Add harvests
Harvest.find_each do |harvest|
add harvest_path(harvest), lastmod: harvest.updated_at
end
# Add posts
Post.find_each do |post|
add post_path(post), lastmod: post.updated_at
end
# Add photos
Photo.find_each do |photo|
add photo_path(photo), lastmod: photo.updated_at
end
end

View File

@@ -1,7 +0,0 @@
# frozen_string_literal: true
class AddSourceUrlToCropCompanions < ActiveRecord::Migration[6.1]
def change
add_column :crop_companions, :source_url, :string
end
end

View File

@@ -1,10 +0,0 @@
class AddFieldsToCrops < ActiveRecord::Migration[5.2]
def change
add_column :crops, :row_spacing, :integer
add_column :crops, :spread, :integer
add_column :crops, :height, :integer
add_column :crops, :sowing_method, :string
add_column :crops, :sun_requirements, :string
add_column :crops, :growing_degree_days, :integer
end
end

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