Merge branch 'dev' into awesomecode-style/andor-8234

This commit is contained in:
Brenda Wallace
2018-02-11 08:50:50 +13:00
committed by GitHub
380 changed files with 2834 additions and 5658 deletions

View File

@@ -1,6 +1,6 @@
# This configuration was generated by
# `rubocop --auto-gen-config --no-offense-counts`
# on 2017-12-06 11:20:15 +1300 using RuboCop version 0.49.1.
# on 2018-02-05 14:37:22 +1300 using RuboCop version 0.49.1.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
@@ -39,7 +39,6 @@ Rails/SkipsModelValidations:
# SupportedStyles: strict, flexible
Rails/TimeZone:
Exclude:
- 'spec/controllers/accounts_controller_spec.rb'
- 'spec/factories/member.rb'
- 'spec/factories/post.rb'
- 'spec/models/post_spec.rb'
@@ -60,7 +59,6 @@ Style/AsciiComments:
# SupportedStyles: nested, compact
Style/ClassAndModuleChildren:
Exclude:
- 'app/controllers/admin/orders_controller.rb'
- 'lib/actions/oauth_signup_action.rb'
- 'lib/haml/filters/escaped_markdown.rb'
@@ -68,24 +66,11 @@ Style/IdenticalConditionalBranches:
Exclude:
- 'app/controllers/follows_controller.rb'
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles.
# SupportedStyles: line_count_dependent, lambda, literal
Style/Lambda:
Exclude:
- 'spec/controllers/member_controller_spec.rb'
- 'spec/models/photo_spec.rb'
# Cop supports --auto-correct.
Style/MultilineIfModifier:
Exclude:
- 'spec/rails_helper.rb'
# Cop supports --auto-correct.
Style/MutableConstant:
Exclude:
- 'app/models/planting.rb'
# Cop supports --auto-correct.
# Configuration parameters: AutoCorrect, EnforcedStyle, SupportedStyles.
# SupportedStyles: predicate, comparison
@@ -96,11 +81,6 @@ Style/NumericPredicate:
- 'app/helpers/plantings_helper.rb'
- 'lib/tasks/growstuff.rake'
# Cop supports --auto-correct.
Style/ParallelAssignment:
Exclude:
- 'app/mailers/notifier.rb'
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles, AllowInnerSlashes.
# SupportedStyles: slashes, percent_r, mixed

14
Gemfile
View File

@@ -48,7 +48,6 @@ gem 'bootstrap-kaminari-views' # bootstrap views for kaminari
gem 'kaminari' # pagination
gem 'active_utils'
gem 'activemerchant'
gem 'sidekiq'
# Markdown formatting for updates etc
@@ -78,7 +77,7 @@ gem 'omniauth-facebook'
gem 'omniauth-flickr', '>= 0.0.15'
gem 'omniauth-twitter'
gem 'chartkick'
gem "chartkick"
# client for Elasticsearch. Elasticsearch is a flexible
# and powerful, distributed, real-time search and analytics engine.
@@ -87,15 +86,15 @@ gem 'chartkick'
# Project does not use semver, so we want to be in sync with the version of
# elasticsearch we use
# See https://github.com/elastic/elasticsearch-ruby#compatibility
gem 'elasticsearch-api', '~> 2.0.0'
gem 'elasticsearch-model'
gem 'elasticsearch-rails'
gem 'hashie', '>= 3.5.3'
gem "elasticsearch-api", "~> 2.0.0"
gem "elasticsearch-model"
gem "elasticsearch-rails"
gem "hashie", ">= 3.5.3"
gem 'rake', '>= 10.0.0'
# locale based flash notices for controllers
gem 'responders'
gem "responders"
# allows soft delete. Used for members.
gem 'acts_as_paranoid', '~> 0.5.0'
@@ -125,7 +124,6 @@ group :development do
end
group :development, :test do
gem 'active_merchant-paypal-bogus-gateway'
gem 'bullet' # performance tuning by finding unnecesary queries
gem 'byebug' # debugging
gem 'capybara' # integration tests

View File

@@ -26,19 +26,12 @@ GEM
addressable
active_median (0.1.4)
activerecord
active_merchant-paypal-bogus-gateway (0.1.0)
activemerchant
active_utils (3.3.9)
activesupport (>= 3.2, < 5.2.0)
i18n
activejob (4.2.10)
activesupport (= 4.2.10)
globalid (>= 0.3.0)
activemerchant (1.77.0)
activesupport (>= 3.2.14, < 6.x)
builder (>= 2.1.2, < 4.0.0)
i18n (>= 0.6.9)
nokogiri (~> 1.4)
activemodel (4.2.10)
activesupport (= 4.2.10)
builder (~> 3.1)
@@ -549,9 +542,7 @@ PLATFORMS
DEPENDENCIES
active_median
active_merchant-paypal-bogus-gateway
active_utils
activemerchant
acts_as_paranoid (~> 0.5.0)
better_errors (~> 2.2.0)
binding_of_caller
@@ -636,7 +627,6 @@ DEPENDENCIES
will_paginate
xmlrpc
RUBY VERSION
ruby 2.4.1p111

View File

