Merge branch 'dev' into bw/bar_graphs

This commit is contained in:
Shiny
2017-01-18 11:15:09 +13:00
committed by GitHub
39 changed files with 306 additions and 401 deletions

View File

@@ -9,7 +9,6 @@
# Offense count: 24
Lint/AmbiguousRegexpLiteral:
Exclude:
- 'app/models/order.rb'
- 'spec/controllers/admin/orders_controller_spec.rb'
- 'spec/controllers/orders_controller_spec.rb'
- 'spec/features/cms_spec.rb'
@@ -33,7 +32,6 @@ Lint/UnusedBlockArgument:
Exclude:
- 'app/controllers/crops_controller.rb'
- 'app/controllers/sessions_controller.rb'
- 'app/models/post.rb'
- 'config/unicorn.rb'
- 'lib/haml/filters/growstuff_markdown.rb'
@@ -45,7 +43,6 @@ Lint/UnusedMethodArgument:
- 'app/controllers/application_controller.rb'
- 'app/controllers/passwords_controller.rb'
- 'app/controllers/registrations_controller.rb'
- 'app/models/crop.rb'
- 'app/validators/approved_validator.rb'
- 'spec/views/plantings/show.html.haml_spec.rb'
@@ -60,10 +57,7 @@ Lint/Void:
# Cop supports --auto-correct.
Performance/StringReplacement:
Exclude:
- 'app/models/garden.rb'
- 'app/models/harvest.rb'
- 'app/models/planting.rb'
- 'app/models/seed.rb'
- 'spec/rails_helper.rb'
# Offense count: 10
@@ -85,15 +79,7 @@ Rails/Date:
# Include: app/models/**/*.rb
Rails/HasAndBelongsToMany:
Exclude:
- 'app/models/crop.rb'
- 'app/models/garden.rb'
- 'app/models/harvest.rb'
- 'app/models/member.rb'
- 'app/models/photo.rb'
- 'app/models/planting.rb'
- 'app/models/post.rb'
- 'app/models/product.rb'
- 'app/models/role.rb'
# Offense count: 3
Rails/OutputSafety:
@@ -114,30 +100,18 @@ Rails/TimeZone:
- 'spec/models/post_spec.rb'
- 'spec/views/plantings/index.html.haml_spec.rb'
# Offense count: 2
# Cop supports --auto-correct.
# Configuration parameters: Include.
# Include: app/models/**/*.rb
Rails/Validation:
Exclude:
- 'app/models/member.rb'
- 'app/models/order_item.rb'
# Offense count: 12
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles.
# SupportedStyles: always, conditionals
Style/AndOr:
Exclude:
- 'app/models/notification.rb'
- 'app/models/photo.rb'
- 'config/unicorn.rb'
- 'lib/tasks/growstuff.rake'
# Offense count: 2
Style/AsciiComments:
Exclude:
- 'app/models/crop.rb'
- 'config/initializers/comfortable_mexican_sofa.rb'
# Offense count: 5
@@ -193,9 +167,6 @@ Style/BracesAroundHashParameters:
- 'app/controllers/crops_controller.rb'
- 'app/controllers/posts_controller.rb'
- 'app/helpers/application_helper.rb'
- 'app/models/crop.rb'
- 'app/models/member.rb'
- 'app/models/order.rb'
- 'config/environments/test.rb'
- 'spec/controllers/admin/orders_controller_spec.rb'
- 'spec/controllers/comments_controller_spec.rb'
@@ -227,12 +198,7 @@ Style/ClassAndModuleChildren:
# Cop supports --auto-correct.
Style/ClassMethods:
Exclude:
- 'app/models/crop.rb'
- 'app/models/member.rb'
- 'app/models/order.rb'
- 'app/models/planting.rb'
- 'app/models/post.rb'
- 'app/models/seed.rb'
# Offense count: 2
# Cop supports --auto-correct.
@@ -262,19 +228,6 @@ Style/EachForSimpleLoop:
- 'spec/models/crop_spec.rb'
- 'spec/views/home/_crops.html.haml_spec.rb'
# Offense count: 1
# Cop supports --auto-correct.
Style/EmptyLiteral:
Exclude:
- 'app/models/member.rb'
# Offense count: 1
# Configuration parameters: EnforcedStyle, SupportedStyles.
# SupportedStyles: for, each
Style/For:
Exclude:
- 'app/models/order.rb'
# Offense count: 5
# Configuration parameters: EnforcedStyle, SupportedStyles.
# SupportedStyles: format, sprintf, percent
@@ -290,11 +243,6 @@ Style/IdenticalConditionalBranches:
- 'app/controllers/crops_controller.rb'
- 'app/controllers/follows_controller.rb'
# Offense count: 1
Style/IfInsideElse:
Exclude:
- 'app/models/harvest.rb'
# Offense count: 26
# Cop supports --auto-correct.
# Configuration parameters: MaxLineLength.
@@ -303,13 +251,7 @@ Style/IfUnlessModifier:
- 'app/controllers/gardens_controller.rb'
- 'app/controllers/shop_controller.rb'
- 'app/helpers/crops_helper.rb'
- 'app/models/crop.rb'
- 'app/models/garden.rb'
- 'app/models/harvest.rb'
- 'app/models/member.rb'
- 'app/models/order.rb'
- 'app/models/planting.rb'
- 'app/models/seed.rb'
- 'config/initializers/geocoder.rb'
- 'lib/tasks/growstuff.rake'
@@ -327,18 +269,9 @@ Style/Lambda:
# Cop supports --auto-correct.
Style/MethodCallParentheses:
Exclude:
- 'app/models/photo.rb'
- 'spec/helpers/application_helper_spec.rb'
- 'spec/views/plantings/new.html.haml_spec.rb'
# Offense count: 2
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles.
# SupportedStyles: symmetrical, new_line, same_line
Style/MultilineArrayBraceLayout:
Exclude:
- 'app/models/seed.rb'
# Offense count: 8
# Cop supports --auto-correct.
Style/MultilineBlockLayout:
@@ -355,11 +288,7 @@ Style/MultilineBlockLayout:
# SupportedStyles: symmetrical, new_line, same_line
Style/MultilineHashBraceLayout:
Exclude:
- 'app/models/garden.rb'
- 'app/models/harvest.rb'
- 'app/models/planting.rb'
- 'app/models/product.rb'
- 'app/models/seed.rb'
# Offense count: 1
# Cop supports --auto-correct.
@@ -384,8 +313,6 @@ Style/MultilineMethodCallBraceLayout:
- 'app/controllers/application_controller.rb'
- 'app/controllers/authentications_controller.rb'
- 'app/controllers/seeds_controller.rb'
- 'app/models/account.rb'
- 'app/models/crop.rb'
- 'spec/controllers/order_items_controller_spec.rb'
- 'spec/helpers/gardens_helper_spec.rb'
- 'spec/helpers/harvests_helper_spec.rb'
@@ -436,10 +363,7 @@ Style/MultilineTernaryOperator:
Style/MutableConstant:
Exclude:
- 'app/controllers/members_controller.rb'
- 'app/models/garden.rb'
- 'app/models/harvest.rb'
- 'app/models/planting.rb'
- 'app/models/seed.rb'
# Offense count: 7
# Cop supports --auto-correct.
@@ -447,8 +371,6 @@ Style/NegatedIf:
Exclude:
- 'app/controllers/crops_controller.rb'
- 'app/helpers/crops_helper.rb'
- 'app/models/crop.rb'
- 'app/models/garden.rb'
- 'script/check_contributors_md'
# Offense count: 2
@@ -463,7 +385,6 @@ Style/NestedTernaryOperator:
# SupportedStyles: skip_modifier_ifs, always
Style/Next:
Exclude:
- 'app/models/post.rb'
- 'lib/tasks/growstuff.rake'
# Offense count: 2
@@ -472,13 +393,6 @@ Style/NilComparison:
Exclude:
- 'lib/tasks/growstuff.rake'
# Offense count: 1
# Cop supports --auto-correct.
# Configuration parameters: IncludeSemanticChanges.
Style/NonNilCheck:
Exclude:
- 'app/models/harvest.rb'
# Offense count: 2
# Cop supports --auto-correct.
# Configuration parameters: EnforcedOctalStyle, SupportedOctalStyles.
@@ -502,10 +416,6 @@ Style/NumericPredicate:
- 'app/helpers/crops_helper.rb'
- 'app/helpers/harvests_helper.rb'
- 'app/helpers/plantings_helper.rb'
- 'app/models/crop.rb'
- 'app/models/garden.rb'
- 'app/models/harvest.rb'
- 'app/models/photo.rb'
- 'lib/tasks/growstuff.rake'
- 'script/check_contributors_md'
@@ -523,8 +433,6 @@ Style/ParenthesesAroundCondition:
- 'app/controllers/application_controller.rb'
- 'app/controllers/orders_controller.rb'
- 'app/helpers/crops_helper.rb'
- 'app/models/garden.rb'
- 'app/models/member.rb'
- 'config/factory_girl.rb'
# Offense count: 5
@@ -541,7 +449,6 @@ Style/PercentLiteralDelimiters:
# Cop supports --auto-correct.
Style/PerlBackrefs:
Exclude:
- 'app/models/post.rb'
- 'lib/haml/filters/growstuff_markdown.rb'
# Offense count: 3
@@ -552,7 +459,6 @@ Style/PerlBackrefs:
Style/PredicateName:
Exclude:
- 'spec/**/*'
- 'app/models/member.rb'
# Offense count: 1
# Cop supports --auto-correct.
@@ -565,23 +471,12 @@ Style/RedundantBegin:
Style/RedundantParentheses:
Exclude:
- 'app/helpers/plantings_helper.rb'
- 'app/models/garden.rb'
# Offense count: 56
# Cop supports --auto-correct.
Style/RedundantSelf:
Exclude:
- 'app/models/comment.rb'
- 'app/models/crop.rb'
- 'app/models/follow.rb'
- 'app/models/harvest.rb'
- 'app/models/member.rb'
- 'app/models/notification.rb'
- 'app/models/order.rb'
- 'app/models/photo.rb'
- 'app/models/planting.rb'
- 'app/models/post.rb'
- 'app/models/seed.rb'
- 'lib/geocodable.rb'
# Offense count: 9
@@ -590,7 +485,6 @@ Style/RedundantSelf:
# SupportedStyles: slashes, percent_r, mixed
Style/RegexpLiteral:
Exclude:
- 'app/models/crop.rb'
- 'spec/lib/haml/filters/growstuff_markdown_spec.rb'
- 'spec/rails_helper.rb'
- 'spec/views/devise/registrations/edit_spec.rb'
@@ -611,15 +505,6 @@ Style/SelfAssignment:
Style/SpecialGlobalVars:
EnforcedStyle: use_perl_names
# Offense count: 2
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles.
# SupportedStyles: single_quotes, double_quotes
Style/StringLiteralsInInterpolation:
Exclude:
- 'app/models/follow.rb'
- 'app/models/post.rb'
# Offense count: 9
# Cop supports --auto-correct.
# Configuration parameters: IgnoredMethods.
@@ -627,11 +512,7 @@ Style/StringLiteralsInInterpolation:
Style/SymbolProc:
Exclude:
- 'app/controllers/crops_controller.rb'
- 'app/models/crop.rb'
- 'app/models/garden.rb'
- 'app/models/harvest.rb'
- 'app/models/planting.rb'
- 'app/models/post.rb'
- 'lib/tasks/growstuff.rake'
# Offense count: 1
@@ -648,7 +529,6 @@ Style/TernaryParentheses:
# SupportedStyles: comma, consistent_comma, no_comma
Style/TrailingCommaInArguments:
Exclude:
- 'app/models/post.rb'
- 'db/seeds.rb'
- 'lib/actions/oauth_signup_action.rb'
- 'lib/tasks/growstuff.rake'
@@ -659,7 +539,6 @@ Style/TrailingCommaInArguments:
# SupportedStyles: comma, consistent_comma, no_comma
Style/TrailingCommaInLiteral:
Exclude:
- 'app/models/crop.rb'
- 'config/environments/test.rb'
- 'spec/rails_helper.rb'
@@ -673,8 +552,6 @@ Style/UnlessElse:
# Cop supports --auto-correct.
Style/UnneededInterpolation:
Exclude:
- 'app/models/crop.rb'
- 'app/models/harvest.rb'
- 'spec/features/crops/crop_wranglers_spec.rb'
- 'spec/features/following_spec.rb'
- 'spec/features/shared_examples/append_date.rb'
@@ -697,12 +574,4 @@ Style/UnneededPercentQ:
Style/WordArray:
Exclude:
- 'app/controllers/omniauth_callbacks_controller.rb'
- 'app/models/crop.rb'
- 'spec/models/seed_spec.rb'
# Offense count: 6
# Cop supports --auto-correct.
Style/ZeroLengthPredicate:
Exclude:
- 'app/models/crop.rb'
- 'app/models/photo.rb'

