mirror of
https://github.com/Growstuff/growstuff.git
synced 2026-05-18 13:38:24 -04:00
Merge branch 'dev' into members_nearby
Conflicts: spec/factories/member.rb
This commit is contained in:
@@ -1,5 +1,27 @@
|
||||
class HomeController < ApplicationController
|
||||
skip_authorize_resource
|
||||
|
||||
def index
|
||||
@member_count = Member.confirmed.count
|
||||
@crop_count = Crop.count
|
||||
@planting_count = Planting.count
|
||||
@garden_count = Garden.count
|
||||
|
||||
@interesting_members = Member.interesting.limit(6)
|
||||
|
||||
# customise what we show on the homepage based on whether you're
|
||||
# logged in or not.
|
||||
@member = current_member
|
||||
@plantings = current_member ?
|
||||
current_member.plantings.limit(10) :
|
||||
Planting.limit(10)
|
||||
@posts = current_member ?
|
||||
current_member.posts.limit(10) :
|
||||
Post.limit(10)
|
||||
|
||||
respond_to do |format|
|
||||
format.html # index.html.haml
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -9,7 +9,7 @@ class MembersController < ApplicationController
|
||||
end
|
||||
|
||||
def show
|
||||
@member = Member.find_confirmed(params[:id])
|
||||
@member = Member.confirmed.find(params[:id])
|
||||
@posts = @member.posts
|
||||
# The garden form partial is called from the "New Garden" tab;
|
||||
# it requires a garden to be passed in @garden.
|
||||
|
||||
@@ -1,18 +1,15 @@
|
||||
class NotificationsController < ApplicationController
|
||||
load_and_authorize_resource
|
||||
# GET /notifications
|
||||
# GET /notifications.json
|
||||
def index
|
||||
@notifications = Notification.find_all_by_recipient_id(current_member)
|
||||
|
||||
respond_to do |format|
|
||||
format.html # index.html.erb
|
||||
format.json { render json: @notifications }
|
||||
end
|
||||
end
|
||||
|
||||
# GET /notifications/1
|
||||
# GET /notifications/1.json
|
||||
def show
|
||||
@notification = Notification.find(params[:id])
|
||||
@notification.read = true
|
||||
@@ -20,19 +17,42 @@ class NotificationsController < ApplicationController
|
||||
|
||||
respond_to do |format|
|
||||
format.html # show.html.erb
|
||||
format.json { render json: @notification }
|
||||
end
|
||||
end
|
||||
|
||||
# GET /notifications/new
|
||||
|
||||
def new
|
||||
@notification = Notification.new
|
||||
@recipient = Member.find_by_id(params[:recipient_id])
|
||||
|
||||
respond_to do |format|
|
||||
format.html # new.html.erb
|
||||
end
|
||||
end
|
||||
|
||||
# DELETE /notifications/1
|
||||
# DELETE /notifications/1.json
|
||||
def destroy
|
||||
@notification = Notification.find(params[:id])
|
||||
@notification.destroy
|
||||
|
||||
respond_to do |format|
|
||||
format.html { redirect_to notifications_url }
|
||||
format.json { head :no_content }
|
||||
end
|
||||
end
|
||||
|
||||
# POST /notifications
|
||||
def create
|
||||
params[:notification][:sender_id] = current_member.id
|
||||
@notification = Notification.new(params[:notification])
|
||||
@recipient = Member.find_by_id(params[:notification][:recipient_id])
|
||||
|
||||
respond_to do |format|
|
||||
if @notification.save
|
||||
format.html { redirect_to @recipient, notice: 'Message was successfully sent.' }
|
||||
else
|
||||
format.html { render action: "new" }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -18,6 +18,7 @@ class PostsController < ApplicationController
|
||||
# GET /posts/1.json
|
||||
def show
|
||||
@post = Post.find(params[:id])
|
||||
@comments = @post.comments
|
||||
|
||||
respond_to do |format|
|
||||
format.html # show.html.haml
|
||||
|
||||
@@ -7,6 +7,7 @@ class Ability
|
||||
# everyone can do these things, even non-logged in
|
||||
can :read, :all
|
||||
cannot :read, Notification
|
||||
cannot :create, Notification
|
||||
|
||||
# nobody should be able to view this except admins
|
||||
cannot :read, Role
|
||||
@@ -28,7 +29,13 @@ class Ability
|
||||
# can read/delete notifications that were sent to them
|
||||
can :read, Notification, :recipient_id => member.id
|
||||
can :destroy, Notification, :recipient_id => member.id
|
||||
# note we don't support create/update for notifications
|
||||
# can send a private message to anyone but themselves
|
||||
# note: sadly, we can't test for this from the view, but it works
|
||||
# for the model/controller
|
||||
can :create, Notification do |n|
|
||||
n.recipient_id != member.id
|
||||
end
|
||||
# note we don't support update for notifications
|
||||
|
||||
# only crop wranglers can create/edit/destroy crops
|
||||
if member.has_role? :crop_wrangler
|
||||
|
||||
@@ -3,6 +3,8 @@ class Comment < ActiveRecord::Base
|
||||
belongs_to :author, :class_name => 'Member'
|
||||
belongs_to :post
|
||||
|
||||
default_scope order("created_at asc")
|
||||
|
||||
after_create do
|
||||
recipient = self.post.author.id
|
||||
sender = self.author.id
|
||||
|
||||
@@ -10,7 +10,15 @@ class Member < ActiveRecord::Base
|
||||
has_and_belongs_to_many :roles
|
||||
has_many :notifications, :foreign_key => 'recipient_id'
|
||||
has_many :sent_notifications, :foreign_key => 'sender_id'
|
||||
|
||||
default_scope order("lower(login_name) asc")
|
||||
scope :confirmed, where('confirmed_at IS NOT NULL')
|
||||
scope :located, where('location IS NOT NULL')
|
||||
scope :recently_signed_in, reorder('updated_at DESC')
|
||||
|
||||
# this is used on the signed-out homepage so we're basically
|
||||
# just trying to select some members who look good.
|
||||
scope :interesting, confirmed.located.recently_signed_in
|
||||
|
||||
# Include default devise modules. Others available are:
|
||||
# :token_authenticatable, :confirmable,
|
||||
@@ -68,14 +76,6 @@ class Member < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
|
||||
def self.find_confirmed(params)
|
||||
find(params, :conditions => 'confirmed_at IS NOT NULL')
|
||||
end
|
||||
|
||||
def self.confirmed
|
||||
where('confirmed_at IS NOT NULL')
|
||||
end
|
||||
|
||||
def to_s
|
||||
return login_name
|
||||
end
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
class Notification < ActiveRecord::Base
|
||||
attr_accessible :sender_id, :recipient_id,
|
||||
attr_accessible :sender_id, :recipient_id,
|
||||
:subject, :body, :post_id, :read
|
||||
|
||||
belongs_to :sender, :class_name => 'Member'
|
||||
|
||||
@@ -2,17 +2,29 @@ class Planting < ActiveRecord::Base
|
||||
extend FriendlyId
|
||||
friendly_id :planting_slug, use: :slugged
|
||||
|
||||
attr_accessible :crop_id, :description, :garden_id, :planted_at, :quantity,
|
||||
:planted_at_string
|
||||
attr_accessible :crop_id, :description, :garden_id, :planted_at,
|
||||
:quantity, :sunniness, :planted_at_string
|
||||
|
||||
belongs_to :garden
|
||||
belongs_to :crop
|
||||
|
||||
delegate :default_scientific_name,
|
||||
default_scope order("created_at desc")
|
||||
|
||||
delegate :system_name,
|
||||
:en_wikipedia_url,
|
||||
:default_scientific_name,
|
||||
:plantings_count,
|
||||
:to => :crop,
|
||||
:prefix => true
|
||||
|
||||
default_scope order("created_at desc")
|
||||
|
||||
SUNNINESS_VALUES = %w(sun semi-shade shade)
|
||||
validates :sunniness, :inclusion => { :in => SUNNINESS_VALUES,
|
||||
:message => "%{value} is not a valid sunniness value" },
|
||||
:allow_nil => true,
|
||||
:allow_blank => true
|
||||
|
||||
def planting_slug
|
||||
"#{owner.login_name}-#{garden}-#{crop}".downcase.gsub(' ', '-')
|
||||
end
|
||||
@@ -34,6 +46,6 @@ class Planting < ActiveRecord::Base
|
||||
end
|
||||
|
||||
def planted_at_string=(str)
|
||||
self.planted_at = Time.parse(str)
|
||||
self.planted_at = str == '' ? nil : Time.parse(str)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
|
||||
.thumbnail(style='height: 200px')
|
||||
.thumbnail(style='height: 220px')
|
||||
- if crop
|
||||
= link_to image_tag('http://placehold.it/150x150', :alt => '', :class => 'img-rounded'), crop
|
||||
%p
|
||||
|
||||
@@ -1,6 +1,15 @@
|
||||
%h1
|
||||
= Growstuff::Application.config.site_name
|
||||
%h1= Growstuff::Application.config.site_name
|
||||
|
||||
%p #{Growstuff::Application.config.site_name} is a community of food gardeners working together to build an open source platform to track, share, and discuss edible gardens and sustainable lifestyles. You can join us right now and be part of growing our website, from seed to harvest. We welcome you regardless of your experience, and invite you to be part of our development process.
|
||||
%p
|
||||
#{Growstuff::Application.config.site_name} is a community of food gardeners. We're building an open source platform to track, share, and discuss edible gardens and sustainable lifestyles. We offer growing information tailored to your location, and help you connect with your local food-growing community.
|
||||
|
||||
%p= link_to 'Learn more', 'http://wiki.growstuff.org/', :class => 'btn btn-primary btn-large'
|
||||
%strong
|
||||
So far,
|
||||
= link_to "#{@member_count} members", members_path
|
||||
have planted
|
||||
= link_to "#{@crop_count} crops", crops_path
|
||||
#{@planting_count} times in #{@garden_count} gardens.
|
||||
|
||||
You could be one of them. Sign up for a free account and start tracking your food garden today.
|
||||
%p
|
||||
= link_to 'Join now', new_member_registration_path, :class => 'btn btn-primary btn-large'
|
||||
|
||||
@@ -45,78 +45,30 @@
|
||||
.row
|
||||
.span6
|
||||
%h2 Your recent plantings
|
||||
- if current_member.plantings.count > 0
|
||||
%ul
|
||||
- current_member.plantings.limit(10).each do |p|
|
||||
%li
|
||||
= link_to "#{p.crop.system_name} in #{p.location}", p
|
||||
- if p.planted_at
|
||||
on
|
||||
= p.planted_at.to_s(:date)
|
||||
- else
|
||||
%p None yet.
|
||||
- if can? :create, Planting
|
||||
%p= link_to "Plant something", new_planting_path, :class => 'btn btn-primary'
|
||||
= render :partial => 'shared/recent_plantings'
|
||||
|
||||
.span6
|
||||
%h2 Your recent posts
|
||||
- if current_member.posts.count > 0
|
||||
%ul
|
||||
- current_member.posts.limit(10).each do |p|
|
||||
%li
|
||||
= link_to p.subject, p
|
||||
- if p.forum
|
||||
in
|
||||
= link_to p.forum.name, p.forum
|
||||
on
|
||||
= p.created_at.to_s(:date)
|
||||
- else
|
||||
%p None yet.
|
||||
- if can? :create, Planting
|
||||
%p= link_to "Post something", new_post_path, :class => 'btn btn-primary'
|
||||
|
||||
.span6
|
||||
|
||||
= render :partial => 'shared/recent_posts'
|
||||
|
||||
- else
|
||||
.visible-desktop.visible-tablet
|
||||
.hero-unit
|
||||
= render :partial => 'blurb'
|
||||
|
||||
.visible-phone
|
||||
= render :partial => 'blurb'
|
||||
|
||||
.row
|
||||
.span3
|
||||
%h2 Track
|
||||
%p
|
||||
Track your garden, your
|
||||
= link_to 'crops', crops_path
|
||||
, and everything to do with them. |
|
||||
Remember what you planted or harvested, and plan for what you want to do next. |
|
||||
Import and export your data to a spreadsheet or other format.
|
||||
- if @interesting_members
|
||||
%h2 Some of our members
|
||||
%ul.thumbnails
|
||||
- @interesting_members.each do |m|
|
||||
%li.span2
|
||||
= render :partial => "members/thumbnail", :locals => { :member => m }
|
||||
|
||||
.span3
|
||||
%h2 Connect
|
||||
%p
|
||||
Connect with friends, people who live in your area, or others |
|
||||
who share your gardening interests. Show off your crops and |
|
||||
harvests, share updates and tips, and
|
||||
= link_to 'see', posts_path
|
||||
what everyone else is doing, too.
|
||||
.span3
|
||||
%h2 Learn
|
||||
%p
|
||||
Browse our
|
||||
= link_to 'crops', crops_path
|
||||
database and learn about food plants for your
|
||||
climate and garden type. Read other
|
||||
= link_to "members' posts", posts_path
|
||||
and tips, or post questions and discuss food gardening issues in our forums.
|
||||
.span3
|
||||
%h2 Trade
|
||||
%p
|
||||
Use #{ Growstuff::Application.config.site_name } as a marketplace
|
||||
for everything related to food gardens. Buy and sell, trade,
|
||||
or give away anything from seeds to garden supplies, or find
|
||||
events and businesses in your area.
|
||||
.row
|
||||
.span6
|
||||
%h2 Recent plantings
|
||||
= render :partial => 'shared/recent_plantings'
|
||||
.span6
|
||||
%h2 Recent posts
|
||||
= render :partial => 'shared/recent_posts'
|
||||
|
||||
@@ -25,4 +25,4 @@
|
||||
/ Placed at the end of the document so the pages load faster
|
||||
= javascript_include_tag "application"
|
||||
|
||||
= Growstuff::Application.config.analytics_code
|
||||
!= Growstuff::Application.config.analytics_code
|
||||
|
||||
8
app/views/members/_thumbnail.html.haml
Normal file
8
app/views/members/_thumbnail.html.haml
Normal file
@@ -0,0 +1,8 @@
|
||||
.thumbnail(style="height: 220px")
|
||||
= render :partial => "members/avatar", :locals => { :member => member }
|
||||
%p
|
||||
= link_to member.to_s, member
|
||||
- if member.location
|
||||
%br/
|
||||
%i
|
||||
%small= member.location
|
||||
@@ -11,9 +11,7 @@
|
||||
%ul.thumbnails
|
||||
- @members.each do |m|
|
||||
%li.span2
|
||||
.thumbnail(style="height: 190px")
|
||||
= render :partial => "members/avatar", :locals => { :member => m }
|
||||
= link_to m.to_s, m
|
||||
= render :partial => "members/thumbnail", :locals => { :member => m }
|
||||
|
||||
%div.pagination
|
||||
= page_entries_info @members, :model => "members"
|
||||
|
||||
@@ -6,6 +6,11 @@
|
||||
.span3
|
||||
= render :partial => "members/avatar", :locals => { :member => @member }
|
||||
|
||||
-if can? :create, Notification and current_member != @member
|
||||
%p
|
||||
%br/
|
||||
=link_to 'Send Message', new_notification_path(:sender_id => current_member.id, :recipient_id => @member.id), :class => 'btn btn-primary'
|
||||
|
||||
%p
|
||||
= "Member since: #{@member.created_at.to_s(:date)}"
|
||||
- if @member.location.to_s != ''
|
||||
|
||||
22
app/views/notifications/_form.html.haml
Normal file
22
app/views/notifications/_form.html.haml
Normal file
@@ -0,0 +1,22 @@
|
||||
= form_for @notification do |f|
|
||||
- if @notification.errors.any?
|
||||
#error_explanation
|
||||
%h2= "#{pluralize(@post.errors.count, "error")} prohibited this message from being sent:"
|
||||
%ul
|
||||
- @notification.errors.full_messages.each do |msg|
|
||||
%li= msg
|
||||
|
||||
.field
|
||||
= f.hidden_field :recipient_id, :value => @recipient.id
|
||||
|
||||
%p
|
||||
To:
|
||||
= link_to @recipient, @recipient
|
||||
= label_tag :notification, "Subject:"
|
||||
= f.text_field :subject, :class => 'input-block-level'
|
||||
= label_tag :body, "Type your message here:"
|
||||
= f.text_area :body, :rows => 12, :class => 'input-block-level'
|
||||
%span.help-block
|
||||
= render :partial => "shared/markdown_help"
|
||||
|
||||
= f.submit "Send", :class => 'btn btn-primary'
|
||||
@@ -23,9 +23,9 @@
|
||||
%strong= link_to n.subject, notification_path(n)
|
||||
%td
|
||||
- if n.read
|
||||
= n.created_at.to_s(:date)
|
||||
= n.created_at
|
||||
- else
|
||||
%strong= n.created_at.to_s(:date)
|
||||
%strong= n.created_at
|
||||
%td
|
||||
= link_to 'Delete', n, method: :delete, data: { confirm: 'Are you sure?' }, :class => 'btn btn-mini'
|
||||
- else
|
||||
|
||||
4
app/views/notifications/new.html.haml
Normal file
4
app/views/notifications/new.html.haml
Normal file
@@ -0,0 +1,4 @@
|
||||
= content_for :title, "Send a message to #{@recipient}"
|
||||
|
||||
=render 'form'
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
From
|
||||
= link_to @notification.sender, @notification.sender
|
||||
on
|
||||
= @notification.created_at.to_s(:date)
|
||||
= @notification.created_at
|
||||
|
||||
- if @notification.post_id
|
||||
in response to:
|
||||
|
||||
@@ -3,18 +3,18 @@
|
||||
|
||||
%p
|
||||
You have received a message from
|
||||
= link_to @notification.sender.login_name, url_for(:controller => 'members', :action => 'show', :id => @notification.sender.id, :only_path => false )
|
||||
on #{site_name} at #{@notification.created_at.to_s(:date)}
|
||||
= link_to @notification.sender.login_name, member_url(@notification.sender)
|
||||
on #{site_name} at #{@notification.created_at}
|
||||
- if @notification.post
|
||||
in response to
|
||||
= link_to @notification.post.subject, url_for(:controller => 'posts', :action => 'show', :id => @notification.post.id, :only_path => false)
|
||||
= link_to @notification.post.subject, post_url(@notification.post)
|
||||
\.
|
||||
%blockquote
|
||||
:markdown
|
||||
#{strip_tags @notification.body}
|
||||
|
||||
%p
|
||||
= link_to "View this message in your inbox", url_for(:controller => 'notifications', :action => 'show', :id => @notification.id, :only_path => false)
|
||||
= link_to "View this message in your inbox", notification_url(@notification)
|
||||
%br/
|
||||
= link_to "Turn off these notifications", edit_member_registration_url
|
||||
|
||||
|
||||
@@ -20,6 +20,10 @@
|
||||
= f.label 'How many?', :class => 'control-label'
|
||||
.controls
|
||||
= f.number_field :quantity, :class => 'input-small'
|
||||
.control-group
|
||||
= f.label 'Sun or shade?', :class => 'control-label'
|
||||
.controls
|
||||
= f.select(:sunniness, Planting::SUNNINESS_VALUES, {:include_blank => true})
|
||||
.control-group
|
||||
= f.label 'Tell us more about it', :class => 'control-label'
|
||||
.controls= f.text_area :description, :rows => 6
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
%p
|
||||
Planted
|
||||
- if planting.planted_at
|
||||
= planting.planted_at.to_s(:date)
|
||||
= planting.planted_at
|
||||
in
|
||||
= link_to planting.location, planting.garden
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
.span6
|
||||
%p
|
||||
%b Planted:
|
||||
= @planting.planted_at ? @planting.planted_at.to_s(:date) : "not specified"
|
||||
= @planting.planted_at ? @planting.planted_at : "not specified"
|
||||
%p
|
||||
%b Where:
|
||||
=link_to "#{@planting.owner}'s", @planting.owner
|
||||
@@ -15,6 +15,12 @@
|
||||
%b Quantity:
|
||||
= @planting.quantity != 0 ? @planting.quantity : "not specified"
|
||||
|
||||
- if ! @planting.sunniness.blank?
|
||||
%p
|
||||
%b Sun or shade?
|
||||
= @planting.sunniness
|
||||
|
||||
|
||||
- if can? :edit, @planting or can? :destroy, @planting
|
||||
%p
|
||||
- if can? :edit, @planting
|
||||
|
||||
@@ -12,10 +12,10 @@
|
||||
|
||||
|
||||
%a{:name => "comments"}
|
||||
- if @post.comments.length > 0
|
||||
- if @comments
|
||||
%h2
|
||||
=pluralize(@post.comments.length, "comment")
|
||||
- @post.comments.each do |c|
|
||||
=pluralize(@comments.length, "comment")
|
||||
- @comments.each do |c|
|
||||
= render :partial => "comments/single", :locals => { :comment => c }
|
||||
|
||||
- else
|
||||
|
||||
12
app/views/shared/_recent_plantings.html.haml
Normal file
12
app/views/shared/_recent_plantings.html.haml
Normal file
@@ -0,0 +1,12 @@
|
||||
- if @plantings
|
||||
%ul
|
||||
- @plantings.each do |p|
|
||||
%li
|
||||
= link_to "#{p.crop_system_name} in #{p.location}", p
|
||||
- if p.planted_at
|
||||
on
|
||||
= p.planted_at
|
||||
- else
|
||||
%p None yet.
|
||||
- if can? :create, Planting
|
||||
%p= link_to "Plant something", new_planting_path, :class => 'btn btn-primary'
|
||||
17
app/views/shared/_recent_posts.html.haml
Normal file
17
app/views/shared/_recent_posts.html.haml
Normal file
@@ -0,0 +1,17 @@
|
||||
- if @posts
|
||||
%ul
|
||||
- @posts.each do |p|
|
||||
%li
|
||||
= link_to p.subject, p
|
||||
- unless @member
|
||||
posted by
|
||||
= link_to p.author, p.author
|
||||
- if p.forum
|
||||
in
|
||||
= link_to p.forum.name, p.forum
|
||||
on
|
||||
= p.created_at.to_s(:date)
|
||||
- else
|
||||
%p None yet.
|
||||
- if can? :create, Post
|
||||
%p= link_to "Post something", new_post_path, :class => 'btn btn-primary'
|
||||
@@ -1 +1,7 @@
|
||||
Time::DATE_FORMATS[:default] = '%B %d, %Y at %H:%M'
|
||||
Date::DATE_FORMATS[:default] = "%B %d, %Y"
|
||||
|
||||
Time::DATE_FORMATS[:date] = "%B %d, %Y"
|
||||
Date::DATE_FORMATS[:date] = "%B %d, %Y"
|
||||
|
||||
Time::DATE_FORMATS[:datetime] = '%B %d, %Y at %H:%M'
|
||||
|
||||
5
db/migrate/20130329045744_add_sunniness_to_planting.rb
Normal file
5
db/migrate/20130329045744_add_sunniness_to_planting.rb
Normal file
@@ -0,0 +1,5 @@
|
||||
class AddSunninessToPlanting < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :plantings, :sunniness, :string
|
||||
end
|
||||
end
|
||||
@@ -11,7 +11,7 @@
|
||||
#
|
||||
# It's strongly recommended to check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(:version => 20130327120024) do
|
||||
ActiveRecord::Schema.define(:version => 20130329045744) do
|
||||
|
||||
create_table "comments", :force => true do |t|
|
||||
t.integer "post_id", :null => false
|
||||
@@ -116,6 +116,7 @@ ActiveRecord::Schema.define(:version => 20130327120024) do
|
||||
t.datetime "created_at", :null => false
|
||||
t.datetime "updated_at", :null => false
|
||||
t.string "slug"
|
||||
t.string "sunniness"
|
||||
end
|
||||
|
||||
add_index "plantings", ["slug"], :name => "index_plantings_on_slug", :unique => true
|
||||
|
||||
39
spec/controllers/home_controller_spec.rb
Normal file
39
spec/controllers/home_controller_spec.rb
Normal file
@@ -0,0 +1,39 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe HomeController do
|
||||
|
||||
describe "GET index" do
|
||||
it "assigns counts" do
|
||||
@planting = FactoryGirl.create(:planting)
|
||||
get :index, {}
|
||||
assigns(:garden_count).should == 2 # auto-created for member and planting
|
||||
assigns(:planting_count).should == 1
|
||||
assigns(:crop_count).should == 1
|
||||
assigns(:member_count).should == 1
|
||||
end
|
||||
|
||||
it "assigns posts and plantings" do
|
||||
@post = FactoryGirl.create(:post)
|
||||
@planting = FactoryGirl.create(:planting)
|
||||
get :index, {}
|
||||
assigns(:posts).should eq [@post]
|
||||
assigns(:plantings).should eq [@planting]
|
||||
end
|
||||
|
||||
it 'assigns interesting members' do
|
||||
@member = FactoryGirl.create(:geolocated_member)
|
||||
get :index, {}
|
||||
assigns(:interesting_members).should eq [@member]
|
||||
end
|
||||
|
||||
context 'logged in' do
|
||||
|
||||
login_member
|
||||
|
||||
it 'assigns member' do
|
||||
get :index, {}
|
||||
assigns(:member).should be_an_instance_of Member
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -5,7 +5,22 @@ describe NotificationsController do
|
||||
login_member
|
||||
|
||||
def valid_attributes
|
||||
{ "recipient_id" => subject.current_member.id }
|
||||
{
|
||||
"recipient_id" => subject.current_member.id,
|
||||
"sender_id" => FactoryGirl.create(:member).id
|
||||
}
|
||||
end
|
||||
|
||||
# this gets a bit confused because for most of the notification tests
|
||||
# (reading, etc) the logged in member needs to be the recipient.
|
||||
# However, for sending private messages (create, etc) the logged in
|
||||
# member needs to be the sender. Hence this separate set of
|
||||
# attributes.
|
||||
def valid_attributes_for_sender
|
||||
{
|
||||
"sender_id" => subject.current_member.id,
|
||||
"recipient_id" => FactoryGirl.create(:member).id
|
||||
}
|
||||
end
|
||||
|
||||
def valid_session
|
||||
@@ -36,6 +51,19 @@ describe NotificationsController do
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET new" do
|
||||
it "assigns a new notification as @notification" do
|
||||
get :new, {}
|
||||
assigns(:notification).should be_a_new(Notification)
|
||||
end
|
||||
|
||||
it "assigns a recipient" do
|
||||
@recipient = FactoryGirl.create(:member)
|
||||
get :new, {:recipient_id => @recipient.id }
|
||||
assigns(:recipient).should be_an_instance_of(Member)
|
||||
end
|
||||
end
|
||||
|
||||
describe "DELETE destroy" do
|
||||
it "destroys the requested notification" do
|
||||
notification = FactoryGirl.create(:notification, :recipient_id => subject.current_member.id)
|
||||
@@ -51,4 +79,41 @@ describe NotificationsController do
|
||||
end
|
||||
end
|
||||
|
||||
describe "POST create" do
|
||||
describe "with valid params" do
|
||||
it "creates a new notification" do
|
||||
expect {
|
||||
post :create, {:notification => valid_attributes_for_sender}
|
||||
}.to change(Notification, :count).by(1)
|
||||
end
|
||||
|
||||
it "assigns a newly created notification as @notification" do
|
||||
post :create, {:notification => valid_attributes_for_sender}
|
||||
assigns(:notification).should be_a(Notification)
|
||||
assigns(:notification).should be_persisted
|
||||
end
|
||||
|
||||
it "redirects to the recipient's profile" do
|
||||
@recipient = FactoryGirl.create(:member)
|
||||
post :create, { :notification => { :recipient_id => @recipient.id } }
|
||||
response.should redirect_to(@recipient)
|
||||
end
|
||||
end
|
||||
|
||||
describe "with invalid params" do
|
||||
it "assigns a newly created but unsaved notification as @notification" do
|
||||
# Trigger the behavior that occurs when invalid params are submitted
|
||||
Notification.any_instance.stub(:save).and_return(false)
|
||||
post :create, {:notification => {}}
|
||||
assigns(:notification).should be_a_new(Notification)
|
||||
end
|
||||
|
||||
it "re-renders the 'new' template" do
|
||||
# Trigger the behavior that occurs when invalid params are submitted
|
||||
Notification.any_instance.stub(:save).and_return(false)
|
||||
post :create, {:notification => {}}
|
||||
response.should render_template("new")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Read about factories at https://github.com/thoughtbot/factory_girl
|
||||
|
||||
FactoryGirl.define do
|
||||
factory :notification do
|
||||
factory :notification, aliases: [:message] do
|
||||
sender
|
||||
recipient
|
||||
subject "MyString"
|
||||
|
||||
@@ -2,8 +2,9 @@ FactoryGirl.define do
|
||||
factory :planting do
|
||||
garden
|
||||
crop
|
||||
planted_at Time.now
|
||||
planted_at Date.today
|
||||
quantity 33
|
||||
description "This is a *really* good plant."
|
||||
sunniness 'sun'
|
||||
end
|
||||
end
|
||||
|
||||
@@ -7,16 +7,34 @@ describe Ability do
|
||||
@ability = Ability.new(@member)
|
||||
end
|
||||
|
||||
it 'member can view their own notifications' do
|
||||
@notification = FactoryGirl.create(:notification, :recipient => @member)
|
||||
@ability.should be_able_to(:read, @notification)
|
||||
end
|
||||
context "notifications" do
|
||||
it 'member can view their own notifications' do
|
||||
@notification = FactoryGirl.create(:notification, :recipient => @member)
|
||||
@ability.should be_able_to(:read, @notification)
|
||||
end
|
||||
|
||||
it "member can't view someone else's notifications" do
|
||||
@notification = FactoryGirl.create(:notification,
|
||||
:recipient => FactoryGirl.create(:member)
|
||||
)
|
||||
@ability.should_not be_able_to(:read, @notification)
|
||||
it "member can't view someone else's notifications" do
|
||||
@notification = FactoryGirl.create(:notification,
|
||||
:recipient => FactoryGirl.create(:member)
|
||||
)
|
||||
@ability.should_not be_able_to(:read, @notification)
|
||||
end
|
||||
it "member can't send messages to themself" do
|
||||
@ability.should_not be_able_to(:create,
|
||||
FactoryGirl.create(:notification,
|
||||
:recipient => @member,
|
||||
:sender => @member
|
||||
)
|
||||
)
|
||||
end
|
||||
it "member can send messages to someone else" do
|
||||
@ability.should be_able_to(:create,
|
||||
FactoryGirl.create(:notification,
|
||||
:recipient => FactoryGirl.create(:member),
|
||||
:sender => @member
|
||||
)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context "crop wrangling" do
|
||||
|
||||
@@ -199,4 +199,40 @@ describe 'member' do
|
||||
end
|
||||
end
|
||||
|
||||
context 'confirmed scope' do
|
||||
before(:each) do
|
||||
@member1 = FactoryGirl.create(:member)
|
||||
@member2 = FactoryGirl.create(:member)
|
||||
end
|
||||
|
||||
it 'sees confirmed members' do
|
||||
Member.confirmed.count.should == 2
|
||||
end
|
||||
|
||||
it 'ignores unconfirmed members' do
|
||||
@member3 = FactoryGirl.create(:unconfirmed_member)
|
||||
Member.confirmed.count.should == 2
|
||||
end
|
||||
end
|
||||
|
||||
context 'interesting scope' do
|
||||
|
||||
# active members are defined as:
|
||||
# 1) confirmed
|
||||
# 2) ordered by the most recent sign in
|
||||
it 'finds interesting members' do
|
||||
@member1 = FactoryGirl.create(:geolocated_member)
|
||||
@member2 = FactoryGirl.create(:geolocated_member)
|
||||
@member3 = FactoryGirl.create(:geolocated_member)
|
||||
@member4 = FactoryGirl.create(:unconfirmed_member)
|
||||
|
||||
@member1.updated_at = 3.days.ago
|
||||
@member2.updated_at = 2.days.ago
|
||||
@member3.updated_at = 1.days.ago
|
||||
|
||||
Member.interesting.should eq [ @member3, @member2, @member1 ]
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -19,6 +19,12 @@ describe Planting do
|
||||
@planting.location.should match /^member\d+'s Springfield Community Garden$/
|
||||
end
|
||||
|
||||
it "sorts plantings in descending order of creation" do
|
||||
@planting1 = FactoryGirl.create(:planting)
|
||||
@planting2 = FactoryGirl.create(:planting)
|
||||
Planting.first.should eq @planting2
|
||||
end
|
||||
|
||||
it "should have a slug" do
|
||||
@planting.slug.should match /^member\d+-springfield-community-garden-tomato$/
|
||||
end
|
||||
@@ -33,9 +39,51 @@ describe Planting do
|
||||
@planting.planted_at.should == Time.local(2013, 03, 01)
|
||||
end
|
||||
|
||||
it 'should accept blank dates' do
|
||||
@planting.planted_at_string = ''
|
||||
@planting.planted_at.should == nil
|
||||
end
|
||||
|
||||
it "should output dates in ISO format" do
|
||||
@planting.planted_at = Time.local(2013, 03, 01)
|
||||
@planting.planted_at_string.should == "2013-03-01"
|
||||
end
|
||||
|
||||
it 'should sort in reverse creation order' do
|
||||
@planting2 = FactoryGirl.create(:planting)
|
||||
Planting.first.should eq @planting2
|
||||
end
|
||||
|
||||
context 'delegation' do
|
||||
it 'system name' do
|
||||
@planting.crop_system_name.should eq @planting.crop.system_name
|
||||
end
|
||||
it 'wikipedia url' do
|
||||
@planting.crop_en_wikipedia_url.should eq @planting.crop.en_wikipedia_url
|
||||
end
|
||||
it 'default scientific name' do
|
||||
@planting.crop_default_scientific_name.should eq @planting.crop.default_scientific_name
|
||||
end
|
||||
it 'plantings count' do
|
||||
@planting.crop_plantings_count.should eq @planting.crop.plantings_count
|
||||
end
|
||||
end
|
||||
|
||||
it 'should have a sunniness value' do
|
||||
@planting.sunniness.should eq 'sun'
|
||||
end
|
||||
|
||||
it 'all three valid sunniness values should work' do
|
||||
['sun', 'shade', 'semi-shade', nil, ''].each do |s|
|
||||
@planting = FactoryGirl.build(:planting, :sunniness => s)
|
||||
@planting.should be_valid
|
||||
end
|
||||
end
|
||||
|
||||
it 'should refuse invalid sunniness values' do
|
||||
@planting = FactoryGirl.build(:planting, :sunniness => 'not valid')
|
||||
@planting.should_not be_valid
|
||||
@planting.errors[:sunniness].should include("not valid is not a valid sunniness value")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -3,12 +3,33 @@ require 'spec_helper'
|
||||
describe 'home/index.html.haml', :type => "view" do
|
||||
context 'logged out' do
|
||||
before(:each) do
|
||||
@member = FactoryGirl.create(:geolocated_member)
|
||||
@member.updated_at = 2.days.ago
|
||||
@post = FactoryGirl.create(:post, :author => @member)
|
||||
@planting = FactoryGirl.create(:planting, :garden => @member.gardens.first)
|
||||
controller.stub(:current_user) { nil }
|
||||
assign(:interesting_members, [@member])
|
||||
assign(:plantings, [@planting])
|
||||
assign(:posts, [@post])
|
||||
render
|
||||
end
|
||||
|
||||
it 'should have description' do
|
||||
it 'has description' do
|
||||
rendered.should contain 'is a community of food gardeners'
|
||||
rendered.should contain 'We welcome you regardless of your experience, and invite you to be part of our development process.'
|
||||
end
|
||||
|
||||
it 'show recent posts' do
|
||||
rendered.should contain @post.subject
|
||||
end
|
||||
|
||||
it 'show recent plantings' do
|
||||
rendered.should contain @planting.crop_system_name
|
||||
rendered.should contain @planting.garden.name
|
||||
end
|
||||
|
||||
it 'show interesting members' do
|
||||
rendered.should contain @member.login_name
|
||||
rendered.should contain @member.location
|
||||
end
|
||||
end
|
||||
|
||||
@@ -17,11 +38,14 @@ describe 'home/index.html.haml', :type => "view" do
|
||||
@member = FactoryGirl.create(:geolocated_member)
|
||||
controller.stub(:current_user) { @member }
|
||||
sign_in @member
|
||||
assign(:member, @member)
|
||||
@planting = FactoryGirl.create(:planting,
|
||||
:garden => @member.gardens.first
|
||||
)
|
||||
assign(:plantings, [@planting])
|
||||
@forum = FactoryGirl.create(:forum, :owner => @member)
|
||||
@post = FactoryGirl.create(:post, :author => @member)
|
||||
assign(:posts, [@post])
|
||||
@role = FactoryGirl.create(:admin)
|
||||
@member.roles << @role
|
||||
render
|
||||
|
||||
@@ -58,9 +58,10 @@ describe 'layouts/application.html.haml', :type => "view" do
|
||||
end
|
||||
|
||||
it 'includes the analytics code' do
|
||||
Growstuff::Application.config.analytics_code = 'ANALYTICS'
|
||||
Growstuff::Application.config.analytics_code = '<script>alert("foo!")</script>'
|
||||
render
|
||||
rendered.should contain 'ANALYTICS'
|
||||
assert_select "script", :text => 'alert("foo!")'
|
||||
rendered.should_not contain 'script'
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -6,11 +6,9 @@ describe "members/index" do
|
||||
page = 1
|
||||
per_page = 2
|
||||
total_entries = 2
|
||||
@member = FactoryGirl.create(:geolocated_member)
|
||||
members = WillPaginate::Collection.create(page, per_page, total_entries) do |pager|
|
||||
pager.replace([
|
||||
FactoryGirl.create(:member),
|
||||
FactoryGirl.create(:member)
|
||||
])
|
||||
pager.replace([ @member, @member ])
|
||||
end
|
||||
assign(:members, members)
|
||||
render
|
||||
@@ -20,4 +18,8 @@ describe "members/index" do
|
||||
assert_select "img", :src => /gravatar\.com\/avatar/, :count => 2
|
||||
end
|
||||
|
||||
it 'contains member locations' do
|
||||
rendered.should contain @member.location
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -76,6 +76,10 @@ describe "members/show" do
|
||||
it "contains an edit settings button" do
|
||||
rendered.should contain "Edit Settings"
|
||||
end
|
||||
|
||||
it "contains no send message button" do
|
||||
rendered.should_not contain "Send Message"
|
||||
end
|
||||
end
|
||||
|
||||
context "signed in as different member" do
|
||||
@@ -97,6 +101,10 @@ describe "members/show" do
|
||||
it "contains no edit settings button" do
|
||||
rendered.should_not contain "Edit Settings"
|
||||
end
|
||||
|
||||
it "contains a send message button" do
|
||||
rendered.should contain "Send Message"
|
||||
end
|
||||
end
|
||||
|
||||
context "public member" do
|
||||
@@ -108,6 +116,10 @@ describe "members/show" do
|
||||
it "shows the email address" do
|
||||
rendered.should contain @member.email
|
||||
end
|
||||
|
||||
it "doesn't show a send message button" do
|
||||
rendered.should_not contain "Send Message"
|
||||
end
|
||||
end
|
||||
|
||||
context "geolocations" do
|
||||
|
||||
36
spec/views/notifications/new.html.haml_spec.rb
Normal file
36
spec/views/notifications/new.html.haml_spec.rb
Normal file
@@ -0,0 +1,36 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe "notifications/new" do
|
||||
before(:each) do
|
||||
@recipient = FactoryGirl.create(:member)
|
||||
@sender = FactoryGirl.create(:member)
|
||||
assign(:notification, FactoryGirl.create(:notification, :recipient_id => @recipient.id, :sender_id => @sender.id))
|
||||
# assign(:forum, Forum.new)
|
||||
sign_in @sender
|
||||
controller.stub(:current_user) { @sender}
|
||||
end
|
||||
|
||||
it "renders new message form" do
|
||||
render
|
||||
assert_select "form", :action => notifications_path, :method => "notification" do
|
||||
assert_select "input#notification_subject", :name => "notification[subject]"
|
||||
assert_select "textarea#notification_body", :name => "notification[body]"
|
||||
end
|
||||
end
|
||||
|
||||
it "tells you who the recipient is" do
|
||||
render
|
||||
rendered.should contain @recipient.login_name
|
||||
end
|
||||
|
||||
it "Tells you to write your message here" do
|
||||
render
|
||||
rendered.should contain "Type your message here"
|
||||
end
|
||||
|
||||
it 'shows markdown help' do
|
||||
render
|
||||
rendered.should contain 'Markdown'
|
||||
end
|
||||
|
||||
end
|
||||
@@ -25,7 +25,7 @@ describe "plantings/_thumbnail" do
|
||||
end
|
||||
|
||||
it "renders the date planted" do
|
||||
rendered.should contain @planting.planted_at.to_s(:date)
|
||||
rendered.should contain @planting.planted_at.to_s(:default)
|
||||
end
|
||||
|
||||
it "shows the name of the crop" do
|
||||
|
||||
@@ -33,6 +33,7 @@ describe "plantings/new" do
|
||||
assert_select "select#planting_crop_id", :name => "planting[crop_id]"
|
||||
assert_select "input#planting_quantity", :name => "planting[quantity]"
|
||||
assert_select "textarea#planting_description", :name => "planting[description]"
|
||||
assert_select "select#planting_sunniness", :name => "planting[sunniness]"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -9,6 +9,26 @@ describe "plantings/show" do
|
||||
)
|
||||
end
|
||||
|
||||
it "shows the sunniness" do
|
||||
controller.stub(:current_user) { nil }
|
||||
@member = FactoryGirl.create(:member)
|
||||
create_planting_for(@member)
|
||||
render
|
||||
rendered.should contain 'Sun or shade?'
|
||||
rendered.should contain 'sun'
|
||||
end
|
||||
|
||||
it "doesn't show sunniness if blank" do
|
||||
controller.stub(:current_user) { nil }
|
||||
@member = FactoryGirl.create(:member)
|
||||
@p = create_planting_for(@member)
|
||||
@p.sunniness = ''
|
||||
@p.save
|
||||
render
|
||||
rendered.should_not contain 'Sun or shade?'
|
||||
rendered.should_not contain 'sun'
|
||||
end
|
||||
|
||||
context "no location set" do
|
||||
before(:each) do
|
||||
controller.stub(:current_user) { nil }
|
||||
|
||||
@@ -46,6 +46,7 @@ describe "posts/show" do
|
||||
@post = assign(:post,
|
||||
FactoryGirl.create(:html_post, :author => @author))
|
||||
@comment = FactoryGirl.create(:comment, :post => @post)
|
||||
@comments = @post.comments
|
||||
render
|
||||
end
|
||||
|
||||
@@ -62,6 +63,26 @@ describe "posts/show" do
|
||||
end
|
||||
end
|
||||
|
||||
context "when there is more than one comment" do
|
||||
before(:each) do
|
||||
@post = assign(:post,
|
||||
FactoryGirl.create(:html_post, :author => @author))
|
||||
@comment1 = FactoryGirl.create(:comment, :post => @post, :body => "F1rst!!!",
|
||||
:created_at => Date.new(2010, 5, 17))
|
||||
@comment3 = FactoryGirl.create(:comment, :post => @post, :body => "Th1rd!!!",
|
||||
:created_at => Date.new(2012, 5, 17))
|
||||
@comment4 = FactoryGirl.create(:comment, :post => @post, :body => "F0urth!!!")
|
||||
@comment2 = FactoryGirl.create(:comment, :post => @post, :body => "S3c0nd!!1!",
|
||||
:created_at => Date.new(2011, 5, 17))
|
||||
@comments = @post.comments
|
||||
render
|
||||
end
|
||||
|
||||
it "shows the oldest comments first" do
|
||||
rendered.should contain /#{@comment1.body}.*#{@comment2.body}.*#{@comment3.body}.*#{@comment4.body}/m
|
||||
end
|
||||
end
|
||||
|
||||
context "forum post" do
|
||||
it "shows forum name" do
|
||||
@post = assign(:post,
|
||||
|
||||
Reference in New Issue
Block a user