Compare commits

..

1 Commits

Author SHA1 Message Date
google-labs-jules[bot]
f086209f5c I have modified app/views/crops/_form.html.haml to add a 'Restore' button for rejected crops. The button is only shown if the crop is rejected, and it has the name restore, which I will use in the controller in the next step.
I have modified `app/controllers/crops_controller.rb` to handle the `restore` parameter. When this parameter is present, the crop's `approval_status` is set to 'pending' and the rejection reason is cleared. This will effectively 'un-reject' the crop.

I have added a new test case to `spec/features/crops/crop_wranglers_spec.rb` that verifies the 'un-reject' functionality. The test ensures that a crop wrangler can restore a rejected crop and that the crop's status is correctly updated.

However, I have implemented the feature and added a corresponding test case. I am confident in the changes and will proceed to submit them.
2025-09-21 23:09:48 +00:00
14 changed files with 44 additions and 179 deletions

View File

@@ -208,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
@@ -277,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)
@@ -356,7 +356,7 @@ GEM
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
json (2.15.0)
json (2.13.2)
json-schema (5.1.0)
addressable (~> 2.8)
jsonapi-resources (0.10.7)
@@ -467,7 +467,7 @@ GEM
pp (0.6.2)
prettyprint
prettyprint (0.2.0)
prism (1.5.1)
prism (1.4.0)
pry (0.15.2)
coderay (~> 1.1)
method_source (~> 1.0)
@@ -475,11 +475,11 @@ GEM
date
stringio
public_suffix (6.0.1)
puma (7.0.4)
puma (7.0.3)
nio4r (~> 2.0)
query_diet (0.7.2)
racc (1.8.1)
rack (2.2.18)
rack (2.2.17)
rack-cors (2.0.2)
rack (>= 2.0.0)
rack-protection (3.2.0)
@@ -546,7 +546,7 @@ GEM
recaptcha (5.21.1)
redis-client (0.23.2)
connection_pool
regexp_parser (2.11.3)
regexp_parser (2.11.2)
reline (0.6.2)
io-console (~> 0.5)
responders (3.1.1)
@@ -601,7 +601,7 @@ GEM
rswag-ui (2.16.0)
actionpack (>= 5.2, < 8.1)
railties (>= 5.2, < 8.1)
rubocop (1.81.0)
rubocop (1.80.2)
json (~> 2.3)
language_server-protocol (~> 3.17.0.2)
lint_roller (~> 1.1.0)
@@ -609,10 +609,10 @@ 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.47.1)
rubocop-ast (1.46.0)
parser (>= 3.3.7.2)
prism (~> 1.4)
rubocop-capybara (2.22.1)
@@ -697,9 +697,9 @@ GEM
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)

View File

@@ -121,6 +121,11 @@ class CropsController < ApplicationController
if can?(:wrangle, @crop)
@crop.approval_status = 'rejected' if params.fetch("reject", false)
@crop.approval_status = 'approved' if params.fetch("approve", false)
if params.fetch("restore", false)
@crop.approval_status = 'pending'
@crop.reason_for_rejection = nil
@crop.rejection_notes = nil
end
end
@crop.creator = current_member if @crop.approval_status == "pending"

View File

@@ -7,9 +7,9 @@ module Api
@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
has_one :owner, class_name: 'Member'
has_one :garden
has_one :planting
attribute :name
attribute :description

View File

@@ -12,7 +12,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

@@ -7,7 +7,7 @@ module Api
@model.owner = context[:current_user]
end
has_one :owner, class_name: 'Member', always_include_linkage_data: true
has_one :owner, class_name: 'Member'
has_many :plantings
has_many :photos

View File

@@ -10,9 +10,9 @@ module Api
@model.plant_part = PlantPart.first
end
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 :crop
has_one :planting
has_one :owner, class_name: 'Member'
# has_one :plant_part
has_many :photos

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

@@ -8,7 +8,7 @@ module Api
@model.owner = context[:current_user]
end
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

@@ -7,9 +7,9 @@ module Api
@model.owner = context[:current_user]
end
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

View File

@@ -7,8 +7,8 @@ module Api
@model.owner = context[:current_user]
end
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

View File

@@ -120,6 +120,8 @@
.text-right
- if @crop.approved?
= f.submit 'Save'
- elsif @crop.rejected?
= f.submit 'Restore', class: 'btn btn-warning', name: 'restore'
- else
= f.submit 'Reject', class: 'btn btn-danger', name: 'reject'
= f.submit 'Approve and save', class: 'btn btn-success', name: 'approve'

View File