View File

@@ -50,9 +50,9 @@ GEM
tzinfo (~> 1.1)
addressable (2.5.0)
public_suffix (~> 2.0, >= 2.0.2)
arel (6.0.3)
arel (6.0.4)
ast (2.3.0)
autoprefixer-rails (6.5.3.1)
autoprefixer-rails (6.6.1)
execjs
bcrypt (3.1.11)
better_errors (2.1.1)
@@ -71,8 +71,8 @@ GEM
bootstrap-sass (3.3.7)
autoprefixer-rails (>= 5.2.1)
sass (>= 3.3.4)
bootstrap_form (2.5.2)
builder (3.2.2)
bootstrap_form (2.5.3)
builder (3.2.3)
byebug (9.0.6)
cancancan (1.15.0)
capybara (2.10.1)
@@ -90,8 +90,7 @@ GEM
launchy
childprocess (0.5.9)
ffi (~> 1.0, >= 1.0.11)
climate_control (0.0.3)
activesupport (>= 3.0)
climate_control (0.1.0)
cliver (0.3.2)
cocaine (0.5.8)
climate_control (>= 0.0.3, < 1.0)
@@ -106,8 +105,8 @@ GEM
coffee-script (2.4.1)
coffee-script-source
execjs
coffee-script-source (1.11.1)
comfortable_mexican_sofa (1.12.9)
coffee-script-source (1.12.2)
comfortable_mexican_sofa (1.12.10)
active_link_to (>= 1.0.0)
bootstrap-sass (>= 3.2.0)
bootstrap_form (>= 2.2.0)
@@ -119,10 +118,10 @@ GEM
kramdown (>= 1.0.0)
paperclip (>= 4.0.0)
plupload-rails (>= 1.2.1)
rails (>= 4.0.0, < 5)
rails (>= 4.0.0, < 5.1)
rails-i18n (>= 4.0.0)
sass-rails (>= 4.0.3)
concurrent-ruby (1.0.2)
concurrent-ruby (1.0.4)
connection_pool (2.2.0)
coveralls (0.8.16)
json (>= 1.8, < 3)
@@ -241,7 +240,7 @@ GEM
parser (>= 2.2.3.0)
term-ansicolor (>= 1.3.2)
terminal-table (>= 1.5.1)
jquery-rails (4.2.1)
jquery-rails (4.2.2)
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
@@ -250,13 +249,13 @@ GEM
js-routes (1.3.0)
railties (>= 3.2)
sprockets-rails
json (1.8.3)
json (1.8.6)
jwt (1.5.6)
kaminari (0.17.0)
actionpack (>= 3.0.0)
activesupport (>= 3.0.0)
kgio (2.10.0)
kramdown (1.13.1)
kramdown (1.13.2)
launchy (2.4.3)
addressable (~> 2.3)
leaflet-markercluster-rails (0.7.0)
@@ -357,9 +356,9 @@ GEM
sprockets-rails
rails-deprecated_sanitizer (1.0.3)
activesupport (>= 4.2.0.alpha)
rails-dom-testing (1.0.7)
rails-dom-testing (1.0.8)
activesupport (>= 4.2.0.beta, < 5.0)
nokogiri (~> 1.6.0)
nokogiri (~> 1.6)
rails-deprecated_sanitizer (>= 1.0.1)
rails-html-sanitizer (1.0.3)
loofah (~> 2.0)
@@ -419,10 +418,10 @@ GEM
ruby-progressbar (1.8.1)
ruby-units (2.0.1)
ruby_dep (1.4.0)
ruby_parser (3.8.3)
ruby_parser (3.8.4)
sexp_processor (~> 4.1)
rubyzip (1.2.0)
sass (3.4.22)
sass (3.4.23)
sass-rails (5.0.6)
railties (>= 4.0.0, < 6)
sass (~> 3.1)
@@ -452,10 +451,10 @@ GEM
slop (3.6.0)
sparkpost_rails (1.4.0)
rails (>= 4.0, < 5.1)
sprockets (3.7.0)
sprockets (3.7.1)
concurrent-ruby (~> 1.0)
rack (> 1, < 3)
sprockets-rails (3.1.1)
sprockets-rails (3.2.0)
actionpack (>= 4.0)
activesupport (>= 4.0)
sprockets (>= 3.0.0)
@@ -573,8 +572,5 @@ DEPENDENCIES
webrat
will_paginate (~> 3.0)
RUBY VERSION
ruby 2.3.3p222
BUNDLED WITH
1.13.6

