From 7d54ab347fbc8bf5c367bd0b8f150b0b7077b546 Mon Sep 17 00:00:00 2001 From: Mackenzie Morgan Date: Tue, 9 Sep 2014 19:55:40 -0400 Subject: [PATCH 01/20] Adding photo functionality to harvests --- app/controllers/photos_controller.rb | 41 ++++++++---- app/models/harvest.rb | 7 ++ app/models/photo.rb | 6 +- app/views/harvests/show.html.haml | 13 ++++ app/views/photos/new.html.haml | 2 +- app/views/plantings/show.html.haml | 2 +- config/initializers/devise.rb | 3 +- db/schema.rb | 7 +- spec/controllers/photos_controller_spec.rb | 74 +++++++++++++++++++--- spec/models/harvest_spec.rb | 28 ++++++++ 10 files changed, 158 insertions(+), 25 deletions(-) diff --git a/app/controllers/photos_controller.rb b/app/controllers/photos_controller.rb index 4962fc54e..8932ebae8 100644 --- a/app/controllers/photos_controller.rb +++ b/app/controllers/photos_controller.rb @@ -29,7 +29,8 @@ class PhotosController < ApplicationController # GET /photos/new.json def new @photo = Photo.new - @planting_id = params[:planting_id] + @type = params[:type] + @id = params[:id] page = params[:page] || 1 @@ -63,17 +64,33 @@ class PhotosController < ApplicationController @photo.owner_id = current_member.id @photo.set_flickr_metadata - if params[:planting_id] - planting = Planting.find_by_id(params[:planting_id]) - if planting - if planting.owner.id == current_member.id - @photo.plantings << planting unless @photo.plantings.include?(planting) - else - flash[:alert] = "You must own both the planting and the photo." - end - else - flash[:alert] = "Couldn't find planting to connect to photo." - end + # several models can have photos. we need to know what model and the id + # for the entry to attach the photo to + valid_models = ["planting", "harvest"] + if params[:type] + if valid_models.include?(params[:type]) + if params[:id] + item = params[:type].camelcase.constantize.find_by_id(params[:id]) + if item + if item.owner.id == current_member.id + # This syntax is weird, so just know that it means this: + # @photo.harvests << item unless @photo.harvests.include?(item) + # but with the correct many-to-many relationship automatically referenced + (@photo.send "#{params[:type]}s") << item unless (@photo.send "#{params[:type]}s").include?(item) + else + flash[:alert] = "You must own both the #{params[:type]} and the photo." + end + else + flash[:alert] = "Couldn't find #{params[:type]} to connect to photo." + end + else + flash[:alert] = "Missing id parameter" + end + else + flash[:alert] = "Cannot attach photos to #{params[:type]}" + end + else + flash[:alert] = "Missing type parameter" end respond_to do |format| diff --git a/app/models/harvest.rb b/app/models/harvest.rb index a7851fdc8..8cc54e043 100644 --- a/app/models/harvest.rb +++ b/app/models/harvest.rb @@ -9,6 +9,9 @@ class Harvest < ActiveRecord::Base belongs_to :owner, :class_name => 'Member' belongs_to :plant_part + has_and_belongs_to_many :photos + before_destroy {|harvest| harvest.photos.clear} + default_scope order('created_at DESC') validates :crop, :presence => {:message => "must be present and exist in our database"} @@ -72,4 +75,8 @@ class Harvest < ActiveRecord::Base "#{owner.login_name}-#{crop}".downcase.gsub(' ', '-') end + def default_photo + return photos.first + end + end diff --git a/app/models/photo.rb b/app/models/photo.rb index e65617c87..aa5a624d6 100644 --- a/app/models/photo.rb +++ b/app/models/photo.rb @@ -4,7 +4,11 @@ class Photo < ActiveRecord::Base belongs_to :owner, :class_name => 'Member' has_and_belongs_to_many :plantings - before_destroy {|photo| photo.plantings.clear} + has_and_belongs_to_many :harvests + before_destroy do |photo| + photo.plantings.clear + photo.harvests.clear + end default_scope order("created_at desc") diff --git a/app/views/harvests/show.html.haml b/app/views/harvests/show.html.haml index 95897bd42..fe0690f1e 100644 --- a/app/views/harvests/show.html.haml +++ b/app/views/harvests/show.html.haml @@ -34,3 +34,16 @@ :growstuff_markdown #{ @harvest.description != "" ? @harvest.description : "No description given." } + +- if @harvest.photos.count > 0 or (can? :edit, @harvest and can? :create, Photo) + %h2 Pictures + + %ul.thumbnails + - @harvest.photos.each do |p| + %li.span2.six-across + = render :partial => 'photos/thumbnail', :locals => { :photo => p } + - if can? :create, Photo and can? :edit, @harvest + %li.span2 + .thumbnail(style='height: 220px') + %p{:style => 'text-align: center; padding-top: 50px'} + = link_to "Add photo", new_photo_path(:type => "harvest", :id => @harvest.id), :class => 'btn btn-primary' diff --git a/app/views/photos/new.html.haml b/app/views/photos/new.html.haml index 32ea66915..965ff28e4 100644 --- a/app/views/photos/new.html.haml +++ b/app/views/photos/new.html.haml @@ -25,7 +25,7 @@ - @photos.each do |p| .col-md-2.six-across .thumbnail(style='height: 220px') - = link_to image_tag(FlickRaw.url_q(p), :alt => '', :class => 'img-rounded'), photos_path(:photo => { :flickr_photo_id => p.id }, :planting_id => @planting_id), :method => :post + = link_to image_tag(FlickRaw.url_q(p), :alt => '', :class => 'img-rounded'), photos_path(:photo => { :flickr_photo_id => p.id }, :type => @type, :id => @id), :method => :post %p =p.title diff --git a/app/views/plantings/show.html.haml b/app/views/plantings/show.html.haml index a6a713229..a5f8c8b8e 100644 --- a/app/views/plantings/show.html.haml +++ b/app/views/plantings/show.html.haml @@ -57,4 +57,4 @@ .col-md-2 .thumbnail(style='height: 220px') %p{:style => 'text-align: center; padding-top: 50px'} - = link_to "Add photo", new_photo_path(:planting_id => @planting.id), :class => 'btn btn-primary' + = link_to "Add photo", new_photo_path(:type => "planting", :id => @planting.id), :class => 'btn btn-primary' diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index eb51fab96..92d55dfaa 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -6,7 +6,8 @@ Devise.setup do |config| # note that it will be overwritten if you use your own mailer class with default "from" parameter. config.mailer_sender = "Growstuff " - config.secret_key = ENV['RAILS_SECRET_TOKEN'] + #config.secret_key = ENV['RAILS_SECRET_TOKEN'] + config.secret_key = '6ccb49df7c02ce710c37ec3eadd81ec65e732708bd859ce6076f42593f0cff186b7c35be2fd195f46c9e923296ee07bf309eb33866fe1ea7d9ffeb88f367489c' # Configure the class responsible to send e-mails. # config.mailer = "Devise::Mailer" diff --git a/db/schema.rb b/db/schema.rb index 4c5ee003b..4ac5f92c7 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 => 20140720085713) do +ActiveRecord::Schema.define(:version => 20140905001730) do create_table "account_types", :force => true do |t| t.string "name", :null => false @@ -108,6 +108,11 @@ ActiveRecord::Schema.define(:version => 20140720085713) do t.integer "plant_part_id" end + create_table "harvests_photos", :id => false, :force => true do |t| + t.integer "photo_id" + t.integer "harvest_id" + 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/photos_controller_spec.rb b/spec/controllers/photos_controller_spec.rb index a73981e4c..4370e626f 100644 --- a/spec/controllers/photos_controller_spec.rb +++ b/spec/controllers/photos_controller_spec.rb @@ -37,8 +37,15 @@ describe PhotosController do end it "assigns a planting id" do - get :new, { :planting_id => 5 } - assigns(:planting_id).should eq "5" + get :new, { :type => "planting", :id => 5 } + assigns(:id).should eq "5" + assigns(:type).should eq "planting" + end + + it "assigns a harvest id" do + get :new, { :type => "harvest", :id => 5 } + assigns(:id).should eq "5" + assigns(:type).should eq "harvest" end it "assigns the current set as @current_set" do @@ -69,7 +76,8 @@ describe PhotosController do planting = FactoryGirl.create(:planting, :garden => garden, :owner => member) photo = FactoryGirl.create(:photo, :owner => member) post :create, {:photo => { :flickr_photo_id => photo.flickr_photo_id }, - :planting_id => planting.id } + :type => "planting", + :id => planting.id } Photo.last.plantings.first.should eq planting end @@ -80,12 +88,39 @@ describe PhotosController do planting = FactoryGirl.create(:planting, :garden => garden, :owner => member) photo = FactoryGirl.create(:photo, :owner => member) post :create, {:photo => { :flickr_photo_id => photo.flickr_photo_id }, - :planting_id => planting.id } + :type => "planting", + :id => planting.id } post :create, {:photo => { :flickr_photo_id => photo.flickr_photo_id }, - :planting_id => planting.id } + :type => "planting", + :id => planting.id } Photo.last.plantings.count.should eq 1 end - end + + it "attaches the photo to a harvest" do + member = FactoryGirl.create(:member) + controller.stub(:current_member) { member } + harvest = FactoryGirl.create(:harvest, :owner => member) + photo = FactoryGirl.create(:photo, :owner => member) + post :create, {:photo => { :flickr_photo_id => photo.flickr_photo_id }, + :type => "harvest", + :id => harvest.id } + Photo.last.harvests.first.should eq harvest + end + + it "doesn't attach a photo to a harvest twice" do + member = FactoryGirl.create(:member) + controller.stub(:current_member) { member } + harvest = FactoryGirl.create(:harvest, :owner => member) + photo = FactoryGirl.create(:photo, :owner => member) + post :create, {:photo => { :flickr_photo_id => photo.flickr_photo_id }, + :type => "harvest", + :id => harvest.id } + post :create, {:photo => { :flickr_photo_id => photo.flickr_photo_id }, + :type => "harvest", + :id => harvest.id } + Photo.last.harvests.count.should eq 1 + end + end describe "for the second time" do it "does not add a photo twice" do @@ -106,9 +141,21 @@ describe PhotosController do planting = FactoryGirl.create(:planting, :garden => garden, :owner => member) photo = FactoryGirl.create(:photo, :owner => member) post :create, {:photo => { :flickr_photo_id => photo.flickr_photo_id }, - :planting_id => planting.id } + :type => "planting", + :id => planting.id } Photo.last.plantings.first.should eq planting end + + it "creates the harvest/photo link" do + member = FactoryGirl.create(:member) + controller.stub(:current_member) { member } + harvest = FactoryGirl.create(:harvest, :owner => member) + photo = FactoryGirl.create(:photo, :owner => member) + post :create, {:photo => { :flickr_photo_id => photo.flickr_photo_id }, + :type => "harvest", + :id => harvest.id } + Photo.last.harvests.first.should eq harvest + end end describe "with mismatched owners" do @@ -117,9 +164,20 @@ describe PhotosController do planting = FactoryGirl.create(:planting) photo = FactoryGirl.create(:photo) post :create, {:photo => { :flickr_photo_id => photo.flickr_photo_id }, - :planting_id => planting.id } + :type => "planting", + :id => planting.id } Photo.last.plantings.first.should_not eq planting end + + it "creates the harvest/photo link" do + # members will be auto-created, and different + harvest = FactoryGirl.create(:harvest) + photo = FactoryGirl.create(:photo) + post :create, {:photo => { :flickr_photo_id => photo.flickr_photo_id }, + :type => "harvest", + :id => harvest.id } + Photo.last.harvests.first.should_not eq harvest + end end end end diff --git a/spec/models/harvest_spec.rb b/spec/models/harvest_spec.rb index ca0180ca1..a5b5cabf7 100644 --- a/spec/models/harvest_spec.rb +++ b/spec/models/harvest_spec.rb @@ -125,4 +125,32 @@ describe Harvest do Harvest.all.should eq [@h2, @h1] end end + + context 'photos' do + before(:each) do + @harvest = FactoryGirl.create(:harvest) + @photo = FactoryGirl.create(:photo) + @harvest.photos << @photo + end + + it 'has a photo' do + @harvest.photos.first.should eq @photo + end + + it 'deletes association with photos when photo is deleted' do + @photo.destroy + @harvest.reload + @harvest.photos.should be_empty + end + + it 'has a default photo' do + @harvest.default_photo.should eq @photo + end + + it 'chooses the most recent photo' do + @photo2 = FactoryGirl.create(:photo) + @harvest.photos << @photo2 + @harvest.default_photo.should eq @photo2 + end + end end From 2b7b5bad6378edb66a0b9307c3c33b89c10f4b4e Mon Sep 17 00:00:00 2001 From: Mackenzie Morgan Date: Tue, 9 Sep 2014 20:21:16 -0400 Subject: [PATCH 02/20] including all the new files needed for harvest photos, this time --- .../harvests/_image_with_popover.html.haml | 12 ++++++ app/views/harvests/_thumbnail.html.haml | 37 +++++++++++++++++++ ...0140905001730_add_harvests_photos_table.rb | 8 ++++ 3 files changed, 57 insertions(+) create mode 100644 app/views/harvests/_image_with_popover.html.haml create mode 100644 app/views/harvests/_thumbnail.html.haml create mode 100644 db/migrate/20140905001730_add_harvests_photos_table.rb diff --git a/app/views/harvests/_image_with_popover.html.haml b/app/views/harvests/_image_with_popover.html.haml new file mode 100644 index 000000000..5eef8610e --- /dev/null +++ b/app/views/harvests/_image_with_popover.html.haml @@ -0,0 +1,12 @@ +- cache "planting_image_#{planting.id}" do + = link_to | + image_tag( | + planting.photos.present? ? planting.photos.first.thumbnail_url : 'placeholder_150.png', | + :alt => planting.to_s | + ), | + planting, | + :rel => "popover", | + 'data-trigger' => 'hover', | + 'data-title' => planting.to_s, | + 'data-content' => "#{ render :partial => 'plantings/popover', :locals => { :planting => planting } }", | + 'data-html' => true diff --git a/app/views/harvests/_thumbnail.html.haml b/app/views/harvests/_thumbnail.html.haml new file mode 100644 index 000000000..f3b1c1211 --- /dev/null +++ b/app/views/harvests/_thumbnail.html.haml @@ -0,0 +1,37 @@ +.well + .row-fluid + .span3 + = link_to image_tag((planting.default_photo ? planting.default_photo.thumbnail_url : 'placeholder_150.png'), :alt => '', :class => 'img-rounded'), planting + + .span9 + %h4 + - if defined?(title) && title == 'owner' + = link_to planting.owner, planting.owner + - else + = link_to planting.crop.name, planting + + %p + Planted + - if planting.planted_at + = planting.planted_at + in + = link_to planting.location, planting.garden + + %p + - if planting.quantity + Quantity: + = planting.quantity + - else +   + + - if planting.description && ! defined?(hide_description) + %div + :growstuff_markdown + #{ planting.description } + + - if can? :edit, planting or can? :destroy, planting + %p + - if can? :edit, planting + =link_to 'Edit', edit_planting_path(planting), :class => 'btn btn-mini' + - if can? :destroy, planting + =link_to 'Delete', planting, method: :delete, data: { confirm: 'Are you sure?' }, :class => 'btn btn-mini' diff --git a/db/migrate/20140905001730_add_harvests_photos_table.rb b/db/migrate/20140905001730_add_harvests_photos_table.rb new file mode 100644 index 000000000..edacd061b --- /dev/null +++ b/db/migrate/20140905001730_add_harvests_photos_table.rb @@ -0,0 +1,8 @@ +class AddHarvestsPhotosTable < ActiveRecord::Migration + def change + create_table :harvests_photos, :id => false do |t| + t.integer :photo_id + t.integer :harvest_id + end + end +end From ed537e583baa711f64e48eb2d744a54e1cfbfc89 Mon Sep 17 00:00:00 2001 From: Mackenzie Morgan Date: Tue, 9 Sep 2014 20:31:14 -0400 Subject: [PATCH 03/20] whitespace fixes and um oops no there shouldn't be a secret key in that config file --- app/controllers/photos_controller.rb | 48 +++++++++++----------- app/models/photo.rb | 4 +- config/initializers/devise.rb | 3 +- spec/controllers/photos_controller_spec.rb | 28 ++++++------- 4 files changed, 41 insertions(+), 42 deletions(-) diff --git a/app/controllers/photos_controller.rb b/app/controllers/photos_controller.rb index 8932ebae8..f4004ad73 100644 --- a/app/controllers/photos_controller.rb +++ b/app/controllers/photos_controller.rb @@ -64,32 +64,32 @@ class PhotosController < ApplicationController @photo.owner_id = current_member.id @photo.set_flickr_metadata - # several models can have photos. we need to know what model and the id - # for the entry to attach the photo to - valid_models = ["planting", "harvest"] + # several models can have photos. we need to know what model and the id + # for the entry to attach the photo to + valid_models = ["planting", "harvest"] if params[:type] if valid_models.include?(params[:type]) - if params[:id] - item = params[:type].camelcase.constantize.find_by_id(params[:id]) - if item - if item.owner.id == current_member.id - # This syntax is weird, so just know that it means this: - # @photo.harvests << item unless @photo.harvests.include?(item) - # but with the correct many-to-many relationship automatically referenced - (@photo.send "#{params[:type]}s") << item unless (@photo.send "#{params[:type]}s").include?(item) - else - flash[:alert] = "You must own both the #{params[:type]} and the photo." - end - else - flash[:alert] = "Couldn't find #{params[:type]} to connect to photo." - end - else - flash[:alert] = "Missing id parameter" - end - else - flash[:alert] = "Cannot attach photos to #{params[:type]}" - end - else + if params[:id] + item = params[:type].camelcase.constantize.find_by_id(params[:id]) + if item + if item.owner.id == current_member.id + # This syntax is weird, so just know that it means this: + # @photo.harvests << item unless @photo.harvests.include?(item) + # but with the correct many-to-many relationship automatically referenced + (@photo.send "#{params[:type]}s") << item unless (@photo.send "#{params[:type]}s").include?(item) + else + flash[:alert] = "You must own both the #{params[:type]} and the photo." + end + else + flash[:alert] = "Couldn't find #{params[:type]} to connect to photo." + end + else + flash[:alert] = "Missing id parameter" + end + else + flash[:alert] = "Cannot attach photos to #{params[:type]}" + end + else flash[:alert] = "Missing type parameter" end diff --git a/app/models/photo.rb b/app/models/photo.rb index aa5a624d6..4f0a0160f 100644 --- a/app/models/photo.rb +++ b/app/models/photo.rb @@ -6,8 +6,8 @@ class Photo < ActiveRecord::Base has_and_belongs_to_many :plantings has_and_belongs_to_many :harvests before_destroy do |photo| - photo.plantings.clear - photo.harvests.clear + photo.plantings.clear + photo.harvests.clear end default_scope order("created_at desc") diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index 92d55dfaa..eb51fab96 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -6,8 +6,7 @@ Devise.setup do |config| # note that it will be overwritten if you use your own mailer class with default "from" parameter. config.mailer_sender = "Growstuff " - #config.secret_key = ENV['RAILS_SECRET_TOKEN'] - config.secret_key = '6ccb49df7c02ce710c37ec3eadd81ec65e732708bd859ce6076f42593f0cff186b7c35be2fd195f46c9e923296ee07bf309eb33866fe1ea7d9ffeb88f367489c' + config.secret_key = ENV['RAILS_SECRET_TOKEN'] # Configure the class responsible to send e-mails. # config.mailer = "Devise::Mailer" diff --git a/spec/controllers/photos_controller_spec.rb b/spec/controllers/photos_controller_spec.rb index 4370e626f..1c3b47780 100644 --- a/spec/controllers/photos_controller_spec.rb +++ b/spec/controllers/photos_controller_spec.rb @@ -39,13 +39,13 @@ describe PhotosController do it "assigns a planting id" do get :new, { :type => "planting", :id => 5 } assigns(:id).should eq "5" - assigns(:type).should eq "planting" + assigns(:type).should eq "planting" end it "assigns a harvest id" do get :new, { :type => "harvest", :id => 5 } assigns(:id).should eq "5" - assigns(:type).should eq "harvest" + assigns(:type).should eq "harvest" end it "assigns the current set as @current_set" do @@ -76,7 +76,7 @@ describe PhotosController do planting = FactoryGirl.create(:planting, :garden => garden, :owner => member) photo = FactoryGirl.create(:photo, :owner => member) post :create, {:photo => { :flickr_photo_id => photo.flickr_photo_id }, - :type => "planting", + :type => "planting", :id => planting.id } Photo.last.plantings.first.should eq planting end @@ -88,10 +88,10 @@ describe PhotosController do planting = FactoryGirl.create(:planting, :garden => garden, :owner => member) photo = FactoryGirl.create(:photo, :owner => member) post :create, {:photo => { :flickr_photo_id => photo.flickr_photo_id }, - :type => "planting", + :type => "planting", :id => planting.id } post :create, {:photo => { :flickr_photo_id => photo.flickr_photo_id }, - :type => "planting", + :type => "planting", :id => planting.id } Photo.last.plantings.count.should eq 1 end @@ -102,7 +102,7 @@ describe PhotosController do harvest = FactoryGirl.create(:harvest, :owner => member) photo = FactoryGirl.create(:photo, :owner => member) post :create, {:photo => { :flickr_photo_id => photo.flickr_photo_id }, - :type => "harvest", + :type => "harvest", :id => harvest.id } Photo.last.harvests.first.should eq harvest end @@ -113,14 +113,14 @@ describe PhotosController do harvest = FactoryGirl.create(:harvest, :owner => member) photo = FactoryGirl.create(:photo, :owner => member) post :create, {:photo => { :flickr_photo_id => photo.flickr_photo_id }, - :type => "harvest", + :type => "harvest", :id => harvest.id } post :create, {:photo => { :flickr_photo_id => photo.flickr_photo_id }, - :type => "harvest", + :type => "harvest", :id => harvest.id } Photo.last.harvests.count.should eq 1 - end - end + end + end describe "for the second time" do it "does not add a photo twice" do @@ -141,7 +141,7 @@ describe PhotosController do planting = FactoryGirl.create(:planting, :garden => garden, :owner => member) photo = FactoryGirl.create(:photo, :owner => member) post :create, {:photo => { :flickr_photo_id => photo.flickr_photo_id }, - :type => "planting", + :type => "planting", :id => planting.id } Photo.last.plantings.first.should eq planting end @@ -152,7 +152,7 @@ describe PhotosController do harvest = FactoryGirl.create(:harvest, :owner => member) photo = FactoryGirl.create(:photo, :owner => member) post :create, {:photo => { :flickr_photo_id => photo.flickr_photo_id }, - :type => "harvest", + :type => "harvest", :id => harvest.id } Photo.last.harvests.first.should eq harvest end @@ -164,7 +164,7 @@ describe PhotosController do planting = FactoryGirl.create(:planting) photo = FactoryGirl.create(:photo) post :create, {:photo => { :flickr_photo_id => photo.flickr_photo_id }, - :type => "planting", + :type => "planting", :id => planting.id } Photo.last.plantings.first.should_not eq planting end @@ -174,7 +174,7 @@ describe PhotosController do harvest = FactoryGirl.create(:harvest) photo = FactoryGirl.create(:photo) post :create, {:photo => { :flickr_photo_id => photo.flickr_photo_id }, - :type => "harvest", + :type => "harvest", :id => harvest.id } Photo.last.harvests.first.should_not eq harvest end From 550f3c53265e80185486298079fdb7bebde63fc0 Mon Sep 17 00:00:00 2001 From: Mackenzie Morgan Date: Tue, 9 Sep 2014 22:18:43 -0400 Subject: [PATCH 04/20] removing unneeded photo-related files --- .../harvests/_image_with_popover.html.haml | 12 ------ app/views/harvests/_thumbnail.html.haml | 37 ------------------- 2 files changed, 49 deletions(-) delete mode 100644 app/views/harvests/_image_with_popover.html.haml delete mode 100644 app/views/harvests/_thumbnail.html.haml diff --git a/app/views/harvests/_image_with_popover.html.haml b/app/views/harvests/_image_with_popover.html.haml deleted file mode 100644 index 5eef8610e..000000000 --- a/app/views/harvests/_image_with_popover.html.haml +++ /dev/null @@ -1,12 +0,0 @@ -- cache "planting_image_#{planting.id}" do - = link_to | - image_tag( | - planting.photos.present? ? planting.photos.first.thumbnail_url : 'placeholder_150.png', | - :alt => planting.to_s | - ), | - planting, | - :rel => "popover", | - 'data-trigger' => 'hover', | - 'data-title' => planting.to_s, | - 'data-content' => "#{ render :partial => 'plantings/popover', :locals => { :planting => planting } }", | - 'data-html' => true diff --git a/app/views/harvests/_thumbnail.html.haml b/app/views/harvests/_thumbnail.html.haml deleted file mode 100644 index f3b1c1211..000000000 --- a/app/views/harvests/_thumbnail.html.haml +++ /dev/null @@ -1,37 +0,0 @@ -.well - .row-fluid - .span3 - = link_to image_tag((planting.default_photo ? planting.default_photo.thumbnail_url : 'placeholder_150.png'), :alt => '', :class => 'img-rounded'), planting - - .span9 - %h4 - - if defined?(title) && title == 'owner' - = link_to planting.owner, planting.owner - - else - = link_to planting.crop.name, planting - - %p - Planted - - if planting.planted_at - = planting.planted_at - in - = link_to planting.location, planting.garden - - %p - - if planting.quantity - Quantity: - = planting.quantity - - else -   - - - if planting.description && ! defined?(hide_description) - %div - :growstuff_markdown - #{ planting.description } - - - if can? :edit, planting or can? :destroy, planting - %p - - if can? :edit, planting - =link_to 'Edit', edit_planting_path(planting), :class => 'btn btn-mini' - - if can? :destroy, planting - =link_to 'Delete', planting, method: :delete, data: { confirm: 'Are you sure?' }, :class => 'btn btn-mini' From 8ab4f885f11db1ec53fb568b728b2abc49b0c79d Mon Sep 17 00:00:00 2001 From: Wendy Smoak Date: Fri, 26 Sep 2014 10:32:06 -0400 Subject: [PATCH 05/20] Renamed gardens.rb to gardens_spec.rb so that these tests will run. --- spec/features/{gardens.rb => gardens_spec.rb} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename spec/features/{gardens.rb => gardens_spec.rb} (100%) diff --git a/spec/features/gardens.rb b/spec/features/gardens_spec.rb similarity index 100% rename from spec/features/gardens.rb rename to spec/features/gardens_spec.rb From 25abcdc9236aea1efaaad8683b0f246faffe91f8 Mon Sep 17 00:00:00 2001 From: Skud Date: Sun, 28 Sep 2014 13:50:55 +1000 Subject: [PATCH 06/20] Upload tomato varieties to crop database --- db/seeds/README.md | 6 +++++ db/seeds/crops-11-tomatoes.csv | 41 ++++++++++++++++++++++++++++++++++ script/deploy-tasks.sh | 7 ++---- 3 files changed, 49 insertions(+), 5 deletions(-) create mode 100644 db/seeds/README.md create mode 100644 db/seeds/crops-11-tomatoes.csv diff --git a/db/seeds/README.md b/db/seeds/README.md new file mode 100644 index 000000000..c3cfd1902 --- /dev/null +++ b/db/seeds/README.md @@ -0,0 +1,6 @@ +The format for these crop seed files is CSV with the following fields: + +Crop name +Scientific name +English Wikipedia URL +Parent crop name diff --git a/db/seeds/crops-11-tomatoes.csv b/db/seeds/crops-11-tomatoes.csv new file mode 100644 index 000000000..eb28aaa79 --- /dev/null +++ b/db/seeds/crops-11-tomatoes.csv @@ -0,0 +1,41 @@ +adoration tomato,,https://en.wikipedia.org/wiki/Adoration_%28Tomato%29,tomato, +alicante tomato,,https://en.wikipedia.org/wiki/Alicante_%28tomato%29,tomato, +Amish paste tomato,,http://en.wikipedia.org/wiki/Amish_Paste,tomato, +azoychka tomato,,https://en.wikipedia.org/wiki/Azoychka%28Tomato%29,tomato, +beefsteak tomato,,https://en.wikipedia.org/wiki/Beefsteak_(tomato),tomato, +better boy tomato,,https://en.wikipedia.org/wiki/Better_Boy,tomato, +big rainbow tomato,,https://en.wikipedia.org/wiki/Big_Rainbow_(Tomato),tomato, +Blaby special tomato,,https://en.wikipedia.org/wiki/Blaby_Special_(Tomato),tomato, +black krim tomato,,https://en.wikipedia.org/wiki/Black_Krim_%28tomato%29,tomato, +brandywine tomato,,https://en.wikipedia.org/wiki/Brandywine_(tomato),tomato, +campari tomato,,https://en.wikipedia.org/wiki/Campari_tomato,tomato, +Cherokee purple tomato,,https://en.wikipedia.org/wiki/Cherokee_purple,tomato, +currant tomato,solanum pimpinellifolium,https://en.wikipedia.org/wiki/Solanum_pimpinellifolium, +early girl tomato,,https://en.wikipedia.org/wiki/Early_Girl,tomato, +Fourth of July tomato,,https://en.wikipedia.org/wiki/Fourth_of_July_(tomato_variety),tomato, +garden peach tomato,,https://en.wikipedia.org/wiki/Garden_peach_tomato,tomato, +green zebra tomato,,https://en.wikipedia.org/wiki/Green_Zebra,tomato, +hillbilly tomato,,http://en.wikipedia.org/wiki/Hillbilly_(tomato),tomato, +jubilee tomato,,http://en.wikipedia.org/wiki/Jubilee_(tomato),tomato, +lillian's yellow tomato,,http://en.wikipedia.org/wiki/Lillian%27s_Yellow_(tomato),tomato, +Matt's wild cherry tomato,,http://en.wikipedia.org/wiki/Matt%27s_Wild_Cherry,tomato, +mortgage lifter tomato,,http://en.wikipedia.org/wiki/Mortgage_Lifter,tomato, +Mr. Stripey tomato,,http://en.wikipedia.org/wiki/Mr._Stripey,tomato, +Roma tomato,,http://en.wikipedia.org/wiki/Roma_tomato,tomato, +San Marzano tomato,,http://en.wikipedia.org/wiki/San_Marzano_tomato,tomato, +Santorini tomato,,http://en.wikipedia.org/wiki/Santorini_(tomato),tomato, +stupice tomato,,http://en.wikipedia.org/wiki/Super_Sweet_100,tomato, +tigerella tomato,,http://en.wikipedia.org/wiki/Tigerella,tomato, +tomaccio tomato,,http://en.wikipedia.org/wiki/Tomaccio_(tomato),tomato, +traveller tomato,,http://en.wikipedia.org/wiki/Traveller_(tomato),tomato +three sisters tomato,,http://en.wikipedia.org/wiki/Three_Sisters_(tomato),tomato, +Hanover tomato,,http://en.wikipedia.org/wiki/Hanover_tomato,tomato, +celebrity tomato,,http://en.wikipedia.org/wiki/Celebrity_(tomato),tomato, +tomberry,,http://en.wikipedia.org/wiki/Tomberry,tomato, +super sweet 100 tomato,,http://en.wikipedia.org/wiki/Super_Sweet_100,tomato, +marglobe tomato,,http://en.wikipedia.org/wiki/Marglobe,tomato, +grape tomato,,http://en.wikipedia.org/wiki/Grape_tomato,tomato, +cherry tomato,,http://en.wikipedia.org/wiki/Cherry_tomato,tomato, +Aunt Ruby's German green tomato,,http://en.wikipedia.org/wiki/Aunt_Ruby%27s_German_Green,tomato, +white queen tomato,,http://en.wikipedia.org/wiki/White_Queen_tomato,tomato, +pear tomato,,http://en.wikipedia.org/wiki/Pear_tomato,tomato, diff --git a/script/deploy-tasks.sh b/script/deploy-tasks.sh index f861d27ed..ac4068b26 100755 --- a/script/deploy-tasks.sh +++ b/script/deploy-tasks.sh @@ -10,8 +10,5 @@ # echo "YYYY-MM-DD - do something or other" # rake growstuff:oneoff:something -echo "2013-07-18 - zero crop plantings_count" -rake growstuff:oneoff:zero_plantings_count - -echo "2014-08-10 - replace ping with pint in db" -rake growstuff:oneoff:ping_to_pint +echo "2014-09-28 - upload tomatoes" +rake growstuff:import_crops file=db/seeds/crops-11-tomatoes.csv From 87b6780220071860be7eef24f677fe971f32bfa0 Mon Sep 17 00:00:00 2001 From: Taylor Griffin Date: Sun, 28 Sep 2014 21:57:05 +1000 Subject: [PATCH 07/20] stop generating helpers, constroller specs, view specs, and javascripts --- app/assets/javascripts/admin.js.coffee | 3 --- app/assets/javascripts/admin/orders.js.coffee | 3 --- app/assets/javascripts/comments.js.coffee | 3 --- app/assets/javascripts/forums.js.coffee | 3 --- app/assets/javascripts/gardens.js.coffee | 3 --- app/assets/javascripts/harvests.js.coffee | 3 --- app/assets/javascripts/home.js.coffee | 3 --- app/assets/javascripts/notifications.js.coffee | 3 --- app/assets/javascripts/order_items.js.coffee | 3 --- app/assets/javascripts/orders.js.coffee | 3 --- app/assets/javascripts/photos.js.coffee | 3 --- app/assets/javascripts/plant_parts.js.coffee | 3 --- app/assets/javascripts/products.js.coffee | 3 --- app/assets/javascripts/roles.js.coffee | 3 --- app/assets/javascripts/scientific_names.js.coffee | 3 --- app/assets/javascripts/updates.js.coffee | 3 --- app/helpers/plant_parts_helper.rb | 2 -- app/helpers/seeds_helper.rb | 2 -- config/application.rb | 8 ++++++-- 19 files changed, 6 insertions(+), 54 deletions(-) delete mode 100644 app/assets/javascripts/admin.js.coffee delete mode 100644 app/assets/javascripts/admin/orders.js.coffee delete mode 100644 app/assets/javascripts/comments.js.coffee delete mode 100644 app/assets/javascripts/forums.js.coffee delete mode 100644 app/assets/javascripts/gardens.js.coffee delete mode 100644 app/assets/javascripts/harvests.js.coffee delete mode 100644 app/assets/javascripts/home.js.coffee delete mode 100644 app/assets/javascripts/notifications.js.coffee delete mode 100644 app/assets/javascripts/order_items.js.coffee delete mode 100644 app/assets/javascripts/orders.js.coffee delete mode 100644 app/assets/javascripts/photos.js.coffee delete mode 100644 app/assets/javascripts/plant_parts.js.coffee delete mode 100644 app/assets/javascripts/products.js.coffee delete mode 100644 app/assets/javascripts/roles.js.coffee delete mode 100644 app/assets/javascripts/scientific_names.js.coffee delete mode 100644 app/assets/javascripts/updates.js.coffee delete mode 100644 app/helpers/plant_parts_helper.rb delete mode 100644 app/helpers/seeds_helper.rb diff --git a/app/assets/javascripts/admin.js.coffee b/app/assets/javascripts/admin.js.coffee deleted file mode 100644 index 761567942..000000000 --- a/app/assets/javascripts/admin.js.coffee +++ /dev/null @@ -1,3 +0,0 @@ -# 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/assets/javascripts/admin/orders.js.coffee b/app/assets/javascripts/admin/orders.js.coffee deleted file mode 100644 index 761567942..000000000 --- a/app/assets/javascripts/admin/orders.js.coffee +++ /dev/null @@ -1,3 +0,0 @@ -# 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/assets/javascripts/comments.js.coffee b/app/assets/javascripts/comments.js.coffee deleted file mode 100644 index 761567942..000000000 --- a/app/assets/javascripts/comments.js.coffee +++ /dev/null @@ -1,3 +0,0 @@ -# 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/assets/javascripts/forums.js.coffee b/app/assets/javascripts/forums.js.coffee deleted file mode 100644 index 761567942..000000000 --- a/app/assets/javascripts/forums.js.coffee +++ /dev/null @@ -1,3 +0,0 @@ -# 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/assets/javascripts/gardens.js.coffee b/app/assets/javascripts/gardens.js.coffee deleted file mode 100644 index 761567942..000000000 --- a/app/assets/javascripts/gardens.js.coffee +++ /dev/null @@ -1,3 +0,0 @@ -# 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/assets/javascripts/harvests.js.coffee b/app/assets/javascripts/harvests.js.coffee deleted file mode 100644 index 761567942..000000000 --- a/app/assets/javascripts/harvests.js.coffee +++ /dev/null @@ -1,3 +0,0 @@ -# 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/assets/javascripts/home.js.coffee b/app/assets/javascripts/home.js.coffee deleted file mode 100644 index 761567942..000000000 --- a/app/assets/javascripts/home.js.coffee +++ /dev/null @@ -1,3 +0,0 @@ -# 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/assets/javascripts/notifications.js.coffee b/app/assets/javascripts/notifications.js.coffee deleted file mode 100644 index 761567942..000000000 --- a/app/assets/javascripts/notifications.js.coffee +++ /dev/null @@ -1,3 +0,0 @@ -# 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/assets/javascripts/order_items.js.coffee b/app/assets/javascripts/order_items.js.coffee deleted file mode 100644 index 761567942..000000000 --- a/app/assets/javascripts/order_items.js.coffee +++ /dev/null @@ -1,3 +0,0 @@ -# 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/assets/javascripts/orders.js.coffee b/app/assets/javascripts/orders.js.coffee deleted file mode 100644 index 761567942..000000000 --- a/app/assets/javascripts/orders.js.coffee +++ /dev/null @@ -1,3 +0,0 @@ -# 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/assets/javascripts/photos.js.coffee b/app/assets/javascripts/photos.js.coffee deleted file mode 100644 index 761567942..000000000 --- a/app/assets/javascripts/photos.js.coffee +++ /dev/null @@ -1,3 +0,0 @@ -# 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/assets/javascripts/plant_parts.js.coffee b/app/assets/javascripts/plant_parts.js.coffee deleted file mode 100644 index 761567942..000000000 --- a/app/assets/javascripts/plant_parts.js.coffee +++ /dev/null @@ -1,3 +0,0 @@ -# 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/assets/javascripts/products.js.coffee b/app/assets/javascripts/products.js.coffee deleted file mode 100644 index 761567942..000000000 --- a/app/assets/javascripts/products.js.coffee +++ /dev/null @@ -1,3 +0,0 @@ -# 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/assets/javascripts/roles.js.coffee b/app/assets/javascripts/roles.js.coffee deleted file mode 100644 index 761567942..000000000 --- a/app/assets/javascripts/roles.js.coffee +++ /dev/null @@ -1,3 +0,0 @@ -# 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/assets/javascripts/scientific_names.js.coffee b/app/assets/javascripts/scientific_names.js.coffee deleted file mode 100644 index 761567942..000000000 --- a/app/assets/javascripts/scientific_names.js.coffee +++ /dev/null @@ -1,3 +0,0 @@ -# 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/assets/javascripts/updates.js.coffee b/app/assets/javascripts/updates.js.coffee deleted file mode 100644 index 761567942..000000000 --- a/app/assets/javascripts/updates.js.coffee +++ /dev/null @@ -1,3 +0,0 @@ -# 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/helpers/plant_parts_helper.rb b/app/helpers/plant_parts_helper.rb deleted file mode 100644 index b97b124e8..000000000 --- a/app/helpers/plant_parts_helper.rb +++ /dev/null @@ -1,2 +0,0 @@ -module PlantPartsHelper -end diff --git a/app/helpers/seeds_helper.rb b/app/helpers/seeds_helper.rb deleted file mode 100644 index 46c697f02..000000000 --- a/app/helpers/seeds_helper.rb +++ /dev/null @@ -1,2 +0,0 @@ -module SeedsHelper -end diff --git a/config/application.rb b/config/application.rb index f1a5e9dd6..6bbe1fe7d 100644 --- a/config/application.rb +++ b/config/application.rb @@ -67,8 +67,12 @@ module Growstuff config.assets.initialize_on_precompile = true config.generators do |g| - g.template_engine :haml - g.stylesheets false + g.template_engine :haml + g.view_specs false + g.controller_specs false + g.helper false + g.stylesheets false + g.javascripts false end config.action_mailer.delivery_method = :sendmail From 65c46c334b097816cdc92348a8a390680c4e5a7f Mon Sep 17 00:00:00 2001 From: Skud Date: Mon, 29 Sep 2014 09:18:28 +1000 Subject: [PATCH 08/20] Delete unused photos Make sure the models are setup so that if a photo is not used for anything, it's removed from the system. Also wrote a rake task (which should be run on deploy) to remove older unused photos. --- app/models/harvest.rb | 10 +++++- app/models/photo.rb | 9 ++++- app/models/planting.rb | 10 +++++- db/schema.rb | 4 ++- lib/tasks/growstuff.rake | 9 ++++- spec/models/photo_spec.rb | 76 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 113 insertions(+), 5 deletions(-) diff --git a/app/models/harvest.rb b/app/models/harvest.rb index 8cc54e043..68afb2ee5 100644 --- a/app/models/harvest.rb +++ b/app/models/harvest.rb @@ -10,7 +10,15 @@ class Harvest < ActiveRecord::Base belongs_to :plant_part has_and_belongs_to_many :photos - before_destroy {|harvest| harvest.photos.clear} + + before_destroy do |harvest| + photolist = harvest.photos.to_a # save a temp copy of the photo list + harvest.photos.clear # clear relationship b/w harvest and photo + + photolist.each do |photo| + photo.destroy_if_unused + end + end default_scope order('created_at DESC') diff --git a/app/models/photo.rb b/app/models/photo.rb index 4f0a0160f..32679eeed 100644 --- a/app/models/photo.rb +++ b/app/models/photo.rb @@ -5,13 +5,20 @@ class Photo < ActiveRecord::Base has_and_belongs_to_many :plantings has_and_belongs_to_many :harvests - before_destroy do |photo| + before_destroy do |photo| photo.plantings.clear photo.harvests.clear end default_scope order("created_at desc") + # remove photos that aren't used by anything + def destroy_if_unused + unless plantings.size > 0 and harvests.size > 0 + self.destroy + end + end + # This is split into a side-effect free method and a side-effecting method # for easier stubbing and testing. def flickr_metadata diff --git a/app/models/planting.rb b/app/models/planting.rb index 270a827d2..8d0a5227a 100644 --- a/app/models/planting.rb +++ b/app/models/planting.rb @@ -11,7 +11,15 @@ class Planting < ActiveRecord::Base belongs_to :crop, :counter_cache => true has_and_belongs_to_many :photos - before_destroy {|planting| planting.photos.clear} + + before_destroy do |planting| + photolist = planting.photos.to_a # save a temp copy of the photo list + planting.photos.clear # clear relationship b/w planting and photo + + photolist.each do |photo| + photo.destroy_if_unused + end + end default_scope order("created_at desc") scope :finished, where(:finished => true) diff --git a/db/schema.rb b/db/schema.rb index 5ad7d3192..3790e9340 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 => 20140909001730) do +ActiveRecord::Schema.define(:version => 20140928085713) do create_table "account_types", :force => true do |t| t.string "name", :null => false @@ -144,6 +144,7 @@ ActiveRecord::Schema.define(:version => 20140909001730) do t.text "bio" t.integer "plantings_count" t.boolean "newsletter" + t.boolean "send_planting_reminder", :default => true end add_index "members", ["confirmation_token"], :name => "index_users_on_confirmation_token", :unique => true @@ -243,6 +244,7 @@ ActiveRecord::Schema.define(:version => 20140909001730) do t.datetime "updated_at", :null => false t.string "slug" t.integer "forum_id" + t.integer "parent_id" end add_index "posts", ["created_at", "author_id"], :name => "index_updates_on_created_at_and_user_id" diff --git a/lib/tasks/growstuff.rake b/lib/tasks/growstuff.rake index 34739217b..0ae08a699 100644 --- a/lib/tasks/growstuff.rake +++ b/lib/tasks/growstuff.rake @@ -249,13 +249,20 @@ namespace :growstuff do desc "August 2014: fix ping to pint in database" task :ping_to_pint => :environment do Harvest.find_each do |h| - if h.unit == "ping" + if h.unit == "ping" h.unit = "pint" h.save end end end + desc "October 2014: remove unused photos" + task :remove_unused_photos => :environment do + Photo.find_each do |p| + p.destroy_if_unused + end + end + end # end oneoff section end diff --git a/spec/models/photo_spec.rb b/spec/models/photo_spec.rb index 8ac067ab7..2a0b1d5ff 100644 --- a/spec/models/photo_spec.rb +++ b/spec/models/photo_spec.rb @@ -2,6 +2,82 @@ require 'spec_helper' describe Photo do + describe 'add/delete functionality' do + let(:photo) { FactoryGirl.create(:photo) } + let(:planting) { FactoryGirl.create(:planting) } + let(:harvest) { FactoryGirl.create(:harvest) } + + context "adds photos" do + it 'to a planting' do + planting.photos << photo + expect(planting.photos.count).to eq 1 + expect(planting.photos.first).to eq photo + end + + it 'to a harvest' do + harvest.photos << photo + expect(harvest.photos.count).to eq 1 + expect(harvest.photos.first).to eq photo + end + end + + context "removing photos" do + it 'from a planting' do + planting.photos << photo + photo.destroy + expect(planting.photos.count).to eq 0 + end + + it 'from a harvest' do + harvest.photos << photo + photo.destroy + expect(harvest.photos.count).to eq 0 + end + + it "automatically if unused" do + photo.destroy_if_unused + expect(lambda { photo.reload }).to raise_error ActiveRecord::RecordNotFound + end + + it 'they are no longer used by plantings' do + planting.photos << photo + planting.destroy # photo is now no longer used by anything + expect(lambda { photo.reload }).to raise_error ActiveRecord::RecordNotFound + end + + it 'they are no longer used by harvests' do + harvest.photos << photo + harvest.destroy # photo is now no longer used by anything + expect(lambda { photo.reload }).to raise_error ActiveRecord::RecordNotFound + end + + it 'they are no longer used by anything' do + planting.photos << photo + harvest.photos << photo + expect(photo.plantings.size).to eq 1 + expect(photo.harvests.size).to eq 1 + + planting.destroy # photo is still used by harvest + photo.reload + expect(photo).to be_an_instance_of Photo + expect(photo.plantings.size).to eq 0 + expect(photo.harvests.size).to eq 1 + + harvest.destroy # photo is now no longer used by anything + expect(lambda { photo.reload }).to raise_error ActiveRecord::RecordNotFound + end + + it 'does not occur when a photo is still in use' do + planting.photos << photo + harvest.photos << photo + planting.destroy # photo is still used by the harvest + expect(photo).to be_an_instance_of Photo + end + + end # removing photos + + end # add/delete functionality + describe 'flickr_metadata' do # Any further tests led to us MOCKING ALL THE THINGS # which was epistemologically unsatisfactory. From 8497782847f491ebee838c75115e23995c098d5b Mon Sep 17 00:00:00 2001 From: Skud Date: Tue, 30 Sep 2014 23:02:06 +1000 Subject: [PATCH 09/20] Clear crop hierarchy view cache after uploading crops The crop_sweeper only acts in response to things that happen in the controller. Since this works directly with the model, we need to clear the cache fragment manually. --- lib/tasks/growstuff.rake | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/tasks/growstuff.rake b/lib/tasks/growstuff.rake index 34739217b..65a418201 100644 --- a/lib/tasks/growstuff.rake +++ b/lib/tasks/growstuff.rake @@ -30,6 +30,7 @@ namespace :growstuff do CSV.foreach(@file) do |row| Crop.create_from_csv(row) end + Rails.cache.delete('full_crop_hierarchy') puts "Finished loading crops" end From 9a9eeecb46b8c2e3fba4ff7d33ce05674eee2ce8 Mon Sep 17 00:00:00 2001 From: Skud Date: Thu, 2 Oct 2014 10:09:21 +1000 Subject: [PATCH 10/20] Removing tests for migrations These were never run anyway (they don't have _spec.rb in their names) and were obviously written when we had no idea what we were doing. They're full of syntax errors and all sorts of stuff that just won't work. The best thing is to remove them so they don't confuse people! --- spec/migrations/give_each_user_a_garden.spec | 12 ------------ spec/migrations/set_up_test_users.spec | 10 ---------- 2 files changed, 22 deletions(-) delete mode 100644 spec/migrations/give_each_user_a_garden.spec delete mode 100644 spec/migrations/set_up_test_users.spec diff --git a/spec/migrations/give_each_user_a_garden.spec b/spec/migrations/give_each_user_a_garden.spec deleted file mode 100644 index 1c6972e54..000000000 --- a/spec/migrations/give_each_user_a_garden.spec +++ /dev/null @@ -1,12 +0,0 @@ -require 'spec_helper' - -describe 'new gardens' do - it "should have 'my garden' for each user" do - (1..3).each do |i| - @user = User.find_by_username("test#{i}") - @garden = Garden.find(:name => "My Garden", :user_id => @user.id) - @garden.should_exist - @garden.slug.should == "test#{i}-my-garden" - end - end -end diff --git a/spec/migrations/set_up_test_users.spec b/spec/migrations/set_up_test_users.spec deleted file mode 100644 index d1f69d3f6..000000000 --- a/spec/migrations/set_up_test_users.spec +++ /dev/null @@ -1,10 +0,0 @@ -require 'spec_helper' - -describe 'test users' do - it 'should have 3 test users' do - (1..3).each do |i| - @user = User.find_by_username("test#{i}") - @user.email.should == "test#{i}@example.com" - end - end -end From 0ad217c9a264cdeb9899362ad9eb098eaf8defa4 Mon Sep 17 00:00:00 2001 From: Mackenzie Morgan Date: Wed, 1 Oct 2014 20:16:53 -0400 Subject: [PATCH 11/20] add index to harvest_photo --- db/migrate/20140905001730_add_harvests_photos_table.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/db/migrate/20140905001730_add_harvests_photos_table.rb b/db/migrate/20140905001730_add_harvests_photos_table.rb index edacd061b..299d6653e 100644 --- a/db/migrate/20140905001730_add_harvests_photos_table.rb +++ b/db/migrate/20140905001730_add_harvests_photos_table.rb @@ -5,4 +5,6 @@ class AddHarvestsPhotosTable < ActiveRecord::Migration t.integer :harvest_id end end + + add_index(:harvests_photos, [:harvest_id, :photo_id]) end From a29d11a07c24d5da516cc35f7993c584982317ad Mon Sep 17 00:00:00 2001 From: Mackenzie Morgan Date: Wed, 1 Oct 2014 20:17:11 -0400 Subject: [PATCH 12/20] refactor error handling on photo upload to be easier to read --- app/controllers/photos_controller.rb | 50 ++++++++++++++-------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/app/controllers/photos_controller.rb b/app/controllers/photos_controller.rb index f4004ad73..9c53e9168 100644 --- a/app/controllers/photos_controller.rb +++ b/app/controllers/photos_controller.rb @@ -67,31 +67,31 @@ class PhotosController < ApplicationController # several models can have photos. we need to know what model and the id # for the entry to attach the photo to valid_models = ["planting", "harvest"] - if params[:type] - if valid_models.include?(params[:type]) - if params[:id] - item = params[:type].camelcase.constantize.find_by_id(params[:id]) - if item - if item.owner.id == current_member.id - # This syntax is weird, so just know that it means this: - # @photo.harvests << item unless @photo.harvests.include?(item) - # but with the correct many-to-many relationship automatically referenced - (@photo.send "#{params[:type]}s") << item unless (@photo.send "#{params[:type]}s").include?(item) - else - flash[:alert] = "You must own both the #{params[:type]} and the photo." - end - else - flash[:alert] = "Couldn't find #{params[:type]} to connect to photo." - end - else - flash[:alert] = "Missing id parameter" - end - else - flash[:alert] = "Cannot attach photos to #{params[:type]}" - end - else - flash[:alert] = "Missing type parameter" - end + if ! params[:type] + flash[:alert] = "Missing type parameter" + return 1 + end + if ! valid_models.include?(params[:type]) + flash[:alert] = "Cannot attach photos to #{params[:type]}" + return 1 + end + if ! params[:id] + flash[:alert] = "Missing id parameter" + return 1 + end + item = params[:type].camelcase.constantize.find_by_id(params[:id]) + if ! item + flash[:alert] = "Couldn't find #{params[:type]} to connect to photo." + return 1 + end + if item.owner.id != current_member.id + flash[:alert] = "You must own both the #{params[:type]} and the photo." + return 1 + end + # This syntax is weird, so just know that it means this: + # @photo.harvests << item unless @photo.harvests.include?(item) + # but with the correct many-to-many relationship automatically referenced + (@photo.send "#{params[:type]}s") << item unless (@photo.send "#{params[:type]}s").include?(item) respond_to do |format| if @photo.save From 557d07d2f1093009806e3eec323517911288b941 Mon Sep 17 00:00:00 2001 From: Wendy Smoak Date: Wed, 1 Oct 2014 20:24:15 -0400 Subject: [PATCH 13/20] Rename Sign in tests and add Sign up tests. --- spec/features/{signin.rb => signin_spec.rb} | 0 spec/features/signup_spec.rb | 52 +++++++++++++++++++++ 2 files changed, 52 insertions(+) rename spec/features/{signin.rb => signin_spec.rb} (100%) create mode 100644 spec/features/signup_spec.rb diff --git a/spec/features/signin.rb b/spec/features/signin_spec.rb similarity index 100% rename from spec/features/signin.rb rename to spec/features/signin_spec.rb diff --git a/spec/features/signup_spec.rb b/spec/features/signup_spec.rb new file mode 100644 index 000000000..9962df359 --- /dev/null +++ b/spec/features/signup_spec.rb @@ -0,0 +1,52 @@ +require 'spec_helper' + +feature "signup" do + + scenario "sign up for new account from top menubar" do + visit crops_path # something other than front page, which has multiple signup links + click_link 'Sign up' + fill_in 'Login name', with: 'person123' + fill_in 'Email', with: 'gardener@example.com' + fill_in 'Password', with: 'abc123' + fill_in 'Password confirmation', with: 'abc123' + check 'member_tos_agreement' + click_button 'Sign up' + page.has_content? 'A message with a confirmation link has been sent to your email address. Please open the link to activate your account.' + current_path.should eq root_path + end + + scenario "sign up for new account with existing username" do + visit crops_path # something other than front page, which has multiple signup links + click_link 'Sign up' + fill_in 'Login name', with: 'person123' + fill_in 'Email', with: 'gardener@example.com' + fill_in 'Password', with: 'abc123' + fill_in 'Password confirmation', with: 'abc123' + check 'member_tos_agreement' + click_button 'Sign up' + page.has_content? 'A message with a confirmation link has been sent to your email address. Please open the link to activate your account.' + current_path.should eq root_path + first('.signup a').click # click the 'Sign up' button in the middle of the page + fill_in 'Login name', with: 'person123' + fill_in 'Email', with: 'gardener@example.com' + fill_in 'Password', with: 'abc123' + fill_in 'Password confirmation', with: 'abc123' + check 'member_tos_agreement' + click_button 'Sign up' + page.has_content? 'Login name has already been taken' + end + + scenario "sign up for new account without accepting TOS" do + visit root_path + first('.signup a').click # click the 'Sign up' button in the middle of the page + fill_in 'Login name', with: 'person123' + fill_in 'Email', with: 'gardener@example.com' + fill_in 'Password', with: 'abc123' + fill_in 'Password confirmation', with: 'abc123' + # do not check 'member_tos_agreement' + click_button 'Sign up' + page.has_content? 'Tos agreement must be accepted' + current_path.should eq members_path + end + +end From 57abfa04b38f23d15bed82572ce44319279b7edb Mon Sep 17 00:00:00 2001 From: Mackenzie Morgan Date: Wed, 1 Oct 2014 21:46:15 -0400 Subject: [PATCH 14/20] fix whitespace --- app/controllers/photos_controller.rb | 58 ++++++++++++++-------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/app/controllers/photos_controller.rb b/app/controllers/photos_controller.rb index 9c53e9168..a22a3c2f1 100644 --- a/app/controllers/photos_controller.rb +++ b/app/controllers/photos_controller.rb @@ -64,35 +64,35 @@ class PhotosController < ApplicationController @photo.owner_id = current_member.id @photo.set_flickr_metadata - # several models can have photos. we need to know what model and the id - # for the entry to attach the photo to - valid_models = ["planting", "harvest"] - if ! params[:type] - flash[:alert] = "Missing type parameter" - return 1 - end - if ! valid_models.include?(params[:type]) - flash[:alert] = "Cannot attach photos to #{params[:type]}" - return 1 - end - if ! params[:id] - flash[:alert] = "Missing id parameter" - return 1 - end - item = params[:type].camelcase.constantize.find_by_id(params[:id]) - if ! item - flash[:alert] = "Couldn't find #{params[:type]} to connect to photo." - return 1 - end - if item.owner.id != current_member.id - flash[:alert] = "You must own both the #{params[:type]} and the photo." - return 1 - end - # This syntax is weird, so just know that it means this: - # @photo.harvests << item unless @photo.harvests.include?(item) - # but with the correct many-to-many relationship automatically referenced - (@photo.send "#{params[:type]}s") << item unless (@photo.send "#{params[:type]}s").include?(item) - + # several models can have photos. we need to know what model and the id + # for the entry to attach the photo to + valid_models = ["planting", "harvest"] + if ! params[:type] + flash[:alert] = "Missing type parameter" + return 1 + end + if ! valid_models.include?(params[:type]) + flash[:alert] = "Cannot attach photos to #{params[:type]}" + return 1 + end + if ! params[:id] + flash[:alert] = "Missing id parameter" + return 1 + end + item = params[:type].camelcase.constantize.find_by_id(params[:id]) + if ! item + flash[:alert] = "Couldn't find #{params[:type]} to connect to photo." + return 1 + end + if item.owner.id != current_member.id + flash[:alert] = "You must own both the #{params[:type]} and the photo." + return 1 + end + # This syntax is weird, so just know that it means this: + # @photo.harvests << item unless @photo.harvests.include?(item) + # but with the correct many-to-many relationship automatically referenced + (@photo.send "#{params[:type]}s") << item unless (@photo.send "#{params[:type]}s").include?(item) + respond_to do |format| if @photo.save format.html { redirect_to @photo, notice: 'Photo was successfully added.' } From fcda8742d8049bac9bcfb46f82b00f79c54c4f69 Mon Sep 17 00:00:00 2001 From: Mackenzie Morgan Date: Wed, 1 Oct 2014 22:52:52 -0400 Subject: [PATCH 15/20] go back to the nested error handling in the photos controller and add a migration for indexing harvests_photos --- app/controllers/photos_controller.rb | 48 +++++++++---------- ...0140905001730_add_harvests_photos_table.rb | 2 - ...41002022459_create_index_harvest_photos.rb | 5 ++ db/schema.rb | 6 +-- 4 files changed, 32 insertions(+), 29 deletions(-) create mode 100644 db/migrate/20141002022459_create_index_harvest_photos.rb diff --git a/app/controllers/photos_controller.rb b/app/controllers/photos_controller.rb index a22a3c2f1..1bb9ea4cf 100644 --- a/app/controllers/photos_controller.rb +++ b/app/controllers/photos_controller.rb @@ -67,31 +67,31 @@ class PhotosController < ApplicationController # several models can have photos. we need to know what model and the id # for the entry to attach the photo to valid_models = ["planting", "harvest"] - if ! params[:type] + if params[:type] + if valid_models.include?(params[:type]) + if params[:id] + item = params[:type].camelcase.constantize.find_by_id(params[:id]) + if item + if item.owner.id == current_member.id + # This syntax is weird, so just know that it means this: + # @photo.harvests << item unless @photo.harvests.include?(item) + # but with the correct many-to-many relationship automatically referenced + (@photo.send "#{params[:type]}s") << item unless (@photo.send "#{params[:type]}s").include?(item) + else + flash[:alert] = "You must own both the #{params[:type]} and the photo." + end + else + flash[:alert] = "Couldn't find #{params[:type]} to connect to photo." + end + else + flash[:alert] = "Missing id parameter" + end + else + flash[:alert] = "Cannot attach photos to #{params[:type]}" + end + else flash[:alert] = "Missing type parameter" - return 1 - end - if ! valid_models.include?(params[:type]) - flash[:alert] = "Cannot attach photos to #{params[:type]}" - return 1 - end - if ! params[:id] - flash[:alert] = "Missing id parameter" - return 1 - end - item = params[:type].camelcase.constantize.find_by_id(params[:id]) - if ! item - flash[:alert] = "Couldn't find #{params[:type]} to connect to photo." - return 1 - end - if item.owner.id != current_member.id - flash[:alert] = "You must own both the #{params[:type]} and the photo." - return 1 - end - # This syntax is weird, so just know that it means this: - # @photo.harvests << item unless @photo.harvests.include?(item) - # but with the correct many-to-many relationship automatically referenced - (@photo.send "#{params[:type]}s") << item unless (@photo.send "#{params[:type]}s").include?(item) + end respond_to do |format| if @photo.save diff --git a/db/migrate/20140905001730_add_harvests_photos_table.rb b/db/migrate/20140905001730_add_harvests_photos_table.rb index 299d6653e..edacd061b 100644 --- a/db/migrate/20140905001730_add_harvests_photos_table.rb +++ b/db/migrate/20140905001730_add_harvests_photos_table.rb @@ -5,6 +5,4 @@ class AddHarvestsPhotosTable < ActiveRecord::Migration t.integer :harvest_id end end - - add_index(:harvests_photos, [:harvest_id, :photo_id]) end diff --git a/db/migrate/20141002022459_create_index_harvest_photos.rb b/db/migrate/20141002022459_create_index_harvest_photos.rb new file mode 100644 index 000000000..b3bd4317a --- /dev/null +++ b/db/migrate/20141002022459_create_index_harvest_photos.rb @@ -0,0 +1,5 @@ +class CreateIndexHarvestPhotos < ActiveRecord::Migration + def change + add_index(:harvests_photos, [:harvest_id, :photo_id]) + end +end diff --git a/db/schema.rb b/db/schema.rb index 3790e9340..31f3b4487 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 => 20140928085713) do +ActiveRecord::Schema.define(:version => 20141002022459) do create_table "account_types", :force => true do |t| t.string "name", :null => false @@ -113,6 +113,8 @@ ActiveRecord::Schema.define(:version => 20140928085713) do t.integer "harvest_id" end + add_index "harvests_photos", ["harvest_id", "photo_id"], :name => "index_harvests_photos_on_harvest_id_and_photo_id" + create_table "members", :force => true do |t| t.string "email", :default => "", :null => false t.string "encrypted_password", :default => "", :null => false @@ -144,7 +146,6 @@ ActiveRecord::Schema.define(:version => 20140928085713) do t.text "bio" t.integer "plantings_count" t.boolean "newsletter" - t.boolean "send_planting_reminder", :default => true end add_index "members", ["confirmation_token"], :name => "index_users_on_confirmation_token", :unique => true @@ -244,7 +245,6 @@ ActiveRecord::Schema.define(:version => 20140928085713) do t.datetime "updated_at", :null => false t.string "slug" t.integer "forum_id" - t.integer "parent_id" end add_index "posts", ["created_at", "author_id"], :name => "index_updates_on_created_at_and_user_id" From 48ad561b76c4128928650c8bde26dc6109383278 Mon Sep 17 00:00:00 2001 From: Mackenzie Morgan Date: Wed, 1 Oct 2014 23:58:54 -0400 Subject: [PATCH 16/20] convert tabs to spaces --- app/controllers/photos_controller.rb | 2 +- ...41002022459_create_index_harvest_photos.rb | 2 +- spec/models/harvest_spec.rb | 52 +++++++++---------- 3 files changed, 28 insertions(+), 28 deletions(-) diff --git a/app/controllers/photos_controller.rb b/app/controllers/photos_controller.rb index 1bb9ea4cf..45755db84 100644 --- a/app/controllers/photos_controller.rb +++ b/app/controllers/photos_controller.rb @@ -91,7 +91,7 @@ class PhotosController < ApplicationController end else flash[:alert] = "Missing type parameter" - end + end respond_to do |format| if @photo.save diff --git a/db/migrate/20141002022459_create_index_harvest_photos.rb b/db/migrate/20141002022459_create_index_harvest_photos.rb index b3bd4317a..75ef69d36 100644 --- a/db/migrate/20141002022459_create_index_harvest_photos.rb +++ b/db/migrate/20141002022459_create_index_harvest_photos.rb @@ -1,5 +1,5 @@ class CreateIndexHarvestPhotos < ActiveRecord::Migration def change - add_index(:harvests_photos, [:harvest_id, :photo_id]) + add_index(:harvests_photos, [:harvest_id, :photo_id]) end end diff --git a/spec/models/harvest_spec.rb b/spec/models/harvest_spec.rb index a5b5cabf7..66c83c93e 100644 --- a/spec/models/harvest_spec.rb +++ b/spec/models/harvest_spec.rb @@ -127,30 +127,30 @@ describe Harvest do end context 'photos' do - before(:each) do - @harvest = FactoryGirl.create(:harvest) - @photo = FactoryGirl.create(:photo) - @harvest.photos << @photo - end - - it 'has a photo' do - @harvest.photos.first.should eq @photo - end - - it 'deletes association with photos when photo is deleted' do - @photo.destroy - @harvest.reload - @harvest.photos.should be_empty - end - - it 'has a default photo' do - @harvest.default_photo.should eq @photo - end - - it 'chooses the most recent photo' do - @photo2 = FactoryGirl.create(:photo) - @harvest.photos << @photo2 - @harvest.default_photo.should eq @photo2 - end - end + before(:each) do + @harvest = FactoryGirl.create(:harvest) + @photo = FactoryGirl.create(:photo) + @harvest.photos << @photo + end + + it 'has a photo' do + @harvest.photos.first.should eq @photo + end + + it 'deletes association with photos when photo is deleted' do + @photo.destroy + @harvest.reload + @harvest.photos.should be_empty + end + + it 'has a default photo' do + @harvest.default_photo.should eq @photo + end + + it 'chooses the most recent photo' do + @photo2 = FactoryGirl.create(:photo) + @harvest.photos << @photo2 + @harvest.default_photo.should eq @photo2 + end + end end From e002cb2d35dcd209fb462f4d8bed4b81cdcef9ec Mon Sep 17 00:00:00 2001 From: Skud Date: Thu, 2 Oct 2014 17:48:19 +1000 Subject: [PATCH 17/20] added deploy task to remove unused photos --- script/deploy-tasks.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/script/deploy-tasks.sh b/script/deploy-tasks.sh index ac4068b26..3c6dfb909 100755 --- a/script/deploy-tasks.sh +++ b/script/deploy-tasks.sh @@ -12,3 +12,6 @@ echo "2014-09-28 - upload tomatoes" rake growstuff:import_crops file=db/seeds/crops-11-tomatoes.csv + +echo "2014-10-02 - remove unused photos" +rake growstuff:oneoff:remove_unused_photos From a2f2508f0ddd9080fcb793da0ca1415c4df6de7d Mon Sep 17 00:00:00 2001 From: Mackenzie Morgan Date: Thu, 2 Oct 2014 09:38:02 -0400 Subject: [PATCH 18/20] don't lose the thing we're attaching the photo to when we change sets. This is a modification of oshiho3's previous fix. --- app/views/photos/new.html.haml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/views/photos/new.html.haml b/app/views/photos/new.html.haml index f0503a6a6..bc3eb35df 100644 --- a/app/views/photos/new.html.haml +++ b/app/views/photos/new.html.haml @@ -15,7 +15,8 @@ = form_tag(new_photo_path, :method => :get, :class => 'form-inline') do = label_tag :set, "Choose a photo set:", :class => 'control-label' = select_tag :set, options_for_select(@sets, @current_set), :class => 'input-large' - = hidden_field_tag :planting_id, @planting_id + = hidden_field_tag :type, @type + = hidden_field_tag :id, @id = submit_tag "Search", :class => 'btn btn-primary' %div.pagination From 14d039ee018b4d877df10c17285d7a0f471fecd4 Mon Sep 17 00:00:00 2001 From: Shiho Takagi Date: Mon, 29 Sep 2014 22:37:03 +1000 Subject: [PATCH 19/20] Added crops-posts association as well as updated GUI for crop show --- app/controllers/crops_controller.rb | 1 + app/controllers/harvests_controller.rb | 18 +++--- app/controllers/plantings_controller.rb | 18 +++--- app/models/crop.rb | 3 + app/models/post.rb | 14 ++++ app/views/crops/_harvests.html.haml | 8 ++- app/views/crops/_plantings.html.haml | 21 ++++++ app/views/crops/show.html.haml | 14 ++-- app/views/harvests/index.html.haml | 2 +- app/views/plantings/index.html.haml | 2 +- config/routes.rb | 2 + .../20140928044231_add_crops_posts_table.rb | 10 +++ db/schema.rb | 10 ++- lib/haml/filters/growstuff_markdown.rb | 3 +- lib/tasks/growstuff.rake | 7 ++ spec/controllers/harvests_controller_spec.rb | 24 ++++++- spec/controllers/plantings_controller_spec.rb | 28 ++++++-- spec/models/crop_spec.rb | 18 ++++++ spec/models/post_spec.rb | 37 +++++++++++ spec/views/crops/show.html.haml_spec.rb | 64 ++++++++++++++++--- spec/views/harvests/index.html.haml_spec.rb | 13 ++++ spec/views/plantings/index.html.haml_spec.rb | 11 ++++ 22 files changed, 281 insertions(+), 47 deletions(-) create mode 100644 app/views/crops/_plantings.html.haml create mode 100644 db/migrate/20140928044231_add_crops_posts_table.rb diff --git a/app/controllers/crops_controller.rb b/app/controllers/crops_controller.rb index 1316350de..a30de159a 100644 --- a/app/controllers/crops_controller.rb +++ b/app/controllers/crops_controller.rb @@ -69,6 +69,7 @@ class CropsController < ApplicationController # GET /crops/1.json def show @crop = Crop.includes(:scientific_names, {:plantings => :photos}).find(params[:id]) + @posts = @crop.posts.paginate(:page => params[:page]) respond_to do |format| format.html # show.html.haml diff --git a/app/controllers/harvests_controller.rb b/app/controllers/harvests_controller.rb index 96e029ac3..524007d47 100644 --- a/app/controllers/harvests_controller.rb +++ b/app/controllers/harvests_controller.rb @@ -6,23 +6,21 @@ class HarvestsController < ApplicationController # GET /harvests.json def index @owner = Member.find_by_slug(params[:owner]) + @crop = Crop.find_by_slug(params[:crop]) if @owner - @harvests = @owner.harvests.includes(:owner, :crop).paginate(:page => params[:page]) + @harvests = @owner.harvests.includes(:owner, :crop) + elsif @crop + @harvests = @crop.harvests.includes(:owner, :crop) else - @harvests = Harvest.includes(:owner, :crop).paginate(:page => params[:page]) + @harvests = Harvest.includes(:owner, :crop) end respond_to do |format| - format.html # index.html.erb + format.html { @harvests = @harvests.paginate(:page => params[:page]) } 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 + specifics = (@owner ? "#{@owner.name}-" : @crop ? "#{@crop.name}-" : nil) + @filename = "Growstuff-#{specifics}Harvests-#{Time.zone.now.to_s(:number)}.csv" render :csv => @harvests end end diff --git a/app/controllers/plantings_controller.rb b/app/controllers/plantings_controller.rb index 0d419d2f1..62eaf5b79 100644 --- a/app/controllers/plantings_controller.rb +++ b/app/controllers/plantings_controller.rb @@ -7,24 +7,22 @@ class PlantingsController < ApplicationController # GET /plantings.json def index @owner = Member.find_by_slug(params[:owner]) + @crop = Crop.find_by_slug(params[:crop]) if @owner - @plantings = @owner.plantings.includes(:owner, :crop, :garden).paginate(:page => params[:page]) + @plantings = @owner.plantings.includes(:owner, :crop, :garden) + elsif @crop + @plantings = @crop.plantings.includes(:owner, :crop, :garden) else - @plantings = Planting.includes(:owner, :crop, :garden).paginate(:page => params[:page]) + @plantings = Planting.includes(:owner, :crop, :garden) end respond_to do |format| - format.html # index.html.erb + format.html { @plantings = @plantings.paginate(:page => params[:page]) } 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 + specifics = (@owner ? "#{@owner.name}-" : @crop ? "#{@crop.name}-" : nil) + @filename = "Growstuff-#{specifics}Plantings-#{Time.zone.now.to_s(:number)}.csv" render :csv => @plantings end end diff --git a/app/models/crop.rb b/app/models/crop.rb index 3efe8be57..387936d91 100644 --- a/app/models/crop.rb +++ b/app/models/crop.rb @@ -17,6 +17,9 @@ class Crop < ActiveRecord::Base belongs_to :parent, :class_name => 'Crop' has_many :varieties, :class_name => 'Crop', :foreign_key => 'parent_id' + has_and_belongs_to_many :posts + before_destroy {|crop| crop.posts.clear} + default_scope order("lower(name) asc") scope :recent, reorder("created_at desc") diff --git a/app/models/post.rb b/app/models/post.rb index 3a853c18a..7f72a4e57 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -5,6 +5,9 @@ class Post < ActiveRecord::Base belongs_to :author, :class_name => 'Member' belongs_to :forum has_many :comments, :dependent => :destroy + has_and_belongs_to_many :crops + before_destroy {|post| post.crops.clear} + after_save :update_crops_posts_association # also has_many notifications, but kinda meaningless to get at them # from this direction, so we won't set up an association for now. @@ -39,4 +42,15 @@ class Post < ActiveRecord::Base end end + private + def update_crops_posts_association + self.crops.destroy_all + # look for crops mentioned in the post. eg. [tomato](crop) + self.body.scan(Haml::Filters::GrowstuffMarkdown::CROP_REGEX) do |m| + # find crop case-insensitively + crop = Crop.where('lower(name) = ?', $1.downcase).first + # create association + self.crops << crop if crop and not self.crops.include?(crop) + end + end end diff --git a/app/views/crops/_harvests.html.haml b/app/views/crops/_harvests.html.haml index b8cb25447..d10f57d06 100644 --- a/app/views/crops/_harvests.html.haml +++ b/app/views/crops/_harvests.html.haml @@ -4,16 +4,18 @@ Nobody has harvested this crop yet. - else %ul - - crop.harvests.each do |harvest| + - crop.harvests.take(3).each do |harvest| %li = link_to "#{harvest.owner} harvested #{display_quantity(harvest)}.", harvest_path(harvest) = render :partial => 'members/location', :locals => { :member => harvest.owner } %small = distance_of_time_in_words(harvest.created_at, Time.zone.now) ago. - + %p.col-md-offset-1 + = link_to "See all #{crop.name} harvests", harvests_by_crop_path(crop) - if current_member - = link_to "Track your #{crop.name} harvests.", new_harvest_path() + %p.col-md-offset-1 + = link_to "Track your #{crop.name} harvests.", new_harvest_path(:crop_id => crop.id) - else = render :partial => 'shared/signin_signup', :locals => { :to => "track your #{crop.name} harvests" } diff --git a/app/views/crops/_plantings.html.haml b/app/views/crops/_plantings.html.haml new file mode 100644 index 000000000..72bce5608 --- /dev/null +++ b/app/views/crops/_plantings.html.haml @@ -0,0 +1,21 @@ +%h4 Plantings +- if crop.plantings.empty? + %p + Nobody has planted this crop yet. +- else + %ul + - crop.plantings.take(3).each do |planting| + %li + = link_to "#{planting.owner} planted #{planting.quantity} #{planting.planted_from}.", planting_path(planting) + = render :partial => 'members/location', :locals => { :member => planting.owner } + %small + = distance_of_time_in_words(planting.created_at, Time.zone.now) + ago. + %p.col-md-offset-1 + = link_to "See all #{crop.name} plantings", plantings_by_crop_path(crop) +- if current_member + %p.col-md-offset-1 + = link_to "Track your #{crop.name} plantings.", new_planting_path(:crop_id => crop.id) +- else + = render :partial => 'shared/signin_signup', :locals => { :to => "track your #{crop.name} plantings" } + diff --git a/app/views/crops/show.html.haml b/app/views/crops/show.html.haml index b79320698..d28084280 100644 --- a/app/views/crops/show.html.haml +++ b/app/views/crops/show.html.haml @@ -33,12 +33,17 @@ %div#cropmap - - if @crop.plantings.size > 0 + %div.pagination + = page_entries_info @posts, :model => "posts" + = will_paginate @posts - %h2 All plantings + - unless @posts.empty? + - @posts.each do |post| + = render :partial => "posts/single", :locals => { :post => post, :subject => true } - - @crop.plantings.each do |p| - = render :partial => "plantings/thumbnail", :locals => { :planting => p, :title => 'owner' } + %div.pagination + = page_entries_info @posts, :model => "posts" + = will_paginate @posts .col-md-3 - if can? :edit, @crop or can? :destroy, @crop @@ -76,5 +81,6 @@ %ul %li= link_to 'Wikipedia (English)', @crop.en_wikipedia_url + = render :partial => 'plantings', :locals => { :crop => @crop } = render :partial => 'harvests', :locals => { :crop => @crop } = render :partial => 'find_seeds', :locals => { :crop => @crop } diff --git a/app/views/harvests/index.html.haml b/app/views/harvests/index.html.haml index 90bbb4638..f80ce0dd5 100644 --- a/app/views/harvests/index.html.haml +++ b/app/views/harvests/index.html.haml @@ -1,4 +1,4 @@ -- content_for :title, @owner ? "#{@owner}'s harvests" : "Everyone's harvests" +- content_for :title, @owner ? "#{@owner}'s harvests" : @crop ? "Everyone's #{@crop.name} harvests" : "Everyone's harvests" %p #{ENV['GROWSTUFF_SITE_NAME']} helps you track what you're diff --git a/app/views/plantings/index.html.haml b/app/views/plantings/index.html.haml index 091974ef8..eb1e017dc 100644 --- a/app/views/plantings/index.html.haml +++ b/app/views/plantings/index.html.haml @@ -1,4 +1,4 @@ -- content_for :title, @owner ? "#{@owner}'s plantings" : "Everyone's plantings" +- content_for :title, @owner ? "#{@owner}'s plantings" : @crop ? "Everyone's #{@crop.name} plantings" : "Everyone's plantings" %p - if can? :create, Planting diff --git a/config/routes.rb b/config/routes.rb index 360ed2477..0d645a1be 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -12,6 +12,7 @@ Growstuff::Application.routes.draw do resources :plantings match '/plantings/owner/:owner' => 'plantings#index', :as => 'plantings_by_owner' + match '/plantings/crop/:crop' => 'plantings#index', :as => 'plantings_by_crop' resources :gardens match '/gardens/owner/:owner' => 'gardens#index', :as => 'gardens_by_owner' @@ -21,6 +22,7 @@ Growstuff::Application.routes.draw do resources :harvests match '/harvests/owner/:owner' => 'harvests#index', :as => 'harvests_by_owner' + match '/harvests/crop/:crop' => 'harvests#index', :as => 'harvests_by_crop' resources :posts match '/posts/author/:author' => 'posts#index', :as => 'posts_by_author' diff --git a/db/migrate/20140928044231_add_crops_posts_table.rb b/db/migrate/20140928044231_add_crops_posts_table.rb new file mode 100644 index 000000000..a8c06927b --- /dev/null +++ b/db/migrate/20140928044231_add_crops_posts_table.rb @@ -0,0 +1,10 @@ +class AddCropsPostsTable < ActiveRecord::Migration + def change + create_table :crops_posts, :id => false do |t| + t.integer :crop_id + t.integer :post_id + end + add_index :crops_posts, [:crop_id, :post_id] + add_index :crops_posts, :crop_id + end +end \ No newline at end of file diff --git a/db/schema.rb b/db/schema.rb index 29271f5e6..e103777e6 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 => 20140829230600) do +ActiveRecord::Schema.define(:version => 20140928053257) do create_table "account_types", :force => true do |t| t.string "name", :null => false @@ -64,6 +64,14 @@ ActiveRecord::Schema.define(:version => 20140829230600) do add_index "crops", ["name"], :name => "index_crops_on_name" add_index "crops", ["slug"], :name => "index_crops_on_slug", :unique => true + create_table "crops_posts", :id => false, :force => true do |t| + t.integer "crop_id" + t.integer "post_id" + end + + add_index "crops_posts", ["crop_id", "post_id"], :name => "index_crops_posts_on_crop_id_and_post_id" + add_index "crops_posts", ["crop_id"], :name => "index_crops_posts_on_crop_id" + create_table "forums", :force => true do |t| t.string "name", :null => false t.text "description", :null => false diff --git a/lib/haml/filters/growstuff_markdown.rb b/lib/haml/filters/growstuff_markdown.rb index 7069590e7..dba081e44 100644 --- a/lib/haml/filters/growstuff_markdown.rb +++ b/lib/haml/filters/growstuff_markdown.rb @@ -2,12 +2,13 @@ require 'bluecloth' module Haml::Filters module GrowstuffMarkdown + CROP_REGEX = /\[([^\[\]]+?)\]\(crop\)/ include Haml::Filters::Base def render(text) # turn [tomato](crop) into [tomato](http://growstuff.org/crops/tomato) - expanded = text.gsub(/\[([^\[\]]+?)\]\(crop\)/) do |m| + expanded = text.gsub(CROP_REGEX) do |m| crop_str = $1 # find crop case-insensitively crop = Crop.where('lower(name) = ?', crop_str.downcase).first diff --git a/lib/tasks/growstuff.rake b/lib/tasks/growstuff.rake index 34739217b..3c4a676bc 100644 --- a/lib/tasks/growstuff.rake +++ b/lib/tasks/growstuff.rake @@ -256,6 +256,13 @@ namespace :growstuff do end end + desc "October 2014: generate crops_posts records for existing posts" + task :generate_crops_posts_records => :environment do + Post.find_each do |p| + p.send :update_crops_posts_association + end + end + end # end oneoff section end diff --git a/spec/controllers/harvests_controller_spec.rb b/spec/controllers/harvests_controller_spec.rb index f2ecb8e32..38b0edf8c 100644 --- a/spec/controllers/harvests_controller_spec.rb +++ b/spec/controllers/harvests_controller_spec.rb @@ -12,10 +12,30 @@ describe HarvestsController do end describe "GET index" do + before do + @member1 = FactoryGirl.create(:member) + @member2 = FactoryGirl.create(:member) + @tomato = FactoryGirl.create(:tomato) + @maize = FactoryGirl.create(:maize) + @harvest1 = FactoryGirl.create(:harvest, :owner_id => @member1.id, :crop_id => @tomato.id) + @harvest2 = FactoryGirl.create(:harvest, :owner_id => @member2.id, :crop_id => @maize.id) + end + it "assigns all harvests as @harvests" do - harvest = Harvest.create! valid_attributes get :index, {} - assigns(:harvests).should eq([harvest]) + assigns(:harvests).should =~ [@harvest1, @harvest2] + end + + it "picks up owner from params and shows owner's harvests only" do + get :index, {:owner => @member1.slug} + assigns(:owner).should eq @member1 + assigns(:harvests).should eq [@harvest1] + end + + it "picks up crop from params and shows the harvests for the crop only" do + get :index, {:crop => @maize.name} + assigns(:crop).should eq @maize + assigns(:harvests).should eq [@harvest2] end end diff --git a/spec/controllers/plantings_controller_spec.rb b/spec/controllers/plantings_controller_spec.rb index 7e6a75d22..4b3a518a5 100644 --- a/spec/controllers/plantings_controller_spec.rb +++ b/spec/controllers/plantings_controller_spec.rb @@ -12,10 +12,30 @@ describe PlantingsController do end describe "GET index" do - it "picks up owner from params" do - owner = FactoryGirl.create(:member) - get :index, {:owner => owner.slug} - assigns(:owner).should eq(owner) + before do + @member1 = FactoryGirl.create(:member) + @member2 = FactoryGirl.create(:member) + @tomato = FactoryGirl.create(:tomato) + @maize = FactoryGirl.create(:maize) + @planting1 = FactoryGirl.create(:planting, :crop => @tomato, :owner => @member1) + @planting2 = FactoryGirl.create(:planting, :crop => @maize, :owner => @member2) + end + + it "assigns all plantings as @plantings" do + get :index, {} + assigns(:plantings).should =~ [@planting1, @planting2] + end + + it "picks up owner from params and shows owner's plantings only" do + get :index, {:owner => @member1.slug} + assigns(:owner).should eq @member1 + assigns(:plantings).should eq [@planting1] + end + + it "picks up crop from params and shows the plantings for the crop only" do + get :index, {:crop => @maize.name} + assigns(:crop).should eq @maize + assigns(:plantings).should eq [@planting2] end end diff --git a/spec/models/crop_spec.rb b/spec/models/crop_spec.rb index 1741faf74..b54097070 100644 --- a/spec/models/crop_spec.rb +++ b/spec/models/crop_spec.rb @@ -343,4 +343,22 @@ describe Crop do end end + context "crop-post association" do + before { + @tomato = FactoryGirl.create(:tomato) + @maize = FactoryGirl.create(:maize) + @post = FactoryGirl.create(:post, :body => "[maize](crop)[tomato](crop)[tomato](crop)") + } + + describe "destroying a crop" do + before do + @tomato.destroy + end + + it "shouod delete the association but not the posts" do + Post.find_by_id(@post.id).should_not eq nil + Post.find_by_id(@post.id).crops.should eq [@maize] + end + end + end end diff --git a/spec/models/post_spec.rb b/spec/models/post_spec.rb index 441b9c6a9..3751c13c7 100644 --- a/spec/models/post_spec.rb +++ b/spec/models/post_spec.rb @@ -95,4 +95,41 @@ describe Post do end end + context "crop-post association" do + before { + @tomato = FactoryGirl.create(:tomato) + @maize = FactoryGirl.create(:maize) + @chard = FactoryGirl.create(:chard) + @post = FactoryGirl.create(:post, :body => "[maize](crop)[tomato](crop)[tomato](crop)") + } + + it "should be generated without duplicate" do + @post.crops.should =~ [@tomato, @maize] + @tomato.posts.should eq [@post] + @maize.posts.should eq [@post] + end + + it "should be updated when post was modified" do + @post.update_attributes(:body => "[chard](crop)") + + @post.crops.should eq [@chard] + @chard.posts.should eq [@post] + @tomato.posts.should eq [] + @maize.posts.should eq [] + end + + describe "destroying the post" do + before do + @crops = @post.crops + @post.destroy + end + + it "shouod delete the association but not the crops" do + Crop.find_by_id(@tomato.id).should_not eq nil + Crop.find_by_id(@maize.id).should_not eq nil + Crop.find_by_id(@tomato.id).posts.should eq [] + Crop.find_by_id(@maize.id).posts.should eq [] + end + end + end end diff --git a/spec/views/crops/show.html.haml_spec.rb b/spec/views/crops/show.html.haml_spec.rb index 6e8250b27..1ef461508 100644 --- a/spec/views/crops/show.html.haml_spec.rb +++ b/spec/views/crops/show.html.haml_spec.rb @@ -7,6 +7,16 @@ describe "crops/show" do :scientific_names => [ FactoryGirl.create(:zea_mays) ] ) assign(:crop, @crop) + @author = FactoryGirl.create(:member) + page = 1 + per_page = 2 + total_entries = 2 + @posts = WillPaginate::Collection.create(page, per_page, total_entries) do |pager| + pager.replace([ + @post1 = FactoryGirl.create(:post, :author => @author, :body => "Post it!" ), + @post2 = FactoryGirl.create(:post, :author => @author, :body => "Done!" ) + ]) + end end context 'photos' do @@ -125,11 +135,10 @@ describe "crops/show" do context "has plantings" do before(:each) do - @owner = FactoryGirl.create(:member) - @garden = FactoryGirl.create(:garden, :owner => @owner) + @owner = FactoryGirl.create(:london_member) @planting = FactoryGirl.create(:planting, - :garden => @garden, - :crop => @crop + :crop => @crop, + :owner => @owner ) @crop.reload # to pick up latest plantings_count end @@ -137,16 +146,24 @@ describe "crops/show" do it "links to people who are growing this crop" do render rendered.should contain @owner.login_name - rendered.should contain @garden.name + rendered.should contain @owner.location end + end - it "shows photos where available" do - @photo = FactoryGirl.create(:photo) - @planting.photos << @photo + context "has posts" do + it "links to posts" do render - assert_select "img", :src => @photo.thumbnail_url + @posts.each do |p| + rendered.should contain p.author.login_name + rendered.should contain p.subject + rendered.should contain p.body + end end + it "contains two gravatar icons" do + render + assert_select "img", :src => /gravatar\.com\/avatar/, :count => 2 + end end context 'varieties' do @@ -189,9 +206,36 @@ describe "crops/show" do rendered.should contain "Harvest this" end - it "links to the right crop in the planting link" do + it "links to the right crop in the new planting link" do assert_select("a[href=#{new_planting_path}?crop_id=#{@crop.id}]") end + + it "links to the right crop in the new harvest link" do + assert_select("a[href=#{new_harvest_path}?crop_id=#{@crop.id}]") + end + + it { rendered.should contain "Nobody has planted this crop yet" } + it { rendered.should contain "Nobody has harvested this crop yet" } + + context "should have a link to" do + before do + FactoryGirl.create(:planting, :crop => @crop) + FactoryGirl.create(:harvest, :crop => @crop) + @crop.reload + render + end + + it "show all plantings by the crop link" do + assert_select("a[href=#{plantings_by_crop_path @crop}]") + end + + it "show all harvests by the crop link" do + assert_select("a[href=#{harvests_by_crop_path @crop}]") + end + end + + + end context "logged in and crop wrangler" do diff --git a/spec/views/harvests/index.html.haml_spec.rb b/spec/views/harvests/index.html.haml_spec.rb index 3a147e0b6..093a383a9 100644 --- a/spec/views/harvests/index.html.haml_spec.rb +++ b/spec/views/harvests/index.html.haml_spec.rb @@ -41,4 +41,17 @@ describe "harvests/index" do assert_select "a", :href => harvests_path(:format => 'csv') assert_select "a", :href => harvests_path(:format => 'json') end + + it "displays member's name in title" do + assign(:owner, @member) + render + view.content_for(:title).should contain @member.login_name + end + + it "displays crop's name in title" do + assign(:crop, @tomato) + render + view.content_for(:title).should contain @tomato.name + end + end diff --git a/spec/views/plantings/index.html.haml_spec.rb b/spec/views/plantings/index.html.haml_spec.rb index 5ff890514..d46b4e003 100644 --- a/spec/views/plantings/index.html.haml_spec.rb +++ b/spec/views/plantings/index.html.haml_spec.rb @@ -48,4 +48,15 @@ describe "plantings/index" do assert_select "a", :href => plantings_path(:format => 'rss') end + it "displays member's name in title" do + assign(:owner, @member) + render + view.content_for(:title).should contain @member.login_name + end + + it "displays crop's name in title" do + assign(:crop, @tomato) + render + view.content_for(:title).should contain @tomato.name + end end From cf07ecfa4aa9e96c8100437653b7088b6bfb5a20 Mon Sep 17 00:00:00 2001 From: Shiho Takagi Date: Sun, 5 Oct 2014 23:16:46 +1100 Subject: [PATCH 20/20] improved test spec, crop page and added rake task --- app/views/crops/show.html.haml | 5 ++-- db/schema.rb | 1 - lib/tasks/growstuff.rake | 2 +- script/deploy-tasks.sh | 3 +++ spec/models/crop_spec.rb | 19 +++++++------- spec/models/post_spec.rb | 47 ++++++++++++++++++---------------- 6 files changed, 42 insertions(+), 35 deletions(-) diff --git a/app/views/crops/show.html.haml b/app/views/crops/show.html.haml index d28084280..670a0d438 100644 --- a/app/views/crops/show.html.haml +++ b/app/views/crops/show.html.haml @@ -33,9 +33,10 @@ %div#cropmap + %a{:name => 'posts'} %div.pagination = page_entries_info @posts, :model => "posts" - = will_paginate @posts + = will_paginate @posts, :params => {:anchor => "posts"} - unless @posts.empty? - @posts.each do |post| @@ -43,7 +44,7 @@ %div.pagination = page_entries_info @posts, :model => "posts" - = will_paginate @posts + = will_paginate @posts, :params => {:anchor => "posts"} .col-md-3 - if can? :edit, @crop or can? :destroy, @crop diff --git a/db/schema.rb b/db/schema.rb index e4425711c..9292a6fbb 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,6 @@ # # It's strongly recommended to check this file into your version control system. - ActiveRecord::Schema.define(:version => 20141002022459) do create_table "account_types", :force => true do |t| diff --git a/lib/tasks/growstuff.rake b/lib/tasks/growstuff.rake index 62046d87a..f19bf1fed 100644 --- a/lib/tasks/growstuff.rake +++ b/lib/tasks/growstuff.rake @@ -267,7 +267,7 @@ namespace :growstuff do desc "October 2014: generate crops_posts records for existing posts" task :generate_crops_posts_records => :environment do Post.find_each do |p| - p.send :update_crops_posts_association + p.save end end end # end oneoff section diff --git a/script/deploy-tasks.sh b/script/deploy-tasks.sh index 3c6dfb909..451fe0032 100755 --- a/script/deploy-tasks.sh +++ b/script/deploy-tasks.sh @@ -15,3 +15,6 @@ rake growstuff:import_crops file=db/seeds/crops-11-tomatoes.csv echo "2014-10-02 - remove unused photos" rake growstuff:oneoff:remove_unused_photos + +echo "2014-10-05 - generate crops_posts records for existing posts" +rake growstuff:oneoff:generate_crops_posts_records diff --git a/spec/models/crop_spec.rb b/spec/models/crop_spec.rb index b54097070..d9e3d4b0a 100644 --- a/spec/models/crop_spec.rb +++ b/spec/models/crop_spec.rb @@ -344,20 +344,21 @@ describe Crop do end context "crop-post association" do - before { - @tomato = FactoryGirl.create(:tomato) - @maize = FactoryGirl.create(:maize) - @post = FactoryGirl.create(:post, :body => "[maize](crop)[tomato](crop)[tomato](crop)") - } + let!(:tomato) { FactoryGirl.create(:tomato) } + let!(:maize) { FactoryGirl.create(:maize) } + let!(:post) { FactoryGirl.create(:post, :body => "[maize](crop)[tomato](crop)[tomato](crop)") } describe "destroying a crop" do before do - @tomato.destroy + tomato.destroy end - it "shouod delete the association but not the posts" do - Post.find_by_id(@post.id).should_not eq nil - Post.find_by_id(@post.id).crops.should eq [@maize] + it "should delete the association between post and the crop(tomato)" do + expect(Post.find(post).crops).to eq [maize] + end + + it "should not delete the posts" do + expect(Post.find(post)).to_not eq nil end end end diff --git a/spec/models/post_spec.rb b/spec/models/post_spec.rb index 3751c13c7..30c19c500 100644 --- a/spec/models/post_spec.rb +++ b/spec/models/post_spec.rb @@ -96,39 +96,42 @@ describe Post do end context "crop-post association" do - before { - @tomato = FactoryGirl.create(:tomato) - @maize = FactoryGirl.create(:maize) - @chard = FactoryGirl.create(:chard) - @post = FactoryGirl.create(:post, :body => "[maize](crop)[tomato](crop)[tomato](crop)") - } + let!(:tomato) { FactoryGirl.create(:tomato) } + let!(:maize) { FactoryGirl.create(:maize) } + let!(:chard) { FactoryGirl.create(:chard) } + let!(:post) { FactoryGirl.create(:post, :body => "[maize](crop)[tomato](crop)[tomato](crop)") } - it "should be generated without duplicate" do - @post.crops.should =~ [@tomato, @maize] - @tomato.posts.should eq [@post] - @maize.posts.should eq [@post] + it "should be generated" do + expect(tomato.posts).to eq [post] + expect(maize.posts).to eq [post] + end + + it "should not duplicate" do + expect(post.crops) =~ [tomato, maize] end it "should be updated when post was modified" do - @post.update_attributes(:body => "[chard](crop)") + post.update_attributes(:body => "[chard](crop)") - @post.crops.should eq [@chard] - @chard.posts.should eq [@post] - @tomato.posts.should eq [] - @maize.posts.should eq [] + expect(post.crops).to eq [chard] + expect(chard.posts).to eq [post] + expect(tomato.posts).to eq [] + expect(maize.posts).to eq [] end describe "destroying the post" do before do - @crops = @post.crops - @post.destroy + post.destroy end - it "shouod delete the association but not the crops" do - Crop.find_by_id(@tomato.id).should_not eq nil - Crop.find_by_id(@maize.id).should_not eq nil - Crop.find_by_id(@tomato.id).posts.should eq [] - Crop.find_by_id(@maize.id).posts.should eq [] + it "should delete the association" do + expect(Crop.find(tomato).posts).to eq [] + expect(Crop.find(maize).posts).to eq [] + end + + it "should not delete the crops" do + expect(Crop.find(tomato)).to_not eq nil + expect(Crop.find(maize)).to_not eq nil end end end