Merge pull request #3 from jcaudle/unique_usernames

Unique usernames
This commit is contained in:
Courtney Hazel
2013-02-21 19:21:31 -08:00
73 changed files with 1547 additions and 134 deletions

View File

@@ -2,9 +2,9 @@ source 'https://rubygems.org'
gem 'bundler', '>=1.1.5'
gem 'rails', '3.2.11'
gem 'rails', '3.2.12'
gem 'rack', '~>1.4.5'
gem 'json', '~>1.7.7'
gem 'haml'
gem 'cancan'
@@ -26,7 +26,7 @@ group :assets do
# long term, we'll probably want node.js for performance, but this will do for now as it's easier for new people to install
gem 'therubyracer', '~> 0.10.2', :platforms => :ruby
gem "less-rails"
gem "twitter-bootstrap-rails", '2.1.6'
gem "twitter-bootstrap-rails", '~> 2.2.2'
gem 'uglifier', '>= 1.0.3'
@@ -64,6 +64,8 @@ gem 'friendly_id'
# gravatars
gem 'gravatar-ultimate'
gem 'geocoder'
# for phusion passenger (i.e. mod_rails) on the server
gem 'passenger'
gem 'rake', '>= 10.0.0'

View File

@@ -1,31 +1,31 @@
GEM
remote: https://rubygems.org/
specs:
actionmailer (3.2.11)
actionpack (= 3.2.11)
actionmailer (3.2.12)
actionpack (= 3.2.12)
mail (~> 2.4.4)
actionpack (3.2.11)
activemodel (= 3.2.11)
activesupport (= 3.2.11)
actionpack (3.2.12)
activemodel (= 3.2.12)
activesupport (= 3.2.12)
builder (~> 3.0.0)
erubis (~> 2.7.0)
journey (~> 1.0.4)
rack (~> 1.4.0)
rack (~> 1.4.5)
rack-cache (~> 1.2)
rack-test (~> 0.6.1)
sprockets (~> 2.2.1)
activemodel (3.2.11)
activesupport (= 3.2.11)
activemodel (3.2.12)
activesupport (= 3.2.12)
builder (~> 3.0.0)
activerecord (3.2.11)
activemodel (= 3.2.11)
activesupport (= 3.2.11)
activerecord (3.2.12)
activemodel (= 3.2.12)
activesupport (= 3.2.12)
arel (~> 3.0.2)
tzinfo (~> 0.3.29)
activeresource (3.2.11)
activemodel (= 3.2.11)
activesupport (= 3.2.11)
activesupport (3.2.11)
activeresource (3.2.12)
activemodel (= 3.2.12)
activesupport (= 3.2.12)
activesupport (3.2.12)
i18n (~> 0.6)
multi_json (~> 1.0)
arel (3.0.2)
@@ -85,12 +85,14 @@ GEM
fastthread (1.0.7)
friendly_id (4.0.9)
fssm (0.2.10)
geocoder (1.1.6)
gravatar-ultimate (1.0.3)
haml (3.1.7)
haml-rails (0.3.5)
haml (4.0.0)
tilt
haml-rails (0.4)
actionpack (>= 3.1, < 4.1)
activesupport (>= 3.1, < 4.1)
haml (~> 3.1)
haml (>= 3.1, < 4.1)
railties (>= 3.1, < 4.1)
highline (1.6.15)
hike (1.2.1)
@@ -99,7 +101,7 @@ GEM
jquery-rails (2.2.1)
railties (>= 3.0, < 5.0)
thor (>= 0.14, < 2.0)
json (1.7.6)
json (1.7.7)
less (2.2.2)
commonjs (~> 0.2.6)
less-rails (2.2.6)
@@ -110,8 +112,8 @@ GEM
i18n (>= 0.4.0)
mime-types (~> 1.16)
treetop (~> 1.4.8)
mime-types (1.20.1)
multi_json (1.5.0)
mime-types (1.21)
multi_json (1.6.1)
net-scp (1.1.0)
net-ssh (>= 2.6.5)
net-sftp (2.1.1)
@@ -135,17 +137,17 @@ GEM
rack
rack-test (0.6.2)
rack (>= 1.0)
rails (3.2.11)
actionmailer (= 3.2.11)
actionpack (= 3.2.11)
activerecord (= 3.2.11)
activeresource (= 3.2.11)
activesupport (= 3.2.11)
rails (3.2.12)
actionmailer (= 3.2.12)
actionpack (= 3.2.12)
activerecord (= 3.2.12)
activeresource (= 3.2.12)
activesupport (= 3.2.12)
bundler (~> 1.0)
railties (= 3.2.11)
railties (3.2.11)
actionpack (= 3.2.11)
activesupport (= 3.2.11)
railties (= 3.2.12)
railties (3.2.12)
actionpack (= 3.2.12)
activesupport (= 3.2.12)
rack-ssl (~> 1.3.2)
rake (>= 0.8.7)
rdoc (~> 3.4)
@@ -189,7 +191,7 @@ GEM
treetop (1.4.12)
polyglot
polyglot (>= 0.3.1)
twitter-bootstrap-rails (2.1.6)
twitter-bootstrap-rails (2.2.4)
actionpack (>= 3.1)
execjs
railties (>= 3.1)
@@ -222,15 +224,17 @@ DEPENDENCIES
diff-lcs
factory_girl_rails (~> 4.0)
friendly_id
geocoder
gravatar-ultimate
haml
haml-rails
jquery-rails
json (~> 1.7.7)
less-rails
passenger
pg
rack (~> 1.4.5)
rails (= 3.2.11)
rails (= 3.2.12)
rake (>= 10.0.0)
rspec-rails (~> 2.12.1)
rvm-capistrano
@@ -239,7 +243,7 @@ DEPENDENCIES
sqlite3
therubyracer (~> 0.10.2)
thin
twitter-bootstrap-rails (= 2.1.6)
twitter-bootstrap-rails (~> 2.2.2)
uglifier (>= 1.0.3)
watchr
webrat

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,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

