From f914d809e0c6ebedf9b3583a2c5a40405363fd82 Mon Sep 17 00:00:00 2001 From: Justin Grevich Date: Fri, 19 Apr 2013 18:34:14 -0700 Subject: [PATCH] refined code for recommenders and added basic tests. --- Gemfile | 92 +++--- Gemfile.lock | 186 ++++++++++- Guardfile | 33 ++ .../applicants/recommenders_controller.rb | 34 +- .../applicants/registrations_controller.rb | 117 ------- app/controllers/users/sessions_controller.rb | 42 ++- app/models/applicant.rb | 13 +- app/models/recommendation.rb | 10 + app/models/recommender.rb | 41 ++- .../recommendations/edit.html.erb | 0 .../applicants/recommenders/edit.html.erb | 6 +- config/environments/development.rb | 4 +- config/environments/production.rb | 2 +- config/environments/test.rb | 4 +- config/initializers/rails_admin.rb | 68 ---- config/routes.rb | 69 +---- .../academic_records_controller_spec.rb | 2 +- .../confirmations_controller_spec.rb | 2 +- .../recommendations_controller_spec.rb | 3 +- .../recommenders_controller_spec.rb | 293 ++++++++++++++++++ .../registrations_controller_spec.rb | 2 +- .../applicants/sessions_controller_spec.rb | 2 +- .../users/sessions_controller_spec.rb | 2 +- spec/factories/applicants.rb | 35 +++ spec/factories/recommendations.rb | 8 + spec/factories/recommenders.rb | 12 + spec/helpers/academic_records_helper_spec.rb | 2 +- spec/models/recommender_spec.rb | 27 ++ spec/spec_helper.rb | 62 ++++ spec/support/devise.rb | 5 + spec/support/mailer.rb | 11 + 31 files changed, 860 insertions(+), 329 deletions(-) create mode 100644 Guardfile rename app/views/{ => applicants}/recommendations/edit.html.erb (100%) create mode 100644 spec/controllers/applicants/recommenders_controller_spec.rb create mode 100644 spec/factories/applicants.rb create mode 100644 spec/factories/recommendations.rb create mode 100644 spec/factories/recommenders.rb create mode 100644 spec/spec_helper.rb create mode 100644 spec/support/devise.rb create mode 100644 spec/support/mailer.rb diff --git a/Gemfile b/Gemfile index 479c3cb5..077af147 100644 --- a/Gemfile +++ b/Gemfile @@ -9,60 +9,70 @@ source 'http://gems.github.com' gem 'rails', '~>3.2.12' gem 'aasm' -gem 'carmen' -gem 'capistrano' -# gem 'capistrano-database', :git => "git://github.com/jgrevich/capistrano-database.git" -gem 'rvm-capistrano' - -gem 'devise' #gem 'exception_notification', :require => 'exception_notifier' gem 'figaro' gem 'formtastic' gem 'haml' -gem 'jquery-rails' + +gem 'carmen' +gem 'ckeditor' +gem 'client_side_validations' +gem 'cocaine', :git => 'git://github.com/thoughtbot/cocaine.git' +gem 'capistrano' +gem 'devise' +gem 'eventbrite-client' +gem 'jquery-rails', '~> 2.1.0' +gem 'jquery-ui-rails' gem 'kaminari' gem 'mysql2' gem 'paperclip' +gem 'paper_trail' gem 'rails_admin' +gem 'rvm-capistrano' +gem 'whenever', :require => false -# Use unicorn as the web server -# gem 'unicorn' - -# To use debugger (ruby-debug for Ruby 1.8.7+, ruby-debug19 for Ruby 1.9.2+) -# gem 'ruby-debug' -# gem 'ruby-debug19', :require => 'ruby-debug' - -# Bundle the extra gems: -# gem 'bj' -# gem 'nokogiri' -# gem 'sqlite3-ruby', :require => 'sqlite3' -# gem 'aws-s3', :require => 'aws/s3' -# Bundle gems for the local environment. Make sure to -# put test-only gems in this group so their generators -# and rake tasks are available in development mode: -# group :development, :test do -# gem 'webrat' -# end +group :assets do + gem 'bootstrap-sass', '~> 2.1.1.0' + gem 'bootstrap-datepicker-rails', :require => 'bootstrap-datepicker-rails', :git => 'git://github.com/Nerian/bootstrap-datepicker-rails.git' + gem 'coffee-rails', '~> 3.2.1' + gem 'font-awesome-sass-rails' + gem 'libv8', '~> 3.11.8' + gem 'modernizr-rails' + gem 'therubyracer' + gem 'sass-rails', '~> 3.2.3' + gem 'uglifier', '>= 1.0.3' +end -group :development, :test do -# gem 'bond' - gem 'bundler' +group :development do + gem "better_errors" + gem 'binding_of_caller' gem 'map_by_method' -# gem 'mocha' + gem 'meta_request' + gem 'rb-fchange', :require => false + gem 'rb-fsevent', :require => false + gem 'rb-inotify', :require => false + gem 'ruby_gntp' + gem 'simplecov' gem 'what_methods' - gem 'wirble' + gem 'wirble' end -# Gems used only for assets and not required -# in production environments by default. -group :assets do - gem 'bootstrap-sass', '~> 2.1.0.0' - gem 'bootstrap-datepicker-rails', :require => 'bootstrap-datepicker-rails', :git => 'git://github.com/Nerian/bootstrap-datepicker-rails.git' - gem 'coffee-rails', " ~> 3.2.0" - gem 'libv8', '~> 3.11.8' - gem 'sass-rails', " ~> 3.2.0" - gem 'font-awesome-sass-rails' - gem 'uglifier' - gem 'therubyracer' +group :test, :development do + gem 'capybara' + gem "capybara-webkit" + gem 'database_cleaner' + gem 'debugger' + gem 'faker' + gem 'factory_girl_rails' + gem 'launchy' + gem 'poltergeist' + gem "rspec-rails", "~> 2.0" +end + +group :test do + gem 'guard-livereload' + gem 'guard-rspec' + gem 'shoulda' + gem 'sqlite3' end diff --git a/Gemfile.lock b/Gemfile.lock index 7fdc20c7..96c2a850 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -5,6 +5,13 @@ GIT bootstrap-datepicker-rails (1.0.0.4) railties (>= 3.0) +GIT + remote: git://github.com/thoughtbot/cocaine.git + revision: 1fa540ec169919930db3a0e6e4a2f5d9421b9aeb + specs: + cocaine (0.5.1) + climate_control (>= 0.0.3, < 1.0) + GEM remote: http://rubygems.org/ remote: http://gems.github.com/ @@ -37,9 +44,17 @@ GEM activesupport (3.2.13) i18n (= 0.6.1) multi_json (~> 1.0) + addressable (2.3.4) arel (3.0.2) bcrypt-ruby (3.0.1) - bootstrap-sass (2.1.0.1) + better_errors (0.8.0) + coderay (>= 1.0.0) + erubis (>= 2.6.6) + binding_of_caller (0.7.1) + debug_inspector (>= 0.0.1) + bootstrap-sass (2.1.1.0) + bourne (1.4.0) + mocha (~> 0.13.2) builder (3.0.4) capistrano (2.14.2) highline @@ -47,11 +62,24 @@ GEM net-sftp (>= 2.0.0) net-ssh (>= 2.0.14) net-ssh-gateway (>= 1.1.0) + capybara (2.1.0) + mime-types (>= 1.16) + nokogiri (>= 1.3.3) + rack (>= 1.0.0) + rack-test (>= 0.5.4) + xpath (~> 2.0) + capybara-webkit (0.14.2) + capybara (~> 2.0, >= 2.0.2) + json carmen (0.2.13) + chronic (0.9.1) + ckeditor (4.0.4) + mime-types + orm_adapter + client_side_validations (3.2.5) climate_control (0.0.3) activesupport (>= 3.0) - cocaine (0.5.1) - climate_control (>= 0.0.3, < 1.0) + coderay (1.0.9) coffee-rails (3.2.2) coffee-script (>= 2.2.0) railties (~> 3.2.0) @@ -59,28 +87,73 @@ GEM coffee-script-source execjs coffee-script-source (1.6.2) + columnize (0.3.6) + database_cleaner (0.9.1) + debug_inspector (0.0.2) + debugger (1.5.0) + columnize (>= 0.3.1) + debugger-linecache (~> 1.2.0) + debugger-ruby_core_source (~> 1.2.0) + debugger-linecache (1.2.0) + debugger-ruby_core_source (1.2.0) devise (2.2.3) bcrypt-ruby (~> 3.0) orm_adapter (~> 0.1) railties (~> 3.1) warden (~> 1.2.1) + diff-lcs (1.2.3) + em-websocket (0.5.0) + eventmachine (>= 0.12.9) + http_parser.rb (~> 0.5.3) erubis (2.7.0) + eventbrite-client (0.1.4) + httparty (~> 0.8.0) + tzinfo (~> 0.3.22) + eventmachine (1.0.3) execjs (1.4.0) multi_json (~> 1.0) + factory_girl (4.2.0) + activesupport (>= 3.0.0) + factory_girl_rails (4.2.1) + factory_girl (~> 4.2.0) + railties (>= 3.0.0) + faker (1.1.2) + i18n (~> 0.5) + faye-websocket (0.4.7) + eventmachine (>= 0.12.0) + ffi (1.7.0) figaro (0.6.3) bundler (~> 1.0) rails (>= 3, < 5) font-awesome-sass-rails (3.0.2.2) railties (>= 3.1.1) sass-rails (>= 3.1.1) + formatador (0.2.4) formtastic (2.2.1) actionpack (>= 3.0) + guard (1.7.0) + formatador (>= 0.2.4) + listen (>= 0.6.0) + lumberjack (>= 1.0.2) + pry (>= 0.9.10) + thor (>= 0.14.6) + guard-livereload (1.2.1) + em-websocket (>= 0.2.0) + guard (>= 1.5.0) + multi_json (~> 1.0) + guard-rspec (2.5.3) + guard (>= 1.1) + rspec (~> 2.11) haml (3.1.8) highline (1.6.18) hike (1.2.2) + http_parser.rb (0.5.3) + httparty (0.8.3) + multi_json (~> 1.0) + multi_xml i18n (0.6.1) journey (1.0.4) - jquery-rails (2.2.1) + jquery-rails (2.1.4) railties (>= 3.0, < 5.0) thor (>= 0.14, < 2.0) jquery-ui-rails (3.0.1) @@ -90,14 +163,27 @@ GEM kaminari (0.14.1) actionpack (>= 3.0.0) activesupport (>= 3.0.0) + launchy (2.3.0) + addressable (~> 2.3) libv8 (3.11.8.17) + listen (0.7.3) + lumberjack (1.0.3) mail (2.5.3) i18n (>= 0.4.0) mime-types (~> 1.16) treetop (~> 1.4.8) map_by_method (0.8.3) + meta_request (0.2.3) + rack-contrib + railties + metaclass (0.0.1) + method_source (0.8.1) mime-types (1.22) + mocha (0.13.3) + metaclass (~> 0.0.1) + modernizr-rails (2.6.2.1) multi_json (1.7.2) + multi_xml (0.5.3) mysql2 (0.3.11) nested_form (0.3.2) net-scp (1.1.0) @@ -109,16 +195,29 @@ GEM net-ssh (>= 2.6.5) nokogiri (1.5.9) orm_adapter (0.4.0) + paper_trail (2.7.1) + activerecord (~> 3.0) + railties (~> 3.0) paperclip (3.4.1) activemodel (>= 3.0.0) activerecord (>= 3.0.0) activesupport (>= 3.0.0) cocaine (~> 0.5.0) mime-types + poltergeist (1.2.0) + capybara (~> 2.1.0) + faye-websocket (~> 0.4, >= 0.4.4) + http_parser.rb (~> 0.5.3) polyglot (0.3.3) + pry (0.9.12) + coderay (~> 1.0.5) + method_source (~> 0.8) + slop (~> 3.4) rack (1.4.5) rack-cache (1.2) rack (>= 0.4) + rack-contrib (1.1.0) + rack (>= 0.9.1) rack-pjax (0.7.0) nokogiri (~> 1.5) rack (~> 1.3) @@ -156,10 +255,31 @@ GEM rdoc (~> 3.4) thor (>= 0.14.6, < 2.0) rake (10.0.4) + rb-fchange (0.0.6) + ffi + rb-fsevent (0.9.3) + rb-inotify (0.9.0) + ffi (>= 0.5.0) rdoc (3.12.2) json (~> 1.4) ref (1.0.4) remotipart (1.0.5) + rspec (2.13.0) + rspec-core (~> 2.13.0) + rspec-expectations (~> 2.13.0) + rspec-mocks (~> 2.13.0) + rspec-core (2.13.1) + rspec-expectations (2.13.0) + diff-lcs (>= 1.1.3, < 2.0) + rspec-mocks (2.13.1) + rspec-rails (2.13.0) + actionpack (>= 3.0) + activesupport (>= 3.0) + railties (>= 3.0) + rspec-core (~> 2.13.0) + rspec-expectations (~> 2.13.0) + rspec-mocks (~> 2.13.0) + ruby_gntp (0.3.4) rvm-capistrano (1.3.0) capistrano (>= 2.0.0) sass (3.2.7) @@ -167,11 +287,24 @@ GEM railties (~> 3.2.0) sass (>= 3.1.10) tilt (~> 1.3) + shoulda (3.4.0) + shoulda-context (~> 1.0, >= 1.0.1) + shoulda-matchers (~> 1.0, >= 1.4.1) + shoulda-context (1.1.1) + shoulda-matchers (1.5.6) + activesupport (>= 3.0.0) + bourne (~> 1.3) + simplecov (0.7.1) + multi_json (~> 1.0) + simplecov-html (~> 0.7.1) + simplecov-html (0.7.1) + slop (3.4.4) sprockets (2.2.2) hike (~> 1.2) multi_json (~> 1.0) rack (~> 1.0) tilt (~> 1.1, != 1.3.0) + sqlite3 (1.3.7) therubyracer (0.11.4) libv8 (~> 3.11.8.12) ref @@ -187,35 +320,68 @@ GEM warden (1.2.1) rack (>= 1.0) what_methods (1.0.1) + whenever (0.8.2) + activesupport (>= 2.3.4) + chronic (>= 0.6.3) wirble (0.1.3) + xpath (2.0.0) + nokogiri (~> 1.3) PLATFORMS ruby DEPENDENCIES aasm + better_errors + binding_of_caller bootstrap-datepicker-rails! - bootstrap-sass (~> 2.1.0.0) - bundler + bootstrap-sass (~> 2.1.1.0) capistrano + capybara + capybara-webkit carmen - coffee-rails (~> 3.2.0) + ckeditor + client_side_validations + cocaine! + coffee-rails (~> 3.2.1) + database_cleaner + debugger devise + eventbrite-client + factory_girl_rails + faker figaro font-awesome-sass-rails formtastic + guard-livereload + guard-rspec haml - jquery-rails + jquery-rails (~> 2.1.0) + jquery-ui-rails kaminari + launchy libv8 (~> 3.11.8) map_by_method + meta_request + modernizr-rails mysql2 + paper_trail paperclip + poltergeist rails (~> 3.2.12) rails_admin + rb-fchange + rb-fsevent + rb-inotify + rspec-rails (~> 2.0) + ruby_gntp rvm-capistrano - sass-rails (~> 3.2.0) + sass-rails (~> 3.2.3) + shoulda + simplecov + sqlite3 therubyracer - uglifier + uglifier (>= 1.0.3) what_methods + whenever wirble diff --git a/Guardfile b/Guardfile new file mode 100644 index 00000000..a86f1e29 --- /dev/null +++ b/Guardfile @@ -0,0 +1,33 @@ +# A sample Guardfile +# More info at https://github.com/guard/guard#readme + +guard 'livereload' do + watch(%r{app/views/.+\.(erb|haml|slim)$}) + watch(%r{app/helpers/.+\.rb}) + watch(%r{public/.+\.(css|js|html)}) + watch(%r{config/locales/.+\.yml}) + # Rails Assets Pipeline + watch(%r{(app|vendor)(/assets/\w+/(.+\.(css|js|html))).*}) { |m| "/assets/#{m[3]}" } +end + +guard 'rspec' do + watch(%r{^spec/.+_spec\.rb$}) + watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" } + watch('spec/spec_helper.rb') { "spec" } + + # Rails example + watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" } + watch(%r{^app/(.*)(\.erb|\.haml)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" } + watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb" } + watch(%r{^app/models/(.+)\.rb$}) { "spec" } + watch(%r{^spec/support/(.+)\.rb$}) { "spec" } + watch('config/routes.rb') { "spec" } + watch('app/controllers/application_controller.rb') { "spec/controllers" } + + # Capybara features specs + watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/features/#{m[1]}_spec.rb" } + + # Turnip features and steps + watch(%r{^spec/acceptance/(.+)\.feature$}) + watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' } +end diff --git a/app/controllers/applicants/recommenders_controller.rb b/app/controllers/applicants/recommenders_controller.rb index 066f1282..fa994c12 100644 --- a/app/controllers/applicants/recommenders_controller.rb +++ b/app/controllers/applicants/recommenders_controller.rb @@ -1,20 +1,42 @@ class Applicants::RecommendersController < ApplicationController before_filter :authenticate_applicant! + before_filter :instantiate_applicant def edit - if current_applicant.recommendations.count == 0 - r = current_applicant.recommendations.build + if @applicant.recommenders.count == 0 + @applicant.recommenders.build end render :edit end def update - if current_applicant.update_attributes params[:applicant] - redirect_to applicant_status_url + # check to see if recommender_attribs correlates to an existing recommender(s) + recommender_data = Recommender.remove_exisitng_recommenders_from_params(params[:applicant][:recommenders_attributes]) + + + # add existing recommenders to applicant + unless recommender_data[0].empty? + recommender_data[0].map do |r| + @applicant.recommenders << r unless @applicant.recommenders.include?(r) + end + end + if recommender_data[1] + params[:applicant][:recommenders_attributes] = recommender_data[1] + if @applicant.update_attributes(params[:applicant]) + redirect_to applicants_recommenders_url + else + render :edit + end else - render :edit + redirect_to applicants_recommenders_url end end -end + private + + def instantiate_applicant + @applicant = current_applicant + end + +end \ No newline at end of file diff --git a/app/controllers/applicants/registrations_controller.rb b/app/controllers/applicants/registrations_controller.rb index 22f76ac2..89cf6c74 100644 --- a/app/controllers/applicants/registrations_controller.rb +++ b/app/controllers/applicants/registrations_controller.rb @@ -1,82 +1,4 @@ class Applicants::RegistrationsController < Devise::RegistrationsController - prepend_before_filter :require_no_authentication, :only => [ :new, :create, :cancel ] - prepend_before_filter :authenticate_scope!, :only => [:edit, :update, :destroy] - - - # before_filter :set_null_params, :only => [:update, :create] - - # GET /resource/sign_up - def new - resource = build_resource({}) - resource.addresses.build - - respond_with resource - end - - # POST /resource - def create - build_resource - - if resource.save - if resource.active_for_authentication? - set_flash_message :notice, :signed_up if is_navigational_format? - sign_in(resource_name, resource) - respond_with resource, :location => after_sign_up_path_for(resource) - else - set_flash_message :notice, :"signed_up_but_#{resource.inactive_message}" if is_navigational_format? - expire_session_data_after_sign_in! - respond_with resource, :location => after_inactive_sign_up_path_for(resource) - end - else - clean_up_passwords resource - respond_with resource - end - end - - # GET /resource/edit - def edit - resource.addresses.build unless resource.addresses.count > 0 - - render :edit - end - - # PUT /resource - # We need to use a copy of the resource because we don't want to change - # the current user in place. - def update - self.resource = resource_class.to_adapter.get!(send(:"current_#{resource_name}").to_key) - prev_unconfirmed_email = resource.unconfirmed_email if resource.respond_to?(:unconfirmed_email) - if resource.update_without_password(resource_params) - if is_navigational_format? - flash_key = update_needs_confirmation?(resource, prev_unconfirmed_email) ? - :update_needs_confirmation : :updated - set_flash_message :notice, flash_key - end - sign_in resource_name, resource, :bypass => true - respond_with resource, :location => after_update_path_for(resource) - else - clean_up_passwords resource - respond_with resource - end - end - - # DELETE /resource - def destroy - resource.destroy - Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name) - set_flash_message :notice, :destroyed if is_navigational_format? - respond_with_navigational(resource){ redirect_to after_sign_out_path_for(resource_name) } - end - - # GET /resource/cancel - # Forces the session data which is usually expired after sign - # in to be expired now. This is useful if the user wants to - # cancel oauth signing in/up in the middle of the process, - # removing all OAuth session data. - def cancel - expire_session_data_after_sign_in! - redirect_to new_registration_path(resource_name) - end # GET /resource/status # Show view of profile @@ -85,44 +7,5 @@ def status @user.validates_application_completeness if @user end - protected - - def update_needs_confirmation?(resource, previous) - resource.respond_to?(:pending_reconfirmation?) && - resource.pending_reconfirmation? && - previous != resource.unconfirmed_email - end - # Build a devise resource passing in the session. Useful to move - # temporary session data to the newly created user. - def build_resource(hash=nil) - hash ||= resource_params || {} - self.resource = resource_class.new_with_session(hash, session) - end - - # The path used after sign up. You need to overwrite this method - # in your own RegistrationsController. - def after_sign_up_path_for(resource) - after_sign_in_path_for(resource) - end - - # The path used after sign up for inactive accounts. You need to overwrite - # this method in your own RegistrationsController. - def after_inactive_sign_up_path_for(resource) - respond_to?(:root_path) ? root_path : "/" - end - - # The default url to be used after updating a resource. You need to overwrite - # this method in your own RegistrationsController. - def after_update_path_for(resource) - #applicant_status_path - applicants_records_path - end - - # Authenticates the current scope and gets the current resource from the session. - def authenticate_scope! - send(:"authenticate_#{resource_name}!", :force => true) - self.resource = send(:"current_#{resource_name}") - end - end \ No newline at end of file diff --git a/app/controllers/users/sessions_controller.rb b/app/controllers/users/sessions_controller.rb index 2154d249..19c44814 100644 --- a/app/controllers/users/sessions_controller.rb +++ b/app/controllers/users/sessions_controller.rb @@ -1,17 +1,47 @@ -class Users::SessionsController < Devise::SessionsController +class Users::SessionsController < DeviseController + prepend_before_filter :require_no_authentication, :only => [ :new, :create ] + prepend_before_filter :allow_params_authentication!, :only => :create + prepend_before_filter { request.env["devise.skip_timeout"] = true } # GET /resource/sign_in def new - resource = build_resource + self.resource = build_resource(nil, :unsafe => true) clean_up_passwords(resource) - respond_with_navigational(resource, stub_options(resource)){ render_with_scope :new } + respond_with(resource, serialize_options(resource)) end - + # POST /resource/sign_in def create - resource = warden.authenticate!(:scope => resource_name, :recall => "#{controller_path}#new") + self.resource = warden.authenticate!(auth_options) set_flash_message(:notice, :signed_in) if is_navigational_format? sign_in(resource_name, resource) - redirect_to rails_admin_path + respond_with resource, :location => after_sign_in_path_for(resource) + end + + # DELETE /resource/sign_out + def destroy + redirect_path = after_sign_out_path_for(resource_name) + signed_out = (Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name)) + set_flash_message :notice, :signed_out if signed_out && is_navigational_format? + + # We actually need to hardcode this as Rails default responder doesn't + # support returning empty response on GET request + respond_to do |format| + format.all { head :no_content } + format.any(*navigational_formats) { redirect_to redirect_path } + end + end + + protected + + def serialize_options(resource) + methods = resource_class.authentication_keys.dup + methods = methods.keys if methods.is_a?(Hash) + methods << :password if resource.respond_to?(:password) + { :methods => methods, :only => [:password] } + end + + def auth_options + { :scope => resource_name, :recall => "#{controller_path}#new" } end end \ No newline at end of file diff --git a/app/models/applicant.rb b/app/models/applicant.rb index b7207470..8b9ee32a 100644 --- a/app/models/applicant.rb +++ b/app/models/applicant.rb @@ -3,25 +3,26 @@ class Applicant < ActiveRecord::Base # :token_authenticatable, and :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable, :lockable, :timeoutable, :confirmable - attr_accessible :email, :password, :password_confirmation, :remember_me, :first_name, :last_name, :phone, :dob, :citizenship, :disability, :gender, :ethnicity, :race, :cpu_skills, :gpa_comment, :lab_skills, :addresses_attributes, :awards_attributes, :records_attributes, :recommendations_attributes, :recommenders_attributes, :statement + attr_accessible :email, :password, :password_confirmation, :remember_me, :first_name, :last_name, :phone, :dob, :citizenship, :disability, :gender, :ethnicity, :race, :cpu_skills, :gpa_comment, :lab_skills, :addresses_attributes, :awards_attributes, :records_attributes, :recommendations_attributes, :recommenders_attributes, :statement, :recommenders has_many :addresses, :class_name => "Address", :dependent => :destroy has_many :records, :class_name => "AcademicRecord", :dependent => :destroy has_many :awards, :class_name => "Award", :dependent => :destroy has_many :recommendations - has_many :recommenders, :through => :recommendations - + has_many :recommenders, :through => :recommendations, :dependent => :restrict validates_associated :addresses, :awards, :records, :recommenders -# validates_presence_of :records, :if => :academic_records_controller? - -# validate :must_have_academic_record, :if => :academic_records_controller? accepts_nested_attributes_for :addresses, :allow_destroy => true, :reject_if => proc { |obj| obj.blank? } accepts_nested_attributes_for :awards, :allow_destroy => true, :reject_if => proc { |obj| obj.blank? } accepts_nested_attributes_for :records, :allow_destroy => true, :reject_if => proc { |obj| obj.blank? } accepts_nested_attributes_for :recommendations, :allow_destroy => true, :reject_if => proc { |obj| obj.blank? } accepts_nested_attributes_for :recommenders, :allow_destroy => true, :reject_if => proc { |obj| obj.blank? } + +# validates_presence_of :records, :if => :academic_records_controller? + +# validate :must_have_academic_record, :if => :academic_records_controller? + rails_admin do diff --git a/app/models/recommendation.rb b/app/models/recommendation.rb index 97871f5a..e03f0597 100644 --- a/app/models/recommendation.rb +++ b/app/models/recommendation.rb @@ -3,4 +3,14 @@ class Recommendation < ActiveRecord::Base belongs_to :applicant, :class_name => "Applicant" belongs_to :recommender, :class_name => "Recommender" + + after_destroy :remove_orphaned_recommenders + + private + + def remove_orphaned_recommenders + recommender = Recommender.find_by_email(self.recommender.email) + recommender.destroy if recommender.recommendations.empty? + end + end diff --git a/app/models/recommender.rb b/app/models/recommender.rb index 8683bb2e..67a0b9d5 100644 --- a/app/models/recommender.rb +++ b/app/models/recommender.rb @@ -1,5 +1,5 @@ class Recommender < ActiveRecord::Base - attr_accessible :department, :email, :first_name, :last_name, :organization, :phone, :title, :url + attr_accessible :department, :email, :first_name, :last_name, :organization, :phone, :title, :url, :id has_many :recommendations has_many :applicants, :through => :recommendations @@ -10,6 +10,45 @@ class Recommender < ActiveRecord::Base validates :organization, :presence => true validates :department, :presence => true validates :title, :presence => true + + validates_uniqueness_of :email, :message => "must be unique" + + def name + name = "" + name += "#{self.first_name} #{self.last_name}" + end + + private + + # parse params for existing recommenders and add to array. returns + # array of existing recommender object and hash with existing + # recommender attributes removed. + def self.remove_exisitng_recommenders_from_params(recommenders_attributes) + existing_recommenders = find_existing_recommenders(recommenders_attributes) + + recommenders_attributes.map do |r| + # if the existing recommender is included in the attributes hash + if existing_recommenders.map(&:email).include?(r[1]['email']) + # remove the attributes for that recommender unless they include the destroy flag + # debugger + recommenders_attributes.delete(r[0]) unless r[1]["_destroy"] == '1' + end + end + + [existing_recommenders, recommenders_attributes] + end + # parse params and lookup recommenders by email. if they exist, add + # them to an array. + def self.find_existing_recommenders(recommenders_attributes) + existing_recommenders = [] + + recommenders_attributes.each do |recommenders_attribute| + recommender = Recommender.find_by_email(recommenders_attribute[1]['email']) + existing_recommenders << recommender if recommender != nil + end + + existing_recommenders + end end diff --git a/app/views/recommendations/edit.html.erb b/app/views/applicants/recommendations/edit.html.erb similarity index 100% rename from app/views/recommendations/edit.html.erb rename to app/views/applicants/recommendations/edit.html.erb diff --git a/app/views/applicants/recommenders/edit.html.erb b/app/views/applicants/recommenders/edit.html.erb index 7a5eb9a3..9f298dfc 100644 --- a/app/views/applicants/recommenders/edit.html.erb +++ b/app/views/applicants/recommenders/edit.html.erb @@ -1,6 +1,6 @@ -<%= form_for(current_applicant, :url => applicants_recommenders_url, :html => { :method => :put }) do |f| %> +<%= form_for(@applicant, :url => applicants_recommenders_url, :html => { :method => :put }) do |f| %> - <%= errors_for current_applicant %> + <%= errors_for @applicant %>
@@ -47,7 +47,7 @@