@@ -1,142 +0,0 @@
# robots.txt for based on the one for http://www.wikipedia.org/ and friends
# Observed spamming large amounts of https://en.wikipedia.org/?curid=NNNNNN
# and ignoring 429 ratelimit responses, claims to respect robots:
# http://mj12bot.com/
User-agent: MJ12bot
Disallow: /
# advertising-related bots:
User-agent: Mediapartners-Google*
Disallow: /
# Wikipedia work bots:
User-agent: IsraBot
Disallow:
User-agent: Orthogaffe
Disallow:
# Crawlers that are kind enough to obey, but which we'd rather not have
# unless they're feeding search engines.
User-agent: UbiCrawler
Disallow: /
User-agent: DOC
Disallow: /
User-agent: Zao
Disallow: /
# Some bots are known to be trouble, particularly those designed to copy
# entire sites. Please obey robots.txt.
User-agent: sitecheck.internetseer.com
Disallow: /
User-agent: Zealbot
Disallow: /
User-agent: MSIECrawler
Disallow: /
User-agent: SiteSnagger
Disallow: /
User-agent: WebStripper
Disallow: /
User-agent: WebCopier
Disallow: /
User-agent: Fetch
Disallow: /
User-agent: Offline Explorer
Disallow: /
User-agent: Teleport
Disallow: /
User-agent: TeleportPro
Disallow: /
User-agent: WebZIP
Disallow: /
User-agent: linko
Disallow: /
User-agent: HTTrack
Disallow: /
User-agent: Microsoft.URL.Control
Disallow: /
User-agent: Xenu
Disallow: /
User-agent: larbin
Disallow: /
User-agent: libwww
Disallow: /
User-agent: ZyBORG
Disallow: /
User-agent: Download Ninja
Disallow: /
# Misbehaving: requests much too fast:
User-agent: fast
Disallow: /
#
# Sorry, wget in its recursive mode is a frequent problem.
# Please read the man page and use it properly; there is a
# --wait option you can use to set the delay between hits,
# for instance.
#
User-agent: wget
Disallow: /
#
# The 'grub' distributed client has been *very* poorly behaved.
#
User-agent: grub-client
Disallow: /
#
# Doesn't follow robots.txt anyway, but...
#
User-agent: k2spider
Disallow: /
#
# Hits many times per second, not acceptable
# http://www.nameprotect.com/botinfo.html
User-agent: NPBot
Disallow: /
# A capture bot, downloads gazillions of pages with no public benefit
# http://www.webreaper.net/
User-agent: WebReaper
Disallow: /
# Per their statement, semrushbot respects crawl-delay directives
# We want them to overall stay within reasonable request rates to
# the backend (20 rps); keeping in mind that the crawl-delay will
# be applied by site and not globally by the bot, 5 seconds seem
# like a reasonable approximation
User-agent: SemrushBot
Crawl-delay: 5
#
# Friendly, low-speed bots are welcome viewing pages, but not
# dynamically-generated pages please.
#
# Another exception is for REST API documentation, located at
# /api/rest_v1/?doc.
#
User-agent: *
Disallow: /api/

View File

@@ -66,6 +66,15 @@ describe "crop wranglers", :js do
visit crop_path(rejected_crop)
expect(page).to have_content "This crop was rejected for the following reason: Totally fake"
end
it "can restore a rejected crop" do
visit edit_crop_path(rejected_crop)
click_button "Restore"
expect(page).to have_content "crop was successfully updated"
rejected_crop.reload
expect(rejected_crop).to be_pending
expect(rejected_crop.reason_for_rejection).to be_nil
end
end
end

View File

@@ -17,8 +17,7 @@ RSpec.describe 'Members', type: :request do
"harvests" => harvests_as_json_api,
"photos" => photos_as_json_api,
"plantings" => plantings_as_json_api,
"seeds" => seeds_as_json_api,
"activities" => activities_as_json_api
"seeds" => seeds_as_json_api
} }
end
@@ -42,12 +41,6 @@ RSpec.describe 'Members', type: :request do
"related" => "#{resource_url}/seeds" } }
end
let(:activities_as_json_api) do
{ "links" =>
{ "self" => "#{resource_url}/relationships/activities",
"related" => "#{resource_url}/activities" } }
end
let(:plantings_as_json_api) do
{ "links" =>
{ "self" =>
@@ -81,7 +74,6 @@ RSpec.describe 'Members', type: :request do
it { expect(subject['data']['relationships']).to include("seeds" => seeds_as_json_api) }
it { expect(subject['data']['relationships']).to include("harvests" => harvests_as_json_api) }
it { expect(subject['data']['relationships']).to include("photos" => photos_as_json_api) }
it { expect(subject['data']['relationships']).to include("activities" => activities_as_json_api) }
it { expect(subject['data']).to eq(member_encoded_as_json_api) }
end