@@ -2,16 +2,16 @@
@import "twitter/bootstrap/responsive";
// Set the correct sprite paths
@iconSpritePath: asset-path("twitter/bootstrap/glyphicons-halflings");
@iconWhiteSpritePath: asset-path("twitter/bootstrap/glyphicons-halflings-white");
@iconSpritePath: asset-path("twitter/bootstrap/glyphicons-halflings.png");
@iconWhiteSpritePath: asset-path("twitter/bootstrap/glyphicons-halflings-white.png");
// Set the Font Awesome (Font Awesome is default. You can disable by commenting below lines)
// Note: If you use asset_path() here, your compiled boostrap_and_overrides.css will not
// Note: If you use asset_path() here, your compiled bootstrap_and_overrides.css will not
// have the proper paths. So for now we use the absolute path.
@fontAwesomeEotPath: asset-path("fontawesome-webfont.eot");
@fontAwesomeWoffPath: asset-path("fontawesome-webfont.woff");
@fontAwesomeTtfPath: asset-path("fontawesome-webfont.ttf");
@fontAwesomeSvgPath: asset-path("fontawesome-webfont.svg");
@fontAwesomeEotPath: asset-path("fontawesome-webfont.eot?v=3.0.2");
@fontAwesomeEotPath_iefix: asset-path("fontawesome-webfont.eot?#iefix&v=3.0.2");
@fontAwesomeWoffPath: asset-path("fontawesome-webfont.woff?v=3.0.2");
@fontAwesomeTtfPath: asset-path("fontawesome-webfont.ttf?v=3.0.2");
// Font Awesome
@import "fontawesome";

View File