@@ -3,11 +3,11 @@ guard :rspec,
failed_mode: :keep do
watch(%r{^spec/.+_spec\.rb$})
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/libs/#{m[1]}_spec.rb" }
watch('spec/spec_helper.rb') { 'spec' }
watch('spec/spec_helper.rb') { "spec" }
# Rails example
watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
watch(%r{^app/(.*)(\.erb|\.haml|\.slim)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
watch(%r{^spec/support/(.+)\.rb$}) { 'spec' }
watch('config/routes.rb') { 'spec/routing' }
watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
watch('config/routes.rb') { "spec/routing" }
end

View File

@@ -1,53 +0,0 @@
class AccountTypesController < ApplicationController
before_action :authenticate_member!
load_and_authorize_resource
respond_to :html
# GET /account_types
def index
@account_types = AccountType.all.order(:name)
respond_with(@account_types)
end
# GET /account_types/1
def show
respond_with(@account_types)
end
# GET /account_types/new
def new
@account_type = AccountType.new
respond_with(@account_type)
end
# GET /account_types/1/edit
def edit
respond_with(@account_type)
end
# POST /account_types
def create
@account_type = AccountType.new(account_type_params)
flash[:notice] = I18n.t('account_types.created') if @account_type.save
respond_with(@account_type)
end
# PUT /account_types/1
def update
flash[:notice] = I18n.t('account_types.updated') if @account_type.update(account_type_params)
respond_with(@account_type)
end
# DELETE /account_types/1
def destroy
@account_type.destroy
flash[:notice] = I18n.t('account_types.deleted')
respond_with(@account_type)
end
private
def account_type_params
params.require(:account_type).permit(:is_paid, :is_permanent_paid, :name)
end
end

View File

@@ -1,31 +0,0 @@
class AccountsController < ApplicationController
before_action :authenticate_member!
load_and_authorize_resource
respond_to :html
# GET /accounts
def index
@accounts = Account.all.order(created_at: :desc)
respond_with(@accounts)
end
# GET /accounts/1
def show
respond_with(@account)
end
# GET /accounts/1/edit
def edit; end
# PUT /accounts/1
def update
flash[:notice] = I18n.t('account.update') if @account.update(params[:account])
respond_with(@account)
end
private
def account_params
params.require(:account).permit(:account_type_id, :member_id, :paid_until)
end
end

View File

@@ -1,23 +0,0 @@
module Admin
class OrdersController < ApplicationController
def index
authorize! :manage, :all
respond_to do |format|
format.html # index.html.haml
end
end
def search
authorize! :manage, :all
@orders = Order.search(by: params[:search_by], for: params[:search_text])
if @orders.empty?
flash[:alert] = "Couldn't find order with #{params[:search_by]} = #{params[:search_text]}"
end
respond_to do |format|
format.html # index.html.haml
end
end
end
end

View File

@@ -30,7 +30,7 @@ class AlternateNamesController < ApplicationController
if @alternate_name.save
redirect_to @alternate_name.crop, notice: 'Alternate name was successfully created.'
else
render action: 'new'
render action: "new"
end
end
@@ -40,7 +40,7 @@ class AlternateNamesController < ApplicationController
if @alternate_name.update(alternate_name_params)
redirect_to @alternate_name.crop, notice: 'Alternate name was successfully updated.'
else
render action: 'edit'
render action: "edit"
end
end

View File

@@ -7,12 +7,12 @@ class ApplicationController < ActionController::Base
before_action :set_locale
def store_location
unless request.path.in?(['/members/sign_in',
'/members/sign_up',
'/members/password/new',
'/members/password/edit',
'/members/confirmation',
'/members/sign_out']) || request.xhr?
unless request.path.in?(["/members/sign_in",
"/members/sign_up",
"/members/password/new",
"/members/password/edit",
"/members/confirmation",
"/members/sign_out"]) || request.xhr?
store_location_for(:member, request.fullpath)
end
end
@@ -77,6 +77,6 @@ class ApplicationController < ActionController::Base
end
def expire_homepage
expire_fragment('homepage_stats')
expire_fragment("homepage_stats")
end
end

View File

@@ -22,9 +22,9 @@ class AuthenticationsController < ApplicationController
name: name
)
flash[:notice] = 'Authentication successful.'
flash[:notice] = "Authentication successful."
else
flash[:notice] = 'Authentication failed.'
flash[:notice] = "Authentication failed."
end
redirect_to request.env['omniauth.origin'] || edit_member_registration_path
end

View File

@@ -14,7 +14,7 @@ module Charts
@crop = Crop.find(params[:crop_id])
render json: Harvest.joins(:plant_part)
.where(crop: @crop)
.group('plant_parts.name').count(:id)
.group("plant_parts.name").count(:id)
end
private

View File

@@ -23,9 +23,9 @@ class CropsController < ApplicationController
def wrangle
@approval_status = params[:approval_status]
@crops = case @approval_status
when 'pending'
when "pending"
Crop.pending_approval
when 'rejected'
when "rejected"
Crop.rejected
else
Crop.recent
@@ -78,7 +78,7 @@ class CropsController < ApplicationController
@crop.creator = current_member
else
@crop.requester = current_member
@crop.approval_status = 'pending'
@crop.approval_status = "pending"
end
notify_wranglers if Crop.transaction { @crop.save && save_crop_names }
@@ -89,13 +89,13 @@ class CropsController < ApplicationController
def update
previous_status = @crop.approval_status
@crop.creator = current_member if previous_status == 'pending'
@crop.creator = current_member if previous_status == "pending"
if @crop.update(crop_params)
recreate_names('alt_name', 'alternate')
recreate_names('sci_name', 'scientific')
notifier.deliver_now! if previous_status == 'pending'
notifier.deliver_now! if previous_status == "pending"
end
respond_with @crop
@@ -110,9 +110,9 @@ class CropsController < ApplicationController
def notifier
case @crop.approval_status
when 'approved'
when "approved"
Notifier.crop_request_approved(@crop.requester, @crop)
when 'rejected'
when "rejected"
Notifier.crop_request_rejected(@crop.requester, @crop)
end
end
@@ -185,7 +185,7 @@ class CropsController < ApplicationController
def crops
q = Crop.approved.includes(:scientific_names, plantings: :photos)
q = q.popular unless @sort == 'alpha'
q.order('LOWER(crops.name)').includes(:photos).paginate(page: params[:page])
q.order("LOWER(crops.name)").includes(:photos).paginate(page: params[:page])
end
def requested_crops

View File

@@ -11,7 +11,7 @@ class FollowsController < ApplicationController
flash[:notice] = "Followed #{@follow.followed.login_name}"
redirect_to :back
else
flash[:error] = 'Already following or error while following.'
flash[:error] = "Already following or error while following."
redirect_to :back
end
end

View File

@@ -26,7 +26,7 @@ class LikesController < ApplicationController
{
id: like.likeable.id,
liked_by_member: liked_by_member,
description: ActionController::Base.helpers.pluralize(like.likeable.likes.count, 'like'),
description: ActionController::Base.helpers.pluralize(like.likeable.likes.count, "like"),
url: like_path(like, format: :json)
}
end

View File

@@ -49,8 +49,8 @@ class MembersController < ApplicationController
end
EMAIL_TYPE_STRING = {
send_notification_email: 'direct message notifications',
send_planting_reminder: 'planting reminders'
send_notification_email: "direct message notifications",
send_planting_reminder: "planting reminders"
}.freeze
def unsubscribe

View File

@@ -21,7 +21,7 @@ class NotificationsController < ApplicationController
def new
@notification = Notification.new
@recipient = Member.find_by(id: params[:recipient_id])
@subject = params[:subject] || ''
@subject = params[:subject] || ""
end
# GET /notifications/1/reply
@@ -53,7 +53,7 @@ class NotificationsController < ApplicationController
if @notification.save
redirect_to notifications_path, notice: 'Message was successfully sent.'
else
render action: 'new'
render action: "new"
end
end

View File

@@ -12,8 +12,8 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
end
def failure
flash[:alert] = 'Authentication failed.'
redirect_to request.env['omniauth.origin'] || '/'
flash[:alert] = "Authentication failed."
redirect_to request.env['omniauth.origin'] || "/"
end
private
@@ -30,9 +30,9 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
@authentication = action.establish_authentication(auth, member)
if action.member_created?
raise 'Invalid provider' unless %w(facebook twitter flickr).index(auth['provider'].to_s)
raise "Invalid provider" unless %w(facebook twitter flickr).index(auth['provider'].to_s)
session["devise.#{auth['provider']}_data"] = request.env['omniauth.auth']
session["devise.#{auth['provider']}_data"] = request.env["omniauth.auth"]
sign_in member
redirect_to finish_signup_url(member)
else

View File

@@ -1,36 +0,0 @@
class OrderItemsController < ApplicationController
before_action :authenticate_member!
load_and_authorize_resource
respond_to :html
responders :flash
# POST /order_items
def create
if params[:order_item][:price]
params[:order_item][:price] = params[:order_item][:price].to_f * 100 # convert to cents
end
@order_item = OrderItem.new(order_item_params)
@order_item.order = current_member.current_order || Order.create(member_id: current_member.id)
if @order_item.save
redirect_to @order_item.order, notice: 'Added item to your order.'
else
redirect_to shop_path, alert: errors
end
end
private
def errors
if @order_item.errors.empty?
'There was a problem with your order.'
else
@order_item.errors.full_messages.to_sentence
end
end
def order_item_params
params.require(:order_item).permit(:order_id, :price, :product_id, :quantity)
end
end

View File

@@ -1,90 +0,0 @@
class OrdersController < ApplicationController
before_action :authenticate_member!
load_and_authorize_resource
# GET /orders
def index
@orders = Order.by_member(current_member)
respond_to do |format|
format.html # index.html.erb
end
end
# GET /orders/1
def show
respond_to do |format|
format.html # show.html.erb
end
end
# GET /orders/new
def new
@order = Order.new
respond_to do |format|
format.html # new.html.erb
end
end
# checkout with PayPal
def checkout
respond_to do |format|
if @order.update_attributes(referral_code: params[:referral_code])
response = EXPRESS_GATEWAY.setup_purchase(
@order.total,
items: @order.activemerchant_items,
currency: Growstuff::Application.config.currency,
no_shipping: true,
ip: request.remote_ip,
return_url: complete_order_url,
cancel_return_url: shop_url
)
format.html { redirect_to EXPRESS_GATEWAY.redirect_url_for(response.token) }
else
format.html { render action: 'show' }
end
end
end
def complete
if params[:token] && params['PayerID']
purchase = EXPRESS_GATEWAY.purchase(
@order.total,
currency: Growstuff::Application.config.currency,
ip: request.remote_ip,
payer_id: params['PayerID'],
token: params[:token]
)
if purchase.success?
@order.completed_at = Time.zone.now
@order.record_paypal_details(params[:token])
else
flash[:alert] = 'Could not complete your order. Please notify support.'
end
else
flash[:alert] = "PayPal didn't return a token or payer_id for your order. Please notify support."
end
@order.update_account # apply paid account benefits, etc.
respond_to do |format|
format.html # new.html.erb
end
end
def cancel
respond_to do |format|
format.html { redirect_to shop_url, notice: 'Order was cancelled.' }
end
end
# DELETE /orders/1
def destroy
@order.destroy
respond_to do |format|
format.html { redirect_to shop_url, notice: 'Order was deleted.' }
end
end
end

View File

@@ -1,6 +1,6 @@
class PagesController < ApplicationController
def letsencrypt
# use your code here, not mine
render text: 'y9KNck8wqkoQLnlr2RgA2TVwWtyYb4PeY_hzGNx0Tfs.dlIPqFhMDCLyQEccczY3roHZ1UWu6UqVeyb9mkRxheU'
render text: "y9KNck8wqkoQLnlr2RgA2TVwWtyYb4PeY_hzGNx0Tfs.dlIPqFhMDCLyQEccczY3roHZ1UWu6UqVeyb9mkRxheU"
end
end

View File

@@ -3,7 +3,7 @@ class PhotoAssociationsController < ApplicationController
respond_to :json, :html
def destroy
raise 'Photos not supported' unless Photo::PHOTO_CAPABLE.include? item_class
raise "Photos not supported" unless Photo::PHOTO_CAPABLE.include? item_class
@photo = Photo.find_by!(id: params[:photo_id], owner: current_member)
@item = Photographing.item(item_id, item_class)
@item.photos.delete(@photo)

View File

@@ -75,10 +75,10 @@ class PhotosController < ApplicationController
# Item with photos attached
def item_to_link_to
raise 'No item id provided' if item_id.nil?
raise 'No item type provided' if item_type.nil?
raise "No item id provided" if item_id.nil?
raise "No item type provided" if item_type.nil?
item_class = item_type.capitalize
raise 'Photos not supported' unless Photo::PHOTO_CAPABLE.include? item_class
raise "Photos not supported" unless Photo::PHOTO_CAPABLE.include? item_class
item_class.constantize.find_by!(id: params[:id], owner_id: current_member.id)
end

View File

@@ -1,46 +0,0 @@
class ProductsController < ApplicationController
before_action :authenticate_member!
load_and_authorize_resource
respond_to :html
responders :flash
def index
@products = Product.all.order(:name)
respond_with @products
end
def show
respond_with @product
end
def new
@product = Product.new
respond_with @product
end
def edit
respond_with @product
end
def create
@product = Product.create(product_params)
respond_with @product
end
def update
@product.update(product_params)
respond_with @product
end
def destroy
@product.destroy
respond_with @product
end
private
def product_params
params.require(:product).permit(:description, :min_price, :recommended_price, :name,
:account_type_id, :paid_months)
end
end

View File

@@ -5,7 +5,7 @@ class RegistrationsController < Devise::RegistrationsController
@twitter_auth = current_member.auth('twitter')
@flickr_auth = current_member.auth('flickr')
@facebook_auth = current_member.auth('facebook')
render 'edit'
render "edit"
end
# we need this subclassed method so that Devise doesn't force people to
@@ -32,7 +32,7 @@ class RegistrationsController < Devise::RegistrationsController
sign_in @member, bypass: true
redirect_to edit_member_registration_path
else
render 'edit'
render "edit"
end
end
@@ -40,7 +40,7 @@ class RegistrationsController < Devise::RegistrationsController
if @member.destroy_with_password(params.require(:member)[:current_password])
redirect_to root_path
else
render 'edit'
render "edit"
end
end
end

View File

@@ -4,7 +4,7 @@ class SessionsController < Devise::SessionsController
def create
super do |_resource|
if Crop.pending_approval.present? && current_member.role?(:crop_wrangler)
flash[:alert] = 'There are crops waiting to be wrangled.'
flash[:alert] = "There are crops waiting to be wrangled."
end
end
end

View File

@@ -1,19 +0,0 @@
class ShopController < ApplicationController
respond_to :html
def index
@products = Product.all
@order_item = OrderItem.new
# this is (hopefully) part of a short-term hack to prevent people from
# ordering multiple subscriptions, which would be very confusing to deal
# with. We check whether they have an order already in progress, and if
# so, point that out to them and encourage them to checkout, rather than
# letting them add more stuff to their order.
@order = nil
@most_recent_item = nil
return unless current_member
@order = current_member.current_order
@most_recent_item = @order.order_items.first if @order
end
end

View File

@@ -18,7 +18,7 @@ module ApplicationHelper
currency = Growstuff::Application.config.currency
link = "http://www.wolframalpha.com/input/?i=#{pid}+#{currency}"
link_to '(convert)', link, target: '_blank', rel: 'noopener noreferrer'
link_to "(convert)", link, target: "_blank", rel: "noopener noreferrer"
end
def build_alert_classes(alert_type = :info)
@@ -37,7 +37,7 @@ module ApplicationHelper
end
# Produces a cache key for uniquely identifying cached fragments.
def cache_key_for(klass, identifier = 'all')
def cache_key_for(klass, identifier = "all")
count = klass.count
max_updated_at = klass.maximum(:updated_at).try(:utc).try(:to_s, :number)
"#{klass.name.downcase.pluralize}/#{identifier}-#{count}-#{max_updated_at}"
@@ -102,7 +102,7 @@ module ApplicationHelper
elsif planting
t(".title.planting_#{type}", planting: planting.to_s)
else
t('.title.default')
t(".title.default")
end
end

View File

@@ -13,7 +13,7 @@ module CropsHelper
if total_quantity != 0
"You have #{total_quantity} #{Seed.model_name.human(count: total_quantity)} of this crop."
else
'You have an unknown quantity of seeds of this crop.'
"You have an unknown quantity of seeds of this crop."
end
end

View File

@@ -1,10 +1,10 @@
module GardensHelper
def display_garden_description(garden)
if garden.description.nil?
'no description provided.'
"no description provided."
else
truncate(garden.description, length: 130, separator: ' ', omission: '... ') do
link_to 'Read more', garden_path(garden)
link_to "Read more", garden_path(garden)
end
end
end
@@ -19,12 +19,12 @@ module GardensHelper
def display_garden_plantings(plantings)
if plantings.blank?
'None'
"None"
else
output = '<ul class="plantings">'
plantings.each do |planting|
output += '<li>'
output += planting.quantity.nil? ? '0 ' : "#{planting.quantity} "
output += "<li>"
output += planting.quantity.nil? ? "0 " : "#{planting.quantity} "
output += link_to planting.crop.name, planting.crop
output += ", planted on #{planting.planted_at}</li>"
end

View File

@@ -28,7 +28,7 @@ module HarvestsHelper
end
def display_harvest_description(harvest)
return 'No description provided.' if harvest.description.nil?
return "No description provided." if harvest.description.nil?
harvest.description
end
end

View File

@@ -3,18 +3,18 @@ module PlantingsHelper
if planting.finished_at.present?
planting.finished_at
elsif planting.finished
'Yes (no date specified)'
"Yes (no date specified)"
else
'(no date specified)'
"(no date specified)"
end
end
def display_planted_from(planting)
planting.planted_from.present? ? planting.planted_from : 'not specified'
planting.planted_from.present? ? planting.planted_from : "not specified"
end
def display_planting_quantity(planting)
planting.quantity.present? ? planting.quantity : 'not specified'
planting.quantity.present? ? planting.quantity : "not specified"
end
def display_planting(planting)

View File

@@ -1,9 +1,9 @@
module SeedsHelper
def display_seed_description(seed)
if seed.description.nil?
'no description provided.'
"no description provided."
else
truncate(seed.description, length: 130, separator: ' ', omission: '... ') { link_to 'Read more', seed_path(seed) }
truncate(seed.description, length: 130, separator: ' ', omission: '... ') { link_to "Read more", seed_path(seed) }
end
end
end

View File

@@ -1,11 +1,11 @@
class Notifier < ActionMailer::Base
include NotificationsHelper
default from: 'Growstuff <noreply@growstuff.org>'
default from: "Growstuff <noreply@growstuff.org>"
def verifier
unless ENV['RAILS_SECRET_TOKEN']
raise 'RAILS_SECRET_TOKEN environment variable'\
'not set - have you created config/application.yml?'
raise "RAILS_SECRET_TOKEN environment variable"\
"not set - have you created config/application.yml?"
end
ActiveSupport::MessageVerifier.new(ENV['RAILS_SECRET_TOKEN'])
@@ -33,7 +33,7 @@ class Notifier < ActionMailer::Base
message = { member_id: @member.id, type: :send_planting_reminder }
@signed_message = verifier.generate(message)
mail(to: @member.email, subject: 'What have you planted lately?') if @member.send_planting_reminder
mail(to: @member.email, subject: "What have you planted lately?") if @member.send_planting_reminder
end
def new_crop_request(member, request)

View File

@@ -24,19 +24,14 @@ class Ability
# except these, which don't make sense if you're not logged in
cannot :read, Notification
cannot :read, Authentication
cannot :read, Order
cannot :read, OrderItem
# and nobody should be able to view this except admins
cannot :read, Role
cannot :read, Product
cannot :read, Account
cannot :read, AccountType
# nobody should be able to view unapproved crops unless they
# are wranglers or admins
cannot :read, Crop
can :read, Crop, approval_status: 'approved'
can :read, Crop, approval_status: "approved"
# scientific names should only be viewable if associated crop is approved
cannot :read, ScientificName
can :read, ScientificName do |sn|
@@ -120,20 +115,6 @@ class Ability
can :update, Seed, owner_id: member.id
can :destroy, Seed, owner_id: member.id
# orders/shop/etc
can :create, Order
can :read, Order, member_id: member.id
can :complete, Order, member_id: member.id, completed_at: nil
can :checkout, Order, member_id: member.id, completed_at: nil
can :cancel, Order, member_id: member.id, completed_at: nil
can :destroy, Order, member_id: member.id, completed_at: nil
can :create, OrderItem
# for now, let's not let people mess with individual order items
cannot :read, OrderItem, order: { member_id: member.id }
cannot :update, OrderItem, order: { member_id: member.id, completed_at: nil }
cannot :destroy, OrderItem, order: { member_id: member.id, completed_at: nil }
# following/unfollowing permissions
can :create, Follow
cannot :create, Follow, followed_id: member.id # can't follow yourself
@@ -148,12 +129,6 @@ class Ability
can :read, :all
can :manage, :all
# can't change order history, because it's *history*
cannot :create, Order
cannot :complete, Order
cannot :destroy, Order
cannot :manage, OrderItem
# can't delete plant parts if they have harvests associated with them
cannot :destroy, PlantPart
can :destroy, PlantPart do |pp|

View File

@@ -1,23 +0,0 @@
class Account < ActiveRecord::Base
belongs_to :member
belongs_to :account_type
validates :member_id, uniqueness: {
message: 'already has account details associated with it'
}
before_create do |account|
unless account.account_type
account.account_type = AccountType.find_or_create_by(name:
Growstuff::Application.config.default_account_type)
end
end
def paid_until_string
if account_type.is_permanent_paid
'forever'
elsif account_type.is_paid
paid_until.to_s
end
end
end

View File

@@ -1,13 +0,0 @@
class AccountType < ActiveRecord::Base
#
# Relationships
has_many :products
#
# Validations
validates :name, presence: true, uniqueness: true
def to_s
name
end
end

View File

@@ -1,5 +1,5 @@
class AlternateName < ActiveRecord::Base
after_commit { |an| an.crop.__elasticsearch__.index_document if an.crop && ENV['GROWSTUFF_ELASTICSEARCH'] == 'true' }
after_commit { |an| an.crop.__elasticsearch__.index_document if an.crop && ENV['GROWSTUFF_ELASTICSEARCH'] == "true" }
belongs_to :crop
belongs_to :creator, class_name: 'Member'
validates :name, presence: true

View File

@@ -2,7 +2,7 @@ class Comment < ActiveRecord::Base
belongs_to :author, class_name: 'Member'
belongs_to :post
scope :post_order, -> { reorder('created_at ASC') } # for display on post page
scope :post_order, -> { reorder("created_at ASC") } # for display on post page
after_create do
recipient = post.author.id

View File

@@ -15,7 +15,7 @@ class Crop < ActiveRecord::Base
has_many :photos, through: :plantings
has_many :seeds
has_many :harvests
has_many :plant_parts, -> { uniq.reorder('plant_parts.name') }, through: :harvests
has_many :plant_parts, -> { uniq.reorder("plant_parts.name") }, through: :harvests
belongs_to :creator, class_name: 'Member'
belongs_to :requester, class_name: 'Member'
belongs_to :parent, class_name: 'Crop'
@@ -26,12 +26,12 @@ class Crop < ActiveRecord::Base
## Scopes
scope :recent, -> { approved.order(created_at: :desc) }
scope :toplevel, -> { approved.where(parent_id: nil) }
scope :popular, -> { approved.reorder('plantings_count desc, lower(name) asc') }
scope :popular, -> { approved.reorder("plantings_count desc, lower(name) asc") }
# ok on sqlite and psql, but not on mysql
scope :randomized, -> { approved.reorder('random()') }
scope :pending_approval, -> { where(approval_status: 'pending') }
scope :approved, -> { where(approval_status: 'approved') }
scope :rejected, -> { where(approval_status: 'rejected') }
scope :pending_approval, -> { where(approval_status: "pending") }
scope :approved, -> { where(approval_status: "approved") }
scope :rejected, -> { where(approval_status: "rejected") }
scope :interesting, -> { approved.has_photos.randomized }
scope :has_photos, -> { includes(:photos).where.not(photos: { id: nil }) }
@@ -53,17 +53,17 @@ class Crop < ActiveRecord::Base
####################################
# Elastic search configuration
if ENV['GROWSTUFF_ELASTICSEARCH'] == 'true'
if ENV["GROWSTUFF_ELASTICSEARCH"] == "true"
include Elasticsearch::Model
include Elasticsearch::Model::Callbacks
# In order to avoid clashing between different environments,
# use Rails.env as a part of index name (eg. development_growstuff)
index_name [Rails.env, 'growstuff'].join('_')
index_name [Rails.env, "growstuff"].join('_')
settings index: { number_of_shards: 1 },
analysis: {
tokenizer: {
gs_edgeNGram_tokenizer: {
type: 'edgeNGram', # edgeNGram: NGram match from the start of a token
type: "edgeNGram", # edgeNGram: NGram match from the start of a token
min_gram: 3,
max_gram: 10,
# token_chars: Elasticsearch will split on characters
@@ -73,8 +73,8 @@ class Crop < ActiveRecord::Base
},
analyzer: {
gs_edgeNGram_analyzer: {
tokenizer: 'gs_edgeNGram_tokenizer',
filter: ['lowercase']
tokenizer: "gs_edgeNGram_tokenizer",
filter: ["lowercase"]
}
}
} do
@@ -104,7 +104,7 @@ class Crop < ActiveRecord::Base
# update the Elasticsearch index (only if we're using it in this
# environment)
def update_index(_name_obj)
__elasticsearch__.index_document if ENV['GROWSTUFF_ELASTICSEARCH'] == 'true'
__elasticsearch__.index_document if ENV["GROWSTUFF_ELASTICSEARCH"] == "true"
end
# End Elasticsearch section
@@ -148,10 +148,10 @@ class Crop < ActiveRecord::Base
# value: count of how many times it's been used by harvests
def popular_plant_parts
PlantPart.joins(:harvests)
.where('crop_id = ?', id)
.order('count_harvests_id DESC')
.group('plant_parts.id', 'plant_parts.name')
.count('harvests.id')
.where("crop_id = ?", id)
.order("count_harvests_id DESC")
.group("plant_parts.id", "plant_parts.name")
.count("harvests.id")
end
def annual?
@@ -167,15 +167,15 @@ class Crop < ActiveRecord::Base
end
def pending?
approval_status == 'pending'
approval_status == "pending"
end
def approved?
approval_status == 'approved'
approval_status == "approved"
end
def rejected?
approval_status == 'rejected'
approval_status == "rejected"
end
def approval_statuses
@@ -183,11 +183,11 @@ class Crop < ActiveRecord::Base
end
def reasons_for_rejection
['already in database', 'not edible', 'not enough information', 'other']
["already in database", "not edible", "not enough information", "other"]
end
def rejection_explanation
return rejection_notes if reason_for_rejection == 'other'
return rejection_notes if reason_for_rejection == "other"
reason_for_rejection
end
@@ -212,7 +212,7 @@ class Crop < ActiveRecord::Base
end
def self.case_insensitive_name(name)
where(['lower(crops.name) = :value', { value: name.downcase }])
where(["lower(crops.name) = :value", { value: name.downcase }])
end
private
@@ -235,11 +235,11 @@ class Crop < ActiveRecord::Base
def must_be_rejected_if_rejected_reasons_present
return if rejected?
return unless reason_for_rejection.present? || rejection_notes.present?
errors.add(:approval_status, 'must be rejected if a reason for rejection is present')
errors.add(:approval_status, "must be rejected if a reason for rejection is present")
end
def must_have_meaningful_reason_for_rejection
return unless reason_for_rejection == 'other' && rejection_notes.blank?
errors.add(:rejection_notes, 'must be added if the reason for rejection is "other"')
return unless reason_for_rejection == "other" && rejection_notes.blank?
errors.add(:rejection_notes, "must be added if the reason for rejection is \"other\"")
end
end

View File

@@ -65,6 +65,6 @@ class CsvImporter
@cropbot ||= Member.find_by!(login_name: 'cropbot')
@cropbot
rescue StandardError
raise 'cropbot account not found: run rake db:seed'
raise "cropbot account not found: run rake db:seed"
end
end

View File

@@ -1,6 +1,6 @@
class Follow < ActiveRecord::Base
belongs_to :follower, class_name: 'Member'
belongs_to :followed, class_name: 'Member'
belongs_to :follower, class_name: "Member"
belongs_to :followed, class_name: "Member"
validates :follower_id, uniqueness: { scope: :followed_id }
after_create do

View File

@@ -4,7 +4,7 @@ class Forum < ActiveRecord::Base
friendly_id :name, use: %i(slugged finders)
has_many :posts
belongs_to :owner, class_name: 'Member'
belongs_to :owner, class_name: "Member"
def to_s
name

View File

@@ -35,13 +35,13 @@ class Garden < ActiveRecord::Base
allow_nil: true
AREA_UNITS_VALUES = {
'square metres' => 'square metre',
'square feet' => 'square foot',
'hectares' => 'hectare',
'acres' => 'acre'
"square metres" => "square metre",
"square feet" => "square foot",
"hectares" => "hectare",
"acres" => "acre"
}.freeze
validates :area_unit, inclusion: { in: AREA_UNITS_VALUES.values,
message: '%<value>s is not a valid area unit' },
message: "%<value>s is not a valid area unit" },
allow_nil: true,
allow_blank: true

View File

@@ -7,22 +7,22 @@ class Harvest < ActiveRecord::Base
# Constants
UNITS_VALUES = {
'individual' => 'individual',
'bunches' => 'bunch',
'sprigs' => 'sprig',
'handfuls' => 'handful',
'litres' => 'litre',
'pints' => 'pint',
'quarts' => 'quart',
'buckets' => 'bucket',
'baskets' => 'basket',
'bushels' => 'bushel'
"individual" => "individual",
"bunches" => "bunch",
"sprigs" => "sprig",
"handfuls" => "handful",
"litres" => "litre",
"pints" => "pint",
"quarts" => "quart",
"buckets" => "bucket",
"baskets" => "basket",
"bushels" => "bushel"
}.freeze
WEIGHT_UNITS_VALUES = {
'kg' => 'kg',
'lb' => 'lb',
'oz' => 'oz'
"kg" => "kg",
"lb" => "lb",
"oz" => "oz"
}.freeze
##
@@ -44,18 +44,18 @@ class Harvest < ActiveRecord::Base
##
## Validations
validates :crop, approved: true
validates :crop, presence: { message: 'must be present and exist in our database' }
validates :plant_part, presence: { message: 'must be present and exist in our database' }
validates :crop, presence: { message: "must be present and exist in our database" }
validates :plant_part, presence: { message: "must be present and exist in our database" }
validates :harvested_at, presence: true
validates :quantity, allow_nil: true, numericality: {
only_integer: false, greater_than_or_equal_to: 0
}
validates :unit, allow_nil: true, allow_blank: true, inclusion: {
in: UNITS_VALUES.values, message: '%<value>s is not a valid unit'
in: UNITS_VALUES.values, message: "%<value>s is not a valid unit"
}
validates :weight_quantity, allow_nil: true, numericality: { only_integer: false }
validates :weight_unit, allow_nil: true, allow_blank: true, inclusion: {
in: WEIGHT_UNITS_VALUES.values, message: '%<value>s is not a valid unit'
in: WEIGHT_UNITS_VALUES.values, message: "%<value>s is not a valid unit"
}
validate :crop_must_match_planting
validate :owner_must_match_planting
@@ -71,7 +71,7 @@ class Harvest < ActiveRecord::Base
def set_si_weight
return if weight_unit.nil?
weight_string = "#{weight_quantity} #{weight_unit}"
self.si_weight = Unit.new(weight_string).convert_to('kg').to_s('%0.3f').delete(' kg').to_f
self.si_weight = Unit.new(weight_string).convert_to("kg").to_s("%0.3f").delete(" kg").to_f
end
def cleanup_quantities
@@ -94,11 +94,11 @@ class Harvest < ActiveRecord::Base
def quantity_to_human
return number_to_human(quantity.to_s, strip_insignificant_zeros: true) if quantity
''
""
end
def unit_to_human
return '' unless quantity
return "" unless quantity
if unit == 'individual'
'individual'
elsif quantity == 1
@@ -109,7 +109,7 @@ class Harvest < ActiveRecord::Base
end
def weight_to_human
return '' unless weight_quantity
return "" unless weight_quantity
"weighing #{number_to_human(weight_quantity, strip_insignificant_zeros: true)} #{weight_unit}"
end
@@ -131,17 +131,17 @@ class Harvest < ActiveRecord::Base
def crop_must_match_planting
return if planting.blank? # only check if we are linked to a planting
errors.add(:planting, 'must be the same crop') unless crop == planting.crop
errors.add(:planting, "must be the same crop") unless crop == planting.crop
end
def owner_must_match_planting
return if planting.blank? # only check if we are linked to a planting
errors.add(:owner, 'of harvest must be the same as planting') unless owner == planting.owner
errors.add(:owner, "of harvest must be the same as planting") unless owner == planting.owner
end
def harvest_must_be_after_planting
# only check if we are linked to a planting
return unless harvested_at.present? && planting.present? && planting.planted_at.present?
errors.add(:planting, 'cannot be harvested before planting') unless harvested_at > planting.planted_at
errors.add(:planting, "cannot be harvested before planting") unless harvested_at > planting.planted_at
end
end

View File

@@ -7,7 +7,7 @@ class Member < ActiveRecord::Base
friendly_id :login_name, use: %i(slugged finders)
#
# Relationshops
# Relationships
has_many :posts, foreign_key: 'author_id'
has_many :comments, foreign_key: 'author_id'
has_many :forums, foreign_key: 'owner_id'
@@ -19,14 +19,11 @@ class Member < ActiveRecord::Base
has_many :notifications, foreign_key: 'recipient_id'
has_many :sent_notifications, foreign_key: 'sender_id'
has_many :authentications
has_many :orders
has_one :account
has_one :account_type, through: :account
has_many :photos
has_many :requested_crops, class_name: Crop, foreign_key: 'requester_id'
has_many :likes, dependent: :destroy
has_many :follows, class_name: 'Follow', foreign_key: 'follower_id', dependent: :destroy
has_many :inverse_follows, class_name: 'Follow', foreign_key: 'followed_id', dependent: :destroy
has_many :follows, class_name: "Follow", foreign_key: "follower_id", dependent: :destroy
has_many :inverse_follows, class_name: "Follow", foreign_key: "followed_id", dependent: :destroy
has_many :followed, through: :follows
has_many :followers, through: :inverse_follows, source: :follower
@@ -38,7 +35,7 @@ class Member < ActiveRecord::Base
scope :recently_joined, -> { reorder(confirmed_at: :desc) }
scope :wants_newsletter, -> { where(newsletter: true) }
scope :interesting, -> { confirmed.located.recently_signed_in.has_plantings }
scope :has_plantings, -> { joins(:plantings).group('members.id') }
scope :has_plantings, -> { joins(:plantings).group("members.id") }
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
@@ -60,13 +57,13 @@ class Member < ActiveRecord::Base
validates :tos_agreement, acceptance: { allow_nil: true, accept: true }
validates :login_name,
length: {
minimum: 2, maximum: 25, message: 'should be between 2 and 25 characters long'
minimum: 2, maximum: 25, message: "should be between 2 and 25 characters long"
},
exclusion: {
in: %w(growstuff admin moderator staff nearby), message: 'name is reserved'
in: %w(growstuff admin moderator staff nearby), message: "name is reserved"
},
format: {
with: /\A\w+\z/, message: 'may only include letters, numbers, or underscores'
with: /\A\w+\z/, message: "may only include letters, numbers, or underscores"
},
uniqueness: {
case_sensitive: false
@@ -79,11 +76,9 @@ class Member < ActiveRecord::Base
after_save :update_newsletter_subscription
# Give each new member a default garden
# and an account record (for paid accounts etc)
# we use find_or_create to avoid accidentally creating a second one,
# which can happen sometimes especially with FactoryBot associations
after_create { |member| Garden.create(name: 'Garden', owner_id: member.id) }
after_create { |member| Account.find_or_create_by(member_id: member.id) }
after_create { |member| Garden.create(name: "Garden", owner_id: member.id) }
# allow login via either login_name or email address
def self.find_first_by_auth_conditions(warden_conditions)
@@ -98,35 +93,7 @@ class Member < ActiveRecord::Base
end
def role?(role_sym)
roles.any? { |r| r.name.gsub(/\s+/, '_').underscore.to_sym == role_sym }
end
def current_order
orders.find_by(completed_at: nil)
end
# when purchasing a product that gives you a paid account, this method
# does all the messing around to actually make sure the account is
# updated correctly -- account type, paid until, etc. Usually this is
# called by order.update_account, which loops through all order items
# and does this for each one.
def update_account_after_purchase(product)
account.account_type = product.account_type if product.account_type
if product.paid_months
start_date = account.paid_until || Time.zone.now
account.paid_until = start_date + product.paid_months.months
end
account.save
end
def paid?
if account.account_type.is_permanent_paid
true
elsif account.account_type.is_paid && account.paid_until >= Time.zone.now
true
else
false
end
roles.any? { |r| r.name.gsub(/\s+/, "_").underscore.to_sym == role_sym }
end
def auth(provider)
@@ -179,11 +146,11 @@ class Member < ActiveRecord::Base
end
def self.login_name_or_email(login)
where(['lower(login_name) = :value OR lower(email) = :value', { value: login.downcase }])
where(["lower(login_name) = :value OR lower(email) = :value", { value: login.downcase }])
end
def self.case_insensitive_login_name(login)
where(['lower(login_name) = :value', { value: login.downcase }])
where(["lower(login_name) = :value", { value: login.downcase }])
end
def self.nearest_to(place)

View File

@@ -16,7 +16,7 @@ class Notification < ActiveRecord::Base
end
def replace_blank_subject
self.subject = '(no subject)' if subject.nil? || subject =~ /^\s*$/
self.subject = "(no subject)" if subject.nil? || subject =~ /^\s*$/
end
def send_email

View File

@@ -1,90 +0,0 @@
class Order < ActiveRecord::Base
#
# Relationships
belongs_to :member, with_deleted: true
has_many :order_items, dependent: :destroy
#
# Validations
validates :referral_code, format: {
with: /\A[a-zA-Z0-9 ]*\z/,
message: 'may only include letters and numbers'
}
#
# Teiggers
before_save :standardize_referral_code
#
# Scopes
scope :by_member, ->(member) { where(member: member) }
# total price of an order
def total
sum = 0
order_items.each do |i|
subtotal = i.price * i.quantity
sum += subtotal
end
sum
end
# return items in the format ActiveMerchant/PayPal want them
def activemerchant_items
items = []
order_items.each do |i|
items.push(name: i.product.name,
quantity: i.quantity,
amount: i.price)
end
items
end
# record the paypal details for reference
def record_paypal_details(token)
self.paypal_express_token = token
details = EXPRESS_GATEWAY.details_for(token)
self.paypal_express_payer_id = details.payer_id
save
end
# when an order is completed, we update the member's account to mark
# them as paid, or whatever, based on what products they ordered
def update_account
order_items.each do |i|
member.update_account_after_purchase(i.product)
end
end
# removes whitespace and forces to uppercase (we're somewhat liberal
# in what we accept, but we clean it up anyway.)
def standardize_referral_code
self.referral_code = referral_code.upcase.gsub(/\s/, '') if referral_code
end
# search orders (used by admin/orders)
# usage: Order.search({ :by => 'member', :for => 'Skud' })
# can search by: member, order_id, paypal_token, paypal_payer_id,
def self.search(args = {})
if args[:for]
case args[:by]
when 'member'
member = Member.with_deleted.find_by(login_name: args[:for])
return member.orders if member
when 'order_id'
order = Order.find_by(id: args[:for])
return [order] if order
when 'paypal_token'
order = Order.find_by(paypal_express_token: args[:for])
return [order] if order
when 'paypal_payer_id'
order = Order.find_by(paypal_express_payer_id: args[:for])
return [order] if order
when 'referral_code'
# coerce to uppercase
return Order.where(referral_code: args[:for].upcase)
end
end
[]
end
end

View File

@@ -1,12 +0,0 @@
class OrderItem < ActiveRecord::Base
belongs_to :order
belongs_to :product
validate :price_must_be_greater_than_minimum
validates :order_id, uniqueness: { message: 'may only have one item.' }
def price_must_be_greater_than_minimum
@product = Product.find(product_id)
errors.add(:price, "must be greater than the product's minimum value") if price < @product.min_price
end
end

View File

@@ -30,7 +30,7 @@ class Planting < ActiveRecord::Base
scope :one_per_owner, lambda {
joins("JOIN members m ON (m.id=plantings.owner_id)
LEFT OUTER JOIN plantings p2
ON (m.id=p2.owner_id AND plantings.id < p2.id)").where('p2 IS NULL')
ON (m.id=p2.owner_id AND plantings.id < p2.id)").where("p2 IS NULL")
}
##
@@ -41,17 +41,17 @@ class Planting < ActiveRecord::Base
##
## Validations
validates :garden, presence: true
validates :crop, presence: true, approved: { message: 'must be present and exist in our database' }
validates :crop, presence: true, approved: { message: "must be present and exist in our database" }
validate :finished_must_be_after_planted
validate :owner_must_match_garden_owner
validates :quantity, allow_nil: true, numericality: {
only_integer: true, greater_than_or_equal_to: 0
}
validates :sunniness, allow_nil: true, allow_blank: true, inclusion: {
in: SUNNINESS_VALUES, message: '%<value>s is not a valid sunniness value'
in: SUNNINESS_VALUES, message: "%<value>s is not a valid sunniness value"
}
validates :planted_from, allow_nil: true, allow_blank: true, inclusion: {
in: PLANTED_FROM_VALUES, message: '%<value>s is not a valid planting method'
in: PLANTED_FROM_VALUES, message: "%<value>s is not a valid planting method"
}
def planting_slug
@@ -64,7 +64,7 @@ class Planting < ActiveRecord::Base
# location = garden owner + garden name, i.e. "Skud's backyard"
def location
I18n.t('gardens.location', garden: garden.name, owner: garden.owner.login_name)
I18n.t("gardens.location", garden: garden.name, owner: garden.owner.login_name)
end
# stringify as "beet in Skud's backyard" or similar
@@ -134,10 +134,10 @@ class Planting < ActiveRecord::Base
# check that any finished_at date occurs after planted_at
def finished_must_be_after_planted
return unless planted_at && finished_at # only check if we have both
errors.add(:finished_at, 'must be after the planting date') unless planted_at < finished_at
errors.add(:finished_at, "must be after the planting date") unless planted_at < finished_at
end
def owner_must_match_garden_owner
errors.add(:owner, 'must be the same as garden') unless owner == garden.owner
errors.add(:owner, "must be the same as garden") unless owner == garden.owner
end
end

View File

@@ -1,15 +0,0 @@
class Product < ActiveRecord::Base
#
# Relationships
belongs_to :account_type
has_and_belongs_to_many :orders # rubocop:disable Rails/HasAndBelongsToMany
#
# Validations
validates :paid_months, allow_nil: true, numericality: { only_integer: true, greater_than_or_equal_to: 0 }
validates :min_price, presence: true
def to_s
name
end
end

View File

@@ -1,5 +1,5 @@
class ScientificName < ActiveRecord::Base
after_commit { |sn| sn.crop.__elasticsearch__.index_document if sn.crop && ENV['GROWSTUFF_ELASTICSEARCH'] == 'true' }
after_commit { |sn| sn.crop.__elasticsearch__.index_document if sn.crop && ENV['GROWSTUFF_ELASTICSEARCH'] == "true" }
belongs_to :crop
belongs_to :creator, class_name: 'Member'
validates :name, presence: true

View File

@@ -16,7 +16,7 @@ class Seed < ActiveRecord::Base
#
# Validations
validates :crop, approved: true
validates :crop, presence: { message: 'must be present and exist in our database' }
validates :crop, presence: { message: "must be present and exist in our database" }
validates :quantity, allow_nil: true,
numericality: { only_integer: true, greater_than_or_equal_to: 0 }
validates :days_until_maturity_min, allow_nil: true,
@@ -24,17 +24,17 @@ class Seed < ActiveRecord::Base
validates :days_until_maturity_max, allow_nil: true,
numericality: { only_integer: true, greater_than_or_equal_to: 0 }
validates :tradable_to, allow_nil: false, allow_blank: false,
inclusion: { in: TRADABLE_TO_VALUES, message: 'You may only trade seed nowhere, '\
'locally, nationally, or internationally' }
inclusion: { in: TRADABLE_TO_VALUES, message: "You may only trade seed nowhere, "\
"locally, nationally, or internationally" }
validates :organic, allow_nil: false, allow_blank: false,
inclusion: { in: ORGANIC_VALUES, message: 'You must say whether the seeds '\
inclusion: { in: ORGANIC_VALUES, message: "You must say whether the seeds "\
"are organic or not, or that you don't know" }
validates :gmo, allow_nil: false, allow_blank: false,
inclusion: { in: GMO_VALUES, message: 'You must say whether the seeds are '\
inclusion: { in: GMO_VALUES, message: "You must say whether the seeds are "\
"genetically modified or not, or that you don't know" }
validates :heirloom, allow_nil: false, allow_blank: false,
inclusion: { in: HEIRLOOM_VALUES, message: 'You must say whether the seeds'\
'are heirloom, hybrid, or unknown' }
inclusion: { in: HEIRLOOM_VALUES, message: "You must say whether the seeds"\
"are heirloom, hybrid, or unknown" }
#
# Delegations

View File

@@ -1,21 +1,21 @@
class CropSearchService
# Crop.search(string)
def self.search(query)
if ENV['GROWSTUFF_ELASTICSEARCH'] == 'true'
search_str = query.nil? ? '' : query.downcase
if ENV['GROWSTUFF_ELASTICSEARCH'] == "true"
search_str = query.nil? ? "" : query.downcase
response = Crop.__elasticsearch__.search( # Finds documents which match any field, but uses the _score from
# the best field insead of adding up _score from each field.
query: {
multi_match: {
query: search_str.to_s,
analyzer: 'standard',
fields: ['name',
'scientific_names.scientific_name',
'alternate_names.name']
analyzer: "standard",
fields: ["name",
"scientific_names.scientific_name",
"alternate_names.name"]
}
},
filter: {
term: { approval_status: 'approved' }
term: { approval_status: "approved" }
},
size: 50
)
@@ -26,7 +26,7 @@ class CropSearchService
# collection, so it matches what we get from elasticsearch and we can
# manipulate it in the same ways (eg. deleting elements without deleting
# the whole record from the db)
matches = Crop.approved.where('name ILIKE ?', "%#{query}%").to_a
matches = Crop.approved.where("name ILIKE ?", "%#{query}%").to_a
# we want to make sure that exact matches come first, even if not
# using elasticsearch (eg. in development)

View File

@@ -1,21 +0,0 @@
= form_for @account_type do |f|
- if @account_type.errors.any?
#error_explanation
%h2
= pluralize(@account_type.errors.size, "error")
prohibited this account_type from being saved:
%ul
- @account_type.errors.full_messages.each do |msg|
%li= msg
.field
= f.label :name
= f.text_field :name
.field
= f.label :is_paid
= f.check_box :is_paid
.field
= f.label :is_permanent_paid
= f.check_box :is_permanent_paid
.actions
= f.submit 'Save'

View File

@@ -1,7 +0,0 @@
- content_for :title, "Editing account type"
= render 'form'
= link_to 'Show', @account_type
\|
= link_to 'Back', account_types_path

View File

@@ -1,23 +0,0 @@
- content_for :title, "Listing account types"
%table
%tr
%th Name
%th Is paid
%th Is permanent paid
%th
%th
%th
- @account_types.each do |account_type|
%tr
%td= account_type.name
%td= account_type.is_paid
%td= account_type.is_permanent_paid
%td= link_to 'Show', account_type
%td= link_to 'Edit', edit_account_type_path(account_type)
%td= link_to 'Destroy', account_type, method: :delete, data: { confirm: 'Are you sure?' }
%br
= link_to 'New Account type', new_account_type_path

View File

@@ -1,5 +0,0 @@
- content_for :title, "New account type"
= render 'form'
= link_to 'Back', account_types_path

View File

@@ -1,17 +0,0 @@
%p#notice= notice
%p
%b Name:
= @account_type.name
%p
%b Is paid:
= @account_type.is_paid
%p
%b Is permanent paid:
= @account_type.is_permanent_paid
= link_to 'Edit', edit_account_type_path(@account_type)
\|
= link_to 'Delete', @account_type, method: :delete, data: { confirm: 'Are you sure?' }
\|
= link_to 'Back', account_types_path

View File

@@ -1,21 +0,0 @@
= form_for @account do |f|
- if @account.errors.any?
#error_explanation
%h2
= pluralize(@account.errors.size, "error")
prohibited this account from being saved:
%ul
- @account.errors.full_messages.each do |msg|
%li= msg
.field
= f.label :member_id
= f.number_field :member_id
.field
= f.label :account_type
= f.text_field :account_type
.field
= f.label :paid_until
= f.datetime_select :paid_until
.actions
= f.submit 'Save'

View File

@@ -1,7 +0,0 @@
- content_for :title, "Editing account"
= render 'form'
= link_to 'Show', @account
\|
= link_to 'Back', accounts_path

View File

@@ -1,23 +0,0 @@
- content_for :title, "Listing accounts"
%table
%tr
%th Member
%th Account type
%th Paid until
%th
%th
%th
- @accounts.each do |account|
%tr
%td= account.member_id
%td= account.account_type
%td= account.paid_until
%td= link_to 'Show', account
%td= link_to 'Edit', edit_account_path(account)
%td= link_to 'Destroy', account, method: :delete, data: { confirm: 'Are you sure?' }
%br
= link_to 'New Account detail', new_account_path

View File

@@ -1,5 +0,0 @@
- content_for :title, "New account"
= render 'form'
= link_to 'Back', accounts_path

View File

@@ -1,15 +0,0 @@
%p#notice= notice
%p
%b Member:
= @account.member_id
%p
%b Account type:
= @account.account_type.name
%p
%b Paid until:
= @account.paid_until
= link_to 'Edit', edit_account_path(@account)
\|
= link_to 'Back', accounts_path

View File

@@ -6,8 +6,6 @@
.col-md-4
%h2 Site admin
%ul#site_admin
%li= link_to "Account types", account_types_path
%li= link_to "Products", products_path
%li= link_to "Roles", roles_path
%li= link_to "Forums", forums_path
%li= link_to "CMS", comfy_admin_cms_path
@@ -22,8 +20,3 @@
%ul
%li= link_to "Newsletter subscribers", admin_newsletter_path
%li= link_to "Members", admin_members_path
.row
.col-md-12
%h2 Orders
= render "admin/orders/searchform"

View File

@@ -1,8 +0,0 @@
= form_tag(url_for(controller: 'admin/orders', action: 'search'), method: :get, class: 'form-inline') do
= label_tag :distance, "Search orders:", class: 'control-label'
= text_field_tag :search_text
= select_tag :search_by,
options_for_select('Member': 'member', 'Referral code': 'referral_code',
'Order ID': 'order_id', 'Paypal Token': 'paypal_token',
'Paypal Payer ID': 'paypal_payer_id')
= submit_tag "Search", class: 'btn btn-primary'

View File

@@ -1,3 +0,0 @@
- content_for :title, 'Admin Orders'
= render "admin/orders/searchform"

View File

@@ -1,41 +0,0 @@
- content_for :title, 'Search Orders'
= render "admin/orders/searchform"
- unless @orders.empty?
%h2
Found
= pluralize(@orders.size, "result")
%table.table.table-striped
%tr
%th Member
%th Order number
%th Date completed
%th Referral code
%th Items
%th
- @orders.each do |order|
%tr
%td
= link_to order.member.login_name, order.member
= "(deleted)" if order.member.deleted_at
%td= order.id
%td
- if order.completed_at
= order.completed_at.to_s
- else
In progress
%td
= order.referral_code
%td
- unless order.order_items.empty?
- order.order_items.each do |o|
= o.quantity
x
= o.product.name
@
= price_with_currency(o.price)
%br/
%td= link_to 'Details', order, class: 'btn btn-default btn-xs'

View File

@@ -47,7 +47,6 @@
%li= link_to t('.browse_members'), members_path
%li= link_to t('.posts'), posts_path
%li= link_to t('.forums'), forums_path
%li= link_to t('.support_growstuff'), shop_path
- if member_signed_in?
%li.dropdown<
@@ -64,7 +63,6 @@
%li= link_to t('.harvest'), harvests_by_owner_path(owner: current_member.slug)
%li= link_to t('.seeds'), seeds_by_owner_path(owner: current_member.slug)
%li= link_to t('.posts'), posts_by_author_path(author: current_member.slug)
%li= link_to t('.account'), orders_path
%li
- if current_member.notifications.unread_count.positive?
= link_to(t('.inbox_unread', unread_count: current_member.notifications.unread_count),

View File

@@ -1,24 +0,0 @@
%h3 Account details
%p
%strong Member since:
= member.created_at.to_s(:date)
%p
%strong Account type:
= member.account_type
account
%p
%strong Last Login:
= member.last_sign_in_at
%p
%strong Member Roles:
%br
- if member.role? :admin
Administrator
- if member.role? :crop_wrangler
Crop Wrangler
- else
Member

View File

@@ -0,0 +1,9 @@
%p
%strong Member Roles:
%br
- if member.role? :admin
Administrator
- if member.role? :crop_wrangler
Crop Wrangler
- unless (member.role?(:admin) || member.role?(:crop_wrangler))
Member

View File

@@ -1,3 +1,10 @@
%p
%strong Member since:
= member.created_at.to_s(:date)
%p
%strong Last Login:
= member.last_sign_in_at
%h3 Activity
%ul.list-inline
@@ -33,4 +40,3 @@
= link_to pluralize(member.followers.size, "follower"), member_followers_path(member)
- else
0 followers

View File

@@ -10,8 +10,6 @@
- content_for :buttonbar do
- if can? :update, @member
= link_to 'Edit profile', edit_member_registration_path, class: 'btn btn-default'
- if @member == current_member && !@member.paid?
= link_to "Upgrade account", shop_path, class: 'btn btn-default'
- if can?(:create, Notification) && current_member != @member
= link_to 'Send message', new_notification_path(recipient_id: @member.id), class: 'btn btn-default'
@@ -33,7 +31,7 @@
= render partial: "gardens", locals: { member: @member, gardens: @gardens }
.col-md-3
= render partial: "avatar", locals: { member: @member }
= render partial: "account", locals: { member: @member }
= render partial: "roles", locals: { member: @member }
= render partial: "stats", locals: { member: @member }
= render partial: "contact", locals: { member: @member,
twitter_auth: @twitter_auth,

View File

@@ -1,45 +0,0 @@
- content_for :title, "Completed order"
%p Thank you for your order.
%p
%strong Completed at:
= @order.completed_at
%p
%strong Order number:
= @order.id
= render "shared/account_status"
%h2 Order items
%table.table.table-striped
%tr
%th Product
%th Price
%th Quantity
%th Subtotal
- total = 0
- @order.order_items.each do |i|
%tr
%td= i.product.name
%td
= price_with_currency(i.price)
%td= i.quantity
%td
- subtotal = i.price * i.quantity
- total += subtotal
= price_with_currency(subtotal)
%tr
%td
%td
%td
%strong Total:
%td
%strong
= price_with_currency(total)
%p
= link_to "View other orders/order history", orders_path

View File

@@ -1,44 +0,0 @@
- content_for :title, "Your Account"
= render "shared/account_status"
%h2 Orders
- if current_member.orders.present?
%p
Your order history shows what you have bought via our
= succeed "." do
= link_to "shop", shop_path
%table.table.table-striped
%tr
%th Order number
%th Date completed
%th Items
%th
- @orders.each do |order|
%tr
%td= order.id
%td
- if order.completed_at
= order.completed_at.to_s
- else
In progress
%td
- unless order.order_items.empty?
- order.order_items.each do |o|
= o.quantity
x
= o.product.name
@
= price_with_currency(o.price)
%br/
%td= link_to 'Details', order, class: 'btn btn-default btn-xs'
- else
%p
You have not made any orders. You can place an order via our
= succeed "." do
= link_to "shop", shop_path

View File

@@ -1,84 +0,0 @@
- content_for :title, @order.completed_at ? "Order details (##{@order.id})" : "Current order"
%p
%strong Order number:
= @order.id
%p
%strong Ordered by:
= link_to @order.member, @order.member
%p
%strong Date begun:
= @order.created_at.to_s
- if @order.completed_at
%p
%strong Date completed:
= @order.completed_at.to_s
- if @order.referral_code
%p
%strong Referral code:
= @order.referral_code
- if current_member.role? :admin
%p
%strong Paypal Express token:
= @order.paypal_express_token
%p
%strong Paypal Express payer ID:
= @order.paypal_express_payer_id
%h2 Order items
%table.table.table-striped
%tr
%th Product
%th Price
%th Quantity
%th Subtotal
- @order.order_items.each do |i|
%tr
%td= i.product.name
%td
= price_with_currency(i.price)
%td= i.quantity
%td
- subtotal = i.price * i.quantity
= price_with_currency(subtotal)
%tr
%td
%td
%td
%strong Total:
%td
%strong
= price_with_currency(@order.total)
= forex_link(@order.total)
- if @order.errors.any?
.alert
#error_explanation
%h3
= pluralize(@order.errors.size, "error")
stopped you from checking out:
%ul
- @order.errors.full_messages.each do |msg|
%li= msg
- if can?(:complete, @order) || can?(:destroy, @order)
= form_tag(checkout_order_path(@order), method: :get, class: 'form-inline') do
%p
- if can? :complete, @order
= label_tag :referral_code, "Do you have a referral code?"
= text_field_tag :referral_code, @order.referral_code, class: 'input-medium'
= submit_tag "Checkout with PayPal", class: 'btn btn-primary'
- if can? :destroy, @order
= link_to 'Delete this order', @order, method: :delete,
data: { confirm: 'Are you sure?' },
class: 'btn btn-default'
= link_to "View other orders/order history", orders_path, class: 'btn btn-default'
%p

View File

@@ -1,32 +0,0 @@
= form_for @product do |f|
- if @product.errors.any?
#error_explanation
%h2
= pluralize(@product.errors.size, "error")
prohibited this product from being saved:
%ul
- @product.errors.full_messages.each do |msg|
%li= msg
.field
= f.label :name
= f.text_field :name, class: 'form-control'
.field
= f.label :description
= f.text_area :description, class: 'form-control'
.field
= f.label :min_price, "Minimum price (in cents)"
= f.text_field :min_price
.field
= f.label :recommended_price, "Recommended price (in cents)"
= f.text_field :recommended_price
.field
= f.label :account_type
= collection_select(:product, :account_type_id, AccountType.all, :id,
:name, selected: @product.account_type_id)
.field
= f.label :paid_months
= f.text_field :paid_months
.form-group
.actions
= f.submit 'Save'

View File

@@ -1,7 +0,0 @@
- content_for :title, "Editing product"
= render 'form'
= link_to 'Show', @product
\|
= link_to 'Back', products_path

View File

@@ -1,29 +0,0 @@
- content_for :title, "Listing products"
%table
%tr
%th Name
%th Description
%th Min price
%th Recommended price
%th Account type
%th Paid months
%th
%th
%th
- @products.each do |product|
%tr
%td= product.name
%td= product.description
%td= product.min_price
%td= product.recommended_price
%td= product.account_type ? product.account_type.name : ""
%td= product.paid_months
%td= link_to 'Show', product
%td= link_to 'Edit', edit_product_path(product)
%td= link_to 'Destroy', product, method: :delete, data: { confirm: 'Are you sure?' }
%br
= link_to 'New Product', new_product_path

View File

@@ -1,5 +0,0 @@
- content_for :title, "New product"
= render 'form'
= link_to 'Back', products_path

View File

@@ -1,25 +0,0 @@
%p#notice= notice
%p
%b Name:
= @product.name
%p
%b Description:
:growstuff_markdown
#{strip_tags(@product.description)}
%p
%b Min price:
= @product.min_price
%p
%b Recommended price:
= @product.recommended_price
%p
%b Account type:
= @product.account_type.name
%p
%b Paid months:
= @product.paid_months
= link_to 'Edit', edit_product_path(@product)
\|
= link_to 'Back', products_path

View File

@@ -1,13 +0,0 @@
%h2 Your current account status
%p
%strong Account type:
= current_member.account_type.name
- if current_member.account.paid_until_string
%p
%strong Paid until:
= current_member.account.paid_until_string
- unless current_member.paid?
= link_to "Upgrade and support #{ENV['GROWSTUFF_SITE_NAME']}", shop_path, class: 'btn btn-primary'

View File

@@ -1,83 +0,0 @@
- content_for :title, t('.title')
%p
Growstuff relies on your support to build and run this open source
platform for food growers. We do not have outside investment, and do
not accept ads. Instead, we offer paid memberships, which give you
access to premium features, and ensure that we focus our efforts on
keeping you, our members, happy.
%p
We are currently developing a number of advanced features for paid
members. We will announce our progress on these in our
= link_to "Feedback and Support forum", "http://www.growstuff.org/forums/growstuff-feedback-support"
as well as via other channels.
%p
All our accounts are priced on a sliding scale. You can choose how
much you want to pay. Remember, your subscription supports an open
source, open data platform supporting home food growers and promoting
sustainable food systems!
- if current_member && current_member.paid?
%h2 Thank you for supporting Growstuff
%p You currently have a paid membership, and can't buy another one at this time.
= render "shared/account_status"
- elsif @order && !@order.order_items.empty?
%h2 Your current order
%p
You currently have the following item in your cart:
%strong
= @most_recent_item.product
@
= price_with_currency(@most_recent_item.price)
%p
= link_to "View order and checkout", order_path(@order)
or
= succeed "." do
= link_to 'delete this order', @order, method: :delete,
data: { confirm: 'Are you sure?' }
- else
- @products.each do |p|
%h2= p.name
%div
:growstuff_markdown
#{ strip_tags p.description }
%p
Pay what you want, starting at
= succeed "." do
= price_with_currency(p.min_price)
= forex_link(p.min_price)
- if p.recommended_price
Recommended price:
= succeed "." do
= price_with_currency(p.recommended_price)
= forex_link(p.recommended_price)
%div
- if can? :create, Order
= form_for @order_item do |f|
.field
= f.text_field :price, value: price_in_dollars(p.recommended_price || p.min_price)
.field
= f.hidden_field :product_id, value: p.id
.field
= f.hidden_field :quantity, value: 1
.actions
= f.submit 'Buy', class: 'btn btn-primary'
- else
Please
= link_to "sign in", new_member_session_path
or
= link_to "sign up", new_member_registration_path
to purchase.

View File

@@ -1,11 +1,11 @@
# Require any additional compass plugins here.
# rubocop:disable Lint/UselessAssignment
# Set this to the root of your project when deployed:
http_path = '/'
css_dir = 'app/assets/stylesheets'
sass_dir = 'app/assets/stylesheets'
javascripts_dir = 'app/assets/javascripts'
images_dir = 'app/assets/images'
http_path = "/"
css_dir = "app/assets/stylesheets"
sass_dir = "app/assets/stylesheets"
javascripts_dir = "app/assets/javascripts"
images_dir = "app/assets/images"
# You can select your preferred output style here (can be overridden via the command line):
# output_style = :expanded or :nested or :compact or :compressed

View File

@@ -42,10 +42,7 @@ module Growstuff
config.i18n.fallbacks = [:en]
# Configure the default encoding used in templates for Ruby 1.9.
config.encoding = 'utf-8'
# Configure a default account type
config.default_account_type = 'Free'
config.encoding = "utf-8"
# Configure sensitive parameters which will be filtered from the log file.
config.filter_parameters += [:password]
@@ -84,9 +81,9 @@ module Growstuff
# Growstuff-specific configuration variables
config.currency = 'AUD'
config.bot_email = 'noreply@growstuff.org'
config.bot_email = "noreply@growstuff.org"
config.user_agent = 'Growstuff'
config.user_agent_email = 'info@growstuff.org'
config.user_agent_email = "info@growstuff.org"
Gibbon::API.api_key = ENV['GROWSTUFF_MAILCHIMP_APIKEY'] || 'notarealkey'
# API key can't be blank or tests fail

View File

@@ -57,11 +57,6 @@ GROWSTUFF_TWITTER_SECRET: ""
GROWSTUFF_FLICKR_KEY: ""
GROWSTUFF_FLICKR_SECRET: ""
# Paypal is used for payments, obviously.
GROWSTUFF_PAYPAL_USERNAME: "dummy"
GROWSTUFF_PAYPAL_PASSWORD: "dummy"
GROWSTUFF_PAYPAL_SIGNATURE: "dummy"
# https://developers.facebook.com/
GROWSTUFF_FACEBOOK_KEY: ""
GROWSTUFF_FACEBOOK_SECRET: ""

View File

@@ -63,17 +63,6 @@ Growstuff::Application.configure do
config.mapbox_map_id = 'growstuff.i3n2il6a'
config.mapbox_access_token = 'pk.eyJ1IjoiZ3Jvd3N0dWZmIiwiYSI6IkdxMkx4alUifQ.n0igaBsw97s14zMa0lwKCA'
config.after_initialize do
ActiveMerchant::Billing::Base.mode = :test
paypal_options = {
login: ENV['GROWSTUFF_PAYPAL_USERNAME'] || 'dummy',
password: ENV['GROWSTUFF_PAYPAL_PASSWORD'] || 'dummy',
signature: ENV['GROWSTUFF_PAYPAL_SIGNATURE'] || 'dummy'
}
::STANDARD_GATEWAY = ActiveMerchant::Billing::PaypalGateway.new(paypal_options)
::EXPRESS_GATEWAY = ActiveMerchant::Billing::PaypalExpressGateway.new(paypal_options)
end
config.action_controller.action_on_unpermitted_parameters = :raise
config.active_job.queue_adapter = :sidekiq

View File

@@ -91,16 +91,5 @@ Growstuff::Application.configure do
config.mapbox_map_id = 'growstuff.i3n2c4ie'
config.mapbox_access_token = 'pk.eyJ1IjoiZ3Jvd3N0dWZmIiwiYSI6IkdxMkx4alUifQ.n0igaBsw97s14zMa0lwKCA'
config.after_initialize do
ActiveMerchant::Billing::Base.mode = :production
paypal_options = {
login: ENV['GROWSTUFF_PAYPAL_USERNAME'],
password: ENV['GROWSTUFF_PAYPAL_PASSWORD'],
signature: ENV['GROWSTUFF_PAYPAL_SIGNATURE']
}
::STANDARD_GATEWAY = ActiveMerchant::Billing::PaypalGateway.new(paypal_options)
::EXPRESS_GATEWAY = ActiveMerchant::Billing::PaypalExpressGateway.new(paypal_options)
end
config.active_job.queue_adapter = :sidekiq
end

View File

@@ -89,16 +89,5 @@ Growstuff::Application.configure do
config.mapbox_map_id = 'growstuff.i3n2hao7'
config.mapbox_access_token = 'pk.eyJ1IjoiZ3Jvd3N0dWZmIiwiYSI6IkdxMkx4alUifQ.n0igaBsw97s14zMa0lwKCA'
config.after_initialize do
ActiveMerchant::Billing::Base.mode = :test
paypal_options = {
login: ENV['GROWSTUFF_PAYPAL_USERNAME'],
password: ENV['GROWSTUFF_PAYPAL_PASSWORD'],
signature: ENV['GROWSTUFF_PAYPAL_SIGNATURE']
}
::STANDARD_GATEWAY = ActiveMerchant::Billing::PaypalGateway.new(paypal_options)
::EXPRESS_GATEWAY = ActiveMerchant::Billing::PaypalExpressGateway.new(paypal_options)
end
config.active_job.queue_adapter = :sidekiq
end

View File

@@ -20,7 +20,7 @@ Growstuff::Application.configure do
# Configure static asset server for tests with Cache-Control for performance
config.serve_static_files = true
config.static_cache_control = 'public, max-age=3600'
config.static_cache_control = "public, max-age=3600"
# Show full error reports and disable caching
config.consider_all_requests_local = true
@@ -51,19 +51,12 @@ Growstuff::Application.configure do
config.analytics_code = ''
config.currency = 'AUD'
end
config.after_initialize do
require 'active_merchant/ext/paypal_bogus_gateway'
ActiveMerchant::Billing::Base.mode = :test
::STANDARD_GATEWAY = ActiveMerchant::Billing::PaypalBogusGateway.new
::EXPRESS_GATEWAY = ActiveMerchant::Billing::PaypalBogusGateway.new
end
end
Geocoder.configure(lookup: :test)
Geocoder::Lookup::Test.add_stub(
'Amundsen-Scott Base, Antarctica', [
"Amundsen-Scott Base, Antarctica", [
{
'latitude' => -90.0,
'longitude' => 0.0
@@ -72,7 +65,7 @@ Geocoder::Lookup::Test.add_stub(
)
Geocoder::Lookup::Test.add_stub(
'Philippines', [
"Philippines", [
{
'latitude' => 12.7503486,
'longitude' => 122.7312101,
@@ -86,7 +79,7 @@ Geocoder::Lookup::Test.add_stub(
)
Geocoder::Lookup::Test.add_stub(
'Greenwich, UK', [
"Greenwich, UK", [
{
'latitude' => 51.483061,
'longitude' => -0.004151
@@ -95,7 +88,7 @@ Geocoder::Lookup::Test.add_stub(
)
Geocoder::Lookup::Test.add_stub(
'Edinburgh', [
"Edinburgh", [
{
'latitude' => 55.953252,
'longitude' => -3.188267
@@ -104,7 +97,7 @@ Geocoder::Lookup::Test.add_stub(
)
# Unknown location
Geocoder::Lookup::Test.add_stub('Tatooine', [])
Geocoder::Lookup::Test.add_stub("Tatooine", [])
Capybara.configure do |config|
config.always_include_port = true
@@ -115,12 +108,12 @@ OmniAuth.config.test_mode = true
OmniAuth.config.mock_auth[:facebook] = OmniAuth::AuthHash.new(provider: 'facebook',
uid: '123545',
info: {
name: 'John Testerson',
name: "John Testerson",
nickname: 'JohnnyT',
email: 'example.oauth.facebook@example.com',
image: 'http://findicons.com/files/icons/1072/face_avatars/300/i04.png'
},
credentials: {
token: 'token',
secret: 'donttell'
token: "token",
secret: "donttell"
})

View File

@@ -5,7 +5,7 @@ Devise.setup do |config|
# ==> Mailer Configuration
# Configure the e-mail address which will be shown in Devise::Mailer,
# note that it will be overwritten if you use your own mailer class with default "from" parameter.
config.mailer_sender = 'Growstuff <noreply@growstuff.org>'
config.mailer_sender = "Growstuff <noreply@growstuff.org>"
config.secret_key = ENV['RAILS_SECRET_TOKEN']

View File

@@ -4,9 +4,9 @@ Geocoder.configure(
units: :km,
timeout: 10,
http_headers: {
'User-Agent' =>
"User-Agent" =>
"#{Growstuff::Application.config.user_agent} #{Growstuff::Application.config.user_agent_email}",
'From' => Growstuff::Application.config.user_agent_email
"From" => Growstuff::Application.config.user_agent_email
}
)
# This configuration takes precedence over environment/test.rb

View File

@@ -1,9 +1,9 @@
Time::DATE_FORMATS[:default] = '%B %d, %Y at %H:%M'
Date::DATE_FORMATS[:default] = '%B %d, %Y'
Date::DATE_FORMATS[:default] = "%B %d, %Y"
Time::DATE_FORMATS[:date] = '%B %d, %Y'
Date::DATE_FORMATS[:date] = '%B %d, %Y'
Time::DATE_FORMATS[:date] = "%B %d, %Y"
Date::DATE_FORMATS[:date] = "%B %d, %Y"
Date::DATE_FORMATS[:ymd] = '%Y-%m-%d'
Date::DATE_FORMATS[:ymd] = "%Y-%m-%d"
Time::DATE_FORMATS[:datetime] = '%B %d, %Y at %H:%M'

View File

@@ -1,11 +1,5 @@
---
en:
account:
update: Account detail was successfully updated.
account_types:
created: Account type was successfully created.
deleted: Account type was successfully deleted.
updated: Account type was successfully updated.
activerecord:
models:
comment:
@@ -99,7 +93,6 @@ en:
open:
ad_free_linktext: ad-free
api_docs_linktext: API documentation
buy_account_linktext: buying a paid account
creative_commons_linktext: Creative Commons license
get_involved_body_html: >
We believe in collaboration, and work closely with our members and the wider food-growing community.
@@ -213,9 +206,6 @@ en:
default: Everyone's seeds
owner_seeds: "%{owner} seeds"
string: "%{crop} seeds belonging to %{owner}"
shop:
index:
title: Shop
unauthorized:
create:
all: Please sign in or sign up to create a %{subject}.

View File

@@ -4,10 +4,10 @@ Growstuff::Application.routes.draw do
resources :plant_parts
devise_for :members, controllers: {
registrations: 'registrations',
passwords: 'passwords',
sessions: 'sessions',
omniauth_callbacks: 'omniauth_callbacks'
registrations: "registrations",
passwords: "passwords",
sessions: "sessions",
omniauth_callbacks: "omniauth_callbacks"
}
devise_scope :member do
get '/members/unsubscribe/:message' => 'members#unsubscribe', as: 'unsubscribe_member'
@@ -72,34 +72,19 @@ Growstuff::Application.routes.draw do
get '/places/search' => 'places#search', as: 'search_places'
get '/places/:place' => 'places#show', as: 'place'
# everything for paid accounts etc
resources :account_types
resources :accounts
resources :orders
get 'orders/:id/checkout' => 'orders#checkout', as: 'checkout_order'
get 'orders/:id/complete' => 'orders#complete', as: 'complete_order'
get 'orders/:id/cancel' => 'orders#cancel', as: 'cancel_order'
resources :order_items
resources :products
resources :likes, only: %i(create destroy)
get 'home/index'
get "home/index"
root to: 'home#index'
get 'auth/:provider/callback' => 'authentications#create'
get 'members/auth/:provider/callback' => 'authentications#create'
get '/shop' => 'shop#index'
get '/shop/:action' => 'shop#:action'
comfy_route :cms_admin, path: '/admin/cms'
namespace :admin do
resources :members
end
get '/admin/orders' => 'admin/orders#index'
get '/admin/orders/:action' => 'admin/orders#:action'
get '/admin' => 'admin#index'
get '/admin/newsletter' => 'admin#newsletter', as: :admin_newsletter
get '/admin/:action' => 'admin#:action'

View File

@@ -4,7 +4,7 @@ if ENV['MY_RUBY_HOME'] && ENV['MY_RUBY_HOME'].include?('rvm')
RVM.use_from_path! File.dirname(File.dirname(__FILE__))
rescue LoadError
# RVM is unavailable at this point.
raise 'RVM ruby lib is currently unavailable.'
raise "RVM ruby lib is currently unavailable."
end
end

View File

@@ -2,8 +2,8 @@ class DeviseCreateUsers < ActiveRecord::Migration
def change
create_table(:users) do |t|
## Database authenticatable
t.string :email, null: false, default: ''
t.string :encrypted_password, null: false, default: ''
t.string :email, null: false, default: ""
t.string :encrypted_password, null: false, default: ""
## Recoverable
t.string :reset_password_token

View File

@@ -1,5 +1,5 @@
class AddApprovalStatusToCrops < ActiveRecord::Migration
def change
add_column :crops, :approval_status, :string, default: 'approved'
add_column :crops, :approval_status, :string, default: "approved"
end
end

View File

@@ -1,8 +1,8 @@
class SetPredictionData < ActiveRecord::Migration
def up
say 'Updating all plantings time to first harvest'
say "Updating all plantings time to first harvest"
Planting.all.each(&:update_harvest_days)
say 'Updating crop median time to first harvest, and lifespan'
say "Updating crop median time to first harvest, and lifespan"
Crop.all.each do |crop|
crop.update_lifespan_medians
crop.update_harvest_medians

View File

@@ -18,19 +18,19 @@ class CreatePhotographings < ActiveRecord::Migration
end
def migrate_data
say 'migrating garden photos'
say "migrating garden photos"
GardensPhoto.all.each do |g|
Photographing.create! photo_id: g.photo_id, photographable_id: g.garden_id, photographable_type: 'Garden'
end
say 'migrating planting photos'
say "migrating planting photos"
PhotosPlanting.all.each do |p|
Photographing.create! photo_id: p.photo_id, photographable_id: p.planting_id, photographable_type: 'Planting'
end
say 'migrating harvest photos'
say "migrating harvest photos"
HarvestsPhoto.all.each do |h|
Photographing.create! photo_id: h.photo_id, photographable_id: h.harvest_id, photographable_type: 'Harvest'
end
say 'migrating seed photos'
say "migrating seed photos"
PhotosSeed.all.each do |s|
Photographing.create! photo_id: s.photo_id, photographable_id: s.seed_id, photographable_type: 'Seed'
end

View File

@@ -1,20 +1,5 @@
class AddDatetakenToPhotos < ActiveRecord::Migration
def up
def change
add_column :photos, :date_taken, :datetime
update_flickr_metadata
end
def down
add_column :photos, :date_taken
end
private
def update_flickr_metadata
# Fetch from flickr, the photos updated the longest ago will be fetched first
Photo.all.order(:updated_at).each do |photo|
say "Fetch flickr data for #{photo}"
photo.set_flickr_metadata!
end
end
end

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