View File

@@ -119,7 +119,7 @@ class CropsController < ApplicationController
def create
@crop = Crop.new(crop_params)
if current_member.has_role? :crop_wrangler
if current_member.role? :crop_wrangler
@crop.creator = current_member
success_msg = "Crop was successfully created."
else
@@ -136,7 +136,7 @@ class CropsController < ApplicationController
params[:sci_name].each do |index, value|
create_name('scientific', value)
end
unless current_member.has_role? :crop_wrangler
unless current_member.role? :crop_wrangler
Role.crop_wranglers.each do |w|
Notifier.new_crop_request(w, @crop).deliver_later!
end

View File

@@ -5,15 +5,10 @@ class PlantingsController < ApplicationController
# GET /plantings
# GET /plantings.json
def index
@owner = Member.find_by(slug: params[:owner])
@crop = Crop.find_by(slug: params[:crop])
@plantings = if @owner
@owner.plantings.includes(:owner, :crop, :garden).paginate(page: params[:page])
elsif @crop
@crop.plantings.includes(:owner, :crop, :garden).paginate(page: params[:page])
else
Planting.includes(:owner, :crop, :garden).paginate(page: params[:page])
end
@owner = Member.find_by(slug: params[:owner]) if params[:owner]
@crop = Crop.find_by(slug: params[:crop]) if params[:crop]
@show_all = params[:all] == '1'
@plantings = plantings
respond_to do |format|
format.html { @plantings = @plantings.paginate(page: params[:page]) }
@@ -41,7 +36,7 @@ class PlantingsController < ApplicationController
# GET /plantings/new
# GET /plantings/new.json
def new
@planting = Planting.new('planted_at' => Date.today)
@planting = Planting.new('planted_at' => Time.zone.today)
# using find_by_id here because it returns nil, unlike find
@crop = Crop.find_by(id: params[:crop_id]) || Crop.new
@@ -127,4 +122,18 @@ class PlantingsController < ApplicationController
(planting.finished_at - planting.planted_at).to_i
end
end
def plantings
@plantings = if @owner
@owner.plantings
elsif @crop
@crop.plantings
else
Planting
end
@plantings = @plantings.current unless @show_all
@plantings = @plantings.includes(:owner, :crop, :garden).order(:created_at).paginate(page: params[:page])
@plantings
end
end

View File

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

View File

@@ -57,7 +57,7 @@ class Ability
# note we don't support update for notifications
# only crop wranglers can create/edit/destroy crops
if member.has_role? :crop_wrangler
if member.role? :crop_wrangler
can :wrangle, Crop
can :manage, Crop
can :manage, ScientificName
@@ -124,7 +124,7 @@ class Ability
can :destroy, Follow
cannot :destroy, Follow, followed_id: member.id # can't unfollow yourself
return unless member.has_role? :admin
return unless member.role? :admin
can :read, :all
can :manage, :all

View File

@@ -9,8 +9,7 @@ class Account < ActiveRecord::Base
before_create do |account|
unless account.account_type
account.account_type = AccountType.find_or_create_by(name:
Growstuff::Application.config.default_account_type
)
Growstuff::Application.config.default_account_type)
end
end

View File

@@ -6,16 +6,16 @@ class Comment < ActiveRecord::Base
scope :post_order, -> { reorder("created_at ASC") } # for display on post page
after_create do
recipient = self.post.author.id
sender = self.author.id
recipient = post.author.id
sender = author.id
# don't send notifications to yourself
if recipient != sender
Notification.create(
recipient_id: recipient,
sender_id: sender,
subject: "#{self.author} commented on #{self.post.subject}",
body: self.body,
post_id: self.post.id
subject: "#{author} commented on #{post.subject}",
body: body,
post_id: post.id
)
end
end

View File