@@ -0,0 +1,84 @@
class ForumsController < ApplicationController
load_and_authorize_resource
# GET /forums
# GET /forums.json
def index
@forums = Forum.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: @forums }
end
end
# GET /forums/1
# GET /forums/1.json
def show
@forum = Forum.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: @forum }
end
end
# GET /forums/new
# GET /forums/new.json
def new
@forum = Forum.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: @forum }
end
end
# GET /forums/1/edit
def edit
@forum = Forum.find(params[:id])
end
# POST /forums
# POST /forums.json
def create
@forum = Forum.new(params[:forum])
respond_to do |format|
if @forum.save
format.html { redirect_to @forum, notice: 'Forum was successfully created.' }
format.json { render json: @forum, status: :created, location: @forum }
else
format.html { render action: "new" }
format.json { render json: @forum.errors, status: :unprocessable_entity }
end
end
end
# PUT /forums/1
# PUT /forums/1.json
def update
@forum = Forum.find(params[:id])
respond_to do |format|
if @forum.update_attributes(params[:forum])
format.html { redirect_to @forum, notice: 'Forum was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: @forum.errors, status: :unprocessable_entity }
end
end
end
# DELETE /forums/1
# DELETE /forums/1.json
def destroy
@forum = Forum.find(params[:id])
@forum.destroy
respond_to do |format|
format.html { redirect_to forums_url }
format.json { head :no_content }
end
end
end

View File

@@ -29,6 +29,7 @@ class PostsController < ApplicationController
# GET /posts/new.json
def new
@post = Post.new
@forum = Forum.find_by_id(params[:forum_id]) || Forum.new
respond_to do |format|
format.html # new.html.haml

View File

@@ -0,0 +1,84 @@
class RolesController < ApplicationController
load_and_authorize_resource
# GET /roles
# GET /roles.json
def index
@roles = Role.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: @roles }
end
end
# GET /roles/1
# GET /roles/1.json
def show
@role = Role.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: @role }
end
end
# GET /roles/new
# GET /roles/new.json
def new
@role = Role.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: @role }
end
end
# GET /roles/1/edit
def edit
@role = Role.find(params[:id])
end
# POST /roles
# POST /roles.json
def create
@role = Role.new(params[:role])
respond_to do |format|
if @role.save
format.html { redirect_to @role, notice: 'Role was successfully created.' }
format.json { render json: @role, status: :created, location: @role }
else
format.html { render action: "new" }
format.json { render json: @role.errors, status: :unprocessable_entity }
end
end
end
# PUT /roles/1
# PUT /roles/1.json
def update
@role = Role.find(params[:id])
respond_to do |format|
if @role.update_attributes(params[:role])
format.html { redirect_to @role, notice: 'Role was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: @role.errors, status: :unprocessable_entity }
end
end
end
# DELETE /roles/1
# DELETE /roles/1.json
def destroy
@role = Role.find(params[:id])
@role.destroy
respond_to do |format|
format.html { redirect_to roles_url }
format.json { head :no_content }
end
end
end

View File

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

View File

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

View File

@@ -7,18 +7,27 @@ class Ability
# everyone can do these things, even non-logged in
can :read, :all
# nobody should be able to view this except admins
cannot :read, Role
if member
if member.has_role? :admin
# admin user roles (for authorization)
can :read, Role
can :manage, Role
# for now, only admins can create/edit forums
can :manage, Forum
end
# managing your own user settings
can :update, Member, :id => member.id
# for now, anyone can create/edit/destroy crops
# (later, we probably want to limit this to a role)
can :create, Crop
can :update, Crop
can :destroy, Crop
can :create, ScientificName
can :update, ScientificName
can :destroy, ScientificName
can :manage, Crop
can :manage, ScientificName
# anyone can create a post, or comment on a post,
# but only the author can edit/destroy it.

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

@@ -0,0 +1,12 @@
class Forum < ActiveRecord::Base
extend FriendlyId
friendly_id :name, use: :slugged
attr_accessible :description, :name, :owner_id, :slug
has_many :posts
belongs_to :owner, :class_name => "Member"
def to_s
return name
end
end

View File

@@ -5,6 +5,8 @@ class Member < ActiveRecord::Base
has_many :posts, :foreign_key => 'author_id'
has_many :comments, :foreign_key => 'author_id'
has_many :gardens, :foreign_key => 'owner_id'
has_many :forums, :foreign_key => 'owner_id'
has_and_belongs_to_many :roles
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
@@ -15,7 +17,13 @@ class Member < ActiveRecord::Base
# Setup accessible (or protected) attributes for your model
attr_accessible :login_name, :email, :password, :password_confirmation,
:remember_me, :login, :tos_agreement, :show_email
:remember_me, :login, :tos_agreement, :show_email,
:location, :latitude, :longitude
# set up geocoding
geocoded_by :location
after_validation :geocode
after_validation :empty_unwanted_geocodes
# Virtual attribute for authenticating by either username or email
# This is in addition to a real persisted field like 'username'
@@ -51,4 +59,17 @@ class Member < ActiveRecord::Base
def to_s
return login_name
end
def has_role?(role_sym)
roles.any? { |r| r.name.underscore.to_sym == role_sym }
end
protected
def empty_unwanted_geocodes
if self.location.to_s == ''
self.latitude = nil
self.longitude = nil
end
end
end

View File

@@ -1,8 +1,9 @@
class Post < ActiveRecord::Base
extend FriendlyId
friendly_id :author_date_subject, use: :slugged
attr_accessible :body, :subject, :author_id
attr_accessible :body, :subject, :author_id, :forum_id
belongs_to :author, :class_name => 'Member'
belongs_to :forum
has_many :comments, :dependent => :destroy
default_scope order("created_at desc")
@@ -11,4 +12,19 @@ class Post < ActiveRecord::Base
time = created_at || Time.now
"#{author.login_name} #{time.strftime("%Y%m%d")} #{subject}"
end
def comment_count
self.comments.count
end
def recent_activity
self.comments.last ? self.comments.last.created_at : self.created_at
end
def Post.recently_active
Post.all.sort do |a,b|
b.recent_activity <=> a.recent_activity
end
end
end

6
app/models/role.rb Normal file
View File

@@ -0,0 +1,6 @@
class Role < ActiveRecord::Base
extend FriendlyId
friendly_id :name, use: :slugged
attr_accessible :description, :name, :members, :slug
has_and_belongs_to_many :members
end

View File

@@ -11,28 +11,37 @@
= f.email_field :email
%span.help-inline If you change your email address you will have to reconfirm
%h2 Profile details
.control-group
=f.label :location, 'Your location', :class => 'control-label'
.controls
=f.text_field :location
%span.help-inline Be as detailed or vague as you like.
.control-group
.controls
= f.check_box :show_email
Show email publicly on your profile page
%h2 Change password
.control-group
= f.label :password, :class => 'control-label'
.controls
= f.password_field :password, :autocomplete => "off"
%span.help-inline Leave blank if you don't want to change your password
.control-group
= f.label :password_confirmation, :class => 'control-label'
.controls= f.password_field :password_confirmation
%p
%span.help-block Leave blank if you don't want to change your password
.control-group
= f.label :current_password, :class => 'control-label'
.controls
= f.password_field :current_password
.control-group
= f.label :password, "New password", :class => 'control-label'
.controls
= f.password_field :password, :autocomplete => "off"
.control-group
= f.label :password_confirmation, :class => 'control-label'
.controls= f.password_field :password_confirmation
.form-actions
= f.submit "Update", :class => 'btn'

View File

@@ -0,0 +1,19 @@
= form_for @forum, :html => { :class => 'form-horizontal' } do |f|
- if @forum.errors.any?
#error_explanation
%h2= "#{pluralize(@forum.errors.count, "error")} prohibited this forum from being saved:"
%ul
- @forum.errors.full_messages.each do |msg|
%li= msg
.control-group
= f.label :name, :class => 'control-label'
.controls= f.text_field :name, :class => 'input-block-level'
.control-group
= f.label :description, :class => 'control-label'
.controls= f.text_area :description, :rows => 6, :class => 'input-block-level'
.control-group
= f.label :owner_id, :class => 'control-label'
.controls= collection_select(:forum, :owner_id, Member.all, :id, :login_name)
.form-actions
= f.submit 'Save', :class => 'btn'

View File

@@ -0,0 +1,7 @@
- content_for :title, "Editing forum"
= render 'form'
= link_to 'Show', @forum
\|
= link_to 'Back', forums_path

View File

@@ -0,0 +1,12 @@
- content_for :title, "Forums"
- @forums.each do |forum|
%h2= forum
%p
= pluralize(forum.posts.count, "post")
|
=link_to "Post", new_post_path(:forum_id => forum.id)
|
=link_to "Visit forum", forum
=render :partial => "posts/summary", :locals => { :posts => forum.posts, :howmany => 4 }

View File

@@ -0,0 +1,5 @@
- content_for :title, "New Forum"
= render 'form'
= link_to 'Back', forums_path

View File

@@ -0,0 +1,25 @@
- content_for :title, @forum.name
%p#notice= notice
%p
:markdown
#{ strip_tags(@forum.description) }
%p
This forum is run by
= link_to @forum.owner, @forum.owner
- if can? :edit, @forum
=link_to "Edit", edit_forum_path(@forum), :class => 'btn'
%h2
Posts
=link_to "Post something", new_post_path(:forum_id => @forum.id), :class => 'btn'
- if @forum.posts.count > 0
=render :partial => "posts/summary", :locals => { :posts => @forum.posts }
- else
No posts yet.

View File

@@ -11,6 +11,7 @@
%li= link_to "Crops", crops_path
%li= link_to "Members", members_path
%li= link_to "Posts", posts_path
%li= link_to "Forums", forums_path
- if can? :create, Post
%li= link_to("Post something", new_post_path)
- if can? :create, Planting

View File

@@ -8,8 +8,12 @@
%p
= "Member since: #{@member.created_at.to_s(:date)}"
%p
Location: Unknown
- if @member.location.to_s != ''
%p
Location:
= @member.location
%br/
= image_tag("http://maps.google.com/maps/api/staticmap?size=200x200&maptype=roadmap&sensor=false&markers=color:green|label:A|#{@member.latitude},#{@member.longitude}&zoom=12", :alt => "Map showing #{@member.location}", :width => 200, :height => 200 )
- if @member.show_email
%p
Email:
@@ -23,7 +27,8 @@
%li{:class => first_garden ? 'active' : '' }
- first_garden = false
= link_to g.name, "#garden#{g.id}", 'data-toggle' => 'tab'
%li= link_to 'New Garden', '#garden_new', 'data-toggle' => 'tab'
- if current_member == @member
%li= link_to 'New Garden', '#garden_new', 'data-toggle' => 'tab'
.tab-content
- first_garden = true
- @member.gardens.each do |g|
@@ -42,9 +47,10 @@
%p
= link_to "More about this garden...", url_for(g)
%div{:class => 'tab-pane', :id => "garden_new"}
%h3 Create a new garden
= render 'gardens/form'
- if current_member == @member
%div{:class => 'tab-pane', :id => "garden_new"}
%h3 Create a new garden
= render 'gardens/form'
%h3 Updates
- @member.posts.each do |post|

View File

@@ -6,14 +6,18 @@
- @post.errors.full_messages.each do |msg|
%li= msg
.field
= f.label :author_id
= f.number_field :author_id
.field
= f.label :subject
= f.text_field :subject
.field
= f.label :body
= f.text_area :body
.actions
= f.submit 'Save'
= label_tag :post, "Subject"
= f.text_field :subject, :class => 'input-block-level'
= label_tag :body, "What's going on in your food garden?"
= f.text_area :body, :rows => 12, :class => 'input-block-level'
- if @post.forum || @forum
- forum = @post.forum || @forum
%p
This post will be posted in the forum
=link_to forum.name, forum
.field
= f.hidden_field :forum_id, :value => forum.id
= f.submit "Post", :class => 'btn'

View File

@@ -8,10 +8,14 @@
%h3= link_to strip_tags(post.subject), post
.post-meta
Posted by
= link_to post.author.login_name, member_path(post.author)
at
= post.created_at
%p
Posted by
= link_to post.author.login_name, member_path(post.author)
- if post.forum
in
= link_to post.forum, post.forum
at
= post.created_at
.post-body
:markdown

View File

@@ -0,0 +1,23 @@
- howmany ||= 100
- if posts.length > 0
%table.table.table-striped
%tr
%th Subject
%th Posted by
%th Posted
%th Most recent activity
%th Comments
- posts.recently_active[0..howmany-1].each do |post|
%tr
%td
= link_to strip_tags(post.subject), post
%td
=link_to post.author, post.author
%td
= post.created_at.to_s(:date)
%td
= distance_of_time_in_words(post.recent_activity, Time.zone.now)
ago
%td
= post.comments.count.to_s

View File

@@ -1,7 +1,4 @@
= content_for :title, "Edit post"
= form_for @post do |f|
= label_tag :subject, "Subject"
= f.text_field :subject, :class => 'input-block-level'
= f.text_area :body, :rows => 12, :class => 'input-block-level'
= f.submit "Post"
=render 'form'

View File

@@ -1,9 +1,4 @@
= content_for :title, "Post a post"
= content_for :title, @forum.name ? "Post in #{@forum.name}" : "Post something"
=render 'form'
= form_for @post, :url => { :action => "create" } do |f|
%fieldset
= label_tag :post, "Subject"
= f.text_field :subject, :class => 'input-block-level'
= label_tag :body, "What's going on in your food garden?"
= f.text_area :body, :rows => 12, :class => 'input-block-level'
= f.submit "Post", :class => 'btn'

View File

@@ -0,0 +1,16 @@
= form_for @role do |f|
- if @role.errors.any?
#error_explanation
%h2= "#{pluralize(@role.errors.count, "error")} prohibited this role from being saved:"
%ul
- @role.errors.full_messages.each do |msg|
%li= msg
.field
= f.label :name
= f.text_field :name
.field
= f.label :description
= f.text_area :description
.actions
= f.submit 'Save'

View File

@@ -0,0 +1,7 @@
%h1 Editing role
= render 'form'
= link_to 'Show', @role
\|
= link_to 'Back', roles_path

View File

@@ -0,0 +1,21 @@
%h1 Listing roles
%table
%tr
%th Name
%th Description
%th
%th
%th
- @roles.each do |role|
%tr
%td= role.name
%td= role.description
%td= link_to 'Show', role
%td= link_to 'Edit', edit_role_path(role)
%td= link_to 'Destroy', role, method: :delete, data: { confirm: 'Are you sure?' }
%br
= link_to 'New Role', new_role_path

View File

@@ -0,0 +1,5 @@
%h1 New role
= render 'form'
= link_to 'Back', roles_path

View File

@@ -0,0 +1,12 @@
%p#notice= notice
%p
%b Name:
= @role.name
%p
%b Description:
= @role.description
= link_to 'Edit', edit_role_path(@role)
\|
= link_to 'Back', roles_path

View File

@@ -28,7 +28,7 @@ module Growstuff
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
config.time_zone = 'UTC'
config.active_record.default_timezone = 'UTC'
config.active_record.default_timezone = :local
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]