-

<%= f.submit "Update Recommendation Info", :class => "btn btn-success" %>   Changed your mind? <%= link_to "Delete your application", registration_path(current_applicant), :confirm => "Are you sure?", :method => :delete, :class => "btn btn-mini btn-danger" %>

+

<%= f.submit "Update Recommendation Info", :class => "btn btn-success" %>   Changed your mind? <%= link_to "Delete your application", registration_path(@applicant), :confirm => "Are you sure?", :method => :delete, :class => "btn btn-mini btn-danger" %>

You can <%= link_to "logout", destroy_applicant_session_path, :method => :delete %> and continue you application at anytime, however, it will not be accepted until all the above data has been submitted.
diff --git a/config/environments/development.rb b/config/environments/development.rb index 0e906d40..479b99d5 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -35,5 +35,7 @@ # Expands the lines which load the assets config.assets.debug = true - config.action_mailer.default_url_options = { :host => 'localhost:3000' } + config.action_mailer.default_url_options = { :host => 'dev.reu.local:3000' } + + config.action_mailer.smtp_settings = { :enable_starttls_auto => false, :host => 'dev.reu.local' } end diff --git a/config/environments/production.rb b/config/environments/production.rb index 897caefb..89e62927 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -65,7 +65,7 @@ # with SQLite, MySQL, and PostgreSQL) # config.active_record.auto_explain_threshold_in_seconds = 0.5 - config.action_mailer.default_url_options = { :protocol => 'https', :host => 'www.be.ucsd.edu' } + config.action_mailer.default_url_options = { :protocol => 'https', :host => 'reumanager.com' } config.action_mailer.smtp_settings = { :enable_starttls_auto => false, :host => 'localhost' } end diff --git a/config/environments/test.rb b/config/environments/test.rb index 0ceb2344..a6bddc40 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -35,5 +35,7 @@ # Print deprecation notices to the stderr config.active_support.deprecation = :stderr - config.action_mailer.default_url_options = { :host => 'localhost:3000' } + config.action_mailer.default_url_options = { :host => 'test.reu.local:3000' } + + config.action_mailer.smtp_settings = { :enable_starttls_auto => false, :host => 'test.reu.local' } end diff --git a/config/initializers/rails_admin.rb b/config/initializers/rails_admin.rb index c2ffc919..fd529286 100644 --- a/config/initializers/rails_admin.rb +++ b/config/initializers/rails_admin.rb @@ -80,74 +80,6 @@ # All fields marked as 'hidden' won't be shown anywhere in the rails_admin unless you mark them as visible. (visible(true)) - config.model Applicant do - # Found associations: - # Found columns: - # configure :id, :integer - # configure :password, :password # Hidden - # configure :password_confirmation, :password # Hidden - # configure :reset_password_token, :string # Hidden - # configure :reset_password_sent_at, :datetime - # configure :remember_created_at, :datetime - # configure :sign_in_count, :integer - # configure :current_sign_in_at, :datetime - # configure :last_sign_in_at, :datetime - # configure :confirmation_token, :string - # configure :confirmed_at, :datetime - # configure :confirmation_sent_at, :datetime - # configure :failed_attempts, :integer - # configure :unlock_token, :string - # configure :locked_at, :datetime - # configure :authentication_token, :string - # configure :pid, :string - configure :email, :string - configure :current_sign_in_ip, :string - configure :last_sign_in_ip, :string - configure :first_name, :string - configure :last_name, :string - configure :college, :string - configure :current_major, :string - configure :applying_to, :string - configure :bild_1, :float - configure :chem_6a, :float - configure :chem_6b, :float - configure :mae_8, :float - configure :math_20a, :float - configure :math_20b, :float - configure :math_20c, :float - configure :phys_2a, :float - configure :phys_2b, :float - configure :average_gpa, :float - configure :created_at, :datetime - # configure :submitted_at, :datetime - # configure :updated_at, :datetime # # Sections: - # list do; end - # export do; end - # show do; end - edit do - configure :email, :string - configure :current_sign_in_ip, :string - configure :last_sign_in_ip, :string - configure :first_name, :string - configure :last_name, :string - configure :college, :string - configure :current_major, :string - configure :applying_to, :string - configure :bild_1, :float - configure :chem_6a, :float - configure :chem_6b, :float - configure :mae_8, :float - configure :math_20a, :float - configure :math_20b, :float - configure :math_20c, :float - configure :phys_2a, :float - configure :phys_2b, :float - configure :average_gpa, :float - configure :created_at, :datetime - end - # create do; end - # update do; end - end # config.model User do # # Found associations: # # Found columns: diff --git a/config/routes.rb b/config/routes.rb index 4314dbab..f0745e83 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,12 +1,6 @@ Reuman::Application.routes.draw do mount RailsAdmin::Engine => '/admin', :as => 'rails_admin' - devise_for :users - - devise_for :users, :controllers => { :sessions => "users/sessions" } do - match "users/sign_out" => "devise/sessions#destroy" - end - namespace :applicants do get "recommenders" => "recommenders#edit" put "recommenders" => "recommenders#update" @@ -17,67 +11,20 @@ delete "records" => "academic_records#destroy" end - match "closed" => "welcome#closed" + devise_for :applicants, :controllers => { :confirmations => "applicants/confirmations", :registrations => "applicants/registrations", :sessions => "applicants/sessions" } - # The priority is based upon order of creation: - # first created -> highest priority. - devise_for :applicants, :controllers => { :confirmations => "applicants/confirmations", :registrations => "applicants/registrations", :sessions => "applicants/sessions" } do + devise_scope :applicant do get "applicants/status" => "applicants/registrations#status", :as => :applicant_status get "applicants/submit" => "applicants/registrations#submit", :as => :submit_application end - - # Sample of regular route: - # match 'products/:id' => 'catalog#view' - # Keep in mind you can assign values other than :controller and :action - - # Sample of named route: - # match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase - # This route can be invoked with purchase_url(:id => product.id) - - # Sample resource route (maps HTTP verbs to controller actions automatically): - # resources :products - - # Sample resource route with options: - # resources :products do - # member do - # get 'short' - # post 'toggle' - # end - # - # collection do - # get 'sold' - # end - # end - # Sample resource route with sub-resources: - # resources :products do - # resources :comments, :sales - # resource :seller - # end - - # Sample resource route with more complex sub-resources - # resources :products do - # resources :comments - # resources :sales do - # get 'recent', :on => :collection - # end - # end - - # Sample resource route within a namespace: - # namespace :admin do - # # Directs /admin/products/* to Admin::ProductsController - # # (app/controllers/admin/products_controller.rb) - # resources :products - # end + devise_for :users, :controllers => { :sessions => "users/sessions" } + + devise_scope :user do + match "users/sign_out" => "devise/sessions#destroy" + end + match "closed" => "welcome#closed" - # You can have the root of your site routed with "root" - # just remember to delete public/index.html. root :to => "welcome#index" - - # See how all your routes lay out with "rake routes" - - # This is a legacy wild controller route that's not recommended for RESTful applications. - # Note: This route will make all actions in every controller accessible via GET requests. - # match ':controller(/:action(/:id(.:format)))' end diff --git a/spec/controllers/applicants/academic_records_controller_spec.rb b/spec/controllers/applicants/academic_records_controller_spec.rb index fb6c7db1..083fbbb0 100644 --- a/spec/controllers/applicants/academic_records_controller_spec.rb +++ b/spec/controllers/applicants/academic_records_controller_spec.rb @@ -1,5 +1,5 @@ require 'spec_helper' -describe AcademicRecordsController do +describe Applicants::AcademicRecordsController do end \ No newline at end of file diff --git a/spec/controllers/applicants/confirmations_controller_spec.rb b/spec/controllers/applicants/confirmations_controller_spec.rb index 25796b50..48dda569 100644 --- a/spec/controllers/applicants/confirmations_controller_spec.rb +++ b/spec/controllers/applicants/confirmations_controller_spec.rb @@ -1,5 +1,5 @@ require 'spec_helper' -describe ConfirmationsController +describe Applicants::ConfirmationsController do end \ No newline at end of file diff --git a/spec/controllers/applicants/recommendations_controller_spec.rb b/spec/controllers/applicants/recommendations_controller_spec.rb index fddd68e9..7c802fe4 100644 --- a/spec/controllers/applicants/recommendations_controller_spec.rb +++ b/spec/controllers/applicants/recommendations_controller_spec.rb @@ -1,5 +1,6 @@ require 'spec_helper' -describe RecommendaitonsController +describe Applicants::RecommendationsController do + end \ No newline at end of file diff --git a/spec/controllers/applicants/recommenders_controller_spec.rb b/spec/controllers/applicants/recommenders_controller_spec.rb new file mode 100644 index 00000000..9bdb7875 --- /dev/null +++ b/spec/controllers/applicants/recommenders_controller_spec.rb @@ -0,0 +1,293 @@ +require 'spec_helper' + +describe Applicants::RecommendersController do + + context "without authenticated applicant" do + + describe "#edit (GET /applicants/recommenders)" do + + it "redirects to the applicant login" do + get :edit + expect(response).to redirect_to new_applicant_session_url + end + + end + + describe "#update (PUT /applicants/recommenders/1)" do + + it "redirects to the applicant login" do + put :update, "applicant"=> { "recommenders_attributes" => { "0" => FactoryGirl.attributes_for(:applicant) } } + expect(response).to redirect_to new_applicant_session_url + end + + end + + end + + def confirm_and_login(applicant=nil) + @applicant = applicant || FactoryGirl.create(:applicant) + @applicant.update_attribute(:confirmed_at, Time.now) + sign_in @applicant + @applicant + end + + context "with authenticated applicant" do + before { confirm_and_login } + + context "without previous recommenders" do + describe "#edit (GET /applicants/recommenders)" do + + it "builds a new recommender object with blank attributes for the authenticated applicant" do + get :edit + expect(assigns(:applicant).recommenders.first.email).to be_nil + end + + it "renders the :edit template" do + get :edit + expect(response).to render_template :edit + end + + end + + describe "#update (PUT /applicants/recommenders/1)" do + + context 'with valid recommender attributes' do + before do + @recommender_attributes = FactoryGirl.attributes_for(:recommender) + put :update, "applicant"=> { "recommenders_attributes" => { "0" => @recommender_attributes } } + end + + it "redirects to the applicant recommender page" do + expect(response).to redirect_to applicants_recommenders_url + end + + it "creates a recommender object for the authenticated applicant using the provided attributes" do + expect(assigns(:applicant).recommenders.first.email).to eq(@recommender_attributes[:email]) + end + end + + context 'with INVALID recommender attributes' do + before do + @recommender_attributes = FactoryGirl.attributes_for(:recommender, email: nil) + put :update, "applicant"=> { "recommenders_attributes" => { "0" => @recommender_attributes } } + end + + it "re-renders the edit page" do + expect(response).to render_template(:edit) + end + + it "does not change the recommender's attributes" do + expect(assigns(:applicant).recommenders.first.email).to eq(@recommender_attributes[:email]) + end + + it "the recomender object is invalid" do + expect(assigns(:applicant).recommenders.first).to be_invalid + end + end + + end + + end + + context "with existing recommender" do + before { @recommender = @applicant.recommenders.create(FactoryGirl.attributes_for(:recommender)) } + + describe "#edit (GET /applicants/recommenders)" do + + it "does not build a new recommender object for the authenticated applicant and only loads the existing recommender" do + get :edit + expect(assigns(:applicant).recommenders.first).to eq(@recommender) + end + + it "renders the :edit template" do + get :edit + expect(response).to render_template :edit + end + + end + + describe "#update (PUT /applicants/recommenders/1)" do + + describe "deleting a recommender" do + before { @applicant_attributes} + + context 'with only one associated applicant/recommendation' do + it "deletes the recommender association (blank recommendation) when given the proper parameter" do + put :update, "applicant"=> { "recommenders_attributes" => { "0" => { + "first_name"=> @recommender.first_name, + "last_name"=> @recommender.last_name, + "email"=> @recommender.email, + "organization"=> @recommender.organization, + "title"=> @recommender.title, + "department"=> @recommender.department, + "id"=> @recommender.id, + "_destroy"=>"1" } } } + + assigns(:applicant).reload + + expect(assigns(:applicant).recommenders).to eq([]) + expect(Recommender.find_by_email(@recommender.email)).to be_nil + end + end + + context 'with more than one associated applicant/recommendation' do + it "deletes the recommender association (blank recommendation) when given the proper parameter" do + another_applicant = FactoryGirl.create(:applicant) + another_applicant.recommenders << @recommender + + put :update, "applicant"=> { "recommenders_attributes" => { "0" => { + "first_name"=> @recommender.first_name, + "last_name"=> @recommender.last_name, + "email"=> @recommender.email, + "organization"=> @recommender.organization, + "title"=> @recommender.title, + "department"=> @recommender.department, + "id"=> @recommender.id, + "_destroy"=>"1" } } } + + assigns(:applicant).reload + + expect(assigns(:applicant).recommenders).to eq([]) + expect(Recommender.find_by_email(@recommender.email)).to eq(@recommender) + end + end + + end + + + context 'with valid recommender attributes' do + before do + @recommender_attributes = FactoryGirl.attributes_for(:recommender) + put :update, "applicant"=> { "recommenders_attributes" => { "0" => @recommender_attributes } } + end + + it "redirects to the applicant recommender page" do + expect(response).to redirect_to applicants_recommenders_url + end + + it "updates the existing recommender using the provided attributes" do + expect(assigns(:applicant).recommenders.last.email).to eq(@recommender_attributes[:email]) + end + + end + + context 'with INVALID recommender attributes' do + before do + @recommender_attributes = FactoryGirl.attributes_for(:recommender, email: nil) + put :update, "applicant"=> { "recommenders_attributes" => { "0" => @recommender_attributes } } + end + + it "re-renders the edit page" do + expect(response).to render_template(:edit) + end + + it "does not change the recommender's attributes" do + expect(assigns(:applicant).recommenders.last.email).to eq(@recommender_attributes[:email]) + end + + end + + end + + end + + context "with existing recommender in application but not belonging to authenticated applicant" do + + describe "#update (PUT /applicants/recommenders/1)" do + before do + @some_other_applicant = FactoryGirl.create(:applicant) + @recommender = @some_other_applicant.recommenders.create(FactoryGirl.attributes_for(:recommender)) + end + + context 'with valid recommender attributes' do + before do + @recommender_attributes = @recommender.attributes + %w{ created_at updated_at }.map {|key| @recommender_attributes.delete(key) } + put :update, "applicant"=> { "recommenders_attributes" => { "0" => @recommender_attributes } } + end + + it "redirects to the applicant recommender page" do + expect(response).to redirect_to applicants_recommenders_url + end + + it "creates a recommender object for the authenticated applicant using the provided attributes" do + expect(assigns(:applicant).recommenders.first.email).to eq(@recommender.email) + end + end # context 'with valid recommender attributes' + + context 'with INVALID recommender attributes' do + before do + @recommender_attributes = @recommender.attributes + @recommender_attributes['title'] = nil + %w{ created_at updated_at }.map {|key| @recommender_attributes.delete(key) } + put :update, "applicant"=> { "recommenders_attributes" => { "0" => @recommender_attributes } } + end + + it "re-renders the edit page" do + expect(response).to redirect_to applicants_recommenders_url + end + + it "replaces the invalid attribute (and others) with those from the existing recommender" do + expect(assigns(:applicant).recommenders.first.title).to eq(@recommender.title) + end + + it "the recomender object is valid due to the reloaded attributes from the existing recommender" do + expect(assigns(:applicant).recommenders.first).to be_valid + end + end # context 'with INVALID recommender attributes' + + describe 'with multiple recommenders (one ex)' do + context 'with valid recommender attributes' do + before do + confirm_and_login(FactoryGirl.create(:applicant_with_recommender)) + @recommender0_attributes = @applicant.recommenders.first.attributes + @recommender1_attributes = @recommender.attributes + %w{ created_at updated_at }.map {|key| @recommender0_attributes.delete(key) } + %w{ created_at updated_at }.map {|key| @recommender1_attributes.delete(key) } + put :update, "applicant"=> { "recommenders_attributes" => { "0" => @recommender0_attributes, "1" => @recommender1_attributes } } + end + + it "redirects to the applicant recommender page" do + expect(response).to redirect_to applicants_recommenders_url + end + + it "creates a recommender object for the authenticated applicant using the provided attributes" do + expect(assigns(:applicant).recommenders.count).to eq(2) + expect(assigns(:applicant).recommenders.first.email).to eq(@recommender0_attributes['email']) + expect(assigns(:applicant).recommenders.last.email).to eq(@recommender1_attributes['email']) + end + end # context 'with valid recommender attributes' + + context 'with INVALID recommender attributes' do + before do + @applicant1 = confirm_and_login(FactoryGirl.create(:applicant_with_recommender)) + @recommender0_attributes = @applicant.recommenders.first.attributes + @recommender1_attributes = @recommender.attributes + %w{ created_at updated_at }.map {|key| @recommender0_attributes.delete(key) } + %w{ id title email created_at updated_at }.map {|key| @recommender1_attributes.delete(key) } + put :update, "applicant"=> { "recommenders_attributes" => { "0" => @recommender0_attributes, "1" => @recommender1_attributes } } + end + + it "re-renders the edit page" do + expect(response).to render_template :edit + end + + it "does not change the invalid recommender's attributes unless it is able to be looked up by email (email attribute provided)" do + expect(assigns(:applicant).recommenders.last.organization).to eq(@recommender1_attributes['organization']) + end + + it "retains the prexisting recommender" do + expect(assigns(:applicant).recommenders.first.organization).to eq(@recommender0_attributes['organization']) + end + + it "retains the applicant's recommender count" do + expect(assigns(:applicant).recommenders.count).to eq(1) + end + + end # context 'with INVALID recommender attributes' + + end # describe 'with multiple recommenders' + end # describe "#update (PUT /applicants/recommenders/1)" + end # context "with existing recommender in application but not belonging to authenticated applicant" + end # context "with authenticated applicant" +end # describe Applicants::RecommendersController diff --git a/spec/controllers/applicants/registrations_controller_spec.rb b/spec/controllers/applicants/registrations_controller_spec.rb index 6d29b12a..6865028b 100644 --- a/spec/controllers/applicants/registrations_controller_spec.rb +++ b/spec/controllers/applicants/registrations_controller_spec.rb @@ -1,5 +1,5 @@ require 'spec_helper' -describe RegistrationsController do +describe Applicants::RegistrationsController do end \ No newline at end of file diff --git a/spec/controllers/applicants/sessions_controller_spec.rb b/spec/controllers/applicants/sessions_controller_spec.rb index 48e84ec6..301e31ce 100644 --- a/spec/controllers/applicants/sessions_controller_spec.rb +++ b/spec/controllers/applicants/sessions_controller_spec.rb @@ -1,5 +1,5 @@ require 'spec_helper' -describe SessionsController do +describe Applicants::SessionsController do end \ No newline at end of file diff --git a/spec/controllers/users/sessions_controller_spec.rb b/spec/controllers/users/sessions_controller_spec.rb index 689e68b6..16ce0a6d 100644 --- a/spec/controllers/users/sessions_controller_spec.rb +++ b/spec/controllers/users/sessions_controller_spec.rb @@ -1,5 +1,5 @@ require 'spec_helper' -describe SessionsController do +describe Users::SessionsController do end \ No newline at end of file diff --git a/spec/factories/applicants.rb b/spec/factories/applicants.rb new file mode 100644 index 00000000..547f9d3a --- /dev/null +++ b/spec/factories/applicants.rb @@ -0,0 +1,35 @@ +# Read about factories at https://github.com/thoughtbot/factory_girl + +FactoryGirl.define do + + # confirmed applicant + factory :applicant do + first_name { Faker::Name.first_name } + last_name { Faker::Name.last_name } + email { Faker::Internet.email } + phone { Faker::PhoneNumber.phone_number } + password { Faker::Lorem.words(6).join('-') } + + factory :applicant_with_recommender do + first_name { Faker::Name.first_name } + last_name { Faker::Name.last_name } + email { Faker::Internet.email } + phone { Faker::PhoneNumber.phone_number } + password { Faker::Lorem.words(6).join('-') } + + after(:create) do |applicant| + applicant.recommenders.create FactoryGirl.attributes_for(:recommender) + end + end + + factory :unconfirmed_applicant do + first_name { Faker::Name.first_name } + last_name { Faker::Name.last_name } + email { Faker::Internet.email } + phone { Faker::PhoneNumber.phone_number } + password { Faker::Lorem.words(6).join('-') } + end + + end + +end diff --git a/spec/factories/recommendations.rb b/spec/factories/recommendations.rb new file mode 100644 index 00000000..1f295942 --- /dev/null +++ b/spec/factories/recommendations.rb @@ -0,0 +1,8 @@ +# Read about factories at https://github.com/thoughtbot/factory_girl + +FactoryGirl.define do + factory :recommendation do + title { Faker::Lorem.sentence } + body { Faker::Lorem.sentences(rand(5)+4).join(' ') } + end +end diff --git a/spec/factories/recommenders.rb b/spec/factories/recommenders.rb new file mode 100644 index 00000000..1b1189a3 --- /dev/null +++ b/spec/factories/recommenders.rb @@ -0,0 +1,12 @@ +# Read about factories at https://github.com/thoughtbot/factory_girl + +FactoryGirl.define do + factory :recommender do + first_name { Faker::Name.first_name } + last_name { Faker::Name.last_name } + email { Faker::Internet.email } + organization { Faker::Company.name } + department { %w{ Bioengineering Engineering Biology Nanotechnology Chemistry Medicine }[rand 6] } + title { %w{ Professor Assistant\ Professor Research\ Scientist Dean }[rand 4] } + end +end diff --git a/spec/helpers/academic_records_helper_spec.rb b/spec/helpers/academic_records_helper_spec.rb index d78ee2d8..00242bd4 100644 --- a/spec/helpers/academic_records_helper_spec.rb +++ b/spec/helpers/academic_records_helper_spec.rb @@ -1,5 +1,5 @@ require 'spec_helper' -describe 'AcademicRecordsHelper' do +describe 'Applicants::AcademicRecordsHelper' do end \ No newline at end of file diff --git a/spec/models/recommender_spec.rb b/spec/models/recommender_spec.rb index 1b2fa85e..da890f4f 100644 --- a/spec/models/recommender_spec.rb +++ b/spec/models/recommender_spec.rb @@ -1,5 +1,32 @@ require 'spec_helper' describe Recommender do + + # object instantiation + it { should be_an_instance_of(Recommender) } + + # association(s) + it { should respond_to :applicants } + it { should have_many :applicants } + it { should respond_to :recommendations } + it { should have_many :recommendations } + %w{ first_name last_name email organization department title}.each do |m| + it "is NOT valid without the required attribute '#{m}'" do + recommender = Recommender.create(FactoryGirl.attributes_for(:recommender, m.to_sym => nil)) + expect(recommender).to be_invalid + end + end + + it 'returns the combination of firstname / lastname when called with .name' do + recommender = FactoryGirl.create(:recommender) + expect(recommender.name).to eq("#{recommender.first_name} #{recommender.last_name}") + end + + it 'requires the email to be unique' do + recommender = FactoryGirl.create(:recommender) + + same_email_recommender = FactoryGirl.build(:recommender, email: recommender.email) + expect(same_email_recommender).to be_invalid + end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 00000000..64615b13 --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1,62 @@ +# This file is copied to spec/ when you run 'rails generate rspec:install' +ENV["RAILS_ENV"] ||= 'test' +require File.expand_path("../../config/environment", __FILE__) +require 'rspec/rails' +require 'rspec/autorun' +require 'shoulda/matchers/integrations/rspec' +require 'shoulda-matchers' +require 'capybara/rspec' +require 'capybara/rails' +require 'capybara/poltergeist' +require 'capybara/webkit' +#Capybara.javascript_driver = :poltergeist +Capybara.javascript_driver = :webkit + +# Requires supporting ruby files with custom matchers and macros, etc, +# in spec/support/ and its subdirectories. +Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f} + +RSpec.configure do |config| + config.mock_with :mocha + config.fixture_path = "#{::Rails.root}/spec/fixtures" + + # If you're not using ActiveRecord, or you'd prefer not to run each of your + # examples within a transaction, remove the following line or assign false + # instead of true. + config.use_transactional_fixtures = true + + # If true, the base class of anonymous controllers will be inferred + # automatically. This will be the default behavior in future versions of + # rspec-rails. + config.infer_base_class_for_anonymous_controllers = true + + # Run specs in random order to surface order dependencies. If you find an + # order dependency and want to debug it, you can fix the order by providing + # the seed, which is printed after each run. + # --seed 1234 + config.order = "random" + + config.before(:suite) do + DatabaseCleaner.strategy = :truncation + end + + config.before(:each) do + DatabaseCleaner.start + end + + config.after(:each) do + DatabaseCleaner.clean + end + + config.include Devise::TestHelpers, :type => :controller + + config.include Rails.application.routes.url_helpers + + # include custom mailer macros + config.include(Devise) + + # include custom mailer macros + config.include(Mailer) + config.before(:each) { reset_email } + +end diff --git a/spec/support/devise.rb b/spec/support/devise.rb new file mode 100644 index 00000000..491e7dfd --- /dev/null +++ b/spec/support/devise.rb @@ -0,0 +1,5 @@ +RSpec.configure do |config| + config.include Devise::TestHelpers, :type => :controller +end + + diff --git a/spec/support/mailer.rb b/spec/support/mailer.rb new file mode 100644 index 00000000..7505c757 --- /dev/null +++ b/spec/support/mailer.rb @@ -0,0 +1,11 @@ +module Mailer + Rails.application.routes.default_url_options[:host] = 'test.host' + + def last_email + ActionMailer::Base.deliveries.last + end + + def reset_email + ActionMailer::Base.deliveries = [] + end +end