From 82a37d69bca6917901c668f272359de523e78985 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 23 Oct 2017 14:37:45 +1300 Subject: [PATCH 01/79] Ensure harvests are same crop, and after the planting was planted --- app/models/harvest.rb | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/app/models/harvest.rb b/app/models/harvest.rb index 293fe81a9..7e6e05708 100644 --- a/app/models/harvest.rb +++ b/app/models/harvest.rb @@ -15,6 +15,19 @@ class Harvest < ActiveRecord::Base validates :crop, presence: { message: "must be present and exist in our database" } validates :plant_part, presence: { message: "must be present and exist in our database" } + validate :crop_must_match_planting + validate :harvest_must_be_after_planting + + def crop_must_match_planting + return unless planting.present? # only check if we are linked to a planting + errors.add(:planting, "must be the same crop") unless crop == planting.crop + end + + def harvest_must_be_after_planting + # only check if we are linked to a planting + return unless harvested_at.present? && planting.present? && planting.planted_at.present? + errors.add(:planting, "cannot be harvested before planting") unless harvested_at > planting.planted_at + end validates :quantity, numericality: { From 0d8ca89b14bc27e3fb94241ef5ae339a8935bb7d Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 23 Oct 2017 14:42:51 +1300 Subject: [PATCH 02/79] harvested_at and harvest_predicted_at added to plantings --- db/migrate/20171022032108_all_the_predictions.rb | 14 ++++++++++++++ db/schema.rb | 4 +++- 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 db/migrate/20171022032108_all_the_predictions.rb diff --git a/db/migrate/20171022032108_all_the_predictions.rb b/db/migrate/20171022032108_all_the_predictions.rb new file mode 100644 index 000000000..12f0372c0 --- /dev/null +++ b/db/migrate/20171022032108_all_the_predictions.rb @@ -0,0 +1,14 @@ +class AllThePredictions < ActiveRecord::Migration + def change + # add_column :crops, :perennial, :boolean, default: false + # add_column :crops, :median_time_to_first_harvest, :interval + # add_column :crops, :median_time_to_last_harvest, :interval + # add_column :crops, :median_time_to_finished, :interval + + add_column :plantings, :harvest_predicted_at, :datetime + add_column :plantings, :harvested_at, :datetime + # add_column :plantings, :failed_at, :datetime + + # add_column :plantings, :finish_predicted_at, :datetime + end +end diff --git a/db/schema.rb b/db/schema.rb index 601d38e7f..699b89d7d 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20170520060252) do +ActiveRecord::Schema.define(version: 20171022032108) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -423,6 +423,8 @@ ActiveRecord::Schema.define(version: 20170520060252) do t.boolean "finished", default: false t.date "finished_at" t.integer "days_before_maturity" + t.datetime "harvest_predicted_at" + t.datetime "harvested_at" end add_index "plantings", ["slug"], name: "index_plantings_on_slug", unique: true, using: :btree From 7d6c49d8c3a776b6a8e47c1ec599b581b8e39940 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 23 Oct 2017 14:47:35 +1300 Subject: [PATCH 03/79] Set harvest preductions on plantings --- app/controllers/plantings_controller.rb | 2 -- app/models/harvest.rb | 18 ++++++++++++- app/models/planting.rb | 22 +++++++++++++--- app/services/planting_predictions.rb | 35 ++++++++++++++++++++----- spec/factories/harvests.rb | 2 +- spec/factories/planting.rb | 6 ++--- spec/models/harvest_spec.rb | 6 +++++ spec/models/planting_spec.rb | 16 ++++++++--- 8 files changed, 87 insertions(+), 20 deletions(-) diff --git a/app/controllers/plantings_controller.rb b/app/controllers/plantings_controller.rb index e7f57939c..54a5c29af 100644 --- a/app/controllers/plantings_controller.rb +++ b/app/controllers/plantings_controller.rb @@ -51,13 +51,11 @@ class PlantingsController < ApplicationController def create @planting = Planting.new(planting_params) @planting.owner = current_member - @planting.calc_and_set_days_before_maturity @planting.save respond_with @planting end def update - @planting.calc_and_set_days_before_maturity @planting.update(planting_params) respond_with @planting end diff --git a/app/models/harvest.rb b/app/models/harvest.rb index 7e6e05708..2ac662e6e 100644 --- a/app/models/harvest.rb +++ b/app/models/harvest.rb @@ -2,6 +2,8 @@ class Harvest < ActiveRecord::Base extend FriendlyId include ActionView::Helpers::NumberHelper include PhotoCapable + + after_save :update_predictions friendly_id :harvest_slug, use: [:slugged, :finders] belongs_to :crop @@ -19,7 +21,7 @@ class Harvest < ActiveRecord::Base validate :harvest_must_be_after_planting def crop_must_match_planting - return unless planting.present? # only check if we are linked to a planting + return if planting.blank? # only check if we are linked to a planting errors.add(:planting, "must be the same crop") unless crop == planting.crop end @@ -71,6 +73,11 @@ class Harvest < ActiveRecord::Base before_save :set_si_weight + def time_from_planting_to_harvest + return if planting.blank? + harvested_at - plating.planted_at + end + # we're storing the harvest weight in kilograms in the db too # to make data manipulation easier def set_si_weight @@ -131,4 +138,13 @@ class Harvest < ActiveRecord::Base def default_photo photos.first || crop.default_photo end + + def update_predictions + return if planting.blank? + # Set the actual harvest on the planting + planting.update(harvested_at: Harvest.where(planting: self).order(:harvested_at).first.harvested_at) + + differences = Planting.where(crop: crop, finished: false).collect(&:time_to_first_harvest) + differences.compact.sum / differences.compact.size unless differences.compact.empty? + end end diff --git a/app/models/planting.rb b/app/models/planting.rb index fa6fe7fc7..e444b945c 100644 --- a/app/models/planting.rb +++ b/app/models/planting.rb @@ -1,6 +1,9 @@ class Planting < ActiveRecord::Base extend FriendlyId include PhotoCapable + + before_validation :update_predictions + friendly_id :planting_slug, use: [:slugged, :finders] belongs_to :garden @@ -63,10 +66,11 @@ class Planting < ActiveRecord::Base validate :finished_must_be_after_planted - delegate :days_until_finished, to: :predict - delegate :days_until_mature, to: :predict + delegate :days_before_finished, to: :predict + delegate :days_before_mature, to: :predict delegate :percentage_grown, to: :predict delegate :start_to_finish_diff, to: :predict + delegate :time_to_first_harvest, to: :predict # check that any finished_at date occurs after planted_at def finished_must_be_after_planted @@ -74,6 +78,10 @@ class Planting < ActiveRecord::Base errors.add(:finished_at, "must be after the planting date") unless planted_at < finished_at end + def first_harvest + harvests.order(:harvested_at).first + end + def planting_slug [ owner.login_name, @@ -100,8 +108,14 @@ class Planting < ActiveRecord::Base planted_at.present? && planted_at <= Date.current end - def calc_and_set_days_before_maturity - self.days_before_maturity = predict.predict_days_before_maturity + def update_predictions + # Note: this looks up days until finished, but the column is named + # maturity. TODO: Fix up names + self.days_before_maturity = predict.predict_days_before_finished + self.finish_predicted_at = Time.zone.now + days_before_maturity if days_before_maturity + + self.harvest_predicted_at = predict.predict_harvest + self.harvested_at = harvests.order(:harvested_at).first.harvested_at if harvests.present? end private diff --git a/app/services/planting_predictions.rb b/app/services/planting_predictions.rb index c71d56964..3e69ae23c 100644 --- a/app/services/planting_predictions.rb +++ b/app/services/planting_predictions.rb @@ -3,13 +3,13 @@ class PlantingPredictions @planting = planting end - def days_until_finished + def days_before_finished return 0 if @planting.finished? days = (@planting.finished_at - Date.current).to_i days.positive? ? days : 0 end - def days_until_mature + def days_before_mature days = ((@planting.planted_at + @planting.days_before_maturity) - Date.current).to_i days.positive? ? days : 0 end @@ -29,27 +29,50 @@ class PlantingPredictions end def start_to_finish_diff - (@planting.finished_at - @planting.planted_at).to_i if @planting.finished_at && @planting.planted_at + return unless @planting.finished_at && @planting.planted_at + (@planting.finished_at.to_datetime - @planting.planted_at.to_datetime).to_i end - def predict_days_before_maturity + def time_to_first_harvest + return unless @planting.harvested_at && @planting.planted_at + (@planting.harvested_at.to_datetime - @planting.planted_at.to_datetime).to_i + end + + def predict_days_before_finished # calculate the number of days, from planted_at, until maturity if @planting.planted_at && @planting.finished_at start_to_finish_diff elsif @planting.crop_id plantings = other_finished_plantings_same_crop - PlantingPredictions.mean_days_until_maturity(plantings) + PlantingPredictions.mean_days_before_finished(plantings) end end - def self.mean_days_until_maturity(plantings) + def self.mean_days_before_finished(plantings) ## Given a set of finished plantings, calculate the average/mean time from start to finish differences = plantings.collect(&:start_to_finish_diff) differences.compact.sum / differences.compact.size unless differences.compact.empty? end + def self.mean_days_before_first_harvest(plantings) + ## Given a set of finished plantings, calculate the average/mean time from start to finish + differences = plantings.collect(&:time_to_first_harvest) + differences.compact.sum / differences.compact.size unless differences.compact.empty? + end + + def predict_harvest + days = PlantingPredictions.mean_days_before_first_harvest(other_harvested_plantings_same_crop) + @planting.planted_at + days.days unless days.nil? + end + private + def other_harvested_plantings_same_crop + Planting.where(crop_id: @planting.crop_id) + .where.not(id: @planting.id) + .where.not(harvested_at: nil) + end + def other_finished_plantings_same_crop Planting.where(crop_id: @planting.crop_id) .where.not(id: @planting.id) diff --git a/spec/factories/harvests.rb b/spec/factories/harvests.rb index 20a3affcd..7f4455652 100644 --- a/spec/factories/harvests.rb +++ b/spec/factories/harvests.rb @@ -5,7 +5,7 @@ FactoryGirl.define do crop plant_part owner - harvested_at "2013-09-17" + harvested_at DateTime.new(2015, 9, 17).in_time_zone quantity "3" unit "individual" weight_quantity 6 diff --git a/spec/factories/planting.rb b/spec/factories/planting.rb index 32e0a6483..aa4cd32ac 100644 --- a/spec/factories/planting.rb +++ b/spec/factories/planting.rb @@ -3,7 +3,7 @@ FactoryGirl.define do garden owner crop - planted_at Time.zone.today + planted_at DateTime.new(2014, 7, 30).in_time_zone quantity 33 description "This is a *really* good plant." @@ -33,8 +33,8 @@ FactoryGirl.define do factory :finished_planting do finished true - planted_at '2014-07-30' - finished_at '2014-08-30' + planted_at DateTime.new(2014, 7, 30).in_time_zone + finished_at DateTime.new(2014, 8, 30).in_time_zone end end end diff --git a/spec/models/harvest_spec.rb b/spec/models/harvest_spec.rb index 614fd673c..70d74cb0d 100644 --- a/spec/models/harvest_spec.rb +++ b/spec/models/harvest_spec.rb @@ -302,4 +302,10 @@ describe Harvest do member.destroy expect(Harvest.joins(:owner).all).not_to include(harvest) end + + it 'sets planting harvested_at date' do + planting = FactoryGirl.create :planting + harvest = FactoryGirl.create :harvest, planting: planting, crop: planting.crop + expect(harvest.harvested_at).to eq(planting.harvested_at) + end end diff --git a/spec/models/planting_spec.rb b/spec/models/planting_spec.rb index 7650992f0..6d7b8a44e 100644 --- a/spec/models/planting_spec.rb +++ b/spec/models/planting_spec.rb @@ -29,17 +29,17 @@ describe Planting do end end - describe 'mean_days_until_maturity' do + describe 'mean_days_before_finished' do let(:plantings) do FactoryGirl.create_list(:planting, 10, crop: crop, planted_at: 12.days.ago, finished_at: 2.days.ago) end it { expect(plantings.size).to eq(10) } - it { expect(PlantingPredictions.mean_days_until_maturity(plantings)).to eq(10) } + it { expect(PlantingPredictions.mean_days_before_finished(plantings)).to eq(10) } end describe 'saving planting calculates days_before_maturity' do before { 5.times { FactoryGirl.create :planting, planted_at: 30.days.ago, finished_at: 9.days.ago, crop: crop } } - before { planting.calc_and_set_days_before_maturity } + before { planting.update_predictions } it { expect(planting.days_before_maturity).to eq(21) } end end @@ -355,4 +355,14 @@ describe Planting do planting.owner.destroy expect(Planting.joins(:owner).all).not_to include(planting) end + + it 'predicts harvest times' do + crop = FactoryGirl.create :crop + 10.times do + planting = FactoryGirl.create :planting, crop: crop, planted_at: DateTime.new(2013, 1, 1).in_time_zone + FactoryGirl.create :harvest, crop: crop, planting: planting, harvested_at: DateTime.new(2013, 2, 1).in_time_zone + end + planting = FactoryGirl.create :planting, planted_at: DateTime.new(2017, 1, 1).in_time_zone, crop: crop + expect(planting.harvest_predicted_at).to eq DateTime.new(2017, 2, 1).in_time_zone + end end From a9cedc6a8a61d72637f4067072a322d74b89ec45 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 29 Oct 2017 14:56:36 +1300 Subject: [PATCH 04/79] Add active median gem --- Gemfile | 3 +++ Gemfile.lock | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index ed5d1ca8f..1433f5eac 100644 --- a/Gemfile +++ b/Gemfile @@ -17,6 +17,9 @@ gem 'font-awesome-sass' gem 'uglifier' # JavaScript compressor +# planting and harvest predictions +gem 'active_median' + gem 'flickraw' gem 'jquery-rails' gem 'jquery-ui-rails', '~> 5.0.2' # needs careful upgrade with change of location diff --git a/Gemfile.lock b/Gemfile.lock index 8ffe37d88..1a787920e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -23,6 +23,8 @@ GEM active_link_to (1.0.5) actionpack addressable + active_median (0.1.4) + activerecord active_merchant-paypal-bogus-gateway (0.1.0) activemerchant active_utils (3.3.9) @@ -537,6 +539,7 @@ PLATFORMS ruby DEPENDENCIES + active_median active_merchant-paypal-bogus-gateway active_utils activemerchant @@ -622,7 +625,6 @@ DEPENDENCIES will_paginate xmlrpc - RUBY VERSION ruby 2.4.1p111 From 8e94ddb4bf9d0aab87efe80aaa1fde65410b063c Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 29 Oct 2017 14:58:42 +1300 Subject: [PATCH 05/79] Moved planting predictions to crop --- .../20171022032108_all_the_predictions.rb | 13 +++--- .../20171028230429_create_median_function.rb | 22 +++++++++ db/schema.rb | 45 +++++++++++++++++-- 3 files changed, 69 insertions(+), 11 deletions(-) create mode 100644 db/migrate/20171028230429_create_median_function.rb diff --git a/db/migrate/20171022032108_all_the_predictions.rb b/db/migrate/20171022032108_all_the_predictions.rb index 12f0372c0..92e0e7ba4 100644 --- a/db/migrate/20171022032108_all_the_predictions.rb +++ b/db/migrate/20171022032108_all_the_predictions.rb @@ -1,14 +1,11 @@ class AllThePredictions < ActiveRecord::Migration def change - # add_column :crops, :perennial, :boolean, default: false - # add_column :crops, :median_time_to_first_harvest, :interval - # add_column :crops, :median_time_to_last_harvest, :interval - # add_column :crops, :median_time_to_finished, :interval + add_column :crops, :perennial, :boolean, default: false - add_column :plantings, :harvest_predicted_at, :datetime - add_column :plantings, :harvested_at, :datetime - # add_column :plantings, :failed_at, :datetime + add_column :plantings, :lifespan, :integer + add_column :crops, :median_lifespan, :integer - # add_column :plantings, :finish_predicted_at, :datetime + create_table :median_functions do |t| + end end end diff --git a/db/migrate/20171028230429_create_median_function.rb b/db/migrate/20171028230429_create_median_function.rb new file mode 100644 index 000000000..708da7f10 --- /dev/null +++ b/db/migrate/20171028230429_create_median_function.rb @@ -0,0 +1,22 @@ +class CreateMedianFunction < ActiveRecord::Migration + def up + ActiveMedian.create_function + + say "Calculating lifespan of known finished plantings" + Planting.where.not(planted_at: nil, finished_at: nil).each do |planting| + planting.calculate_lifespan + planting.save! + say "#{planting.crop.name} median lifespan #{planting.crop.median_lifespan} days" if planting.crop.median_lifespan.present? + end + + say 'Calculating median lifespan of crops' + # Crop.all.each do |crop| + # crop.update_medians + # say "#{crop.name} median lifespan #{crop.median_lifespan} days" if crop.median_lifespan.present? + # end + end + + def down + ActiveMedian.drop_function + end +end diff --git a/db/schema.rb b/db/schema.rb index 699b89d7d..fb7c71321 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20171022032108) do +ActiveRecord::Schema.define(version: 20171028230429) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -194,6 +194,8 @@ ActiveRecord::Schema.define(version: 20171022032108) do t.text "reason_for_rejection" t.text "request_notes" t.text "rejection_notes" + t.boolean "perennial", default: false + t.integer "median_lifespan" end add_index "crops", ["name"], name: "index_crops_on_name", using: :btree @@ -208,6 +210,28 @@ ActiveRecord::Schema.define(version: 20171022032108) do add_index "crops_posts", ["crop_id", "post_id"], name: "index_crops_posts_on_crop_id_and_post_id", using: :btree add_index "crops_posts", ["crop_id"], name: "index_crops_posts_on_crop_id", using: :btree + create_table "event_types", force: :cascade do |t| + t.text "name" + t.text "description" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + + add_index "event_types", ["name"], name: "index_event_types_on_name", using: :btree + + create_table "events", force: :cascade do |t| + t.datetime "planned_for" + t.datetime "occured_at" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.integer "event_type_id", null: false + t.integer "planting_id", null: false + end + + add_index "events", ["event_type_id"], name: "index_events_on_event_type_id", using: :btree + add_index "events", ["planned_for"], name: "index_events_on_planned_for", using: :btree + add_index "events", ["planting_id"], name: "index_events_on_planting_id", using: :btree + create_table "follows", force: :cascade do |t| t.integer "follower_id" t.integer "followed_id" @@ -239,6 +263,8 @@ ActiveRecord::Schema.define(version: 20171022032108) do t.float "longitude" t.decimal "area" t.string "area_unit" + t.integer "width" + t.integer "length" end add_index "gardens", ["owner_id"], name: "index_gardens_on_owner_id", using: :btree @@ -290,6 +316,9 @@ ActiveRecord::Schema.define(version: 20171022032108) do add_index "likes", ["likeable_type", "likeable_id"], name: "index_likes_on_likeable_type_and_likeable_id", using: :btree add_index "likes", ["member_id"], name: "index_likes_on_member_id", using: :btree + create_table "median_functions", force: :cascade do |t| + end + create_table "members", force: :cascade do |t| t.string "email", default: "", null: false t.string "encrypted_password", default: "", null: false @@ -423,8 +452,7 @@ ActiveRecord::Schema.define(version: 20171022032108) do t.boolean "finished", default: false t.date "finished_at" t.integer "days_before_maturity" - t.datetime "harvest_predicted_at" - t.datetime "harvested_at" + t.integer "lifespan" end add_index "plantings", ["slug"], name: "index_plantings_on_slug", unique: true, using: :btree @@ -490,5 +518,16 @@ ActiveRecord::Schema.define(version: 20171022032108) do add_index "seeds", ["slug"], name: "index_seeds_on_slug", unique: true, using: :btree + create_table "squares", force: :cascade do |t| + t.integer "garden_id" + t.integer "x" + t.integer "y" + t.integer "planting_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + + add_foreign_key "events", "event_types" + add_foreign_key "events", "plantings" add_foreign_key "harvests", "plantings" end From 0f066ab302af66003c9f7cfbcb20817701ab1441 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 29 Oct 2017 14:59:29 +1300 Subject: [PATCH 06/79] Cleaning up models as adding predictions --- app/models/crop.rb | 99 +++++++++--------------------- app/models/harvest.rb | 106 ++++++++++++++++---------------- app/models/planting.rb | 135 +++++++++++++++++++---------------------- 3 files changed, 147 insertions(+), 193 deletions(-) diff --git a/app/models/crop.rb b/app/models/crop.rb index 5f81831bc..265b311a2 100644 --- a/app/models/crop.rb +++ b/app/models/crop.rb @@ -2,11 +2,14 @@ class Crop < ActiveRecord::Base extend FriendlyId friendly_id :name, use: [:slugged, :finders] - has_many :scientific_names, after_add: :update_index, after_remove: :update_index - accepts_nested_attributes_for :scientific_names, - allow_destroy: true, - reject_if: :all_blank + ## + ## Triggers + before_destroy { |crop| crop.posts.clear } + ## + ## Relationships + has_many :scientific_names, after_add: :update_index, after_remove: :update_index + accepts_nested_attributes_for :scientific_names, allow_destroy: true, reject_if: :all_blank has_many :alternate_names, after_add: :update_index, after_remove: :update_index, dependent: :destroy has_many :plantings has_many :photos, through: :plantings @@ -15,33 +18,32 @@ class Crop < ActiveRecord::Base has_many :plant_parts, -> { uniq.reorder("plant_parts.name") }, through: :harvests belongs_to :creator, class_name: 'Member' belongs_to :requester, class_name: 'Member' - belongs_to :parent, class_name: 'Crop' has_many :varieties, class_name: 'Crop', foreign_key: 'parent_id' has_and_belongs_to_many :posts # rubocop:disable Rails/HasAndBelongsToMany - before_destroy { |crop| crop.posts.clear } + ## + ## Scopes default_scope { order("lower(crops.name) asc") } - scope :recent, lambda { - approved.reorder("created_at desc") - } - scope :toplevel, lambda { - approved.where(parent_id: nil) - } - scope :popular, lambda { - approved.reorder("plantings_count desc, lower(name) asc") - } - scope :randomized, lambda { - # ok on sqlite and psql, but not on mysql - approved.reorder('random()') - } + scope :recent, -> { approved.reorder("created_at desc") } + scope :toplevel, -> { approved.where(parent_id: nil) } + scope :popular, -> { approved.reorder("plantings_count desc, lower(name) asc") } + # ok on sqlite and psql, but not on mysql + scope :randomized, -> { approved.reorder('random()') } scope :pending_approval, -> { where(approval_status: "pending") } scope :approved, -> { where(approval_status: "approved") } scope :rejected, -> { where(approval_status: "rejected") } - scope :interesting, -> { approved.has_photos.randomized } scope :has_photos, -> { includes(:photos).where.not(photos: { id: nil }) } + ## + ## Validations + # Reasons are only necessary when rejecting + validates :reason_for_rejection, presence: true, if: :rejected? + ## This validation addresses a race condition + validate :approval_status_cannot_be_changed_again + validate :must_be_rejected_if_rejected_reasons_present + validate :must_have_meaningful_reason_for_rejection ## Wikipedia urls are only necessary when approving a crop validates :en_wikipedia_url, format: { @@ -50,16 +52,6 @@ class Crop < ActiveRecord::Base }, if: :approved? - ## Reasons are only necessary when rejecting - validates :reason_for_rejection, presence: true, if: :rejected? - - ## This validation addresses a race condition - validate :approval_status_cannot_be_changed_again - - validate :must_be_rejected_if_rejected_reasons_present - - validate :must_have_meaningful_reason_for_rejection - #################################### # Elastic search configuration if ENV["GROWSTUFF_ELASTICSEARCH"] == "true" @@ -210,51 +202,20 @@ class Crop < ActiveRecord::Base reason_for_rejection end - # Crop.search(string) - def self.search(query) - if ENV['GROWSTUFF_ELASTICSEARCH'] == "true" - search_str = query.nil? ? "" : query.downcase - response = __elasticsearch__.search( # Finds documents which match any field, but uses the _score from - # the best field insead of adding up _score from each field. - query: { - multi_match: { - query: search_str.to_s, - analyzer: "standard", - fields: ["name", - "scientific_names.scientific_name", - "alternate_names.name"] - } - }, - filter: { - term: { approval_status: "approved" } - }, - size: 50 - ) - response.records.to_a - else - # if we don't have elasticsearch, just do a basic SQL query. - # also, make sure it's an actual array not an activerecord - # collection, so it matches what we get from elasticsearch and we can - # manipulate it in the same ways (eg. deleting elements without deleting - # the whole record from the db) - matches = Crop.approved.where("name ILIKE ?", "%#{query}%").to_a - - # we want to make sure that exact matches come first, even if not - # using elasticsearch (eg. in development) - exact_match = Crop.approved.find_by(name: query) - if exact_match - matches.delete(exact_match) - matches.unshift(exact_match) - end - - matches - end + # # Crop.search(string) + def self.search(_query) + CropSearchService.search end def self.case_insensitive_name(name) where(["lower(crops.name) = :value", { value: name.downcase }]) end + def update_medians + # byebug + update(median_lifespan: Planting.where(crop: self).median(:lifespan)) + end + private def count_uses_of_property(col_name) diff --git a/app/models/harvest.rb b/app/models/harvest.rb index 2ac662e6e..531192a1a 100644 --- a/app/models/harvest.rb +++ b/app/models/harvest.rb @@ -1,43 +1,11 @@ class Harvest < ActiveRecord::Base - extend FriendlyId include ActionView::Helpers::NumberHelper + extend FriendlyId include PhotoCapable - after_save :update_predictions friendly_id :harvest_slug, use: [:slugged, :finders] - belongs_to :crop - belongs_to :owner, class_name: 'Member', counter_cache: true - belongs_to :plant_part - belongs_to :planting - - default_scope { joins(:owner).order(created_at: :desc) } - validates :crop, approved: true - - validates :crop, presence: { message: "must be present and exist in our database" } - - validates :plant_part, presence: { message: "must be present and exist in our database" } - validate :crop_must_match_planting - validate :harvest_must_be_after_planting - - def crop_must_match_planting - return if planting.blank? # only check if we are linked to a planting - errors.add(:planting, "must be the same crop") unless crop == planting.crop - end - - def harvest_must_be_after_planting - # only check if we are linked to a planting - return unless harvested_at.present? && planting.present? && planting.planted_at.present? - errors.add(:planting, "cannot be harvested before planting") unless harvested_at > planting.planted_at - end - - validates :quantity, - numericality: { - only_integer: false, - greater_than_or_equal_to: 0 - }, - allow_nil: true - + # Constants UNITS_VALUES = { "individual" => "individual", "bunches" => "bunch", @@ -50,32 +18,53 @@ class Harvest < ActiveRecord::Base "baskets" => "basket", "bushels" => "bushel" }.freeze - validates :unit, inclusion: { in: UNITS_VALUES.values, - message: "%{value} is not a valid unit" }, - allow_nil: true, - allow_blank: true - - validates :weight_quantity, - numericality: { only_integer: false }, - allow_nil: true WEIGHT_UNITS_VALUES = { "kg" => "kg", "lb" => "lb", "oz" => "oz" }.freeze - validates :weight_unit, inclusion: { in: WEIGHT_UNITS_VALUES.values, - message: "%{value} is not a valid unit" }, - allow_nil: true, - allow_blank: true + ## + ## Triggers after_validation :cleanup_quantities - before_save :set_si_weight + after_save :update_predictions + + ## + ## Relationships + belongs_to :crop + belongs_to :owner, class_name: 'Member', counter_cache: true + belongs_to :plant_part + belongs_to :planting + + ## + ## Scopes + default_scope { joins(:owner).order(created_at: :desc) } + + ## + ## Validations + validates :crop, approved: true + validates :crop, presence: { message: "must be present and exist in our database" } + validates :plant_part, presence: { message: "must be present and exist in our database" } + validate :crop_must_match_planting + validate :harvest_must_be_after_planting + validates :quantity, numericality: { + only_integer: false, greater_than_or_equal_to: 0 + }, allow_nil: true + validates :unit, inclusion: { + in: UNITS_VALUES.values, + message: "%{value} is not a valid unit" + }, allow_nil: true, allow_blank: true + validates :weight_quantity, numericality: { only_integer: false }, allow_nil: true + validates :weight_unit, inclusion: { + in: WEIGHT_UNITS_VALUES.values, + message: "%{value} is not a valid unit" + }, allow_nil: true, allow_blank: true def time_from_planting_to_harvest return if planting.blank? - harvested_at - plating.planted_at + harvested_at - planting.planted_at end # we're storing the harvest weight in kilograms in the db too @@ -140,11 +129,22 @@ class Harvest < ActiveRecord::Base end def update_predictions - return if planting.blank? - # Set the actual harvest on the planting - planting.update(harvested_at: Harvest.where(planting: self).order(:harvested_at).first.harvested_at) + # return if planting.blank? + # # Set the actual harvest on the planting + # planting.update(harvested_at: Harvest.where(planting: self).order(:harvested_at).first.harvested_at) - differences = Planting.where(crop: crop, finished: false).collect(&:time_to_first_harvest) - differences.compact.sum / differences.compact.size unless differences.compact.empty? + # differences = Planting.where(crop: crop, finished: false).collect(&:time_to_first_harvest) + # differences.compact.sum / differences.compact.size unless differences.compact.empty? + end + + def crop_must_match_planting + return if planting.blank? # only check if we are linked to a planting + errors.add(:planting, "must be the same crop") unless crop == planting.crop + end + + def harvest_must_be_after_planting + # only check if we are linked to a planting + return unless harvested_at.present? && planting.present? && planting.planted_at.present? + errors.add(:planting, "cannot be harvested before planting") unless harvested_at > planting.planted_at end end diff --git a/app/models/planting.rb b/app/models/planting.rb index e444b945c..a29ad9e20 100644 --- a/app/models/planting.rb +++ b/app/models/planting.rb @@ -1,51 +1,10 @@ class Planting < ActiveRecord::Base extend FriendlyId include PhotoCapable - - before_validation :update_predictions - friendly_id :planting_slug, use: [:slugged, :finders] - belongs_to :garden - belongs_to :owner, class_name: 'Member', counter_cache: true - belongs_to :crop, counter_cache: true - has_many :harvests, dependent: :destroy - - default_scope { joins(:owner).order(created_at: :desc) } - scope :finished, -> { where(finished: true) } - scope :current, -> { where(finished: false) } - - scope :interesting, -> { has_photos.one_per_owner } - scope :one_per_owner, lambda { - joins("JOIN members m ON (m.id=plantings.owner_id) - LEFT OUTER JOIN plantings p2 - ON (m.id=p2.owner_id AND plantings.id < p2.id)").where("p2 IS NULL") - } - - delegate :name, - :en_wikipedia_url, - :default_scientific_name, - :plantings_count, - to: :crop, - prefix: true - - validates :garden, presence: true - validates :crop, presence: true - validates :crop, approved: { message: "must be present and exist in our database" } - - validates :quantity, - numericality: { - only_integer: true, - greater_than_or_equal_to: 0 - }, - allow_nil: true - + # Constants SUNNINESS_VALUES = %w(sun semi-shade shade) - validates :sunniness, inclusion: { in: SUNNINESS_VALUES, - message: "%{value} is not a valid sunniness value" }, - allow_nil: true, - allow_blank: true - PLANTED_FROM_VALUES = [ 'seed', 'seedling', @@ -59,28 +18,47 @@ class Planting < ActiveRecord::Base 'graft', 'layering' ] - validates :planted_from, inclusion: { in: PLANTED_FROM_VALUES, - message: "%{value} is not a valid planting method" }, - allow_nil: true, - allow_blank: true + ## + ## Triggers + before_save :calculate_lifespan + + belongs_to :garden + belongs_to :owner, class_name: 'Member', counter_cache: true + belongs_to :crop, counter_cache: true + has_many :harvests, dependent: :destroy + + ## + ## Scopes + default_scope { joins(:owner).order(created_at: :desc) } + scope :finished, -> { where(finished: true) } + scope :current, -> { where(finished: false) } + scope :interesting, -> { has_photos.one_per_owner } + scope :one_per_owner, lambda { + joins("JOIN members m ON (m.id=plantings.owner_id) + LEFT OUTER JOIN plantings p2 + ON (m.id=p2.owner_id AND plantings.id < p2.id)").where("p2 IS NULL") + } + + ## + ## Delegations + delegate :name, :en_wikipedia_url, :default_scientific_name, :plantings_count, + to: :crop, prefix: true + + ## + ## Validations + validates :garden, presence: true + validates :crop, presence: true, approved: { message: "must be present and exist in our database" } validate :finished_must_be_after_planted - - delegate :days_before_finished, to: :predict - delegate :days_before_mature, to: :predict - delegate :percentage_grown, to: :predict - delegate :start_to_finish_diff, to: :predict - delegate :time_to_first_harvest, to: :predict - - # check that any finished_at date occurs after planted_at - def finished_must_be_after_planted - return unless planted_at && finished_at # only check if we have both - errors.add(:finished_at, "must be after the planting date") unless planted_at < finished_at - end - - def first_harvest - harvests.order(:harvested_at).first - end + validates :quantity, allow_nil: true, numericality: { + only_integer: true, greater_than_or_equal_to: 0 + } + validates :sunniness, allow_nil: true, allow_blank: true, inclusion: { + in: SUNNINESS_VALUES, message: "%{value} is not a valid sunniness value" + } + validates :planted_from, allow_nil: true, allow_blank: true, inclusion: { + in: PLANTED_FROM_VALUES, message: "%{value} is not a valid planting method" + } def planting_slug [ @@ -108,19 +86,34 @@ class Planting < ActiveRecord::Base planted_at.present? && planted_at <= Date.current end - def update_predictions - # Note: this looks up days until finished, but the column is named - # maturity. TODO: Fix up names - self.days_before_maturity = predict.predict_days_before_finished - self.finish_predicted_at = Time.zone.now + days_before_maturity if days_before_maturity + def finish_predicted_at + planted_at + crop.median_lifespan.days if crop.median_lifespan.present? && planted_at.present? + end - self.harvest_predicted_at = predict.predict_harvest - self.harvested_at = harvests.order(:harvested_at).first.harvested_at if harvests.present? + def calculate_lifespan + self.lifespan = planted_at.present? && finished_at.present? ? finished_at - planted_at : nil + end + + def expected_lifespan + if planted_at.present? && finished_at.present? + return finished_at - planted_at + end + crop.median_lifespan + end + + def days_old + (Date.today - planted_at).to_i if planted_at.present? + end + + def percentage_grown + (days_old / expected_lifespan.to_f) * 100 end private - def predict - PlantingPredictions.new(self) + # check that any finished_at date occurs after planted_at + def finished_must_be_after_planted + return unless planted_at && finished_at # only check if we have both + errors.add(:finished_at, "must be after the planting date") unless planted_at < finished_at end end From 47ecbe3f94eeda727c14791105d0139db6b331d0 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 29 Oct 2017 14:59:58 +1300 Subject: [PATCH 07/79] Call the predictions update on planting modifications from controller --- app/controllers/plantings_controller.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/controllers/plantings_controller.rb b/app/controllers/plantings_controller.rb index 54a5c29af..f32732ed8 100644 --- a/app/controllers/plantings_controller.rb +++ b/app/controllers/plantings_controller.rb @@ -51,16 +51,19 @@ class PlantingsController < ApplicationController def create @planting = Planting.new(planting_params) @planting.owner = current_member - @planting.save + @planting.save! + @planting.crop.update_medians respond_with @planting end def update @planting.update(planting_params) + @planting.crop.update_medians respond_with @planting end def destroy + @planting.crop.update_medians @planting.destroy respond_with @planting, location: @planting.garden end From 41dbf6fb1befa62b17eccb5b66a36fd2c9e80592 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 29 Oct 2017 15:00:18 +1300 Subject: [PATCH 08/79] Moved crop search out of crop model file --- app/services/crop_search_service.rb | 42 +++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 app/services/crop_search_service.rb diff --git a/app/services/crop_search_service.rb b/app/services/crop_search_service.rb new file mode 100644 index 000000000..aeb82a67b --- /dev/null +++ b/app/services/crop_search_service.rb @@ -0,0 +1,42 @@ +class CropSearchService + # Crop.search(string) + def self.search(query) + if ENV['GROWSTUFF_ELASTICSEARCH'] == "true" + search_str = query.nil? ? "" : query.downcase + response = __elasticsearch__.search( # Finds documents which match any field, but uses the _score from + # the best field insead of adding up _score from each field. + query: { + multi_match: { + query: search_str.to_s, + analyzer: "standard", + fields: ["name", + "scientific_names.scientific_name", + "alternate_names.name"] + } + }, + filter: { + term: { approval_status: "approved" } + }, + size: 50 + ) + response.records.to_a + else + # if we don't have elasticsearch, just do a basic SQL query. + # also, make sure it's an actual array not an activerecord + # collection, so it matches what we get from elasticsearch and we can + # manipulate it in the same ways (eg. deleting elements without deleting + # the whole record from the db) + matches = Crop.approved.where("name ILIKE ?", "%#{query}%").to_a + + # we want to make sure that exact matches come first, even if not + # using elasticsearch (eg. in development) + exact_match = Crop.approved.find_by(name: query) + if exact_match + matches.delete(exact_match) + matches.unshift(exact_match) + end + + matches + end + end +end From 3a286cd2400b6e179d9ee52894d5542b7ffbd88e Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 29 Oct 2017 15:00:45 +1300 Subject: [PATCH 09/79] Show median lifespan of a crop --- app/views/crops/_index_card.html.haml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/views/crops/_index_card.html.haml b/app/views/crops/_index_card.html.haml index c893148f1..7554e7caf 100644 --- a/app/views/crops/_index_card.html.haml +++ b/app/views/crops/_index_card.html.haml @@ -17,6 +17,10 @@ Planted = pluralize(crop.plantings.size, "time") by #{ENV['GROWSTUFF_SITE_NAME']} members + %p + Median Lifespan + %b= crop.median_lifespan + days - if can? :create, Planting = link_to 'Plant this', new_planting_path(params: { crop_id: crop.id }), class: 'btn btn-primary' From 8364c8c6884eb9f77b7b8390a91e682df5ec2004 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 29 Oct 2017 15:01:25 +1300 Subject: [PATCH 10/79] updated schema --- db/schema.rb | 35 ----------------------------------- 1 file changed, 35 deletions(-) diff --git a/db/schema.rb b/db/schema.rb index fb7c71321..c76e230e4 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -210,28 +210,6 @@ ActiveRecord::Schema.define(version: 20171028230429) do add_index "crops_posts", ["crop_id", "post_id"], name: "index_crops_posts_on_crop_id_and_post_id", using: :btree add_index "crops_posts", ["crop_id"], name: "index_crops_posts_on_crop_id", using: :btree - create_table "event_types", force: :cascade do |t| - t.text "name" - t.text "description" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - end - - add_index "event_types", ["name"], name: "index_event_types_on_name", using: :btree - - create_table "events", force: :cascade do |t| - t.datetime "planned_for" - t.datetime "occured_at" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.integer "event_type_id", null: false - t.integer "planting_id", null: false - end - - add_index "events", ["event_type_id"], name: "index_events_on_event_type_id", using: :btree - add_index "events", ["planned_for"], name: "index_events_on_planned_for", using: :btree - add_index "events", ["planting_id"], name: "index_events_on_planting_id", using: :btree - create_table "follows", force: :cascade do |t| t.integer "follower_id" t.integer "followed_id" @@ -263,8 +241,6 @@ ActiveRecord::Schema.define(version: 20171028230429) do t.float "longitude" t.decimal "area" t.string "area_unit" - t.integer "width" - t.integer "length" end add_index "gardens", ["owner_id"], name: "index_gardens_on_owner_id", using: :btree @@ -518,16 +494,5 @@ ActiveRecord::Schema.define(version: 20171028230429) do add_index "seeds", ["slug"], name: "index_seeds_on_slug", unique: true, using: :btree - create_table "squares", force: :cascade do |t| - t.integer "garden_id" - t.integer "x" - t.integer "y" - t.integer "planting_id" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - end - - add_foreign_key "events", "event_types" - add_foreign_key "events", "plantings" add_foreign_key "harvests", "plantings" end From 202f557e32af6c0f022df7bd373de779af686af1 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 29 Oct 2017 15:02:55 +1300 Subject: [PATCH 11/79] Delete the old predictions code --- app/services/planting_predictions.rb | 81 ---------------------------- 1 file changed, 81 deletions(-) delete mode 100644 app/services/planting_predictions.rb diff --git a/app/services/planting_predictions.rb b/app/services/planting_predictions.rb deleted file mode 100644 index 3e69ae23c..000000000 --- a/app/services/planting_predictions.rb +++ /dev/null @@ -1,81 +0,0 @@ -class PlantingPredictions - def initialize(planting) - @planting = planting - end - - def days_before_finished - return 0 if @planting.finished? - days = (@planting.finished_at - Date.current).to_i - days.positive? ? days : 0 - end - - def days_before_mature - days = ((@planting.planted_at + @planting.days_before_maturity) - Date.current).to_i - days.positive? ? days : 0 - end - - def percentage_grown - return nil unless @planting.days_before_maturity && @planting.planted? - - days = (Date.current - @planting.planted_at.to_date).to_f - - return 0 if Date.current < @planting.planted_at - return 100 if days > @planting.days_before_maturity - percent = (days / @planting.days_before_maturity * 100).to_i - - percent = 100 if percent >= 100 - - percent - end - - def start_to_finish_diff - return unless @planting.finished_at && @planting.planted_at - (@planting.finished_at.to_datetime - @planting.planted_at.to_datetime).to_i - end - - def time_to_first_harvest - return unless @planting.harvested_at && @planting.planted_at - (@planting.harvested_at.to_datetime - @planting.planted_at.to_datetime).to_i - end - - def predict_days_before_finished - # calculate the number of days, from planted_at, until maturity - if @planting.planted_at && @planting.finished_at - start_to_finish_diff - elsif @planting.crop_id - plantings = other_finished_plantings_same_crop - PlantingPredictions.mean_days_before_finished(plantings) - end - end - - def self.mean_days_before_finished(plantings) - ## Given a set of finished plantings, calculate the average/mean time from start to finish - differences = plantings.collect(&:start_to_finish_diff) - differences.compact.sum / differences.compact.size unless differences.compact.empty? - end - - def self.mean_days_before_first_harvest(plantings) - ## Given a set of finished plantings, calculate the average/mean time from start to finish - differences = plantings.collect(&:time_to_first_harvest) - differences.compact.sum / differences.compact.size unless differences.compact.empty? - end - - def predict_harvest - days = PlantingPredictions.mean_days_before_first_harvest(other_harvested_plantings_same_crop) - @planting.planted_at + days.days unless days.nil? - end - - private - - def other_harvested_plantings_same_crop - Planting.where(crop_id: @planting.crop_id) - .where.not(id: @planting.id) - .where.not(harvested_at: nil) - end - - def other_finished_plantings_same_crop - Planting.where(crop_id: @planting.crop_id) - .where.not(id: @planting.id) - .where.not(finished_at: nil) - end -end From b90b4e42fb7b27ef5eae614ed2a8d4884bc742ce Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 29 Oct 2017 15:10:12 +1300 Subject: [PATCH 12/79] Updated progress bar to use new predictions --- app/views/plantings/_progress.html.haml | 9 ++------- app/views/plantings/_progress_bar.html.haml | 4 ++-- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/app/views/plantings/_progress.html.haml b/app/views/plantings/_progress.html.haml index 521561152..260082736 100644 --- a/app/views/plantings/_progress.html.haml +++ b/app/views/plantings/_progress.html.haml @@ -2,18 +2,13 @@ - if show_explanation == true Progress: 0% - not planted yet = render "plantings/progress_bar", status: "not planted", progress: 0 - - elsif planting.finished? - - if show_explanation == true - Progress: 100% = render "plantings/progress_bar", status: 'finished', progress: 100 -- elsif planting.days_before_maturity.nil? +- elsif planting.finish_predicted_at.nil? - if show_explanation == true - Progress: Not calculated, days before maturity unknown + Progress: Not enough data = render "plantings/progress_bar", status: "unknown", progress: nil - else - - if show_explanation == true - Progress: #{planting.percentage_grown}% = render "plantings/progress_bar", status: 'growing', progress: planting.percentage_grown diff --git a/app/views/plantings/_progress_bar.html.haml b/app/views/plantings/_progress_bar.html.haml index 834112976..59d4f2f37 100644 --- a/app/views/plantings/_progress_bar.html.haml +++ b/app/views/plantings/_progress_bar.html.haml @@ -5,7 +5,7 @@ -# haml-lint:disable InlineStyles %div{ class: "progress-bar progress-bar-#{status}", role: "progressbar", style: "width: #{progress}%" } - if progress >= 30 - #{progress}% + #{sprintf '%.2f', progress}% - if progress < 30 - #{progress}% + #{sprintf '%.2f', progress}% -# haml-lint:enable InlineStyles From 22e1718ce6d8fff33dfc5ede0ccfc1968fe95f0e Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 29 Oct 2017 17:01:30 +1300 Subject: [PATCH 13/79] Rubocop fix ups --- app/models/planting.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/models/planting.rb b/app/models/planting.rb index a29ad9e20..f2cb98c58 100644 --- a/app/models/planting.rb +++ b/app/models/planting.rb @@ -91,7 +91,7 @@ class Planting < ActiveRecord::Base end def calculate_lifespan - self.lifespan = planted_at.present? && finished_at.present? ? finished_at - planted_at : nil + self.lifespan = (planted_at.present? && finished_at.present? ? finished_at - planted_at : nil) end def expected_lifespan @@ -102,7 +102,7 @@ class Planting < ActiveRecord::Base end def days_old - (Date.today - planted_at).to_i if planted_at.present? + (Time.zone.today - planted_at).to_i if planted_at.present? end def percentage_grown From 9703d4e98326eb31324b8511f1c15725d300e385 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 29 Oct 2017 17:07:38 +1300 Subject: [PATCH 14/79] Remove harvest preductions for now --- app/models/harvest.rb | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/app/models/harvest.rb b/app/models/harvest.rb index 531192a1a..1b9f2c737 100644 --- a/app/models/harvest.rb +++ b/app/models/harvest.rb @@ -29,7 +29,6 @@ class Harvest < ActiveRecord::Base ## Triggers after_validation :cleanup_quantities before_save :set_si_weight - after_save :update_predictions ## ## Relationships @@ -128,15 +127,6 @@ class Harvest < ActiveRecord::Base photos.first || crop.default_photo end - def update_predictions - # return if planting.blank? - # # Set the actual harvest on the planting - # planting.update(harvested_at: Harvest.where(planting: self).order(:harvested_at).first.harvested_at) - - # differences = Planting.where(crop: crop, finished: false).collect(&:time_to_first_harvest) - # differences.compact.sum / differences.compact.size unless differences.compact.empty? - end - def crop_must_match_planting return if planting.blank? # only check if we are linked to a planting errors.add(:planting, "must be the same crop") unless crop == planting.crop From 3b81affbe5b047a4ceb4720fccb28494d37a7ddb Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 29 Oct 2017 17:09:46 +1300 Subject: [PATCH 15/79] include child records when reading plantings from db --- app/controllers/plantings_controller.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/controllers/plantings_controller.rb b/app/controllers/plantings_controller.rb index f32732ed8..3b3672c4d 100644 --- a/app/controllers/plantings_controller.rb +++ b/app/controllers/plantings_controller.rb @@ -88,6 +88,9 @@ class PlantingsController < ApplicationController Planting end p = p.current unless @show_all - p.joins(:owner, :crop, :garden).order(:created_at).paginate(page: params[:page]) + p.joins(:owner, :crop, :garden) + .includes(:crop, :owner, :garden) + .order(:created_at) + .paginate(page: params[:page]) end end From 70ba8c842147fbd28e442d07b616620c53f3add2 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 29 Oct 2017 19:51:47 +1300 Subject: [PATCH 16/79] Updating planting model specs, for predictions --- app/models/planting.rb | 7 ++- spec/models/planting_spec.rb | 96 +++++++++++++++++++++--------------- 2 files changed, 60 insertions(+), 43 deletions(-) diff --git a/app/models/planting.rb b/app/models/planting.rb index f2cb98c58..58dd4ef81 100644 --- a/app/models/planting.rb +++ b/app/models/planting.rb @@ -101,12 +101,15 @@ class Planting < ActiveRecord::Base crop.median_lifespan end - def days_old + def days_since_planted (Time.zone.today - planted_at).to_i if planted_at.present? end def percentage_grown - (days_old / expected_lifespan.to_f) * 100 + return if planted_at.blank? || expected_lifespan.blank? + p = (days_since_planted / expected_lifespan.to_f) * 100 + return p if p <= 100 + 100 end private diff --git a/spec/models/planting_spec.rb b/spec/models/planting_spec.rb index 6d7b8a44e..574bf22e8 100644 --- a/spec/models/planting_spec.rb +++ b/spec/models/planting_spec.rb @@ -5,42 +5,56 @@ describe Planting do let(:garden_owner) { FactoryGirl.create(:member) } let(:garden) { FactoryGirl.create(:garden, owner: garden_owner) } let(:planting) { FactoryGirl.create(:planting, crop: crop, garden: garden) } - let(:finished_planting) { FactoryGirl.create :planting, planted_at: 4.days.ago, finished_at: 2.days.ago } + let(:finished_planting) do + FactoryGirl.create :planting, planted_at: 4.days.ago, finished_at: 2.days.ago, finished: true + end - describe 'maturity calculations' do - describe 'start_to_finish_diff' do - it { expect(finished_planting.start_to_finish_diff).to eq(2) } + describe 'predictions' do + context 'no previous data' do + describe 'planting planted, not finished' do + end + describe 'planting not planted yet' do + end + describe 'planting finished, no planted_at' do + end + describe 'planing all finished' do + end end - - describe 'other_finished_plantings_same_crop' do + context 'lots of data' do before do - # eight finished plantings - 8.times { FactoryGirl.create :planting, crop: crop, planted_at: 10.days.ago, finished_at: 2.days.ago } - # eight not finished plantings - 8.times { FactoryGirl.create :planting, crop: crop, finished_at: nil } + FactoryGirl.create :planting, crop: planting.crop, planted_at: 10.days.ago + FactoryGirl.create :planting, crop: planting.crop, planted_at: 100.days.ago, finished_at: 50.days.ago + FactoryGirl.create :planting, crop: planting.crop, planted_at: 100.days.ago, finished_at: 51.days.ago + FactoryGirl.create :planting, crop: planting.crop, planted_at: 2.years.ago, finished_at: 50.days.ago + FactoryGirl.create :planting, crop: planting.crop, planted_at: 150.days.ago, finished_at: 100.days.ago + planting.crop.update_medians end - let!(:planting_with_diff_crop) { FactoryGirl.create :planting, planted_at: 10.days.ago, finished_at: 2.days.ago } - let(:planting_predictions) { PlantingPredictions.new(planting) } - it { expect(planting_predictions.send(:other_finished_plantings_same_crop).size).to eq(8) } - it { expect(planting_predictions.send(:other_finished_plantings_same_crop)).not_to include(planting) } - it do - expect(planting_predictions.send(:other_finished_plantings_same_crop)) - .not_to include(planting_with_diff_crop) - end - end - describe 'mean_days_before_finished' do - let(:plantings) do - FactoryGirl.create_list(:planting, 10, crop: crop, planted_at: 12.days.ago, finished_at: 2.days.ago) - end - it { expect(plantings.size).to eq(10) } - it { expect(PlantingPredictions.mean_days_before_finished(plantings)).to eq(10) } - end + it { expect(planting.crop.median_lifespan).to eq 50 } - describe 'saving planting calculates days_before_maturity' do - before { 5.times { FactoryGirl.create :planting, planted_at: 30.days.ago, finished_at: 9.days.ago, crop: crop } } - before { planting.update_predictions } - it { expect(planting.days_before_maturity).to eq(21) } + describe 'planting 30 days ago, not finished' do + let(:planting) { FactoryGirl.create :planting, planted_at: 30.days.ago } + + # 30 / 50 + it { expect(planting.percentage_grown).to eq 60.0 } + it { expect(planting.days_since_planted).to eq 30 } + end + + describe 'planting not planted yet' do + let(:planting) { FactoryGirl.create :planting, planted_at: nil, finished_at: nil } + it { expect(planting.percentage_grown).to eq nil } + end + + describe 'planting finished 10 days, but was never planted' do + let(:planting) { FactoryGirl.create :planting, planted_at: nil, finished_at: 10.days.ago } + it { expect(planting.percentage_grown).to eq nil } + end + + describe 'planted 30 days ago, finished 10 days ago' do + let(:planting) { FactoryGirl.create :planting, planted_at: 30.days.ago, finished_at: 10.days.ago } + it { expect(planting.days_since_planted).to eq 30 } + it { expect(planting.percentage_grown).to eq 100 } + end end end @@ -88,7 +102,7 @@ describe Planting do end end - describe '#percentage_grown' do + pending '#percentage_grown' do it 'should not be more than 100%' do @planting = FactoryGirl.build(:planting, days_before_maturity: 1, planted_at: 1.day.ago) @@ -105,7 +119,7 @@ describe Planting do end end - it 'should reflect the current growth' do + pending 'should reflect the current growth' do @planting = FactoryGirl.build(:planting, days_before_maturity: 10, planted_at: 4.days.ago) expect(@planting.percentage_grown).to eq 40 end @@ -356,13 +370,13 @@ describe Planting do expect(Planting.joins(:owner).all).not_to include(planting) end - it 'predicts harvest times' do - crop = FactoryGirl.create :crop - 10.times do - planting = FactoryGirl.create :planting, crop: crop, planted_at: DateTime.new(2013, 1, 1).in_time_zone - FactoryGirl.create :harvest, crop: crop, planting: planting, harvested_at: DateTime.new(2013, 2, 1).in_time_zone - end - planting = FactoryGirl.create :planting, planted_at: DateTime.new(2017, 1, 1).in_time_zone, crop: crop - expect(planting.harvest_predicted_at).to eq DateTime.new(2017, 2, 1).in_time_zone - end + # it 'predicts harvest times' do + # crop = FactoryGirl.create :crop + # 10.times do + # planting = FactoryGirl.create :planting, crop: crop, planted_at: DateTime.new(2013, 1, 1).in_time_zone + # FactoryGirl.create :harvest, crop: crop, planting: planting, harvested_at: DateTime.new(2013, 2, 1).in_time_zone + # end + # planting = FactoryGirl.create :planting, planted_at: DateTime.new(2017, 1, 1).in_time_zone, crop: crop + # expect(planting.harvest_predicted_at).to eq DateTime.new(2017, 2, 1).in_time_zone + # end end From 9ef40532ad38fc04740209fcb0e6125a88e3b058 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 29 Oct 2017 19:52:55 +1300 Subject: [PATCH 17/79] removed old percentage grow specs --- spec/models/planting_spec.rb | 35 ----------------------------------- 1 file changed, 35 deletions(-) diff --git a/spec/models/planting_spec.rb b/spec/models/planting_spec.rb index 574bf22e8..887b78e38 100644 --- a/spec/models/planting_spec.rb +++ b/spec/models/planting_spec.rb @@ -102,41 +102,6 @@ describe Planting do end end - pending '#percentage_grown' do - it 'should not be more than 100%' do - @planting = FactoryGirl.build(:planting, days_before_maturity: 1, planted_at: 1.day.ago) - - Timecop.freeze(2.days.from_now) do - @planting.percentage_grown.should be 100 - end - end - - it 'should not be less than 0%' do - @planting = FactoryGirl.build(:planting, days_before_maturity: 1, planted_at: 1.day.ago) - - Timecop.freeze(2.days.ago) do - @planting.percentage_grown.should be nil - end - end - - pending 'should reflect the current growth' do - @planting = FactoryGirl.build(:planting, days_before_maturity: 10, planted_at: 4.days.ago) - expect(@planting.percentage_grown).to eq 40 - end - - it 'should not be calculated for unplanted plantings' do - @planting = FactoryGirl.build(:planting, planted_at: nil) - - @planting.planted?.should be false - @planting.percentage_grown.should be nil - end - - it 'should not be calculated for plantings with an unknown days before maturity' do - @planting = FactoryGirl.build(:planting, days_before_maturity: nil) - @planting.percentage_grown.should be nil - end - end - context 'delegation' do it 'system name' do planting.crop_name.should eq planting.crop.name From aa3057056fbf46c403ae6cc5bb0ae535990e46a5 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 29 Oct 2017 19:54:25 +1300 Subject: [PATCH 18/79] rubocop fix up --- app/models/planting.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/planting.rb b/app/models/planting.rb index 58dd4ef81..f7aebcb47 100644 --- a/app/models/planting.rb +++ b/app/models/planting.rb @@ -4,7 +4,7 @@ class Planting < ActiveRecord::Base friendly_id :planting_slug, use: [:slugged, :finders] # Constants - SUNNINESS_VALUES = %w(sun semi-shade shade) + SUNNINESS_VALUES = %w[sun semi-shade shade] PLANTED_FROM_VALUES = [ 'seed', 'seedling', From 302bdba15004c8460920d540b5eef60fa93c5288 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 29 Oct 2017 20:08:09 +1300 Subject: [PATCH 19/79] fixes search --- app/models/crop.rb | 4 ++-- app/services/crop_search_service.rb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/models/crop.rb b/app/models/crop.rb index 265b311a2..f38910041 100644 --- a/app/models/crop.rb +++ b/app/models/crop.rb @@ -203,8 +203,8 @@ class Crop < ActiveRecord::Base end # # Crop.search(string) - def self.search(_query) - CropSearchService.search + def self.search(query) + CropSearchService.search(query) end def self.case_insensitive_name(name) diff --git a/app/services/crop_search_service.rb b/app/services/crop_search_service.rb index aeb82a67b..af6085737 100644 --- a/app/services/crop_search_service.rb +++ b/app/services/crop_search_service.rb @@ -3,7 +3,7 @@ class CropSearchService def self.search(query) if ENV['GROWSTUFF_ELASTICSEARCH'] == "true" search_str = query.nil? ? "" : query.downcase - response = __elasticsearch__.search( # Finds documents which match any field, but uses the _score from + response = Crop.__elasticsearch__.search( # Finds documents which match any field, but uses the _score from # the best field insead of adding up _score from each field. query: { multi_match: { From 692ab5928553f56582a234f049340df79a73402e Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 29 Oct 2017 20:10:52 +1300 Subject: [PATCH 20/79] Display expected finished date --- app/views/plantings/show.html.haml | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/app/views/plantings/show.html.haml b/app/views/plantings/show.html.haml index f0fb868e6..06493cd64 100644 --- a/app/views/plantings/show.html.haml +++ b/app/views/plantings/show.html.haml @@ -28,13 +28,11 @@ - unless @planting.owner.location.blank? (#{@planting.owner.location}) %dt Quantity: - %dd - = display_planting_quantity(@planting) + %dd= display_planting_quantity(@planting) - unless @planting.planted_from.blank? %dt Planted from: - %dd - = display_planted_from(@planting) + %dd= display_planted_from(@planting) %dt Sun or shade? %dd @@ -42,11 +40,24 @@ = image_tag("sunniness_#{sunniness}.png", size: "25x25", alt: sunniness, title: sunniness) = sunniness - %dt Days until maturity: - %dd= display_days_before_maturity(@planting) - %dt Finished: - %dd= display_finished(@planting) + - unless @planting.crop.perennial + - if @planting.finished_at.present? + %dt Finished: + %dd= display_finished(@planting) + -else + %dt Predicted finish: + %dd + - if @planting.planted_at.present? + =@planting.finish_predicted_at + - else + Set planted date to get predictions + + - if @planting.lifespan.present? + %dt Lifespan: + %dd + #{@planting.lifespan} days + -# (median = #{@planting.crop.median_lifespan} days) %p= render 'plantings/harvests', planting: @planting %p= render 'plantings/progress', planting: @planting, show_explanation: true From b09c4aa7a1f9abab974c706cea1afc24990e5429 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 29 Oct 2017 20:24:36 +1300 Subject: [PATCH 21/79] Update display, to show predicted finish date --- app/helpers/plantings_helper.rb | 12 ------------ app/views/plantings/_card.html.haml | 6 ++---- app/views/plantings/show.html.haml | 5 +---- 3 files changed, 3 insertions(+), 20 deletions(-) diff --git a/app/helpers/plantings_helper.rb b/app/helpers/plantings_helper.rb index 96ba62ea5..823167773 100644 --- a/app/helpers/plantings_helper.rb +++ b/app/helpers/plantings_helper.rb @@ -1,16 +1,4 @@ module PlantingsHelper - def display_days_before_maturity(planting) - # First try to calc from finished/finished_at - if planting.finished? || planting.finished_at.present? - planting.days_until_finished.to_s - # then try to calc from planted at + maturity - elsif planting.planted_at.present? && planting.days_before_maturity.present? - planting.days_until_mature.to_s - else - "unknown" - end - end - def display_finished(planting) if !planting.finished_at.nil? planting.finished_at diff --git a/app/views/plantings/_card.html.haml b/app/views/plantings/_card.html.haml index c7d1e4f2b..73fafa24f 100644 --- a/app/views/plantings/_card.html.haml +++ b/app/views/plantings/_card.html.haml @@ -33,10 +33,8 @@ %dt Planted from: %dd= display_planted_from(planting) - %dt Mature in: - %dd - = display_days_before_maturity(planting) - days + %dt Finish expected: + %dd=planting.finish_predicted_at if planting.finish.predicted_at.present? %p= render 'plantings/progress', planting: planting, show_explanation: true diff --git a/app/views/plantings/show.html.haml b/app/views/plantings/show.html.haml index 06493cd64..4f8fbfe35 100644 --- a/app/views/plantings/show.html.haml +++ b/app/views/plantings/show.html.haml @@ -40,7 +40,6 @@ = image_tag("sunniness_#{sunniness}.png", size: "25x25", alt: sunniness, title: sunniness) = sunniness - - unless @planting.crop.perennial - if @planting.finished_at.present? %dt Finished: @@ -55,9 +54,7 @@ - if @planting.lifespan.present? %dt Lifespan: - %dd - #{@planting.lifespan} days - -# (median = #{@planting.crop.median_lifespan} days) + %dd #{@planting.lifespan} days %p= render 'plantings/harvests', planting: @planting %p= render 'plantings/progress', planting: @planting, show_explanation: true From 92fa09a1d3d76a1b493553faf1fd30a53b917b03 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 29 Oct 2017 20:54:33 +1300 Subject: [PATCH 22/79] Mark harvest predictions as pending --- spec/models/harvest_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/models/harvest_spec.rb b/spec/models/harvest_spec.rb index 70d74cb0d..bc626f294 100644 --- a/spec/models/harvest_spec.rb +++ b/spec/models/harvest_spec.rb @@ -303,7 +303,7 @@ describe Harvest do expect(Harvest.joins(:owner).all).not_to include(harvest) end - it 'sets planting harvested_at date' do + pending 'sets planting harvested_at date' do planting = FactoryGirl.create :planting harvest = FactoryGirl.create :harvest, planting: planting, crop: planting.crop expect(harvest.harvested_at).to eq(planting.harvested_at) From 62d84d7af4266e1c018c7de75ca5d636b6329f5e Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 29 Oct 2017 21:26:08 +1300 Subject: [PATCH 23/79] planting progress is 100% if finished --- app/models/planting.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/models/planting.rb b/app/models/planting.rb index f7aebcb47..16e87fbde 100644 --- a/app/models/planting.rb +++ b/app/models/planting.rb @@ -106,6 +106,7 @@ class Planting < ActiveRecord::Base end def percentage_grown + return 100 if finished return if planted_at.blank? || expected_lifespan.blank? p = (days_since_planted / expected_lifespan.to_f) * 100 return p if p <= 100 From ff446c2139baba8b76f840eff84725c132b040b0 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 29 Oct 2017 21:26:41 +1300 Subject: [PATCH 24/79] Updated spec, new message when not enough data to predict progress --- spec/features/plantings/planting_a_crop_spec.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/spec/features/plantings/planting_a_crop_spec.rb b/spec/features/plantings/planting_a_crop_spec.rb index ebc6e89ec..d78ec107e 100644 --- a/spec/features/plantings/planting_a_crop_spec.rb +++ b/spec/features/plantings/planting_a_crop_spec.rb @@ -43,7 +43,7 @@ feature "Planting a crop", :js, :elasticsearch do end expect(page).to have_content "planting was successfully created" - expect(page).to have_content "Progress: Not calculated, days before maturity unknown" + expect(page).to have_content "Progress: Not enough data" end scenario "Clicking link to owner's profile" do @@ -91,7 +91,7 @@ feature "Planting a crop", :js, :elasticsearch do end expect(page).to have_content "planting was successfully created" - expect(page).to have_content "Progress: Not calculated, days before maturity unknown" + expect(page).to have_content "Progress: Not enough data" expect(page).to have_content "Days until maturity: unknown" end @@ -110,7 +110,7 @@ feature "Planting a crop", :js, :elasticsearch do expect(page).to have_content "planting was successfully created" expect(page).to_not have_content "Progress: 0% - not planted yet" - expect(page).to_not have_content "Progress: Not calculated, days before maturity unknown" + expect(page).to_not have_content "Progress: Not enough data" end it "should show that planting is 100% complete (no date specified)" do @@ -173,13 +173,13 @@ feature "Planting a crop", :js, :elasticsearch do scenario "Editing a planting to fill in the finished date" do visit planting_path(planting) - expect(page).to have_content "Progress: Not calculated, days before maturity unknown" + expect(page).to have_content "Progress: Not enough data" click_link "Edit" check "finished" fill_in "Finished date", with: "2015-06-25" click_button "Save" expect(page).to have_content "planting was successfully updated" - expect(page).to_not have_content "Progress: Not calculated, days before maturity unknown" + expect(page).to_not have_content "Progress: Not enough data" end scenario "Marking a planting as finished" do From 54b204c636ef590942f14fd65ca86fc6161c4e7c Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 29 Oct 2017 21:26:55 +1300 Subject: [PATCH 25/79] fixed typo --- app/views/plantings/_card.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/plantings/_card.html.haml b/app/views/plantings/_card.html.haml index 73fafa24f..d92b3f920 100644 --- a/app/views/plantings/_card.html.haml +++ b/app/views/plantings/_card.html.haml @@ -34,7 +34,7 @@ %dd= display_planted_from(planting) %dt Finish expected: - %dd=planting.finish_predicted_at if planting.finish.predicted_at.present? + %dd=planting.finish_predicted_at if planting.finish_predicted_at.present? %p= render 'plantings/progress', planting: planting, show_explanation: true From adf07ce5efd69ceb2f5cd0c54def56682b012d95 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 29 Oct 2017 21:39:47 +1300 Subject: [PATCH 26/79] Planting feature specs passing --- app/helpers/plantings_helper.rb | 2 +- app/views/plantings/_progress.html.haml | 1 - app/views/plantings/_progress_bar.html.haml | 4 ++-- app/views/plantings/show.html.haml | 18 ++++++++---------- .../features/plantings/planting_a_crop_spec.rb | 9 +++------ 5 files changed, 14 insertions(+), 20 deletions(-) diff --git a/app/helpers/plantings_helper.rb b/app/helpers/plantings_helper.rb index 823167773..b8e2b257c 100644 --- a/app/helpers/plantings_helper.rb +++ b/app/helpers/plantings_helper.rb @@ -1,6 +1,6 @@ module PlantingsHelper def display_finished(planting) - if !planting.finished_at.nil? + if planting.finished_at.present? planting.finished_at elsif planting.finished "Yes (no date specified)" diff --git a/app/views/plantings/_progress.html.haml b/app/views/plantings/_progress.html.haml index 260082736..36a3ab4d4 100644 --- a/app/views/plantings/_progress.html.haml +++ b/app/views/plantings/_progress.html.haml @@ -4,7 +4,6 @@ = render "plantings/progress_bar", status: "not planted", progress: 0 - elsif planting.finished? = render "plantings/progress_bar", status: 'finished', progress: 100 - - elsif planting.finish_predicted_at.nil? - if show_explanation == true Progress: Not enough data diff --git a/app/views/plantings/_progress_bar.html.haml b/app/views/plantings/_progress_bar.html.haml index 59d4f2f37..e8544fc65 100644 --- a/app/views/plantings/_progress_bar.html.haml +++ b/app/views/plantings/_progress_bar.html.haml @@ -5,7 +5,7 @@ -# haml-lint:disable InlineStyles %div{ class: "progress-bar progress-bar-#{status}", role: "progressbar", style: "width: #{progress}%" } - if progress >= 30 - #{sprintf '%.2f', progress}% + #{sprintf '%.0f', progress}% - if progress < 30 - #{sprintf '%.2f', progress}% + #{sprintf '%.0f', progress}% -# haml-lint:enable InlineStyles diff --git a/app/views/plantings/show.html.haml b/app/views/plantings/show.html.haml index 4f8fbfe35..6f5284cd3 100644 --- a/app/views/plantings/show.html.haml +++ b/app/views/plantings/show.html.haml @@ -41,16 +41,14 @@ = sunniness - unless @planting.crop.perennial - - if @planting.finished_at.present? - %dt Finished: - %dd= display_finished(@planting) - -else - %dt Predicted finish: - %dd - - if @planting.planted_at.present? - =@planting.finish_predicted_at - - else - Set planted date to get predictions + %dt Finished: + %dd= display_finished(@planting) + %dt Predicted finish: + %dd + - if @planting.finish_predicted_at.present? + =@planting.finish_predicted_at + - else + Set planted date to get predictions - if @planting.lifespan.present? %dt Lifespan: diff --git a/spec/features/plantings/planting_a_crop_spec.rb b/spec/features/plantings/planting_a_crop_spec.rb index d78ec107e..432672874 100644 --- a/spec/features/plantings/planting_a_crop_spec.rb +++ b/spec/features/plantings/planting_a_crop_spec.rb @@ -92,7 +92,6 @@ feature "Planting a crop", :js, :elasticsearch do expect(page).to have_content "planting was successfully created" expect(page).to have_content "Progress: Not enough data" - expect(page).to have_content "Days until maturity: unknown" end it "should show that planting is in progress" do @@ -127,9 +126,8 @@ feature "Planting a crop", :js, :elasticsearch do end expect(page).to have_content "planting was successfully created" - expect(page).to have_content "Progress: 100%" + expect(page).to have_content "100%" expect(page).to have_content "Yes (no date specified)" - expect(page).to have_content "Days until maturity: 0" end it "should show that planting is 100% complete (date specified)" do @@ -146,8 +144,7 @@ feature "Planting a crop", :js, :elasticsearch do end expect(page).to have_content "planting was successfully created" - expect(page).to have_content "Progress: 100%" - expect(page).to have_content "Days until maturity: 0" + expect(page).to have_content "100%" end end @@ -232,7 +229,7 @@ feature "Planting a crop", :js, :elasticsearch do end expect(page).to have_content "planting was successfully created" expect(page).to have_content "Finished: Yes (no date specified)" - expect(page).to have_content "Progress: 100%" + expect(page).to have_content "100%" end describe "Planting sunniness" do From 251f44b0c7c8047bae14fb141e99c9fe75f1ffa4 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 30 Oct 2017 08:23:28 +1300 Subject: [PATCH 27/79] Updated tests of progress bar --- spec/features/plantings/planting_a_crop_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/features/plantings/planting_a_crop_spec.rb b/spec/features/plantings/planting_a_crop_spec.rb index 432672874..177cf9942 100644 --- a/spec/features/plantings/planting_a_crop_spec.rb +++ b/spec/features/plantings/planting_a_crop_spec.rb @@ -109,7 +109,7 @@ feature "Planting a crop", :js, :elasticsearch do expect(page).to have_content "planting was successfully created" expect(page).to_not have_content "Progress: 0% - not planted yet" - expect(page).to_not have_content "Progress: Not enough data" + expect(page).to_not have_content "Not enough data" end it "should show that planting is 100% complete (no date specified)" do From f66b0768e26f8680614832f3a56b44cd12e0da35 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 30 Oct 2017 09:09:30 +1300 Subject: [PATCH 28/79] Changed how db schema is loaded in travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 6b6966904..ef68fec4f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,7 +33,7 @@ before_script: if [ "${STATIC_CHECKS}" = "true" ]; then ./script/install_linters; else - bundle exec rake db:create db:migrate db:test:prepare; + RAILS_ENV=test bundle exec rake db:create db:migrate; bundle exec rake assets:precompile; fi - set +e From d540342acbf787462df20671d8b5e6b800ce609e Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 30 Oct 2017 13:27:44 +1300 Subject: [PATCH 29/79] removed the days_before_maturity specs because function no longer exists --- spec/helpers/plantings_helper_spec.rb | 58 --------------------------- 1 file changed, 58 deletions(-) diff --git a/spec/helpers/plantings_helper_spec.rb b/spec/helpers/plantings_helper_spec.rb index abbf74bd4..62994ec68 100644 --- a/spec/helpers/plantings_helper_spec.rb +++ b/spec/helpers/plantings_helper_spec.rb @@ -1,64 +1,6 @@ require 'rails_helper' describe PlantingsHelper do - describe "display_days_before_maturity" do - it "handles nil planted_at, nil finished_at, non-nil days_until_maturity" do - planting = FactoryGirl.build(:planting, - quantity: 5, - planted_at: nil, - finished_at: nil, - days_before_maturity: 17) - result = helper.display_days_before_maturity(planting) - expect(result).to eq "unknown" - end - - it "handles non-nil planted_at and d_b_m, nil finished_at" do - planting = FactoryGirl.build(:planting, - quantity: 5, - planted_at: Date.current, - finished_at: nil, - days_before_maturity: 17) - result = helper.display_days_before_maturity(planting) - expect(result).to eq "17" - end - - it "handles completed plantings" do - planting = FactoryGirl.build(:planting, finished: true) - result = helper.display_days_before_maturity(planting) - expect(result).to eq "0" - end - - it "handles plantings that should have finished" do - planting = FactoryGirl.build(:planting, - quantity: 5, - planted_at: Date.new(0, 1, 1), - finished_at: nil, - days_before_maturity: "17") - result = helper.display_days_before_maturity(planting) - expect(result).to eq "0" - end - - it "handles nil d_b_m and nil finished_at" do - planting = FactoryGirl.build(:planting, - quantity: 5, - planted_at: Date.new(2012, 5, 12), - finished_at: nil, - days_before_maturity: nil) - result = helper.display_days_before_maturity(planting) - expect(result).to eq "unknown" - end - - it "handles finished_at dates in the future" do - planting = FactoryGirl.build(:planting, - quantity: 5, - planted_at: Date.current, - finished_at: Date.current + 5, - days_before_maturity: nil) - result = helper.display_days_before_maturity(planting) - expect(result).to eq "5" - end - end - describe "display_planting" do let!(:member) { FactoryGirl.build(:member, login_name: 'crop_lady') } From 71cb3f8c5fffc0d6f00200a6b424cf45fbb11477 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 1 Nov 2017 13:56:25 +1300 Subject: [PATCH 30/79] Rubocop fixes --- app/models/planting.rb | 2 +- app/views/plantings/show.html.haml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/models/planting.rb b/app/models/planting.rb index 16e87fbde..249a8df16 100644 --- a/app/models/planting.rb +++ b/app/models/planting.rb @@ -4,7 +4,7 @@ class Planting < ActiveRecord::Base friendly_id :planting_slug, use: [:slugged, :finders] # Constants - SUNNINESS_VALUES = %w[sun semi-shade shade] + SUNNINESS_VALUES = %w(sun semi-shade shade) PLANTED_FROM_VALUES = [ 'seed', 'seedling', diff --git a/app/views/plantings/show.html.haml b/app/views/plantings/show.html.haml index 6f5284cd3..56cfedc08 100644 --- a/app/views/plantings/show.html.haml +++ b/app/views/plantings/show.html.haml @@ -46,7 +46,7 @@ %dt Predicted finish: %dd - if @planting.finish_predicted_at.present? - =@planting.finish_predicted_at + = @planting.finish_predicted_at - else Set planted date to get predictions From cd997693116a15f025a428bc98f3e6dbbd0efe22 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 1 Nov 2017 14:02:56 +1300 Subject: [PATCH 31/79] Wrapped a long line --- db/migrate/20171028230429_create_median_function.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/db/migrate/20171028230429_create_median_function.rb b/db/migrate/20171028230429_create_median_function.rb index 708da7f10..e57d63b4f 100644 --- a/db/migrate/20171028230429_create_median_function.rb +++ b/db/migrate/20171028230429_create_median_function.rb @@ -6,7 +6,9 @@ class CreateMedianFunction < ActiveRecord::Migration Planting.where.not(planted_at: nil, finished_at: nil).each do |planting| planting.calculate_lifespan planting.save! - say "#{planting.crop.name} median lifespan #{planting.crop.median_lifespan} days" if planting.crop.median_lifespan.present? + if planting.crop.median_lifespan.present? + say "#{planting.crop.name} median lifespan #{planting.crop.median_lifespan} days" + end end say 'Calculating median lifespan of crops' From d1951b8b653991e3ac0c8393ff28d68a445a762f Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 1 Nov 2017 14:22:39 +1300 Subject: [PATCH 32/79] Edit and show perennial plants --- app/controllers/crops_controller.rb | 3 ++- app/views/crops/_form.html.haml | 10 ++++++++++ app/views/crops/show.html.haml | 8 ++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/app/controllers/crops_controller.rb b/app/controllers/crops_controller.rb index 1329478f1..3e3da6987 100644 --- a/app/controllers/crops_controller.rb +++ b/app/controllers/crops_controller.rb @@ -137,7 +137,7 @@ class CropsController < ApplicationController return unless params[param_name].present? destroy_names(name_type) params[param_name].each do |_i, value| - create_name!(name_type, value) + create_name!(name_type, value) unless value.blank? end end @@ -154,6 +154,7 @@ class CropsController < ApplicationController :name, :parent_id, :creator_id, + :perennial, :approval_status, :request_notes, :reason_for_rejection, diff --git a/app/views/crops/_form.html.haml b/app/views/crops/_form.html.haml index bc1b76631..c391c79d2 100644 --- a/app/views/crops/_form.html.haml +++ b/app/views/crops/_form.html.haml @@ -29,6 +29,16 @@ Wranglers: please ensure this is singular, and capitalize proper nouns only. + .form-group + = f.label :perennial, 'Lifespan', class: 'control-label col-md-2' + .col-md-8 + = f.radio_button(:perennial, false) + = f.label(:perennial_false, "Annual") + %span.help-block Living and reproducing in a single year or less + = f.radio_button(:perennial, true) + = f.label(:perennial_true, "Perennial") + %span.help-block Living more than two years + .form-group = f.label :en_wikipedia_url, 'Wikipedia URL', class: 'control-label col-md-2' .col-md-8 diff --git a/app/views/crops/show.html.haml b/app/views/crops/show.html.haml index 286017b22..5e1e04786 100644 --- a/app/views/crops/show.html.haml +++ b/app/views/crops/show.html.haml @@ -34,6 +34,14 @@ = render partial: 'photos', locals: { crop: @crop } + %h2 + #{@crop.name} is + = link_to 'https://en.wikipedia.org/wiki/Annual_vs._perennial_plant_evolution' do + -if @crop.perennial + perennial (living more than two years) + - else + annual (living and reproducing in a single year or less) + %h2 - if !@crop.plantings.empty? = @crop.name.titleize From 31a37bf6dc204260cb51418fafa269605c14213b Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 1 Nov 2017 14:27:03 +1300 Subject: [PATCH 33/79] No progress bar for perennials --- app/views/plantings/_progress.html.haml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/views/plantings/_progress.html.haml b/app/views/plantings/_progress.html.haml index 36a3ab4d4..876259b85 100644 --- a/app/views/plantings/_progress.html.haml +++ b/app/views/plantings/_progress.html.haml @@ -1,4 +1,6 @@ -- if !planting.planted? +- if planting.crop.perennial + %p Perennial +- elsif !planting.planted? - if show_explanation == true Progress: 0% - not planted yet = render "plantings/progress_bar", status: "not planted", progress: 0 From 267f27b3f87d9ee67666ca3a1cd444c09f52d439 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 1 Nov 2017 14:33:59 +1300 Subject: [PATCH 34/79] rubocop fix up --- app/controllers/crops_controller.rb | 2 +- app/views/crops/show.html.haml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/crops_controller.rb b/app/controllers/crops_controller.rb index 3e3da6987..1deb716c7 100644 --- a/app/controllers/crops_controller.rb +++ b/app/controllers/crops_controller.rb @@ -137,7 +137,7 @@ class CropsController < ApplicationController return unless params[param_name].present? destroy_names(name_type) params[param_name].each do |_i, value| - create_name!(name_type, value) unless value.blank? + create_name!(name_type, value) unless value.empty? end end diff --git a/app/views/crops/show.html.haml b/app/views/crops/show.html.haml index 5e1e04786..4ac071ae9 100644 --- a/app/views/crops/show.html.haml +++ b/app/views/crops/show.html.haml @@ -37,7 +37,7 @@ %h2 #{@crop.name} is = link_to 'https://en.wikipedia.org/wiki/Annual_vs._perennial_plant_evolution' do - -if @crop.perennial + - if @crop.perennial perennial (living more than two years) - else annual (living and reproducing in a single year or less) From 7104781d1bce9da6c96d62691edd24a2435c5a3c Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 1 Nov 2017 15:13:32 +1300 Subject: [PATCH 35/79] Rubocop array fix ups --- app/models/forum.rb | 2 +- app/models/garden.rb | 2 +- app/models/harvest.rb | 4 ++-- app/models/member.rb | 4 ++-- app/models/plant_part.rb | 2 +- app/models/planting.rb | 4 ++-- app/models/post.rb | 2 +- app/models/role.rb | 4 ++-- app/models/seed.rb | 4 ++-- 9 files changed, 14 insertions(+), 14 deletions(-) diff --git a/app/models/forum.rb b/app/models/forum.rb index fd3c99464..f9d7099fe 100644 --- a/app/models/forum.rb +++ b/app/models/forum.rb @@ -1,7 +1,7 @@ class Forum < ActiveRecord::Base extend FriendlyId validates :name, presence: true - friendly_id :name, use: [:slugged, :finders] + friendly_id :name, use: %i[slugged finders] has_many :posts belongs_to :owner, class_name: "Member" diff --git a/app/models/garden.rb b/app/models/garden.rb index 5af61506a..2cd2499c4 100644 --- a/app/models/garden.rb +++ b/app/models/garden.rb @@ -2,7 +2,7 @@ class Garden < ActiveRecord::Base extend FriendlyId include Geocodable include PhotoCapable - friendly_id :garden_slug, use: [:slugged, :finders] + friendly_id :garden_slug, use: %i[slugged finders] belongs_to :owner, class_name: 'Member', foreign_key: 'owner_id', counter_cache: true has_many :plantings, dependent: :destroy diff --git a/app/models/harvest.rb b/app/models/harvest.rb index 1b9f2c737..18fc9b183 100644 --- a/app/models/harvest.rb +++ b/app/models/harvest.rb @@ -1,9 +1,9 @@ -class Harvest < ActiveRecord::Base +class Harvest < ApplicationRecord include ActionView::Helpers::NumberHelper extend FriendlyId include PhotoCapable - friendly_id :harvest_slug, use: [:slugged, :finders] + friendly_id :harvest_slug, use: %i[slugged finders] # Constants UNITS_VALUES = { diff --git a/app/models/member.rb b/app/models/member.rb index 9a05d6206..bbfca26d4 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -4,7 +4,7 @@ class Member < ActiveRecord::Base include Geocodable extend FriendlyId - friendly_id :login_name, use: [:slugged, :finders] + friendly_id :login_name, use: %i[slugged finders] has_many :posts, foreign_key: 'author_id' has_many :comments, foreign_key: 'author_id' @@ -75,7 +75,7 @@ class Member < ActiveRecord::Base message: "should be between 2 and 25 characters long" }, exclusion: { - in: %w(growstuff admin moderator staff nearby), + in: %w[growstuff admin moderator staff nearby], message: "name is reserved" }, format: { diff --git a/app/models/plant_part.rb b/app/models/plant_part.rb index fdf1d69e6..aa689f8ef 100644 --- a/app/models/plant_part.rb +++ b/app/models/plant_part.rb @@ -1,6 +1,6 @@ class PlantPart < ActiveRecord::Base extend FriendlyId - friendly_id :name, use: [:slugged, :finders] + friendly_id :name, use: %i[slugged finders] has_many :harvests has_many :crops, -> { uniq }, through: :harvests diff --git a/app/models/planting.rb b/app/models/planting.rb index 249a8df16..ab95f5042 100644 --- a/app/models/planting.rb +++ b/app/models/planting.rb @@ -1,10 +1,10 @@ class Planting < ActiveRecord::Base extend FriendlyId include PhotoCapable - friendly_id :planting_slug, use: [:slugged, :finders] + friendly_id :planting_slug, use: %i[slugged finders] # Constants - SUNNINESS_VALUES = %w(sun semi-shade shade) + SUNNINESS_VALUES = %w[sun semi-shade shade] PLANTED_FROM_VALUES = [ 'seed', 'seedling', diff --git a/app/models/post.rb b/app/models/post.rb index e2cd0194c..2b34d4e22 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -1,7 +1,7 @@ class Post < ActiveRecord::Base extend FriendlyId include Likeable - friendly_id :author_date_subject, use: [:slugged, :finders] + friendly_id :author_date_subject, use: %i[slugged finders] belongs_to :author, class_name: 'Member' belongs_to :forum has_many :comments, dependent: :destroy diff --git a/app/models/role.rb b/app/models/role.rb index 98224062c..1ce887a56 100644 --- a/app/models/role.rb +++ b/app/models/role.rb @@ -1,11 +1,11 @@ class Role < ActiveRecord::Base extend FriendlyId - friendly_id :name, use: [:slugged, :finders] + friendly_id :name, use: %i[slugged finders] has_and_belongs_to_many :members # rubocop:disable Rails/HasAndBelongsToMany class << self - [:crop_wranglers, :admins].each do |method| + %i[crop_wranglers admins].each do |method| define_method method do slug = method.to_s.singularize.dasherize Role.where(slug: slug).try(:first).try(:members) diff --git a/app/models/seed.rb b/app/models/seed.rb index 9b2fc510b..c4ab18e3d 100644 --- a/app/models/seed.rb +++ b/app/models/seed.rb @@ -35,7 +35,7 @@ class Seed < ActiveRecord::Base scope :tradable, -> { where.not(tradable_to: 'nowhere') } scope :interesting, -> { tradable.has_location } scope :has_location, -> { joins(:owner).where.not("members.location": nil) } - TRADABLE_TO_VALUES = %w(nowhere locally nationally internationally).freeze + TRADABLE_TO_VALUES = %w[nowhere locally nationally internationally].freeze validates :tradable_to, inclusion: { in: TRADABLE_TO_VALUES, message: "You may only trade seed nowhere, "\ "locally, nationally, or internationally" }, @@ -66,7 +66,7 @@ class Seed < ActiveRecord::Base allow_nil: false, allow_blank: false - HEIRLOOM_VALUES = %w(heirloom hybrid unknown).freeze + HEIRLOOM_VALUES = %w[heirloom hybrid unknown].freeze validates :heirloom, inclusion: { in: HEIRLOOM_VALUES, message: "You must say whether the seeds are heirloom, hybrid, or unknown" }, allow_nil: false, From cabc4fd0306e87dd607e74c52bfb323bee89963b Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 4 Nov 2017 10:13:21 +1300 Subject: [PATCH 36/79] %i-literals should be delimited by ( and ) --- app/models/forum.rb | 2 +- app/models/garden.rb | 2 +- app/models/harvest.rb | 4 ++-- app/models/member.rb | 4 ++-- app/models/plant_part.rb | 2 +- app/models/planting.rb | 4 ++-- app/models/post.rb | 2 +- app/models/role.rb | 4 ++-- app/models/seed.rb | 4 ++-- 9 files changed, 14 insertions(+), 14 deletions(-) diff --git a/app/models/forum.rb b/app/models/forum.rb index f9d7099fe..7cbc0d43d 100644 --- a/app/models/forum.rb +++ b/app/models/forum.rb @@ -1,7 +1,7 @@ class Forum < ActiveRecord::Base extend FriendlyId validates :name, presence: true - friendly_id :name, use: %i[slugged finders] + friendly_id :name, use: %i(slugged finders) has_many :posts belongs_to :owner, class_name: "Member" diff --git a/app/models/garden.rb b/app/models/garden.rb index b5e3b3c55..3a8da5828 100644 --- a/app/models/garden.rb +++ b/app/models/garden.rb @@ -2,7 +2,7 @@ class Garden < ActiveRecord::Base extend FriendlyId include Geocodable include PhotoCapable - friendly_id :garden_slug, use: %i[slugged finders] + friendly_id :garden_slug, use: %i(slugged finders) belongs_to :owner, class_name: 'Member', foreign_key: 'owner_id', counter_cache: true has_many :plantings, dependent: :destroy diff --git a/app/models/harvest.rb b/app/models/harvest.rb index 18fc9b183..8a05561f3 100644 --- a/app/models/harvest.rb +++ b/app/models/harvest.rb @@ -1,9 +1,9 @@ -class Harvest < ApplicationRecord +class Harvest < ActiveRecord::Base include ActionView::Helpers::NumberHelper extend FriendlyId include PhotoCapable - friendly_id :harvest_slug, use: %i[slugged finders] + friendly_id :harvest_slug, use: %i(slugged finders) # Constants UNITS_VALUES = { diff --git a/app/models/member.rb b/app/models/member.rb index f20f73540..5108cf711 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -4,7 +4,7 @@ class Member < ActiveRecord::Base include Geocodable extend FriendlyId - friendly_id :login_name, use: %i[slugged finders] + friendly_id :login_name, use: %i(slugged finders) has_many :posts, foreign_key: 'author_id' has_many :comments, foreign_key: 'author_id' @@ -75,7 +75,7 @@ class Member < ActiveRecord::Base message: "should be between 2 and 25 characters long" }, exclusion: { - in: %w[growstuff admin moderator staff nearby], + in: %w(growstuff admin moderator staff nearby), message: "name is reserved" }, format: { diff --git a/app/models/plant_part.rb b/app/models/plant_part.rb index aa689f8ef..e5045baa8 100644 --- a/app/models/plant_part.rb +++ b/app/models/plant_part.rb @@ -1,6 +1,6 @@ class PlantPart < ActiveRecord::Base extend FriendlyId - friendly_id :name, use: %i[slugged finders] + friendly_id :name, use: %i(slugged finders) has_many :harvests has_many :crops, -> { uniq }, through: :harvests diff --git a/app/models/planting.rb b/app/models/planting.rb index ab95f5042..7156caf05 100644 --- a/app/models/planting.rb +++ b/app/models/planting.rb @@ -1,10 +1,10 @@ class Planting < ActiveRecord::Base extend FriendlyId include PhotoCapable - friendly_id :planting_slug, use: %i[slugged finders] + friendly_id :planting_slug, use: %i(slugged finders) # Constants - SUNNINESS_VALUES = %w[sun semi-shade shade] + SUNNINESS_VALUES = %w(sun semi-shade shade) PLANTED_FROM_VALUES = [ 'seed', 'seedling', diff --git a/app/models/post.rb b/app/models/post.rb index 2b34d4e22..df7303c9e 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -1,7 +1,7 @@ class Post < ActiveRecord::Base extend FriendlyId include Likeable - friendly_id :author_date_subject, use: %i[slugged finders] + friendly_id :author_date_subject, use: %i(slugged finders) belongs_to :author, class_name: 'Member' belongs_to :forum has_many :comments, dependent: :destroy diff --git a/app/models/role.rb b/app/models/role.rb index 1ce887a56..89b940125 100644 --- a/app/models/role.rb +++ b/app/models/role.rb @@ -1,11 +1,11 @@ class Role < ActiveRecord::Base extend FriendlyId - friendly_id :name, use: %i[slugged finders] + friendly_id :name, use: %i(slugged finders) has_and_belongs_to_many :members # rubocop:disable Rails/HasAndBelongsToMany class << self - %i[crop_wranglers admins].each do |method| + %i(crop_wranglers admins).each do |method| define_method method do slug = method.to_s.singularize.dasherize Role.where(slug: slug).try(:first).try(:members) diff --git a/app/models/seed.rb b/app/models/seed.rb index c4ab18e3d..9b2fc510b 100644 --- a/app/models/seed.rb +++ b/app/models/seed.rb @@ -35,7 +35,7 @@ class Seed < ActiveRecord::Base scope :tradable, -> { where.not(tradable_to: 'nowhere') } scope :interesting, -> { tradable.has_location } scope :has_location, -> { joins(:owner).where.not("members.location": nil) } - TRADABLE_TO_VALUES = %w[nowhere locally nationally internationally].freeze + TRADABLE_TO_VALUES = %w(nowhere locally nationally internationally).freeze validates :tradable_to, inclusion: { in: TRADABLE_TO_VALUES, message: "You may only trade seed nowhere, "\ "locally, nationally, or internationally" }, @@ -66,7 +66,7 @@ class Seed < ActiveRecord::Base allow_nil: false, allow_blank: false - HEIRLOOM_VALUES = %w[heirloom hybrid unknown].freeze + HEIRLOOM_VALUES = %w(heirloom hybrid unknown).freeze validates :heirloom, inclusion: { in: HEIRLOOM_VALUES, message: "You must say whether the seeds are heirloom, hybrid, or unknown" }, allow_nil: false, From f2fac9db1bc5b4ccbb112ed4d1e9018854a3c1a9 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 4 Nov 2017 11:33:54 +1300 Subject: [PATCH 37/79] Time.zone.local --- .rubocop.yml | 6 ++++-- spec/factories/harvests.rb | 2 +- spec/factories/planting.rb | 6 +++--- spec/models/planting_spec.rb | 8 ++++---- spec/views/plantings/index.html.haml_spec.rb | 6 +++--- 5 files changed, 15 insertions(+), 13 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index 8bea347fe..8eae6e0b6 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -38,8 +38,10 @@ Metrics/LineLength: Max: 120 -# See https://github.com/bbatsov/rubocop/issues/3629 -Rails/HttpPositionalArguments: +# turn these back on in Rails 5 +Style/FormatStringToken: + Enabled: false +Rails/HttpPositionalArguments: # See https://github.com/bbatsov/rubocop/issues/3629 Enabled: false Style/Documentation: diff --git a/spec/factories/harvests.rb b/spec/factories/harvests.rb index 632dfc5ef..e1ff04fb3 100644 --- a/spec/factories/harvests.rb +++ b/spec/factories/harvests.rb @@ -5,7 +5,7 @@ FactoryBot.define do crop plant_part owner - harvested_at DateTime.new(2015, 9, 17).in_time_zone + harvested_at Time.zone.local(2015, 9, 17) quantity "3" unit "individual" weight_quantity 6 diff --git a/spec/factories/planting.rb b/spec/factories/planting.rb index 3a808e97c..2deb014c5 100644 --- a/spec/factories/planting.rb +++ b/spec/factories/planting.rb @@ -3,7 +3,7 @@ FactoryBot.define do garden owner crop - planted_at DateTime.new(2014, 7, 30).in_time_zone + planted_at Time.zone.local(2014, 7, 30) quantity 33 description "This is a *really* good plant." @@ -33,8 +33,8 @@ FactoryBot.define do factory :finished_planting do finished true - planted_at DateTime.new(2014, 7, 30).in_time_zone - finished_at DateTime.new(2014, 8, 30).in_time_zone + planted_at Time.zone.local(2014, 7, 30) + finished_at Time.zone.local(2014, 8, 30) end end end diff --git a/spec/models/planting_spec.rb b/spec/models/planting_spec.rb index 54cdf296a..cd86b9ae3 100644 --- a/spec/models/planting_spec.rb +++ b/spec/models/planting_spec.rb @@ -338,10 +338,10 @@ describe Planting do # it 'predicts harvest times' do # crop = FactoryBot.create :crop # 10.times do - # planting = FactoryBot.create :planting, crop: crop, planted_at: DateTime.new(2013, 1, 1).in_time_zone - # FactoryBot.create :harvest, crop: crop, planting: planting, harvested_at: DateTime.new(2013, 2, 1).in_time_zone + # planting = FactoryBot.create :planting, crop: crop, planted_at: Time.zone.local(2013, 1, 1) + # FactoryBot.create :harvest, crop: crop, planting: planting, harvested_at: Time.zone.local(2013, 2, 1) # end - # planting = FactoryBot.create :planting, planted_at: DateTime.new(2017, 1, 1).in_time_zone, crop: crop - # expect(planting.harvest_predicted_at).to eq DateTime.new(2017, 2, 1).in_time_zone + # planting = FactoryBot.create :planting, planted_at: Time.zone.local(2017, 1, 1), crop: crop + # expect(planting.harvest_predicted_at).to eq Time.zone.local(2017, 2, 1) # end end diff --git a/spec/views/plantings/index.html.haml_spec.rb b/spec/views/plantings/index.html.haml_spec.rb index 10769548e..e7831889f 100644 --- a/spec/views/plantings/index.html.haml_spec.rb +++ b/spec/views/plantings/index.html.haml_spec.rb @@ -32,12 +32,12 @@ describe "plantings/index" do garden: @garden, crop: @maize, description: '', - planted_at: Time.local(2013, 1, 13)), + planted_at: Time.zone.local(2013, 1, 13)), FactoryBot.create(:planting, garden: @garden, crop: @tomato, - planted_at: Time.local(2013, 1, 13), - finished_at: Time.local(2013, 1, 20), + planted_at: Time.zone.local(2013, 1, 13), + finished_at: Time.zone.local(2013, 1, 20), finished: true) ]) end From 285e6edc61be39daa20a90f5a69bf1f495f93714 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 4 Nov 2017 11:51:19 +1300 Subject: [PATCH 38/79] crop -> sci_names needs dependent:destroy so we don't get orphans --- app/models/crop.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/crop.rb b/app/models/crop.rb index f38910041..25ebcb7d8 100644 --- a/app/models/crop.rb +++ b/app/models/crop.rb @@ -8,7 +8,7 @@ class Crop < ActiveRecord::Base ## ## Relationships - has_many :scientific_names, after_add: :update_index, after_remove: :update_index + has_many :scientific_names, after_add: :update_index, after_remove: :update_index, dependent: :destroy accepts_nested_attributes_for :scientific_names, allow_destroy: true, reject_if: :all_blank has_many :alternate_names, after_add: :update_index, after_remove: :update_index, dependent: :destroy has_many :plantings From 8359218294858993aeee45f16a5864280af609ca Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 4 Nov 2017 11:53:40 +1300 Subject: [PATCH 39/79] Update crop medians after deletion of planting (not before) --- app/controllers/plantings_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/plantings_controller.rb b/app/controllers/plantings_controller.rb index 3b3672c4d..28878ac2d 100644 --- a/app/controllers/plantings_controller.rb +++ b/app/controllers/plantings_controller.rb @@ -63,8 +63,8 @@ class PlantingsController < ApplicationController end def destroy - @planting.crop.update_medians @planting.destroy + @planting.crop.update_medians respond_with @planting, location: @planting.garden end From f5bb47e4ca1f27ace2fedf731dd535481b358d9e Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 4 Nov 2017 15:36:51 +1300 Subject: [PATCH 40/79] DRY plantings controller a bit more - update crop means in one place --- app/controllers/plantings_controller.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/app/controllers/plantings_controller.rb b/app/controllers/plantings_controller.rb index 28878ac2d..50ca83218 100644 --- a/app/controllers/plantings_controller.rb +++ b/app/controllers/plantings_controller.rb @@ -1,6 +1,7 @@ class PlantingsController < ApplicationController before_action :authenticate_member!, except: [:index, :show] after_action :expire_homepage, only: [:create, :update, :destroy] + after_action :update_crop_medians, only: [:create, :update, :destroy] load_and_authorize_resource respond_to :html, :json @@ -52,24 +53,25 @@ class PlantingsController < ApplicationController @planting = Planting.new(planting_params) @planting.owner = current_member @planting.save! - @planting.crop.update_medians respond_with @planting end def update @planting.update(planting_params) - @planting.crop.update_medians respond_with @planting end def destroy @planting.destroy - @planting.crop.update_medians respond_with @planting, location: @planting.garden end private + def update_crop_medians + @planting.crop.update_medians + end + def planting_params params[:planted_at] = parse_date(params[:planted_at]) if params[:planted_at] params.require(:planting).permit( From d5a1a683f1c860700ca357ed9330f4fac77a58dd Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 4 Nov 2017 15:44:56 +1300 Subject: [PATCH 41/79] Rubocop fix --- app/controllers/plantings_controller.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/controllers/plantings_controller.rb b/app/controllers/plantings_controller.rb index 50ca83218..0364f39d6 100644 --- a/app/controllers/plantings_controller.rb +++ b/app/controllers/plantings_controller.rb @@ -1,7 +1,7 @@ class PlantingsController < ApplicationController - before_action :authenticate_member!, except: [:index, :show] - after_action :expire_homepage, only: [:create, :update, :destroy] - after_action :update_crop_medians, only: [:create, :update, :destroy] + before_action :authenticate_member!, except: %i(index show) + after_action :expire_homepage, only: %i(create update destroy) + after_action :update_crop_medians, only: %i(create update destroy) load_and_authorize_resource respond_to :html, :json From 2422939b4ff69fd946fcf5bb02450c2f05a17ae4 Mon Sep 17 00:00:00 2001 From: deppbot Date: Sat, 4 Nov 2017 12:13:31 +0800 Subject: [PATCH 42/79] Bundle Update on 2017-11-04 --- Gemfile.lock | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index e06468efe..9920056c7 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -93,7 +93,7 @@ GEM capybara-email (2.5.0) capybara (~> 2.4) mail - capybara-screenshot (1.0.17) + capybara-screenshot (1.0.18) capybara (>= 1.0, < 3) launchy childprocess (0.8.0) @@ -247,7 +247,7 @@ GEM ruby_parser (~> 3.5) httparty (0.15.6) multi_xml (>= 0.5.2) - i18n (0.9.0) + i18n (0.9.1) concurrent-ruby (~> 1.0) i18n-tasks (0.9.12) activesupport (>= 4.0.2) @@ -305,8 +305,8 @@ GEM crass (~> 1.0.2) nokogiri (>= 1.5.9) lumberjack (1.0.12) - mail (2.6.6) - mime-types (>= 1.16, < 4) + mail (2.7.0) + mini_mime (>= 0.1.1) memcachier (0.0.2) method_source (0.9.0) mime-types (3.1) @@ -473,7 +473,7 @@ GEM sprockets (>= 2.8, < 4.0) sprockets-rails (>= 2.0, < 4.0) tilt (>= 1.1, < 3) - selenium-webdriver (3.6.0) + selenium-webdriver (3.7.0) childprocess (~> 0.5) rubyzip (~> 1.0) sexp_processor (4.10.0) @@ -622,6 +622,7 @@ DEPENDENCIES will_paginate xmlrpc + RUBY VERSION ruby 2.4.1p111 From 5e5773aa5998e7b8773a35a3d765b831c751cdf7 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 5 Nov 2017 12:52:02 +1300 Subject: [PATCH 43/79] feature spec for displaying annual/perennial on crops#show --- app/views/crops/show.html.haml | 15 ++++++++------- spec/factories/crop.rb | 7 +++++++ spec/features/crops/crop_detail_page_spec.rb | 19 +++++++++++++++++++ 3 files changed, 34 insertions(+), 7 deletions(-) diff --git a/app/views/crops/show.html.haml b/app/views/crops/show.html.haml index 4ac071ae9..6006cb6df 100644 --- a/app/views/crops/show.html.haml +++ b/app/views/crops/show.html.haml @@ -34,13 +34,14 @@ = render partial: 'photos', locals: { crop: @crop } - %h2 - #{@crop.name} is - = link_to 'https://en.wikipedia.org/wiki/Annual_vs._perennial_plant_evolution' do - - if @crop.perennial - perennial (living more than two years) - - else - annual (living and reproducing in a single year or less) + - unless @crop.perennial.nil? + %h2 + #{@crop.name} is + = link_to 'https://en.wikipedia.org/wiki/Annual_vs._perennial_plant_evolution' do + - if @crop.perennial == true + perennial (living more than two years) + - elsif @crop.perennial == false + annual (living and reproducing in a single year or less) %h2 - if !@crop.plantings.empty? diff --git a/spec/factories/crop.rb b/spec/factories/crop.rb index c6f095354..2a8c6b656 100644 --- a/spec/factories/crop.rb +++ b/spec/factories/crop.rb @@ -5,6 +5,13 @@ FactoryBot.define do approval_status "approved" creator + factory :annual_crop, parent: :crop do + perennial false + end + factory :perennial_crop, parent: :crop do + perennial true + end + factory :tomato do name "tomato" en_wikipedia_url "http://en.wikipedia.org/wiki/Tomato" diff --git a/spec/features/crops/crop_detail_page_spec.rb b/spec/features/crops/crop_detail_page_spec.rb index cf2d3f502..4c5332c83 100644 --- a/spec/features/crops/crop_detail_page_spec.rb +++ b/spec/features/crops/crop_detail_page_spec.rb @@ -168,4 +168,23 @@ feature "crop detail page", js: true do expect(current_path).to eq seeds_by_owner_path(owner: member.slug) end end + + context 'annual and perennial' do + before { visit crop_path(crop) } + context 'crop is an annual' do + let(:crop) { FactoryBot.create :annual_crop } + it { expect(page).to have_text 'annual (living and reproducing in a single year or less)' } + it { expect(page).not_to have_text 'perennial (living more than two years) ' } + end + context 'crop is perennial' do + let(:crop) { FactoryBot.create :perennial_crop } + it { expect(page).to have_text 'perennial (living more than two years) ' } + it { expect(page).not_to have_text 'annual (living and reproducing in a single year or less)' } + end + context 'crop perennial value is null' do + let(:crop) { FactoryBot.create :crop, perennial: nil } + it { expect(page).not_to have_text 'perennial (living more than two years) ' } + it { expect(page).not_to have_text 'annual (living and reproducing in a single year or less)' } + end + end end From 4cc0f77bd07a10b1616d23aba1532945b54aeb13 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 5 Nov 2017 13:42:30 +1300 Subject: [PATCH 44/79] Predicting first harvest - updating medians --- app/controllers/harvests_controller.rb | 12 +++++++++++- app/controllers/plantings_controller.rb | 2 +- app/models/crop.rb | 8 ++++++-- app/models/planting.rb | 7 +++++++ db/migrate/20171022032108_all_the_predictions.rb | 9 +++++++++ db/schema.rb | 4 ++++ 6 files changed, 38 insertions(+), 4 deletions(-) diff --git a/app/controllers/harvests_controller.rb b/app/controllers/harvests_controller.rb index 1601e04cb..4b7695854 100644 --- a/app/controllers/harvests_controller.rb +++ b/app/controllers/harvests_controller.rb @@ -1,5 +1,6 @@ class HarvestsController < ApplicationController - before_action :authenticate_member!, except: [:index, :show] + before_action :authenticate_member!, except: %i(index show) + after_action :update_crop_medians, only: %i(create update destroy) load_and_authorize_resource respond_to :html, :json respond_to :csv, only: :index @@ -83,4 +84,13 @@ class HarvestsController < ApplicationController end "Growstuff-#{specifics}Harvests-#{Time.zone.now.to_s(:number)}.csv" end + + def update_crop_medians + # We only update medians to predict plantings + # if this harvest is not linked to a planting, then do nothing + return if @harvest.planting.nil? + + @harvest.planting.update_harvest_days + @harvest.crop.update_harvest_medians + end end diff --git a/app/controllers/plantings_controller.rb b/app/controllers/plantings_controller.rb index 0364f39d6..e2b483c46 100644 --- a/app/controllers/plantings_controller.rb +++ b/app/controllers/plantings_controller.rb @@ -69,7 +69,7 @@ class PlantingsController < ApplicationController private def update_crop_medians - @planting.crop.update_medians + @planting.crop.update_lifespan_medians end def planting_params diff --git a/app/models/crop.rb b/app/models/crop.rb index 25ebcb7d8..da9baeffe 100644 --- a/app/models/crop.rb +++ b/app/models/crop.rb @@ -211,11 +211,15 @@ class Crop < ActiveRecord::Base where(["lower(crops.name) = :value", { value: name.downcase }]) end - def update_medians - # byebug + def update_lifespan_medians + # Median lifespan of plantings update(median_lifespan: Planting.where(crop: self).median(:lifespan)) end + def update_harvest_medians + update(median_first_harvest: Planting.where(crop: self).median(:first_harvest)) + end + private def count_uses_of_property(col_name) diff --git a/app/models/planting.rb b/app/models/planting.rb index 7156caf05..8d41e9bd2 100644 --- a/app/models/planting.rb +++ b/app/models/planting.rb @@ -113,6 +113,13 @@ class Planting < ActiveRecord::Base 100 end + def update_harvest_days + # how long ago was this planted + first_harvest = (harvests.first.harvested_at - planted_at).to_i + last_harvest = finished? ? (harvests.last.harvested_at - planted_at).to_i : nil + update(first_harvest: first_harvest, last_harvest: last_harvest) + end + private # check that any finished_at date occurs after planted_at diff --git a/db/migrate/20171022032108_all_the_predictions.rb b/db/migrate/20171022032108_all_the_predictions.rb index 92e0e7ba4..4b7b22a88 100644 --- a/db/migrate/20171022032108_all_the_predictions.rb +++ b/db/migrate/20171022032108_all_the_predictions.rb @@ -2,8 +2,17 @@ class AllThePredictions < ActiveRecord::Migration def change add_column :crops, :perennial, :boolean, default: false + # time from planted, to finished add_column :plantings, :lifespan, :integer + + # how old was planting at first harvest + add_column :plantings, :first_harvest, :integer + add_column :plantings, :last_harvest, :integer + + # Keep the median values for the crop add_column :crops, :median_lifespan, :integer + add_column :crops, :median_first_harvest, :integer + add_column :crops, :median_last_harvest, :integer create_table :median_functions do |t| end diff --git a/db/schema.rb b/db/schema.rb index c76e230e4..3508f9b1a 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -196,6 +196,8 @@ ActiveRecord::Schema.define(version: 20171028230429) do t.text "rejection_notes" t.boolean "perennial", default: false t.integer "median_lifespan" + t.integer "median_first_harvest" + t.integer "median_last_harvest" end add_index "crops", ["name"], name: "index_crops_on_name", using: :btree @@ -429,6 +431,8 @@ ActiveRecord::Schema.define(version: 20171028230429) do t.date "finished_at" t.integer "days_before_maturity" t.integer "lifespan" + t.integer "first_harvest" + t.integer "last_harvest" end add_index "plantings", ["slug"], name: "index_plantings_on_slug", unique: true, using: :btree From 53d7fd1479ebc7dc370789388472e76acd1d9bb6 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 5 Nov 2017 13:43:00 +1300 Subject: [PATCH 45/79] Displaying predicted first harvest on plantings and crops --- app/views/crops/_index_card.html.haml | 21 +++++++++--- app/views/crops/show.html.haml | 46 +++++++++++++++++++-------- app/views/plantings/show.html.haml | 15 +++++++-- 3 files changed, 62 insertions(+), 20 deletions(-) diff --git a/app/views/crops/_index_card.html.haml b/app/views/crops/_index_card.html.haml index 7554e7caf..6bfb95cfe 100644 --- a/app/views/crops/_index_card.html.haml +++ b/app/views/crops/_index_card.html.haml @@ -17,10 +17,23 @@ Planted = pluralize(crop.plantings.size, "time") by #{ENV['GROWSTUFF_SITE_NAME']} members - %p - Median Lifespan - %b= crop.median_lifespan - days + + - unless crop.median_lifespan.nil? + %p + Median Lifespan + %b= crop.median_lifespan + days + - unless crop.median_first_harvest.nil? + %p + First harvest expected after + %b= crop.median_first_harvest + days + + - if crop.perennial == false && crop.median_last_harvest.present? + %p + Last harvest expected after + %b= crop.median_last_harvest + days - if can? :create, Planting = link_to 'Plant this', new_planting_path(params: { crop_id: crop.id }), class: 'btn btn-primary' diff --git a/app/views/crops/show.html.haml b/app/views/crops/show.html.haml index 6006cb6df..e507cb720 100644 --- a/app/views/crops/show.html.haml +++ b/app/views/crops/show.html.haml @@ -20,28 +20,48 @@ - if can? :create, Seed = link_to 'Add seeds to stash', new_seed_path(params: { crop_id: @crop.id }), class: 'btn btn-default' - - if member_signed_in? - = display_seed_availability(@current_member, @crop) - = link_to "View your seeds", seeds_by_owner_path(owner: current_member.slug) .row .col-md-9 + - if member_signed_in? + = display_seed_availability(@current_member, @crop) + = link_to "View your seeds", seeds_by_owner_path(owner: current_member.slug) + %h2 Predictions + - unless @crop.perennial.nil? + %p + #{@crop.name} is + - if @crop.perennial == true + = link_to 'https://en.wikipedia.org/wiki/Annual_vs._perennial_plant_evolution' do + a perennial crop + (living more than two years) + - elsif @crop.perennial == false + = link_to 'https://en.wikipedia.org/wiki/Annual_vs._perennial_plant_evolution' do + an annual crop + (living and reproducing in a single year or less) + - unless @crop.median_lifespan.nil? + %p + Median Lifespan of #{@crop.name} plants is + %b= @crop.median_lifespan + days + - unless @crop.median_first_harvest.nil? + %p + First harvest expected after + %b= @crop.median_first_harvest + days + + - if @crop.perennial == false && @crop.median_last_harvest.present? + %p + Last harvest expected after + %b= @crop.median_last_harvest + days + - unless current_member Learn how to grow #{@crop.name.pluralize} from growers around the world. #{ENV['GROWSTUFF_SITE_NAME']} has tips and advice from real-life growers, including when to plant #{@crop.name.pluralize}, how to harvest #{@crop.name.pluralize}, and more. - = render partial: 'photos', locals: { crop: @crop } - - - unless @crop.perennial.nil? - %h2 - #{@crop.name} is - = link_to 'https://en.wikipedia.org/wiki/Annual_vs._perennial_plant_evolution' do - - if @crop.perennial == true - perennial (living more than two years) - - elsif @crop.perennial == false - annual (living and reproducing in a single year or less) + %p= render 'crops/photos', crop: @crop %h2 - if !@crop.plantings.empty? diff --git a/app/views/plantings/show.html.haml b/app/views/plantings/show.html.haml index 56cfedc08..74d0508f2 100644 --- a/app/views/plantings/show.html.haml +++ b/app/views/plantings/show.html.haml @@ -41,18 +41,27 @@ = sunniness - unless @planting.crop.perennial - %dt Finished: - %dd= display_finished(@planting) %dt Predicted finish: %dd - if @planting.finish_predicted_at.present? = @planting.finish_predicted_at - else - Set planted date to get predictions + %strong Set planted date to get predictions + %dt Finished: + %dd= display_finished(@planting) + - if @planting.crop.median_lifespan.present? + %dt Expected Lifespan: + %dd #{@planting.crop.median_lifespan} days - if @planting.lifespan.present? %dt Lifespan: %dd #{@planting.lifespan} days + - if @planting.first_harvest.present? + %dt First Harvest: + %dd #{@planting.first_harvest} days old + - if @planting.last_harvest.present? + %dt Last Harvest: + %dd #{@planting.last_harvest} days old %p= render 'plantings/harvests', planting: @planting %p= render 'plantings/progress', planting: @planting, show_explanation: true From eb585611fe9b77dedb1f4e46edf01886dfc584f8 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 5 Nov 2017 14:05:54 +1300 Subject: [PATCH 46/79] Fixed spec to call update_lifespan_medians --- spec/models/planting_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/models/planting_spec.rb b/spec/models/planting_spec.rb index cd86b9ae3..75f0b4edb 100644 --- a/spec/models/planting_spec.rb +++ b/spec/models/planting_spec.rb @@ -27,7 +27,7 @@ describe Planting do FactoryBot.create :planting, crop: planting.crop, planted_at: 100.days.ago, finished_at: 51.days.ago FactoryBot.create :planting, crop: planting.crop, planted_at: 2.years.ago, finished_at: 50.days.ago FactoryBot.create :planting, crop: planting.crop, planted_at: 150.days.ago, finished_at: 100.days.ago - planting.crop.update_medians + planting.crop.update_lifespan_medians end it { expect(planting.crop.median_lifespan).to eq 50 } From ec00baef0d2e7637a96b3e815b5b1fd1719bf2bc Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 5 Nov 2017 14:07:33 +1300 Subject: [PATCH 47/79] Updated feature spec to look for new annual/perennial text --- spec/features/crops/crop_detail_page_spec.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/spec/features/crops/crop_detail_page_spec.rb b/spec/features/crops/crop_detail_page_spec.rb index 4c5332c83..5f0fa2ba4 100644 --- a/spec/features/crops/crop_detail_page_spec.rb +++ b/spec/features/crops/crop_detail_page_spec.rb @@ -173,18 +173,18 @@ feature "crop detail page", js: true do before { visit crop_path(crop) } context 'crop is an annual' do let(:crop) { FactoryBot.create :annual_crop } - it { expect(page).to have_text 'annual (living and reproducing in a single year or less)' } - it { expect(page).not_to have_text 'perennial (living more than two years) ' } + it { expect(page).to have_text 'annual crop (living and reproducing in a single year or less)' } + it { expect(page).not_to have_text 'perennial crop (living more than two years)' } end context 'crop is perennial' do let(:crop) { FactoryBot.create :perennial_crop } - it { expect(page).to have_text 'perennial (living more than two years) ' } - it { expect(page).not_to have_text 'annual (living and reproducing in a single year or less)' } + it { expect(page).to have_text 'perennial crop (living more than two years)' } + it { expect(page).not_to have_text 'annual crop (living and reproducing in a single year or less)' } end context 'crop perennial value is null' do let(:crop) { FactoryBot.create :crop, perennial: nil } - it { expect(page).not_to have_text 'perennial (living more than two years) ' } - it { expect(page).not_to have_text 'annual (living and reproducing in a single year or less)' } + it { expect(page).not_to have_text 'perennial crop (living more than two years)' } + it { expect(page).not_to have_text 'annual crop (living and reproducing in a single year or less)' } end end end From b1684b0156cddd7bc81fdce824bbdd93478f60b7 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 5 Nov 2017 14:14:53 +1300 Subject: [PATCH 48/79] Set prediction data for existing planting and crops --- db/migrate/20171105011017_set_prediction_data.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 db/migrate/20171105011017_set_prediction_data.rb diff --git a/db/migrate/20171105011017_set_prediction_data.rb b/db/migrate/20171105011017_set_prediction_data.rb new file mode 100644 index 000000000..ac3a8089d --- /dev/null +++ b/db/migrate/20171105011017_set_prediction_data.rb @@ -0,0 +1,11 @@ +class SetPredictionData < ActiveRecord::Migration + def change + say "Updating all plantings time to first harvest" + Planting.all.each(&:update_harvest_days) + say "Updating crop median time to first harvest, and lifespan" + Crop.all.each do |crop| + crop.update_lifespan_medians + crop.update_harvest_medians + end + end +end From 9d11bcc0399fc4bf0ff772980bb63b481ef8bc2c Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 5 Nov 2017 16:20:51 +1300 Subject: [PATCH 49/79] Can't calculate first harvest if there are no harvests --- app/models/planting.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/models/planting.rb b/app/models/planting.rb index 8d41e9bd2..a33b82b31 100644 --- a/app/models/planting.rb +++ b/app/models/planting.rb @@ -114,6 +114,7 @@ class Planting < ActiveRecord::Base end def update_harvest_days + return unless harvests.size.positive? # how long ago was this planted first_harvest = (harvests.first.harvested_at - planted_at).to_i last_harvest = finished? ? (harvests.last.harvested_at - planted_at).to_i : nil From 996706ee785789e4de8448f77244f00310b9aeb9 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 5 Nov 2017 16:45:02 +1300 Subject: [PATCH 50/79] Tests for planting lifespan predictions when there's no crop data --- app/models/planting.rb | 12 ++++++++---- db/schema.rb | 2 +- spec/models/planting_spec.rb | 27 ++++++++++++++++++++++++--- 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/app/models/planting.rb b/app/models/planting.rb index a33b82b31..eeb880cda 100644 --- a/app/models/planting.rb +++ b/app/models/planting.rb @@ -114,10 +114,14 @@ class Planting < ActiveRecord::Base end def update_harvest_days - return unless harvests.size.positive? - # how long ago was this planted - first_harvest = (harvests.first.harvested_at - planted_at).to_i - last_harvest = finished? ? (harvests.last.harvested_at - planted_at).to_i : nil + if harvests.size.positive? + # how long ago was this planted + first_harvest = (harvests.first.harvested_at - planted_at).to_i + last_harvest = finished? ? (harvests.last.harvested_at - planted_at).to_i : nil + else + first_harvest = nil + last_harvest = nil + end update(first_harvest: first_harvest, last_harvest: last_harvest) end diff --git a/db/schema.rb b/db/schema.rb index 3508f9b1a..945ce107e 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20171028230429) do +ActiveRecord::Schema.define(version: 20171105011017) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" diff --git a/spec/models/planting_spec.rb b/spec/models/planting_spec.rb index 75f0b4edb..0a744a92e 100644 --- a/spec/models/planting_spec.rb +++ b/spec/models/planting_spec.rb @@ -9,17 +9,38 @@ describe Planting do FactoryBot.create :planting, planted_at: 4.days.ago, finished_at: 2.days.ago, finished: true end - describe 'predictions' do - context 'no previous data' do + describe 'planting lifespan predictions' do + context 'no predications data yet' do describe 'planting planted, not finished' do + let(:planting) { FactoryBot.create :planting, planted_at: 30.days.ago, finished_at: nil, finished: false } + it { expect(planting.crop.median_lifespan).to eq(nil) } + it { expect(planting.expected_lifespan).to eq(nil) } + it { expect(planting.days_since_planted).to eq(30) } + it { expect(planting.percentage_grown).to eq(nil) } end describe 'planting not planted yet' do + let(:planting) { FactoryBot.create :planting, planted_at: nil, finished_at: nil, finished: false } + it { expect(planting.crop.median_lifespan).to eq(nil) } + it { expect(planting.expected_lifespan).to eq(nil) } + it { expect(planting.days_since_planted).to eq(nil) } + it { expect(planting.percentage_grown).to eq(nil) } end describe 'planting finished, no planted_at' do + let(:planting) { FactoryBot.create :planting, planted_at: nil, finished_at: 1.day.ago, finished: true } + it { expect(planting.crop.median_lifespan).to eq(nil) } + it { expect(planting.expected_lifespan).to eq(nil) } + it { expect(planting.days_since_planted).to eq(nil) } + it { expect(planting.percentage_grown).to eq(100) } end - describe 'planing all finished' do + describe 'planting all finished' do + let(:planting) { FactoryBot.create :planting, planted_at: 30.days.ago, finished_at: 1.day.ago, finished: true } + it { expect(planting.crop.median_lifespan).to eq(nil) } + it { expect(planting.expected_lifespan).to eq(29) } + it { expect(planting.days_since_planted).to eq(30) } + it { expect(planting.percentage_grown).to eq(100) } end end + context 'lots of data' do before do FactoryBot.create :planting, crop: planting.crop, planted_at: 10.days.ago From 9b1b22afa80f2ecb388d0e616d1e4deeb4c8df60 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 5 Nov 2017 17:33:58 +1300 Subject: [PATCH 51/79] Bugfix and specs for first and last harvest --- app/models/harvest.rb | 3 +- app/models/planting.rb | 13 +++++---- spec/models/planting_spec.rb | 53 ++++++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 7 deletions(-) diff --git a/app/models/harvest.rb b/app/models/harvest.rb index 8a05561f3..12b116296 100644 --- a/app/models/harvest.rb +++ b/app/models/harvest.rb @@ -39,13 +39,14 @@ class Harvest < ActiveRecord::Base ## ## Scopes - default_scope { joins(:owner).order(created_at: :desc) } + default_scope { joins(:owner) } ## ## Validations validates :crop, approved: true validates :crop, presence: { message: "must be present and exist in our database" } validates :plant_part, presence: { message: "must be present and exist in our database" } + validates :harvested_at, presence: true validate :crop_must_match_planting validate :harvest_must_be_after_planting validates :quantity, numericality: { diff --git a/app/models/planting.rb b/app/models/planting.rb index eeb880cda..2c788c047 100644 --- a/app/models/planting.rb +++ b/app/models/planting.rb @@ -96,7 +96,7 @@ class Planting < ActiveRecord::Base def expected_lifespan if planted_at.present? && finished_at.present? - return finished_at - planted_at + return (finished_at - planted_at).to_i end crop.median_lifespan end @@ -114,13 +114,14 @@ class Planting < ActiveRecord::Base end def update_harvest_days + first_harvest = nil + last_harvest = nil if harvests.size.positive? # how long ago was this planted - first_harvest = (harvests.first.harvested_at - planted_at).to_i - last_harvest = finished? ? (harvests.last.harvested_at - planted_at).to_i : nil - else - first_harvest = nil - last_harvest = nil + first_harvest = (harvests.order(harvested_at: :asc).limit(1).first.harvested_at - planted_at).to_i + if finished? + last_harvest = (harvests.order(harvested_at: :desc).limit(1).first.harvested_at - planted_at).to_i + end end update(first_harvest: first_harvest, last_harvest: last_harvest) end diff --git a/spec/models/planting_spec.rb b/spec/models/planting_spec.rb index 0a744a92e..6d0910707 100644 --- a/spec/models/planting_spec.rb +++ b/spec/models/planting_spec.rb @@ -79,6 +79,59 @@ describe Planting do end end + describe 'planting first harvest preductions' do + context 'no data' do + let(:planting) { FactoryBot.create :planting } + it { expect(planting.crop.median_first_harvest).to eq(nil) } + it { expect(planting.first_harvest).to eq(nil) } + it { expect(planting.expected_lifespan).to eq(nil) } + end + context 'lots of data' do + def one_hundred_day_old_planting + FactoryBot.create(:planting, crop: planting.crop, planted_at: 100.days.ago) + end + before do + # 50 days to harvest + FactoryBot.create(:harvest, harvested_at: 50.days.ago, crop: planting.crop, + planting: one_hundred_day_old_planting) + # 20 days to harvest + FactoryBot.create(:harvest, harvested_at: 80.days.ago, crop: planting.crop, + planting: one_hundred_day_old_planting) + # 10 days to harvest + FactoryBot.create(:harvest, harvested_at: 90.days.ago, crop: planting.crop, + planting: one_hundred_day_old_planting) + planting.crop.plantings.each(&:update_harvest_days) + planting.crop.update_lifespan_medians + planting.crop.update_harvest_medians + end + it { expect(planting.crop.median_first_harvest).to eq(20) } + end + describe 'planting has no harvests' do + before { planting.update_harvest_days } + let(:planting) { FactoryBot.create :planting } + it { expect(planting.first_harvest).to eq(nil) } + end + describe 'planting has first harvest' do + let(:planting) { FactoryBot.create :planting, planted_at: 100.days.ago } + before do + FactoryBot.create :harvest, planting: planting, crop: planting.crop, harvested_at: 10.days.ago + planting.update_harvest_days + end + it { expect(planting.first_harvest).to eq(90) } + it { expect(planting.last_harvest).to eq(nil) } + end + describe 'planting has last harvest' do + let(:planting) { FactoryBot.create :planting, planted_at: 100.days.ago, finished_at: 1.day.ago, finished: true } + before do + FactoryBot.create :harvest, planting: planting, crop: planting.crop, harvested_at: 90.days.ago + FactoryBot.create :harvest, planting: planting, crop: planting.crop, harvested_at: 10.days.ago + planting.update_harvest_days + end + it { expect(planting.first_harvest).to eq(10) } + it { expect(planting.last_harvest).to eq(90) } + end + end + it 'has an owner' do planting.owner.should be_an_instance_of Member end From b3fd8e32d047aba1aec1f3c03320ca07506c3b8b Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 5 Nov 2017 17:42:59 +1300 Subject: [PATCH 52/79] Fixed ordering of Harvests - don't order in scope. --- app/controllers/harvests_controller.rb | 5 +++-- spec/controllers/harvests_controller_spec.rb | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/app/controllers/harvests_controller.rb b/app/controllers/harvests_controller.rb index 4b7695854..9b148c3f5 100644 --- a/app/controllers/harvests_controller.rb +++ b/app/controllers/harvests_controller.rb @@ -34,6 +34,7 @@ class HarvestsController < ApplicationController def create @harvest.crop_id = @harvest.planting.crop_id if @harvest.planting_id + @harvest.harvested_at = Time.zone.now if @harvest.harvested_at.blank? @harvest.save respond_with(@harvest) end @@ -72,8 +73,8 @@ class HarvestsController < ApplicationController elsif @planting @planting.harvests else - Harvest - end.joins(:owner, :crop).paginate(page: params[:page]) + Harvest.all + end.order(harvested_at: :desc).joins(:owner, :crop).paginate(page: params[:page]) end def csv_filename diff --git a/spec/controllers/harvests_controller_spec.rb b/spec/controllers/harvests_controller_spec.rb index a42d11f69..ff4972a7a 100644 --- a/spec/controllers/harvests_controller_spec.rb +++ b/spec/controllers/harvests_controller_spec.rb @@ -19,7 +19,8 @@ describe HarvestsController do { owner_id: subject.current_member.id, crop_id: FactoryBot.create(:crop).id, - plant_part_id: FactoryBot.create(:plant_part).id + plant_part_id: FactoryBot.create(:plant_part).id, + harvested_at: '2017-01-01' } end From 136c082003d6611ec3ee7f0676b5c794f103dad8 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 5 Nov 2017 17:47:19 +1300 Subject: [PATCH 53/79] Smaller photos on crop page. Fits in the predictions data --- app/views/crops/_index_card.html.haml | 4 +--- app/views/crops/_photos.html.haml | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/app/views/crops/_index_card.html.haml b/app/views/crops/_index_card.html.haml index 6bfb95cfe..4083a72a8 100644 --- a/app/views/crops/_index_card.html.haml +++ b/app/views/crops/_index_card.html.haml @@ -13,9 +13,7 @@ %b Scientific name: = crop.default_scientific_name %p - %b - Planted - = pluralize(crop.plantings.size, "time") + %b Planted #{pluralize(crop.plantings.size, "time")} by #{ENV['GROWSTUFF_SITE_NAME']} members - unless crop.median_lifespan.nil? diff --git a/app/views/crops/_photos.html.haml b/app/views/crops/_photos.html.haml index 8bd6cf169..0d06daf3c 100644 --- a/app/views/crops/_photos.html.haml +++ b/app/views/crops/_photos.html.haml @@ -1,15 +1,15 @@ -%h2 Photos of #{crop.name} harvests -.row - - unless crop.harvest_photos.empty? - - crop.harvest_photos.includes(:owner).first(3).each do |p| - .col-md-4 +- unless crop.harvest_photos.empty? + %h3 Photos of #{crop.name} harvests + .row + - crop.harvest_photos.includes(:owner).first(6).each do |p| + .col-xs-6.col-md-2 = render "photos/thumbnail", photo: p -%h2 Photos of #{crop.name} plants -.row - - unless crop.photos.empty? - - crop.photos.includes(:owner).first(3).each do |p| - .col-md-4 +- unless crop.photos.empty? + %h3 Photos of #{crop.name} plants + .row + - crop.photos.includes(:owner).first(6).each do |p| + .col-xs-6.col-md-2 = render "photos/thumbnail", photo: p .row = link_to "more photos", crop_photos_path(crop_id: crop.id) From 26537943e3d2df4df85c0a67878318dadd88bccb Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 5 Nov 2017 18:00:49 +1300 Subject: [PATCH 54/79] Removed pending spec --- spec/models/harvest_spec.rb | 6 ------ 1 file changed, 6 deletions(-) diff --git a/spec/models/harvest_spec.rb b/spec/models/harvest_spec.rb index 19d3dea89..6229a1cc0 100644 --- a/spec/models/harvest_spec.rb +++ b/spec/models/harvest_spec.rb @@ -302,10 +302,4 @@ describe Harvest do member.destroy expect(Harvest.joins(:owner).all).not_to include(harvest) end - - pending 'sets planting harvested_at date' do - planting = FactoryGirl.create :planting - harvest = FactoryGirl.create :harvest, planting: planting, crop: planting.crop - expect(harvest.harvested_at).to eq(planting.harvested_at) - end end From 6c33c335d813526a0d9aa0fc6cd6ae545efff156 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 5 Nov 2017 19:26:50 +1300 Subject: [PATCH 55/79] Default ordering for harvests are gone, so order it in spec --- spec/models/harvest_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/models/harvest_spec.rb b/spec/models/harvest_spec.rb index 6229a1cc0..1944c6365 100644 --- a/spec/models/harvest_spec.rb +++ b/spec/models/harvest_spec.rb @@ -142,7 +142,7 @@ describe Harvest do it 'lists most recent harvests first' do @h1 = FactoryBot.create(:harvest, created_at: 1.day.ago) @h2 = FactoryBot.create(:harvest, created_at: 1.hour.ago) - Harvest.all.should eq [@h2, @h1] + Harvest.all.order(created_at: :desc).should eq [@h2, @h1] end end From 35e7b6a5b49a388cc9a313e29eeb1b6846436026 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 5 Nov 2017 19:55:00 +1300 Subject: [PATCH 56/79] Removed an ignore from rubocop --- .rubocop.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index 8eae6e0b6..13d9906ec 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -37,10 +37,7 @@ Style/AlignParameters: Metrics/LineLength: Max: 120 - # turn these back on in Rails 5 -Style/FormatStringToken: - Enabled: false Rails/HttpPositionalArguments: # See https://github.com/bbatsov/rubocop/issues/3629 Enabled: false From e844eade9467f9b90ba0a10f5f4c682dd9f74ce1 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 5 Nov 2017 20:09:21 +1300 Subject: [PATCH 57/79] Changed model validators message to please Hound --- app/models/garden.rb | 2 +- app/models/harvest.rb | 22 ++++++++++------------ app/models/planting.rb | 4 ++-- 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/app/models/garden.rb b/app/models/garden.rb index 3a8da5828..571eca7ba 100644 --- a/app/models/garden.rb +++ b/app/models/garden.rb @@ -41,7 +41,7 @@ class Garden < ActiveRecord::Base "acres" => "acre" }.freeze validates :area_unit, inclusion: { in: AREA_UNITS_VALUES.values, - message: "%{value} is not a valid area unit" }, + message: "%s is not a valid area unit" }, allow_nil: true, allow_blank: true diff --git a/app/models/harvest.rb b/app/models/harvest.rb index 12b116296..21339ab47 100644 --- a/app/models/harvest.rb +++ b/app/models/harvest.rb @@ -47,20 +47,18 @@ class Harvest < ActiveRecord::Base validates :crop, presence: { message: "must be present and exist in our database" } validates :plant_part, presence: { message: "must be present and exist in our database" } validates :harvested_at, presence: true + validates :quantity, allow_nil: true, numericality: { + only_integer: false, greater_than_or_equal_to: 0 + } + validates :unit, allow_nil: true, allow_blank: true, inclusion: { + in: UNITS_VALUES.values, message: "%s is not a valid unit" + } + validates :weight_quantity, allow_nil: true, numericality: { only_integer: false } + validates :weight_unit, allow_nil: true, allow_blank: true, inclusion: { + in: WEIGHT_UNITS_VALUES.values, message: "%s is not a valid unit" + } validate :crop_must_match_planting validate :harvest_must_be_after_planting - validates :quantity, numericality: { - only_integer: false, greater_than_or_equal_to: 0 - }, allow_nil: true - validates :unit, inclusion: { - in: UNITS_VALUES.values, - message: "%{value} is not a valid unit" - }, allow_nil: true, allow_blank: true - validates :weight_quantity, numericality: { only_integer: false }, allow_nil: true - validates :weight_unit, inclusion: { - in: WEIGHT_UNITS_VALUES.values, - message: "%{value} is not a valid unit" - }, allow_nil: true, allow_blank: true def time_from_planting_to_harvest return if planting.blank? diff --git a/app/models/planting.rb b/app/models/planting.rb index 2c788c047..cfff1550f 100644 --- a/app/models/planting.rb +++ b/app/models/planting.rb @@ -54,10 +54,10 @@ class Planting < ActiveRecord::Base only_integer: true, greater_than_or_equal_to: 0 } validates :sunniness, allow_nil: true, allow_blank: true, inclusion: { - in: SUNNINESS_VALUES, message: "%{value} is not a valid sunniness value" + in: SUNNINESS_VALUES, message: "%s is not a valid sunniness value" } validates :planted_from, allow_nil: true, allow_blank: true, inclusion: { - in: PLANTED_FROM_VALUES, message: "%{value} is not a valid planting method" + in: PLANTED_FROM_VALUES, message: "%s is not a valid planting method" } def planting_slug From eaa65fda9ed8e626915f2a63bf5f7a6128a6b718 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 5 Nov 2017 20:28:51 +1300 Subject: [PATCH 58/79] update median_last_harvest too, with specs --- app/models/crop.rb | 1 + spec/models/planting_spec.rb | 14 +++++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/app/models/crop.rb b/app/models/crop.rb index da9baeffe..7cdb0b592 100644 --- a/app/models/crop.rb +++ b/app/models/crop.rb @@ -218,6 +218,7 @@ class Crop < ActiveRecord::Base def update_harvest_medians update(median_first_harvest: Planting.where(crop: self).median(:first_harvest)) + update(median_last_harvest: Planting.where(crop: self).median(:last_harvest)) end private diff --git a/spec/models/planting_spec.rb b/spec/models/planting_spec.rb index 6d0910707..866030e8c 100644 --- a/spec/models/planting_spec.rb +++ b/spec/models/planting_spec.rb @@ -83,7 +83,9 @@ describe Planting do context 'no data' do let(:planting) { FactoryBot.create :planting } it { expect(planting.crop.median_first_harvest).to eq(nil) } + it { expect(planting.crop.median_last_harvest).to eq(nil) } it { expect(planting.first_harvest).to eq(nil) } + it { expect(planting.last_harvest).to eq(nil) } it { expect(planting.expected_lifespan).to eq(nil) } end context 'lots of data' do @@ -107,18 +109,25 @@ describe Planting do it { expect(planting.crop.median_first_harvest).to eq(20) } end describe 'planting has no harvests' do - before { planting.update_harvest_days } + before do + planting.update_harvest_days + planting.crop.update_harvest_medians + end let(:planting) { FactoryBot.create :planting } it { expect(planting.first_harvest).to eq(nil) } + it { expect(planting.last_harvest).to eq(nil) } end describe 'planting has first harvest' do let(:planting) { FactoryBot.create :planting, planted_at: 100.days.ago } before do FactoryBot.create :harvest, planting: planting, crop: planting.crop, harvested_at: 10.days.ago planting.update_harvest_days + planting.crop.update_harvest_medians end it { expect(planting.first_harvest).to eq(90) } it { expect(planting.last_harvest).to eq(nil) } + it { expect(planting.crop.median_first_harvest).to eq(90) } + it { expect(planting.crop.median_last_harvest).to eq(nil) } end describe 'planting has last harvest' do let(:planting) { FactoryBot.create :planting, planted_at: 100.days.ago, finished_at: 1.day.ago, finished: true } @@ -126,9 +135,12 @@ describe Planting do FactoryBot.create :harvest, planting: planting, crop: planting.crop, harvested_at: 90.days.ago FactoryBot.create :harvest, planting: planting, crop: planting.crop, harvested_at: 10.days.ago planting.update_harvest_days + planting.crop.update_harvest_medians end it { expect(planting.first_harvest).to eq(10) } it { expect(planting.last_harvest).to eq(90) } + it { expect(planting.crop.median_first_harvest).to eq(10) } + it { expect(planting.crop.median_last_harvest).to eq(90) } end end From 9997c365d8ab9946bc8257d8bc31509206ed8382 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 5 Nov 2017 20:44:41 +1300 Subject: [PATCH 59/79] Update robocop todo - to reflect progress --- .rubocop.yml | 4 ++-- .rubocop_todo.yml | 16 ++-------------- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index 13d9906ec..8f8ebda37 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -64,9 +64,9 @@ Metrics/BlockLength: Metrics/MethodLength: Max: 34 Metrics/AbcSize: - Max: 32 + Max: 31 Metrics/ClassLength: - Max: 207 + Max: 179 Metrics/CyclomaticComplexity: Max: 11 Metrics/PerceivedComplexity: diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index fff93534b..b303fd313 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,12 +1,11 @@ # This configuration was generated by # `rubocop --auto-gen-config --no-offense-counts` -# on 2017-05-28 10:57:55 +1200 using RuboCop version 0.47.1. +# on 2017-11-05 20:41:45 +1300 using RuboCop version 0.47.1. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new # versions of RuboCop, may require this file to be generated again. - Lint/HandleExceptions: Exclude: - 'lib/tasks/testing.rake' @@ -57,7 +56,6 @@ Rails/TimeZone: - 'spec/factories/member.rb' - 'spec/factories/post.rb' - 'spec/models/post_spec.rb' - - 'spec/views/plantings/index.html.haml_spec.rb' # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles. @@ -122,13 +120,6 @@ Style/EachForSimpleLoop: - 'spec/models/crop_spec.rb' - 'spec/views/home/_crops.html.haml_spec.rb' -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles. -# SupportedStyles: compact, expanded -Style/EmptyMethod: - Exclude: - - 'app/controllers/roles_controller.rb' - # Configuration parameters: EnforcedStyle, SupportedStyles. # SupportedStyles: format, sprintf, percent Style/FormatString: @@ -146,7 +137,6 @@ Style/IdenticalConditionalBranches: Style/IfUnlessModifier: Exclude: - 'app/helpers/crops_helper.rb' - - 'app/models/planting.rb' - 'config/initializers/geocoder.rb' - 'lib/tasks/growstuff.rake' @@ -165,7 +155,6 @@ Style/MultilineIfModifier: Style/MultilineTernaryOperator: Exclude: - - 'app/controllers/notifications_controller.rb' - 'app/controllers/order_items_controller.rb' # Cop supports --auto-correct. @@ -223,7 +212,6 @@ Style/RegexpLiteral: - 'spec/views/devise/registrations/edit_spec.rb' - 'spec/views/members/index.html.haml_spec.rb' - 'spec/views/posts/index.html.haml_spec.rb' - - 'spec/views/posts/show.html.haml_spec.rb' # Cop supports --auto-correct. # Configuration parameters: SupportedStyles. @@ -243,4 +231,4 @@ Style/SymbolProc: # SupportedStyles: percent, brackets Style/WordArray: EnforcedStyle: percent - MinSize: 5 + MinSize: 4 From 470aacd1c9efc180336b0c49f3cfb1877d82d96f Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 6 Nov 2017 09:11:27 +1300 Subject: [PATCH 60/79] Fixed %w for an array of words --- app/views/crops/_index_card.html.haml | 3 --- spec/models/seed_spec.rb | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/app/views/crops/_index_card.html.haml b/app/views/crops/_index_card.html.haml index 4083a72a8..0d9180dee 100644 --- a/app/views/crops/_index_card.html.haml +++ b/app/views/crops/_index_card.html.haml @@ -12,9 +12,6 @@ %p %b Scientific name: = crop.default_scientific_name - %p - %b Planted #{pluralize(crop.plantings.size, "time")} - by #{ENV['GROWSTUFF_SITE_NAME']} members - unless crop.median_lifespan.nil? %p diff --git a/spec/models/seed_spec.rb b/spec/models/seed_spec.rb index c0dfc1e81..aa06af6eb 100644 --- a/spec/models/seed_spec.rb +++ b/spec/models/seed_spec.rb @@ -38,7 +38,7 @@ describe Seed do context 'tradable' do it 'all valid tradable_to values should work' do - ['nowhere', 'locally', 'nationally', 'internationally'].each do |t| + %w(nowhere locally nationally internationally).each do |t| @seed = FactoryBot.build(:seed, tradable_to: t) @seed.should be_valid end From ec63d8086f0693a57e1450940f96f63306e2d206 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 6 Nov 2017 22:36:47 +1300 Subject: [PATCH 61/79] Moved crop predictions to own haml file --- app/views/crops/_predictions.html.haml | 29 +++++++++++++++++ app/views/crops/show.html.haml | 45 ++++++-------------------- 2 files changed, 39 insertions(+), 35 deletions(-) create mode 100644 app/views/crops/_predictions.html.haml diff --git a/app/views/crops/_predictions.html.haml b/app/views/crops/_predictions.html.haml new file mode 100644 index 000000000..765bcc49d --- /dev/null +++ b/app/views/crops/_predictions.html.haml @@ -0,0 +1,29 @@ +- unless crop.perennial.nil? + %p + #{crop.name} is + - if crop.perennial == true + = link_to 'https://en.wikipedia.org/wiki/Annual_vs._perennial_plant_evolution' do + a perennial crop + (living more than two years) + - elsif crop.perennial == false + = link_to 'https://en.wikipedia.org/wiki/Annual_vs._perennial_plant_evolution' do + an annual crop + (living and reproducing in a single year or less) + +- unless crop.median_lifespan.nil? + %p + Median Lifespan of #{crop.name} plants is + %b= crop.median_lifespan + days + +- unless crop.median_first_harvest.nil? + %p + First harvest expected after + %b= crop.median_first_harvest + days + +- if crop.perennial == false && crop.median_last_harvest.present? + %p + Last harvest expected after + %b= crop.median_last_harvest + days diff --git a/app/views/crops/show.html.haml b/app/views/crops/show.html.haml index e507cb720..2b93c6706 100644 --- a/app/views/crops/show.html.haml +++ b/app/views/crops/show.html.haml @@ -26,28 +26,9 @@ - if member_signed_in? = display_seed_availability(@current_member, @crop) = link_to "View your seeds", seeds_by_owner_path(owner: current_member.slug) + %h2 Predictions - - unless @crop.perennial.nil? - %p - #{@crop.name} is - - if @crop.perennial == true - = link_to 'https://en.wikipedia.org/wiki/Annual_vs._perennial_plant_evolution' do - a perennial crop - (living more than two years) - - elsif @crop.perennial == false - = link_to 'https://en.wikipedia.org/wiki/Annual_vs._perennial_plant_evolution' do - an annual crop - (living and reproducing in a single year or less) - - unless @crop.median_lifespan.nil? - %p - Median Lifespan of #{@crop.name} plants is - %b= @crop.median_lifespan - days - - unless @crop.median_first_harvest.nil? - %p - First harvest expected after - %b= @crop.median_first_harvest - days + = render 'predictions', crop: @crop - if @crop.perennial == false && @crop.median_last_harvest.present? %p @@ -55,12 +36,6 @@ %b= @crop.median_last_harvest days - - unless current_member - Learn how to grow #{@crop.name.pluralize} from growers around the world. - #{ENV['GROWSTUFF_SITE_NAME']} has tips and advice from real-life growers, - including when to plant #{@crop.name.pluralize}, how to harvest - #{@crop.name.pluralize}, and more. - %p= render 'crops/photos', crop: @crop %h2 @@ -115,18 +90,18 @@ %h4 How to grow #{@crop.name.pluralize} - = render partial: 'grown_for', locals: { crop: @crop } - = render partial: 'planting_advice', locals: { crop: @crop } + = render 'grown_for', crop: @crop + = render 'planting_advice', crop: @crop - = render partial: 'scientific_names', locals: { crop: @crop } - = render partial: 'alternate_names', locals: { crop: @crop } + = render 'scientific_names', crop: @crop + = render 'alternate_names', crop: @crop %h4 #{@crop.name.capitalize} varieties - = render partial: 'varieties', locals: { crop: @crop } + = render 'varieties', crop: @crop - = render partial: 'plantings', locals: { crop: @crop } - = render partial: 'harvests', locals: { crop: @crop } - = render partial: 'find_seeds', locals: { crop: @crop } + = render 'plantings', crop: @crop + = render 'harvests', crop: @crop + = render 'find_seeds', crop: @crop %h4 Learn more about #{@crop.name.pluralize} From 6bf87c243c4dfe03e466be24f3edc8341572a681 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 6 Nov 2017 22:38:48 +1300 Subject: [PATCH 62/79] Feature spec for crop predictions on crop#show --- spec/features/crops/crop_detail_page_spec.rb | 65 ++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/spec/features/crops/crop_detail_page_spec.rb b/spec/features/crops/crop_detail_page_spec.rb index 5f0fa2ba4..e43a603e7 100644 --- a/spec/features/crops/crop_detail_page_spec.rb +++ b/spec/features/crops/crop_detail_page_spec.rb @@ -169,6 +169,71 @@ feature "crop detail page", js: true do end end + shared_examples "lots of harvests" do + def planting + FactoryBot.create :planting, crop: crop, planted_at: 100.days.ago, finished_at: 1.day.ago + end + before do + # 50 days to harvest + FactoryBot.create(:harvest, harvested_at: 50.days.ago, crop: crop, planting: planting) + # 20 days to harvest + FactoryBot.create(:harvest, harvested_at: 80.days.ago, crop: crop, planting: planting) + # 10 days to harvest + FactoryBot.create(:harvest, harvested_at: 90.days.ago, crop: crop, planting: planting) + planting.crop.plantings.each(&:update_harvest_days) + planting.crop.update_lifespan_medians + planting.crop.update_harvest_medians + end + it { is_expected.to have_text("First harvest expected after 20 days") } + it { is_expected.to have_text "Median Lifespan of #{crop.name} plants is 99 days" } + end + + subject do + visit crop_path(crop) + page + end + + context 'predictions' do + context 'crop is an annual' do + let(:crop) { FactoryBot.create :annual_crop } + + describe 'with no harvests' do + end + + describe 'with harvests' do + include_examples "lots of harvests" + end + it do + is_expected.to have_text( + "#{crop.name} is an annual crop (living and reproducing in a single year or less)" + ) + end + end + + context 'crop is perennial' do + let(:crop) { FactoryBot.create :perennial_crop } + + describe 'with no harvests' do + end + + describe 'with harvests' do + include_examples "lots of harvests" + end + it { is_expected.to have_text("#{crop.name} is a perennial crop (living more than two years)") } + end + + context 'crop perennial value is null' do + let(:crop) { FactoryBot.create :crop, perennial: nil } + + describe 'with no harvests' do + end + + describe 'with harvests' do + include_examples "lots of harvests" + end + end + end + context 'annual and perennial' do before { visit crop_path(crop) } context 'crop is an annual' do From 2696d12771aa97f018e42f52e7c5f4e26bcd9c45 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 6 Nov 2017 22:59:04 +1300 Subject: [PATCH 63/79] Removed duplicate display of last harvest --- app/views/crops/show.html.haml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/app/views/crops/show.html.haml b/app/views/crops/show.html.haml index 2b93c6706..2789d61ef 100644 --- a/app/views/crops/show.html.haml +++ b/app/views/crops/show.html.haml @@ -30,12 +30,6 @@ %h2 Predictions = render 'predictions', crop: @crop - - if @crop.perennial == false && @crop.median_last_harvest.present? - %p - Last harvest expected after - %b= @crop.median_last_harvest - days - %p= render 'crops/photos', crop: @crop %h2 From 941dab7c4a2968addd23d04a34093d47e0ce471c Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 6 Nov 2017 23:00:16 +1300 Subject: [PATCH 64/79] Crop.annual? method --- app/models/crop.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/models/crop.rb b/app/models/crop.rb index 7cdb0b592..8258992c1 100644 --- a/app/models/crop.rb +++ b/app/models/crop.rb @@ -169,6 +169,10 @@ class Crop < ActiveRecord::Base .count("harvests.id") end + def annual? + !(perennial == true) + end + def interesting? min_plantings = 3 # needs this many plantings to be interesting min_photos = 3 # needs this many photos to be interesting From 1e86cf76625c45b220eb1fed5984f3ac7a5087dc Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 6 Nov 2017 23:07:44 +1300 Subject: [PATCH 65/79] Update planting medians after updating record So changes to the planted_at are re-calculated --- app/controllers/plantings_controller.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/controllers/plantings_controller.rb b/app/controllers/plantings_controller.rb index e2b483c46..d6e937a98 100644 --- a/app/controllers/plantings_controller.rb +++ b/app/controllers/plantings_controller.rb @@ -2,6 +2,7 @@ class PlantingsController < ApplicationController before_action :authenticate_member!, except: %i(index show) after_action :expire_homepage, only: %i(create update destroy) after_action :update_crop_medians, only: %i(create update destroy) + after_action :update_planting_medians, only: :update load_and_authorize_resource respond_to :html, :json @@ -72,6 +73,10 @@ class PlantingsController < ApplicationController @planting.crop.update_lifespan_medians end + def update_planting_medians + @planting.update_harvest_days + end + def planting_params params[:planted_at] = parse_date(params[:planted_at]) if params[:planted_at] params.require(:planting).permit( From 1d64d4d1d2cb9d7bb498e5c388cdb773104c581f Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 6 Nov 2017 23:10:55 +1300 Subject: [PATCH 66/79] Clearer message that predctions are for days after planting --- app/views/crops/_index_card.html.haml | 12 ++++++------ app/views/crops/_predictions.html.haml | 10 +++++----- app/views/plantings/_progress.html.haml | 2 +- app/views/plantings/show.html.haml | 6 +++--- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/app/views/crops/_index_card.html.haml b/app/views/crops/_index_card.html.haml index 0d9180dee..92da22965 100644 --- a/app/views/crops/_index_card.html.haml +++ b/app/views/crops/_index_card.html.haml @@ -13,22 +13,22 @@ %b Scientific name: = crop.default_scientific_name - - unless crop.median_lifespan.nil? + - if crop.annual? && crop.median_lifespan.present? %p Median Lifespan %b= crop.median_lifespan days - unless crop.median_first_harvest.nil? %p - First harvest expected after + First harvest expected %b= crop.median_first_harvest - days + days after planting - - if crop.perennial == false && crop.median_last_harvest.present? + - if crop.annual? && crop.median_last_harvest.present? %p - Last harvest expected after + Last harvest expected %b= crop.median_last_harvest - days + days after planting - if can? :create, Planting = link_to 'Plant this', new_planting_path(params: { crop_id: crop.id }), class: 'btn btn-primary' diff --git a/app/views/crops/_predictions.html.haml b/app/views/crops/_predictions.html.haml index 765bcc49d..47f69e9b5 100644 --- a/app/views/crops/_predictions.html.haml +++ b/app/views/crops/_predictions.html.haml @@ -12,18 +12,18 @@ - unless crop.median_lifespan.nil? %p - Median Lifespan of #{crop.name} plants is + Median lifespan of #{crop.name} plants is %b= crop.median_lifespan days - unless crop.median_first_harvest.nil? %p - First harvest expected after + First harvest expected %b= crop.median_first_harvest - days + days after planting - if crop.perennial == false && crop.median_last_harvest.present? %p - Last harvest expected after + Last harvest expected %b= crop.median_last_harvest - days + days after planting diff --git a/app/views/plantings/_progress.html.haml b/app/views/plantings/_progress.html.haml index 876259b85..d5683b9c2 100644 --- a/app/views/plantings/_progress.html.haml +++ b/app/views/plantings/_progress.html.haml @@ -1,4 +1,4 @@ -- if planting.crop.perennial +- if planting.crop.perennial == true %p Perennial - elsif !planting.planted? - if show_explanation == true diff --git a/app/views/plantings/show.html.haml b/app/views/plantings/show.html.haml index 74d0508f2..ff8a08144 100644 --- a/app/views/plantings/show.html.haml +++ b/app/views/plantings/show.html.haml @@ -54,14 +54,14 @@ %dt Expected Lifespan: %dd #{@planting.crop.median_lifespan} days - if @planting.lifespan.present? - %dt Lifespan: + %dt Actual Lifespan: %dd #{@planting.lifespan} days - if @planting.first_harvest.present? %dt First Harvest: - %dd #{@planting.first_harvest} days old + %dd #{@planting.first_harvest} days after planting - if @planting.last_harvest.present? %dt Last Harvest: - %dd #{@planting.last_harvest} days old + %dd #{@planting.last_harvest} days after planting %p= render 'plantings/harvests', planting: @planting %p= render 'plantings/progress', planting: @planting, show_explanation: true From 928749aaad573f9ae4d24690cab20d3a2854cc26 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 6 Nov 2017 23:11:39 +1300 Subject: [PATCH 67/79] Changed a "Pictures" header to "Photos" to be consistent --- app/views/plantings/show.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/plantings/show.html.haml b/app/views/plantings/show.html.haml index ff8a08144..25b7464b6 100644 --- a/app/views/plantings/show.html.haml +++ b/app/views/plantings/show.html.haml @@ -82,7 +82,7 @@ #{ @planting.description != "" ? strip_tags(@planting.description) : "No description given." } - if !@planting.photos.empty? || (can?(:edit, @planting) && can?(:create, Photo)) - %h2 Pictures + %h2 Photos .row - @planting.photos.each do |p| From 2f47eeb7b3eb38339389c8c2a066f410c4a7ecee Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 6 Nov 2017 23:12:28 +1300 Subject: [PATCH 68/79] Bug fix. Can only predict if we have harvested_at and planted_at --- app/models/planting.rb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/models/planting.rb b/app/models/planting.rb index cfff1550f..9923845c3 100644 --- a/app/models/planting.rb +++ b/app/models/planting.rb @@ -114,13 +114,14 @@ class Planting < ActiveRecord::Base end def update_harvest_days + harvests_with_dates = harvests.where.not(harvested_at: nil) first_harvest = nil last_harvest = nil - if harvests.size.positive? + if planted_at.present? && harvests_with_dates.size.positive? # how long ago was this planted - first_harvest = (harvests.order(harvested_at: :asc).limit(1).first.harvested_at - planted_at).to_i + first_harvest = (harvests_with_dates.order(harvested_at: :asc).limit(1).first.harvested_at - planted_at).to_i if finished? - last_harvest = (harvests.order(harvested_at: :desc).limit(1).first.harvested_at - planted_at).to_i + last_harvest = (harvests_with_dates.order(harvested_at: :desc).limit(1).first.harvested_at - planted_at).to_i end end update(first_harvest: first_harvest, last_harvest: last_harvest) From c5971cd46b322cec4d3a7c2a8b03614044a57a55 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 6 Nov 2017 23:12:58 +1300 Subject: [PATCH 69/79] A little bit of eager loading --- app/views/crops/_photos.html.haml | 4 ++-- app/views/plantings/_harvests.html.haml | 2 +- app/views/plantings/show.html.haml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/views/crops/_photos.html.haml b/app/views/crops/_photos.html.haml index 0d06daf3c..927bf97c8 100644 --- a/app/views/crops/_photos.html.haml +++ b/app/views/crops/_photos.html.haml @@ -1,14 +1,14 @@ - unless crop.harvest_photos.empty? %h3 Photos of #{crop.name} harvests .row - - crop.harvest_photos.includes(:owner).first(6).each do |p| + - crop.harvest_photos.first(6).each do |p| .col-xs-6.col-md-2 = render "photos/thumbnail", photo: p - unless crop.photos.empty? %h3 Photos of #{crop.name} plants .row - - crop.photos.includes(:owner).first(6).each do |p| + - crop.photos.first(6).each do |p| .col-xs-6.col-md-2 = render "photos/thumbnail", photo: p .row diff --git a/app/views/plantings/_harvests.html.haml b/app/views/plantings/_harvests.html.haml index 432f91e87..99535b6be 100644 --- a/app/views/plantings/_harvests.html.haml +++ b/app/views/plantings/_harvests.html.haml @@ -1,7 +1,7 @@ - unless planting.harvests.empty? Harvests: %ul - - planting.harvests.each do |harvest| + - planting.harvests.includes(:crop).each do |harvest| %li = harvest.harvested_at ? harvest.harvested_at : "undated" = link_to harvest, harvest_path(harvest) diff --git a/app/views/plantings/show.html.haml b/app/views/plantings/show.html.haml index 25b7464b6..59aa52417 100644 --- a/app/views/plantings/show.html.haml +++ b/app/views/plantings/show.html.haml @@ -85,7 +85,7 @@ %h2 Photos .row - - @planting.photos.each do |p| + - @planting.photos.includes(:owner).each do |p| .col-md-2.six-across = render partial: 'photos/thumbnail', locals: { photo: p } - if can?(:create, Photo) && can?(:edit, @planting) From bf6475da57ce3c7b818dc4547fed41dbe432b08b Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 6 Nov 2017 23:15:08 +1300 Subject: [PATCH 70/79] annual? perennial!=true --- app/models/crop.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/crop.rb b/app/models/crop.rb index 8258992c1..1b76b8af3 100644 --- a/app/models/crop.rb +++ b/app/models/crop.rb @@ -170,7 +170,7 @@ class Crop < ActiveRecord::Base end def annual? - !(perennial == true) + perennial != true end def interesting? From 7206f99510d3ebfb0dec118e8c76b06786380b8c Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Tue, 7 Nov 2017 08:26:38 +1300 Subject: [PATCH 71/79] Updated spec to match new crop detail page text --- spec/features/crops/crop_detail_page_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/features/crops/crop_detail_page_spec.rb b/spec/features/crops/crop_detail_page_spec.rb index e43a603e7..45d855bc2 100644 --- a/spec/features/crops/crop_detail_page_spec.rb +++ b/spec/features/crops/crop_detail_page_spec.rb @@ -184,8 +184,8 @@ feature "crop detail page", js: true do planting.crop.update_lifespan_medians planting.crop.update_harvest_medians end - it { is_expected.to have_text("First harvest expected after 20 days") } - it { is_expected.to have_text "Median Lifespan of #{crop.name} plants is 99 days" } + it { is_expected.to have_text("First harvest expected 20 days after planting") } + it { is_expected.to have_text "Median lifespan of #{crop.name} plants is 99 days" } end subject do From a60a5ce5911c0f8fa290bc6f429bd0170c20a473 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Tue, 7 Nov 2017 09:46:19 +1300 Subject: [PATCH 72/79] Added a space, to please hound --- app/views/plantings/_card.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/plantings/_card.html.haml b/app/views/plantings/_card.html.haml index d92b3f920..a5469461a 100644 --- a/app/views/plantings/_card.html.haml +++ b/app/views/plantings/_card.html.haml @@ -34,7 +34,7 @@ %dd= display_planted_from(planting) %dt Finish expected: - %dd=planting.finish_predicted_at if planting.finish_predicted_at.present? + %dd= planting.finish_predicted_at if planting.finish_predicted_at.present? %p= render 'plantings/progress', planting: planting, show_explanation: true From 62beec23a104ce1548db00dbbea7577ced09e2ab Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 8 Nov 2017 17:17:15 +1300 Subject: [PATCH 73/79] "Changed first_harvest" to "days_to_first_harvest" --- app/models/crop.rb | 2 +- app/models/planting.rb | 9 ++++----- app/views/crops/_index_card.html.haml | 4 ++-- app/views/crops/_predictions.html.haml | 4 ++-- app/views/plantings/show.html.haml | 4 ++-- db/migrate/20171022032108_all_the_predictions.rb | 4 ++-- db/schema.rb | 4 ++-- spec/models/planting_spec.rb | 16 ++++++++-------- 8 files changed, 23 insertions(+), 24 deletions(-) diff --git a/app/models/crop.rb b/app/models/crop.rb index 1b76b8af3..d0c6044c5 100644 --- a/app/models/crop.rb +++ b/app/models/crop.rb @@ -221,7 +221,7 @@ class Crop < ActiveRecord::Base end def update_harvest_medians - update(median_first_harvest: Planting.where(crop: self).median(:first_harvest)) + update(median_days_to_first_harvest: Planting.where(crop: self).median(:days_to_first_harvest)) update(median_last_harvest: Planting.where(crop: self).median(:last_harvest)) end diff --git a/app/models/planting.rb b/app/models/planting.rb index 9923845c3..2f43818fb 100644 --- a/app/models/planting.rb +++ b/app/models/planting.rb @@ -115,16 +115,15 @@ class Planting < ActiveRecord::Base def update_harvest_days harvests_with_dates = harvests.where.not(harvested_at: nil) - first_harvest = nil + days_to_first_harvest = nil last_harvest = nil if planted_at.present? && harvests_with_dates.size.positive? - # how long ago was this planted - first_harvest = (harvests_with_dates.order(harvested_at: :asc).limit(1).first.harvested_at - planted_at).to_i + days_to_first_harvest = (harvests_with_dates.order(harvested_at: :asc).first.harvested_at - planted_at).to_i if finished? - last_harvest = (harvests_with_dates.order(harvested_at: :desc).limit(1).first.harvested_at - planted_at).to_i + last_harvest = (harvests_with_dates.order(harvested_at: :desc).first.harvested_at - planted_at).to_i end end - update(first_harvest: first_harvest, last_harvest: last_harvest) + update(days_to_first_harvest: days_to_first_harvest, last_harvest: last_harvest) end private diff --git a/app/views/crops/_index_card.html.haml b/app/views/crops/_index_card.html.haml index 92da22965..ae2146ae2 100644 --- a/app/views/crops/_index_card.html.haml +++ b/app/views/crops/_index_card.html.haml @@ -18,10 +18,10 @@ Median Lifespan %b= crop.median_lifespan days - - unless crop.median_first_harvest.nil? + - unless crop.median_days_to_first_harvest.nil? %p First harvest expected - %b= crop.median_first_harvest + %b= crop.median_days_to_first_harvest days after planting - if crop.annual? && crop.median_last_harvest.present? diff --git a/app/views/crops/_predictions.html.haml b/app/views/crops/_predictions.html.haml index 47f69e9b5..982b18898 100644 --- a/app/views/crops/_predictions.html.haml +++ b/app/views/crops/_predictions.html.haml @@ -16,10 +16,10 @@ %b= crop.median_lifespan days -- unless crop.median_first_harvest.nil? +- unless crop.median_days_to_first_harvest.nil? %p First harvest expected - %b= crop.median_first_harvest + %b= crop.median_days_to_first_harvest days after planting - if crop.perennial == false && crop.median_last_harvest.present? diff --git a/app/views/plantings/show.html.haml b/app/views/plantings/show.html.haml index 59aa52417..54e8a9abe 100644 --- a/app/views/plantings/show.html.haml +++ b/app/views/plantings/show.html.haml @@ -56,9 +56,9 @@ - if @planting.lifespan.present? %dt Actual Lifespan: %dd #{@planting.lifespan} days - - if @planting.first_harvest.present? + - if @planting.days_to_first_harvest.present? %dt First Harvest: - %dd #{@planting.first_harvest} days after planting + %dd #{@planting.days_to_first_harvest} days after planting - if @planting.last_harvest.present? %dt Last Harvest: %dd #{@planting.last_harvest} days after planting diff --git a/db/migrate/20171022032108_all_the_predictions.rb b/db/migrate/20171022032108_all_the_predictions.rb index 4b7b22a88..70b28db28 100644 --- a/db/migrate/20171022032108_all_the_predictions.rb +++ b/db/migrate/20171022032108_all_the_predictions.rb @@ -6,12 +6,12 @@ class AllThePredictions < ActiveRecord::Migration add_column :plantings, :lifespan, :integer # how old was planting at first harvest - add_column :plantings, :first_harvest, :integer + add_column :plantings, :days_to_first_harvest, :integer add_column :plantings, :last_harvest, :integer # Keep the median values for the crop add_column :crops, :median_lifespan, :integer - add_column :crops, :median_first_harvest, :integer + add_column :crops, :median_days_to_first_harvest, :integer add_column :crops, :median_last_harvest, :integer create_table :median_functions do |t| diff --git a/db/schema.rb b/db/schema.rb index 945ce107e..6427edbd7 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -196,7 +196,7 @@ ActiveRecord::Schema.define(version: 20171105011017) do t.text "rejection_notes" t.boolean "perennial", default: false t.integer "median_lifespan" - t.integer "median_first_harvest" + t.integer "median_days_to_first_harvest" t.integer "median_last_harvest" end @@ -431,7 +431,7 @@ ActiveRecord::Schema.define(version: 20171105011017) do t.date "finished_at" t.integer "days_before_maturity" t.integer "lifespan" - t.integer "first_harvest" + t.integer "days_to_first_harvest" t.integer "last_harvest" end diff --git a/spec/models/planting_spec.rb b/spec/models/planting_spec.rb index 866030e8c..8f477d6f4 100644 --- a/spec/models/planting_spec.rb +++ b/spec/models/planting_spec.rb @@ -82,9 +82,9 @@ describe Planting do describe 'planting first harvest preductions' do context 'no data' do let(:planting) { FactoryBot.create :planting } - it { expect(planting.crop.median_first_harvest).to eq(nil) } + it { expect(planting.crop.median_days_to_first_harvest).to eq(nil) } it { expect(planting.crop.median_last_harvest).to eq(nil) } - it { expect(planting.first_harvest).to eq(nil) } + it { expect(planting.days_to_first_harvest).to eq(nil) } it { expect(planting.last_harvest).to eq(nil) } it { expect(planting.expected_lifespan).to eq(nil) } end @@ -106,7 +106,7 @@ describe Planting do planting.crop.update_lifespan_medians planting.crop.update_harvest_medians end - it { expect(planting.crop.median_first_harvest).to eq(20) } + it { expect(planting.crop.median_days_to_first_harvest).to eq(20) } end describe 'planting has no harvests' do before do @@ -114,7 +114,7 @@ describe Planting do planting.crop.update_harvest_medians end let(:planting) { FactoryBot.create :planting } - it { expect(planting.first_harvest).to eq(nil) } + it { expect(planting.days_to_first_harvest).to eq(nil) } it { expect(planting.last_harvest).to eq(nil) } end describe 'planting has first harvest' do @@ -124,9 +124,9 @@ describe Planting do planting.update_harvest_days planting.crop.update_harvest_medians end - it { expect(planting.first_harvest).to eq(90) } + it { expect(planting.days_to_first_harvest).to eq(90) } it { expect(planting.last_harvest).to eq(nil) } - it { expect(planting.crop.median_first_harvest).to eq(90) } + it { expect(planting.crop.median_days_to_first_harvest).to eq(90) } it { expect(planting.crop.median_last_harvest).to eq(nil) } end describe 'planting has last harvest' do @@ -137,9 +137,9 @@ describe Planting do planting.update_harvest_days planting.crop.update_harvest_medians end - it { expect(planting.first_harvest).to eq(10) } + it { expect(planting.days_to_first_harvest).to eq(10) } it { expect(planting.last_harvest).to eq(90) } - it { expect(planting.crop.median_first_harvest).to eq(10) } + it { expect(planting.crop.median_days_to_first_harvest).to eq(10) } it { expect(planting.crop.median_last_harvest).to eq(90) } end end From 809dd813784c841aa4031bc8da01dd2b62241f4a Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 8 Nov 2017 17:17:58 +1300 Subject: [PATCH 74/79] "Changed last_harvest" to "days_to_last_harvest" --- app/models/crop.rb | 2 +- app/models/planting.rb | 6 +++--- app/views/crops/_index_card.html.haml | 4 ++-- app/views/crops/_predictions.html.haml | 4 ++-- app/views/plantings/show.html.haml | 4 ++-- .../20171022032108_all_the_predictions.rb | 4 ++-- db/schema.rb | 18 +++++++++--------- spec/models/planting_spec.rb | 14 +++++++------- 8 files changed, 28 insertions(+), 28 deletions(-) diff --git a/app/models/crop.rb b/app/models/crop.rb index d0c6044c5..44251ec36 100644 --- a/app/models/crop.rb +++ b/app/models/crop.rb @@ -222,7 +222,7 @@ class Crop < ActiveRecord::Base def update_harvest_medians update(median_days_to_first_harvest: Planting.where(crop: self).median(:days_to_first_harvest)) - update(median_last_harvest: Planting.where(crop: self).median(:last_harvest)) + update(median_days_to_last_harvest: Planting.where(crop: self).median(:days_to_last_harvest)) end private diff --git a/app/models/planting.rb b/app/models/planting.rb index 2f43818fb..8cc7eb921 100644 --- a/app/models/planting.rb +++ b/app/models/planting.rb @@ -116,14 +116,14 @@ class Planting < ActiveRecord::Base def update_harvest_days harvests_with_dates = harvests.where.not(harvested_at: nil) days_to_first_harvest = nil - last_harvest = nil + days_to_last_harvest = nil if planted_at.present? && harvests_with_dates.size.positive? days_to_first_harvest = (harvests_with_dates.order(harvested_at: :asc).first.harvested_at - planted_at).to_i if finished? - last_harvest = (harvests_with_dates.order(harvested_at: :desc).first.harvested_at - planted_at).to_i + days_to_last_harvest = (harvests_with_dates.order(harvested_at: :desc).first.harvested_at - planted_at).to_i end end - update(days_to_first_harvest: days_to_first_harvest, last_harvest: last_harvest) + update(days_to_first_harvest: days_to_first_harvest, days_to_last_harvest: days_to_last_harvest) end private diff --git a/app/views/crops/_index_card.html.haml b/app/views/crops/_index_card.html.haml index ae2146ae2..39b9e8da4 100644 --- a/app/views/crops/_index_card.html.haml +++ b/app/views/crops/_index_card.html.haml @@ -24,10 +24,10 @@ %b= crop.median_days_to_first_harvest days after planting - - if crop.annual? && crop.median_last_harvest.present? + - if crop.annual? && crop.median_days_to_last_harvest.present? %p Last harvest expected - %b= crop.median_last_harvest + %b= crop.median_days_to_last_harvest days after planting - if can? :create, Planting diff --git a/app/views/crops/_predictions.html.haml b/app/views/crops/_predictions.html.haml index 982b18898..86aaf8f43 100644 --- a/app/views/crops/_predictions.html.haml +++ b/app/views/crops/_predictions.html.haml @@ -22,8 +22,8 @@ %b= crop.median_days_to_first_harvest days after planting -- if crop.perennial == false && crop.median_last_harvest.present? +- if crop.perennial == false && crop.median_days_to_last_harvest.present? %p Last harvest expected - %b= crop.median_last_harvest + %b= crop.median_days_to_last_harvest days after planting diff --git a/app/views/plantings/show.html.haml b/app/views/plantings/show.html.haml index 54e8a9abe..099571218 100644 --- a/app/views/plantings/show.html.haml +++ b/app/views/plantings/show.html.haml @@ -59,9 +59,9 @@ - if @planting.days_to_first_harvest.present? %dt First Harvest: %dd #{@planting.days_to_first_harvest} days after planting - - if @planting.last_harvest.present? + - if @planting.days_to_last_harvest.present? %dt Last Harvest: - %dd #{@planting.last_harvest} days after planting + %dd #{@planting.days_to_last_harvest} days after planting %p= render 'plantings/harvests', planting: @planting %p= render 'plantings/progress', planting: @planting, show_explanation: true diff --git a/db/migrate/20171022032108_all_the_predictions.rb b/db/migrate/20171022032108_all_the_predictions.rb index 70b28db28..ca1098491 100644 --- a/db/migrate/20171022032108_all_the_predictions.rb +++ b/db/migrate/20171022032108_all_the_predictions.rb @@ -7,12 +7,12 @@ class AllThePredictions < ActiveRecord::Migration # how old was planting at first harvest add_column :plantings, :days_to_first_harvest, :integer - add_column :plantings, :last_harvest, :integer + add_column :plantings, :days_to_last_harvest, :integer # Keep the median values for the crop add_column :crops, :median_lifespan, :integer add_column :crops, :median_days_to_first_harvest, :integer - add_column :crops, :median_last_harvest, :integer + add_column :crops, :median_days_to_last_harvest, :integer create_table :median_functions do |t| end diff --git a/db/schema.rb b/db/schema.rb index 6427edbd7..5bc01e1fa 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -181,23 +181,23 @@ ActiveRecord::Schema.define(version: 20171105011017) do end create_table "crops", force: :cascade do |t| - t.string "name", null: false + t.string "name", null: false t.string "en_wikipedia_url" t.datetime "created_at" t.datetime "updated_at" t.string "slug" t.integer "parent_id" - t.integer "plantings_count", default: 0 + t.integer "plantings_count", default: 0 t.integer "creator_id" t.integer "requester_id" - t.string "approval_status", default: "approved" + t.string "approval_status", default: "approved" t.text "reason_for_rejection" t.text "request_notes" t.text "rejection_notes" - t.boolean "perennial", default: false + t.boolean "perennial", default: false t.integer "median_lifespan" t.integer "median_days_to_first_harvest" - t.integer "median_last_harvest" + t.integer "median_days_to_last_harvest" end add_index "crops", ["name"], name: "index_crops_on_name", using: :btree @@ -416,8 +416,8 @@ ActiveRecord::Schema.define(version: 20171105011017) do end create_table "plantings", force: :cascade do |t| - t.integer "garden_id", null: false - t.integer "crop_id", null: false + t.integer "garden_id", null: false + t.integer "crop_id", null: false t.date "planted_at" t.integer "quantity" t.text "description" @@ -427,12 +427,12 @@ ActiveRecord::Schema.define(version: 20171105011017) do t.string "sunniness" t.string "planted_from" t.integer "owner_id" - t.boolean "finished", default: false + t.boolean "finished", default: false t.date "finished_at" t.integer "days_before_maturity" t.integer "lifespan" t.integer "days_to_first_harvest" - t.integer "last_harvest" + t.integer "days_to_last_harvest" end add_index "plantings", ["slug"], name: "index_plantings_on_slug", unique: true, using: :btree diff --git a/spec/models/planting_spec.rb b/spec/models/planting_spec.rb index 8f477d6f4..462bee3e4 100644 --- a/spec/models/planting_spec.rb +++ b/spec/models/planting_spec.rb @@ -83,9 +83,9 @@ describe Planting do context 'no data' do let(:planting) { FactoryBot.create :planting } it { expect(planting.crop.median_days_to_first_harvest).to eq(nil) } - it { expect(planting.crop.median_last_harvest).to eq(nil) } + it { expect(planting.crop.median_days_to_last_harvest).to eq(nil) } it { expect(planting.days_to_first_harvest).to eq(nil) } - it { expect(planting.last_harvest).to eq(nil) } + it { expect(planting.days_to_last_harvest).to eq(nil) } it { expect(planting.expected_lifespan).to eq(nil) } end context 'lots of data' do @@ -115,7 +115,7 @@ describe Planting do end let(:planting) { FactoryBot.create :planting } it { expect(planting.days_to_first_harvest).to eq(nil) } - it { expect(planting.last_harvest).to eq(nil) } + it { expect(planting.days_to_last_harvest).to eq(nil) } end describe 'planting has first harvest' do let(:planting) { FactoryBot.create :planting, planted_at: 100.days.ago } @@ -125,9 +125,9 @@ describe Planting do planting.crop.update_harvest_medians end it { expect(planting.days_to_first_harvest).to eq(90) } - it { expect(planting.last_harvest).to eq(nil) } + it { expect(planting.days_to_last_harvest).to eq(nil) } it { expect(planting.crop.median_days_to_first_harvest).to eq(90) } - it { expect(planting.crop.median_last_harvest).to eq(nil) } + it { expect(planting.crop.median_days_to_last_harvest).to eq(nil) } end describe 'planting has last harvest' do let(:planting) { FactoryBot.create :planting, planted_at: 100.days.ago, finished_at: 1.day.ago, finished: true } @@ -138,9 +138,9 @@ describe Planting do planting.crop.update_harvest_medians end it { expect(planting.days_to_first_harvest).to eq(10) } - it { expect(planting.last_harvest).to eq(90) } + it { expect(planting.days_to_last_harvest).to eq(90) } it { expect(planting.crop.median_days_to_first_harvest).to eq(10) } - it { expect(planting.crop.median_last_harvest).to eq(90) } + it { expect(planting.crop.median_days_to_last_harvest).to eq(90) } end end From f187b3165323f4ed06412339a818df4f0f7edb15 Mon Sep 17 00:00:00 2001 From: deppbot Date: Wed, 8 Nov 2017 20:12:32 +0800 Subject: [PATCH 75/79] Bundle Update on 2017-11-08 --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 9920056c7..2216a47d7 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -313,7 +313,7 @@ GEM mime-types-data (~> 3.2015) mime-types-data (3.2016.0521) mimemagic (0.3.2) - mini_mime (0.1.4) + mini_mime (1.0.0) mini_portile2 (2.3.0) minitest (5.10.3) moneta (0.8.1) From 963a182981fe282b9b4ad7d15c6270caed65a590 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 9 Nov 2017 17:24:25 +1300 Subject: [PATCH 76/79] simplified logic in planting's first/last harvest fetcher --- app/models/planting.rb | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/app/models/planting.rb b/app/models/planting.rb index 8cc7eb921..f5f482a5d 100644 --- a/app/models/planting.rb +++ b/app/models/planting.rb @@ -114,20 +114,29 @@ class Planting < ActiveRecord::Base end def update_harvest_days - harvests_with_dates = harvests.where.not(harvested_at: nil) days_to_first_harvest = nil days_to_last_harvest = nil if planted_at.present? && harvests_with_dates.size.positive? - days_to_first_harvest = (harvests_with_dates.order(harvested_at: :asc).first.harvested_at - planted_at).to_i - if finished? - days_to_last_harvest = (harvests_with_dates.order(harvested_at: :desc).first.harvested_at - planted_at).to_i - end + days_to_first_harvest = (first_harvest_date - planted_at).to_i + days_to_last_harvest = (last_harvest_date - planted_at).to_i if finished? end update(days_to_first_harvest: days_to_first_harvest, days_to_last_harvest: days_to_last_harvest) end private + def harvests_with_dates + harvests.where.not(harvested_at: nil) + end + + def first_harvest_date + harvests_with_dates.minimum(:harvested_at) + end + + def last_harvest_date + harvests_with_dates.maximum(:harvested_at) + end + # check that any finished_at date occurs after planted_at def finished_must_be_after_planted return unless planted_at && finished_at # only check if we have both From 205247b136c5508678d1d954b77354466049241e Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 9 Nov 2017 17:30:33 +1300 Subject: [PATCH 77/79] Shorter condition in haml view (progress) --- app/views/plantings/_progress.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/plantings/_progress.html.haml b/app/views/plantings/_progress.html.haml index d5683b9c2..876259b85 100644 --- a/app/views/plantings/_progress.html.haml +++ b/app/views/plantings/_progress.html.haml @@ -1,4 +1,4 @@ -- if planting.crop.perennial == true +- if planting.crop.perennial %p Perennial - elsif !planting.planted? - if show_explanation == true From a5d43af899834b4601219685b7328d87be84d18b Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 9 Nov 2017 17:43:00 +1300 Subject: [PATCH 78/79] Drop the plantings.days_before_maturity column it's not used anywhere --- db/migrate/20171022032108_all_the_predictions.rb | 2 ++ db/migrate/20171105011017_set_prediction_data.rb | 4 +++- db/schema.rb | 1 - 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/db/migrate/20171022032108_all_the_predictions.rb b/db/migrate/20171022032108_all_the_predictions.rb index ca1098491..c4338ad2a 100644 --- a/db/migrate/20171022032108_all_the_predictions.rb +++ b/db/migrate/20171022032108_all_the_predictions.rb @@ -14,6 +14,8 @@ class AllThePredictions < ActiveRecord::Migration add_column :crops, :median_days_to_first_harvest, :integer add_column :crops, :median_days_to_last_harvest, :integer + remove_column :plantings, :days_before_maturity, :integer + create_table :median_functions do |t| end end diff --git a/db/migrate/20171105011017_set_prediction_data.rb b/db/migrate/20171105011017_set_prediction_data.rb index ac3a8089d..149001927 100644 --- a/db/migrate/20171105011017_set_prediction_data.rb +++ b/db/migrate/20171105011017_set_prediction_data.rb @@ -1,5 +1,5 @@ class SetPredictionData < ActiveRecord::Migration - def change + def up say "Updating all plantings time to first harvest" Planting.all.each(&:update_harvest_days) say "Updating crop median time to first harvest, and lifespan" @@ -8,4 +8,6 @@ class SetPredictionData < ActiveRecord::Migration crop.update_harvest_medians end end + + def down; end end diff --git a/db/schema.rb b/db/schema.rb index 5bc01e1fa..5b11fb94f 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -429,7 +429,6 @@ ActiveRecord::Schema.define(version: 20171105011017) do t.integer "owner_id" t.boolean "finished", default: false t.date "finished_at" - t.integer "days_before_maturity" t.integer "lifespan" t.integer "days_to_first_harvest" t.integer "days_to_last_harvest" From e4ab5114f7ede4d0e6f6ef9eaa382cf0aaaf726d Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 9 Nov 2017 17:51:18 +1300 Subject: [PATCH 79/79] Remove duplicate setting of medians in migration --- .../20171028230429_create_median_function.rb | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/db/migrate/20171028230429_create_median_function.rb b/db/migrate/20171028230429_create_median_function.rb index e57d63b4f..e565a4f68 100644 --- a/db/migrate/20171028230429_create_median_function.rb +++ b/db/migrate/20171028230429_create_median_function.rb @@ -1,21 +1,6 @@ class CreateMedianFunction < ActiveRecord::Migration def up ActiveMedian.create_function - - say "Calculating lifespan of known finished plantings" - Planting.where.not(planted_at: nil, finished_at: nil).each do |planting| - planting.calculate_lifespan - planting.save! - if planting.crop.median_lifespan.present? - say "#{planting.crop.name} median lifespan #{planting.crop.median_lifespan} days" - end - end - - say 'Calculating median lifespan of crops' - # Crop.all.each do |crop| - # crop.update_medians - # say "#{crop.name} median lifespan #{crop.median_lifespan} days" if crop.median_lifespan.present? - # end end def down