View File

@@ -0,0 +1,17 @@
# Sample localization file for English. Add more files in this directory for other locales.
# See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
en:
helpers:
actions: "Actions"
links:
back: "Back"
cancel: "Cancel"
confirm: "Are you sure?"
destroy: "Delete"
new: "New"
titles:
edit: "Edit"
save: "Save"
new: "New"
delete: "Delete"

View File

@@ -1,4 +1,5 @@
Growstuff::Application.routes.draw do
devise_for :members, :controllers => { :registrations => "registrations" }
resources :plantings
@@ -8,6 +9,8 @@ Growstuff::Application.routes.draw do
resources :crops
resources :members
resources :comments
resources :roles
resources :forums
get "home/index"

View File

@@ -0,0 +1,7 @@
class AddGeoToMembers < ActiveRecord::Migration
def change
add_column :members, :location, :string
add_column :members, :latitude, :float
add_column :members, :longitude, :float
end
end

View File

@@ -0,0 +1,11 @@
class CreateForums < ActiveRecord::Migration
def change
create_table :forums do |t|
t.string :name, :null => false
t.text :description, :null => false
t.integer :owner_id, :null => false
t.timestamps
end
end
end

View File

@@ -0,0 +1,5 @@
class AddForumToPosts < ActiveRecord::Migration
def change
add_column :posts, :forum_id, :integer
end
end

View File

@@ -0,0 +1,10 @@
class CreateRoles < ActiveRecord::Migration
def change
create_table :roles do |t|
t.string :name, :null => false
t.text :description
t.timestamps
end
end
end

View File

@@ -0,0 +1,8 @@
class AddMembersRolesTable < ActiveRecord::Migration
def change
create_table :members_roles, :id => false do |t|
t.integer :member_id
t.integer :role_id
end
end
end

View File

@@ -0,0 +1,6 @@
class AddSlugToForums < ActiveRecord::Migration
def change
add_column :forums, :slug, :string
add_index :forums, :slug, unique: true
end
end

View File

@@ -0,0 +1,6 @@
class AddSlugToRoles < ActiveRecord::Migration
def change
add_column :roles, :slug, :string
add_index :roles, :slug, unique: true
end
end

View File

