diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 03c4b3489..b803e561d 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -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' diff --git a/Gemfile.lock b/Gemfile.lock index 94d21b6c9..97d2c6b41 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -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 diff --git a/app/controllers/crops_controller.rb b/app/controllers/crops_controller.rb index 0b9d713a0..13324e09f 100644 --- a/app/controllers/crops_controller.rb +++ b/app/controllers/crops_controller.rb @@ -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 diff --git a/app/controllers/plantings_controller.rb b/app/controllers/plantings_controller.rb index 00b080946..3bba8b5a6 100644 --- a/app/controllers/plantings_controller.rb +++ b/app/controllers/plantings_controller.rb @@ -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 diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index cc461f1c3..968e71e33 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -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 diff --git a/app/models/ability.rb b/app/models/ability.rb index db4e4af9e..9920cbcf0 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -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 diff --git a/app/models/account.rb b/app/models/account.rb index 1dd914d62..646e9db78 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -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 diff --git a/app/models/comment.rb b/app/models/comment.rb index c1a49a2bb..f91c9cb42 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -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 diff --git a/app/models/crop.rb b/app/models/crop.rb index 48aa2bd6d..431e09b3a 100644 --- a/app/models/crop.rb +++ b/app/models/crop.rb @@ -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 don’t 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 diff --git a/app/models/follow.rb b/app/models/follow.rb index 733c4fb43..557887cb6 100644 --- a/app/models/follow.rb +++ b/app/models/follow.rb @@ -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 diff --git a/app/models/garden.rb b/app/models/garden.rb index 9771423f7..d4b132f54 100644 --- a/app/models/garden.rb +++ b/app/models/garden.rb @@ -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 diff --git a/app/models/harvest.rb b/app/models/harvest.rb index bb67ccbde..571157d2f 100644 --- a/app/models/harvest.rb +++ b/app/models/harvest.rb @@ -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 diff --git a/app/models/member.rb b/app/models/member.rb index 3965ff27e..ac9010a96 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -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 diff --git a/app/models/notification.rb b/app/models/notification.rb index 7061d7a18..4929a3bbc 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -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 diff --git a/app/models/order.rb b/app/models/order.rb index 9adb53fb0..c15979472 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -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) diff --git a/app/models/order_item.rb b/app/models/order_item.rb index ad85dc37c..380fbff58 100644 --- a/app/models/order_item.rb +++ b/app/models/order_item.rb @@ -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) diff --git a/app/models/photo.rb b/app/models/photo.rb index 5785ac6f0..d11c60a78 100644 --- a/app/models/photo.rb +++ b/app/models/photo.rb @@ -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 diff --git a/app/models/planting.rb b/app/models/planting.rb index 7838d1539..7f731b41e 100644 --- a/app/models/planting.rb +++ b/app/models/planting.rb @@ -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 diff --git a/app/models/post.rb b/app/models/post.rb index bca9bb696..1347f3313 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -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 diff --git a/app/models/product.rb b/app/models/product.rb index 8cab945a7..c2cbedbeb 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -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 diff --git a/app/models/role.rb b/app/models/role.rb index a3364fb89..98224062c 100644 --- a/app/models/role.rb +++ b/app/models/role.rb @@ -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| diff --git a/app/models/seed.rb b/app/models/seed.rb index 6f441964a..77afc7ea4 100644 --- a/app/models/seed.rb +++ b/app/models/seed.rb @@ -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 diff --git a/app/views/layouts/_header.html.haml b/app/views/layouts/_header.html.haml index 803d542f5..6b50c1845 100644 --- a/app/views/layouts/_header.html.haml +++ b/app/views/layouts/_header.html.haml @@ -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 diff --git a/app/views/members/_account.html.haml b/app/views/members/_account.html.haml index ae8333067..cda792ace 100644 --- a/app/views/members/_account.html.haml +++ b/app/views/members/_account.html.haml @@ -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 diff --git a/app/views/members/show.html.haml b/app/views/members/show.html.haml index 0e5a93c93..d1a76f699 100644 --- a/app/views/members/show.html.haml +++ b/app/views/members/show.html.haml @@ -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' diff --git a/app/views/orders/show.html.haml b/app/views/orders/show.html.haml index 29bd0f2bc..674a9ce3b 100644 --- a/app/views/orders/show.html.haml +++ b/app/views/orders/show.html.haml @@ -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 diff --git a/app/views/photos/show.html.haml b/app/views/photos/show.html.haml index 0ad731132..c3bdf967b 100644 --- a/app/views/photos/show.html.haml +++ b/app/views/photos/show.html.haml @@ -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 diff --git a/app/views/plantings/_list.html.haml b/app/views/plantings/_list.html.haml index 2ea1204ff..2bbf4046d 100644 --- a/app/views/plantings/_list.html.haml +++ b/app/views/plantings/_list.html.haml @@ -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 diff --git a/app/views/plantings/_nav.haml b/app/views/plantings/_nav.haml new file mode 100644 index 000000000..7d5efc729 --- /dev/null +++ b/app/views/plantings/_nav.haml @@ -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" } + diff --git a/app/views/plantings/index.html.haml b/app/views/plantings/index.html.haml index fca0d15b9..1311d4451 100644 --- a/app/views/plantings/index.html.haml +++ b/app/views/plantings/index.html.haml @@ -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 diff --git a/app/views/shared/_account_status.html.haml b/app/views/shared/_account_status.html.haml index 7c14f7d4a..2326eb5eb 100644 --- a/app/views/shared/_account_status.html.haml +++ b/app/views/shared/_account_status.html.haml @@ -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' diff --git a/app/views/shop/index.html.haml b/app/views/shop/index.html.haml index 1c8da326a..ef42e823b 100644 --- a/app/views/shop/index.html.haml +++ b/app/views/shop/index.html.haml @@ -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. diff --git a/config/initializers/comfortable_mexican_sofa.rb b/config/initializers/comfortable_mexican_sofa.rb index d3dd4a326..78794d93c 100644 --- a/config/initializers/comfortable_mexican_sofa.rb +++ b/config/initializers/comfortable_mexican_sofa.rb @@ -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 diff --git a/config/locales/en.yml b/config/locales/en.yml index a3e7fbb28..0c0fc66dd 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -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: diff --git a/spec/features/photos/show_photo_spec.rb b/spec/features/photos/show_photo_spec.rb index ea3a20f14..bac25b370 100644 --- a/spec/features/photos/show_photo_spec.rb +++ b/spec/features/photos/show_photo_spec.rb @@ -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 diff --git a/spec/features/plantings/planting_a_crop_spec.rb b/spec/features/plantings/planting_a_crop_spec.rb index affd691cb..2bb8e1a0e 100644 --- a/spec/features/plantings/planting_a_crop_spec.rb +++ b/spec/features/plantings/planting_a_crop_spec.rb @@ -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 diff --git a/spec/models/ability_spec.rb b/spec/models/ability_spec.rb index 4bb68c674..7a01114c0 100644 --- a/spec/models/ability_spec.rb +++ b/spec/models/ability_spec.rb @@ -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 diff --git a/spec/models/member_spec.rb b/spec/models/member_spec.rb index b23f0f882..4bdff9a8f 100644 --- a/spec/models/member_spec.rb +++ b/spec/models/member_spec.rb @@ -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 diff --git a/spec/views/shop/index_spec.rb b/spec/views/shop/index_spec.rb index 736168b63..54994def9 100644 --- a/spec/views/shop/index_spec.rb +++ b/spec/views/shop/index_spec.rb @@ -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