@@ -18,7 +18,7 @@ class Crop < ActiveRecord::Base
belongs_to :parent, class_name: 'Crop'
has_many :varieties, class_name: 'Crop', foreign_key: 'parent_id'
has_and_belongs_to_many :posts
has_and_belongs_to_many :posts # rubocop:disable Rails/HasAndBelongsToMany
before_destroy { |crop| crop.posts.clear }
default_scope { order("lower(name) asc") }
@@ -42,7 +42,7 @@ class Crop < ActiveRecord::Base
## Wikipedia urls are only necessary when approving a crop
validates :en_wikipedia_url,
format: {
with: /\Ahttps?:\/\/en\.wikipedia\.org\/wiki\/[[:alnum:]%_\.()-]+\z/,
with: %r{\Ahttps?:\/\/en\.wikipedia\.org\/wiki\/[[:alnum:]%_\.()-]+\z},
message: 'is not a valid English Wikipedia URL'
},
if: :approved?
@@ -73,8 +73,8 @@ class Crop < ActiveRecord::Base
min_gram: 3,
max_gram: 10,
# token_chars: Elasticsearch will split on characters
# that dont belong to any of these classes
token_chars: ["letter", "digit"]
# that don't belong to any of these classes
token_chars: %w(letter digit)
}
},
analyzer: {
@@ -82,7 +82,7 @@ class Crop < ActiveRecord::Base
tokenizer: "gs_edgeNGram_tokenizer",
filter: ["lowercase"]
}
},
}
} do
mappings dynamic: 'false' do
indexes :id, type: 'long'
@@ -103,18 +103,19 @@ class Crop < ActiveRecord::Base
end
end
def as_indexed_json(options = {})
self.as_json(
def as_indexed_json(_options = {})
as_json(
only: [:id, :name, :approval_status],
include: {
scientific_names: { only: :name },
alternate_names: { only: :name }
})
}
)
end
# update the Elasticsearch index (only if we're using it in this
# environment)
def update_index(name_obj)
def update_index(_name_obj)
__elasticsearch__.index_document if ENV["GROWSTUFF_ELASTICSEARCH"] == "true"
end
@@ -125,7 +126,7 @@ class Crop < ActiveRecord::Base
end
def default_scientific_name
scientific_names.first.name if scientific_names.size > 0
scientific_names.first.name unless scientific_names.empty?
end
# crop.default_photo
@@ -190,7 +191,7 @@ class Crop < ActiveRecord::Base
end
def approval_statuses
['rejected', 'pending', 'approved']
%w(rejected pending approved)
end
def reasons_for_rejection
@@ -199,7 +200,7 @@ class Crop < ActiveRecord::Base
# Crop.interesting
# returns a list of interesting crops, for use on the homepage etc
def Crop.interesting
def self.interesting
howmany = 12 # max number to find
interesting_crops = []
Crop.includes(:photos).randomized.each do |c|
@@ -218,7 +219,7 @@ class Crop < ActiveRecord::Base
# - parent (name, optional)
# - scientific name (optional, can be picked up from parent if it has one)
def Crop.create_from_csv(row)
def self.create_from_csv(row)
name, en_wikipedia_url, parent, scientific_names, alternate_names = row
cropbot = Member.find_by(login_name: 'cropbot')
@@ -246,16 +247,16 @@ class Crop < ActiveRecord::Base
def add_scientific_names_from_csv(scientific_names)
names_to_add = []
if !scientific_names.blank? # i.e. we actually passed something in, which isn't a given
names_to_add = scientific_names.split(%r{,\s*})
elsif parent && parent.scientific_names.size > 0 # pick up from parent
names_to_add = parent.scientific_names.map { |s| s.name }
names_to_add = scientific_names.split(/,\s*/)
elsif parent && !parent.scientific_names.empty? # pick up from parent
names_to_add = parent.scientific_names.map(&:name)
else
logger.warn("Warning: no scientific name (not even on parent crop) for #{self}")
end
cropbot = Member.find_by(login_name: 'cropbot')
return unless names_to_add.size > 0
return if names_to_add.empty?
raise "cropbot account not found: run rake db:seed" unless cropbot
add_names_to_list(names_to_add, 'scientific')
@@ -266,7 +267,7 @@ class Crop < ActiveRecord::Base
return if alternate_names.blank?
cropbot = Member.find_by!(login_name: 'cropbot')
names_to_add = alternate_names.split(%r{,\s*})
names_to_add = alternate_names.split(/,\s*/)
add_names_to_list(names_to_add, 'alternate')
rescue
raise "cropbot account not found: run rake db:seed" unless cropbot
@@ -281,23 +282,21 @@ class Crop < ActiveRecord::Base
def self.search(query)
if ENV['GROWSTUFF_ELASTICSEARCH'] == "true"
search_str = query.nil? ? "" : query.downcase
response = __elasticsearch__.search({
# Finds documents which match any field, but uses the _score from
# the best field insead of adding up _score from each field.
query: {
multi_match: {
query: "#{search_str}",
analyzer: "standard",
fields: ["name",
"scientific_names.scientific_name",
"alternate_names.name"]
}
},
filter: {
term: { approval_status: "approved" }
},
size: 50
}
response = __elasticsearch__.search( # Finds documents which match any field, but uses the _score from
# the best field insead of adding up _score from each field.
query: {
multi_match: {
query: search_str.to_s,
analyzer: "standard",
fields: ["name",
"scientific_names.scientific_name",
"alternate_names.name"]
}
},
filter: {
term: { approval_status: "approved" }
},
size: 50
)
response.records.to_a
else
@@ -320,7 +319,7 @@ class Crop < ActiveRecord::Base
end
end
def Crop.case_insensitive_name(name)
def self.case_insensitive_name(name)
where(["lower(name) = :value", { value: name.downcase }])
end
@@ -339,20 +338,20 @@ class Crop < ActiveRecord::Base
def create_crop_in_list(list_name, name)
cropbot = Member.find_by(login_name: 'cropbot')
create_hash = {
creator_id: "#{cropbot.id}",
creator_id: cropbot.id.to_s,
name: name
}
self.send("#{list_name}_names").create(create_hash)
send("#{list_name}_names").create(create_hash)
end
def name_already_exists(list_name, name)
self.send("#{list_name}_names").exists?(name: name)
send("#{list_name}_names").exists?(name: name)
end
def count_uses_of_property(col_name)
data = Hash.new(0)
plantings.each do |p|
data[p.send("#{col_name}")] += 1 if !p.send("#{col_name}").blank?
data[p.send(col_name.to_s)] += 1 unless p.send(col_name.to_s).blank?
end
data
end

View File

@@ -5,10 +5,10 @@ class Follow < ActiveRecord::Base
after_create do
Notification.create(
recipient_id: self.followed_id,
sender_id: self.follower_id,
subject: "#{self.follower.login_name} is now following you",
body: "#{self.follower.login_name} just followed you on #{ENV["GROWSTUFF_SITE_NAME"]}. "
recipient_id: followed_id,
sender_id: follower_id,
subject: "#{follower.login_name} is now following you",
body: "#{follower.login_name} just followed you on #{ENV['GROWSTUFF_SITE_NAME']}. "
)
end
end

View File

@@ -30,7 +30,8 @@ class Garden < ActiveRecord::Base
validates :area,
numericality: {
only_integer: false,
greater_than_or_equal_to: 0 },
greater_than_or_equal_to: 0
},
allow_nil: true
AREA_UNITS_VALUES = {
@@ -38,7 +39,7 @@ class Garden < ActiveRecord::Base
"square feet" => "square foot",
"hectares" => "hectare",
"acres" => "acre"
}
}.freeze
validates :area_unit, inclusion: { in: AREA_UNITS_VALUES.values,
message: "%{value} is not a valid area unit" },
allow_nil: true,
@@ -47,12 +48,12 @@ class Garden < ActiveRecord::Base
after_validation :cleanup_area
def cleanup_area
self.area = nil if area == 0
self.area = nil if area && area.zero?
self.area_unit = nil if area.blank?
end
def garden_slug
"#{owner.login_name}-#{name}".downcase.gsub(' ', '-')
"#{owner.login_name}-#{name}".downcase.tr(' ', '-')
end
# featured plantings returns the most recent 4 plantings for a garden,
@@ -62,7 +63,7 @@ class Garden < ActiveRecord::Base
seen_crops = []
plantings.each do |p|
if (!seen_crops.include?(p.crop))
unless seen_crops.include?(p.crop)
unique_plantings.push(p)
seen_crops.push(p.crop)
end

View File