@@ -11,14 +11,14 @@
#
# It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20130208034248) do
ActiveRecord::Schema.define(:version => 20130220044642) do
create_table "comments", :force => true do |t|
t.integer "post_id", :limit => 255, :null => false
t.integer "author_id", :limit => 255, :null => false
t.text "body", :limit => 255, :null => false
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.integer "post_id", :null => false
t.integer "author_id", :null => false
t.text "body", :null => false
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "crops", :force => true do |t|
@@ -32,6 +32,17 @@ ActiveRecord::Schema.define(:version => 20130208034248) do
add_index "crops", ["slug"], :name => "index_crops_on_slug", :unique => true
add_index "crops", ["system_name"], :name => "index_crops_on_system_name"
create_table "forums", :force => true do |t|
t.string "name", :null => false
t.text "description", :null => false
t.integer "owner_id", :null => false
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.string "slug"
end
add_index "forums", ["slug"], :name => "index_forums_on_slug", :unique => true
create_table "gardens", :force => true do |t|
t.string "name", :null => false
t.integer "owner_id"
@@ -68,6 +79,9 @@ ActiveRecord::Schema.define(:version => 20130208034248) do
t.string "slug"
t.boolean "tos_agreement"
t.boolean "show_email"
t.string "location"
t.float "latitude"
t.float "longitude"
end
add_index "members", ["confirmation_token"], :name => "index_users_on_confirmation_token", :unique => true
@@ -76,6 +90,11 @@ ActiveRecord::Schema.define(:version => 20130208034248) do
add_index "members", ["slug"], :name => "index_users_on_slug", :unique => true
add_index "members", ["unlock_token"], :name => "index_users_on_unlock_token", :unique => true
create_table "members_roles", :id => false, :force => true do |t|
t.integer "member_id"
t.integer "role_id"
end
create_table "plantings", :force => true do |t|
t.integer "garden_id", :null => false
t.integer "crop_id", :null => false
@@ -96,11 +115,22 @@ ActiveRecord::Schema.define(:version => 20130208034248) do
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.string "slug"
t.integer "forum_id"
end
add_index "posts", ["created_at", "author_id"], :name => "index_updates_on_created_at_and_user_id"
add_index "posts", ["slug"], :name => "index_updates_on_slug", :unique => true
create_table "roles", :force => true do |t|
t.string "name", :null => false
t.text "description"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.string "slug"
end
add_index "roles", ["slug"], :name => "index_roles_on_slug", :unique => true
create_table "scientific_names", :force => true do |t|
t.string "scientific_name", :null => false
t.integer "crop_id", :null => false

14
lib/tasks/growstuff.rake Normal file
View File

@@ -0,0 +1,14 @@
namespace :growstuff do
desc "Add an admin user to Growstuff, by name"
# usage: rake growstuff:admin_user name=skud
task :admin_user => :environment do
member = Member.find(ENV['name']) or raise "Usage: rake growstuff:admin_user name=whoever"
admin = Role.find_or_create_by_name!('admin')
member.roles << admin
end
end

View File

@@ -0,0 +1,146 @@
require 'spec_helper'
describe ForumsController do
login_admin_member
def valid_attributes
{
"name" => "MyString",
"description" => "Something",
"owner_id" => 1
}
end
def valid_session
{}
end
describe "GET index" do
it "assigns all forums as @forums" do
forum = Forum.create! valid_attributes
get :index, {}
assigns(:forums).should eq([forum])
end
end
describe "GET show" do
it "assigns the requested forum as @forum" do
forum = Forum.create! valid_attributes
get :show, {:id => forum.to_param}
assigns(:forum).should eq(forum)
end
end
describe "GET new" do
it "assigns a new forum as @forum" do
get :new, {}
assigns(:forum).should be_a_new(Forum)
end
end
describe "GET edit" do
it "assigns the requested forum as @forum" do
forum = Forum.create! valid_attributes
get :edit, {:id => forum.to_param}
assigns(:forum).should eq(forum)
end
end
describe "POST create" do
describe "with valid params" do
it "creates a new Forum" do
expect {
post :create, {:forum => valid_attributes}
}.to change(Forum, :count).by(1)
end
it "assigns a newly created forum as @forum" do
post :create, {:forum => valid_attributes}
assigns(:forum).should be_a(Forum)
assigns(:forum).should be_persisted
end
it "redirects to the created forum" do
post :create, {:forum => valid_attributes}
response.should redirect_to(Forum.last)
end
end
describe "with invalid params" do
it "assigns a newly created but unsaved forum as @forum" do
# Trigger the behavior that occurs when invalid params are submitted
Forum.any_instance.stub(:save).and_return(false)
post :create, {:forum => { "name" => "invalid value" }}
assigns(:forum).should be_a_new(Forum)
end
it "re-renders the 'new' template" do
# Trigger the behavior that occurs when invalid params are submitted
Forum.any_instance.stub(:save).and_return(false)
post :create, {:forum => { "name" => "invalid value" }}
response.should render_template("new")
end
end
end
describe "PUT update" do
describe "with valid params" do
it "updates the requested forum" do
forum = Forum.create! valid_attributes
# Assuming there are no other forums in the database, this
# specifies that the Forum created on the previous line
# receives the :update_attributes message with whatever params are
# submitted in the request.
Forum.any_instance.should_receive(:update_attributes).with({ "name" => "MyString" })
put :update, {:id => forum.to_param, :forum => { "name" => "MyString" }}
end
it "assigns the requested forum as @forum" do
forum = Forum.create! valid_attributes
put :update, {:id => forum.to_param, :forum => valid_attributes}
assigns(:forum).should eq(forum)
end
it "redirects to the forum" do
forum = Forum.create! valid_attributes
put :update, {:id => forum.to_param, :forum => valid_attributes}
response.should redirect_to(forum)
end
end
describe "with invalid params" do
it "assigns the forum as @forum" do
forum = Forum.create! valid_attributes
# Trigger the behavior that occurs when invalid params are submitted
Forum.any_instance.stub(:save).and_return(false)
put :update, {:id => forum.to_param, :forum => { "name" => "invalid value" }}
assigns(:forum).should eq(forum)
end
it "re-renders the 'edit' template" do
forum = Forum.create! valid_attributes
# Trigger the behavior that occurs when invalid params are submitted
Forum.any_instance.stub(:save).and_return(false)
put :update, {:id => forum.to_param, :forum => { "name" => "invalid value" }}
response.should render_template("edit")
end
end
end
describe "DELETE destroy" do
it "destroys the requested forum" do
forum = Forum.create! valid_attributes
expect {
delete :destroy, {:id => forum.to_param}
}.to change(Forum, :count).by(-1)
end
it "redirects to the forums list" do
forum = Forum.create! valid_attributes
delete :destroy, {:id => forum.to_param}
response.should redirect_to(forums_url)
end
end
end

View File

@@ -39,6 +39,17 @@ describe PostsController do
get :new, {}
assigns(:post).should be_a_new(Post)
end
it "picks up forum from params" do
forum = FactoryGirl.create(:forum)
get :new, {:forum_id => forum.id}
assigns(:forum).should eq(forum)
end
it "doesn't die if no forum specified" do
get :new, {}
assigns(:forum).should be_a_new(Forum)
end
end
describe "GET edit" do

View File

