mirror of
https://github.com/Growstuff/growstuff.git
synced 2026-03-29 20:25:09 -04:00
Merge pull request #2320 from Br3nda/cache/harvests
Reading #index lookup from ElasticSearch instead of the database
This commit is contained in:
@@ -14,7 +14,7 @@ $(document).ready(function() {
|
||||
} else {
|
||||
likeBadge.removeClass('liked');
|
||||
likeButton.data('method', 'post');
|
||||
likeButton.attr('href', '/likes.json?post_id=' + data.id);
|
||||
likeButton.attr('href', '/likes.json?type=Post&id=' + data.id);
|
||||
likeButton.text('Like');
|
||||
}
|
||||
});
|
||||
@@ -34,7 +34,7 @@ $(document).ready(function() {
|
||||
likeBadge.removeClass('liked');
|
||||
// Turn the button into an *like* button
|
||||
likeButton.data('method', 'post');
|
||||
likeButton.attr('href', '/likes.json?photo_id=' + data.id);
|
||||
likeButton.attr('href', '/likes.json?type=Photo&id=' + data.id);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -11,7 +11,10 @@ class CropsController < ApplicationController
|
||||
|
||||
def index
|
||||
@sort = params[:sort]
|
||||
@crops = crops
|
||||
@crops = Crop.search('*', boost_by: %i(plantings_count harvests_count),
|
||||
limit: 100,
|
||||
page: params[:page],
|
||||
load: false)
|
||||
@num_requested_crops = requested_crops.size if current_member
|
||||
@filename = filename
|
||||
respond_with @crops
|
||||
@@ -51,19 +54,19 @@ class CropsController < ApplicationController
|
||||
def search
|
||||
@term = params[:term]
|
||||
|
||||
@crops = CropSearchService.search(
|
||||
@term, page: params[:page],
|
||||
per_page: 36,
|
||||
current_member: current_member
|
||||
)
|
||||
@crops = CropSearchService.search(@term,
|
||||
page: params[:page],
|
||||
per_page: Crop.per_page,
|
||||
current_member: current_member)
|
||||
respond_with @crops
|
||||
end
|
||||
|
||||
def show
|
||||
@crop = Crop.includes(:scientific_names, :alternate_names, :parent, :varieties).find_by!(slug: params[:slug])
|
||||
@crop = Crop.includes(
|
||||
:scientific_names, :alternate_names, :parent, :varieties
|
||||
).find_by!(slug: params[:slug])
|
||||
respond_to do |format|
|
||||
format.html do
|
||||
@photos = Photo.by_crop(@crop)
|
||||
@posts = @crop.posts.order(created_at: :desc).paginate(page: params[:page])
|
||||
@companions = @crop.companions.approved
|
||||
end
|
||||
@@ -204,24 +207,17 @@ class CropsController < ApplicationController
|
||||
def crop_json_fields
|
||||
{
|
||||
include: {
|
||||
plantings: {
|
||||
plantings: {
|
||||
include: {
|
||||
owner: { only: %i(id login_name location latitude longitude) }
|
||||
}
|
||||
},
|
||||
scientific_names: { only: [:name] },
|
||||
alternate_names: { only: [:name] }
|
||||
alternate_names: { only: [:name] }
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def crops
|
||||
q = Crop.approved.includes(:scientific_names, plantings: :photos)
|
||||
q = q.popular unless @sort == 'alpha'
|
||||
q.order(Arel.sql("LOWER(crops.name)"))
|
||||
.includes(:photos).paginate(page: params[:page])
|
||||
end
|
||||
|
||||
def requested_crops
|
||||
current_member.requested_crops.pending_approval
|
||||
end
|
||||
|
||||
@@ -52,7 +52,9 @@ class GardensController < DataController
|
||||
private
|
||||
|
||||
def garden_params
|
||||
params.require(:garden).permit(:name, :slug, :description, :active,
|
||||
:location, :latitude, :longitude, :area, :area_unit, :garden_type_id)
|
||||
params.require(:garden).permit(
|
||||
:name, :slug, :description, :active,
|
||||
:location, :latitude, :longitude, :area, :area_unit, :garden_type_id
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,14 +4,27 @@ class HarvestsController < DataController
|
||||
after_action :update_crop_medians, only: %i(create update destroy)
|
||||
|
||||
def index
|
||||
@owner = Member.find_by(slug: params[:member_slug])
|
||||
@crop = Crop.find_by(slug: params[:crop_slug])
|
||||
@planting = Planting.find_by(slug: params[:planting_id])
|
||||
where = {}
|
||||
if params[:member_slug]
|
||||
@owner = Member.find_by(slug: params[:member_slug])
|
||||
where['owner_id'] = @owner.id
|
||||
end
|
||||
|
||||
@harvests = @harvests.where(owner: @owner) if @owner.present?
|
||||
@harvests = @harvests.where(crop: @crop) if @crop.present?
|
||||
@harvests = @harvests.where(planting: @planting) if @planting.present?
|
||||
@harvests = @harvests.order(harvested_at: :desc).joins(:owner, :crop).paginate(page: params[:page])
|
||||
if params[:crop_slug]
|
||||
@crop = Crop.find_by(slug: params[:crop_slug])
|
||||
where['crop_id'] = @crop.id
|
||||
end
|
||||
|
||||
if params[:planting_slug]
|
||||
@planting = Planting.find_by(slug: params[:planting_slug])
|
||||
where['planting_id'] = @planting.id
|
||||
end
|
||||
|
||||
@harvests = Harvest.search('*', where: where,
|
||||
limit: 100,
|
||||
page: params[:page],
|
||||
load: false,
|
||||
boost_by: [:created_at])
|
||||
|
||||
@filename = csv_filename
|
||||
|
||||
@@ -26,7 +39,7 @@ class HarvestsController < DataController
|
||||
|
||||
def new
|
||||
@harvest = Harvest.new(harvested_at: Time.zone.today)
|
||||
@planting = Planting.find_by(slug: params[:planting_id]) if params[:planting_id]
|
||||
@planting = Planting.find_by(slug: params[:planting_slug]) if params[:planting_slug]
|
||||
@crop = Crop.find_by(id: params[:crop_id])
|
||||
respond_with(@harvest)
|
||||
end
|
||||
|
||||
@@ -5,36 +5,42 @@ class LikesController < ApplicationController
|
||||
respond_to :html, :json
|
||||
|
||||
def create
|
||||
@like = Like.new(member: current_member, likeable: find_likeable)
|
||||
return failed(@like, message: 'Unable to like') unless @like.likeable && @like.save
|
||||
|
||||
success(@like, liked_by_member: true, status_code: :created)
|
||||
@like = Like.new(
|
||||
member: current_member,
|
||||
likeable_type: params[:type],
|
||||
likeable_id: params[:id]
|
||||
)
|
||||
if @like.likeable && @like.save
|
||||
@like.likeable.reindex(refresh: true)
|
||||
success(@like, liked_by_member: true, status_code: :created)
|
||||
else
|
||||
failed(@like, message: 'Unable to like')
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
@like = Like.find_by(id: params[:id], member: current_member)
|
||||
return failed(@like, message: 'Unable to unlike') unless @like&.destroy
|
||||
@like = Like.find_by(
|
||||
likeable_type: params[:type],
|
||||
likeable_id: params[:id],
|
||||
member: current_member
|
||||
)
|
||||
|
||||
success(@like, liked_by_member: false, status_code: :ok)
|
||||
if @like&.destroy
|
||||
@like.likeable.reindex(refresh: true)
|
||||
success(@like, liked_by_member: false, status_code: :ok)
|
||||
else
|
||||
failed(@like, message: 'Unable to unlike')
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_likeable
|
||||
if params[:post_id]
|
||||
Post.find(params[:post_id])
|
||||
elsif params[:photo_id]
|
||||
Photo.find(params[:photo_id])
|
||||
end
|
||||
end
|
||||
|
||||
def render_json(like, liked_by_member: true)
|
||||
{
|
||||
id: like.likeable.id,
|
||||
like_count: like.likeable.likes.count,
|
||||
id: like.likeable.id,
|
||||
like_count: like.likeable.likes.count,
|
||||
liked_by_member: liked_by_member,
|
||||
description: ActionController::Base.helpers.pluralize(like.likeable.likes.count, "like"),
|
||||
url: like_path(like, format: :json)
|
||||
description: ActionController::Base.helpers.pluralize(like.likeable.likes.count, "like")
|
||||
}
|
||||
end
|
||||
|
||||
@@ -42,9 +48,10 @@ class LikesController < ApplicationController
|
||||
respond_to do |format|
|
||||
format.html { redirect_to like.likeable }
|
||||
format.json do
|
||||
render(json: render_json(like,
|
||||
liked_by_member: liked_by_member),
|
||||
status: status_code)
|
||||
render(json: render_json(
|
||||
like,
|
||||
liked_by_member: liked_by_member
|
||||
), status: status_code)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -71,7 +71,7 @@ class MembersController < ApplicationController
|
||||
|
||||
EMAIL_TYPE_STRING = {
|
||||
send_notification_email: "direct message notifications",
|
||||
send_planting_reminder: "planting reminders"
|
||||
send_planting_reminder: "planting reminders"
|
||||
}.freeze
|
||||
|
||||
def member_params
|
||||
|
||||
@@ -13,18 +13,22 @@ class PhotosController < ApplicationController
|
||||
end
|
||||
|
||||
def index
|
||||
where = {}
|
||||
if params[:crop_slug]
|
||||
@crop = Crop.find params[:crop_slug]
|
||||
@photos = Photo.by_crop(@crop)
|
||||
where = { crops: @crop.id }
|
||||
elsif params[:planting_id]
|
||||
@planting = Planting.find params[:planting_id]
|
||||
@photos = @planting.photos
|
||||
else
|
||||
@photos = Photo.all
|
||||
where = { planting_id: @planting.id }
|
||||
end
|
||||
@photos = @photos.order(created_at: :desc)
|
||||
.includes(:owner)
|
||||
.paginate(page: params[:page])
|
||||
|
||||
@photos = Photo.search(
|
||||
load: false,
|
||||
boost_by: [:created_at],
|
||||
where: where,
|
||||
page: params[:page],
|
||||
limit: Photo.per_page
|
||||
)
|
||||
respond_with(@photos)
|
||||
end
|
||||
|
||||
@@ -86,7 +90,7 @@ class PhotosController < ApplicationController
|
||||
def find_or_create_photo_from_flickr_photo
|
||||
photo = Photo.find_or_initialize_by(
|
||||
source_id: photo_params[:source_id],
|
||||
source: 'flickr'
|
||||
source: 'flickr'
|
||||
)
|
||||
photo.update(photo_params)
|
||||
photo.owner_id = current_member.id
|
||||
|
||||
@@ -5,20 +5,28 @@ class PlantingsController < DataController
|
||||
after_action :update_planting_medians, only: :update
|
||||
|
||||
def index
|
||||
@owner = Member.find_by(slug: params[:member_slug]) if params[:member_slug]
|
||||
@crop = Crop.find_by(slug: params[:crop_slug]) if params[:crop_slug]
|
||||
|
||||
@show_all = params[:all] == '1'
|
||||
|
||||
@plantings = @plantings.where(owner: @owner) if @owner.present?
|
||||
@plantings = @plantings.where(crop: @crop) if @crop.present?
|
||||
where = {}
|
||||
where['active'] = true unless @show_all
|
||||
|
||||
@plantings = @plantings.active unless params[:all] == '1'
|
||||
if params[:member_slug]
|
||||
@owner = Member.find_by(slug: params[:member_slug])
|
||||
where['owner_id'] = @owner.id
|
||||
end
|
||||
|
||||
@plantings = @plantings.joins(:owner, :crop, :garden)
|
||||
.order(created_at: :desc)
|
||||
.includes(:owner, :garden, crop: :parent)
|
||||
.paginate(page: params[:page])
|
||||
if params[:crop_slug]
|
||||
@crop = Crop.find_by(slug: params[:crop_slug])
|
||||
where['crop_id'] = @crop.id
|
||||
end
|
||||
|
||||
@plantings = Planting.search(
|
||||
where: where,
|
||||
page: params[:page],
|
||||
limit: 30,
|
||||
boost_by: [:created_at],
|
||||
load: false
|
||||
)
|
||||
|
||||
@filename = "Growstuff-#{specifics}Plantings-#{Time.zone.now.to_s(:number)}.csv"
|
||||
|
||||
@@ -27,9 +35,13 @@ class PlantingsController < DataController
|
||||
|
||||
def show
|
||||
@photos = @planting.photos.includes(:owner).order(date_taken: :desc)
|
||||
@harvests = Harvest.search(where: { planting_id: @planting.id })
|
||||
@matching_seeds = matching_seeds
|
||||
|
||||
# TODO: use elastic search long/lat
|
||||
@neighbours = @planting.nearby_same_crop
|
||||
.where.not(id: @planting.id)
|
||||
.includes(:owner, :crop, :garden)
|
||||
.limit(6)
|
||||
respond_with @planting
|
||||
end
|
||||
@@ -37,15 +49,15 @@ class PlantingsController < DataController
|
||||
def new
|
||||
@planting = Planting.new(
|
||||
planted_at: Time.zone.today,
|
||||
owner: current_member,
|
||||
garden: current_member.gardens.first
|
||||
owner: current_member,
|
||||
garden: current_member.gardens.first
|
||||
)
|
||||
@seed = Seed.find_by(slug: params[:seed_id]) if params[:seed_id]
|
||||
@crop = Crop.approved.find_by(id: params[:crop_id]) || Crop.new
|
||||
if params[:garden_id]
|
||||
@planting.garden = Garden.find_by(
|
||||
owner: current_member,
|
||||
id: params[:garden_id]
|
||||
id: params[:garden_id]
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
@@ -2,14 +2,34 @@
|
||||
|
||||
class SeedsController < DataController
|
||||
def index
|
||||
@owner = Member.find_by(slug: params[:member_slug]) if params[:member_slug].present?
|
||||
@crop = Crop.find_by(slug: params[:crop_slug]) if params[:crop_slug].present?
|
||||
@planting = Planting.find_by(slug: params[:planting_id]) if params[:planting_id].present?
|
||||
where = {}
|
||||
|
||||
if params[:member_slug].present?
|
||||
@owner = Member.find_by(slug: params[:member_slug])
|
||||
where['owner_id'] = @owner.id
|
||||
end
|
||||
|
||||
if params[:crop_slug].present?
|
||||
@crop = Crop.find_by(slug: params[:crop_slug])
|
||||
where['crop_id'] = @crop.id
|
||||
end
|
||||
|
||||
if params[:planting_id].present?
|
||||
@planting = Planting.find_by(slug: params[:planting_id])
|
||||
where['parent_planting'] = @planting.id
|
||||
end
|
||||
|
||||
@show_all = (params[:all] == '1')
|
||||
where['finished'] = false unless @show_all
|
||||
|
||||
@filename = csv_filename
|
||||
@seeds = seeds.order(created_at: :desc).includes(:owner, :crop).paginate(page: params[:page])
|
||||
@seeds = Seed.search(
|
||||
where: where,
|
||||
page: params[:page],
|
||||
limit: 30,
|
||||
boost_by: [:created_at],
|
||||
load: false
|
||||
)
|
||||
|
||||
respond_with(@seeds)
|
||||
end
|
||||
@@ -22,8 +42,8 @@ class SeedsController < DataController
|
||||
def new
|
||||
@seed = Seed.new
|
||||
|
||||
if params[:planting_id]
|
||||
@planting = Planting.find_by(slug: params[:planting_id])
|
||||
if params[:planting_slug]
|
||||
@planting = Planting.find_by(slug: params[:planting_slug])
|
||||
else
|
||||
@crop = Crop.find_or_initialize_by(id: params[:crop_id])
|
||||
end
|
||||
@@ -56,15 +76,6 @@ class SeedsController < DataController
|
||||
|
||||
private
|
||||
|
||||
def seeds
|
||||
records = Seed.all
|
||||
records = records.where(owner: @owner) if @owner.present?
|
||||
records = records.where(crop: @crop) if @crop.present?
|
||||
records = records.where(parent_planting: @planting) if @planting.present?
|
||||
records = records.active unless @show_all
|
||||
records
|
||||
end
|
||||
|
||||
def seed_params
|
||||
params.require(:seed).permit(
|
||||
:crop_id, :description, :quantity, :plant_before,
|
||||
|
||||
@@ -74,14 +74,14 @@ module ButtonsHelper
|
||||
def planting_finish_button(planting, classes: 'btn btn-default btn-secondary')
|
||||
return unless can?(:edit, planting) || planting.finished
|
||||
|
||||
link_to planting_path(planting, planting: { finished: 1 }),
|
||||
link_to planting_path(slug: planting.slug, planting: { finished: 1 }),
|
||||
method: :put, class: "#{classes} append-date" do
|
||||
finished_icon + ' ' + t('buttons.mark_as_finished')
|
||||
end
|
||||
end
|
||||
|
||||
def seed_finish_button(seed, classes: 'btn btn-default')
|
||||
return unless can?(:create, Planting) && seed.active?
|
||||
return unless can?(:create, Planting) && seed.active
|
||||
|
||||
link_to seed_path(seed, seed: { finished: 1 }), method: :put, class: "#{classes} append-date" do
|
||||
finished_icon + ' ' + t('buttons.mark_as_finished')
|
||||
@@ -89,9 +89,9 @@ module ButtonsHelper
|
||||
end
|
||||
|
||||
def planting_harvest_button(planting, classes: 'btn btn-default')
|
||||
return unless planting.active? && can?(:create, Harvest) && can?(:edit, planting)
|
||||
return unless planting.active && can?(:create, Harvest) && can?(:edit, planting)
|
||||
|
||||
link_to new_planting_harvest_path(planting), class: classes do
|
||||
link_to new_planting_harvest_path(planting_slug: planting.slug), class: classes do
|
||||
harvest_icon + ' ' + t('buttons.record_harvest')
|
||||
end
|
||||
end
|
||||
@@ -99,7 +99,7 @@ module ButtonsHelper
|
||||
def planting_save_seeds_button(planting, classes: 'btn btn-default')
|
||||
return unless can?(:edit, planting)
|
||||
|
||||
link_to new_planting_seed_path(planting), class: classes do
|
||||
link_to new_planting_seed_path(planting_slug: planting.slug), class: classes do
|
||||
seed_icon + ' ' + t('buttons.save_seeds')
|
||||
end
|
||||
end
|
||||
|
||||
@@ -15,6 +15,6 @@ module CropsHelper
|
||||
end
|
||||
|
||||
def crop_ebay_seeds_url(crop)
|
||||
"https://rover.ebay.com/rover/1/705-53470-19255-0/1?icep_ff3=9&pub=5575213277&toolid=10001&campid=5337940151&customid=&icep_uq=#{CGI.escape crop.name}&icep_sellerId=&icep_ex_kw=&icep_sortBy=12&icep_catId=181003&icep_minPrice=&icep_maxPrice=&ipn=psmain&icep_vectorid=229515&kwid=902099&mtid=824&kw=lg" # rubocop:disable Metrics/LineLength
|
||||
"https://rover.ebay.com/rover/1/705-53470-19255-0/1?icep_ff3=9&pub=5575213277&toolid=10001&campid=5337940151&customid=&icep_uq=#{CGI.escape crop.name}&icep_sellerId=&icep_ex_kw=&icep_sortBy=12&icep_catId=181003&icep_minPrice=&icep_maxPrice=&ipn=psmain&icep_vectorid=229515&kwid=902099&mtid=824&kw=lg" # rubocop:disable Layout/LineLength
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
module CropSearch
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
####################################
|
||||
# Elastic search configuration
|
||||
searchkick word_start: %i(name alternate_names scientific_names),
|
||||
case_sensitive: false,
|
||||
merge_mappings: true,
|
||||
mappings: {
|
||||
properties: {
|
||||
created_at: { type: :integer }
|
||||
}
|
||||
}
|
||||
|
||||
# Special scope to control if it's in the search index
|
||||
scope :search_import, -> { includes(:scientific_names, :photos) }
|
||||
|
||||
def should_index?
|
||||
approved?
|
||||
end
|
||||
|
||||
def search_data
|
||||
{
|
||||
name: name,
|
||||
slug: slug,
|
||||
alternate_names: alternate_names.pluck(:name),
|
||||
scientific_names: scientific_names.pluck(:name),
|
||||
# boost the crops that are planted the most
|
||||
plantings_count: plantings_count,
|
||||
# boost this crop for these members
|
||||
planters_ids: plantings.pluck(:owner_id),
|
||||
has_photos: photos.size.positive?,
|
||||
photo: default_photo&.thumbnail_url,
|
||||
scientific_name: default_scientific_name&.name,
|
||||
description: description,
|
||||
created_at: created_at.to_i
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -7,7 +7,7 @@ module Finishable
|
||||
scope :finished, -> { where(finished: true) }
|
||||
scope :current, -> { where.not(finished: true) }
|
||||
|
||||
def active?
|
||||
def active
|
||||
!finished
|
||||
end
|
||||
end
|
||||
|
||||
@@ -9,6 +9,10 @@ module Likeable
|
||||
end
|
||||
|
||||
def liked_by?(member)
|
||||
member && members.include?(member)
|
||||
liked_by_members_names.include?(member.login_name)
|
||||
end
|
||||
|
||||
def liked_by_members_names
|
||||
Member.where(id: likes.pluck(:member_id)).pluck(:login_name)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -15,6 +15,14 @@ module PhotoCapable
|
||||
end
|
||||
end
|
||||
|
||||
def thumbnail_url
|
||||
df = default_photo
|
||||
|
||||
return unless df
|
||||
|
||||
df.source == 'flickr' ? df.fullsize_url : df.thumbnail_url
|
||||
end
|
||||
|
||||
def most_liked_photo
|
||||
photos.order(likes_count: :desc, created_at: :desc).first
|
||||
end
|
||||
|
||||
49
app/models/concerns/search_crops.rb
Normal file
49
app/models/concerns/search_crops.rb
Normal file
@@ -0,0 +1,49 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module SearchCrops
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
####################################
|
||||
# Elastic search configuration
|
||||
searchkick word_start: %i(name description alternate_names scientific_names),
|
||||
case_sensitive: false,
|
||||
searchable: %i(name descriptions alternate_names scientific_names),
|
||||
merge_mappings: true,
|
||||
mappings: {
|
||||
properties: {
|
||||
created_at: { type: :integer },
|
||||
plantings_count: { type: :integer },
|
||||
harvests_count: { type: :integer },
|
||||
photos_count: { type: :integer }
|
||||
}
|
||||
}
|
||||
|
||||
# Special scope to control if it's in the search index
|
||||
scope :search_import, -> { includes(:scientific_names, :photos) }
|
||||
|
||||
def should_index?
|
||||
approved?
|
||||
end
|
||||
|
||||
def search_data
|
||||
{
|
||||
name: name,
|
||||
description: description,
|
||||
slug: slug,
|
||||
alternate_names: alternate_names.pluck(:name),
|
||||
scientific_names: scientific_names.pluck(:name),
|
||||
photos_count: photo_associations_count,
|
||||
# boost the crops that are planted the most
|
||||
plantings_count: plantings_count,
|
||||
harvests_count: harvests_count,
|
||||
# boost this crop for these members
|
||||
planters_ids: plantings.pluck(:owner_id),
|
||||
has_photos: photos.size.positive?,
|
||||
thumbnail_url: thumbnail_url,
|
||||
scientific_name: default_scientific_name&.name,
|
||||
created_at: created_at.to_i
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
60
app/models/concerns/search_harvests.rb
Normal file
60
app/models/concerns/search_harvests.rb
Normal file
@@ -0,0 +1,60 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module SearchHarvests
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
searchkick merge_mappings: true, mappings: {
|
||||
properties: {
|
||||
harvests_count: { type: :integer },
|
||||
photos_count: { type: :integer },
|
||||
created_at: { type: :integer },
|
||||
harvested_at: { type: :date }
|
||||
}
|
||||
}
|
||||
|
||||
scope :search_import, -> { includes(:owner, :crop, :plant_part) }
|
||||
|
||||
def search_data
|
||||
{
|
||||
slug: slug,
|
||||
quantity: quantity,
|
||||
|
||||
# crop
|
||||
crop_id: crop_id,
|
||||
crop_name: crop_name,
|
||||
crop_slug: crop.slug,
|
||||
|
||||
# owner
|
||||
owner_id: owner_id,
|
||||
owner_login_name: owner_login_name,
|
||||
owner_slug: owner_slug,
|
||||
plant_part_name: plant_part&.name,
|
||||
|
||||
# planting
|
||||
planting_id: planting_id,
|
||||
planting_slug: planting&.slug,
|
||||
|
||||
# photo
|
||||
has_photos: photos.size.positive?,
|
||||
thumbnail_url: default_photo&.thumbnail_url || crop.default_photo&.thumbnail_url,
|
||||
|
||||
# counts
|
||||
photos_count: photos.count,
|
||||
|
||||
# timestamps
|
||||
harvested_at: harvested_at,
|
||||
created_at: created_at.to_i
|
||||
}
|
||||
end
|
||||
|
||||
def self.homepage_records(limit)
|
||||
search('*', limit: limit,
|
||||
where: {
|
||||
photos_count: { gt: 0 }
|
||||
},
|
||||
boost_by: [:created_at],
|
||||
load: false)
|
||||
end
|
||||
end
|
||||
end
|
||||
34
app/models/concerns/search_photos.rb
Normal file
34
app/models/concerns/search_photos.rb
Normal file
@@ -0,0 +1,34 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module SearchPhotos
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
searchkick merge_mappings: true, mappings: {
|
||||
properties: {
|
||||
title: { type: :text },
|
||||
created_at: { type: :integer }
|
||||
}
|
||||
}
|
||||
|
||||
def search_data
|
||||
{
|
||||
id: id,
|
||||
title: title,
|
||||
thumbnail_url: thumbnail_url,
|
||||
fullsize_url: fullsize_url,
|
||||
# crops
|
||||
crops: crops.pluck(:id),
|
||||
# likes
|
||||
liked_by_members_names: liked_by_members_names,
|
||||
# owner
|
||||
owner_id: owner_id,
|
||||
owner_login_name: owner.login_name,
|
||||
# counts
|
||||
likes_count: likes_count,
|
||||
|
||||
created_at: created_at.to_i
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
63
app/models/concerns/search_plantings.rb
Normal file
63
app/models/concerns/search_plantings.rb
Normal file
@@ -0,0 +1,63 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module SearchPlantings
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
searchkick merge_mappings: true, mappings: {
|
||||
properties: {
|
||||
active: { type: :boolean },
|
||||
created_at: { type: :integer },
|
||||
harvests_count: { type: :integer },
|
||||
photos_count: { type: :integer },
|
||||
owner_location: { type: :text }
|
||||
}
|
||||
}
|
||||
|
||||
scope :search_import, -> { includes(:owner, :crop) }
|
||||
|
||||
def search_data
|
||||
{
|
||||
slug: slug,
|
||||
active: active,
|
||||
finished: finished?,
|
||||
has_photos: photos.size.positive?,
|
||||
location: location,
|
||||
percentage_grown: percentage_grown.to_i,
|
||||
planted_at: planted_at,
|
||||
planted_from: planted_from,
|
||||
quantity: quantity,
|
||||
sunniness: sunniness,
|
||||
|
||||
# crops
|
||||
crop_id: crop_id,
|
||||
crop_name: crop.name,
|
||||
crop_slug: crop.slug,
|
||||
|
||||
# owner
|
||||
owner_id: owner_id,
|
||||
owner_location: owner_location,
|
||||
owner_login_name: owner_login_name,
|
||||
owner_slug: owner_slug,
|
||||
|
||||
# photos
|
||||
thumbnail_url: default_photo&.thumbnail_url || crop.default_photo&.thumbnail_url,
|
||||
# counts
|
||||
photos_count: photos.size,
|
||||
harvests_count: harvests_count,
|
||||
|
||||
# timestamps
|
||||
created_at: created_at.to_i
|
||||
}
|
||||
end
|
||||
|
||||
def self.homepage_records(limit)
|
||||
search('*', limit: limit,
|
||||
where: {
|
||||
photos_count: { gt: 0 }
|
||||
},
|
||||
boost_by: [:created_at],
|
||||
load: false)
|
||||
end
|
||||
end
|
||||
end
|
||||
66
app/models/concerns/search_seeds.rb
Normal file
66
app/models/concerns/search_seeds.rb
Normal file
@@ -0,0 +1,66 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module SearchSeeds
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
searchkick merge_mappings: true, mappings: {
|
||||
properties: {
|
||||
id: { type: :integer },
|
||||
created_at: { type: :integer },
|
||||
plant_before: { type: :text },
|
||||
photos_count: { type: :integer },
|
||||
tradable_to: { type: :text }
|
||||
}
|
||||
}
|
||||
|
||||
def search_data
|
||||
{
|
||||
slug: slug,
|
||||
finished: finished?,
|
||||
gmo: gmo,
|
||||
active: active,
|
||||
heirloom: heirloom,
|
||||
location: owner.location,
|
||||
organic: organic,
|
||||
quantity: quantity,
|
||||
plant_before: plant_before&.to_s(:ymd),
|
||||
tradable_to: tradable_to,
|
||||
tradable: tradable,
|
||||
|
||||
# crop
|
||||
crop_id: crop_id,
|
||||
crop_name: crop.name,
|
||||
crop_slug: crop.slug,
|
||||
|
||||
# owner
|
||||
owner_id: owner_id,
|
||||
owner_location: owner_location,
|
||||
owner_login_name: owner_login_name,
|
||||
owner_slug: owner_slug,
|
||||
|
||||
# planting
|
||||
parent_planting: parent_planting,
|
||||
|
||||
# counts
|
||||
photos_count: photos.size,
|
||||
|
||||
# photo
|
||||
has_photos: photos.size.positive?,
|
||||
thumbnail_url: default_photo&.thumbnail_url || crop.default_photo&.thumbnail_url,
|
||||
|
||||
created_at: created_at.to_i
|
||||
}
|
||||
end
|
||||
|
||||
def self.homepage_records(limit)
|
||||
search('*', limit: limit,
|
||||
where: {
|
||||
finished: false,
|
||||
tradable: true
|
||||
},
|
||||
boost_by: [:created_at],
|
||||
load: false)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -4,7 +4,7 @@ class Crop < ApplicationRecord
|
||||
extend FriendlyId
|
||||
include PhotoCapable
|
||||
include OpenFarmData
|
||||
include CropSearch
|
||||
include SearchCrops
|
||||
|
||||
friendly_id :name, use: %i(slugged finders)
|
||||
|
||||
@@ -18,7 +18,7 @@ class Crop < ApplicationRecord
|
||||
has_many :plantings, dependent: :destroy
|
||||
has_many :seeds, dependent: :destroy
|
||||
has_many :harvests, dependent: :destroy
|
||||
has_many :photo_associations, dependent: :delete_all
|
||||
has_many :photo_associations, dependent: :delete_all, inverse_of: :crop
|
||||
has_many :photos, through: :photo_associations
|
||||
has_many :plant_parts, -> { joins_members.distinct.order("plant_parts.name") }, through: :harvests
|
||||
has_many :varieties, class_name: 'Crop', foreign_key: 'parent_id', dependent: :nullify, inverse_of: :parent
|
||||
|
||||
@@ -77,6 +77,8 @@ class Garden < ApplicationRecord
|
||||
end
|
||||
end
|
||||
|
||||
def reindex(refresh: false); end
|
||||
|
||||
protected
|
||||
|
||||
def strip_blanks
|
||||
|
||||
@@ -5,6 +5,7 @@ class Harvest < ApplicationRecord
|
||||
extend FriendlyId
|
||||
include PhotoCapable
|
||||
include Ownable
|
||||
include SearchHarvests
|
||||
|
||||
friendly_id :harvest_slug, use: %i(slugged finders)
|
||||
|
||||
@@ -45,10 +46,14 @@ class Harvest < ApplicationRecord
|
||||
scope :recent, -> { order(created_at: :desc) }
|
||||
scope :one_per_owner, lambda {
|
||||
joins("JOIN members m ON (m.id=harvests.owner_id)
|
||||
LEFT OUTER JOIN harvests h2
|
||||
ON (m.id=h2.owner_id AND harvests.id < h2.id)").where("h2 IS NULL")
|
||||
LEFT OUTER JOIN harvests h2
|
||||
ON (m.id=h2.owner_id AND harvests.id < h2.id)").where("h2 IS NULL")
|
||||
}
|
||||
|
||||
delegate :name, :slug, to: :crop, prefix: true
|
||||
delegate :login_name, :slug, to: :owner, prefix: true
|
||||
delegate :name, to: :plant_part, prefix: true
|
||||
|
||||
##
|
||||
## Validations
|
||||
validates :crop, approved: true
|
||||
|
||||
@@ -3,11 +3,18 @@
|
||||
class Photo < ApplicationRecord
|
||||
include Likeable
|
||||
include Ownable
|
||||
include SearchPhotos
|
||||
|
||||
PHOTO_CAPABLE = %w(Garden Planting Harvest Seed Post Crop).freeze
|
||||
|
||||
has_many :photo_associations, foreign_key: :photo_id, dependent: :delete_all, inverse_of: :photo
|
||||
has_many :crops, through: :photo_associations, counter_cache: true
|
||||
|
||||
# This doesn't work, ActiveRecord tries to use the polymoriphinc photographable
|
||||
# relationship instead.
|
||||
# has_many :crops, through: :photo_associations
|
||||
def crops
|
||||
Crop.distinct.joins(:photo_associations).where(photo_associations: { photo: self })
|
||||
end
|
||||
|
||||
validates :fullsize_url, url: true
|
||||
validates :thumbnail_url, url: true
|
||||
@@ -25,6 +32,8 @@ class Photo < ApplicationRecord
|
||||
joins(:photo_associations).where(photo_associations: { photographable_type: model_name.to_s })
|
||||
}
|
||||
|
||||
delegate :login_name, to: :owner, prefix: true
|
||||
|
||||
# This is split into a side-effect free method and a side-effecting method
|
||||
# for easier stubbing and testing.
|
||||
def flickr_metadata
|
||||
|
||||
@@ -1,24 +1,23 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class PhotoAssociation < ApplicationRecord
|
||||
belongs_to :photo, inverse_of: :photo_associations
|
||||
belongs_to :photo, touch: true
|
||||
belongs_to :crop, optional: true, touch: true # , counter_cache: true
|
||||
belongs_to :photographable, polymorphic: true, touch: true
|
||||
belongs_to :crop, optional: true, counter_cache: true
|
||||
|
||||
validate :photo_and_item_have_same_owner
|
||||
validate :crop_present
|
||||
|
||||
##
|
||||
## Triggers
|
||||
before_save :set_crop
|
||||
|
||||
def item
|
||||
find_by!(photographable_id: photographable_id, photographable_type: photographable_type).photographable
|
||||
end
|
||||
before_validation :set_crop
|
||||
|
||||
def self.item(item_id, item_type)
|
||||
find_by!(photographable_id: item_id, photographable_type: item_type).photographable
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_crop
|
||||
if %w(Planting Seed Harvest).include?(photographable_type)
|
||||
self.crop_id = photographable.crop_id
|
||||
@@ -27,11 +26,15 @@ class PhotoAssociation < ApplicationRecord
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def photo_and_item_have_same_owner
|
||||
return unless photographable_type != 'Crop'
|
||||
return if photographable_type == 'Crop'
|
||||
|
||||
errors.add(:photo, "must have same owner as item it links to") unless photographable.owner_id == photo.owner_id
|
||||
end
|
||||
|
||||
def crop_present
|
||||
if %w(Planting Seed Harvest).include?(photographable_type)
|
||||
errors.add(:crop_id, "failed to calculate crop") if crop_id.blank?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -7,6 +7,8 @@ class Planting < ApplicationRecord
|
||||
include Ownable
|
||||
include PredictPlanting
|
||||
include PredictHarvest
|
||||
include SearchPlantings
|
||||
|
||||
friendly_id :planting_slug, use: %i(slugged finders)
|
||||
|
||||
# Constants
|
||||
@@ -56,6 +58,8 @@ class Planting < ApplicationRecord
|
||||
## Delegations
|
||||
delegate :name, :slug, :en_wikipedia_url, :default_scientific_name, :plantings_count,
|
||||
to: :crop, prefix: true
|
||||
delegate :login_name, :slug, :location, to: :owner, prefix: true
|
||||
delegate :slug, to: :planting, prefix: true
|
||||
|
||||
delegate :annual?, :perennial?, :svg_icon, to: :crop
|
||||
delegate :location, :longitude, :latitude, to: :garden
|
||||
|
||||
@@ -57,6 +57,8 @@ class Post < ApplicationRecord
|
||||
subject
|
||||
end
|
||||
|
||||
def reindex(refresh: false); end
|
||||
|
||||
private
|
||||
|
||||
def update_crop_posts_association
|
||||
|
||||
@@ -5,6 +5,7 @@ class Seed < ApplicationRecord
|
||||
include PhotoCapable
|
||||
include Finishable
|
||||
include Ownable
|
||||
include SearchSeeds
|
||||
friendly_id :seed_slug, use: %i(slugged finders)
|
||||
|
||||
TRADABLE_TO_VALUES = %w(nowhere locally nationally internationally).freeze
|
||||
@@ -46,7 +47,9 @@ class Seed < ApplicationRecord
|
||||
|
||||
#
|
||||
# Delegations
|
||||
delegate :name, to: :crop
|
||||
delegate :name, to: :crop, prefix: true
|
||||
delegate :location, :latitude, :longitude, to: :owner
|
||||
delegate :login_name, :slug, :location, to: :owner, prefix: true
|
||||
|
||||
#
|
||||
# Scopes
|
||||
@@ -57,7 +60,7 @@ class Seed < ApplicationRecord
|
||||
scope :recent, -> { order(created_at: :desc) }
|
||||
scope :active, -> { where('finished <> true').where('finished_at IS NULL OR finished_at < ?', Time.zone.now) }
|
||||
|
||||
def tradable?
|
||||
def tradable
|
||||
tradable_to != 'nowhere'
|
||||
end
|
||||
|
||||
|
||||
@@ -4,13 +4,14 @@ class CropSearchService
|
||||
# Crop.search(string)
|
||||
def self.search(query, page: 1, per_page: 12, current_member: nil)
|
||||
search_params = {
|
||||
page: page,
|
||||
per_page: per_page,
|
||||
fields: %i(name^5 alternate_names scientific_names),
|
||||
match: :word_start,
|
||||
boost_by: [:plantings_count],
|
||||
includes: %i(scientific_names alternate_names),
|
||||
misspellings: { edit_distance: 2 }
|
||||
page: page,
|
||||
per_page: per_page,
|
||||
fields: %i(name^5 alternate_names scientific_names),
|
||||
match: :word_start,
|
||||
boost_by: [:plantings_count],
|
||||
includes: %i(scientific_names alternate_names),
|
||||
misspellings: { edit_distance: 2 },
|
||||
load: false
|
||||
}
|
||||
# prioritise crops the member has planted
|
||||
search_params[:boost_where] = { planters_ids: current_member.id } if current_member
|
||||
@@ -22,22 +23,22 @@ class CropSearchService
|
||||
body = {
|
||||
"query": {
|
||||
"function_score": {
|
||||
"query": { "query_string": { "query": 'has_photos:true' } },
|
||||
"query": { "query_string": { "query": 'has_photos:true' } },
|
||||
"random_score": { "seed": DateTime.now.to_i }
|
||||
}
|
||||
}
|
||||
}
|
||||
Crop.search(
|
||||
limit: limit,
|
||||
load: false,
|
||||
body: body
|
||||
load: false,
|
||||
body: body
|
||||
)
|
||||
end
|
||||
|
||||
def self.recent(limit)
|
||||
Crop.search(
|
||||
limit: limit,
|
||||
load: false,
|
||||
limit: limit,
|
||||
load: false,
|
||||
boost_by: { created_at: { factor: 100 } } # default factor is 1
|
||||
)
|
||||
end
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
crop
|
||||
.card-body
|
||||
%h3.card-title
|
||||
%strong= link_to crop, crop
|
||||
%strong= link_to crop.name, crop_path(slug: crop.slug)
|
||||
= crop.default_scientific_name
|
||||
.d-flex.justify-content-between
|
||||
- if crop.annual? && crop.median_lifespan.present?
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
- if photos.size.positive?
|
||||
- if crop.photos.count.positive?
|
||||
%h2 #{photo_icon} Photos
|
||||
- [Crop, Planting, Harvest, Seed].each do |model_name|
|
||||
- if photos.by_model(model_name).size.positive?
|
||||
- if crop.photos.by_model(model_name).size.positive?
|
||||
%h3 #{@crop.name.capitalize} #{t("activerecord.models.#{model_name.to_s.downcase}.other")}
|
||||
= render 'photos/gallery', photos: photos.by_model(model_name).includes(:owner).order(likes_count: :desc).limit(5)
|
||||
= render 'photos/gallery', photos: crop.photos.by_model(model_name).includes(:owner).order(likes_count: :desc).limit(5)
|
||||
= link_to 'more photos »', crop_photos_path(@crop), class: 'btn'
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
- cache crop do
|
||||
.card.crop-thumbnail
|
||||
= link_to image_tag(crop_image_path(crop),
|
||||
= link_to image_tag(crop.thumbnail_url ? crop.thumbnail_url : placeholder_image,
|
||||
alt: crop.name,
|
||||
class: 'img img-card'),
|
||||
crop
|
||||
crop_path(slug: crop.slug)
|
||||
|
||||
.text
|
||||
%h3.crop-name= link_to crop, crop
|
||||
%h3.crop-name= link_to crop.name, crop_path(slug: crop.slug)
|
||||
%h5.crop-sci-name
|
||||
|
||||
= crop.scientific_names.first&.name
|
||||
= crop.scientific_names.first
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
%h2= t('.title')
|
||||
= will_paginate @crops
|
||||
.index-cards
|
||||
- @crops.each do |crop|
|
||||
= render 'crops/thumbnail', crop: crop
|
||||
- @crops.each do |c|
|
||||
= render 'crops/thumbnail', crop: c
|
||||
|
||||
= will_paginate @crops
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
%section.photos
|
||||
= cute_icon
|
||||
= render 'crops/photos', photos: @photos, crop: @crop
|
||||
= render 'crops/photos', crop: @crop
|
||||
|
||||
- if @crop.plantings.any?
|
||||
%section.charts
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
.card
|
||||
= link_to harvest do
|
||||
= image_tag harvest_image_path(harvest), alt: harvest, class: 'img-card'
|
||||
.card-body
|
||||
%h5
|
||||
= crop_icon(harvest.crop)
|
||||
%strong
|
||||
= link_to harvest.crop, harvest
|
||||
%span.badge.badge-pill= harvest.plant_part
|
||||
.card-footer
|
||||
.float-right=render 'members/tiny', member: harvest.owner
|
||||
- cache harvest do
|
||||
.card
|
||||
= link_to harvest do
|
||||
= image_tag harvest.thumbnail_url ? harvest.thumbnail_url : placeholder_image, alt: harvest.crop_name, class: 'img-card'
|
||||
.card-body
|
||||
%h5
|
||||
%strong= link_to harvest.crop_name, harvest_path(slug: harvest.slug)
|
||||
%span.badge.badge-pill= harvest.plant_part_name
|
||||
.card-footer
|
||||
.float-right
|
||||
%span.chip.member-chip
|
||||
= link_to member_path(slug: harvest.owner_slug) do
|
||||
= harvest.owner_login_name
|
||||
@@ -1,6 +1,4 @@
|
||||
- if local_assigns[:full]
|
||||
- cache harvest do
|
||||
= render 'harvests/card', harvest: harvest
|
||||
= render 'harvests/card', harvest: harvest
|
||||
- else
|
||||
- cache harvest do
|
||||
= render 'harvests/thumbnail', harvest: harvest
|
||||
= render 'harvests/thumbnail', harvest: harvest
|
||||
@@ -1,9 +1,10 @@
|
||||
.card.harvest-thumbnail
|
||||
= link_to image_tag(harvest_image_path(harvest),
|
||||
alt: harvest,
|
||||
class: 'img img-card'),
|
||||
harvest
|
||||
- cache harvest do
|
||||
.card.harvest-thumbnail
|
||||
= link_to image_tag(harvest_image_path(harvest),
|
||||
alt: harvest,
|
||||
class: 'img img-card'),
|
||||
harvest
|
||||
|
||||
.text
|
||||
%h3.harvest-plant-part= link_to harvest.plant_part, harvest
|
||||
%h5.harvest-crop= harvest.crop
|
||||
.text
|
||||
%h3.harvest-plant-part= link_to harvest.plant_part, harvest
|
||||
%h5.harvest-crop= harvest.crop
|
||||
|
||||
@@ -29,8 +29,9 @@
|
||||
.badge.badge-success= link_to 'API Methods', '/api-docs'
|
||||
.col-md-10
|
||||
%section
|
||||
%h2
|
||||
= page_entries_info @harvests
|
||||
%h2= page_entries_info @harvests
|
||||
= will_paginate @harvests
|
||||
.index-cards=render @harvests, full: true
|
||||
.index-cards
|
||||
- @harvests.each do |h|
|
||||
= render 'harvests/card', harvest: h
|
||||
= will_paginate @harvests
|
||||
|
||||
@@ -2,18 +2,17 @@
|
||||
%rss{ version: 2.0 }
|
||||
%channel
|
||||
%title
|
||||
Recent harvests from #{@owner ? @owner : 'all members'} (#{ENV['GROWSTUFF_SITE_NAME']})
|
||||
Recent harvests from #{@owner ||= 'all members'} (#{ENV['GROWSTUFF_SITE_NAME']})
|
||||
%link= harvests_url
|
||||
- @harvests.each do |harvest|
|
||||
%item
|
||||
%title #{harvest.owner.login_name}'s #{harvest.crop.name}
|
||||
%pubdate= harvest.harvested_at.to_s(:rfc822)
|
||||
%title #{harvest.owner_login_name}'s #{harvest.crop_name}
|
||||
%pubdate= harvest.harvested_at
|
||||
%description
|
||||
:escaped
|
||||
<p>Crop: #{harvest.crop ? harvest.crop : 'unknown' }</p>
|
||||
<p>Quantity: #{harvest.quantity ? harvest.quantity : 'unknown' }</p>
|
||||
<p>Harvested on: #{harvest.harvested_at ? harvest.harvested_at : 'unknown' }</p>
|
||||
:escaped_markdown
|
||||
#{ strip_tags harvest.description }
|
||||
%link= harvest_url(harvest)
|
||||
%guid= harvest_url(harvest)
|
||||
<p>Crop: #{harvest.crop_name}</p>
|
||||
<p>Plant path: #{harvest.plant_part_name}</p>
|
||||
<p>Quantity: #{harvest.quantity ||= 'unknown' }</p>
|
||||
<p>Harvested on: #{harvest.harvested_at ||= 'unknown' }</p>
|
||||
%link= harvest_url(slug: harvest.slug)
|
||||
%guid= harvest_url(slug: harvest.slug)
|
||||
|
||||
@@ -1,16 +1,4 @@
|
||||
- cache cache_key_for(Crop, 'homepage'), expires_in: 1.day do
|
||||
.index-cards
|
||||
- CropSearchService.random_with_photos(16).each do |crop|
|
||||
.card.crop-thumbnail
|
||||
= link_to crop_path(slug: crop['slug']) do
|
||||
= image_tag(crop['photo'],
|
||||
alt: crop['name'],
|
||||
class: 'img img-card')
|
||||
|
||||
.text
|
||||
%h3.crop-name
|
||||
= link_to crop['name'], crop_path(slug: crop['slug'])
|
||||
%h5.crop-sci-name
|
||||
|
||||
= crop['scientific_name']
|
||||
|
||||
- CropSearchService.random_with_photos(16).each do |c|
|
||||
= render 'crops/thumbnail', crop: c
|
||||
@@ -12,7 +12,7 @@
|
||||
%p.mb-2
|
||||
= truncate(strip_tags(post.body), length: 200)
|
||||
%small
|
||||
= post.comments.size
|
||||
= post.comments_count
|
||||
comments
|
||||
%p.text-right
|
||||
= link_to "#{t('.view_all')} »", posts_path, class: 'btn btn-block'
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
%h2= t('.recently_harvested')
|
||||
- Harvest.has_photos.recent.includes(:crop, :owner, :photos, :plant_part).limit(6).each do |harvest|
|
||||
- Harvest.homepage_records(6).each do |harvest|
|
||||
- cache harvest do
|
||||
= link_to harvest, class: 'list-group-item list-group-item-action flex-column align-items-start' do
|
||||
= link_to harvest_path(slug: harvest.slug), class: 'list-group-item list-group-item-action flex-column align-items-start' do
|
||||
.d-flex.w-100.justify-content-between.homepage--list-item
|
||||
%div
|
||||
%h5= harvest.crop.name
|
||||
%h5= harvest.crop_name
|
||||
%span.badge.badge-success=harvest.plant_part
|
||||
%small.text-muted
|
||||
harvested by #{harvest.owner}
|
||||
%p.mb-2= image_tag harvest_image_path(harvest), width: 75, class: 'rounded shadow'
|
||||
harvested by #{harvest.owner_name}
|
||||
%p.mb-2
|
||||
= image_tag harvest.thumbnail_url, width: 75, class: 'rounded shadow'
|
||||
@@ -1,12 +1,11 @@
|
||||
%h2= t('.recently_planted')
|
||||
- Planting.has_photos.recent.includes(:owner, :crop).limit(6).each do |planting|
|
||||
- cache planting do
|
||||
= link_to planting, class: 'list-group-item list-group-item-action flex-column align-items-start' do
|
||||
.d-flex.w-100.justify-content-between.homepage--list-item
|
||||
%p.mb-2
|
||||
= image_tag planting_image_path(planting), width: 75, class: 'rounded shadow'
|
||||
.text-right
|
||||
%h5= planting.crop.name
|
||||
- if planting.planted_from.present?
|
||||
%span.badge.badge-success= planting.planted_from.pluralize
|
||||
%small.text-muted planted by #{planting.owner}
|
||||
- Planting.homepage_records(6).each do |planting|
|
||||
= link_to planting_path(slug: planting['slug']), class: 'list-group-item list-group-item-action flex-column align-items-start' do
|
||||
.d-flex.w-100.justify-content-between.homepage--list-item
|
||||
%p.mb-2
|
||||
= image_tag planting['thumbnail_url'], width: 75, class: 'rounded shadow'
|
||||
.text-right
|
||||
%h5= planting['crop_name']
|
||||
- if planting['planted_from'].present?
|
||||
%span.badge.badge-success= planting['planted_from'].pluralize
|
||||
%small.text-muted planted by #{planting['owner_name']}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
- cache cache_key_for(Seed) do
|
||||
%h2.text-center= t('home.seeds.title')
|
||||
.index-cards
|
||||
- Seed.current.tradable.includes(:owner, :crop).order(created_at: :desc).limit(6).each do |seed|
|
||||
= render 'seeds/card', seed: seed
|
||||
- Seed.homepage_records(6).each do |s|
|
||||
= render 'seeds/card', seed: s
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
= link_to timeline_index_path, method: :get, class: 'nav-link text-white' do
|
||||
= image_tag 'icons/notification.svg', class: 'img img-icon'
|
||||
%li.nav-item
|
||||
= link_to member_gardens_path(member_slug: current_member.slug), class: 'nav-link text-white' do
|
||||
= link_to member_gardens_path(current_member), class: 'nav-link text-white' do
|
||||
= image_icon 'gardens'
|
||||
%li.nav-item.dropdown
|
||||
%a.nav-link.dropdown-toggle{"aria-expanded" => "false", "aria-haspopup" => "true", "data-toggle" => "dropdown", href: "#", role: "button"}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
%span.badge.like-badge{class: (likeable.liked_by?(current_member)) ? 'liked' : ''}
|
||||
%span.badge.like-badge{class: liked ? 'liked' : ''}
|
||||
= like_icon
|
||||
|
||||
%span.like-count= likeable.likes_count
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
.card.photo-card{id: "photo-#{photo.id}"}
|
||||
= link_to image_tag(photo.source == 'flickr' ? photo.fullsize_url : photo.thumbnail_url, alt: photo.title, class: 'img img-card'), photo
|
||||
= link_to photo_path(id: photo.id) do
|
||||
= image_tag(photo.source == 'flickr' ? photo.fullsize_url : photo.thumbnail_url, alt: photo.title, class: 'img img-card')
|
||||
.card-body
|
||||
%h5.ellipsis
|
||||
= photo_icon
|
||||
= link_to photo.title, photo
|
||||
%i by #{link_to photo.owner, photo.owner}
|
||||
= link_to photo.title, photo_path(id: photo.id)
|
||||
%i by #{link_to photo.owner_login_name, member_path(slug: photo.owner_login_name)}
|
||||
- if photo.date_taken.present?
|
||||
%small.text-muted
|
||||
%time{datetime: photo.date_taken}= I18n.l(photo.date_taken.to_date)
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
%span.likes
|
||||
- if member_signed_in?
|
||||
- if can?(:new, Like) && !photo.liked_by?(current_member)
|
||||
= link_to likes_path(photo_id: photo.id, format: :json),
|
||||
method: :post, remote: true, class: 'photo-like like-btn' do
|
||||
= render 'likes/count', likeable: photo
|
||||
- if member_signed_in? && can?(:new, Like)
|
||||
- if !photo.liked_by_members_names.include?(current_member.login_name)
|
||||
= link_to likes_path(type: 'Photo', id: photo.id, format: :json),
|
||||
method: :post, remote: true, class: 'photo-like like-btn ' do
|
||||
= render 'likes/count', likeable: photo, liked: false
|
||||
- else
|
||||
- like = photo.likes.find_by(member: current_member)
|
||||
- if like && can?(:destroy, like)
|
||||
= link_to like_path(id: like.id, format: :json),
|
||||
method: :delete, remote: true, class: 'photo-like like-btn' do
|
||||
= render 'likes/count', likeable: photo
|
||||
= link_to likes_path(type: 'Photo', id: photo.id, format: :json),
|
||||
method: :delete, remote: true, class: 'photo-like like-btn' do
|
||||
= render 'likes/count', likeable: photo, liked: true
|
||||
- else
|
||||
= render 'likes/count', likeable: photo
|
||||
= render 'likes/count', likeable: photo, liked: member_signed_in? && photo.liked_by_members_names.include?(current_member.login_name)
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
.dropdown-menu.dropdown-menu-xs{"aria-labelledby" => "planting-actions-button"}
|
||||
= planting_edit_button(planting, classes: 'dropdown-item')
|
||||
= add_photo_button(planting, classes: 'dropdown-item')
|
||||
- if planting.active?
|
||||
- if planting.active
|
||||
= planting_finish_button(planting, classes: 'dropdown-item')
|
||||
= planting_harvest_button(planting, classes: 'dropdown-item')
|
||||
= planting_save_seeds_button(planting, classes: 'dropdown-item')
|
||||
|
||||
@@ -1,27 +1,37 @@
|
||||
- cache planting do
|
||||
.card.planting{class: planting.active? ? '' : 'card-finished'}
|
||||
= link_to planting do
|
||||
= image_tag planting_image_path(planting), class: 'img-card', alt: planting
|
||||
- if can? :edit, planting
|
||||
.planting-quick-actions
|
||||
.dropdown
|
||||
%a.planting-menu.btn.dropdown-toggle{"aria-expanded" => "false", "aria-haspopup" => "true", "data-toggle" => "dropdown", type: "button", href: '#'}
|
||||
.dropdown-menu{"aria-labelledby" => "planting-menu"}
|
||||
= planting_edit_button(planting, classes: 'dropdown-item')
|
||||
= add_photo_button(planting, classes: 'dropdown-item')
|
||||
.card.planting{class: planting.active ? '' : 'card-finished'}
|
||||
= link_to planting_path(slug: planting.slug) do
|
||||
= image_tag planting.thumbnail_url ? planting.thumbnail_url : placeholder_image, class: 'img-card', alt: planting.crop_name
|
||||
|
||||
- if planting.active?
|
||||
= planting_finish_button(planting, classes: 'dropdown-item')
|
||||
= planting_harvest_button(planting, classes: 'dropdown-item')
|
||||
= planting_save_seeds_button(planting, classes: 'dropdown-item')
|
||||
- if member_signed_in? && current_member.id == planting.owner_id
|
||||
= link_to planting_path(slug: planting.slug) do
|
||||
.planting-quick-actions
|
||||
.dropdown
|
||||
%a.planting-menu.btn.dropdown-toggle{"aria-expanded" => "false", "aria-haspopup" => "true", "data-toggle" => "dropdown", type: "button", href: '#'}
|
||||
|
||||
- if can? :destroy, planting
|
||||
.dropdown-divider
|
||||
= delete_button(planting, classes: 'dropdown-item text-danger')
|
||||
= link_to planting do
|
||||
.dropdown-menu{"aria-labelledby" => "planting-menu"}
|
||||
= link_to edit_planting_path(slug: planting.slug), class: 'dropdown-item' do
|
||||
= edit_icon
|
||||
= t('buttons.edit')
|
||||
= link_to new_photo_path(id: planting.id, type: 'planting'), class: 'dropdown-item' do
|
||||
= add_photo_icon
|
||||
= t('buttons.add_photo')
|
||||
|
||||
- if planting.active
|
||||
= planting_finish_button(planting, classes: 'dropdown-item')
|
||||
= planting_harvest_button(planting, classes: 'dropdown-item')
|
||||
= planting_save_seeds_button(planting, classes: 'dropdown-item')
|
||||
|
||||
- if can? :destroy, planting
|
||||
.dropdown-divider
|
||||
= delete_button(planting, classes: 'dropdown-item text-danger')
|
||||
= link_to planting_path(slug: planting.slug) do
|
||||
.card-body.text-center
|
||||
%h4= planting.crop
|
||||
%h4= planting.crop_name
|
||||
.text-center= render 'plantings/badges', planting: planting
|
||||
= render 'plantings/progress', planting: planting
|
||||
.card-footer
|
||||
.float-right=render 'members/tiny', member: planting.owner
|
||||
.float-right
|
||||
%span.chip.member-chip
|
||||
= link_to member_path(slug: planting.owner_slug) do
|
||||
= planting.owner_login_name
|
||||
@@ -16,14 +16,14 @@
|
||||
unknown
|
||||
- if planting.planted_at.present?
|
||||
%span.planted_at
|
||||
=planting.planted_at.year
|
||||
= planting.planted_at.year
|
||||
|
||||
- if planting.finish_is_predicatable?
|
||||
.card.fact-card
|
||||
%h3 Progress
|
||||
%strong #{planting.age_in_days}/#{planting.expected_lifespan}
|
||||
%span days
|
||||
|
||||
|
||||
.card.fact-card{class: planting.quantity.present? ? '' : 'text-muted'}
|
||||
%h3
|
||||
Quantity
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
%h2 Harvests
|
||||
|
||||
- if can? :edit, @planting
|
||||
- if can? :edit, planting
|
||||
%a.btn.dropdown-toggle{"aria-expanded" => "false", "aria-haspopup" => "true", "data-toggle" => "dropdown", :href => "#", :role => "button"}
|
||||
= harvest_icon
|
||||
Record harvest
|
||||
|
||||
.dropdown-menu.dropdown-secondary
|
||||
- PlantPart.all.each do |plant_part|
|
||||
= link_to harvests_path(return: 'planting', harvest: {crop_id: @planting.crop_id, planting_id: @planting.id, plant_part_id: plant_part.id}), method: :post, class: 'dropdown-item' do
|
||||
= link_to harvests_path(return: 'planting', harvest: {crop_id: planting.crop_id, planting_id: planting.id, plant_part_id: plant_part.id}), method: :post, class: 'dropdown-item' do
|
||||
= plant_part.name
|
||||
|
||||
- if planting.harvests.empty?
|
||||
@@ -16,5 +16,5 @@
|
||||
%p Record your harvests here to improve crop predictions, and you'll be able to compare with your garden next season.
|
||||
- else
|
||||
.index-cards
|
||||
- planting.harvests.order(created_at: :desc).includes(:crop).each do |harvest|
|
||||
- planting.harvests.each do |harvest|
|
||||
= render 'harvests/thumbnail', harvest: harvest
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
- if planting.active? && planting.annual? && planting.percentage_grown.present?
|
||||
- if planting.active && planting.annual? && planting.percentage_grown.present?
|
||||
.progress
|
||||
.progress-bar.bg-success{"aria-valuemax" => "100", "aria-valuemin" => "0", "aria-valuenow" => planting.percentage_grown, role: "progressbar", style: "width: #{planting.percentage_grown}%"}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
%li= planting_edit_button(planting, classes: 'dropdown-item')
|
||||
%li= add_photo_button(planting, classes: 'dropdown-item')
|
||||
|
||||
- if planting.active?
|
||||
- if planting.active
|
||||
%li= planting_finish_button(planting, classes: 'dropdown-item')
|
||||
%li= planting_harvest_button(planting, classes: 'dropdown-item')
|
||||
%li= planting_save_seeds_button(planting, classes: 'dropdown-item')
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
%h1.display-2.text-center
|
||||
= planting_icon
|
||||
= title('plantings', @owner, @crop, @planting)
|
||||
|
||||
.row
|
||||
.col-md-2
|
||||
= render 'layouts/nav', model: Planting
|
||||
@@ -20,9 +19,9 @@
|
||||
include finished plantings
|
||||
%hr
|
||||
- if @owner.present?
|
||||
= render @owner
|
||||
= render @owner, cached: true
|
||||
- if @crop.present?
|
||||
= render @crop
|
||||
= render @crop, cached: true
|
||||
|
||||
%section.open-data
|
||||
%h2 Open Data
|
||||
@@ -40,7 +39,6 @@
|
||||
%h2= page_entries_info @plantings
|
||||
= will_paginate @plantings
|
||||
.index-cards
|
||||
- @plantings.each do |planting|
|
||||
= render planting, full: true
|
||||
|
||||
- @plantings.each do |p|
|
||||
= render 'plantings/card', planting: p
|
||||
= will_paginate @plantings
|
||||
|
||||
@@ -6,15 +6,15 @@
|
||||
%link= plantings_url
|
||||
- @plantings.each do |planting|
|
||||
%item
|
||||
%title #{planting.crop} in #{planting.location}
|
||||
%pubdate= planting.created_at.to_s(:rfc822)
|
||||
%title #{planting['crop_name']} in #{planting['location']}
|
||||
%pubdate= planting['created_at'].to_s(:rfc822)
|
||||
%description
|
||||
:escaped
|
||||
<p>Quantity: #{planting.quantity ? planting.quantity : 'unknown' }</p>
|
||||
<p>Planted on: #{planting.planted_at ? planting.planted_at : 'unknown' }</p>
|
||||
<p>Sunniness: #{planting.sunniness ? planting.sunniness : 'unknown' }</p>
|
||||
<p>Planted from: #{planting.planted_from ? planting.planted_from : 'unknown' }</p>
|
||||
<p>Quantity: #{planting['quantity'] ? planting['quantity'] : 'unknown' }</p>
|
||||
<p>Planted on: #{planting['planted_at'] ? planting['planted_at'] : 'unknown' }</p>
|
||||
<p>Sunniness: #{planting['sunniness'] ? planting['sunniness'] : 'unknown' }</p>
|
||||
<p>Planted from: #{planting['planted_from'] ? planting['planted_from'] : 'unknown' }</p>
|
||||
:escaped_markdown
|
||||
#{ strip_tags planting.description }
|
||||
%link= planting_url(planting)
|
||||
%guid= planting_url(planting)
|
||||
#{ strip_tags planting['description'] }
|
||||
%link= planting_url(slug: planting['slug'])
|
||||
%guid= planting_url(slug: planting['slug'])
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
|
||||
- if member_signed_in?
|
||||
- if can?(:new, Like) && !post.liked_by?(current_member)
|
||||
= link_to 'Like', likes_path(post_id: post.id, format: :json),
|
||||
- if member_signed_in? && can?(:new, Like)
|
||||
- if !post.liked_by?(current_member)
|
||||
= link_to 'Like', likes_path(type: 'Post', id: post.id, format: :json),
|
||||
method: :post, remote: true, class: 'post-like btn like-btn'
|
||||
- else
|
||||
- like = post.likes.find_by(member: current_member)
|
||||
- if like && can?(:destroy, like)
|
||||
= link_to 'Unlike', like_path(id: like.id, format: :json),
|
||||
method: :delete, remote: true, class: 'post-like btn like-btn'
|
||||
= link_to 'Unlike', likes_path(type: 'Post', id: post.id, format: :json),
|
||||
method: :delete, remote: true, class: 'post-like btn like-btn'
|
||||
|
||||
= render 'likes/count', likeable: post
|
||||
= render 'likes/count', likeable: post, liked: member_signed_in? && post.liked_by?(current_member)
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
%a#seed-actions-button.btn.btn-info.dropdown-toggle{"aria-expanded" => "false", "aria-haspopup" => "true", "data-toggle" => "dropdown", type: "button", href: '#'}
|
||||
Actions
|
||||
.dropdown-menu.dropdown-menu-xs{"aria-labelledby" => "seed-actions-button"}
|
||||
- if can?(:create, Planting) && can?(:update, seed) && seed.active?
|
||||
- if can?(:create, Planting) && can?(:update, seed) && seed.active
|
||||
= link_to new_planting_path(seed_id: seed), class: 'dropdown-item success-color' do
|
||||
= seed_icon
|
||||
Plant seeds
|
||||
= seed_edit_button(seed, classes: 'dropdown-item')
|
||||
= add_photo_button(seed, classes: 'dropdown-item')
|
||||
- if seed.active?
|
||||
- if seed.active
|
||||
= seed_finish_button(seed, classes: 'dropdown-item')
|
||||
.dropdown-divider
|
||||
= delete_button(seed, classes: 'dropdown-item text-danger')
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
- cache seed do
|
||||
.card.seed-card{class: seed.active? ? '' : 'card-finished'}
|
||||
= link_to seed do
|
||||
= image_tag(seed_image_path(seed), alt: seed, class: 'img-card')
|
||||
.card.seed-card{class: seed.finished ? 'card-finished' : ''}
|
||||
= link_to seed_path(slug: seed.slug) do
|
||||
= image_tag(seed.thumbnail_url ? seed.thumbnail_url : placeholder_image, alt: seed.crop_name, class: 'img-card')
|
||||
.text
|
||||
= render 'members/tiny', member: seed.owner
|
||||
%span.chip.member-chip
|
||||
= seed.owner_login_name
|
||||
.card-body
|
||||
.card-title
|
||||
= crop_icon(seed.crop)
|
||||
= link_to seed.crop, seed
|
||||
- if seed.tradable?
|
||||
= link_to seed.crop_name, seed_path(slug: seed.slug)
|
||||
- if seed.tradable
|
||||
.text-muted
|
||||
= icon 'fas', 'map'
|
||||
Will trade #{seed.tradable_to}
|
||||
.badge.badge-pill.badge-location
|
||||
= icon 'fas', 'map-marker'
|
||||
= truncate(seed.owner.location, length: 20, separator: ' ', omission: '... ')
|
||||
= truncate(seed.owner_location, length: 20, separator: ' ', omission: '... ')
|
||||
@@ -38,9 +38,7 @@
|
||||
= will_paginate @seeds
|
||||
|
||||
.index-cards
|
||||
- @seeds.each do |seed|
|
||||
= render 'seeds/card', seed: seed
|
||||
- @seeds.each do |s|
|
||||
= render 'seeds/card', seed: s
|
||||
|
||||
= will_paginate @seeds
|
||||
|
||||
|
||||
|
||||
@@ -2,24 +2,21 @@
|
||||
%rss{ version: 2.0 }
|
||||
%channel
|
||||
%title
|
||||
Recent seeds from #{@owner ? @owner : 'all members'} (#{ENV['GROWSTUFF_SITE_NAME']})
|
||||
Recent seeds from #{@owner ||= 'all members'} (#{ENV['GROWSTUFF_SITE_NAME']})
|
||||
%link= seeds_url
|
||||
- @seeds.each do |seed|
|
||||
%item
|
||||
%title #{seed.owner}'s #{seed.crop} seeds
|
||||
%title #{seed.owner_login_name}'s #{seed.crop_name} seeds
|
||||
%pubdate= seed.created_at.to_s(:rfc822)
|
||||
%description
|
||||
:escaped
|
||||
<p>Quantity: #{seed.quantity ? seed.quantity : 'unknown' }</p>
|
||||
<p>Plant before: #{seed.plant_before ? seed.plant_before : 'unknown' }</p>
|
||||
<p>Quantity: #{seed.quantity ||= 'unknown' }</p>
|
||||
<p>Plant before: #{seed.plant_before ||= 'unknown' }</p>
|
||||
<p>Organic? #{seed.organic}</p>
|
||||
<p>GMO? #{seed.gmo}</p>
|
||||
<p>Heirloom? #{seed.heirloom}</p>
|
||||
- if seed.tradable?
|
||||
%p
|
||||
Will trade #{seed.tradable_to} from #{seed.owner.location ? seed.owner.location : 'unknown location'}
|
||||
|
||||
:escaped_markdown
|
||||
#{ strip_tags seed.description }
|
||||
%link= seed_url(seed)
|
||||
%guid= seed_url(seed)
|
||||
- if seed.tradable
|
||||
:escaped
|
||||
<p>Will trade #{seed.tradable_to} from #{seed.location ||= 'unknown location'}</p>
|
||||
%link= seed_url(slug: seed.slug)
|
||||
%guid= seed_url(slug: seed.slug)
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
#{strip_tags(@seed.description)}
|
||||
|
||||
- if current_member
|
||||
- if @seed.tradable? && current_member != @seed.owner
|
||||
- if @seed.tradable && current_member != @seed.owner
|
||||
%p= link_to "Request seeds",
|
||||
new_message_path(recipient_id: @seed.owner.id,
|
||||
subject: "Interested in your #{@seed.crop} seeds"),
|
||||
|
||||
@@ -125,7 +125,7 @@ en:
|
||||
title:
|
||||
crop_harvests: Everyone's %{crop} harvests
|
||||
default: Everyone's harvests
|
||||
owner_harvests: "%{owner} harvests"
|
||||
owner_harvests: "%{owner}'s harvests"
|
||||
planting_harvests: Harvests from %{planting}
|
||||
updated: Harvest was successfully updated.
|
||||
home:
|
||||
|
||||
@@ -86,7 +86,10 @@ Rails.application.routes.draw do
|
||||
resources :forums
|
||||
|
||||
resources :follows, only: %i(create destroy)
|
||||
resources :likes, only: %i(create destroy)
|
||||
|
||||
post 'likes' => 'likes#create'
|
||||
delete 'likes' => 'likes#destroy'
|
||||
|
||||
resources :timeline
|
||||
|
||||
resources :members, param: :slug do
|
||||
|
||||
@@ -30,7 +30,9 @@ class CmsTags < ActiveRecord::Migration[5.2]
|
||||
layout.content = layout.content.gsub(/\{\{ ?cms:(\w+):([\w]+):([^:]*) ?\}\}/, '{{ cms:\1 \2, "\3" }}') if layout.content.is_a? String
|
||||
layout.content = layout.content.gsub(/cms:rich_text/, 'cms:wysiwyg') if layout.content.is_a? String
|
||||
layout.content = layout.content.gsub(/cms:integer/, 'cms:number') if layout.content.is_a? String
|
||||
layout.content = layout.content.gsub(/cms: string/, 'cms:text') if layout.content.is_a? String # probably a result of goofing one of the more general regexps
|
||||
if layout.content.is_a? String
|
||||
layout.content = layout.content.gsub(/cms: string/, 'cms:text')
|
||||
end # probably a result of goofing one of the more general regexps
|
||||
if layout.content.is_a? String
|
||||
layout.content = layout.content.gsub(%r{\{\{ ?cms:page_file ([\w/]+) ?\}\}}, '{{ cms:file \1, render: false }}')
|
||||
end
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
|
||||
# frozen_string_literal: true
|
||||
|
||||
|
||||
class CropPhotoCounterCache < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
change_table :crops do |t|
|
||||
|
||||
18
db/migrate/20191226051019_elastic_indexing.rb
Normal file
18
db/migrate/20191226051019_elastic_indexing.rb
Normal file
@@ -0,0 +1,18 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class ElasticIndexing < ActiveRecord::Migration[5.2]
|
||||
def up
|
||||
say 'indexing crops'
|
||||
Crop.reindex
|
||||
say 'indexing plantings'
|
||||
Planting.reindex
|
||||
say 'indexing seeds'
|
||||
Seed.reindex
|
||||
say 'indexing harvests'
|
||||
Harvest.reindex
|
||||
say 'indexing photos'
|
||||
Photo.reindex
|
||||
end
|
||||
|
||||
def down; end
|
||||
end
|
||||
@@ -10,7 +10,7 @@
|
||||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 2019_12_26_025225) do
|
||||
ActiveRecord::Schema.define(version: 2019_12_26_051019) do
|
||||
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
|
||||
@@ -2,15 +2,15 @@
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe HarvestsController do
|
||||
describe HarvestsController, :search do
|
||||
login_member
|
||||
|
||||
def valid_attributes
|
||||
{
|
||||
owner_id: subject.current_member.id,
|
||||
crop_id: FactoryBot.create(:crop).id,
|
||||
owner_id: subject.current_member.id,
|
||||
crop_id: FactoryBot.create(:crop).id,
|
||||
plant_part_id: FactoryBot.create(:plant_part).id,
|
||||
harvested_at: '2017-01-01'
|
||||
harvested_at: '2017-01-01'
|
||||
}
|
||||
end
|
||||
|
||||
@@ -22,24 +22,30 @@ describe HarvestsController do
|
||||
let!(:harvest1) { FactoryBot.create(:harvest, owner_id: member1.id, crop_id: tomato.id) }
|
||||
let!(:harvest2) { FactoryBot.create(:harvest, owner_id: member2.id, crop_id: maize.id) }
|
||||
|
||||
before { Harvest.reindex }
|
||||
|
||||
describe "assigns all harvests as @harvests" do
|
||||
before { get :index, params: {} }
|
||||
|
||||
it { expect(assigns(:harvests)).to eq [harvest1, harvest2] }
|
||||
it { expect(assigns(:harvests).size).to eq 2 }
|
||||
it { expect(assigns(:harvests)[0].slug).to eq harvest1.slug }
|
||||
it { expect(assigns(:harvests)[1].slug).to eq harvest2.slug }
|
||||
end
|
||||
|
||||
describe "picks up owner from params and shows owner's harvests only" do
|
||||
before { get :index, params: { member_slug: member1.slug } }
|
||||
|
||||
it { expect(assigns(:owner)).to eq member1 }
|
||||
it { expect(assigns(:harvests)).to eq [harvest1] }
|
||||
it { expect(assigns(:harvests).size).to eq 1 }
|
||||
it { expect(assigns(:harvests)[0].slug).to eq harvest1.slug }
|
||||
end
|
||||
|
||||
describe "picks up crop from params and shows the harvests for the crop only" do
|
||||
before { get :index, params: { crop_slug: maize.name } }
|
||||
|
||||
it { expect(assigns(:crop)).to eq maize }
|
||||
it { expect(assigns(:harvests)).to eq [harvest2] }
|
||||
it { expect(assigns(:harvests).size).to eq 1 }
|
||||
it { expect(assigns(:harvests)[0].slug).to eq harvest2.slug }
|
||||
end
|
||||
|
||||
describe "generates a csv" do
|
||||
@@ -189,8 +195,10 @@ describe HarvestsController do
|
||||
|
||||
describe "does not save planting_id" do
|
||||
before do
|
||||
put :update, params: { slug: harvest.to_param,
|
||||
harvest: valid_attributes.merge(planting_id: not_my_planting.id) }
|
||||
put :update, params: {
|
||||
slug: harvest.to_param,
|
||||
harvest: valid_attributes.merge(planting_id: not_my_planting.id)
|
||||
}
|
||||
end
|
||||
|
||||
it { expect(harvest.planting_id).to eq(nil) }
|
||||
|
||||
@@ -10,7 +10,7 @@ describe LikesController do
|
||||
before { sign_in member }
|
||||
|
||||
describe "POST create" do
|
||||
before { post :create, params: { post_id: blogpost.id, format: :json } }
|
||||
before { post :create, params: { type: 'Post', id: blogpost.id, format: :json } }
|
||||
|
||||
it { expect(response.content_type).to eq "application/json" }
|
||||
|
||||
@@ -27,7 +27,7 @@ describe LikesController do
|
||||
end
|
||||
|
||||
describe "DELETE destroy" do
|
||||
before { delete :destroy, params: { id: like.id, format: :json } }
|
||||
before { delete :destroy, params: { type: like.likeable_type, id: like.likeable_id, format: :json } }
|
||||
|
||||
it { expect(response.content_type).to eq "application/json" }
|
||||
|
||||
|
||||
@@ -2,36 +2,53 @@
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe PhotosController do
|
||||
describe PhotosController, :search do
|
||||
login_member
|
||||
|
||||
describe 'GET index' do
|
||||
describe 'all photos' do
|
||||
let!(:photo) { FactoryBot.create :photo }
|
||||
let!(:photo) { FactoryBot.create :photo, :reindex }
|
||||
|
||||
before { get :index }
|
||||
before do
|
||||
Photo.reindex
|
||||
get :index
|
||||
end
|
||||
|
||||
it { expect(assigns(:photos)).to eq [photo] }
|
||||
it "finds photos" do
|
||||
expect(assigns(:photos).count).to eq 1
|
||||
expect(assigns(:photos).first.id).to eq photo.id
|
||||
end
|
||||
end
|
||||
|
||||
describe 'crop photos' do
|
||||
let!(:photo) { FactoryBot.create :photo, owner: member }
|
||||
let!(:crop_photo) { FactoryBot.create :photo, owner: member }
|
||||
let!(:planting) { FactoryBot.create :planting, crop: crop, owner: member }
|
||||
let!(:crop) { FactoryBot.create :crop }
|
||||
describe '#index crop photos' do
|
||||
let!(:photo) { FactoryBot.create :photo, :reindex, owner: member, title: 'no assocations photo' }
|
||||
let!(:crop_photo) { FactoryBot.create :photo, :reindex, owner: member, title: 'photos of planting' }
|
||||
let!(:planting) { FactoryBot.create :planting, :reindex, crop: crop, owner: member }
|
||||
let!(:crop) { FactoryBot.create :crop, :reindex }
|
||||
|
||||
before do
|
||||
planting.photos << crop_photo
|
||||
Photo.reindex
|
||||
get :index, params: { crop_slug: crop.to_param }
|
||||
end
|
||||
|
||||
it { expect(assigns(:crop)).to eq crop }
|
||||
it { expect(assigns(:photos)).to eq [crop_photo] }
|
||||
describe "find photos by crop" do
|
||||
it "has indexed the photos of this crop" do
|
||||
expect(Photo.search).to include crop_photo
|
||||
end
|
||||
it "assigns crop" do
|
||||
expect(assigns(:crop)).to eq crop
|
||||
end
|
||||
|
||||
it { expect(assigns(:photos).size).to eq 1 }
|
||||
it { expect(assigns(:photos).first.crops).to include crop.id }
|
||||
it { expect(assigns(:photos).first.id).to eq crop_photo.id }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET new" do
|
||||
let(:tomato) { FactoryBot.create(:tomato) }
|
||||
let(:tomato) { FactoryBot.create(:tomato) }
|
||||
let(:planting) { FactoryBot.create(:planting, crop: tomato, owner: member) }
|
||||
let(:garden) { FactoryBot.create(:garden, owner: member) }
|
||||
let(:harvest) { FactoryBot.create(:harvest, owner: member) }
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe PlantingsController do
|
||||
describe PlantingsController, :search do
|
||||
login_member
|
||||
|
||||
def valid_attributes
|
||||
@@ -12,32 +12,38 @@ describe PlantingsController do
|
||||
}
|
||||
end
|
||||
|
||||
describe "GET index" do
|
||||
describe "GET index", :search do
|
||||
let!(:member1) { FactoryBot.create(:member) }
|
||||
let!(:member2) { FactoryBot.create(:member) }
|
||||
let!(:tomato) { FactoryBot.create(:tomato) }
|
||||
let!(:maize) { FactoryBot.create(:maize) }
|
||||
let!(:planting1) { FactoryBot.create :planting, crop: tomato, owner: member1, created_at: 1.day.ago }
|
||||
let!(:planting2) { FactoryBot.create :planting, crop: maize, owner: member2, created_at: 5.days.ago }
|
||||
before do
|
||||
Planting.reindex
|
||||
end
|
||||
|
||||
describe "assigns all plantings as @plantings" do
|
||||
before { get :index }
|
||||
|
||||
it { expect(assigns(:plantings)).to match [planting1, planting2] }
|
||||
it { expect(assigns(:plantings).size).to eq 2 }
|
||||
it { expect(assigns(:plantings)[0]['slug']).to eq planting1.slug }
|
||||
it { expect(assigns(:plantings)[1]['slug']).to eq planting2.slug }
|
||||
end
|
||||
|
||||
describe "picks up owner from params and shows owner's plantings only" do
|
||||
before { get :index, params: { member_slug: member1.slug } }
|
||||
|
||||
it { expect(assigns(:owner)).to eq member1 }
|
||||
it { expect(assigns(:plantings)).to eq [planting1] }
|
||||
it { expect(assigns(:plantings).size).to eq 1 }
|
||||
it { expect(assigns(:plantings).first['slug']).to eq planting1.slug }
|
||||
end
|
||||
|
||||
describe "picks up crop from params and shows the plantings for the crop only" do
|
||||
before { get :index, params: { crop_slug: maize.slug } }
|
||||
|
||||
it { expect(assigns(:crop)).to eq maize }
|
||||
it { expect(assigns(:plantings)).to eq [planting2] }
|
||||
it { expect(assigns(:plantings).first['slug']).to eq planting2.slug }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -119,4 +125,19 @@ describe PlantingsController do
|
||||
it { expect(assigns(:planting).owner).to eq subject.current_member }
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET :edit' do
|
||||
let(:my_planting) { FactoryBot.create :planting, owner: member }
|
||||
let(:not_my_planting) { FactoryBot.create :planting }
|
||||
context 'my planting' do
|
||||
before { get :edit, params: { slug: my_planting } }
|
||||
it { expect(assigns(:planting)).to eq my_planting }
|
||||
end
|
||||
|
||||
context 'not my planting' do
|
||||
before { get :edit, params: { slug: not_my_planting } }
|
||||
|
||||
it { expect(response).to redirect_to(root_path) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,14 +2,15 @@
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe SeedsController do
|
||||
describe SeedsController, :search do
|
||||
let(:owner) { FactoryBot.create(:member) }
|
||||
|
||||
describe "GET index" do
|
||||
let(:owner) { FactoryBot.create(:member) }
|
||||
|
||||
describe "picks up owner from params" do
|
||||
before { get :index, params: { member_slug: owner.slug } }
|
||||
before do
|
||||
Seed.reindex
|
||||
get :index, params: { member_slug: owner.slug }
|
||||
end
|
||||
|
||||
it { expect(assigns(:owner)).to eq(owner) }
|
||||
end
|
||||
@@ -25,9 +26,12 @@ describe SeedsController do
|
||||
end
|
||||
|
||||
context 'with parent planting' do
|
||||
let(:planting) { FactoryBot.create :planting, owner: owner }
|
||||
let!(:planting) { FactoryBot.create :planting, owner: owner }
|
||||
|
||||
before { get :new, params: { planting_id: planting.to_param } }
|
||||
before do
|
||||
Seed.reindex
|
||||
get :new, params: { planting_slug: planting.to_param }
|
||||
end
|
||||
|
||||
it { expect(assigns(:planting)).to eq(planting) }
|
||||
end
|
||||
|
||||
@@ -53,6 +53,11 @@ FactoryBot.define do
|
||||
name { "eggplant" }
|
||||
end
|
||||
|
||||
factory :crop_with_photo do
|
||||
name { 'marshmallow' }
|
||||
photos { FactoryBot.create_list :photo, 1 }
|
||||
end
|
||||
|
||||
# This should have a name that is alphabetically earlier than :uppercase
|
||||
# crop to ensure that the ordering tests work.
|
||||
factory :lowercasecrop do
|
||||
@@ -81,5 +86,11 @@ FactoryBot.define do
|
||||
approval_status { "rejected" }
|
||||
reason_for_rejection { "Totally fake" }
|
||||
end
|
||||
|
||||
trait :reindex do
|
||||
after(:create) do |crop, _evaluator|
|
||||
crop.reindex(refresh: true)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -27,4 +27,10 @@ FactoryBot.define do
|
||||
trait :no_description do
|
||||
description { "" }
|
||||
end
|
||||
|
||||
trait :reindex do
|
||||
after(:create) do |harvest, _evaluator|
|
||||
harvest.reindex(refresh: true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -18,5 +18,11 @@ FactoryBot.define do
|
||||
license_name { "All rights reserved" }
|
||||
license_url { nil }
|
||||
end
|
||||
|
||||
trait :reindex do
|
||||
after(:create) do |photo, _evaluator|
|
||||
photo.reindex(refresh: true)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -61,5 +61,18 @@ FactoryBot.define do
|
||||
crop
|
||||
end
|
||||
end
|
||||
|
||||
trait :with_photo do
|
||||
after(:create) do |planting, _evaluator|
|
||||
planting.photos << FactoryBot.create(:photo, owner_id: planting.owner_id)
|
||||
planting.save
|
||||
end
|
||||
end
|
||||
|
||||
trait :reindex do
|
||||
after(:create) do |planting, _evaluator|
|
||||
planting.reindex(refresh: true)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -31,5 +31,11 @@ FactoryBot.define do
|
||||
factory :untradable_seed do
|
||||
tradable_to { "nowhere" }
|
||||
end
|
||||
|
||||
trait :reindex do
|
||||
after(:create) do |seed, _evaluator|
|
||||
seed.reindex(refresh: true)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,14 +2,18 @@
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe "browse crops" do
|
||||
let!(:tomato) { FactoryBot.create :tomato }
|
||||
let!(:maize) { FactoryBot.create :maize }
|
||||
let!(:pending_crop) { FactoryBot.create :crop_request }
|
||||
let!(:rejected_crop) { FactoryBot.create :rejected_crop }
|
||||
describe "browse crops", :search do
|
||||
let!(:tomato) { FactoryBot.create :tomato, :reindex }
|
||||
let!(:maize) { FactoryBot.create :maize, :reindex }
|
||||
let!(:pending_crop) { FactoryBot.create :crop_request, :reindex }
|
||||
let!(:rejected_crop) { FactoryBot.create :rejected_crop, :reindex }
|
||||
|
||||
shared_examples 'shows crops' do
|
||||
before { visit crops_path }
|
||||
before do
|
||||
Crop.reindex
|
||||
visit crops_path
|
||||
end
|
||||
|
||||
it "has a form for sorting by" do
|
||||
expect(page).to have_css "select#sort"
|
||||
end
|
||||
|
||||
@@ -2,15 +2,17 @@
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe "crop detail page", js: true do
|
||||
describe "crop detail page", :js, :search do
|
||||
subject { page }
|
||||
|
||||
let!(:owner_member) { FactoryBot.create :member }
|
||||
|
||||
let!(:crop) { FactoryBot.create :crop }
|
||||
let!(:crop) { FactoryBot.create :crop, :reindex }
|
||||
|
||||
let(:plant_part) { FactoryBot.create :plant_part, name: 'fruit' }
|
||||
|
||||
let!(:harvest) { FactoryBot.create :harvest, crop: crop, owner: owner_member, plant_part: plant_part }
|
||||
let!(:planting) { FactoryBot.create :planting, crop: crop, owner: owner_member }
|
||||
let!(:harvest) { FactoryBot.create :harvest, crop: crop, owner: owner_member }
|
||||
let!(:seed) { FactoryBot.create :seed, crop: crop, owner: owner_member }
|
||||
|
||||
let!(:photo1) { FactoryBot.create(:photo, owner: owner_member) }
|
||||
@@ -27,7 +29,11 @@ describe "crop detail page", js: true do
|
||||
harvest.photos << photo4
|
||||
seed.photos << photo5
|
||||
seed.photos << photo6
|
||||
Crop.reindex
|
||||
visit crop_path(crop)
|
||||
expect(crop.photos.count).to eq 6
|
||||
expect(crop.photos.by_model(Planting).count).to eq 2
|
||||
expect(page).to have_content 'Photos'
|
||||
end
|
||||
|
||||
shared_examples "shows photos" do
|
||||
|
||||
@@ -115,7 +115,7 @@ describe "Planting a crop", js: true do
|
||||
describe "Making a planting inactive from garden show" do
|
||||
it do
|
||||
visit garden_path(garden)
|
||||
click_link(class: 'planting-menu')
|
||||
click_link(class: 'planting-menu') # quick menu
|
||||
click_link "Mark as finished"
|
||||
find(".datepicker-days td.day", text: "21").click
|
||||
expect(page).to have_content 'Finished'
|
||||
|
||||
@@ -2,17 +2,21 @@
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe "browse harvests" do
|
||||
describe "browse harvests", :search do
|
||||
subject { page }
|
||||
|
||||
let!(:harvest) { create :harvest, owner: member }
|
||||
|
||||
context 'signed in' do
|
||||
include_context 'signed in member'
|
||||
describe 'blank optional fields' do
|
||||
let!(:harvest) { create :harvest, :no_description }
|
||||
|
||||
before { visit harvests_path }
|
||||
describe 'blank optional fields' do
|
||||
let!(:harvest) { create :harvest, :no_description, :reindex }
|
||||
|
||||
before do
|
||||
Harvest.reindex
|
||||
visit harvests_path
|
||||
end
|
||||
|
||||
it 'read more' do
|
||||
expect(subject).not_to have_link "Read more"
|
||||
@@ -20,9 +24,10 @@ describe "browse harvests" do
|
||||
end
|
||||
|
||||
describe "filled in optional fields" do
|
||||
let!(:harvest) { create :harvest, :long_description }
|
||||
let!(:harvest) { create :harvest, :long_description, :reindex }
|
||||
|
||||
before do
|
||||
Harvest.reindex
|
||||
visit harvests_path
|
||||
end
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
require 'rails_helper'
|
||||
require 'custom_matchers'
|
||||
|
||||
describe "Harvesting a crop", :js do
|
||||
describe "Harvesting a crop", :js, :search do
|
||||
context 'signed in' do
|
||||
include_context 'signed in member'
|
||||
let!(:maize) { create :maize }
|
||||
@@ -40,12 +40,15 @@ describe "Harvesting a crop", :js do
|
||||
expect(page).to have_content "harvest was successfully created."
|
||||
end
|
||||
|
||||
it "Clicking link to owner's profile" do
|
||||
visit member_harvests_path(member)
|
||||
within '.login-name' do
|
||||
click_link member.login_name
|
||||
describe 'member harvests' do
|
||||
before { visit member_harvests_path(member) }
|
||||
it { expect(page).to have_text "#{member.login_name}'s harvests" }
|
||||
it "Clicking link to owner's profile" do
|
||||
within '.login-name' do
|
||||
click_link member.login_name
|
||||
end
|
||||
expect(current_path).to eq member_path(member)
|
||||
end
|
||||
expect(current_path).to eq member_path member
|
||||
end
|
||||
|
||||
describe "Harvesting from crop page" do
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe "home page" do
|
||||
describe "home page", :search do
|
||||
subject { page }
|
||||
|
||||
let(:member) { FactoryBot.create :member }
|
||||
@@ -14,19 +14,24 @@ describe "home page" do
|
||||
let(:seed) { FactoryBot.create :tradable_seed, owner: member, crop: crop }
|
||||
let(:harvest) { FactoryBot.create :harvest, owner: member, crop: crop }
|
||||
|
||||
let!(:tradable_seed) { FactoryBot.create :tradable_seed, finished: false }
|
||||
let!(:finished_seed) { FactoryBot.create :tradable_seed, finished: true }
|
||||
let!(:untradable_seed) { FactoryBot.create :untradable_seed }
|
||||
let!(:tradable_seed) { FactoryBot.create :tradable_seed, :reindex, finished: false }
|
||||
let!(:finished_seed) { FactoryBot.create :tradable_seed, :reindex, finished: true }
|
||||
let!(:untradable_seed) { FactoryBot.create :untradable_seed, :reindex }
|
||||
|
||||
before do
|
||||
# Add photos, so they can appear on home page
|
||||
planting.photos << photo
|
||||
seed.photos << photo
|
||||
harvest.photos << photo
|
||||
Crop.reindex
|
||||
end
|
||||
|
||||
before { visit root_path }
|
||||
Crop.reindex
|
||||
Planting.reindex
|
||||
Seed.reindex
|
||||
Harvest.reindex
|
||||
Photo.reindex
|
||||
|
||||
visit root_path
|
||||
end
|
||||
|
||||
shared_examples 'shows seeds' do
|
||||
it "show tradeable seed" do
|
||||
@@ -48,6 +53,7 @@ describe "home page" do
|
||||
it { expect(subject).to have_link href: planting_path(planting) }
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples 'show harvests' do
|
||||
describe 'shows harvests section' do
|
||||
it { expect(subject).to have_text 'Recently Harvested' }
|
||||
|
||||
@@ -2,14 +2,21 @@
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe 'Likeable', js: true do
|
||||
describe 'Likeable', :js, search: true do
|
||||
let(:another_member) { FactoryBot.create(:london_member) }
|
||||
let!(:post) { FactoryBot.create(:post, author: member) }
|
||||
let!(:photo) { FactoryBot.create(:photo, owner: member) }
|
||||
let!(:post) { FactoryBot.create(:post, :reindex, author: member) }
|
||||
let!(:photo) { FactoryBot.create(:photo, :reindex, owner: member) }
|
||||
|
||||
before do
|
||||
Photo.reindex
|
||||
end
|
||||
|
||||
include_context 'signed in member'
|
||||
|
||||
describe 'photos' do
|
||||
let(:like_count_class) { "#photo-#{photo.id} .like-count" }
|
||||
def like_count_class
|
||||
"#photo-#{photo.id} .like-count"
|
||||
end
|
||||
|
||||
shared_examples 'photo can be liked' do
|
||||
it 'can be liked' do
|
||||
|
||||
@@ -3,13 +3,15 @@
|
||||
require "rails_helper"
|
||||
require 'custom_matchers'
|
||||
|
||||
describe "Planting a crop", :js do
|
||||
describe "Planting a crop", :js, :search do
|
||||
let!(:maize) { FactoryBot.create :maize }
|
||||
let(:garden) { FactoryBot.create :garden, owner: member, name: 'Orchard' }
|
||||
let!(:planting) do
|
||||
FactoryBot.create :planting, garden: garden, owner: member, planted_at: Date.parse("2013-03-10")
|
||||
end
|
||||
|
||||
before { Planting.reindex }
|
||||
|
||||
context 'signed in' do
|
||||
include_context 'signed in member'
|
||||
before { visit new_planting_path }
|
||||
@@ -222,6 +224,9 @@ describe "Planting a crop", :js do
|
||||
expect(page).to have_content "Finished"
|
||||
expect(page).to have_content "Aug 2014"
|
||||
|
||||
# ensure we've indexed in elastic search
|
||||
planting.reindex(refresh: true)
|
||||
|
||||
# shouldn't be on the page
|
||||
visit plantings_path
|
||||
expect(page).not_to have_content "maize"
|
||||
|
||||
@@ -4,11 +4,13 @@ require 'rails_helper'
|
||||
|
||||
describe 'Crops RSS feed' do
|
||||
it 'The index feed exists' do
|
||||
Crop.reindex
|
||||
visit crops_path(format: 'rss')
|
||||
# expect(page.status_code).to equal 200
|
||||
end
|
||||
|
||||
it 'The index title is what we expect' do
|
||||
Crop.reindex
|
||||
visit crops_path(format: 'rss')
|
||||
expect(page).to have_content "Recently added crops (#{ENV['GROWSTUFF_SITE_NAME']})"
|
||||
end
|
||||
|
||||
@@ -9,6 +9,7 @@ describe 'Plantings RSS feed' do
|
||||
end
|
||||
|
||||
it 'The index title is what we expect' do
|
||||
Planting.reindex
|
||||
visit plantings_path(format: 'rss')
|
||||
expect(page).to have_content "Recent plantings from "\
|
||||
"#{@owner || 'all members'} (#{ENV['GROWSTUFF_SITE_NAME']})"
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
require 'rails_helper'
|
||||
require 'custom_matchers'
|
||||
|
||||
describe "Seeds", :js do
|
||||
describe "Seeds", :js, :search do
|
||||
context 'signed in' do
|
||||
include_context 'signed in member'
|
||||
let!(:maize) { create :maize }
|
||||
|
||||
@@ -3,5 +3,12 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe CropCompanion, type: :model do
|
||||
pending "add some examples to (or delete) #{__FILE__}"
|
||||
it 'has a crop' do
|
||||
cc = CropCompanion.new
|
||||
cc.crop_a = FactoryBot.create :tomato
|
||||
cc.crop_b = FactoryBot.create :maize
|
||||
cc.save!
|
||||
|
||||
expect(cc.crop_a.name).to eq 'tomato'
|
||||
end
|
||||
end
|
||||
|
||||
@@ -5,6 +5,7 @@ require 'rails_helper'
|
||||
describe 'like' do
|
||||
let(:member) { FactoryBot.create(:member) }
|
||||
let(:post) { FactoryBot.create(:post) }
|
||||
let(:photo) { FactoryBot.create :photo }
|
||||
|
||||
context 'existing like' do
|
||||
before do
|
||||
@@ -61,4 +62,14 @@ describe 'like' do
|
||||
member.destroy
|
||||
expect(Like.all).not_to include like
|
||||
end
|
||||
|
||||
it 'liked_by_members_names' do
|
||||
expect(post.liked_by_members_names).to eq []
|
||||
Like.create(member: member, likeable: post)
|
||||
expect(post.liked_by_members_names).to eq [member.login_name]
|
||||
|
||||
expect(photo.liked_by_members_names).to eq []
|
||||
Like.create(member: member, likeable: photo)
|
||||
expect(photo.liked_by_members_names).to eq [member.login_name]
|
||||
end
|
||||
end
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe Photo do
|
||||
let(:photo) { FactoryBot.create(:photo, owner: member) }
|
||||
let(:old_photo) { FactoryBot.create(:photo, owner: member, created_at: 1.year.ago, date_taken: 2.years.ago) }
|
||||
let(:photo) { FactoryBot.create(:photo, :reindex, owner: member) }
|
||||
let(:member) { FactoryBot.create(:member) }
|
||||
|
||||
it_behaves_like "it is likeable"
|
||||
@@ -20,13 +19,14 @@ describe Photo do
|
||||
describe 'to a planting' do
|
||||
before { planting.photos << photo }
|
||||
|
||||
it { expect(planting.photos.size).to eq 1 }
|
||||
it { expect(planting.photos.count).to eq 1 }
|
||||
it { expect(planting.photos.first).to eq photo }
|
||||
# there's only one photo, so that's the default
|
||||
it { expect(planting.default_photo).to eq photo }
|
||||
it { expect(planting.crop.default_photo).to eq photo }
|
||||
|
||||
describe 'with a second older photo' do
|
||||
let(:old_photo) { FactoryBot.create(:photo, owner: member, created_at: 1.year.ago, date_taken: 2.years.ago) }
|
||||
# Add an old photo
|
||||
before { planting.photos << old_photo }
|
||||
it { expect(planting.default_photo).to eq photo }
|
||||
@@ -40,28 +40,45 @@ describe Photo do
|
||||
end
|
||||
end
|
||||
|
||||
it 'to a harvest' do
|
||||
harvest.photos << photo
|
||||
expect(harvest.photos.size).to eq 1
|
||||
expect(harvest.photos.first).to eq photo
|
||||
describe 'to a harvest' do
|
||||
let(:crop) { harvest.crop }
|
||||
before { harvest.photos << photo }
|
||||
|
||||
it { expect(harvest.photos).to eq [photo] }
|
||||
it { expect(harvest.photo_associations.count).to eq 1 }
|
||||
|
||||
# Check the relationship from crop
|
||||
it { expect(crop.photo_associations.count).to eq 1 }
|
||||
it { expect(crop.photos.count).to eq 1 }
|
||||
it { expect(crop.photos).to eq [photo] }
|
||||
|
||||
# Check the relationship from the photo
|
||||
it { expect(photo.photo_associations.count).to eq 1 }
|
||||
it { expect(photo.photo_associations.map(&:crop)).to eq [ crop ] }
|
||||
it { expect(photo.crops.count).to eq 1 }
|
||||
it { expect(photo.crops).to eq [crop] }
|
||||
end
|
||||
|
||||
it 'to a seed' do
|
||||
seed.photos << photo
|
||||
expect(seed.photos.size).to eq 1
|
||||
expect(seed.photos.first).to eq photo
|
||||
expect(seed.photos).to eq [photo]
|
||||
expect(photo.crops).to eq [seed.crop]
|
||||
end
|
||||
|
||||
it 'to a planting' do
|
||||
planting.photos << photo
|
||||
expect(planting.photos).to eq [photo]
|
||||
expect(photo.crops).to eq [planting.crop]
|
||||
end
|
||||
|
||||
it 'to a garden' do
|
||||
garden.photos << photo
|
||||
expect(garden.photos.size).to eq 1
|
||||
expect(garden.photos.first).to eq photo
|
||||
expect(garden.photos).to eq [photo]
|
||||
end
|
||||
|
||||
it 'to a post' do
|
||||
post.photos << photo
|
||||
expect(post.photos.size).to eq 1
|
||||
expect(post.photos.first).to eq photo
|
||||
expect(post.photos).to eq [photo]
|
||||
end
|
||||
end
|
||||
|
||||
@@ -69,19 +86,19 @@ describe Photo do
|
||||
it 'from a planting' do
|
||||
planting.photos << photo
|
||||
photo.destroy
|
||||
expect(planting.photos.size).to eq 0
|
||||
expect(planting.photos.count).to eq 0
|
||||
end
|
||||
|
||||
it 'from a harvest' do
|
||||
harvest.photos << photo
|
||||
photo.destroy
|
||||
expect(harvest.photos.size).to eq 0
|
||||
expect(harvest.photos.count).to eq 0
|
||||
end
|
||||
|
||||
it 'from a garden' do
|
||||
garden.photos << photo
|
||||
photo.destroy
|
||||
expect(garden.photos.size).to eq 0
|
||||
expect(garden.photos.count).to eq 0
|
||||
end
|
||||
|
||||
it "automatically if unused" do
|
||||
@@ -117,23 +134,23 @@ describe Photo do
|
||||
planting.photos << photo
|
||||
harvest.photos << photo
|
||||
garden.photos << photo
|
||||
expect(photo.plantings.size).to eq 1
|
||||
expect(photo.harvests.size).to eq 1
|
||||
expect(photo.gardens.size).to eq 1
|
||||
expect(photo.plantings.count).to eq 1
|
||||
expect(photo.harvests.count).to eq 1
|
||||
expect(photo.gardens.count).to eq 1
|
||||
|
||||
planting.destroy # photo is still used by harvest and garden
|
||||
photo.reload
|
||||
|
||||
expect(photo.plantings.size).to eq 0
|
||||
expect(photo.harvests.size).to eq 1
|
||||
expect(photo.plantings.count).to eq 0
|
||||
expect(photo.harvests.count).to eq 1
|
||||
|
||||
harvest.destroy
|
||||
garden.destroy # photo is now no longer used by anything
|
||||
photo.reload
|
||||
|
||||
expect(photo.plantings.size).to eq 0
|
||||
expect(photo.harvests.size).to eq 0
|
||||
expect(photo.gardens.size).to eq 0
|
||||
expect(photo.plantings.count).to eq 0
|
||||
expect(photo.harvests.count).to eq 0
|
||||
expect(photo.gardens.count).to eq 0
|
||||
photo.destroy_if_unused
|
||||
expect(-> { photo.reload }).to raise_error ActiveRecord::RecordNotFound
|
||||
end
|
||||
@@ -163,16 +180,16 @@ describe Photo do
|
||||
expect(Photo.joins(:owner).all).not_to include(photo)
|
||||
end
|
||||
|
||||
describe 'scopes' do
|
||||
let(:harvest_crop) { FactoryBot.create :crop }
|
||||
describe 'assocations' do
|
||||
let(:harvest_crop) { FactoryBot.create :crop, name: 'harvest_crop' }
|
||||
let!(:harvest) { FactoryBot.create :harvest, owner: member, crop: harvest_crop }
|
||||
let!(:harvest_photo) { FactoryBot.create :photo, owner: member }
|
||||
|
||||
let(:planting_crop) { FactoryBot.create :crop }
|
||||
let(:planting_crop) { FactoryBot.create :crop, name: 'planting_crop' }
|
||||
let!(:planting) { FactoryBot.create :planting, owner: member, crop: planting_crop }
|
||||
let!(:planting_photo) { FactoryBot.create :photo, owner: member }
|
||||
|
||||
let(:seed_crop) { FactoryBot.create :crop }
|
||||
let(:seed_crop) { FactoryBot.create :crop, name: 'seed_crop' }
|
||||
let!(:seed) { FactoryBot.create :seed, owner: member, crop: seed_crop }
|
||||
let!(:seed_photo) { FactoryBot.create :photo, owner: member }
|
||||
|
||||
@@ -180,14 +197,70 @@ describe Photo do
|
||||
harvest.photos << harvest_photo
|
||||
planting.photos << planting_photo
|
||||
seed.photos << seed_photo
|
||||
|
||||
# harvest_photo.reload
|
||||
# harvest.reload
|
||||
# # harvest.reindex
|
||||
|
||||
# planting_photo.reload
|
||||
# planting.reload
|
||||
# # planting.reindex
|
||||
|
||||
# seed_photo.reload
|
||||
# seed.reload
|
||||
# seed.reindex
|
||||
end
|
||||
|
||||
it { expect(Photo.by_model(Harvest)).to eq([harvest_photo]) }
|
||||
it { expect(Photo.by_model(Planting)).to eq([planting_photo]) }
|
||||
it { expect(Photo.by_model(Seed)).to eq([seed_photo]) }
|
||||
describe 'relationships' do
|
||||
it { expect(seed_photo.crops).to eq [seed_crop] }
|
||||
it { expect(seed_crop.photos).to eq [seed_photo] }
|
||||
|
||||
it { expect(Photo.by_crop(harvest_crop)).to eq([harvest_photo]) }
|
||||
it { expect(Photo.by_crop(planting_crop)).to eq([planting_photo]) }
|
||||
it { expect(Photo.by_crop(seed_crop)).to eq([seed_photo]) }
|
||||
it { expect(harvest_photo.crops).to eq [harvest_crop] }
|
||||
it { expect(harvest_crop.photos).to eq [harvest_photo] }
|
||||
|
||||
it { expect(planting_photo.crops).to eq [planting_crop] }
|
||||
it { expect(planting_crop.photos).to eq [planting_photo] }
|
||||
end
|
||||
|
||||
describe 'scopes' do
|
||||
it { expect(Photo.by_model(Harvest)).to eq([harvest_photo]) }
|
||||
it { expect(Photo.by_model(Planting)).to eq([planting_photo]) }
|
||||
it { expect(Photo.by_model(Seed)).to eq([seed_photo]) }
|
||||
|
||||
it { expect(Photo.by_crop(harvest_crop)).to eq([harvest_photo]) }
|
||||
it { expect(Photo.by_crop(planting_crop)).to eq([planting_photo]) }
|
||||
it { expect(Photo.by_crop(seed_crop)).to eq([seed_photo]) }
|
||||
end
|
||||
end
|
||||
|
||||
describe 'Elastic search indexing', search: true do
|
||||
let!(:planting) { FactoryBot.create(:planting, :reindex, owner: photo.owner) }
|
||||
let!(:crop) { FactoryBot.create :crop, :reindex }
|
||||
|
||||
before do
|
||||
planting.photos << photo
|
||||
Photo.reindex
|
||||
Photo.searchkick_index.refresh
|
||||
end
|
||||
|
||||
describe "finds all photos in search index" do
|
||||
it "finds just one" do
|
||||
expect(Photo.search.count).to eq 1
|
||||
end
|
||||
it "finds the matching photo" do
|
||||
expect(Photo.search).to include photo
|
||||
end
|
||||
|
||||
it "retrieves crops from ES" do
|
||||
expect(Photo.search(load: false).first.crops).to eq [planting.crop.id]
|
||||
end
|
||||
end
|
||||
|
||||
it "finds photos by owner in search index" do
|
||||
expect(Photo.search(where: { owner_id: planting.owner_id })).to include photo
|
||||
end
|
||||
it "finds photos by crop in search index" do
|
||||
expect(Photo.search(where: { crops: planting.crop.id })).to include photo
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -179,8 +179,8 @@ describe Planting do
|
||||
|
||||
before do
|
||||
FactoryBot.create(:harvest,
|
||||
planting: planting,
|
||||
crop: planting.crop,
|
||||
planting: planting,
|
||||
crop: planting.crop,
|
||||
harvested_at: 10.days.ago)
|
||||
planting.update_harvest_days!
|
||||
planting.crop.update_harvest_medians
|
||||
@@ -232,8 +232,11 @@ describe Planting do
|
||||
before do
|
||||
# Near by planting with harvests
|
||||
nearby_garden = FactoryBot.create :garden, location: 'Greenwich, UK'
|
||||
nearby_planting = FactoryBot.create :planting, crop: crop,
|
||||
garden: nearby_garden, owner: nearby_garden.owner, planted_at: '1 January 2000'
|
||||
nearby_planting = FactoryBot.create(:planting,
|
||||
crop: crop,
|
||||
garden: nearby_garden,
|
||||
owner: nearby_garden.owner,
|
||||
planted_at: '1 January 2000')
|
||||
FactoryBot.create :harvest, planting: nearby_planting, crop: crop,
|
||||
harvested_at: '1 May 2019'
|
||||
FactoryBot.create :harvest, planting: nearby_planting, crop: crop,
|
||||
@@ -354,9 +357,11 @@ describe Planting do
|
||||
end
|
||||
|
||||
it 'all valid planted_from values should work' do
|
||||
['seed', 'seedling', 'cutting', 'root division',
|
||||
'runner', 'bare root plant', 'advanced plant',
|
||||
'graft', 'layering', 'bulb', 'root/tuber', nil, ''].each do |p|
|
||||
[
|
||||
'seed', 'seedling', 'cutting', 'root division',
|
||||
'runner', 'bare root plant', 'advanced plant',
|
||||
'graft', 'layering', 'bulb', 'root/tuber', nil, ''
|
||||
].each do |p|
|
||||
@planting = FactoryBot.build(:planting, planted_from: p)
|
||||
@planting.should be_valid
|
||||
end
|
||||
@@ -407,16 +412,10 @@ describe Planting do
|
||||
before do
|
||||
# plantings have members created implicitly for them
|
||||
# each member is different, hence these are all interesting
|
||||
@planting1 = FactoryBot.create(:planting, planted_at: 5.days.ago)
|
||||
@planting2 = FactoryBot.create(:planting, planted_at: 4.days.ago)
|
||||
@planting3 = FactoryBot.create(:planting, planted_at: 3.days.ago)
|
||||
@planting4 = FactoryBot.create(:planting, planted_at: 2.days.ago)
|
||||
|
||||
# plantings need photos to be interesting
|
||||
[@planting1, @planting2, @planting3, @planting4].each do |p|
|
||||
p.photos << FactoryBot.create(:photo, owner_id: p.owner_id)
|
||||
p.save
|
||||
end
|
||||
@planting1 = FactoryBot.create(:planting, :with_photo, planted_at: 5.days.ago)
|
||||
@planting2 = FactoryBot.create(:planting, :with_photo, planted_at: 4.days.ago)
|
||||
@planting3 = FactoryBot.create(:planting, :with_photo, planted_at: 3.days.ago)
|
||||
@planting4 = FactoryBot.create(:planting, :with_photo, planted_at: 2.days.ago)
|
||||
end
|
||||
|
||||
it { expect(Planting.interesting).to eq([@planting4, @planting3, @planting2, @planting1]) }
|
||||
@@ -445,8 +444,8 @@ describe Planting do
|
||||
# this one is newer, and has the same owner, through the garden
|
||||
@planting2 = FactoryBot.create(:planting,
|
||||
created_at: 1.minute.ago,
|
||||
garden: @planting1.garden,
|
||||
owner: @planting1.owner)
|
||||
garden: @planting1.garden,
|
||||
owner: @planting1.owner)
|
||||
@planting2.photos << FactoryBot.create(:photo, owner: @planting2.owner)
|
||||
@planting2.save
|
||||
|
||||
@@ -541,4 +540,16 @@ describe Planting do
|
||||
it { expect(member.plantings.active).to include(planting) }
|
||||
it { expect(member.plantings.active).not_to include(finished_planting) }
|
||||
end
|
||||
|
||||
describe 'homepage', :search do
|
||||
let!(:interesting_planting) { FactoryBot.create :planting, :reindex, :with_photo }
|
||||
let!(:finished_interesting_planting) { FactoryBot.create :finished_planting, :reindex, :with_photo }
|
||||
let!(:planting) { FactoryBot.create :planting, :reindex }
|
||||
|
||||
before { Planting.reindex }
|
||||
subject { Planting.homepage_records(100) }
|
||||
|
||||
it { expect(subject.count).to eq 2 }
|
||||
it { expect(subject.map(&:id)).to eq([interesting_planting.id.to_s, finished_interesting_planting.id.to_s]) }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -63,23 +63,23 @@ describe Seed do
|
||||
@seed.should_not be_valid
|
||||
end
|
||||
|
||||
it 'tradable? gives the right answers' do
|
||||
it 'tradable gives the right answers' do
|
||||
@seed = FactoryBot.create(:seed, tradable_to: 'nowhere')
|
||||
@seed.tradable?.should eq false
|
||||
@seed.tradable.should eq false
|
||||
@seed = FactoryBot.create(:seed, tradable_to: 'locally')
|
||||
@seed.tradable?.should eq true
|
||||
@seed.tradable.should eq true
|
||||
@seed = FactoryBot.create(:seed, tradable_to: 'nationally')
|
||||
@seed.tradable?.should eq true
|
||||
@seed.tradable.should eq true
|
||||
@seed = FactoryBot.create(:seed, tradable_to: 'internationally')
|
||||
@seed.tradable?.should eq true
|
||||
@seed.tradable.should eq true
|
||||
end
|
||||
|
||||
it 'recognises a tradable seed' do
|
||||
FactoryBot.create(:tradable_seed).tradable?.should == true
|
||||
FactoryBot.create(:tradable_seed).tradable.should == true
|
||||
end
|
||||
|
||||
it 'recognises an untradable seed' do
|
||||
FactoryBot.create(:untradable_seed).tradable?.should == false
|
||||
FactoryBot.create(:untradable_seed).tradable.should == false
|
||||
end
|
||||
|
||||
it 'scopes correctly' do
|
||||
@@ -197,4 +197,16 @@ describe Seed do
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'homepage', :search do
|
||||
let!(:tradable_seed) { FactoryBot.create :tradable_seed, :reindex, finished: false }
|
||||
let!(:finished_seed) { FactoryBot.create :tradable_seed, :reindex, finished: true }
|
||||
let!(:untradable_seed) { FactoryBot.create :untradable_seed, :reindex }
|
||||
|
||||
before { Seed.reindex }
|
||||
subject { Seed.homepage_records(100) }
|
||||
|
||||
it { expect(subject.count).to eq 1 }
|
||||
it { expect(subject.first.id).to eq tradable_seed.id.to_s }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -59,8 +59,8 @@ include Warden::Test::Helpers
|
||||
# directory. Alternatively, in the individual `*_spec.rb` files, manually
|
||||
# require only the support files necessary.
|
||||
#
|
||||
Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
|
||||
Dir[Rails.root.join("spec/features/shared_examples/**/*.rb")].each { |f| require f }
|
||||
Dir[Rails.root.join("spec/support/**/*.rb")].sort.each { |f| require f }
|
||||
Dir[Rails.root.join("spec/features/shared_examples/**/*.rb")].sort.each { |f| require f }
|
||||
|
||||
# Checks for pending migrations before tests are run.
|
||||
# If you are not using ActiveRecord, you can remove this line.
|
||||
|
||||
@@ -5,9 +5,8 @@ require 'rails_helper'
|
||||
describe "Harvests" do
|
||||
describe "GET /harvests" do
|
||||
it "works! (now write some real specs)" do
|
||||
# Run the generator again with the --webrat flag if you want to use webrat methods/matchers
|
||||
get harvests_path
|
||||
response.status.should be(200)
|
||||
expect(response.status).to be 200
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -20,6 +20,7 @@ require 'simplecov'
|
||||
require 'percy'
|
||||
|
||||
SimpleCov.start
|
||||
|
||||
RSpec.configure do |config|
|
||||
# rspec-expectations config goes here. You can use an alternate
|
||||
# assertion/expectation library such as wrong or the stdlib/minitest
|
||||
@@ -36,9 +37,17 @@ RSpec.configure do |config|
|
||||
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
||||
end
|
||||
|
||||
config.before(:suite) do
|
||||
def index_everything
|
||||
# reindex models
|
||||
Crop.reindex
|
||||
Harvest.reindex
|
||||
Photo.reindex
|
||||
Planting.reindex
|
||||
Seed.reindex
|
||||
end
|
||||
|
||||
config.before(:suite) do
|
||||
index_everything
|
||||
|
||||
# and disable callbacks
|
||||
Searchkick.disable_callbacks
|
||||
@@ -46,7 +55,9 @@ RSpec.configure do |config|
|
||||
|
||||
config.around(:each, search: true) do |example|
|
||||
Searchkick.callbacks(true) do
|
||||
index_everything
|
||||
example.run
|
||||
index_everything
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -10,8 +10,8 @@ describe "forums/show" do
|
||||
|
||||
it "renders attributes" do
|
||||
render
|
||||
rendered.should have_content "Everything about permaculture"
|
||||
rendered.should have_content @forum.owner.to_s
|
||||
expect(rendered).to have_content "Everything about permaculture"
|
||||
expect(rendered).to have_content @forum.owner.to_s
|
||||
end
|
||||
|
||||
it "parses markdown description into html" do
|
||||
@@ -26,14 +26,14 @@ describe "forums/show" do
|
||||
|
||||
it 'has no posts' do
|
||||
render
|
||||
rendered.should have_content "No posts yet."
|
||||
expect(rendered).to have_content "No posts yet."
|
||||
end
|
||||
|
||||
it 'shows posts' do
|
||||
@post = FactoryBot.create(:post, forum: @forum)
|
||||
render
|
||||
assert_select "table"
|
||||
rendered.should have_content @post.subject
|
||||
rendered.should have_content @post.author.to_s
|
||||
expect(rendered).to have_content @post.subject
|
||||
expect(rendered).to have_content @post.author.to_s
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,43 +2,38 @@
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe 'harvests/index.rss.haml' do
|
||||
describe 'harvests/index.rss.haml', :search do
|
||||
before do
|
||||
controller.stub(:current_user) { nil }
|
||||
@member = FactoryBot.create(:member)
|
||||
@tomato = FactoryBot.create(:tomato)
|
||||
@maize = FactoryBot.create(:maize)
|
||||
@pp = FactoryBot.create(:plant_part)
|
||||
page = 1
|
||||
per_page = 2
|
||||
total_entries = 2
|
||||
harvests = WillPaginate::Collection.create(page, per_page, total_entries) do |pager|
|
||||
pager.replace([
|
||||
FactoryBot.create(:harvest,
|
||||
crop: @tomato,
|
||||
owner: @member),
|
||||
FactoryBot.create(:harvest,
|
||||
crop: @maize,
|
||||
plant_part: @pp,
|
||||
owner: @member,
|
||||
quantity: 2)
|
||||
])
|
||||
|
||||
@harvest1 = FactoryBot.create :harvest, crop: @tomato
|
||||
@harvest2 = FactoryBot.create :harvest, crop: @tomato
|
||||
@harvest3 = FactoryBot.create :harvest, crop: @tomato
|
||||
|
||||
Harvest.searchkick_index.refresh
|
||||
assign(:harvests, Harvest.search(load: false))
|
||||
end
|
||||
|
||||
context 'all harvests' do
|
||||
before { render }
|
||||
it 'shows RSS feed title' do
|
||||
expect(rendered).to have_content "Recent harvests from all members"
|
||||
end
|
||||
|
||||
it 'shows formatted content of harvest posts' do
|
||||
expect(rendered).to have_content "<p>Quantity: "
|
||||
end
|
||||
assign(:harvests, harvests)
|
||||
render
|
||||
end
|
||||
|
||||
it 'shows RSS feed title' do
|
||||
rendered.should have_content "Recent harvests from all members"
|
||||
end
|
||||
|
||||
it "displays crop's name in title" do
|
||||
assign(:crop, @tomato)
|
||||
render
|
||||
expect(rendered).to have_content @tomato.name
|
||||
end
|
||||
|
||||
it 'shows formatted content of harvest posts' do
|
||||
expect(rendered).to have_content "<p>Quantity: "
|
||||
context 'for one crop' do
|
||||
before do
|
||||
assign(:crop, @tomato)
|
||||
render
|
||||
end
|
||||
it "displays crop's name in title" do
|
||||
expect(rendered).to have_content @tomato.name
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,10 +2,13 @@
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe 'home/_seeds.html.haml', type: "view" do
|
||||
describe 'home/_seeds.html.haml', type: "view", search: true do
|
||||
let!(:seed) { FactoryBot.create(:tradable_seed, owner: owner) }
|
||||
let(:owner) { FactoryBot.create(:london_member) }
|
||||
before { render }
|
||||
before do
|
||||
Seed.searchkick_index.refresh
|
||||
render
|
||||
end
|
||||
|
||||
it 'has a heading' do
|
||||
assert_select 'h2', 'Seeds available to trade'
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user