@@ -20,7 +20,8 @@ class Harvest < ActiveRecord::Base
validates :quantity,
numericality: {
only_integer: false,
greater_than_or_equal_to: 0 },
greater_than_or_equal_to: 0
},
allow_nil: true
UNITS_VALUES = {
@@ -34,7 +35,7 @@ class Harvest < ActiveRecord::Base
"buckets" => "bucket",
"baskets" => "basket",
"bushels" => "bushel"
}
}.freeze
validates :unit, inclusion: { in: UNITS_VALUES.values,
message: "%{value} is not a valid unit" },
allow_nil: true,
@@ -48,7 +49,7 @@ class Harvest < ActiveRecord::Base
"kg" => "kg",
"lb" => "lb",
"oz" => "oz"
}
}.freeze
validates :weight_unit, inclusion: { in: WEIGHT_UNITS_VALUES.values,
message: "%{value} is not a valid unit" },
allow_nil: true,
@@ -61,20 +62,20 @@ class Harvest < ActiveRecord::Base
# we're storing the harvest weight in kilograms in the db too
# to make data manipulation easier
def set_si_weight
return if self.weight_unit.nil?
weight_string = "#{self.weight_quantity} #{self.weight_unit}"
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
end
def cleanup_quantities
self.quantity = nil if quantity == 0
self.quantity = nil if quantity && quantity.zero?
self.unit = nil if quantity.blank?
self.weight_quantity = nil if weight_quantity == 0
self.weight_quantity = nil if weight_quantity && weight_quantity.zero?
self.weight_unit = nil if weight_quantity.blank?
end
def harvest_slug
"#{owner.login_name}-#{crop}".downcase.gsub(' ', '-')
"#{owner.login_name}-#{crop}".downcase.tr(' ', '-')
end
# stringify as "beet in Skud's backyard" or similar
@@ -82,28 +83,28 @@ class Harvest < ActiveRecord::Base
# 50 individual apples, weighing 3lb
# 2 buckets of apricots, weighing 10kg
string = ''
if self.quantity
string += "#{number_to_human(self.quantity.to_s, strip_insignificant_zeros: true)} "
string += if self.unit == 'individual'
if quantity
string += "#{number_to_human(quantity.to_s, strip_insignificant_zeros: true)} "
string += if unit == 'individual'
'individual '
elsif self.quantity == 1
"#{self.unit} of "
elsif quantity == 1
"#{unit} of "
else
"#{self.unit.pluralize} of "
"#{unit.pluralize} of "
end
end
string += if self.unit != 'individual' # buckets of apricot*s*
"#{self.crop.name.pluralize}"
elsif self.quantity == 1
"#{self.crop.name}"
string += if unit != 'individual' # buckets of apricot*s*
crop.name.pluralize.to_s
elsif quantity == 1
crop.name.to_s
else
"#{self.crop.name.pluralize}"
crop.name.pluralize.to_s
end
if self.weight_quantity
string += " weighing #{number_to_human(self.weight_quantity, strip_insignificant_zeros: true)}"\
" #{self.weight_unit}"
if weight_quantity
string += " weighing #{number_to_human(weight_quantity, strip_insignificant_zeros: true)}"\
" #{weight_unit}"
end
string

View File