@@ -0,0 +1,143 @@
require 'spec_helper'
describe RolesController do
def valid_attributes
{ "name" => "MyString" }
end
def valid_session
{}
end
login_admin_member
describe "GET index" do
it "assigns all roles as @roles" do
role = Role.create! valid_attributes
get :index, {}
# note that admin role exists because of login_admin_member
assigns(:roles).should eq([Role.find_by_name('admin'), role])
end
end
describe "GET show" do
it "assigns the requested role as @role" do
role = Role.create! valid_attributes
get :show, {:id => role.to_param}
assigns(:role).should eq(role)
end
end
describe "GET new" do
it "assigns a new role as @role" do
get :new, {}
assigns(:role).should be_a_new(Role)
end
end
describe "GET edit" do
it "assigns the requested role as @role" do
role = Role.create! valid_attributes
get :edit, {:id => role.to_param}
assigns(:role).should eq(role)
end
end
describe "POST create" do
describe "with valid params" do
it "creates a new Role" do
expect {
post :create, {:role => valid_attributes}
}.to change(Role, :count).by(1)
end
it "assigns a newly created role as @role" do
post :create, {:role => valid_attributes}
assigns(:role).should be_a(Role)
assigns(:role).should be_persisted
end
it "redirects to the created role" do
post :create, {:role => valid_attributes}
response.should redirect_to(Role.last)
end
end
describe "with invalid params" do
it "assigns a newly created but unsaved role as @role" do
# Trigger the behavior that occurs when invalid params are submitted
Role.any_instance.stub(:save).and_return(false)
post :create, {:role => { "name" => "invalid value" }}
assigns(:role).should be_a_new(Role)
end
it "re-renders the 'new' template" do
# Trigger the behavior that occurs when invalid params are submitted
Role.any_instance.stub(:save).and_return(false)
post :create, {:role => { "name" => "invalid value" }}
response.should render_template("new")
end
end
end
describe "PUT update" do
describe "with valid params" do
it "updates the requested role" do
role = Role.create! valid_attributes
# Assuming there are no other roles in the database, this
# specifies that the Role created on the previous line
# receives the :update_attributes message with whatever params are
# submitted in the request.
Role.any_instance.should_receive(:update_attributes).with({ "name" => "MyString" })
put :update, {:id => role.to_param, :role => { "name" => "MyString" }}
end
it "assigns the requested role as @role" do
role = Role.create! valid_attributes
put :update, {:id => role.to_param, :role => valid_attributes}
assigns(:role).should eq(role)
end
it "redirects to the role" do
role = Role.create! valid_attributes
put :update, {:id => role.to_param, :role => valid_attributes}
response.should redirect_to(role)
end
end
describe "with invalid params" do
it "assigns the role as @role" do
role = Role.create! valid_attributes
# Trigger the behavior that occurs when invalid params are submitted
Role.any_instance.stub(:save).and_return(false)
put :update, {:id => role.to_param, :role => { "name" => "invalid value" }}
assigns(:role).should eq(role)
end
it "re-renders the 'edit' template" do
role = Role.create! valid_attributes
# Trigger the behavior that occurs when invalid params are submitted
Role.any_instance.stub(:save).and_return(false)
put :update, {:id => role.to_param, :role => { "name" => "invalid value" }}
response.should render_template("edit")
end
end
end
describe "DELETE destroy" do
it "destroys the requested role" do
role = Role.create! valid_attributes
expect {
delete :destroy, {:id => role.to_param}
}.to change(Role, :count).by(-1)
end
it "redirects to the roles list" do
role = Role.create! valid_attributes
delete :destroy, {:id => role.to_param}
response.should redirect_to(roles_url)
end
end
end

9
spec/factories/forums.rb Normal file
View File

@@ -0,0 +1,9 @@
# Read about factories at https://github.com/thoughtbot/factory_girl
FactoryGirl.define do
factory :forum do
name "Permaculture"
description "*Everything* about permaculture!"
owner
end
end

View File

@@ -28,6 +28,18 @@ FactoryGirl.define do
show_email true
end
factory :geolocated_member do
login_name 'JohnH' # for the astronomer who figured out longitude
location 'Greenwich, UK'
# including lat/long explicitly because geocoder doesn't work with FG
latitude 51.483
longitude 0.004
end
factory :admin_member do
roles { [ FactoryGirl.create(:admin) ] }
end
end
end

View File

@@ -15,6 +15,10 @@ FactoryGirl.define do
factory :html_post do
body '<a href="http://evil.com">EVIL</a>'
end
factory :forum_post do
forum
end
end
end

13
spec/factories/roles.rb Normal file
View File

@@ -0,0 +1,13 @@
# Read about factories at https://github.com/thoughtbot/factory_girl
FactoryGirl.define do
factory :role do
name "Moderator"
description "These people moderate the forums"
factory :admin do
name "admin"
end
end
end

32
spec/models/forum_spec.rb Normal file
View File

@@ -0,0 +1,32 @@
require 'spec_helper'
describe Forum do
before(:each) do
@forum = FactoryGirl.create(:forum)
end
it "belongs to an owner" do
@forum.owner.should be_an_instance_of Member
end
it "stringifies nicely" do
"#{@forum}".should eq @forum.name
end
it 'has a slug' do
@forum.slug.should eq 'permaculture'
end
it "has many posts" do
@post1 = FactoryGirl.create(:forum_post, :forum => @forum)
@post2 = FactoryGirl.create(:forum_post, :forum => @forum)
@forum.posts.length.should == 2
end
it "orders posts in reverse chron order" do
@post1 = FactoryGirl.create(:forum_post, :forum => @forum)
@post2 = FactoryGirl.create(:forum_post, :forum => @forum)
@forum.posts.first.should eq @post2
end
end

View File

@@ -56,6 +56,29 @@ describe 'member' do
@comment2 = FactoryGirl.create(:comment, :author => @member)
@member.comments.length.should == 2
end
it "has many forums" do
@member.save
@forum1 = FactoryGirl.create(:forum, :owner => @member)
@forum2 = FactoryGirl.create(:forum, :owner => @member)
@member.forums.length.should == 2
end
it 'has location and lat/long fields' do
@member.update_attributes(:location => 'Greenwich, UK')
@member.location.should eq 'Greenwich, UK'
@member.latitude.round(2).should eq 51.48
@member.longitude.round(2).should eq 0.00
end
it 'empties the lat/long if location removed' do
@member.update_attributes(:location => 'Greenwich, UK')
@member.update_attributes(:location => '')
@member.location.should eq ''
@member.latitude.should be_nil
@member.longitude.should be_nil
end
end
context 'no TOS agreement' do
@@ -77,4 +100,22 @@ describe 'member' do
end
end
context 'roles' do
before(:each) do
@member = FactoryGirl.create(:member)
@role = FactoryGirl.create(:role)
@member.roles << @role
end
it 'has a role' do
@member.roles.first.should eq @role
@member.has_role?(:moderator).should eq true
end
it 'sets up roles in factories' do
@admin = FactoryGirl.create(:admin_member)
@admin.has_role?(:admin).should eq true
end
end
end

