Conflicts:
	spec/views/crops/show.html.haml_spec.rb
This commit is contained in:
Skud
2013-07-23 19:35:31 +10:00
36 changed files with 654 additions and 39 deletions

View File

@@ -0,0 +1,3 @@
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/

View File

@@ -0,0 +1,92 @@
class SeedsController < ApplicationController
load_and_authorize_resource
# GET /seeds
# GET /seeds.json
def index
@seeds = Seed.all
@owner = Member.find_by_id(params[:owner_id])
if @owner
@seeds = @owner.seeds.all
end
respond_to do |format|
format.html # index.html.erb
format.json { render json: @seeds }
end
end
# GET /seeds/1
# GET /seeds/1.json
def show
@seed = Seed.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: @seed }
end
end
# GET /seeds/new
# GET /seeds/new.json
def new
@seed = Seed.new
# using find_by_id here because it returns nil, unlike find
@crop = Crop.find_by_id(params[:crop_id]) || Crop.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: @seed }
end
end
# GET /seeds/1/edit
def edit
@seed = Seed.find(params[:id])
end
# POST /seeds
# POST /seeds.json
def create
params[:seed][:owner_id] = current_member.id
@seed = Seed.new(params[:seed])
respond_to do |format|
if @seed.save
format.html { redirect_to @seed, notice: "Successfully added #{@seed.crop} seed to your stash." }
format.json { render json: @seed, status: :created, location: @seed }
else
format.html { render action: "new" }
format.json { render json: @seed.errors, status: :unprocessable_entity }
end
end
end
# PUT /seeds/1
# PUT /seeds/1.json
def update
@seed = Seed.find(params[:id])
respond_to do |format|
if @seed.update_attributes(params[:seed])
format.html { redirect_to @seed, notice: 'Seed was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: @seed.errors, status: :unprocessable_entity }
end
end
end
# DELETE /seeds/1
# DELETE /seeds/1.json
def destroy
@seed = Seed.find(params[:id])
@seed.destroy
respond_to do |format|
format.html { redirect_to seeds_url }
format.json { head :no_content }
end
end
end

View File

@@ -0,0 +1,2 @@
module SeedsHelper
end

View File

@@ -67,6 +67,10 @@ class Ability
can :update, Photo, :owner_id => member.id
can :destroy, Photo, :owner_id => member.id
can :create, Seed
can :update, Seed, :owner_id => member.id
can :destroy, Seed, :owner_id => member.id
# orders/shop/etc
can :create, Order
can :read, Order, :member_id => member.id

View File

@@ -9,6 +9,8 @@ class Member < ActiveRecord::Base
has_many :gardens, :foreign_key => 'owner_id'
has_many :plantings, :through => :gardens
has_many :seeds, :foreign_key => 'owner_id'
has_and_belongs_to_many :roles
has_many :notifications, :foreign_key => 'recipient_id'

12
app/models/seed.rb Normal file
View File

@@ -0,0 +1,12 @@
class Seed < ActiveRecord::Base
attr_accessible :owner_id, :crop_id, :description, :quantity, :plant_before,
:tradable, :tradable_to
belongs_to :crop
belongs_to :owner, :class_name => 'Member', :foreign_key => 'owner_id'
TRADABLE_TO_VALUES = %w(locally nationally internationally)
validates :tradable_to, :inclusion => { :in => TRADABLE_TO_VALUES,
:message => "You may only trade seed locally, nationally, or internationally" },
:allow_nil => true,
:allow_blank => true
end

View File

@@ -1,7 +1,5 @@
= content_for :title, @comment.post.subject
%p#notice= notice
= render :partial => "posts/single", :locals => { :post => @comment.post }
%h2 Showing 1 comment

View File

@@ -0,0 +1,21 @@
.well
.row-fluid
.span4
= link_to image_tag((crop.default_photo ? crop.default_photo.thumbnail_url : 'placeholder_150.png'), :alt => '', :class => 'img-rounded'), crop
.span8
%h3{:style => 'padding-top: 0px; margin-top: 0px'}
= link_to crop, crop
%p
%b Scientific name:
= crop.default_scientific_name
%p
%b
Planted
= pluralize(crop.plantings_count, "time")
by #{Growstuff::Application.config.site_name} members
- if can? :create, Planting
= link_to 'Plant this', new_planting_path(:params => { :crop_id => crop.id }), :class => 'btn btn-primary'
- if can? :create, Seed
= link_to 'Add seeds to stash', new_seed_path(:params => { :crop_id => crop.id }), :class => 'btn btn-primary'

View File

@@ -25,20 +25,29 @@
- sunniness = @crop.sunniness.sort_by {|s, freq| freq }.reverse
= sunniness.map {|s, freq| "#{s} (#{freq})" }.join(", ")
- if @crop.plantings_count > 0
%p
%p
- if @crop.plantings_count > 0
Planted
= pluralize(@crop.plantings_count, "time")
by #{Growstuff::Application.config.site_name} members
%p= link_to "Plant this", new_planting_path(:crop_id => @crop.id), :class => 'btn btn-primary'
- else
Nobody is growing this yet. You could be the first!
%p
- if can? :create, Planting
= link_to "Plant this", new_planting_path(:crop_id => @crop.id), :class => 'btn btn-primary'
- else
= render :partial => 'shared/signin_signup', :locals => { :to => 'plant this crop' }
- if can? :create, Seed
= link_to 'Add seeds to stash', new_seed_path(:params => { :crop_id => @crop.id }), :class => 'btn btn-primary'
- else
= render :partial => 'shared/signin_signup', :locals => { :to => 'add seeds for this crop to your stash' }
- if @crop.plantings_count > 0
- @crop.plantings.each do |p|
= render :partial => "plantings/thumbnail", :locals => { :planting => p, :title => 'owner' }
- else
%p Nobody is growing this yet. You could be the first!
%p= link_to "Plant this", new_planting_path(:crop_id => @crop.id), :class => 'btn btn-primary'
.span3
- if can? :edit, @crop or can? :destroy, @crop
%h4 Crop wrangling

View File

@@ -26,6 +26,11 @@
%li
= link_to 'Add', new_garden_path, :class => 'btn btn-mini'
%p
%b Your seed stash:
= link_to pluralize(current_member.seeds.count, "variety"), seeds_path(:owner_id => current_member.id)
= link_to 'Add', new_seed_path, :class => 'btn btn-mini'
.span4
%p
Your account:

View File

@@ -88,6 +88,13 @@
%h3 Create a new garden
= render 'gardens/form'
%h3 Seeds
%p
- if @member.seeds.count > 0
= link_to pluralize(@member.seeds.count, "variety"), seeds_path(:owner_id => @member.id)
- else
No seeds yet.
%h3 Posts
- if @member.posts.count > 0
- @member.posts.each do |post|

View File

@@ -34,26 +34,7 @@
=link_to 'Delete', @planting, method: :delete, data: { confirm: 'Are you sure?' }, :class => 'btn btn-mini'
.span6
.well
.row-fluid
.span4
= link_to image_tag((@planting.crop.default_photo ? @planting.crop.default_photo.thumbnail_url : 'placeholder_150.png'), :alt => '', :class => 'img-rounded'), @planting.crop
.span8
%h3
= link_to @planting.crop, @planting.crop
- if can? :edit, @planting
= link_to 'Plant another', new_planting_path, :class => 'btn btn-primary'
- elsif can? :create, Planting
= link_to 'Plant this', new_planting_path, :class => 'btn btn-primary'
%p
%b Scientific name:
= @planting.crop_default_scientific_name
%p
%b
Planted
= pluralize(@planting.crop_plantings_count, "time")
by #{Growstuff::Application.config.site_name} members
= render :partial => "crops/index_card", :locals => { :crop => @planting.crop}
%h2 Notes

View File

@@ -0,0 +1,40 @@
= form_for(@seed, :html => {:class => "form-horizontal"}) do |f|
- if @seed.errors.any?
#error_explanation
%h2= "#{pluralize(@seed.errors.count, "error")} prohibited this seed from being saved:"
%ul
- @seed.errors.full_messages.each do |msg|
%li= msg
.control-group
= f.label 'Crop:', :class => 'control-label'
.controls= collection_select(:seed, :crop_id, Crop.all, :id, :system_name, :selected => @seed.crop_id || @crop.id)
.control-group
= f.label 'Description:', :class => 'control-label'
.controls= f.text_area :description, :rows => 6
.control-group
= f.label 'Quantity:', :class => 'control-label'
.controls
= f.number_field :quantity, :class => 'input-small'
.control-group
= f.label 'Plant before:', :class => 'control-label'
.controls= f.text_field :plant_before, :value => @seed.plant_before ? @seed.plant_before.to_s(:ymd) : '', :class => 'add-datepicker'
.control-group
= f.label 'Willing to trade:', :class => 'control-label'
.controls= f.check_box :tradable
.control-group
= f.label 'Will trade:', :class => 'control-label'
.controls
= f.select(:tradable_to, Seed::TRADABLE_TO_VALUES, {:include_blank => true})
%span.help_inline
- if current_member.location.blank?
Don't forget to
=succeed "." do
=link_to "set your location", edit_member_registration_path
- else
from
=succeed "." do
= current_member.location
=link_to "Change your location.", edit_member_registration_path
.form-actions
= f.submit 'Save', :class => 'btn btn-primary'

View File

@@ -0,0 +1,3 @@
- content_for :title, "Editing seeds"
= render 'form'

View File

@@ -0,0 +1,40 @@
- content_for :title, @owner ? "#{@owner}'s seeds" : "Everyone's seeds"
%p
- if can? :create, Seed
- if @owner
- if @owner == current_member
= link_to 'Add seeds', new_seed_path, :class => 'btn btn-primary'
- else # everyone's seeds
= link_to 'Add seeds', new_seed_path, :class => 'btn btn-primary'
- else
= render :partial => 'shared/signin_signup', :locals => { :to => 'add seeds to your stash' }
- if @seeds.length > 0
%table.table.table-striped
%tr
%th Owner
%th Crop
%th Description
%th Quantity
%th Plant before
%th Willing to trade
%th Will trade
%th From location
%th
- @seeds.each do |seed|
%tr
%td= link_to seed.owner.login_name, seed.owner
%td= link_to seed.crop.system_name, seed.crop
%td= seed.description
%td= seed.quantity
%td= seed.plant_before
%td= seed.tradable ? "Yes" : ""
%td= seed.tradable_to
%td
- if seed.tradable_to
= seed.owner.location.blank? ? "unspecified" : seed.owner.location
%td= link_to 'Details', seed, :class => 'btn btn-mini'
- else
%p There are no seeds to display.

View File

@@ -0,0 +1,3 @@
- content_for :title, "Add seeds"
= render 'form'

View File

@@ -0,0 +1,50 @@
- content_for :title, "#{@seed.owner}'s #{@seed.crop} seeds"
.row
.span6
%p
%b Owner:
= link_to @seed.owner, @seed.owner
%p
%b Quantity:
= @seed.quantity.blank? ? "not specified" : @seed.quantity
%p
%b Plant before:
= @seed.plant_before.to_s
%p
%b Tradable:
= @seed.tradable ? "Yes" : "No"
%p
%b Will trade to:
= @seed.tradable_to ? @seed.tradable_to : "nowhere"
- if @seed.tradable
- if @seed.owner.location.blank?
(from unspecified location)
- if current_member == @seed.owner
= link_to "Set Location", edit_registration_path(current_member), :class => 'btn btn-mini'
- else
(from
= succeed ")" do
=@seed.owner.location
%p
%b Description:
:markdown
#{ @seed.description != "" ? @seed.description : "No description given." }
- if current_member
- if @seed.tradable && current_member != @seed.owner
%p
= link_to "Request seeds", new_notification_path(:recipient_id => @seed.owner.id, :subject => "Interested in your #{@seed.crop} seeds"), :class => 'btn btn-primary'
- else
= render :partial => 'shared/signin_signup', :locals => { :to => 'request seeds' }
- if can? :edit, @seed or can? :destroy, @seed
%p
- if can? :edit, @seed
=link_to 'Edit', edit_seed_path(@seed), :class => 'btn btn-mini'
- if can? :destroy, @seed
=link_to 'Delete', @seed, method: :delete, data: { confirm: 'Are you sure?' }, :class => 'btn btn-mini'
.span6
= render :partial => "crops/index_card", :locals => { :crop => @seed.crop}

View File

@@ -0,0 +1,6 @@
=link_to 'Sign in', new_member_session_path
or
=link_to 'sign up', new_member_registration_path
to
= succeed "." do
= to

View File

@@ -8,7 +8,8 @@ en:
create:
planting: "Please sign in or sign up to plant something."
post: "Please sign in or sign up to post."
seed: "Please sign in or sign up to add seeds."
notification: "Please sign in to send a message."
all: "You don't have permission to create a %{subject}."
all: "Please sign in or sign up to create a %{subject}."
manage:
all: "Not authorized to %{action} %{subject}."

View File

@@ -1,9 +1,10 @@
Growstuff::Application.routes.draw do
resources :photos
devise_for :members, :controllers => { :registrations => "registrations" }
resources :members
resources :photos
resources :seeds
resources :authentications
resources :plantings
@@ -11,7 +12,6 @@ Growstuff::Application.routes.draw do
resources :posts
resources :scientific_names
resources :crops
resources :members
resources :comments
resources :roles
resources :forums

View File

@@ -0,0 +1,13 @@
class CreateSeeds < ActiveRecord::Migration
def change
create_table :seeds do |t|
t.integer :owner_id, :null => false
t.integer :crop_id, :null => false
t.text :description
t.integer :quantity
t.date :use_by
t.timestamps
end
end
end

View File

@@ -0,0 +1,5 @@
class ChangeUseByToPlantBeforeOnSeed < ActiveRecord::Migration
def change
rename_column :seeds, :use_by, :plant_before
end
end

View File

@@ -0,0 +1,6 @@
class AddTradingToSeeds < ActiveRecord::Migration
def change
add_column :seeds, :tradable, :boolean
add_column :seeds, :tradable_to, :string
end
end

View File

@@ -11,7 +11,7 @@
#
# It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20130705104238) do
ActiveRecord::Schema.define(:version => 20130718011247) do
create_table "account_types", :force => true do |t|
t.string "name", :null => false
@@ -234,4 +234,16 @@ ActiveRecord::Schema.define(:version => 20130705104238) do
t.datetime "updated_at", :null => false
end
create_table "seeds", :force => true do |t|
t.integer "owner_id", :null => false
t.integer "crop_id", :null => false
t.text "description"
t.integer "quantity"
t.date "plant_before"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.boolean "tradable"
t.string "tradable_to"
end
end

View File

@@ -0,0 +1,11 @@
require 'spec_helper'
describe SeedsController do
describe "GET index" do
it "picks up owner from params" do
owner = FactoryGirl.create(:member)
get :index, {:owner_id => owner.id}
assigns(:owner).should eq(owner)
end
end
end

16
spec/factories/seeds.rb Normal file
View File

@@ -0,0 +1,16 @@
# Read about factories at https://github.com/thoughtbot/factory_girl
FactoryGirl.define do
factory :seed do
owner
crop
description "MyText"
quantity 1
plant_before "2013-07-15"
factory :tradable_seed do
tradable true
tradable_to "locally"
end
end
end

28
spec/models/seed_spec.rb Normal file
View File

@@ -0,0 +1,28 @@
require 'spec_helper'
describe Seed do
before(:each) do
@seed = FactoryGirl.build(:seed)
end
it 'should save a basic seed' do
@seed.save.should be_true
end
context 'tradable' do
it 'all three valid tradable_to values should work' do
['locally', 'nationally', 'internationally', nil, ''].each do |t|
@seed = FactoryGirl.build(:seed, :tradable_to => t)
@seed.should be_valid
end
end
it 'should refuse invalid tradable_to values' do
@seed = FactoryGirl.build(:seed, :tradable_to => 'not valid')
@seed.should_not be_valid
@seed.errors[:tradable_to].should include("You may only trade seed locally, nationally, or internationally")
end
end
end

View File

@@ -0,0 +1,11 @@
require 'spec_helper'
describe "Seeds" do
describe "GET /seeds" do
it "works! (now write some real specs)" do
# Run the generator again with the --webrat flag if you want to use webrat methods/matchers
get seeds_path
response.status.should be(200)
end
end
end

View File

@@ -0,0 +1,35 @@
require "spec_helper"
describe SeedsController do
describe "routing" do
it "routes to #index" do
get("/seeds").should route_to("seeds#index")
end
it "routes to #new" do
get("/seeds/new").should route_to("seeds#new")
end
it "routes to #show" do
get("/seeds/1").should route_to("seeds#show", :id => "1")
end
it "routes to #edit" do
get("/seeds/1/edit").should route_to("seeds#edit", :id => "1")
end
it "routes to #create" do
post("/seeds").should route_to("seeds#create")
end
it "routes to #update" do
put("/seeds/1").should route_to("seeds#update", :id => "1")
end
it "routes to #destroy" do
delete("/seeds/1").should route_to("seeds#destroy", :id => "1")
end
end
end

View File

@@ -28,7 +28,6 @@ describe "crops/show" do
it "links to the right crop in the planting link" do
render
assert_select("a[href=#{new_planting_path}?crop_id=#{@crop.id}]")
end
context "has plantings" do
before(:each) do
@@ -116,6 +115,29 @@ describe "crops/show" do
end
it 'tells you to sign in/sign up' do
render
rendered.should contain 'Sign in or sign up to plant'
rendered.should contain 'Sign in or sign up to add seed'
end
context 'logged in' do
before(:each) do
@member = FactoryGirl.create(:member)
sign_in @member
controller.stub(:current_user) { @member }
render
end
it "shows a plant this button" do
rendered.should contain "Plant this"
end
it "links to the right crop in the planting link" do
assert_select("a[href=#{new_planting_path}?crop_id=#{@crop.id}]")
end
end
context "logged in and crop wrangler" do
before(:each) do

View File

@@ -43,6 +43,7 @@ describe 'home/index.html.haml', :type => "view" do
:garden => @member.gardens.first
)
assign(:plantings, [@planting])
@seed = FactoryGirl.create(:seed, :owner => @member)
@forum = FactoryGirl.create(:forum, :owner => @member)
@post = FactoryGirl.create(:post, :author => @member)
assign(:posts, [@post])
@@ -62,6 +63,11 @@ describe 'home/index.html.haml', :type => "view" do
assert_select "a[href=#{url_for(@member.gardens.first)}]", "Garden"
end
it 'shows seeds' do
rendered.should contain "Your seed stash"
rendered.should contain "1 variety"
end
it 'shows account type' do
rendered.should contain "Free account"
end

View File

@@ -5,7 +5,8 @@ describe "plantings/show" do
@garden = FactoryGirl.create(:garden, :owner => @member)
@crop = FactoryGirl.create(:tomato)
@planting = assign(:planting,
FactoryGirl.create(:planting, :garden => @garden, :crop => @crop)
FactoryGirl.create(:planting, :garden => @garden, :crop => @crop,
:planted_from => 'cutting')
)
end
@@ -45,7 +46,7 @@ describe "plantings/show" do
it "shows planted_from" do
render
rendered.should contain 'Planted from:'
rendered.should contain 'seed'
rendered.should contain 'cutting'
end
it "doesn't show planted_from if blank" do
@@ -53,7 +54,7 @@ describe "plantings/show" do
@p.save
render
rendered.should_not contain 'Planted from:'
rendered.should_not contain 'seed'
rendered.should_not contain 'cutting'
end
end

View File

@@ -0,0 +1,23 @@
require 'spec_helper'
describe "seeds/edit" do
before(:each) do
@member = FactoryGirl.create(:member)
sign_in @member
controller.stub(:current_user) { @member }
@seed = FactoryGirl.create(:seed, :owner => @member)
end
it "renders the edit seed form" do
render
# Run the generator again with the --webrat flag if you want to use webrat matchers
assert_select "form", :action => seeds_path(@seed), :method => "post" do
assert_select "select#seed_crop_id", :name => "seed[crop_id]"
assert_select "textarea#seed_description", :name => "seed[description]"
assert_select "input#seed_quantity", :name => "seed[quantity]"
assert_select "input#seed_tradable", :name => "seed[tradable]"
assert_select "select#seed_tradable_to", :name => "seed[tradable_to]"
end
end
end

View File

@@ -0,0 +1,35 @@
require 'spec_helper'
describe "seeds/index" do
before(:each) do
@member = FactoryGirl.create(:member)
sign_in @member
controller.stub(:current_user) { @member }
@seed1 = FactoryGirl.create(:seed, :owner => @member)
assign(:seeds, [@seed1, @seed1])
end
it "renders a list of seeds" do
render
assert_select "tr>td", :text => @seed1.crop.system_name, :count => 2
assert_select "tr>td", :text => @seed1.owner.login_name, :count => 2
assert_select "tr>td", :text => @seed1.quantity.to_s, :count => 2
end
context "tradable" do
before(:each) do
@owner = FactoryGirl.create(:london_member)
@seed1 = FactoryGirl.create(:tradable_seed, :owner => @owner)
assign(:seeds, [@seed1, @seed1])
render
end
it "shows tradable seeds" do
assert_select "tr>td", :text => @seed1.tradable_to, :count => 2
end
it "shows location of seed owner" do
assert_select "tr>td", :text => @owner.location, :count => 2
end
end
end

View File

@@ -0,0 +1,49 @@
require 'spec_helper'
describe "seeds/new" do
before(:each) do
@member = FactoryGirl.create(:member)
sign_in @member
controller.stub(:current_user) { @member }
@seed1 = FactoryGirl.create(:seed, :owner => @member)
assign(:seed, @seed1)
end
it "renders new seed form" do
render
assert_select "form", :action => seeds_path, :method => "post" do
assert_select "select#seed_crop_id", :name => "seed[crop_id]"
assert_select "textarea#seed_description", :name => "seed[description]"
assert_select "input#seed_quantity", :name => "seed[quantity]"
assert_select "input#seed_tradable", :name => "seed[tradable]"
assert_select "select#seed_tradable_to", :name => "seed[tradable_to]"
end
end
it 'reminds you to set your location' do
render
rendered.should contain "Don't forget to set your location."
assert_select "a", :text => "set your location"
end
context 'member has location' do
before(:each) do
@member = FactoryGirl.create(:london_member)
sign_in @member
controller.stub(:current_user) { @member }
@seed1 = FactoryGirl.create(:seed, :owner => @member)
assign(:seed, @seed1)
end
it 'shows the location' do
render
rendered.should contain "from #{@member.location}."
end
it 'links to change location' do
render
assert_select "a", :text => "Change your location."
end
end
end

View File

@@ -0,0 +1,63 @@
require 'spec_helper'
describe "seeds/show" do
before(:each) do
controller.stub(:current_user) { nil }
@seed = FactoryGirl.create(:seed)
assign(:seed, @seed)
end
it "renders attributes in <p>" do
render
rendered.should contain @seed.crop.system_name
end
context "tradable" do
before(:each) do
@owner = FactoryGirl.create(:london_member)
assign(:seed, FactoryGirl.create(:tradable_seed,
:owner => @owner))
# note current_member is not the owner of this seed
@member = FactoryGirl.create(:member)
sign_in @member
controller.stub(:current_user) { @member }
end
it "shows tradable attributes" do
render
rendered.should contain "Tradable: Yes"
rendered.should contain "Will trade to: locally"
end
it "shows location of seed owner" do
render
rendered.should contain @owner.location
end
context 'with no location' do
before(:each) do
@owner = FactoryGirl.create(:member) # no location
sign_in @owner
controller.stub(:current_user) { @owner }
assign(:seed, FactoryGirl.create(:tradable_seed, :owner => @owner))
end
it 'says "from unspecified location"' do
render
rendered.should contain "(from unspecified location)"
end
it "links to profile to set location" do
render
assert_select "a[href=#{url_for(edit_member_registration_path)}]", :text => "Set Location"
end
end
it "shows button to send message" do
render
rendered.should contain "Request seeds"
end
end
end