@@ -14,7 +14,7 @@ class Member < ActiveRecord::Base
has_many :seeds, foreign_key: 'owner_id'
has_many :harvests, foreign_key: 'owner_id'
has_and_belongs_to_many :roles
has_and_belongs_to_many :roles # rubocop:disable Rails/HasAndBelongsToMany
has_many :notifications, foreign_key: 'recipient_id'
has_many :sent_notifications, foreign_key: 'sender_id'
@@ -57,8 +57,8 @@ class Member < ActiveRecord::Base
attr_accessor :login
# Requires acceptance of the Terms of Service
validates_acceptance_of :tos_agreement, allow_nil: true,
accept: true
validates :tos_agreement, acceptance: { allow_nil: true,
accept: true }
validates :login_name,
length: {
@@ -100,7 +100,7 @@ class Member < ActiveRecord::Base
login_name
end
def has_role?(role_sym)
def role?(role_sym)
roles.any? { |r| r.name.gsub(/\s+/, "_").underscore.to_sym == role_sym }
end
@@ -114,9 +114,7 @@ class Member < ActiveRecord::Base
# called by order.update_account, which loops through all order items
# and does this for each one.
def update_account_after_purchase(product)
if product.account_type
account.account_type = product.account_type
end
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
@@ -124,7 +122,7 @@ class Member < ActiveRecord::Base
account.save
end
def is_paid?
def paid?
if account.account_type.is_permanent_paid
true
elsif account.account_type.is_paid && account.paid_until >= Time.zone.now
@@ -176,7 +174,7 @@ class Member < ActiveRecord::Base
# Returns a hash of Flickr photosets' ids and titles
def flickr_sets
sets = Hash.new
sets = {}
flickr.photosets.getList.each do |p|
sets[p.title] = p.id
end
@@ -191,27 +189,25 @@ class Member < ActiveRecord::Base
false
end
def Member.login_name_or_email(login)
def self.login_name_or_email(login)
where(["lower(login_name) = :value OR lower(email) = :value", { value: login.downcase }])
end
def Member.case_insensitive_login_name(login)
def self.case_insensitive_login_name(login)
where(["lower(login_name) = :value", { value: login.downcase }])
end
def Member.interesting
def self.interesting
howmany = 12 # max number to find
interesting_members = []
Member.confirmed.located.recently_signed_in.each do |m|
break if interesting_members.size == howmany
if m.interesting?
interesting_members.push(m)
end
interesting_members.push(m) if m.interesting?
end
interesting_members
end
def Member.nearest_to(place)
def self.nearest_to(place)
nearby_members = []
if place
latitude, longitude = Geocoder.coordinates(place, params: { limit: 1 })
@@ -237,28 +233,26 @@ class Member < ActiveRecord::Base
end
def newsletter_subscribe(gb = Gibbon::API.new, testing = false)
return true if (Rails.env.test? && !testing)
gb.lists.subscribe({
id: Growstuff::Application.config.newsletter_list_id,
email: { email: email },
merge_vars: { login_name: login_name },
double_optin: false # they already confirmed their email with us
})
return true if Rails.env.test? && !testing
gb.lists.subscribe(
id: Growstuff::Application.config.newsletter_list_id,
email: { email: email },
merge_vars: { login_name: login_name },
double_optin: false # they already confirmed their email with us
)
end
def newsletter_unsubscribe(gb = Gibbon::API.new, testing = false)
return true if (Rails.env.test? && !testing)
gb.lists.unsubscribe({
id: Growstuff::Application.config.newsletter_list_id,
email: { email: email }
})
return true if Rails.env.test? && !testing
gb.lists.unsubscribe(id: Growstuff::Application.config.newsletter_list_id,
email: { email: email })
end
def already_following?(member)
self.follows.exists?(followed_id: member.id)
follows.exists?(followed_id: member.id)
end
def get_follow(member)
self.follows.find_by(followed_id: member.id) if already_following?(member)
follows.find_by(followed_id: member.id) if already_following?(member)
end
end

View File

@@ -13,14 +13,14 @@ class Notification < ActiveRecord::Base
after_create :send_email
def self.unread_count
self.unread.size
unread.size
end
def replace_blank_subject
self.subject = "(no subject)" if self.subject.nil? or self.subject =~ /^\s*$/
self.subject = "(no subject)" if subject.nil? || subject =~ /^\s*$/
end
def send_email
Notifier.notify(self).deliver_later if self.recipient.send_notification_email
Notifier.notify(self).deliver_later if recipient.send_notification_email
end
end

View File

@@ -17,7 +17,7 @@ class Order < ActiveRecord::Base
# total price of an order
def total
sum = 0
for i in order_items do
order_items.each do |i|
subtotal = i.price * i.quantity
sum += subtotal
end
@@ -28,11 +28,9 @@ class Order < ActiveRecord::Base
def activemerchant_items
items = []
order_items.each do |i|
items.push({
name: i.product.name,
quantity: i.quantity,
amount: i.price
})
items.push(name: i.product.name,
quantity: i.quantity,
amount: i.price)
end
items
end
@@ -42,7 +40,7 @@ class Order < ActiveRecord::Base
self.paypal_express_token = token
details = EXPRESS_GATEWAY.details_for(token)
self.paypal_express_payer_id = details.payer_id
self.save
save
end
# when an order is completed, we update the member's account to mark
@@ -56,35 +54,27 @@ class Order < ActiveRecord::Base
# 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
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 Order.search(args = {})
def self.search(args = {})
if args[:for]
case args[:by]
when "member"
member = Member.find_by(login_name: args[:for])
if member
return member.orders
end
return member.orders if member
when "order_id"
order = Order.find_by(id: args[:for])
if order
return [order]
end
return [order] if order
when "paypal_token"
order = Order.find_by(paypal_express_token: args[:for])
if order
return [order]
end
return [order] if order
when "paypal_payer_id"
order = Order.find_by(paypal_express_payer_id: args[:for])
if order
return [order]
end
return [order] if order
when "referral_code"
# coerce to uppercase
return Order.where(referral_code: args[:for].upcase)

View File

@@ -3,8 +3,7 @@ class OrderItem < ActiveRecord::Base
belongs_to :product
validate :price_must_be_greater_than_minimum
validates_uniqueness_of :order_id, message: "may only have one item."
validates :order_id, uniqueness: { message: "may only have one item." }
def price_must_be_greater_than_minimum
@product = Product.find(product_id)

View File

@@ -1,8 +1,9 @@
require_relative '../constants/photo_models.rb'
class Photo < ActiveRecord::Base
belongs_to :owner, class_name: 'Member'
Growstuff::Constants::PhotoModels.relations.each do |relation|
has_and_belongs_to_many relation.to_sym
has_and_belongs_to_many relation.to_sym # rubocop:disable Rails/HasAndBelongsToMany
end
before_destroy { all_associations.clear }
@@ -12,13 +13,13 @@ class Photo < ActiveRecord::Base
def all_associations
associations = []
Growstuff::Constants::PhotoModels.relations.each do |association_name|
associations << self.send(association_name.to_s).to_a
associations << send(association_name.to_s).to_a
end
associations.flatten!
end
def destroy_if_unused
self.destroy unless all_associations.size > 0
destroy if all_associations.empty?
end
# This is split into a side-effect free method and a side-effecting method
@@ -26,7 +27,7 @@ class Photo < ActiveRecord::Base
def flickr_metadata
flickr = owner.flickr
info = flickr.photos.getInfo(photo_id: flickr_photo_id)
licenses = flickr.photos.licenses.getInfo()
licenses = flickr.photos.licenses.getInfo
license = licenses.find { |l| l.id == info.license }
{
title: info.title || "Untitled",
@@ -39,6 +40,6 @@ class Photo < ActiveRecord::Base
end
def set_flickr_metadata
self.update_attributes(flickr_metadata)
update_attributes(flickr_metadata)
end
end

View File

@@ -64,17 +64,25 @@ class Planting < ActiveRecord::Base
end
def planting_slug
"#{owner.login_name}-#{garden}-#{crop}".downcase.gsub(' ', '-')
if garden.present? && crop.present?
"#{owner.login_name}-#{garden.name}-#{crop.name}"
elsif garden.present?
"#{owner.login_name}-#{garden.name}-null"
elsif crop.present?
"#{owner.login_name}-null-#{crop.name}"
else
"#{owner.login_name}-null-null"
end.downcase.gsub(' ', '-')
end
# location = garden owner + garden name, i.e. "Skud's backyard"
def location
"#{garden.owner.login_name}'s #{garden}"
I18n.t("gardens.location", garden: garden.name, owner: garden.owner.login_name)
end
# stringify as "beet in Skud's backyard" or similar
def to_s
self.crop_name + " in " + self.location
I18n.t('plantings.string', crop: crop.name, garden: garden.name, owner: owner)
end
def default_photo

View File

@@ -4,7 +4,7 @@ class Post < ActiveRecord::Base
belongs_to :author, class_name: 'Member'
belongs_to :forum
has_many :comments, dependent: :destroy
has_and_belongs_to_many :crops
has_and_belongs_to_many :crops # rubocop:disable Rails/HasAndBelongsToMany
before_destroy { |post| post.crops.clear }
after_save :update_crops_posts_association
# also has_many notifications, but kinda meaningless to get at them
@@ -12,27 +12,26 @@ class Post < ActiveRecord::Base
after_create do
recipients = []
sender = self.author.id
self.body.scan(Haml::Filters::GrowstuffMarkdown::MEMBER_REGEX) do |m|
sender = author.id
body.scan(Haml::Filters::GrowstuffMarkdown::MEMBER_REGEX) do |_m|
# find member case-insensitively and add to list of recipients
member = Member.case_insensitive_login_name($1).first
member = Member.case_insensitive_login_name(Regexp.last_match(1)).first
recipients << member if member && !recipients.include?(member)
end
self.body.scan(Haml::Filters::GrowstuffMarkdown::MEMBER_AT_REGEX) do |m|
body.scan(Haml::Filters::GrowstuffMarkdown::MEMBER_AT_REGEX) do |_m|
# find member case-insensitively and add to list of recipients
member = Member.case_insensitive_login_name($1[1..-1]).first
member = Member.case_insensitive_login_name(Regexp.last_match(1)[1..-1]).first
recipients << member if member && !recipients.include?(member)
end
# don't send notifications to yourself
recipients.map { |r| r.id }.each do |recipient|
if recipient != sender
Notification.create(
recipient_id: recipient,
sender_id: sender,
subject: "#{self.author} mentioned you in their post #{self.subject}",
body: self.body,
)
end
recipients.map(&:id).each do |recipient|
next unless recipient != sender
Notification.create(
recipient_id: recipient,
sender_id: sender,
subject: "#{author} mentioned you in their post #{subject}",
body: body
)
end
end
@@ -47,22 +46,22 @@ class Post < ActiveRecord::Base
def author_date_subject
# slugs are created before created_at is set
time = created_at || Time.zone.now
"#{author.login_name} #{time.strftime("%Y%m%d")} #{subject}"
"#{author.login_name} #{time.strftime('%Y%m%d')} #{subject}"
end
def comment_count
self.comments.size
comments.size
end
# return the timestamp of the most recent activity on this post
# i.e. the time of the most recent comment, or of the post itself if
# there are no comments.
def recent_activity
self.comments.present? ? self.comments.reorder('created_at DESC').first.created_at : self.created_at
comments.present? ? comments.reorder('created_at DESC').first.created_at : created_at
end
# return posts sorted by recent activity
def Post.recently_active
def self.recently_active
Post.all.sort do |a, b|
b.recent_activity <=> a.recent_activity
end
@@ -71,13 +70,13 @@ class Post < ActiveRecord::Base
private
def update_crops_posts_association
self.crops.destroy_all
crops.destroy_all
# look for crops mentioned in the post. eg. [tomato](crop)
self.body.scan(Haml::Filters::GrowstuffMarkdown::CROP_REGEX) do |m|
body.scan(Haml::Filters::GrowstuffMarkdown::CROP_REGEX) do |_m|
# find crop case-insensitively
crop = Crop.case_insensitive_name($1).first
crop = Crop.case_insensitive_name(Regexp.last_match(1)).first
# create association
self.crops << crop if crop && !self.crops.include?(crop)
crops << crop if crop && !crops.include?(crop)
end
end
end

View File

@@ -1,11 +1,12 @@
class Product < ActiveRecord::Base
has_and_belongs_to_many :orders
has_and_belongs_to_many :orders # rubocop:disable Rails/HasAndBelongsToMany
belongs_to :account_type
validates :paid_months,
numericality: {
only_integer: true,
greater_than_or_equal_to: 0 },
greater_than_or_equal_to: 0
},
allow_nil: true
def to_s

View File

@@ -2,7 +2,7 @@ class Role < ActiveRecord::Base
extend FriendlyId
friendly_id :name, use: [:slugged, :finders]
has_and_belongs_to_many :members
has_and_belongs_to_many :members # rubocop:disable Rails/HasAndBelongsToMany
class << self
[:crop_wranglers, :admins].each do |method|

View File

@@ -14,22 +14,25 @@ class Seed < ActiveRecord::Base
validates :quantity,
numericality: {
only_integer: true,
greater_than_or_equal_to: 0 },
greater_than_or_equal_to: 0
},
allow_nil: true
validates :days_until_maturity_min,
numericality: {
only_integer: true,
greater_than_or_equal_to: 0 },
greater_than_or_equal_to: 0
},
allow_nil: true
validates :days_until_maturity_max,
numericality: {
only_integer: true,
greater_than_or_equal_to: 0 },
greater_than_or_equal_to: 0
},
allow_nil: true
scope :tradable, -> { where("tradable_to != 'nowhere'") }
TRADABLE_TO_VALUES = %w(nowhere locally nationally internationally)
TRADABLE_TO_VALUES = %w(nowhere locally nationally internationally).freeze
validates :tradable_to, inclusion: { in: TRADABLE_TO_VALUES,
message: "You may only trade seed nowhere, "\
"locally, nationally, or internationally" },
@@ -40,7 +43,8 @@ class Seed < ActiveRecord::Base
'certified organic',
'non-certified organic',
'conventional/non-organic',
'unknown']
'unknown'
].freeze
validates :organic, inclusion: { in: ORGANIC_VALUES,
message: "You must say whether the seeds "\
"are organic or not, or that you don't know" },
@@ -51,21 +55,22 @@ class Seed < ActiveRecord::Base
'certified GMO-free',
'non-certified GMO-free',
'GMO',
'unknown']
'unknown'
].freeze
validates :gmo, inclusion: { in: GMO_VALUES,
message: "You must say whether the seeds are "\
"genetically modified or not, or that you don't know" },
allow_nil: false,
allow_blank: false
HEIRLOOM_VALUES = %w(heirloom hybrid unknown)
HEIRLOOM_VALUES = %w(heirloom hybrid unknown).freeze
validates :heirloom, inclusion: { in: HEIRLOOM_VALUES,
message: "You must say whether the seeds are heirloom, hybrid, or unknown" },
allow_nil: false,
allow_blank: false
def tradable?
if self.tradable_to == 'nowhere'
if tradable_to == 'nowhere'
false
else
true
@@ -81,21 +86,23 @@ class Seed < ActiveRecord::Base
# Seed.interesting
# returns a list of interesting seeds, for use on the homepage etc
def Seed.interesting
def self.interesting
howmany = 12 # max number to find
interesting_seeds = []
Seed.tradable.each do |s|
break if interesting_seeds.size == howmany
if s.interesting?
interesting_seeds.push(s)
end
interesting_seeds.push(s) if s.interesting?
end
interesting_seeds
end
def seed_slug
"#{owner.login_name}-#{crop}".downcase.gsub(' ', '-')
"#{owner.login_name}-#{crop}".downcase.tr(' ', '-')
end
def to_s
I18n.t('seeds.string', crop: crop.name, owner: owner)
end
end