View File

@@ -37,4 +37,35 @@ describe Post do
@post.destroy
Comment.count.should == all - 2
end
it "belongs to a forum" do
@post = FactoryGirl.create(:forum_post)
@post.forum.should be_an_instance_of Forum
end
context "recent activity" do
before(:each) do
Time.stub(:now => Time.now)
@post = FactoryGirl.create(:post)
end
it "sets recent activity to post time" do
@post.recent_activity.to_i.should eq @post.created_at.to_i
end
it "sets recent activity to comment time" do
@comment = FactoryGirl.create(:comment, :post => @post)
@post.recent_activity.to_i.should eq @comment.created_at.to_i
end
it "sorts recently active" do
# create a shiny new post
@post2 = FactoryGirl.create(:post)
Post.recently_active.first.should eq @post2
# now comment on an older post
@comment = FactoryGirl.create(:comment, :post => @post)
Post.recently_active.first.should eq @post
end
end
end

17
spec/models/role_spec.rb Normal file
View File

@@ -0,0 +1,17 @@
require 'spec_helper'
describe Role do
before(:each) do
@member = FactoryGirl.create(:member)
@role = FactoryGirl.create(:role)
@role.members << @member
end
it 'has members' do
@role.members.first.should eq @member
end
it 'has a slug' do
@role.slug.should eq 'moderator'
end
end

View File

@@ -0,0 +1,11 @@
require 'spec_helper'
describe "Forums" do
describe "GET /forums" 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 forums_path
response.status.should be(200)
end
end
end

View File

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

View File

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

View File

@@ -7,4 +7,12 @@ module ControllerMacros
sign_in member
end
end
def login_admin_member
before(:each) do
@request.env["devise.mapping"] = Devise.mappings[:member]
member = FactoryGirl.create(:admin_member)
sign_in member
end
end
end

View File

@@ -18,18 +18,28 @@ describe 'devise/registrations/edit.html.haml', :type => "view" do
rendered.should contain 'Email'
end
context 'email section'
context 'email section' do
it 'has a heading' do
assert_select "h2", "Email address"
end
end
context 'profile section' do
it 'has a heading' do
assert_select "h2", "Profile details"
end
it 'shows show_email checkbox' do
assert_select "input[id=member_show_email][type=checkbox]"
end
it 'shows location field' do
assert_select "input[id=member_location][type=text]"
end
end
it 'should have a password section' do
assert_select "h2", "Change password"
end
end
end

View File

@@ -0,0 +1,22 @@
require 'spec_helper'
describe "forums/edit" do
before(:each) do
@forum = assign(:forum, stub_model(Forum,
:name => "MyString",
:description => "MyText",
:owner_id => 1
))
end
it "renders the edit forum form" do
render
# Run the generator again with the --webrat flag if you want to use webrat matchers
assert_select "form", :action => forums_path(@forum), :method => "post" do
assert_select "input#forum_name", :name => "forum[name]"
assert_select "textarea#forum_description", :name => "forum[description]"
assert_select "select#forum_owner_id", :name => "forum[owner_id]"
end
end
end

View File

@@ -0,0 +1,39 @@
require 'spec_helper'
describe "forums/index" do
before(:each) do
@forum1 = FactoryGirl.create(:forum)
@forum2 = FactoryGirl.create(:forum)
assign(:forums, [ @forum1, @forum2 ])
end
it "renders a list of forums" do
render
assert_select "h2", :text => @forum1.name, :count => 2
end
it "doesn't display posts for empty forums" do
render
assert_select "table", false
end
context "posts" do
before(:each) do
@post = FactoryGirl.create(:forum_post, :forum => @forum1)
@comment = FactoryGirl.create(:comment, :post => @post)
render
end
it "displays posts" do
assert_select "table"
rendered.should contain @post.subject
rendered.should contain @post.created_at.to_s(:date)
rendered.should contain "less than a minute ago"
end
it "displays comment count" do
assert_select "td", :text => "1"
end
end
end

View File

@@ -0,0 +1,16 @@
require 'spec_helper'
describe "forums/new" do
before(:each) do
@forum = assign(:forum, FactoryGirl.create(:forum))
render
end
it "renders new forum form" do
assert_select "form", :action => forums_path, :method => "post" do
assert_select "input#forum_name", :name => "forum[name]"
assert_select "textarea#forum_description", :name => "forum[description]"
assert_select "select#forum_owner_id", :name => "forum[owner_id]"
end
end
end

View File

@@ -0,0 +1,37 @@
require 'spec_helper'
describe "forums/show" do
before(:each) do
controller.stub(:current_user) { nil }
@forum = assign(:forum, FactoryGirl.create(:forum))
end
it "renders attributes" do
render
rendered.should contain "Everything about permaculture"
rendered.should contain @forum.owner.to_s
end
it "parses markdown description into html" do
render
assert_select "em", "Everything"
end
it 'links to new post with the forum id' do
render
assert_select "a[href=#{new_post_path(:forum_id => @forum.id)}]"
end
it 'has no posts' do
render
rendered.should contain "No posts yet."
end
it 'shows posts' do
@post = FactoryGirl.create(:post, :forum => @forum)
render
assert_select "table"
rendered.should contain @post.subject
rendered.should contain @post.author.to_s
end
end

View File

