mirror of
https://github.com/Growstuff/growstuff.git
synced 2026-06-02 13:16:35 -04:00
2
Gemfile
2
Gemfile
@@ -14,6 +14,8 @@ gem 'cancan' # for checking member privileges
|
||||
|
||||
gem 'gibbon' # for Mailchimp newsletter subscriptions
|
||||
|
||||
gem 'csv_shaper' # CSV export
|
||||
|
||||
# vendored activemerchant for testing- needed for bogus paypal
|
||||
# gateway monkeypatch
|
||||
gem 'activemerchant', '1.33.0',
|
||||
|
||||
@@ -88,6 +88,8 @@ GEM
|
||||
rest-client
|
||||
simplecov (>= 0.7)
|
||||
thor
|
||||
csv_shaper (1.0.0)
|
||||
activesupport (>= 3.0.0)
|
||||
dalli (2.6.4)
|
||||
debugger (1.6.1)
|
||||
columnize (>= 0.3.1)
|
||||
@@ -260,6 +262,7 @@ DEPENDENCIES
|
||||
coffee-rails (~> 3.2.1)
|
||||
compass-rails (~> 1.0.3)
|
||||
coveralls
|
||||
csv_shaper
|
||||
dalli
|
||||
debugger
|
||||
devise
|
||||
|
||||
3
app/assets/javascripts/harvests.js.coffee
Normal file
3
app/assets/javascripts/harvests.js.coffee
Normal file
@@ -0,0 +1,3 @@
|
||||
# Place all the behaviors and hooks related to the matching controller here.
|
||||
# All this logic will automatically be available in application.js.
|
||||
# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/
|
||||
@@ -10,9 +10,17 @@ class CropsController < ApplicationController
|
||||
@crops = Crop.includes(:scientific_names, {:plantings => :photos}).paginate(:page => params[:page])
|
||||
|
||||
respond_to do |format|
|
||||
format.html # index.html.haml
|
||||
format.json { render json: @crops }
|
||||
format.rss { render :layout => false }
|
||||
format.html
|
||||
format.json { render :json => @crops }
|
||||
format.rss do
|
||||
@crops = Crop.recent.includes(:scientific_names, :creator)
|
||||
render :rss => @crops
|
||||
end
|
||||
format.csv do
|
||||
@filename = "Growstuff-Crops-#{Time.zone.now.to_s(:number)}.csv"
|
||||
@crops = Crop.includes(:scientific_names, :plantings, :seeds, :creator)
|
||||
render :csv => @crops
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
106
app/controllers/harvests_controller.rb
Normal file
106
app/controllers/harvests_controller.rb
Normal file
@@ -0,0 +1,106 @@
|
||||
class HarvestsController < ApplicationController
|
||||
|
||||
load_and_authorize_resource
|
||||
|
||||
# GET /harvests
|
||||
# GET /harvests.json
|
||||
def index
|
||||
@owner = Member.find_by_slug(params[:owner])
|
||||
if @owner
|
||||
@harvests = @owner.harvests.includes(:owner, :crop).paginate(:page => params[:page])
|
||||
else
|
||||
@harvests = Harvest.includes(:owner, :crop).paginate(:page => params[:page])
|
||||
end
|
||||
|
||||
respond_to do |format|
|
||||
format.html # index.html.erb
|
||||
format.json { render json: @harvests }
|
||||
format.csv do
|
||||
if @owner
|
||||
@filename = "Growstuff-#{@owner}-Harvests-#{Time.zone.now.to_s(:number)}.csv"
|
||||
@harvests = @owner.harvests.includes(:owner, :crop)
|
||||
else
|
||||
@filename = "Growstuff-Harvests-#{Time.zone.now.to_s(:number)}.csv"
|
||||
@harvests = Harvest.includes(:owner, :crop)
|
||||
end
|
||||
render :csv => @harvests
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# GET /harvests/1
|
||||
# GET /harvests/1.json
|
||||
def show
|
||||
@harvest = Harvest.find(params[:id])
|
||||
|
||||
respond_to do |format|
|
||||
format.html # show.html.erb
|
||||
format.json { render json: @harvest }
|
||||
end
|
||||
end
|
||||
|
||||
# GET /harvests/new
|
||||
# GET /harvests/new.json
|
||||
def new
|
||||
@harvest = Harvest.new('harvested_at' => Date.today)
|
||||
|
||||
# using find_by_id here because it returns nil, unlike find
|
||||
@crop = Crop.find_by_id(params[:crop_id]) || Crop.new
|
||||
|
||||
respond_to do |format|
|
||||
format.html # new.html.erb
|
||||
format.json { render json: @harvest }
|
||||
end
|
||||
end
|
||||
|
||||
# GET /harvests/1/edit
|
||||
def edit
|
||||
@harvest = Harvest.find(params[:id])
|
||||
end
|
||||
|
||||
# POST /harvests
|
||||
# POST /harvests.json
|
||||
def create
|
||||
params[:harvest][:owner_id] = current_member.id
|
||||
params[:harvested_at] = parse_date(params[:harvested_at])
|
||||
@harvest = Harvest.new(params[:harvest])
|
||||
|
||||
respond_to do |format|
|
||||
if @harvest.save
|
||||
format.html { redirect_to @harvest, notice: 'Harvest was successfully created.' }
|
||||
format.json { render json: @harvest, status: :created, location: @harvest }
|
||||
else
|
||||
format.html { render action: "new" }
|
||||
format.json { render json: @harvest.errors, status: :unprocessable_entity }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# PUT /harvests/1
|
||||
# PUT /harvests/1.json
|
||||
def update
|
||||
@harvest = Harvest.find(params[:id])
|
||||
|
||||
respond_to do |format|
|
||||
if @harvest.update_attributes(params[:harvest])
|
||||
format.html { redirect_to @harvest, notice: 'Harvest was successfully updated.' }
|
||||
format.json { head :no_content }
|
||||
else
|
||||
format.html { render action: "edit" }
|
||||
format.json { render json: @harvest.errors, status: :unprocessable_entity }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# DELETE /harvests/1
|
||||
# DELETE /harvests/1.json
|
||||
def destroy
|
||||
@harvest = Harvest.find(params[:id])
|
||||
@harvest.destroy
|
||||
|
||||
respond_to do |format|
|
||||
format.html { redirect_to harvests_url }
|
||||
format.json { head :no_content }
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -17,6 +17,16 @@ class PlantingsController < ApplicationController
|
||||
format.html # index.html.erb
|
||||
format.json { render json: @plantings }
|
||||
format.rss { render :layout => false } #index.rss.builder
|
||||
format.csv do
|
||||
if @owner
|
||||
@filename = "Growstuff-#{@owner}-Plantings-#{Time.zone.now.to_s(:number)}.csv"
|
||||
@plantings = @owner.plantings.includes(:owner, :crop, :garden)
|
||||
else
|
||||
@filename = "Growstuff-Plantings-#{Time.zone.now.to_s(:number)}.csv"
|
||||
@plantings = Planting.includes(:owner, :crop, :garden)
|
||||
end
|
||||
render :csv => @plantings
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -17,6 +17,16 @@ class SeedsController < ApplicationController
|
||||
format.html # index.html.erb
|
||||
format.json { render json: @seeds }
|
||||
format.rss { render :layout => false } #index.rss.builder
|
||||
format.csv do
|
||||
if @owner
|
||||
@filename = "Growstuff-#{@owner}-Seeds-#{Time.zone.now.to_s(:number)}.csv"
|
||||
@seeds = @owner.seeds.includes(:owner, :crop)
|
||||
else
|
||||
@filename = "Growstuff-Seeds-#{Time.zone.now.to_s(:number)}.csv"
|
||||
@seeds = Seed.includes(:owner, :crop)
|
||||
end
|
||||
render :csv => @seeds
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
40
app/helpers/harvests_helper.rb
Normal file
40
app/helpers/harvests_helper.rb
Normal file
@@ -0,0 +1,40 @@
|
||||
module HarvestsHelper
|
||||
|
||||
def display_quantity(harvest)
|
||||
human_quantity = display_human_quantity(harvest)
|
||||
weight = display_weight(harvest)
|
||||
|
||||
if human_quantity && weight
|
||||
return "#{human_quantity}, weighing #{weight}"
|
||||
elsif human_quantity
|
||||
return human_quantity
|
||||
elsif weight
|
||||
return weight
|
||||
else
|
||||
return 'not specified'
|
||||
end
|
||||
end
|
||||
|
||||
def display_human_quantity(harvest)
|
||||
if ! harvest.quantity.blank? && harvest.quantity > 0
|
||||
if harvest.unit == 'individual' # just the number
|
||||
number_to_human(harvest.quantity, :strip_insignificant_zeros => true)
|
||||
elsif ! harvest.unit.blank? # pluralize anything else
|
||||
return pluralize(number_to_human(harvest.quantity, :strip_insignificant_zeros => true), harvest.unit)
|
||||
else
|
||||
return "#{number_to_human(harvest.quantity, :strip_insignificant_zeros => true)} #{harvest.unit}"
|
||||
end
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
def display_weight(harvest)
|
||||
if ! harvest.weight_quantity.blank? && harvest.weight_quantity > 0
|
||||
return "#{number_to_human(harvest.weight_quantity, :strip_insignificant_zeros => true)} #{harvest.weight_unit}"
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -64,6 +64,10 @@ class Ability
|
||||
can :update, Planting, :garden => { :owner_id => member.id }
|
||||
can :destroy, Planting, :garden => { :owner_id => member.id }
|
||||
|
||||
can :create, Harvest
|
||||
can :update, Harvest, :owner_id => member.id
|
||||
can :destroy, Harvest, :owner_id => member.id
|
||||
|
||||
can :create, Photo
|
||||
can :update, Photo, :owner_id => member.id
|
||||
can :destroy, Photo, :owner_id => member.id
|
||||
|
||||
@@ -7,6 +7,7 @@ class Crop < ActiveRecord::Base
|
||||
has_many :plantings
|
||||
has_many :photos, :through => :plantings
|
||||
has_many :seeds
|
||||
has_many :harvests
|
||||
belongs_to :creator, :class_name => 'Member'
|
||||
|
||||
belongs_to :parent, :class_name => 'Crop'
|
||||
|
||||
69
app/models/harvest.rb
Normal file
69
app/models/harvest.rb
Normal file
@@ -0,0 +1,69 @@
|
||||
class Harvest < ActiveRecord::Base
|
||||
extend FriendlyId
|
||||
friendly_id :harvest_slug, use: :slugged
|
||||
|
||||
attr_accessible :crop_id, :harvested_at, :description, :owner_id,
|
||||
:quantity, :unit, :weight_quantity, :weight_unit, :slug
|
||||
|
||||
belongs_to :crop
|
||||
belongs_to :owner, :class_name => 'Member'
|
||||
|
||||
validates :quantity,
|
||||
:numericality => { :only_integer => false },
|
||||
:allow_nil => true
|
||||
|
||||
UNITS_VALUES = {
|
||||
"individual" => "individual",
|
||||
"bunches" => "bunch",
|
||||
"sprigs" => "sprig",
|
||||
"handfuls" => "handful",
|
||||
"litres" => "litre",
|
||||
"pints" => "ping",
|
||||
"quarts" => "quart",
|
||||
"buckets" => "bucket",
|
||||
"baskets" => "basket",
|
||||
"bushels" => "bushel"
|
||||
}
|
||||
validates :unit, :inclusion => { :in => UNITS_VALUES.values,
|
||||
:message => "%{value} is not a valid unit" },
|
||||
:allow_nil => true,
|
||||
:allow_blank => true
|
||||
|
||||
validates :weight_quantity,
|
||||
:numericality => { :only_integer => false },
|
||||
:allow_nil => true
|
||||
|
||||
WEIGHT_UNITS_VALUES = {
|
||||
"kg" => "kg",
|
||||
"lb" => "lb"
|
||||
}
|
||||
validates :weight_unit, :inclusion => { :in => WEIGHT_UNITS_VALUES.values,
|
||||
:message => "%{value} is not a valid unit" },
|
||||
:allow_nil => true,
|
||||
:allow_blank => true
|
||||
|
||||
after_validation :cleanup_quantities
|
||||
|
||||
def cleanup_quantities
|
||||
if quantity == 0
|
||||
self.quantity = nil
|
||||
end
|
||||
|
||||
if quantity.blank?
|
||||
self.unit = nil
|
||||
end
|
||||
|
||||
if weight_quantity == 0
|
||||
self.weight_quantity = nil
|
||||
end
|
||||
|
||||
if weight_quantity.blank?
|
||||
self.weight_unit = nil
|
||||
end
|
||||
end
|
||||
|
||||
def harvest_slug
|
||||
"#{owner.login_name}-#{crop}".downcase.gsub(' ', '-')
|
||||
end
|
||||
|
||||
end
|
||||
@@ -10,6 +10,7 @@ class Member < ActiveRecord::Base
|
||||
has_many :plantings, :foreign_key => 'owner_id'
|
||||
|
||||
has_many :seeds, :foreign_key => 'owner_id'
|
||||
has_many :harvests, :foreign_key => 'owner_id'
|
||||
|
||||
has_and_belongs_to_many :roles
|
||||
|
||||
|
||||
83
app/views/crops/index.csv.shaper
Normal file
83
app/views/crops/index.csv.shaper
Normal file
@@ -0,0 +1,83 @@
|
||||
csv.headers :id, :system_name,
|
||||
:growstuff_url, :en_wikipedia_url,
|
||||
:default_scientific_name,
|
||||
:scientific_name_count,
|
||||
:parent_crop_id, :parent_crop_name,
|
||||
:plantings_count,
|
||||
:seeds_count,
|
||||
:recommended_sunniness,
|
||||
:planted_in_sun,
|
||||
:planted_in_semi_shade,
|
||||
:planted_in_shade,
|
||||
:plant_from_recommendation,
|
||||
:planted_from_seed,
|
||||
:planted_from_seedling,
|
||||
:planted_from_cutting,
|
||||
:planted_from_root_division,
|
||||
:planted_from_runner,
|
||||
:planted_from_bulb,
|
||||
:planted_from_bare_root_plant,
|
||||
:planted_from_advanced_plant,
|
||||
:planted_from_graft,
|
||||
:planted_from_layering,
|
||||
:added_by_member_id,
|
||||
:added_by_member_name,
|
||||
:date_added,
|
||||
:last_modified,
|
||||
:license
|
||||
|
||||
@crops.each do |c|
|
||||
csv.row c do |csv, crop|
|
||||
|
||||
|
||||
csv.cells :id, :system_name, :en_wikipedia_url
|
||||
csv.cell :growstuff_url, crop_url(c)
|
||||
|
||||
if c.scientific_names.any?
|
||||
csv.cell :default_scientific_name, c.default_scientific_name
|
||||
csv.cell :scientific_name_count, c.scientific_names.count
|
||||
end
|
||||
|
||||
if c.parent
|
||||
csv.cell :parent_crop_id, c.parent.id
|
||||
csv.cell :parent_crop_name, c.parent.system_name
|
||||
end
|
||||
|
||||
csv.cell :plantings_count || 0
|
||||
csv.cell :seeds_count, c.seeds.count
|
||||
|
||||
sunniness = c.sunniness
|
||||
sunniness_rec = sunniness.max_by{|k,v| v}
|
||||
if sunniness_rec
|
||||
csv.cell :recommended_sunniness, sunniness_rec[0]
|
||||
end
|
||||
csv.cell :planted_in_sun, sunniness['sun']
|
||||
csv.cell :planted_in_semi_shade, sunniness['semi_shade']
|
||||
csv.cell :planted_in_shade, sunniness['shade']
|
||||
|
||||
planted_from = c.planted_from
|
||||
planted_from_rec = planted_from.max_by{|k,v| v}
|
||||
if planted_from_rec
|
||||
csv.cell :plant_from_recommendation, planted_from_rec[0]
|
||||
end
|
||||
|
||||
csv.cell :planted_from_seed, planted_from['seed']
|
||||
csv.cell :planted_from_seedling, planted_from['seedling']
|
||||
csv.cell :planted_from_cutting, planted_from['cutting']
|
||||
csv.cell :planted_from_root_division, planted_from['root division']
|
||||
csv.cell :planted_from_runner, planted_from['runner']
|
||||
csv.cell :planted_from_bulb, planted_from['bulb']
|
||||
csv.cell :planted_from_bare_root_plant, planted_from['bare root plant']
|
||||
csv.cell :planted_from_advanced_plant, planted_from['advanced plant']
|
||||
csv.cell :planted_from_graft, planted_from['graft']
|
||||
csv.cell :planted_from_layering, planted_from['layering']
|
||||
|
||||
csv.cell :added_by_member_id, c.creator.id
|
||||
csv.cell :added_by_member_name, c.creator.to_s
|
||||
csv.cell :date_added, c.created_at.to_s(:db)
|
||||
csv.cell :last_modified, c.updated_at.to_s(:db)
|
||||
|
||||
csv.cell :license, "CC-BY-SA Growstuff http://growstuff.org/"
|
||||
|
||||
end
|
||||
end
|
||||
@@ -22,3 +22,8 @@
|
||||
= page_entries_info @crops, :model => "crops"
|
||||
= will_paginate @crops
|
||||
|
||||
|
||||
%ul.inline
|
||||
%li The data on this page is available in the following formats:
|
||||
%li= link_to "CSV", crops_path(:format => 'csv')
|
||||
%li= link_to "JSON", crops_path(:format => 'json')
|
||||
|
||||
@@ -22,6 +22,9 @@
|
||||
- else
|
||||
= render :partial => 'shared/signin_signup', :locals => { :to => 'plant this crop' }
|
||||
|
||||
- if can? :create, Harvest
|
||||
= link_to "Harvest this", new_harvest_path(:crop_id => @crop.id), :class => 'btn btn-primary'
|
||||
|
||||
- if can? :create, Seed
|
||||
= link_to 'Add seeds to stash', new_seed_path(:params => { :crop_id => @crop.id }), :class => 'btn btn-primary'
|
||||
|
||||
|
||||
39
app/views/harvests/_form.html.haml
Normal file
39
app/views/harvests/_form.html.haml
Normal file
@@ -0,0 +1,39 @@
|
||||
= form_for(@harvest, :html => {:class => "form-horizontal"}) do |f|
|
||||
- if @harvest.errors.any?
|
||||
#error_explanation
|
||||
%h2= "#{pluralize(@harvest.errors.count, "error")} prohibited this harvest from being saved:"
|
||||
%ul
|
||||
- @harvest.errors.full_messages.each do |msg|
|
||||
%li= msg
|
||||
|
||||
.control-group
|
||||
= f.label 'What did you harvest?', :class => 'control-label'
|
||||
.controls
|
||||
= collection_select(:harvest, :crop_id, Crop.all, :id, :system_name, :selected => @harvest.crop_id || @crop.id)
|
||||
%span.help-inline
|
||||
Can't find what you're looking for?
|
||||
= link_to "Request new crops.", Growstuff::Application.config.new_crops_request_link
|
||||
|
||||
.control-group
|
||||
= f.label 'When?', :class => 'control-label'
|
||||
.controls= f.text_field :harvested_at, :value => @harvest.harvested_at ? @harvest.harvested_at.to_s(:ymd) : '', :class => 'add-datepicker'
|
||||
|
||||
.control-group
|
||||
= f.label 'How many?', :class => 'control-label'
|
||||
.controls
|
||||
= f.number_field :quantity, :class => 'input-small'
|
||||
= f.select(:unit, Harvest::UNITS_VALUES, {:include_blank => false}, :class => 'input-medium')
|
||||
|
||||
.control-group
|
||||
= f.label 'Weighing:', :class => 'control-label'
|
||||
.controls
|
||||
= f.number_field :weight_quantity, :class => 'input-small'
|
||||
= f.select(:weight_unit, Harvest::WEIGHT_UNITS_VALUES, {:include_blank => false}, :class => 'input-medium')
|
||||
in total
|
||||
.control-group
|
||||
= f.label 'Notes', :class => 'control-label'
|
||||
.controls= f.text_area :description, :rows => 6
|
||||
|
||||
.form-actions
|
||||
= f.submit 'Save', :class => 'btn btn-primary'
|
||||
|
||||
7
app/views/harvests/edit.html.haml
Normal file
7
app/views/harvests/edit.html.haml
Normal file
@@ -0,0 +1,7 @@
|
||||
- content_for :title, "Editing harvest"
|
||||
|
||||
= render 'form'
|
||||
|
||||
= link_to 'Show', @harvest
|
||||
\|
|
||||
= link_to 'Back', harvests_path
|
||||
41
app/views/harvests/index.csv.shaper
Normal file
41
app/views/harvests/index.csv.shaper
Normal file
@@ -0,0 +1,41 @@
|
||||
csv.headers :id,
|
||||
:growstuff_url,
|
||||
:owner_id,
|
||||
:owner_name,
|
||||
:crop_id,
|
||||
:crop_name,
|
||||
:quantity,
|
||||
:unit,
|
||||
:weight_quantity,
|
||||
:weight_unit,
|
||||
:date_harvested,
|
||||
:description,
|
||||
:date_added,
|
||||
:last_modified,
|
||||
:license
|
||||
|
||||
@harvests.each do |h|
|
||||
csv.row h do |csv, harvest|
|
||||
|
||||
csv.cell :id
|
||||
csv.cell :growstuff_url, harvest_url(h)
|
||||
|
||||
csv.cell :owner_id, h.owner.id
|
||||
csv.cell :owner_name, h.owner.to_s
|
||||
|
||||
csv.cell :crop_id, h.crop.id
|
||||
csv.cell :crop_name, h.crop.to_s
|
||||
|
||||
csv.cells :quantity, :unit, :weight_quantity, :weight_unit
|
||||
|
||||
csv.cell :date_harvested, h.created_at.to_s(:db)
|
||||
|
||||
csv.cell :description
|
||||
|
||||
csv.cell :date_added, h.created_at.to_s(:db)
|
||||
csv.cell :last_modified, h.updated_at.to_s(:db)
|
||||
|
||||
csv.cell :license, "CC-BY-SA Growstuff http://growstuff.org/"
|
||||
|
||||
end
|
||||
end
|
||||
60
app/views/harvests/index.html.haml
Normal file
60
app/views/harvests/index.html.haml
Normal file
@@ -0,0 +1,60 @@
|
||||
- content_for :title, @owner ? "#{@owner}'s harvests" : "Everyone's harvests"
|
||||
|
||||
%p
|
||||
#{Growstuff::Application.config.site_name} helps you track what you're
|
||||
harvesting from your home garden and see how productive it is.
|
||||
|
||||
%p
|
||||
- if can? :create, Harvest
|
||||
- if @owner
|
||||
%p
|
||||
- if @owner == current_member
|
||||
= link_to 'Add harvest', new_harvest_path, :class => 'btn btn-primary'
|
||||
= link_to "View everyone's harvests", harvests_path, :class => 'btn'
|
||||
- else # everyone's harvests
|
||||
= link_to 'Add harvest', new_harvest_path, :class => 'btn btn-primary'
|
||||
- if current_member
|
||||
= link_to 'View your harvests', harvests_by_owner_path(:owner => current_member.slug), :class => 'btn'
|
||||
- else
|
||||
= render :partial => 'shared/signin_signup', :locals => { :to => 'track your harvests' }
|
||||
|
||||
%div.pagination
|
||||
= page_entries_info @harvests, :model => "harvests"
|
||||
= will_paginate @harvests
|
||||
|
||||
- if @harvests.length > 0
|
||||
|
||||
%table.table.table-striped
|
||||
%tr
|
||||
- unless @owner
|
||||
%th Owner
|
||||
%th Crop
|
||||
%th Date
|
||||
%th Quantity
|
||||
%th Description
|
||||
%th
|
||||
|
||||
- @harvests.each do |harvest|
|
||||
%tr
|
||||
- unless @owner
|
||||
%td= link_to harvest.owner.login_name, harvest.owner
|
||||
%td= link_to harvest.crop.system_name, harvest.crop
|
||||
%td= harvest.harvested_at
|
||||
%td
|
||||
- if harvest.quantity
|
||||
= display_quantity(harvest)
|
||||
%td= harvest.description
|
||||
%td= link_to 'Details', harvest, :class => 'btn btn-mini'
|
||||
|
||||
%div.pagination
|
||||
= page_entries_info @harvests, :model => "harvests"
|
||||
= will_paginate @harvests
|
||||
|
||||
%ul.inline
|
||||
%li The data on this page is available in the following formats:
|
||||
- if @owner
|
||||
%li= link_to "CSV", harvests_by_owner_path(@owner, :format => 'csv')
|
||||
%li= link_to "JSON", harvests_by_owner_path(@owner, :format => 'json')
|
||||
- else
|
||||
%li= link_to "CSV", harvests_path(:format => 'csv')
|
||||
%li= link_to "JSON", harvests_path(:format => 'json')
|
||||
3
app/views/harvests/new.html.haml
Normal file
3
app/views/harvests/new.html.haml
Normal file
@@ -0,0 +1,3 @@
|
||||
- content_for :title, "New Harvest"
|
||||
|
||||
= render 'form'
|
||||
30
app/views/harvests/show.html.haml
Normal file
30
app/views/harvests/show.html.haml
Normal file
@@ -0,0 +1,30 @@
|
||||
=content_for :title, "#{@harvest.crop} harvested by #{@harvest.owner}"
|
||||
|
||||
.row-fluid
|
||||
.span6
|
||||
%p
|
||||
%b Owner:
|
||||
= link_to @harvest.owner, @harvest.owner
|
||||
—
|
||||
= link_to "view all #{@harvest.owner}'s harvests", harvests_by_owner_path(:owner => @harvest.owner.slug)
|
||||
%p
|
||||
%b Harvested:
|
||||
= @harvest.harvested_at ? @harvest.harvested_at : "not specified"
|
||||
%p
|
||||
%b Quantity:
|
||||
= display_quantity(@harvest)
|
||||
|
||||
- if can? :edit, @harvest or can? :destroy, @harvest
|
||||
%p
|
||||
- if can? :edit, @harvest
|
||||
=link_to 'Edit', edit_harvest_path(@harvest), :class => 'btn btn-mini'
|
||||
- if can? :destroy, @harvest
|
||||
=link_to 'Delete', @harvest, method: :delete, data: { confirm: 'Are you sure?' }, :class => 'btn btn-mini'
|
||||
|
||||
.span6
|
||||
= render :partial => "crops/index_card", :locals => { :crop => @harvest.crop}
|
||||
|
||||
%h2 Notes
|
||||
|
||||
:markdown
|
||||
#{ @harvest.description != "" ? @harvest.description : "No description given." }
|
||||
@@ -7,13 +7,13 @@
|
||||
= Growstuff::Application.config.site_name
|
||||
= current_member
|
||||
= render :partial => 'stats'
|
||||
%ul.inline
|
||||
%li{ :style => 'padding-left: 0px' }
|
||||
%strong Quick links:
|
||||
%li= link_to "Plant something", new_planting_path
|
||||
%li= link_to "Add seeds", new_seed_path
|
||||
%li= link_to "Post", new_post_path
|
||||
%li= link_to "Edit profile", edit_member_registration_path
|
||||
%p
|
||||
.btn-group
|
||||
= link_to "Plant", new_planting_path, :class => 'btn'
|
||||
= link_to "Harvest", new_harvest_path, :class => 'btn'
|
||||
= link_to "Add seeds", new_seed_path, :class => 'btn'
|
||||
= link_to "Post", new_post_path, :class => 'btn'
|
||||
= link_to "Edit profile", edit_member_registration_path, :class => 'btn'
|
||||
|
||||
- else
|
||||
.visible-desktop.visible-tablet
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
%li= link_to "Profile", member_path(current_member)
|
||||
%li= link_to "Gardens", gardens_by_owner_path(:owner => current_member.slug)
|
||||
%li= link_to "Plantings", plantings_by_owner_path(:owner => current_member.slug)
|
||||
%li= link_to "Harvests", harvests_by_owner_path(:owner => current_member.slug)
|
||||
%li= link_to "Seeds", seeds_by_owner_path(:owner => current_member.slug)
|
||||
%li= link_to "Posts", posts_by_author_path(:author => current_member.slug)
|
||||
%li= link_to "Account", orders_path
|
||||
|
||||
45
app/views/plantings/index.csv.shaper
Normal file
45
app/views/plantings/index.csv.shaper
Normal file
@@ -0,0 +1,45 @@
|
||||
csv.headers :id,
|
||||
:growstuff_url,
|
||||
:owner_id,
|
||||
:owner_name,
|
||||
:garden_id,
|
||||
:garden_name,
|
||||
:crop_id,
|
||||
:crop_name,
|
||||
:quantity,
|
||||
:planted_from,
|
||||
:sunniness,
|
||||
:date_planted,
|
||||
:description,
|
||||
:date_added,
|
||||
:last_modified,
|
||||
:license
|
||||
|
||||
@plantings.each do |p|
|
||||
csv.row p do |csv, planting|
|
||||
|
||||
csv.cell :id
|
||||
csv.cell :growstuff_url, planting_url(p)
|
||||
|
||||
csv.cell :owner_id, p.owner.id
|
||||
csv.cell :owner_name, p.owner.to_s
|
||||
|
||||
csv.cell :garden_id, p.garden.id
|
||||
csv.cell :garden_name, p.garden.to_s
|
||||
|
||||
csv.cell :crop_id, p.crop.id
|
||||
csv.cell :crop_name, p.crop.to_s
|
||||
|
||||
csv.cells :quantity, :planted_from, :sunniness
|
||||
|
||||
csv.cell :date_planted, p.planted_at ? p.planted_at.to_s(:db) : ''
|
||||
|
||||
csv.cell :description
|
||||
|
||||
csv.cell :date_added, p.created_at.to_s(:db)
|
||||
csv.cell :last_modified, p.updated_at.to_s(:db)
|
||||
|
||||
csv.cell :license, "CC-BY-SA Growstuff http://growstuff.org/"
|
||||
|
||||
end
|
||||
end
|
||||
@@ -51,3 +51,14 @@
|
||||
%div.pagination
|
||||
= page_entries_info @plantings, :model => "plantings"
|
||||
= will_paginate @plantings
|
||||
|
||||
%ul.inline
|
||||
%li The data on this page is available in the following formats:
|
||||
- if @owner
|
||||
%li= link_to "CSV", plantings_by_owner_path(@owner, :format => 'csv')
|
||||
%li= link_to "JSON", plantings_by_owner_path(@owner, :format => 'json')
|
||||
%li= link_to "RSS", plantings_by_owner_path(@owner, :format => 'rss')
|
||||
- else
|
||||
%li= link_to "CSV", plantings_path(:format => 'csv')
|
||||
%li= link_to "JSON", plantings_path(:format => 'json')
|
||||
%li= link_to "RSS", plantings_path(:format => 'rss')
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
|
||||
.row-fluid
|
||||
.span6
|
||||
%p
|
||||
%b Owner:
|
||||
= link_to @planting.owner, @planting.owner
|
||||
—
|
||||
= link_to "view all #{@planting.owner}'s plantings", plantings_by_owner_path(:owner => @planting.owner.slug)
|
||||
%p
|
||||
%b Planted:
|
||||
= @planting.planted_at ? @planting.planted_at : "not specified"
|
||||
@@ -41,9 +46,6 @@
|
||||
:markdown
|
||||
#{ @planting.description != "" ? @planting.description : "No description given." }
|
||||
|
||||
- if can? :edit, @planting
|
||||
= link_to 'Edit', edit_planting_path(@planting), :class => 'btn btn-mini'
|
||||
|
||||
- if @planting.photos.count > 0 or (can? :edit, @planting and can? :create, Photo)
|
||||
%h2 Pictures
|
||||
|
||||
|
||||
47
app/views/seeds/index.csv.shaper
Normal file
47
app/views/seeds/index.csv.shaper
Normal file
@@ -0,0 +1,47 @@
|
||||
csv.headers :id,
|
||||
:growstuff_url,
|
||||
:owner_id,
|
||||
:owner_name,
|
||||
:crop_id,
|
||||
:crop_name,
|
||||
:quantity,
|
||||
:plant_before,
|
||||
:tradable_to,
|
||||
:from_location,
|
||||
:latitude,
|
||||
:longitude,
|
||||
:description,
|
||||
:date_added,
|
||||
:last_modified,
|
||||
:license
|
||||
|
||||
@seeds.each do |s|
|
||||
csv.row s do |csv, seed|
|
||||
|
||||
csv.cell :id
|
||||
csv.cell :growstuff_url, seed_url(s)
|
||||
|
||||
csv.cell :owner_id, s.owner.id
|
||||
csv.cell :owner_name, s.owner.to_s
|
||||
|
||||
csv.cell :crop_id, s.crop.id
|
||||
csv.cell :crop_name, s.crop.to_s
|
||||
|
||||
csv.cell :quantity
|
||||
|
||||
csv.cell :plant_before, s.plant_before ? s.plant_before.to_s(:db) : ''
|
||||
|
||||
csv.cell :tradable_to
|
||||
csv.cell :from_location, s.owner.location
|
||||
csv.cell :latitude, s.owner.latitude
|
||||
csv.cell :longitude, s.owner.longitude
|
||||
|
||||
csv.cell :description
|
||||
|
||||
csv.cell :date_added, s.created_at.to_s(:db)
|
||||
csv.cell :last_modified, s.updated_at.to_s(:db)
|
||||
|
||||
csv.cell :license, "CC-BY-SA Growstuff http://growstuff.org/"
|
||||
|
||||
end
|
||||
end
|
||||
@@ -56,3 +56,14 @@
|
||||
%div.pagination
|
||||
= page_entries_info @seeds, :model => "seeds"
|
||||
= will_paginate @seeds
|
||||
|
||||
%ul.inline
|
||||
%li The data on this page is available in the following formats:
|
||||
- if @owner
|
||||
%li= link_to "CSV", seeds_by_owner_path(@owner, :format => 'csv')
|
||||
%li= link_to "JSON", seeds_by_owner_path(@owner, :format => 'json')
|
||||
%li= link_to "RSS", seeds_by_owner_path(@owner, :format => 'rss')
|
||||
- else
|
||||
%li= link_to "CSV", seeds_path(:format => 'csv')
|
||||
%li= link_to "JSON", seeds_path(:format => 'json')
|
||||
%li= link_to "RSS", seeds_path(:format => 'rss')
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
%b Owner:
|
||||
= link_to @seed.owner, @seed.owner
|
||||
—
|
||||
= link_to "view all #{@seed.owner}'s seeds", seeds_path(:owner_id => @seed.owner.id)
|
||||
= link_to "view all #{@seed.owner}'s seeds", seeds_by_owner_path(:owner => @seed.owner.slug)
|
||||
%p
|
||||
%b Quantity:
|
||||
= @seed.quantity.blank? ? "not specified" : @seed.quantity
|
||||
|
||||
@@ -16,6 +16,9 @@ Growstuff::Application.routes.draw do
|
||||
resources :seeds
|
||||
match '/seeds/owner/:owner' => 'seeds#index', :as => 'seeds_by_owner'
|
||||
|
||||
resources :harvests
|
||||
match '/harvests/owner/:owner' => 'harvests#index', :as => 'harvests_by_owner'
|
||||
|
||||
resources :posts
|
||||
match '/posts/author/:author' => 'posts#index', :as => 'posts_by_author'
|
||||
|
||||
|
||||
14
db/migrate/20130917053547_create_harvests.rb
Normal file
14
db/migrate/20130917053547_create_harvests.rb
Normal file
@@ -0,0 +1,14 @@
|
||||
class CreateHarvests < ActiveRecord::Migration
|
||||
def change
|
||||
create_table :harvests do |t|
|
||||
t.integer :crop_id, :null => false
|
||||
t.integer :owner_id, :null => false
|
||||
t.date :harvested_at
|
||||
t.decimal :quantity
|
||||
t.string :units
|
||||
t.text :notes
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,5 @@
|
||||
class ChangeHarvestNotesToDescription < ActiveRecord::Migration
|
||||
def change
|
||||
rename_column :harvests, :notes, :description
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,5 @@
|
||||
class ChangeHarvestUnitsToUnit < ActiveRecord::Migration
|
||||
def change
|
||||
rename_column :harvests, :units, :unit
|
||||
end
|
||||
end
|
||||
5
db/migrate/20130917075803_add_slug_to_harvests.rb
Normal file
5
db/migrate/20130917075803_add_slug_to_harvests.rb
Normal file
@@ -0,0 +1,5 @@
|
||||
class AddSlugToHarvests < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :harvests, :slug, :string
|
||||
end
|
||||
end
|
||||
6
db/migrate/20130925050304_add_weight_to_harvests.rb
Normal file
6
db/migrate/20130925050304_add_weight_to_harvests.rb
Normal file
@@ -0,0 +1,6 @@
|
||||
class AddWeightToHarvests < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :harvests, :weight_quantity, :decimal
|
||||
add_column :harvests, :weight_unit, :string
|
||||
end
|
||||
end
|
||||
16
db/schema.rb
16
db/schema.rb
@@ -11,7 +11,7 @@
|
||||
#
|
||||
# It's strongly recommended to check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(:version => 20130913015118) do
|
||||
ActiveRecord::Schema.define(:version => 20130925050304) do
|
||||
|
||||
create_table "account_types", :force => true do |t|
|
||||
t.string "name", :null => false
|
||||
@@ -87,6 +87,20 @@ ActiveRecord::Schema.define(:version => 20130913015118) do
|
||||
add_index "gardens", ["owner_id"], :name => "index_gardens_on_user_id"
|
||||
add_index "gardens", ["slug"], :name => "index_gardens_on_slug", :unique => true
|
||||
|
||||
create_table "harvests", :force => true do |t|
|
||||
t.integer "crop_id", :null => false
|
||||
t.integer "owner_id", :null => false
|
||||
t.date "harvested_at"
|
||||
t.decimal "quantity"
|
||||
t.string "unit"
|
||||
t.text "description"
|
||||
t.datetime "created_at", :null => false
|
||||
t.datetime "updated_at", :null => false
|
||||
t.string "slug"
|
||||
t.decimal "weight_quantity"
|
||||
t.string "weight_unit"
|
||||
end
|
||||
|
||||
create_table "members", :force => true do |t|
|
||||
t.string "email", :default => "", :null => false
|
||||
t.string "encrypted_password", :default => "", :null => false
|
||||
|
||||
141
spec/controllers/harvests_controller_spec.rb
Normal file
141
spec/controllers/harvests_controller_spec.rb
Normal file
@@ -0,0 +1,141 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe HarvestsController do
|
||||
|
||||
login_member
|
||||
|
||||
def valid_attributes
|
||||
{
|
||||
:owner_id => subject.current_member.id,
|
||||
:crop_id => FactoryGirl.create(:crop).id
|
||||
}
|
||||
end
|
||||
|
||||
describe "GET index" do
|
||||
it "assigns all harvests as @harvests" do
|
||||
harvest = Harvest.create! valid_attributes
|
||||
get :index, {}
|
||||
assigns(:harvests).should eq([harvest])
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET show" do
|
||||
it "assigns the requested harvest as @harvest" do
|
||||
harvest = Harvest.create! valid_attributes
|
||||
get :show, {:id => harvest.to_param}
|
||||
assigns(:harvest).should eq(harvest)
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET new" do
|
||||
it "assigns a new harvest as @harvest" do
|
||||
get :new, {}
|
||||
assigns(:harvest).should be_a_new(Harvest)
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET edit" do
|
||||
it "assigns the requested harvest as @harvest" do
|
||||
harvest = Harvest.create! valid_attributes
|
||||
get :edit, {:id => harvest.to_param}
|
||||
assigns(:harvest).should eq(harvest)
|
||||
end
|
||||
end
|
||||
|
||||
describe "POST create" do
|
||||
describe "with valid params" do
|
||||
it "creates a new Harvest" do
|
||||
expect {
|
||||
post :create, {:harvest => valid_attributes}
|
||||
}.to change(Harvest, :count).by(1)
|
||||
end
|
||||
|
||||
it "assigns a newly created harvest as @harvest" do
|
||||
post :create, {:harvest => valid_attributes}
|
||||
assigns(:harvest).should be_a(Harvest)
|
||||
assigns(:harvest).should be_persisted
|
||||
end
|
||||
|
||||
it "redirects to the created harvest" do
|
||||
post :create, {:harvest => valid_attributes}
|
||||
response.should redirect_to(Harvest.last)
|
||||
end
|
||||
end
|
||||
|
||||
describe "with invalid params" do
|
||||
it "assigns a newly created but unsaved harvest as @harvest" do
|
||||
# Trigger the behavior that occurs when invalid params are submitted
|
||||
Harvest.any_instance.stub(:save).and_return(false)
|
||||
post :create, {:harvest => { "crop_id" => "invalid value" }}
|
||||
assigns(:harvest).should be_a_new(Harvest)
|
||||
end
|
||||
|
||||
it "re-renders the 'new' template" do
|
||||
# Trigger the behavior that occurs when invalid params are submitted
|
||||
Harvest.any_instance.stub(:save).and_return(false)
|
||||
post :create, {:harvest => { "crop_id" => "invalid value" }}
|
||||
response.should render_template("new")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "PUT update" do
|
||||
describe "with valid params" do
|
||||
it "updates the requested harvest" do
|
||||
harvest = Harvest.create! valid_attributes
|
||||
# Assuming there are no other harvests in the database, this
|
||||
# specifies that the Harvest created on the previous line
|
||||
# receives the :update_attributes message with whatever params are
|
||||
# submitted in the request.
|
||||
Harvest.any_instance.should_receive(:update_attributes).with({ "crop_id" => "1" })
|
||||
put :update, {:id => harvest.to_param, :harvest => { "crop_id" => "1" }}
|
||||
end
|
||||
|
||||
it "assigns the requested harvest as @harvest" do
|
||||
harvest = Harvest.create! valid_attributes
|
||||
put :update, {:id => harvest.to_param, :harvest => valid_attributes}
|
||||
assigns(:harvest).should eq(harvest)
|
||||
end
|
||||
|
||||
it "redirects to the harvest" do
|
||||
harvest = Harvest.create! valid_attributes
|
||||
put :update, {:id => harvest.to_param, :harvest => valid_attributes}
|
||||
response.should redirect_to(harvest)
|
||||
end
|
||||
end
|
||||
|
||||
describe "with invalid params" do
|
||||
it "assigns the harvest as @harvest" do
|
||||
harvest = Harvest.create! valid_attributes
|
||||
# Trigger the behavior that occurs when invalid params are submitted
|
||||
Harvest.any_instance.stub(:save).and_return(false)
|
||||
put :update, {:id => harvest.to_param, :harvest => { "crop_id" => "invalid value" }}
|
||||
assigns(:harvest).should eq(harvest)
|
||||
end
|
||||
|
||||
it "re-renders the 'edit' template" do
|
||||
harvest = Harvest.create! valid_attributes
|
||||
# Trigger the behavior that occurs when invalid params are submitted
|
||||
Harvest.any_instance.stub(:save).and_return(false)
|
||||
put :update, {:id => harvest.to_param, :harvest => { "crop_id" => "invalid value" }}
|
||||
response.should render_template("edit")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "DELETE destroy" do
|
||||
it "destroys the requested harvest" do
|
||||
harvest = Harvest.create! valid_attributes
|
||||
expect {
|
||||
delete :destroy, {:id => harvest.to_param}
|
||||
}.to change(Harvest, :count).by(-1)
|
||||
end
|
||||
|
||||
it "redirects to the harvests list" do
|
||||
harvest = Harvest.create! valid_attributes
|
||||
delete :destroy, {:id => harvest.to_param}
|
||||
response.should redirect_to(harvests_url)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
14
spec/factories/harvests.rb
Normal file
14
spec/factories/harvests.rb
Normal file
@@ -0,0 +1,14 @@
|
||||
# Read about factories at https://github.com/thoughtbot/factory_girl
|
||||
|
||||
FactoryGirl.define do
|
||||
factory :harvest do
|
||||
crop
|
||||
owner
|
||||
harvested_at "2013-09-17"
|
||||
quantity "3"
|
||||
unit "individual"
|
||||
weight_quantity 6
|
||||
weight_unit "kg"
|
||||
description "A lovely harvest"
|
||||
end
|
||||
end
|
||||
79
spec/helpers/harvests_helper_spec.rb
Normal file
79
spec/helpers/harvests_helper_spec.rb
Normal file
@@ -0,0 +1,79 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe HarvestsHelper do
|
||||
describe "display_quantity" do
|
||||
|
||||
it "blank" do
|
||||
harvest = FactoryGirl.create(:harvest,
|
||||
:quantity => nil,
|
||||
:weight_quantity => nil
|
||||
)
|
||||
result = helper.display_quantity(harvest)
|
||||
result.should eq 'not specified'
|
||||
end
|
||||
|
||||
it '3 individual' do
|
||||
harvest = FactoryGirl.create(:harvest,
|
||||
:quantity => 3,
|
||||
:unit => 'individual',
|
||||
:weight_quantity => nil
|
||||
)
|
||||
result = helper.display_quantity(harvest)
|
||||
result.should eq '3'
|
||||
end
|
||||
|
||||
it '1 bunch' do
|
||||
harvest = FactoryGirl.create(:harvest,
|
||||
:quantity => 1,
|
||||
:unit => 'bunch',
|
||||
:weight_quantity => nil
|
||||
)
|
||||
result = helper.display_quantity(harvest)
|
||||
result.should eq '1 bunch'
|
||||
end
|
||||
|
||||
it '3 bunches' do
|
||||
harvest = FactoryGirl.create(:harvest,
|
||||
:quantity => 3,
|
||||
:unit => 'bunch',
|
||||
:weight_quantity => nil
|
||||
)
|
||||
result = helper.display_quantity(harvest)
|
||||
result.should eq '3 bunches'
|
||||
end
|
||||
|
||||
it '3 kg' do
|
||||
harvest = FactoryGirl.create(:harvest,
|
||||
:quantity => nil,
|
||||
:unit => nil,
|
||||
:weight_quantity => 3,
|
||||
:weight_unit => 'kg'
|
||||
)
|
||||
result = helper.display_quantity(harvest)
|
||||
result.should eq '3 kg'
|
||||
end
|
||||
|
||||
it '3 individual weighing 3 kg' do
|
||||
harvest = FactoryGirl.create(:harvest,
|
||||
:quantity => 3,
|
||||
:unit => 'individual',
|
||||
:weight_quantity => 3,
|
||||
:weight_unit => 'kg'
|
||||
)
|
||||
result = helper.display_quantity(harvest)
|
||||
result.should eq '3, weighing 3 kg'
|
||||
end
|
||||
|
||||
it '3 bunches weighing 3 kg' do
|
||||
harvest = FactoryGirl.create(:harvest,
|
||||
:quantity => 3,
|
||||
:unit => 'bunch',
|
||||
:weight_quantity => 3,
|
||||
:weight_unit => 'kg'
|
||||
)
|
||||
result = helper.display_quantity(harvest)
|
||||
result.should eq '3 bunches, weighing 3 kg'
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
@@ -235,4 +235,12 @@ describe Crop do
|
||||
|
||||
end
|
||||
|
||||
context "harvests" do
|
||||
it "has harvests" do
|
||||
crop = FactoryGirl.create(:crop)
|
||||
harvest = FactoryGirl.create(:harvest, :crop => crop)
|
||||
crop.harvests.should eq [harvest]
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
120
spec/models/harvest_spec.rb
Normal file
120
spec/models/harvest_spec.rb
Normal file
@@ -0,0 +1,120 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe Harvest do
|
||||
|
||||
it "has an owner" do
|
||||
harvest = FactoryGirl.create(:harvest)
|
||||
harvest.owner.should be_an_instance_of Member
|
||||
end
|
||||
|
||||
it "has a crop" do
|
||||
harvest = FactoryGirl.create(:harvest)
|
||||
harvest.crop.should be_an_instance_of Crop
|
||||
end
|
||||
|
||||
context 'quantity' do
|
||||
it 'allows numeric quantities' do
|
||||
@harvest = FactoryGirl.build(:harvest, :quantity => 33)
|
||||
@harvest.should be_valid
|
||||
end
|
||||
|
||||
it 'allows decimal quantities' do
|
||||
@harvest = FactoryGirl.build(:harvest, :quantity => 3.3)
|
||||
@harvest.should be_valid
|
||||
end
|
||||
|
||||
it 'allows blank quantities' do
|
||||
@harvest = FactoryGirl.build(:harvest, :quantity => '')
|
||||
@harvest.should be_valid
|
||||
end
|
||||
|
||||
it 'allows nil quantities' do
|
||||
@harvest = FactoryGirl.build(:harvest, :quantity => nil)
|
||||
@harvest.should be_valid
|
||||
end
|
||||
|
||||
it 'cleans up zero quantities' do
|
||||
@harvest = FactoryGirl.build(:harvest, :quantity => 0)
|
||||
@harvest.quantity.should == 0
|
||||
end
|
||||
|
||||
it "doesn't allow non-numeric quantities" do
|
||||
@harvest = FactoryGirl.build(:harvest, :quantity => "99a")
|
||||
@harvest.should_not be_valid
|
||||
end
|
||||
end
|
||||
|
||||
context 'units' do
|
||||
Harvest::UNITS_VALUES.values.push(nil, '').each do |s|
|
||||
it "#{s} should be a valid unit" do
|
||||
@harvest = FactoryGirl.build(:harvest, :unit => s)
|
||||
@harvest.should be_valid
|
||||
end
|
||||
end
|
||||
|
||||
it 'should refuse invalid unit values' do
|
||||
@harvest = FactoryGirl.build(:harvest, :unit => 'not valid')
|
||||
@harvest.should_not be_valid
|
||||
@harvest.errors[:unit].should include("not valid is not a valid unit")
|
||||
end
|
||||
|
||||
it 'sets unit to blank if quantity is blank' do
|
||||
@harvest = FactoryGirl.build(:harvest, :quantity => '', :unit => 'individual')
|
||||
@harvest.should be_valid
|
||||
@harvest.unit.should eq nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'weight quantity' do
|
||||
it 'allows numeric weight quantities' do
|
||||
@harvest = FactoryGirl.build(:harvest, :weight_quantity => 33)
|
||||
@harvest.should be_valid
|
||||
end
|
||||
|
||||
it 'allows decimal weight quantities' do
|
||||
@harvest = FactoryGirl.build(:harvest, :weight_quantity => 3.3)
|
||||
@harvest.should be_valid
|
||||
end
|
||||
|
||||
it 'allows blank weight quantities' do
|
||||
@harvest = FactoryGirl.build(:harvest, :weight_quantity => '')
|
||||
@harvest.should be_valid
|
||||
end
|
||||
|
||||
it 'allows nil weight quantities' do
|
||||
@harvest = FactoryGirl.build(:harvest, :weight_quantity => nil)
|
||||
@harvest.should be_valid
|
||||
end
|
||||
|
||||
it 'cleans up zero quantities' do
|
||||
@harvest = FactoryGirl.build(:harvest, :weight_quantity => 0)
|
||||
@harvest.weight_quantity.should == 0
|
||||
end
|
||||
|
||||
it "doesn't allow non-numeric weight quantities" do
|
||||
@harvest = FactoryGirl.build(:harvest, :weight_quantity => "99a")
|
||||
@harvest.should_not be_valid
|
||||
end
|
||||
end
|
||||
|
||||
context 'weight units' do
|
||||
it 'all valid units should work' do
|
||||
['kg', 'lb', nil, ''].each do |s|
|
||||
@harvest = FactoryGirl.build(:harvest, :weight_unit => s)
|
||||
@harvest.should be_valid
|
||||
end
|
||||
end
|
||||
|
||||
it 'should refuse invalid weight unit values' do
|
||||
@harvest = FactoryGirl.build(:harvest, :weight_unit => 'not valid')
|
||||
@harvest.should_not be_valid
|
||||
@harvest.errors[:weight_unit].should include("not valid is not a valid unit")
|
||||
end
|
||||
|
||||
it 'sets weight_unit to blank if quantity is blank' do
|
||||
@harvest = FactoryGirl.build(:harvest, :weight_quantity => '', :weight_unit => 'kg')
|
||||
@harvest.should be_valid
|
||||
@harvest.weight_unit.should eq nil
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -373,4 +373,12 @@ describe 'member' do
|
||||
end
|
||||
end
|
||||
|
||||
context 'harvests' do
|
||||
it 'has harvests' do
|
||||
member = FactoryGirl.create(:member)
|
||||
harvest = FactoryGirl.create(:harvest, :owner => member)
|
||||
member.harvests.should eq [harvest]
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
11
spec/requests/harvests_spec.rb
Normal file
11
spec/requests/harvests_spec.rb
Normal file
@@ -0,0 +1,11 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe "Harvests" do
|
||||
describe "GET /harvests" do
|
||||
it "works! (now write some real specs)" do
|
||||
# Run the generator again with the --webrat flag if you want to use webrat methods/matchers
|
||||
get harvests_path
|
||||
response.status.should be(200)
|
||||
end
|
||||
end
|
||||
end
|
||||
35
spec/routing/harvests_routing_spec.rb
Normal file
35
spec/routing/harvests_routing_spec.rb
Normal file
@@ -0,0 +1,35 @@
|
||||
require "spec_helper"
|
||||
|
||||
describe HarvestsController do
|
||||
describe "routing" do
|
||||
|
||||
it "routes to #index" do
|
||||
get("/harvests").should route_to("harvests#index")
|
||||
end
|
||||
|
||||
it "routes to #new" do
|
||||
get("/harvests/new").should route_to("harvests#new")
|
||||
end
|
||||
|
||||
it "routes to #show" do
|
||||
get("/harvests/1").should route_to("harvests#show", :id => "1")
|
||||
end
|
||||
|
||||
it "routes to #edit" do
|
||||
get("/harvests/1/edit").should route_to("harvests#edit", :id => "1")
|
||||
end
|
||||
|
||||
it "routes to #create" do
|
||||
post("/harvests").should route_to("harvests#create")
|
||||
end
|
||||
|
||||
it "routes to #update" do
|
||||
put("/harvests/1").should route_to("harvests#update", :id => "1")
|
||||
end
|
||||
|
||||
it "routes to #destroy" do
|
||||
delete("/harvests/1").should route_to("harvests#destroy", :id => "1")
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
@@ -45,4 +45,13 @@ describe "crops/index" do
|
||||
rendered.should contain "New Crop"
|
||||
end
|
||||
end
|
||||
|
||||
context "downloads" do
|
||||
it "offers a CSV download" do
|
||||
render
|
||||
rendered.should contain "The data on this page is available in the following formats:"
|
||||
assert_select "a", :href => crops_path(:format => 'csv')
|
||||
assert_select "a", :href => crops_path(:format => 'json')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -187,6 +187,10 @@ describe "crops/show" do
|
||||
rendered.should contain "Plant this"
|
||||
end
|
||||
|
||||
it "shows a harvest this button" do
|
||||
rendered.should contain "Harvest this"
|
||||
end
|
||||
|
||||
it "links to the right crop in the planting link" do
|
||||
assert_select("a[href=#{new_planting_path}?crop_id=#{@crop.id}]")
|
||||
end
|
||||
|
||||
19
spec/views/harvests/edit.html.haml_spec.rb
Normal file
19
spec/views/harvests/edit.html.haml_spec.rb
Normal file
@@ -0,0 +1,19 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe "harvests/edit" do
|
||||
before(:each) do
|
||||
assign(:harvest, FactoryGirl.create(:harvest))
|
||||
render
|
||||
end
|
||||
|
||||
it "renders new harvest form" do
|
||||
assert_select "form", :action => harvests_path, :method => "post" do
|
||||
assert_select "select#harvest_crop_id", :name => "harvest[crop_id]"
|
||||
assert_select "input#harvest_quantity", :name => "harvest[quantity]"
|
||||
assert_select "input#harvest_weight_quantity", :name => "harvest[quantity]"
|
||||
assert_select "select#harvest_unit", :name => "harvest[unit]"
|
||||
assert_select "select#harvest_weight_unit", :name => "harvest[unit]"
|
||||
assert_select "textarea#harvest_description", :name => "harvest[description]"
|
||||
end
|
||||
end
|
||||
end
|
||||
41
spec/views/harvests/index.html.haml_spec.rb
Normal file
41
spec/views/harvests/index.html.haml_spec.rb
Normal file
@@ -0,0 +1,41 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe "harvests/index" do
|
||||
before(:each) do
|
||||
controller.stub(:current_user) { nil }
|
||||
@member = FactoryGirl.create(:member)
|
||||
@tomato = FactoryGirl.create(:tomato)
|
||||
@maize = FactoryGirl.create(:maize)
|
||||
page = 1
|
||||
per_page = 2
|
||||
total_entries = 2
|
||||
harvests = WillPaginate::Collection.create(page, per_page, total_entries) do |pager|
|
||||
pager.replace([
|
||||
FactoryGirl.create(:harvest,
|
||||
:crop => @tomato,
|
||||
:owner => @member
|
||||
),
|
||||
FactoryGirl.create(:harvest,
|
||||
:crop => @maize,
|
||||
:owner => @member
|
||||
)
|
||||
])
|
||||
end
|
||||
assign(:harvests, harvests)
|
||||
render
|
||||
end
|
||||
|
||||
it "renders a list of harvests" do
|
||||
render
|
||||
assert_select "tr>td", :text => @member.login_name
|
||||
assert_select "tr>td", :text => @tomato.system_name
|
||||
assert_select "tr>td", :text => @maize.system_name
|
||||
end
|
||||
|
||||
it "provides data links" do
|
||||
render
|
||||
rendered.should contain "The data on this page is available in the following formats:"
|
||||
assert_select "a", :href => harvests_path(:format => 'csv')
|
||||
assert_select "a", :href => harvests_path(:format => 'json')
|
||||
end
|
||||
end
|
||||
19
spec/views/harvests/new.html.haml_spec.rb
Normal file
19
spec/views/harvests/new.html.haml_spec.rb
Normal file
@@ -0,0 +1,19 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe "harvests/new" do
|
||||
before(:each) do
|
||||
assign(:harvest, FactoryGirl.create(:harvest))
|
||||
render
|
||||
end
|
||||
|
||||
it "renders new harvest form" do
|
||||
assert_select "form", :action => harvests_path, :method => "post" do
|
||||
assert_select "select#harvest_crop_id", :name => "harvest[crop_id]"
|
||||
assert_select "input#harvest_quantity", :name => "harvest[quantity]"
|
||||
assert_select "input#harvest_weight_quantity", :name => "harvest[quantity]"
|
||||
assert_select "select#harvest_unit", :name => "harvest[unit]"
|
||||
assert_select "select#harvest_weight_unit", :name => "harvest[unit]"
|
||||
assert_select "textarea#harvest_description", :name => "harvest[description]"
|
||||
end
|
||||
end
|
||||
end
|
||||
16
spec/views/harvests/show.html.haml_spec.rb
Normal file
16
spec/views/harvests/show.html.haml_spec.rb
Normal file
@@ -0,0 +1,16 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe "harvests/show" do
|
||||
before(:each) do
|
||||
controller.stub(:current_user) { nil }
|
||||
@crop = FactoryGirl.create(:tomato)
|
||||
@harvest = assign(:harvest, FactoryGirl.create(:harvest, :crop => @crop))
|
||||
render
|
||||
end
|
||||
|
||||
it "renders attributes" do
|
||||
rendered.should contain @crop.system_name
|
||||
rendered.should contain @harvest.harvested_at.to_s
|
||||
end
|
||||
|
||||
end
|
||||
@@ -44,4 +44,12 @@ describe "plantings/index" do
|
||||
rendered.should contain 'January 13, 2013'
|
||||
end
|
||||
|
||||
it "provides data links" do
|
||||
render
|
||||
rendered.should contain "The data on this page is available in the following formats:"
|
||||
assert_select "a", :href => plantings_path(:format => 'csv')
|
||||
assert_select "a", :href => plantings_path(:format => 'json')
|
||||
assert_select "a", :href => plantings_path(:format => 'rss')
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -42,4 +42,12 @@ describe "seeds/index" do
|
||||
assert_select 'a', :href => place_path(@owner.location)
|
||||
end
|
||||
end
|
||||
|
||||
it "provides data links" do
|
||||
render
|
||||
rendered.should contain "The data on this page is available in the following formats:"
|
||||
assert_select "a", :href => seeds_path(:format => 'csv')
|
||||
assert_select "a", :href => seeds_path(:format => 'json')
|
||||
assert_select "a", :href => seeds_path(:format => 'rss')
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user