From de1066092377db2da80952e3c2090e1cf6f29a2e Mon Sep 17 00:00:00 2001 From: Travis Grathwell Date: Thu, 10 Dec 2015 22:47:13 -0800 Subject: [PATCH] Admins can create / update Chapters --- app/controllers/chapters_controller.rb | 44 +++++++++++- app/models/chapter.rb | 6 ++ app/views/chapters/_form.html.erb | 18 +++++ app/views/chapters/edit.html.erb | 9 +++ app/views/chapters/index.html.erb | 12 +++- app/views/chapters/new.html.erb | 7 ++ app/views/chapters/show.html.erb | 1 + config/routes.rb | 2 +- spec/controllers/chapters_controller_spec.rb | 71 ++++++++++++++++++++ 9 files changed, 166 insertions(+), 4 deletions(-) create mode 100644 app/views/chapters/_form.html.erb create mode 100644 app/views/chapters/edit.html.erb create mode 100644 app/views/chapters/new.html.erb create mode 100644 spec/controllers/chapters_controller_spec.rb diff --git a/app/controllers/chapters_controller.rb b/app/controllers/chapters_controller.rb index 1318cf6ca..f7a6a1f29 100644 --- a/app/controllers/chapters_controller.rb +++ b/app/controllers/chapters_controller.rb @@ -1,6 +1,7 @@ class ChaptersController < ApplicationController - before_action :authenticate_user!, :except => [:show, :index] - before_action :assign_chapter, :only => [:show] + before_action :authenticate_user!, except: [:show, :index] + before_action :assign_chapter, except: [:index, :new, :create] + before_action :validate_admin!, except: [:show, :index] def index @chapters = Chapter.all @@ -12,8 +13,47 @@ def show ).sort_by(&:ends_at) end + def new + @chapter = Chapter.new + end + + def edit + end + + def create + @chapter = Chapter.new(chapter_params) + + if @chapter.save + redirect_to @chapter, notice: 'Chapter was successfully created.' + else + render :new + end + end + + def update + if @chapter.update_attributes(chapter_params) + redirect_to @chapter, notice: 'Chapter was successfully updated.' + else + render :edit + end + end + + def destroy + unless @chapter.destroyable? + return redirect_to root_url, alert: "Can't delete a chapter that's still assigned to an event or external event." + end + + @chapter.destroy + + redirect_to chapters_url + end + private + def chapter_params + params.require(:chapter).permit(Chapter::PERMITTED_ATTRIBUTES) + end + def assign_chapter @chapter = Chapter.find(params[:id]) end diff --git a/app/models/chapter.rb b/app/models/chapter.rb index e9ad9ea9b..bf6bca8a9 100644 --- a/app/models/chapter.rb +++ b/app/models/chapter.rb @@ -1,7 +1,13 @@ class Chapter < ActiveRecord::Base + PERMITTED_ATTRIBUTES = [:name, :organization_id] + belongs_to :organization has_many :events has_many :external_events validates_presence_of :organization + + def destroyable? + (events_count + external_events_count) == 0 + end end diff --git a/app/views/chapters/_form.html.erb b/app/views/chapters/_form.html.erb new file mode 100644 index 000000000..5b8076fa9 --- /dev/null +++ b/app/views/chapters/_form.html.erb @@ -0,0 +1,18 @@ +
+
+ <%= simple_form_for(@chapter) do |f| %> + <%= render 'shared/model_error_messages', model: @chapter %> + +
+ <%= f.label :organization_id %> + <%= f.collection_select(:organization_id, Organization.order(:name), :id, :name, {prompt: true}, {class: 'form-control'}) %> +
+ + <%= f.input :name %> + +
+ <%= f.submit class: 'btn btn-submit', data: {disable_with: 'Please wait...'} %> +
+ <% end %> +
+
diff --git a/app/views/chapters/edit.html.erb b/app/views/chapters/edit.html.erb new file mode 100644 index 000000000..7c7208755 --- /dev/null +++ b/app/views/chapters/edit.html.erb @@ -0,0 +1,9 @@ +<%= content_for(:header_text, "Editing chapter") %> + +<%= render 'form' %> + +<%= render 'shared/actions', links: [ + ['Show', @chapter], + ['Back', chapters_path] +] %> + diff --git a/app/views/chapters/index.html.erb b/app/views/chapters/index.html.erb index 9bc6c4e62..7d7d825a1 100644 --- a/app/views/chapters/index.html.erb +++ b/app/views/chapters/index.html.erb @@ -5,6 +5,9 @@ Name Events + <% if current_user.try(:admin?) %> + + <% end %> @@ -13,9 +16,16 @@ <%= link_to chapter.name, chapter %> <%= chapter.events_count + chapter.external_events_count %> + <% if current_user.try(:admin?) %> + + <% if current_user.try(:admin?) && chapter.destroyable? %> + <%= link_to 'Destroy', chapter, data: {confirm: 'Are you sure?'}, method: :delete, class: 'btn btn-danger' %> + <% end %> + + <% end %> <% end %> -<%= render 'shared/actions', links: crud_object_nav_links(:chapter) %> \ No newline at end of file +<%= render 'shared/actions', links: crud_object_nav_links(:chapter, current_user.try(:admin?) ? ['New Chapter', new_chapter_path] : nil) %> \ No newline at end of file diff --git a/app/views/chapters/new.html.erb b/app/views/chapters/new.html.erb new file mode 100644 index 000000000..ce5e19ee8 --- /dev/null +++ b/app/views/chapters/new.html.erb @@ -0,0 +1,7 @@ +<%= content_for(:header_text, 'New chapter') %> + +<%= render 'form' %> + +<%= render 'shared/actions', links: [ + ['Back', chapters_path] +] %> diff --git a/app/views/chapters/show.html.erb b/app/views/chapters/show.html.erb index 2082a1c60..6b51e5e1f 100644 --- a/app/views/chapters/show.html.erb +++ b/app/views/chapters/show.html.erb @@ -4,5 +4,6 @@ <%= render 'shared/events_table', events: @chapter_events %> <%= render 'shared/actions', links: [ + current_user.try(:admin?) ? ['Edit', edit_chapter_path(@chapter)] : nil, ['Back', chapters_path] ] %> diff --git a/config/routes.rb b/config/routes.rb index 8ae96a061..4f59b2acc 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -13,7 +13,7 @@ resources :meetup_users, only: [:show] resources :locations - resources :chapters, only: [:index, :show] + resources :chapters resources :regions do resources :region_leaderships, only: [:index, :create, :destroy] end diff --git a/spec/controllers/chapters_controller_spec.rb b/spec/controllers/chapters_controller_spec.rb new file mode 100644 index 000000000..2d5b424e3 --- /dev/null +++ b/spec/controllers/chapters_controller_spec.rb @@ -0,0 +1,71 @@ +require 'rails_helper' + +describe ChaptersController do + let(:organization) { create(:organization, name: 'SpaceBridge') } + let(:user) { create(:user, admin: true) } + + before do + sign_in user + end + + describe '#index' do + let!(:chapter) { create(:chapter) } + + it 'shows all the chapters' do + get :index + expect(assigns(:chapters)).to match_array([chapter]) + end + end + + describe '#new' do + it 'shows an empty chapter' do + get :new + expect(response).to be_success + end + end + + describe '#create' do + it 'creates a new chapter' do + expect { + post :create, chapter: {name: "Fabulous Chapter", organization_id: organization.id} + }.to change(Chapter, :count).by(1) + end + end + + describe '#edit' do + let!(:chapter) { create(:chapter) } + + it "shows a chapter edit form" do + get :edit, id: chapter.id + expect(response).to be_success + end + end + + describe '#update' do + let!(:chapter) { create(:chapter) } + + it "changes chapter details" do + expect { + put :update, id: chapter.id, chapter: {name: 'Sandwich Chapter'} + }.to change { chapter.reload.name } + expect(response).to redirect_to(chapter_path(chapter)) + end + end + + describe "#destroy" do + let!(:chapter) { create(:chapter) } + + it "can delete a chapter that belongs to no events" do + expect { + delete :destroy, {id: chapter.id} + }.to change(Chapter, :count).by(-1) + end + + it "cannot delete a chapter that belongs to a event" do + create(:event, chapter: chapter) + expect { + delete :destroy, {id: chapter.id} + }.not_to change(Chapter, :count) + end + end +end