@@ -1,53 +1,71 @@
require 'spec_helper'
describe "members/show" do
before(:each) do
controller.stub(:current_user) { nil }
@member = FactoryGirl.create(:member)
@time = @member.created_at
@garden = FactoryGirl.create(:garden, :owner => @member)
@planting = FactoryGirl.create(:planting, :garden => @garden)
render
@garden = FactoryGirl.create(:garden, :owner => @member)
end
it "shows account creation date" do
rendered.should contain "Member since"
rendered.should contain @time.strftime("%B %d, %Y")
context "the basics" do
before(:each) do
render
end
it "shows account creation date" do
@time = @member.created_at
rendered.should contain "Member since"
rendered.should contain @time.strftime("%B %d, %Y")
end
it "contains a gravatar icon" do
assert_select "img", :src => /gravatar\.com\/avatar/
end
end
it "contains a gravatar icon" do
assert_select "img", :src => /gravatar\.com\/avatar/
end
context "gardens and plantings" do
before(:each) do
@planting = FactoryGirl.create(:planting, :garden => @garden)
render
end
it "shows the auto-created garden" do
assert_select "li.active>a", :text => "Garden"
end
it "shows the auto-created garden" do
assert_select "li.active>a", :text => "Garden"
end
it 'shows the garden description' do
rendered.should contain "totally cool garden"
end
it 'shows the garden description' do
rendered.should contain "totally cool garden"
end
it 'renders markdown in the garden description' do
assert_select "strong", "totally"
end
it 'renders markdown in the garden description' do
assert_select "strong", "totally"
end
it "shows the plantings in the garden" do
rendered.should contain @planting.crop.system_name
end
it "shows the plantings in the garden" do
rendered.should contain @planting.crop.system_name
end
it "doesn't show the note about random plantings" do
rendered.should_not contain "Note: these are a random selection"
end
it "doesn't show the note about random plantings" do
rendered.should_not contain "Note: these are a random selection"
end
it "doesn't show the email address" do
rendered.should_not contain @member.email
it "doesn't show the email address" do
rendered.should_not contain @member.email
end
it "does not contain a 'New Garden' link" do
assert_select "a[href=#garden_new]", false
end
it "does not contain a 'New Garden' tab" do
assert_select "#garden_new", false
end
end
context "signed in member" do
before(:each) do
sign_in @member
controller.stub(:current_user) { @member }
render
end
@@ -56,6 +74,23 @@ describe "members/show" do
end
end
context "signed in as different member" do
before(:each) do
@member2 = FactoryGirl.create(:member)
sign_in @member2
controller.stub(:current_user) { @member2 }
render
end
it "does not contain a 'New Garden' link" do
assert_select "a[href=#garden_new]", false
end
it "does not contain a 'New Garden' tab" do
assert_select "#garden_new", false
end
end
context "public member" do
before(:each) do
@member = FactoryGirl.create(:public_member)
@@ -67,4 +102,33 @@ describe "members/show" do
end
end
context "geolocations" do
before(:each) do
@member = FactoryGirl.create(:geolocated_member)
render
end
it "shows the location" do
rendered.should contain @member.location
end
it "shows a map" do
assert_select "img", :src => /maps\.google\.com/
end
end
context "no location stated" do
before(:each) do
@member = FactoryGirl.create(:member)
render
end
it "doesn't have a location" do
@member.location.to_s.should eq ''
end
it "doesn't show the location" do
rendered.should_not contain "Location:"
end
it "doesn't show a map" do
assert_select "img[src*=maps]", false
end
end
end

View File

@@ -19,5 +19,33 @@ describe "posts/edit" do
assert_select "textarea#post_body", :name => "post[body]"
end
end
it 'no hidden forum field' do
assert_select "input#post_forum_id[type=hidden]", false
end
it 'no forum mentioned' do
rendered.should_not contain "This post will be posted in the forum"
end
context "forum specified" do
before(:each) do
@forum = assign(:forum, FactoryGirl.create(:forum))
assign(:post, FactoryGirl.create( :post,
:forum => @forum,
:author => @author
))
render
end
it 'creates a hidden field' do
assert_select "input#post_forum_id[type=hidden][value=#{@forum.id}]"
end
it 'tells the user what forum it will be posted in' do
rendered.should contain "This post will be posted in the forum #{@forum.name}"
end
end
end
end

View File

@@ -4,15 +4,41 @@ describe "posts/new" do
before(:each) do
@author = FactoryGirl.create(:member)
assign(:post, FactoryGirl.create(:post, :author => @author))
assign(:forum, Forum.new)
sign_in @author
controller.stub(:current_user) { @author }
render
end
it "renders new post form" do
render
assert_select "form", :action => posts_path, :method => "post" do
assert_select "input#post_subject", :name => "post[subject]"
assert_select "textarea#post_body", :name => "post[body]"
end
end
it 'no hidden forum field' do
assert_select "input#post_forum_id[type=hidden]", false
end
it 'no forum mentioned' do
rendered.should_not contain "This post will be posted in the forum"
end
context "forum specified" do
before(:each) do
@forum = assign(:forum, FactoryGirl.create(:forum))
assign(:post, FactoryGirl.create(:post, :forum => @forum))
render
end
it 'creates a hidden field' do
assert_select "input#post_forum_id[type=hidden][value=#{@forum.id}]"
end
it 'tells the user what forum it will be posted in' do
rendered.should contain "This post will be posted in the forum #{@forum.name}"
end
end
end

View File

@@ -42,6 +42,15 @@ describe "posts/show" do
rendered.should contain @comment.body
end
context "forum post" do
it "shows forum name" do
@post = assign(:post,
FactoryGirl.create(:forum_post, :author => @author))
render
rendered.should contain "in #{@post.forum.name}"
end
end
context "signed in" do
before(:each) do
sign_in @author

View File

@@ -0,0 +1,20 @@
require 'spec_helper'
describe "roles/edit" do
before(:each) do
@role = assign(:role, stub_model(Role,
:name => "MyString",
:description => "MyText"
))
end
it "renders the edit role form" do
render
# Run the generator again with the --webrat flag if you want to use webrat matchers
assert_select "form", :action => roles_path(@role), :method => "post" do
assert_select "input#role_name", :name => "role[name]"
assert_select "textarea#role_description", :name => "role[description]"
end
end
end

View File

@@ -0,0 +1,23 @@
require 'spec_helper'
describe "roles/index" do
before(:each) do
assign(:roles, [
stub_model(Role,
:name => "Name",
:description => "MyText"
),
stub_model(Role,
:name => "Name",
:description => "MyText"
)
])
end
it "renders a list of roles" do
render
# Run the generator again with the --webrat flag if you want to use webrat matchers
assert_select "tr>td", :text => "Name".to_s, :count => 2
assert_select "tr>td", :text => "MyText".to_s, :count => 2
end
end

View File

@@ -0,0 +1,20 @@
require 'spec_helper'
describe "roles/new" do
before(:each) do
assign(:role, stub_model(Role,
:name => "MyString",
:description => "MyText"
).as_new_record)
end
it "renders new role form" do
render
# Run the generator again with the --webrat flag if you want to use webrat matchers
assert_select "form", :action => roles_path, :method => "post" do
assert_select "input#role_name", :name => "role[name]"
assert_select "textarea#role_description", :name => "role[description]"
end
end
end

View File

@@ -0,0 +1,17 @@
require 'spec_helper'
describe "roles/show" do
before(:each) do
@role = assign(:role, stub_model(Role,
:name => "Name",
:description => "MyText"
))
end
it "renders attributes in <p>" do
render
# Run the generator again with the --webrat flag if you want to use webrat matchers
rendered.should match(/Name/)
rendered.should match(/MyText/)
end
end