diff --git a/Gemfile b/Gemfile index 9d6015b65..357d3522e 100644 --- a/Gemfile +++ b/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', diff --git a/Gemfile.lock b/Gemfile.lock index f82f5f9fd..b86dd6b17 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -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 diff --git a/app/assets/javascripts/harvests.js.coffee b/app/assets/javascripts/harvests.js.coffee new file mode 100644 index 000000000..761567942 --- /dev/null +++ b/app/assets/javascripts/harvests.js.coffee @@ -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/ diff --git a/app/controllers/crops_controller.rb b/app/controllers/crops_controller.rb index 29725d959..0706f21d2 100644 --- a/app/controllers/crops_controller.rb +++ b/app/controllers/crops_controller.rb @@ -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 diff --git a/app/controllers/harvests_controller.rb b/app/controllers/harvests_controller.rb new file mode 100644 index 000000000..96e029ac3 --- /dev/null +++ b/app/controllers/harvests_controller.rb @@ -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 diff --git a/app/controllers/plantings_controller.rb b/app/controllers/plantings_controller.rb index a5b781bab..0d419d2f1 100644 --- a/app/controllers/plantings_controller.rb +++ b/app/controllers/plantings_controller.rb @@ -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 diff --git a/app/controllers/seeds_controller.rb b/app/controllers/seeds_controller.rb index 0af8794d5..30918b12e 100644 --- a/app/controllers/seeds_controller.rb +++ b/app/controllers/seeds_controller.rb @@ -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 diff --git a/app/helpers/harvests_helper.rb b/app/helpers/harvests_helper.rb new file mode 100644 index 000000000..b5f335db9 --- /dev/null +++ b/app/helpers/harvests_helper.rb @@ -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 diff --git a/app/models/ability.rb b/app/models/ability.rb index b5fafd8ec..c13a80006 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -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 diff --git a/app/models/crop.rb b/app/models/crop.rb index 8bae75bc4..e8d332220 100644 --- a/app/models/crop.rb +++ b/app/models/crop.rb @@ -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' diff --git a/app/models/harvest.rb b/app/models/harvest.rb new file mode 100644 index 000000000..d6eda9437 --- /dev/null +++ b/app/models/harvest.rb @@ -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 diff --git a/app/models/member.rb b/app/models/member.rb index 67eaf9976..b39d01ea0 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -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 diff --git a/app/views/crops/index.csv.shaper b/app/views/crops/index.csv.shaper new file mode 100644 index 000000000..d186c0099 --- /dev/null +++ b/app/views/crops/index.csv.shaper @@ -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 diff --git a/app/views/crops/index.html.haml b/app/views/crops/index.html.haml index 463d662c5..73dc354d0 100644 --- a/app/views/crops/index.html.haml +++ b/app/views/crops/index.html.haml @@ -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') diff --git a/app/views/crops/show.html.haml b/app/views/crops/show.html.haml index 952d6c5e4..cd6e8adce 100644 --- a/app/views/crops/show.html.haml +++ b/app/views/crops/show.html.haml @@ -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' diff --git a/app/views/harvests/_form.html.haml b/app/views/harvests/_form.html.haml new file mode 100644 index 000000000..d56904ff7 --- /dev/null +++ b/app/views/harvests/_form.html.haml @@ -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' + diff --git a/app/views/harvests/edit.html.haml b/app/views/harvests/edit.html.haml new file mode 100644 index 000000000..8cbe1e62c --- /dev/null +++ b/app/views/harvests/edit.html.haml @@ -0,0 +1,7 @@ +- content_for :title, "Editing harvest" + += render 'form' + += link_to 'Show', @harvest +\| += link_to 'Back', harvests_path diff --git a/app/views/harvests/index.csv.shaper b/app/views/harvests/index.csv.shaper new file mode 100644 index 000000000..1fd9c1fd5 --- /dev/null +++ b/app/views/harvests/index.csv.shaper @@ -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 diff --git a/app/views/harvests/index.html.haml b/app/views/harvests/index.html.haml new file mode 100644 index 000000000..612883330 --- /dev/null +++ b/app/views/harvests/index.html.haml @@ -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') diff --git a/app/views/harvests/new.html.haml b/app/views/harvests/new.html.haml new file mode 100644 index 000000000..5b5004622 --- /dev/null +++ b/app/views/harvests/new.html.haml @@ -0,0 +1,3 @@ +- content_for :title, "New Harvest" + += render 'form' diff --git a/app/views/harvests/show.html.haml b/app/views/harvests/show.html.haml new file mode 100644 index 000000000..62017fd21 --- /dev/null +++ b/app/views/harvests/show.html.haml @@ -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." } diff --git a/app/views/home/index.html.haml b/app/views/home/index.html.haml index b39e55ba5..d98bcc4a0 100644 --- a/app/views/home/index.html.haml +++ b/app/views/home/index.html.haml @@ -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 diff --git a/app/views/layouts/_header.html.haml b/app/views/layouts/_header.html.haml index 3e2b59f5d..a00e2da83 100644 --- a/app/views/layouts/_header.html.haml +++ b/app/views/layouts/_header.html.haml @@ -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 diff --git a/app/views/plantings/index.csv.shaper b/app/views/plantings/index.csv.shaper new file mode 100644 index 000000000..becb6d4d8 --- /dev/null +++ b/app/views/plantings/index.csv.shaper @@ -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 diff --git a/app/views/plantings/index.html.haml b/app/views/plantings/index.html.haml index 434669cb9..5a6d73604 100644 --- a/app/views/plantings/index.html.haml +++ b/app/views/plantings/index.html.haml @@ -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') diff --git a/app/views/plantings/show.html.haml b/app/views/plantings/show.html.haml index a192a27d0..b0120a569 100644 --- a/app/views/plantings/show.html.haml +++ b/app/views/plantings/show.html.haml @@ -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 diff --git a/app/views/seeds/index.csv.shaper b/app/views/seeds/index.csv.shaper new file mode 100644 index 000000000..818e68909 --- /dev/null +++ b/app/views/seeds/index.csv.shaper @@ -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 diff --git a/app/views/seeds/index.html.haml b/app/views/seeds/index.html.haml index 6f62b07a7..201a4669d 100644 --- a/app/views/seeds/index.html.haml +++ b/app/views/seeds/index.html.haml @@ -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') diff --git a/app/views/seeds/show.html.haml b/app/views/seeds/show.html.haml index a24c01e40..7bfa6e992 100644 --- a/app/views/seeds/show.html.haml +++ b/app/views/seeds/show.html.haml @@ -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 diff --git a/config/routes.rb b/config/routes.rb index 4ad09136e..1be11c8a5 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -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' diff --git a/db/migrate/20130917053547_create_harvests.rb b/db/migrate/20130917053547_create_harvests.rb new file mode 100644 index 000000000..e7b7db6b4 --- /dev/null +++ b/db/migrate/20130917053547_create_harvests.rb @@ -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 diff --git a/db/migrate/20130917060257_change_harvest_notes_to_description.rb b/db/migrate/20130917060257_change_harvest_notes_to_description.rb new file mode 100644 index 000000000..bac3167cf --- /dev/null +++ b/db/migrate/20130917060257_change_harvest_notes_to_description.rb @@ -0,0 +1,5 @@ +class ChangeHarvestNotesToDescription < ActiveRecord::Migration + def change + rename_column :harvests, :notes, :description + end +end diff --git a/db/migrate/20130917071545_change_harvest_units_to_unit.rb b/db/migrate/20130917071545_change_harvest_units_to_unit.rb new file mode 100644 index 000000000..d843c2c3d --- /dev/null +++ b/db/migrate/20130917071545_change_harvest_units_to_unit.rb @@ -0,0 +1,5 @@ +class ChangeHarvestUnitsToUnit < ActiveRecord::Migration + def change + rename_column :harvests, :units, :unit + end +end diff --git a/db/migrate/20130917075803_add_slug_to_harvests.rb b/db/migrate/20130917075803_add_slug_to_harvests.rb new file mode 100644 index 000000000..21b44d0ae --- /dev/null +++ b/db/migrate/20130917075803_add_slug_to_harvests.rb @@ -0,0 +1,5 @@ +class AddSlugToHarvests < ActiveRecord::Migration + def change + add_column :harvests, :slug, :string + end +end diff --git a/db/migrate/20130925050304_add_weight_to_harvests.rb b/db/migrate/20130925050304_add_weight_to_harvests.rb new file mode 100644 index 000000000..caf1fd87a --- /dev/null +++ b/db/migrate/20130925050304_add_weight_to_harvests.rb @@ -0,0 +1,6 @@ +class AddWeightToHarvests < ActiveRecord::Migration + def change + add_column :harvests, :weight_quantity, :decimal + add_column :harvests, :weight_unit, :string + end +end diff --git a/db/schema.rb b/db/schema.rb index 7347be52c..1aafa8c89 100644 --- a/db/schema.rb +++ b/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 diff --git a/spec/controllers/harvests_controller_spec.rb b/spec/controllers/harvests_controller_spec.rb new file mode 100644 index 000000000..f2ecb8e32 --- /dev/null +++ b/spec/controllers/harvests_controller_spec.rb @@ -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 diff --git a/spec/factories/harvests.rb b/spec/factories/harvests.rb new file mode 100644 index 000000000..407ccc875 --- /dev/null +++ b/spec/factories/harvests.rb @@ -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 diff --git a/spec/helpers/harvests_helper_spec.rb b/spec/helpers/harvests_helper_spec.rb new file mode 100644 index 000000000..ecc30a51e --- /dev/null +++ b/spec/helpers/harvests_helper_spec.rb @@ -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 diff --git a/spec/models/crop_spec.rb b/spec/models/crop_spec.rb index e872d2ecd..1e0c3c4c1 100644 --- a/spec/models/crop_spec.rb +++ b/spec/models/crop_spec.rb @@ -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 diff --git a/spec/models/harvest_spec.rb b/spec/models/harvest_spec.rb new file mode 100644 index 000000000..eb8143d1f --- /dev/null +++ b/spec/models/harvest_spec.rb @@ -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 diff --git a/spec/models/member_spec.rb b/spec/models/member_spec.rb index 349fd2ce5..49b66ef71 100644 --- a/spec/models/member_spec.rb +++ b/spec/models/member_spec.rb @@ -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 diff --git a/spec/requests/harvests_spec.rb b/spec/requests/harvests_spec.rb new file mode 100644 index 000000000..edb408b0b --- /dev/null +++ b/spec/requests/harvests_spec.rb @@ -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 diff --git a/spec/routing/harvests_routing_spec.rb b/spec/routing/harvests_routing_spec.rb new file mode 100644 index 000000000..66ab7151e --- /dev/null +++ b/spec/routing/harvests_routing_spec.rb @@ -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 diff --git a/spec/views/crops/index.html.haml_spec.rb b/spec/views/crops/index.html.haml_spec.rb index d61d108be..e7520cb2e 100644 --- a/spec/views/crops/index.html.haml_spec.rb +++ b/spec/views/crops/index.html.haml_spec.rb @@ -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 diff --git a/spec/views/crops/show.html.haml_spec.rb b/spec/views/crops/show.html.haml_spec.rb index dd79a443a..84795fa05 100644 --- a/spec/views/crops/show.html.haml_spec.rb +++ b/spec/views/crops/show.html.haml_spec.rb @@ -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 diff --git a/spec/views/harvests/edit.html.haml_spec.rb b/spec/views/harvests/edit.html.haml_spec.rb new file mode 100644 index 000000000..ad3f257e0 --- /dev/null +++ b/spec/views/harvests/edit.html.haml_spec.rb @@ -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 diff --git a/spec/views/harvests/index.html.haml_spec.rb b/spec/views/harvests/index.html.haml_spec.rb new file mode 100644 index 000000000..827785aff --- /dev/null +++ b/spec/views/harvests/index.html.haml_spec.rb @@ -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 diff --git a/spec/views/harvests/new.html.haml_spec.rb b/spec/views/harvests/new.html.haml_spec.rb new file mode 100644 index 000000000..14a1c69d6 --- /dev/null +++ b/spec/views/harvests/new.html.haml_spec.rb @@ -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 diff --git a/spec/views/harvests/show.html.haml_spec.rb b/spec/views/harvests/show.html.haml_spec.rb new file mode 100644 index 000000000..ef233aedc --- /dev/null +++ b/spec/views/harvests/show.html.haml_spec.rb @@ -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 diff --git a/spec/views/plantings/index.html.haml_spec.rb b/spec/views/plantings/index.html.haml_spec.rb index a3df530bd..0653afe62 100644 --- a/spec/views/plantings/index.html.haml_spec.rb +++ b/spec/views/plantings/index.html.haml_spec.rb @@ -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 diff --git a/spec/views/seeds/index.html.haml_spec.rb b/spec/views/seeds/index.html.haml_spec.rb index 02d9d2b44..72cb43b24 100644 --- a/spec/views/seeds/index.html.haml_spec.rb +++ b/spec/views/seeds/index.html.haml_spec.rb @@ -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