View File

@@ -67,11 +67,11 @@
= link_to(t('.inbox_unread', unread_count: current_member.notifications.unread_count), notifications_path)
- else
= link_to(t('.inbox'), notifications_path)
- if current_member.has_role?(:crop_wrangler) || current_member.has_role?(:admin)
- if current_member.role?(:crop_wrangler) || current_member.role?(:admin)
%li{:class => 'divider', :role => 'presentation'}
- if current_member.has_role?(:crop_wrangler)
- if current_member.role?(:crop_wrangler)
%li= link_to t('.crop_wrangling'), wrangle_crops_path
- if current_member.has_role?(:admin)
- if current_member.role?(:admin)
%li= link_to t('.admin'), admin_path

View File

@@ -16,9 +16,9 @@
%p
%strong Member Roles:
%br
- if member.has_role? :admin
- if member.role? :admin
Administrator
- if member.has_role? :crop_wrangler
- if member.role? :crop_wrangler
Crop Wrangler
- else
Member

View File

@@ -10,7 +10,7 @@
- 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.is_paid?
- if @member == current_member && !@member.paid?
= link_to "Upgrade account", shop_path, :class => 'btn btn-default'
- if can? :create, Notification and current_member != @member
= link_to 'Send message', new_notification_path(:recipient_id => @member.id), :class => 'btn btn-default'

View File

@@ -22,7 +22,7 @@
%strong Referral code:
= @order.referral_code
- if current_member.has_role? :admin
- if current_member.role? :admin
%p
%strong Paypal Express token:
= @order.paypal_express_token

View File

@@ -26,19 +26,17 @@
%p= link_to 'Delete Photo', @photo, method: :delete, data: { confirm: 'Are you sure?' }, :class => 'btn btn-default btn-xs'
.col-md-6
- if @photo.plantings.size > 0 or @photo.harvests.size > 0 or @photo.gardens.size > 0
- unless @photo.plantings.empty? && @photo.harvests.empty? && @photo.gardens.empty? && @photo.seeds.empty?
%p This photo depicts:
%ul
- if @photo.plantings.size > 0
- @photo.plantings.each do |p|
%li= link_to t('.thing_by', thing: Planting.model_name.singular, owner: p.owner), p
- if @photo.harvests.size > 0
- @photo.harvests.each do |h|
%li= link_to t('.thing_by', thing: Harvest.model_name.singular, owner: h.owner), h
- if @photo.gardens.size > 0
- @photo.gardens.each do |g|
%li= link_to t('.thing_by', thing: Garden.model_name.singular, owner: g.owner), g
- @photo.plantings.each do |p|
%li= link_to t('.planting', planting: p.to_s, owner: p.owner.to_s), planting_path(p)
- @photo.harvests.each do |h|
%li= link_to t('.harvest', crop: h.crop.name, owner: h.owner.to_s), harvest_path(h)
- @photo.gardens.each do |g|
%li= link_to t('.garden', garden: g.to_s, owner: g.owner.to_s), garden_path(g)
- @photo.seeds.each do |s|
%li= link_to t('.seed', seed: s.to_s, owner: s.owner.to_s), seed_path(s)
.row
.col-md-12

View File

@@ -8,7 +8,7 @@
in
= succeed "'s" do
= link_to p.garden.owner, p.garden.owner
= link_to p.garden, p.garden
= link_to display_garden_name(p.garden), p.garden
%br/
%small
%i

View File

@@ -0,0 +1,22 @@
- content_for :buttonbar do
- if current_member
= link_to 'My Plantings', plantings_by_owner_path(owner: current_member.slug), class: 'btn btn-default'
- if owner && owner != current_member
= link_to "#{owner.login_name}'s Plantings", plantings_by_owner_path(owner: owner.slug), class: 'btn btn-default'
= link_to "Everyone's plantings", plantings_path, :class => 'btn btn-default'
- if owner
- path = plantings_by_owner_path(owner: @owner.slug, all: show_all ? '' : 1)
- else
- path = plantings_path(all: show_all ? '' : 1)
= link_to path do
= check_box_tag 'active', 'all', show_all
include in-active
- if current_member
- if can? :create, Planting
= link_to 'Plant something', new_planting_path, :class => 'btn btn-primary'
- else
= render :partial => 'shared/signin_signup', :locals => { :to => "track what you've planted" }

View File

