aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWei Xie <xieconnect@gmail.com>2010-06-06 10:14:09 +0800
committerHans de Graaff <hans@degraaff.org>2010-07-25 09:08:51 +0200
commit854029152445e65fa67a59d49721801a8ee654df (patch)
tree4f489226a6e7e45ed8246f55b6b031a7246b2854
parentimport User data from db:seed (diff)
downloadcouncil-webapp-854029152445e65fa67a59d49721801a8ee654df.tar.gz
council-webapp-854029152445e65fa67a59d49721801a8ee654df.tar.bz2
council-webapp-854029152445e65fa67a59d49721801a8ee654df.zip
Agenda implemented and tested
-rw-r--r--app/controllers/agendas_controller.rb7
-rw-r--r--app/models/agenda.rb27
-rw-r--r--app/views/taglibs/auto/rapid/cards.dryml11
-rw-r--r--app/views/taglibs/auto/rapid/forms.dryml12
-rw-r--r--app/views/taglibs/auto/rapid/pages.dryml123
-rw-r--r--db/migrate/20100606022209_create_agendas.rb18
-rw-r--r--db/seeds.rb21
-rw-r--r--features/agenda.feature44
-rw-r--r--features/step_definitions/agenda_steps.rb15
-rw-r--r--features/step_definitions/user_steps.rb12
-rw-r--r--features/support/helper.rb15
-rw-r--r--lib/permission.rb16
-rw-r--r--spec/fixtures/agendas.yml18
-rw-r--r--spec/models/agenda_spec.rb27
14 files changed, 366 insertions, 0 deletions
diff --git a/app/controllers/agendas_controller.rb b/app/controllers/agendas_controller.rb
new file mode 100644
index 0000000..438fff7
--- /dev/null
+++ b/app/controllers/agendas_controller.rb
@@ -0,0 +1,7 @@
+class AgendasController < ApplicationController
+
+ hobo_model_controller
+
+ auto_actions :all
+
+end
diff --git a/app/models/agenda.rb b/app/models/agenda.rb
new file mode 100644
index 0000000..057fc7e
--- /dev/null
+++ b/app/models/agenda.rb
@@ -0,0 +1,27 @@
+require 'permission'
+
+class Agenda < ActiveRecord::Base
+
+ hobo_model # Don't put anything above this
+
+ fields do
+ name :string, :required
+ description :text
+ timestamps
+ end
+
+ belongs_to :owner, :class_name => 'User', :creator => true
+
+ validates_presence_of :owner
+
+ # --- Permissions --- #
+ never_show :owner
+
+ multi_permission(:create, :update, :destroy) do
+ permitted_for_roles(:admin, :council_member)
+ end
+
+ def view_permitted?(field)
+ true
+ end
+end
diff --git a/app/views/taglibs/auto/rapid/cards.dryml b/app/views/taglibs/auto/rapid/cards.dryml
index 38c8c7f..4186cdc 100644
--- a/app/views/taglibs/auto/rapid/cards.dryml
+++ b/app/views/taglibs/auto/rapid/cards.dryml
@@ -1,5 +1,16 @@
<!-- AUTOMATICALLY GENERATED FILE - DO NOT EDIT -->
+<def tag="card" for="Agenda">
+ <card class="agenda" param="default" merge>
+ <header: param>
+ <h4 param="heading"><a><name/></a></h4>
+ </header:>
+ <body: param>
+ <a:owner param="creator-link"/>
+ </body:>
+ </card>
+</def>
+
<def tag="card" for="Question">
<card class="question" param="default" merge>
<header: param>
diff --git a/app/views/taglibs/auto/rapid/forms.dryml b/app/views/taglibs/auto/rapid/forms.dryml
index a359af6..c57f7b6 100644
--- a/app/views/taglibs/auto/rapid/forms.dryml
+++ b/app/views/taglibs/auto/rapid/forms.dryml
@@ -1,5 +1,17 @@
<!-- AUTOMATICALLY GENERATED FILE - DO NOT EDIT -->
+<def tag="form" for="Agenda">
+ <form merge param="default">
+ <error-messages param/>
+ <field-list fields="name, description" param/>
+ <div param="actions">
+ <submit label="#{ht 'agendas.actions.save', :default=>['Save']}" param/><or-cancel param="cancel"/>
+ </div>
+ </form>
+</def>
+
+
+
<def tag="form" for="Question">
<form merge param="default">
<error-messages param/>
diff --git a/app/views/taglibs/auto/rapid/pages.dryml b/app/views/taglibs/auto/rapid/pages.dryml
index ad1eee4..5b4a00a 100644
--- a/app/views/taglibs/auto/rapid/pages.dryml
+++ b/app/views/taglibs/auto/rapid/pages.dryml
@@ -5,6 +5,7 @@
<def tag="main-nav">
<navigation class="main-nav" merge-attrs param="default">
<nav-item href="#{base_url}/">Home</nav-item>
+ <nav-item with="&Agenda"><ht key="agendas.nav_item">Agendas</ht></nav-item>
<nav-item with="&Question"><ht key="questions.nav_item">Questions</ht></nav-item>
</navigation>
</def>
@@ -12,6 +13,128 @@
+<!-- ====== Agenda Pages ====== -->
+
+<def tag="index-page" for="Agenda">
+ <page merge title="#{ht 'agendas.index.title', :default=>['Agendas'] }">
+ <body: class="index-page agenda" param/>
+
+ <content: param>
+ <header param="content-header">
+ <h2 param="heading">
+ <ht key="agendas.index.heading">
+ Agendas
+ </ht>
+ </h2>
+
+ <p param="count" if>
+ <ht key="agendas.collection.count" count="&this.size">
+ There <count prefix="are"/>
+ </ht>
+ </p>
+ </header>
+
+ <section param="content-body">
+ <a action="new" to="&model" param="new-link">
+ <ht key="agendas.actions.new">New Agenda</ht>
+ </a>
+
+ <page-nav param="top-page-nav"/>
+
+ <collection param/>
+
+ <page-nav param="bottom-page-nav"/>
+
+
+ </section>
+ </content:>
+ </page>
+</def>
+
+
+<def tag="new-page" for="Agenda">
+ <page merge title="#{ht 'agendas.new.title', :default=>[' New Agenda'] }">
+ <body: class="new-page agenda" param/>
+
+ <content: param>
+ <section param="content-header">
+ <h2 param="heading">
+ <ht key="agendas.new.heading">
+ New Agenda
+ </ht>
+ </h2>
+ </section>
+
+ <section param="content-body">
+ <form param>
+ <submit: label="#{ht 'agendas.actions.create', :default=>['Create Agenda']}"/>
+ </form>
+ </section>
+ </content:>
+ </page>
+</def>
+
+
+<def tag="show-page" for="Agenda">
+ <page merge title="#{ht 'agendas.show.title', :default=>['Agenda'] }">
+
+ <body: class="show-page agenda" param/>
+
+ <content: param>
+ <header param="content-header">
+ <h2 param="heading">
+ <ht key="agendas.show.heading" name="&this.respond_to?(:name) ? this.name : ''">
+ <name/>
+ </ht>
+ </h2>
+
+ <record-flags fields="" param/>
+
+ <a:owner param="creator-link"/>
+
+ <a action="edit" if="&can_edit?" param="edit-link">
+ <ht key="agendas.actions.edit" name="&this.respond_to?(:name) ? this.name : ''">
+ Edit Agenda
+ </ht>
+ </a>
+ </header>
+
+ <section param="content-body">
+ <view:description param="description"/>
+ </section>
+ </content:>
+
+ </page>
+</def>
+
+
+<def tag="edit-page" for="Agenda">
+ <page merge title="#{ht 'agendas.edit.title', :default=>['Edit Agenda'] }">
+
+ <body: class="edit-page agenda" param/>
+
+ <content:>
+ <section param="content-header">
+ <h2 param="heading">
+ <ht key="agendas.edit.heading" name="&this.respond_to?(:name) ? this.name : ''">
+ Edit <type-name/>
+ </ht>
+ </h2>
+ <delete-button label="#{ht 'agendas.actions.delete', :default=>['Remove This Agenda']}" param/>
+ </section>
+
+ <section param="content-body">
+ <form param/>
+ </section>
+ </content:>
+
+ </page>
+</def>
+
+
+
+
+
<!-- ====== Question Pages ====== -->
<def tag="index-page" for="Question">
diff --git a/db/migrate/20100606022209_create_agendas.rb b/db/migrate/20100606022209_create_agendas.rb
new file mode 100644
index 0000000..14a878d
--- /dev/null
+++ b/db/migrate/20100606022209_create_agendas.rb
@@ -0,0 +1,18 @@
+class CreateAgendas < ActiveRecord::Migration
+ def self.up
+ create_table :agendas do |t|
+ t.string :name
+ t.text :description
+ t.datetime :start_at
+ t.datetime :end_at
+ t.datetime :created_at
+ t.datetime :updated_at
+ t.integer :owner_id
+ end
+ add_index :agendas, [:owner_id]
+ end
+
+ def self.down
+ drop_table :agendas
+ end
+end
diff --git a/db/seeds.rb b/db/seeds.rb
index 5882a4b..cd12661 100644
--- a/db/seeds.rb
+++ b/db/seeds.rb
@@ -31,3 +31,24 @@ users = User.create([
:password => 'developer',
:password_confirmation => 'developer'}
])
+
+puts 'adding agendas...'
+agendas = Agenda.create([
+ { :name => 'Go to the Zoo',
+ :description => 'Disneyland',
+ :start_at => 15.days.from_now,
+ :end_at => 16.days.from_now,
+ :owner_id => users[1].id},
+
+ { :name => 'hosting a party',
+ :description => 'HIT',
+ :start_at => 15.days.from_now,
+ :end_at => 16.days.from_now,
+ :owner_id => users[1].id},
+
+ { :name => 'agenda_test_name',
+ :description => 'agenda_test_description',
+ :start_at => 15.days.from_now,
+ :end_at => 16.days.from_now,
+ :owner_id => users[1].id}
+])
diff --git a/features/agenda.feature b/features/agenda.feature
new file mode 100644
index 0000000..2969dc0
--- /dev/null
+++ b/features/agenda.feature
@@ -0,0 +1,44 @@
+Feature: Basic Agenda Creation
+ As a council member
+ I want to use the webapp to create agendas
+ in order to make my life easier
+
+ Background:
+ Given agenda "agenda_test_name" exists
+
+ Scenario: Guest operations
+ When I am on the home page
+ And I follow "Agendas"
+ And I follow "agenda_test_name"
+ Then I should see "agenda_test_name"
+ And I should not see "Edit Agenda"
+
+ Scenario: Council member creates agenda
+ Given I visit agendas as a council member
+ When I follow "New Agenda"
+ And I fill in "agenda_name" with "another_agenda_name"
+ And I press "Create Agenda"
+ Then I should see "created successfully"
+ When I go to the home page
+ And I follow "Agendas"
+ Then I should see "another_agenda_name"
+
+ Scenario: Council member edits agenda
+ Given I visit agendas as a council member
+ When I follow "agenda_test_name"
+ And I follow "Edit Agenda"
+ And I fill in "agenda_name" with "agenda_name_modified"
+ And I press "Save"
+ Then I should see "were saved"
+ When I go to the home page
+ And I follow "Agendas"
+ Then I should see "agenda_name_modified"
+
+ Scenario: Council member deletes agenda
+ Given I visit agendas as a council member
+ When I follow "agenda_test_name"
+ And I follow "Edit Agenda"
+ And I press "Remove This Agenda"
+ Then I should see "was deleted"
+ When I go to the home page
+ Then I should not see "agenda_modified"
diff --git a/features/step_definitions/agenda_steps.rb b/features/step_definitions/agenda_steps.rb
new file mode 100644
index 0000000..94a6248
--- /dev/null
+++ b/features/step_definitions/agenda_steps.rb
@@ -0,0 +1,15 @@
+# agenda creation testing is already covered in other steps.
+# let's speed up the test by directly modifying the Model
+Given /^agenda "([^\"]*)" exists$/ do |agenda_name|
+ @agenda = agendas(:agenda_one)
+ if @agenda.name != agenda_name
+ @agenda.update_attributes(:name => agenda_name)
+ end
+end
+
+# avoid repetition in agenda.features
+Given /^I visit agendas as a (.+)$/ do |user|
+ Given "I am logged in as a #{user}"
+ And 'I am on the home page'
+ When 'I follow "Agendas"'
+end
diff --git a/features/step_definitions/user_steps.rb b/features/step_definitions/user_steps.rb
new file mode 100644
index 0000000..1b4c321
--- /dev/null
+++ b/features/step_definitions/user_steps.rb
@@ -0,0 +1,12 @@
+Given /^I am a visitor$/ do
+ When 'I am on the home page'
+ Then 'I should not see "Logged in as"'
+end
+
+Given /^I am logged in as a (.+)$/ do |user|
+ @user = login_as(user.gsub(/\s/, '_').to_sym)
+ visit user_login_path
+ When %Q{I fill in "login" with "#{@user.email_address}"}
+ And 'I fill in "password" with "kktest3"'
+ And 'I press "Log in"'
+end
diff --git a/features/support/helper.rb b/features/support/helper.rb
new file mode 100644
index 0000000..f58b53d
--- /dev/null
+++ b/features/support/helper.rb
@@ -0,0 +1,15 @@
+# helper for feature test
+
+# helper method for user steps
+def login_as(role)
+ user = User.create!(
+ :name => 'kktest3',
+ :login => 'kktest3@kktest3.com',
+ :password => 'kktest3',
+ :password_confirmation => 'kktest3',
+ :role => :developer # will be ignored
+ )
+ user.role = role
+ user.save!
+ user
+end
diff --git a/lib/permission.rb b/lib/permission.rb
new file mode 100644
index 0000000..9a68a8e
--- /dev/null
+++ b/lib/permission.rb
@@ -0,0 +1,16 @@
+# methods one_permission and multi_permission are originally authored by ahenobarbi.
+# Refer to http://github.com/ahenobarbi/Gentoo-Recruiters-App/blob/master/lib/permissions/set.rb
+
+def one_permission(permission, &block)
+ define_method("#{permission.to_s}_permitted?", &block)
+end
+
+def multi_permission(*permission_list, &block)
+ permission_list.flatten.each do |target|
+ one_permission(target, &block)
+ end
+end
+
+def permitted_for_roles(*roles)
+ acting_user.signed_up? and roles.flatten.include?(acting_user.role.to_sym)
+end
diff --git a/spec/fixtures/agendas.yml b/spec/fixtures/agendas.yml
new file mode 100644
index 0000000..141c7cb
--- /dev/null
+++ b/spec/fixtures/agendas.yml
@@ -0,0 +1,18 @@
+agenda_one:
+ name: Go to the Zoo
+ description: Disneyland
+ start_at: <%= 15.days.from_now %>
+ end_at: <%= 16.days.from_now %>
+ owner: council_member
+agenda_two:
+ name: hosting a party
+ description: HIT
+ start_at: <%= 15.days.from_now %>
+ end_at: <%= 16.days.from_now %>
+ owner: council_member
+agenda_test_name:
+ name: agenda_test_name
+ description: agenda_test_description
+ start_at: <%= 15.days.from_now %>
+ end_at: <%= 16.days.from_now %>
+ owner: council_member
diff --git a/spec/models/agenda_spec.rb b/spec/models/agenda_spec.rb
new file mode 100644
index 0000000..56f866b
--- /dev/null
+++ b/spec/models/agenda_spec.rb
@@ -0,0 +1,27 @@
+require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
+
+describe Agenda do
+ before(:each) do
+ @agenda = agendas(:agenda_one)
+ end
+
+ it "should allow guest to view" do
+ @agenda.should be_viewable_by(users(:guest))
+ end
+
+ it "should allow council member to create" do
+ Agenda.new(
+ :name => 'agenda3',
+ :description => 'agenda 3'
+ ).should be_creatable_by(users(:council_member))
+ end
+
+ it "should not allow guest to update" do
+ @agenda.should_not be_updatable_by(users(:guest))
+ end
+
+ it "should allow council member to edit" do
+ agenda = agendas(:agenda_one)
+ agenda.should be_updatable_by(users(:council_member))
+ end
+end