@@ -1,21 +1,10 @@
- content_for :title, @owner ? t('.title.owner_plantings', owner: @owner) : @crop ? t('.title.crop_plantings', crop: @crop.name) : t('.title.default')
= render 'nav', owner: @owner, show_all: @show_all
- if @owner
= link_to "View #{@owner}'s profile >>", member_path(@owner)
%p
- if can? :create, Planting
- if @owner
%p
- if @owner == current_member
= link_to 'Plant something', new_planting_path, :class => 'btn btn-primary'
= link_to "View everyone's plantings", plantings_path, :class => 'btn btn-default'
- else # everyone's plantings
= link_to 'Plant something', new_planting_path, :class => 'btn btn-primary'
- if current_member
= link_to 'View your plantings', plantings_by_owner_path(:owner => current_member.slug), :class => 'btn btn-default'
- else
= render :partial => 'shared/signin_signup', :locals => { :to => "track what you've planted" }
%div.pagination
= page_entries_info @plantings
= will_paginate @plantings

View File

@@ -9,5 +9,5 @@
%strong Paid until:
= current_member.account.paid_until_string
- if !current_member.is_paid?
- if !current_member.paid?
= link_to "Upgrade and support #{ENV['GROWSTUFF_SITE_NAME']}", shop_path, :class => 'btn btn-primary'

View File

@@ -19,7 +19,7 @@
source, open data platform supporting home food growers and promoting
sustainable food systems!
- if current_member && current_member.is_paid?
- 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.

View File

@@ -95,7 +95,7 @@ end
module CmsDeviseAuth
def authenticate
return if current_member && current_member.has_role?(:admin)
return if current_member && current_member.role?(:admin)
redirect_to root_path, alert: 'Permission denied. Please sign in as an admin user to use the CMS admin area.'
end
end

View File

@@ -42,6 +42,7 @@ en:
index:
title: Forums
gardens:
location: "%{owner}'s %{garden}"
form:
location_helper: If you have a location set in your profile, it will be used when you create a new garden.
forums:
@@ -158,10 +159,15 @@ en:
photos:
show:
thing_by: A %{thing} by %{owner}
garden: "garden named \"%{garden}\" by %{owner}"
harvest: "%{crop} harvest by %{owner}"
planting: "%{planting}"
seed: "%{seed}"
places:
index:
title: "%{site_name} Community Map"
plantings:
string: "%{crop} planting in %{garden} by %{owner}"
form:
finish_helper: A planting is finished when you've harvested all of the crop, or it dies, or it's otherwise no longer growing in your garden.
index:
@@ -175,6 +181,7 @@ en:
author_posts: "%{author} posts"
default: Everyone's posts
seeds:
string: "%{crop} seeds belonging to %{owner}"
form:
trade_help: Are you interested in trading or swapping seeds with other %{site_name} members? If you list your seeds as available for trade, other members can contact you to request seeds. You can list any conditions or other information in the description, above.
index:

View File

@@ -14,7 +14,8 @@ feature "show photo page" do
scenario "shows linkback to planting" do
planting.photos << photo
visit photo_path(photo)
expect(page).to have_link "A planting by #{planting.owner}", href: planting_path(planting)
expect(page).to have_link "#{planting.crop.name} planting in #{planting.garden.name} by #{planting.owner}",
href: planting_path(planting)
end
end
@@ -24,7 +25,7 @@ feature "show photo page" do
scenario "shows linkback to harvest" do
harvest.photos << photo
visit photo_path(photo)
expect(page).to have_link "A harvest by #{harvest.owner}", href: harvest_path(harvest)
expect(page).to have_link "#{harvest.crop.name} harvest by #{harvest.owner}", href: harvest_path(harvest)
end
end
@@ -34,7 +35,17 @@ feature "show photo page" do
scenario "shows linkback to garden" do
garden.photos << photo
visit photo_path(photo)
expect(page).to have_link "A garden by #{garden.owner}", href: garden_path(garden)
expect(page).to have_link "garden named \"#{garden.name}\" by #{garden.owner}", href: garden_path(garden)
end
end
context "linked to seed" do
let(:seed) { create :seed }
scenario "shows linkback to seed" do
seed.photos << photo
visit photo_path(photo)
expect(page).to have_link "#{seed.crop.name} seeds belonging to #{seed.owner}", href: seed_path(seed)
end
end
end

View File

@@ -214,7 +214,12 @@ feature "Planting a crop", :js do
expect(page).to have_content "Planting was successfully created"
expect(page).to have_content "Finished: August 30, 2014"
# shouldn't be on the page
visit plantings_path
expect(page).not_to have_content "maize"
# show all plantings to see this finished planting
visit plantings_path(all: 1)
expect(page).to have_content "August 30, 2014"
end

View File

@@ -61,7 +61,7 @@ describe Ability do
end
it "has crop_wrangler role" do
member.has_role?(:crop_wrangler).should be true
member.role?(:crop_wrangler).should be true
end
it "can create crops" do
@@ -96,7 +96,7 @@ describe Ability do
end
it "has admin role" do
member.has_role?(:admin).should be true
member.role?(:admin).should be true
end
it "can read products" do
@@ -210,7 +210,7 @@ describe Ability do
end
it "has admin role" do
member.has_role?(:admin).should be true
member.role?(:admin).should be true
end
it "can read orders" do

View File

@@ -30,7 +30,7 @@ describe 'member' do
it "should have a default-type account by default" do
member.account.account_type.name.should eq Growstuff::Application.config.default_account_type
member.is_paid?.should be(false)
member.paid?.should be(false)
end
it "doesn't show email by default" do
@@ -194,19 +194,19 @@ describe 'member' do
it 'has a role' do
member.roles.first.should eq role
member.has_role?(:moderator).should eq true
member.role?(:moderator).should eq true
end
it 'sets up roles in factories' do
admin = FactoryGirl.create(:admin_member)
admin.has_role?(:admin).should eq true
admin.role?(:admin).should eq true
end
it 'converts role names properly' do
# need to make sure spaces get turned to underscores
role = FactoryGirl.create(:role, name: "a b c")
member.roles << role
member.has_role?(:a_b_c).should eq true
member.role?(:a_b_c).should eq true
end
end
@@ -305,7 +305,7 @@ describe 'member' do
account_type = FactoryGirl.create(:account_type,
is_paid: true, is_permanent_paid: true)
member.account.account_type = account_type
member.is_paid?.should be(true)
member.paid?.should be(true)
end
it "recognises a current paid account" do
@@ -313,7 +313,7 @@ describe 'member' do
is_paid: true, is_permanent_paid: false)
member.account.account_type = account_type
member.account.paid_until = Time.zone.now + 1.month
member.is_paid?.should be(true)
member.paid?.should be(true)
end
it "recognises an expired paid account" do
@@ -321,14 +321,14 @@ describe 'member' do
is_paid: true, is_permanent_paid: false)
member.account.account_type = account_type
member.account.paid_until = Time.zone.now - 1.minute
member.is_paid?.should be(false)
member.paid?.should be(false)
end
it "recognises a free account" do
account_type = FactoryGirl.create(:account_type,
is_paid: false, is_permanent_paid: false)
member.account.account_type = account_type
member.is_paid?.should be(false)
member.paid?.should be(false)
end
it "recognises a free account even with paid_until set" do
@@ -336,7 +336,7 @@ describe 'member' do
is_paid: false, is_permanent_paid: false)
member.account.account_type = account_type
member.account.paid_until = Time.zone.now + 1.month
member.is_paid?.should be(false)
member.paid?.should be(false)
end
end

View File

@@ -67,7 +67,7 @@ describe 'shop/index.html.haml', type: "view" do
end
it "recognises the paid member" do
@member.is_paid?.should be(true)
@member.paid?.should be(true)
end
it "tells you you have a paid membership" do