rsvp 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +15 -0
  2. data/MIT-LICENSE +20 -0
  3. data/Rakefile +26 -0
  4. data/app/assets/javascripts/rsvp/application.js +15 -0
  5. data/app/assets/javascripts/rsvp/response_tabs.js +22 -0
  6. data/app/assets/stylesheets/rsvp/application.css +13 -0
  7. data/app/controllers/rsvp/application_controller.rb +17 -0
  8. data/app/controllers/rsvp/response_controller.rb +33 -0
  9. data/app/controllers/rsvp/session_controller.rb +26 -0
  10. data/app/helpers/rsvp/application_helper.rb +4 -0
  11. data/app/models/rsvp/family.rb +9 -0
  12. data/app/models/rsvp/invitation.rb +14 -0
  13. data/app/models/rsvp/member.rb +6 -0
  14. data/app/models/rsvp/person/adult_female.rb +4 -0
  15. data/app/models/rsvp/person/adult_male.rb +4 -0
  16. data/app/models/rsvp/person/young_female.rb +4 -0
  17. data/app/models/rsvp/person/young_male.rb +4 -0
  18. data/app/models/rsvp/person.rb +20 -0
  19. data/app/models/rsvp/response.rb +30 -0
  20. data/app/models/rsvp/salutation/husband_and_wife.rb +10 -0
  21. data/app/models/rsvp/salutation/husband_wife_and_family.rb +10 -0
  22. data/app/models/rsvp/salutation/lieutenant_colonel_and_wife.rb +10 -0
  23. data/app/models/rsvp/salutation/male_doctor_and_wife.rb +10 -0
  24. data/app/models/rsvp/salutation/single_female.rb +10 -0
  25. data/app/models/rsvp/salutation/single_female_and_guest.rb +10 -0
  26. data/app/models/rsvp/salutation/single_male.rb +10 -0
  27. data/app/models/rsvp/salutation/single_male_and_guest.rb +10 -0
  28. data/app/models/rsvp/salutation/widow.rb +10 -0
  29. data/app/models/rsvp/salutation/widow_and_family.rb +10 -0
  30. data/app/models/rsvp/salutation/widower.rb +10 -0
  31. data/app/models/rsvp/salutation/widower_and_family.rb +10 -0
  32. data/app/models/rsvp/salutation.rb +25 -0
  33. data/app/views/layouts/rsvp/application.html.erb +21 -0
  34. data/app/views/rsvp/response/_show.html.erb +10 -0
  35. data/app/views/rsvp/response/confirmation.html.erb +7 -0
  36. data/app/views/rsvp/response/index.html.erb +47 -0
  37. data/app/views/rsvp/response/show.html.erb +4 -0
  38. data/app/views/rsvp/session/index.html.erb +5 -0
  39. data/config/cucumber.yml +8 -0
  40. data/config/routes.rb +12 -0
  41. data/db/migrate/20140106042028_create_rsvp_people.rb +12 -0
  42. data/db/migrate/20140106042630_create_rsvp_families.rb +13 -0
  43. data/db/migrate/20140106042748_create_rsvp_members.rb +10 -0
  44. data/db/migrate/20140106042845_create_rsvp_invitations.rb +13 -0
  45. data/db/migrate/20140106043014_create_rsvp_responses.rb +12 -0
  46. data/db/migrate/20140106043143_create_rsvp_salutations.rb +10 -0
  47. data/lib/generators/rsvp/USAGE +12 -0
  48. data/lib/generators/rsvp/views_generator.rb +13 -0
  49. data/lib/rsvp/engine.rb +20 -0
  50. data/lib/rsvp/version.rb +3 -0
  51. data/lib/rsvp.rb +4 -0
  52. data/lib/tasks/cucumber.rake +63 -0
  53. data/lib/tasks/rsvp_tasks.rake +4 -0
  54. metadata +231 -0
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ZDYyNWQzMTk3MzVlYTM5MWQ5YWQwMWI0YWU2ZTRmODdmN2NlMDdhNA==
5
+ data.tar.gz: !binary |-
6
+ ZjBjYjFjYjBiMTM3MmQ3NWZlMTczNTk3N2U2YmJkMDdhZmU3ZTQ0NQ==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ YzIxMDQzZDQyZjZlMmVhZjRiNmFiMmUwNzQ3ZDFhYzg1M2EzMTc1NmJmNGVl
10
+ ZDFhM2UwNTZlNTQ3OWQ5YWYxZTg2ODJhNTM0ODI4ZmE5OTE0ZmUxOTM1OGEw
11
+ Y2NlMmEzYzEzNTFiMDIzMjZmMzAwNGY3YzUyYWUzOTNlMDAwMmQ=
12
+ data.tar.gz: !binary |-
13
+ YTgyOTgyZWYyMTRhNDlmOTQyNDgyZWMzOTVmOTIxODFhNzA0ZDAyOTQ1NDJk
14
+ OTY2N2I1NGNiZDlmZTJjZDI0NzNhYzQ2ZTFkY2QxODRhOWU2MGYxZWNiM2Jm
15
+ MDViM2VhNjI0NzZiMjdkYzg1MDUzN2YwNTdjNDFhYjJhMTdlN2I=
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2014 Ryan Ricard
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,26 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'Rsvp'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.rdoc')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
18
+ load 'rails/tasks/engine.rake'
19
+
20
+ Bundler::GemHelper.install_tasks
21
+
22
+ # Run rspec as default task
23
+ # more info here: https://www.relishapp.com/rspec/rspec-core/docs/command-line/rake-task
24
+ require 'rspec/core/rake_task'
25
+ RSpec::Core::RakeTask.new(:spec)
26
+ task :default => :spec
@@ -0,0 +1,15 @@
1
+ // This is a manifest file that'll be compiled into application.js, which will include all the files
2
+ // listed below.
3
+ //
4
+ // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
+ // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
6
+ //
7
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
+ // compiled file.
9
+ //
10
+ // Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
11
+ // about supported directives.
12
+ //
13
+ //= require jquery
14
+ //= require jquery_ujs
15
+ // require_tree .
@@ -0,0 +1,22 @@
1
+ $(function(){
2
+ (function(){
3
+ var _tabs, _containers;
4
+ var show = function(tab){
5
+ _tabs.removeClass("active");
6
+ _containers.hide();
7
+ tab.addClass("active");
8
+ $(tab.data("container")).show();
9
+ };
10
+ return {
11
+ init: function(tabs, containers){
12
+ _tabs = tabs;
13
+ _containers = containers.hide();
14
+ tabs.click(function(e){
15
+ var tab = $(e.target);
16
+ show(tab);
17
+ });
18
+ $(".tab.active").click();
19
+ }
20
+ };
21
+ })().init($(".tab"), $(".container"));
22
+ });
@@ -0,0 +1,13 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the top of the
9
+ * compiled file, but it's generally better to create a new file per style scope.
10
+ *
11
+ *= require_self
12
+ *= require_tree .
13
+ */
@@ -0,0 +1,17 @@
1
+ module Rsvp
2
+ class ApplicationController < ActionController::Base
3
+ protect_from_forgery
4
+
5
+ before_filter :require_session
6
+
7
+ private
8
+
9
+ def require_session
10
+ unless session[:invitation_id]
11
+ flash[:alert] = "You must begin a RSVP session to access that page."
12
+ redirect_to root_path
13
+ end
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,33 @@
1
+ module Rsvp
2
+ class ResponseController < ApplicationController
3
+ before_filter :prepare_instance_vars, :only => [:index, :show, :confirmation]
4
+
5
+ # GET /response
6
+ def index; end
7
+
8
+ # POST /response
9
+ def create
10
+ @invitation = Invitation.find(session[:invitation_id])
11
+ @response = @invitation.responses.build(params[:response])
12
+ if @response.save
13
+ redirect_to confirmation_response_index_path
14
+ else
15
+ render :action => :index
16
+ end
17
+ end
18
+
19
+ # GET /response/overview
20
+ def show; end
21
+
22
+ # GET /response/confirmation
23
+ def confirmation; end
24
+
25
+ private
26
+
27
+ def prepare_instance_vars
28
+ @invitation = Invitation.find(session[:invitation_id])
29
+ @invitation.responses.build unless @invitation.responses.any?
30
+ @response = @invitation.responses.last
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,26 @@
1
+ module Rsvp
2
+ class SessionController < ApplicationController
3
+ skip_before_filter :require_session, :only => [:index, :create]
4
+
5
+ # GET /session
6
+ def index; end
7
+
8
+ # POST /session
9
+ def create
10
+ invitation = Invitation.find_by_rsvp_code(params[:rsvp_code])
11
+ if invitation
12
+ session[:invitation_id] = invitation.id
13
+ redirect_to (invitation.responses.any? ? show_response_index_path : response_index_path)
14
+ else
15
+ flash.alert = "Oops!! The code you entered is not valid. Please try again."
16
+ redirect_to root_path
17
+ end
18
+ end
19
+
20
+ # DELETE /session
21
+ def destroy
22
+ session[:invitation_id] = nil
23
+ redirect_to root_path, notice: "Thank you for your response!"
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,4 @@
1
+ module Rsvp
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -0,0 +1,9 @@
1
+ module Rsvp
2
+ class Family < ActiveRecord::Base
3
+ attr_accessible :city, :postal_code, :state, :street_1, :street_2
4
+ has_many :invitations
5
+ has_many :members
6
+ has_many :people, :through => :members
7
+ has_one :salutation
8
+ end
9
+ end
@@ -0,0 +1,14 @@
1
+ module Rsvp
2
+ class Invitation < ActiveRecord::Base
3
+ attr_accessible :rsvp_code, :total_invited
4
+ belongs_to :family
5
+ has_many :responses
6
+
7
+ validates :rsvp_code, :presence => true, :uniqueness => true, :length => { is: 7 }
8
+ validates :total_invited, :inclusion => 1..10
9
+
10
+ def total_invite_options
11
+ (1..total_invited).to_a
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,6 @@
1
+ module Rsvp
2
+ class Member < ActiveRecord::Base
3
+ belongs_to :family
4
+ belongs_to :person
5
+ end
6
+ end
@@ -0,0 +1,4 @@
1
+ module Rsvp
2
+ class Person::AdultFemale < Person
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Rsvp
2
+ class Person::AdultMale < Person
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Rsvp
2
+ class Person::YoungFemale < Person
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Rsvp
2
+ class Person::YoungMale < Person
3
+ end
4
+ end
@@ -0,0 +1,20 @@
1
+ module Rsvp
2
+ class Person < ActiveRecord::Base
3
+ self.inheritance_column = :gender
4
+ attr_accessible :first_name, :gender, :last_name, :suffix
5
+ has_many :memberships, :class_name => "Member"
6
+ has_many :families, :through => :memberships
7
+
8
+ validates :first_name, :presence => true
9
+ validates :last_name, :presence => true
10
+
11
+
12
+ def self.adult_males
13
+ where("gender = ?", Person::AdultMale.to_s)
14
+ end
15
+
16
+ def self.adult_females
17
+ where("gender = ?", Person::AdultFemale.to_s)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,30 @@
1
+ module Rsvp
2
+ class Response < ActiveRecord::Base
3
+ attr_accessible :comment, :email, :total_attending
4
+ belongs_to :invitation
5
+
6
+ validates :total_attending, :presence => true
7
+ validate :validate_total_attending
8
+ validate :validate_email_if_entered
9
+
10
+ def validate_total_attending
11
+ if invitation.total_invited < total_attending.to_i
12
+ errors.add(:total_attending, "cannot be greater than total invited")
13
+ end
14
+ end
15
+
16
+ def validate_email_if_entered
17
+ if email.present? && !email.match(/^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i)
18
+ errors.add(:email, "is invalid")
19
+ end
20
+ end
21
+
22
+ def is_yes?
23
+ total_attending.to_i > 0
24
+ end
25
+
26
+ def is_no?
27
+ total_attending.to_i == 0 && !total_attending.nil?
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,10 @@
1
+ module Rsvp
2
+ class Salutation::HusbandAndWife < Salutation
3
+ def male
4
+ family.people.adult_males.first
5
+ end
6
+ def template
7
+ "Mr. and Mrs. [[male__first_name]] [[male__last_name]]"
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module Rsvp
2
+ class Salutation::HusbandWifeAndFamily < Salutation
3
+ def male
4
+ family.people.adult_males.first
5
+ end
6
+ def template
7
+ "Mr. and Mrs. [[male__first_name]] [[male__last_name]] and family"
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module Rsvp
2
+ class Salutation::LieutenantColonelAndWife < Salutation
3
+ def male
4
+ family.people.adult_males.first
5
+ end
6
+ def template
7
+ "Lt. Col. and Mrs. [[male__first_name]] [[male__last_name]]"
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module Rsvp
2
+ class Salutation::MaleDoctorAndWife < Salutation
3
+ def male
4
+ family.people.adult_males.first
5
+ end
6
+ def template
7
+ "Dr. and Mrs. [[male__first_name]] [[male__last_name]]"
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module Rsvp
2
+ class Salutation::SingleFemale < Salutation
3
+ def female
4
+ family.people.adult_females.first
5
+ end
6
+ def template
7
+ "Ms. [[female__first_name]] [[female__last_name]]"
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module Rsvp
2
+ class Salutation::SingleFemaleAndGuest < Salutation
3
+ def female
4
+ family.people.adult_females.first
5
+ end
6
+ def template
7
+ "Ms. [[female__first_name]] [[female__last_name]] and guest"
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module Rsvp
2
+ class Salutation::SingleMale < Salutation
3
+ def male
4
+ family.people.adult_males.first
5
+ end
6
+ def template
7
+ "Mr. [[male__first_name]] [[male__last_name]]"
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module Rsvp
2
+ class Salutation::SingleMaleAndGuest < Salutation
3
+ def male
4
+ family.people.adult_males.first
5
+ end
6
+ def template
7
+ "Mr. [[male__first_name]] [[male__last_name]] and guest"
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module Rsvp
2
+ class Salutation::Widow < Salutation
3
+ def female
4
+ family.people.adult_females.first
5
+ end
6
+ def template
7
+ "Mrs. [[female__first_name]] [[female__last_name]]"
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module Rsvp
2
+ class Salutation::WidowAndFamily < Salutation
3
+ def female
4
+ family.people.adult_females.first
5
+ end
6
+ def template
7
+ "Mrs. [[female__first_name]] [[female__last_name]] and family"
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module Rsvp
2
+ class Salutation::Widower < Salutation
3
+ def male
4
+ family.people.adult_males.first
5
+ end
6
+ def template
7
+ "Mr. [[male__first_name]] [[male__last_name]]"
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module Rsvp
2
+ class Salutation::WidowerAndFamily < Salutation
3
+ def male
4
+ family.people.adult_males.first
5
+ end
6
+ def template
7
+ "Mr. [[male__first_name]] [[male__last_name]] and family"
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,25 @@
1
+ module Rsvp
2
+ class Salutation < ActiveRecord::Base
3
+ attr_accessible :type
4
+ belongs_to :family
5
+
6
+ def template
7
+ raise "Template not implemented in subclass."
8
+ end
9
+
10
+ def to_s
11
+ merge
12
+ end
13
+
14
+ private
15
+
16
+ def merge
17
+ salutation = template
18
+ template.scan(/\[\[\w*\]\]/).each do |expression|
19
+ salutation_method, person_method = expression.tr("][", "").split(/__/)
20
+ salutation.gsub!(expression, send(salutation_method).send(person_method))
21
+ end
22
+ salutation
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,21 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>RSVP</title>
5
+ <%= stylesheet_link_tag "rsvp/application", media: "all" %>
6
+ <%= javascript_include_tag "rsvp/application" %>
7
+ <%= csrf_meta_tags %>
8
+ </head>
9
+ <body>
10
+ <% if notice %>
11
+ <p><%= notice %></p>
12
+ <% end %>
13
+
14
+ <% if alert %>
15
+ <p><%= alert %></p>
16
+ <% end %>
17
+
18
+ <%= yield %>
19
+
20
+ </body>
21
+ </html>
@@ -0,0 +1,10 @@
1
+ <% if @response.is_yes? %>
2
+ <%= "Total attending: " + @response.total_attending.to_s %>
3
+ <%= "Email: " + @response.email.html_safe %>
4
+ <%= "Comment: " + @response.comment.html_safe %>
5
+ <% else %>
6
+ <p>No, I will not be attending.</p>
7
+ <% end %>
8
+
9
+ <%= link_to "Change my response", response_index_path %>
10
+ <%= link_to "I'm done!", sign_out_path %>
@@ -0,0 +1,7 @@
1
+ <% if @response.is_yes? %>
2
+ Awesome!! We look forward to seeing you there!
3
+ <% else %>
4
+ Aw shucks. You will be missed.
5
+ <% end %>
6
+
7
+ <%= render "show" %>
@@ -0,0 +1,47 @@
1
+ <% if @response.errors.any? %>
2
+ <% @response.errors.full_messages.each do |msg| %>
3
+ <ul>
4
+ <li><%= msg %></li>
5
+ </ul>
6
+ <% end %>
7
+ <% end %>
8
+
9
+ <p>Hi, <%= @invitation.family.salutation %>! Thank you for choosing to RSVP to our special day.</p>
10
+ <p>Will you attend?</p>
11
+
12
+ <ul>
13
+ <li><a href="#" data-container="#yes-container" class="tab <%= 'active' if @response.is_yes? || @response.errors.any? %>">Yes</a></li>
14
+ <li><a href="#" data-container="#no-container" class="tab <%= 'active' if @response.is_no? %>">No</a></li>
15
+ </ul>
16
+
17
+ <div id="yes-container" class="container">
18
+ <%= form_for @invitation, :url => response_index_path, :method => :post do |f| %>
19
+ <%= fields_for @response do |r| %>
20
+ <% if @invitation.total_invited > 1 %>
21
+ <%= r.label :total_attending %>
22
+ <%= r.select :total_attending, @invitation.total_invite_options, :include_blank => true %>
23
+ <% else %>
24
+ <%= r.hidden_field :total_attending, value: @invitation.total_invited %>
25
+ <% end %>
26
+ <%= r.label :email %>
27
+ <%= r.text_field :email %>
28
+ <%= r.label :comment %>
29
+ <%= r.text_area :comment %>
30
+ <% end %>
31
+ <%= f.button "Cancel", :type => :button %>
32
+ <%= f.submit "Submit RSVP" %>
33
+ <% end %>
34
+ </div>
35
+
36
+ <div id="no-container" class="container">
37
+ <%= form_for @invitation, :url => response_index_path, :method => :post do |f| %>
38
+ <%= fields_for @response do |r| %>
39
+ <%= r.hidden_field :total_attending, value: 0 %>
40
+ <% end %>
41
+ <p>No, I will not be attending.</p>
42
+ <%= f.button "Cancel", :type => :button %>
43
+ <%= f.submit "Submit RSVP" %>
44
+ <% end %>
45
+ </div>
46
+
47
+ <%= javascript_include_tag "rsvp/response_tabs.js" %>
@@ -0,0 +1,4 @@
1
+ <!-- TODO: Tell Amanda I changed the text below -->
2
+ <p>Hi, <%= @invitation.family.salutation %>! Welcome back.</p>
3
+
4
+ <%= render "show" %>
@@ -0,0 +1,5 @@
1
+ <%= form_tag sign_in_path, :method => :post do |f| %>
2
+ <%= label_tag :rsvp_code, "Enter your RSVP Code" %>
3
+ <%= text_field_tag :rsvp_code %>
4
+ <%= submit_tag "Begin RSVP" %>
5
+ <% end %>
@@ -0,0 +1,8 @@
1
+ <%
2
+ rerun = File.file?('rerun.txt') ? IO.read('rerun.txt') : ""
3
+ rerun_opts = rerun.to_s.strip.empty? ? "--format #{ENV['CUCUMBER_FORMAT'] || 'progress'} features" : "--format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} #{rerun}"
4
+ std_opts = "--format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} --strict --tags ~@wip"
5
+ %>
6
+ default: <%= std_opts %> features
7
+ wip: --tags @wip:3 --wip features
8
+ rerun: <%= rerun_opts %> --format rerun --out rerun.txt --strict --tags ~@wip
data/config/routes.rb ADDED
@@ -0,0 +1,12 @@
1
+ Rsvp::Engine.routes.draw do
2
+ root :to => "session#index"
3
+ get :sign_in, :controller => :session, :action => :index
4
+ post :sign_in, :controller => :session, :action => :create
5
+ get :sign_out, :controller => :session, :action => :destroy
6
+ resources :response, :only => [:index, :create] do
7
+ collection do
8
+ get :overview, :action => :show, :as => :show
9
+ get :confirmation, :action => :confirmation
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ class CreateRsvpPeople < ActiveRecord::Migration
2
+ def change
3
+ create_table :rsvp_people do |t|
4
+ t.string :gender, :limit => 50
5
+ t.string :first_name, :limit => 50
6
+ t.string :last_name, :limit => 50
7
+ t.string :suffix, :limit => 15
8
+
9
+ t.timestamps
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,13 @@
1
+ class CreateRsvpFamilies < ActiveRecord::Migration
2
+ def change
3
+ create_table :rsvp_families do |t|
4
+ t.string :street_1, :limit => 75
5
+ t.string :street_2, :limit => 75
6
+ t.string :city, :limit => 50
7
+ t.string :state, :limit => 25
8
+ t.string :postal_code, :limit => 15
9
+
10
+ t.timestamps
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,10 @@
1
+ class CreateRsvpMembers < ActiveRecord::Migration
2
+ def change
3
+ create_table :rsvp_members do |t|
4
+ t.integer :family_id
5
+ t.integer :person_id
6
+
7
+ t.timestamps
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,13 @@
1
+ class CreateRsvpInvitations < ActiveRecord::Migration
2
+ def change
3
+ create_table :rsvp_invitations do |t|
4
+ t.integer :family_id
5
+ t.string :rsvp_code, :limit => 20
6
+ t.integer :total_invited
7
+
8
+ t.timestamps
9
+ end
10
+
11
+ add_index :rsvp_invitations, :rsvp_code, :unique => true
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ class CreateRsvpResponses < ActiveRecord::Migration
2
+ def change
3
+ create_table :rsvp_responses do |t|
4
+ t.integer :invitation_id
5
+ t.string :email, :limit => 50
6
+ t.integer :total_attending
7
+ t.text :comment
8
+
9
+ t.timestamps
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,10 @@
1
+ class CreateRsvpSalutations < ActiveRecord::Migration
2
+ def change
3
+ create_table :rsvp_salutations do |t|
4
+ t.integer :family_id
5
+ t.string :type, :limit => 50
6
+
7
+ t.timestamps
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,12 @@
1
+ Description:
2
+ Copies all Rsvp views to your application.
3
+
4
+ Example:
5
+ rails generate rsvp:views
6
+
7
+ This will create:
8
+ app/views/rsvp/response/edit.html.erb
9
+ app/views/rsvp/response/index.html.erb
10
+ app/views/rsvp/response/no_confirmation.html.erb
11
+ app/views/rsvp/response/yes_confirmation.html.erb
12
+ app/views/rsvp/shared/_error_messages.html.erb
@@ -0,0 +1,13 @@
1
+ require 'rails/generators/base'
2
+
3
+ module Rsvp
4
+ class ViewsGenerator < ::Rails::Generators::Base
5
+ source_root File.expand_path("../../../", __FILE__)
6
+
7
+ desc "Copies all Rsvp views to your application."
8
+ def copy_views
9
+ directory "#{Rsvp::Engine.root}/app/views/layouts/rsvp", "#{Rails.root}/app/views/layouts/rsvp/."
10
+ directory "#{Rsvp::Engine.root}/app/views/rsvp", "#{Rails.root}/app/views/rsvp/."
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,20 @@
1
+ module Rsvp
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace Rsvp
4
+
5
+ config.generators do |g|
6
+ g.test_framework :rspec
7
+ end
8
+
9
+ # Add engine db/migrate to paths so migrations run with wrapping application
10
+ # Inspired by: http://pivotallabs.com/leave-your-migrations-in-your-rails-engines/
11
+ initializer :append_migrations do |app|
12
+ # unless app.root.to_s.match root.to_s
13
+ config.paths["db/migrate"].expanded.each do |expanded_path|
14
+ app.config.paths["db/migrate"] << expanded_path
15
+ end
16
+ # end
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,3 @@
1
+ module Rsvp
2
+ VERSION = "0.0.1"
3
+ end
data/lib/rsvp.rb ADDED
@@ -0,0 +1,4 @@
1
+ require "rsvp/engine"
2
+
3
+ module Rsvp
4
+ end
@@ -0,0 +1,63 @@
1
+ # IMPORTANT: This file is generated by cucumber-rails - edit at your own peril.
2
+ # It is recommended to regenerate this file in the future when you upgrade to a
3
+ # newer version of cucumber-rails. Consider adding your own code to a new file
4
+ # instead of editing this one. Cucumber will automatically load all features/**/*.rb
5
+ # files.
6
+ unless ARGV.any? {|a| a =~ /^gems/} # Don't load anything when running the gems:* tasks
7
+
8
+ vendored_cucumber_bin = Dir["#{Rails.root}/../../vendor/bundle/gems/cucumber*/bin/cucumber"].first
9
+ $LOAD_PATH.unshift(File.dirname(vendored_cucumber_bin) + '/../lib') unless vendored_cucumber_bin.nil?
10
+
11
+ begin
12
+ require 'cucumber/rake/task'
13
+
14
+ namespace :cucumber do
15
+ Cucumber::Rake::Task.new({:ok => 'test:prepare'}, 'Run features that should pass') do |t|
16
+ t.binary = vendored_cucumber_bin # If nil, the gem's binary is used.
17
+ t.fork = true # You may get faster startup if you set this to false
18
+ t.profile = 'default'
19
+ end
20
+
21
+ Cucumber::Rake::Task.new({:wip => 'test:prepare'}, 'Run features that are being worked on') do |t|
22
+ t.binary = vendored_cucumber_bin
23
+ t.fork = true # You may get faster startup if you set this to false
24
+ t.profile = 'wip'
25
+ end
26
+
27
+ Cucumber::Rake::Task.new({:rerun => 'test:prepare'}, 'Record failing features and run only them if any exist') do |t|
28
+ t.binary = vendored_cucumber_bin
29
+ t.fork = true # You may get faster startup if you set this to false
30
+ t.profile = 'rerun'
31
+ end
32
+
33
+ desc 'Run all features'
34
+ task :all => [:ok, :wip]
35
+
36
+ task :statsetup do
37
+ require 'rails/code_statistics'
38
+ ::STATS_DIRECTORIES << %w(Cucumber\ features features) if File.exist?('features')
39
+ ::CodeStatistics::TEST_TYPES << "Cucumber features" if File.exist?('features')
40
+ end
41
+ end
42
+ desc 'Alias for cucumber:ok'
43
+ task :cucumber => 'cucumber:ok'
44
+
45
+ task :default => :cucumber
46
+
47
+ task :features => :cucumber do
48
+ STDERR.puts "*** The 'features' task is deprecated. See rake -T cucumber ***"
49
+ end
50
+
51
+ # In case we don't have the generic Rails test:prepare hook, append a no-op task that we can depend upon.
52
+ task 'test:prepare' do
53
+ end
54
+
55
+ task :stats => 'cucumber:statsetup'
56
+ rescue LoadError
57
+ desc 'cucumber rake task not available (cucumber not installed)'
58
+ task :cucumber do
59
+ abort 'Cucumber rake task is not available. Be sure to install cucumber as a gem or plugin'
60
+ end
61
+ end
62
+
63
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :rsvp do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,231 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rsvp
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Ryan Ricard
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-02-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '4.0'
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: 4.0.2
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '4.0'
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: 4.0.2
33
+ - !ruby/object:Gem::Dependency
34
+ name: sqlite3
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ~>
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ~>
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ - !ruby/object:Gem::Dependency
48
+ name: debugger
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: '1.6'
54
+ - - ! '>='
55
+ - !ruby/object:Gem::Version
56
+ version: 1.6.5
57
+ type: :development
58
+ prerelease: false
59
+ version_requirements: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ~>
62
+ - !ruby/object:Gem::Version
63
+ version: '1.6'
64
+ - - ! '>='
65
+ - !ruby/object:Gem::Version
66
+ version: 1.6.5
67
+ - !ruby/object:Gem::Dependency
68
+ name: rspec-rails
69
+ requirement: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ~>
72
+ - !ruby/object:Gem::Version
73
+ version: '2.14'
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: 2.14.1
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ~>
82
+ - !ruby/object:Gem::Version
83
+ version: '2.14'
84
+ - - ! '>='
85
+ - !ruby/object:Gem::Version
86
+ version: 2.14.1
87
+ - !ruby/object:Gem::Dependency
88
+ name: capybara
89
+ requirement: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ version: '2.2'
94
+ - - ! '>='
95
+ - !ruby/object:Gem::Version
96
+ version: 2.2.1
97
+ type: :development
98
+ prerelease: false
99
+ version_requirements: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ~>
102
+ - !ruby/object:Gem::Version
103
+ version: '2.2'
104
+ - - ! '>='
105
+ - !ruby/object:Gem::Version
106
+ version: 2.2.1
107
+ - !ruby/object:Gem::Dependency
108
+ name: selenium-webdriver
109
+ requirement: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - ~>
112
+ - !ruby/object:Gem::Version
113
+ version: '2.39'
114
+ - - ! '>='
115
+ - !ruby/object:Gem::Version
116
+ version: 2.39.0
117
+ type: :development
118
+ prerelease: false
119
+ version_requirements: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ~>
122
+ - !ruby/object:Gem::Version
123
+ version: '2.39'
124
+ - - ! '>='
125
+ - !ruby/object:Gem::Version
126
+ version: 2.39.0
127
+ - !ruby/object:Gem::Dependency
128
+ name: database_cleaner
129
+ requirement: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - ~>
132
+ - !ruby/object:Gem::Version
133
+ version: '1.2'
134
+ - - ! '>='
135
+ - !ruby/object:Gem::Version
136
+ version: 1.2.0
137
+ type: :development
138
+ prerelease: false
139
+ version_requirements: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - ~>
142
+ - !ruby/object:Gem::Version
143
+ version: '1.2'
144
+ - - ! '>='
145
+ - !ruby/object:Gem::Version
146
+ version: 1.2.0
147
+ description: Provides wrapping application necessary views and data structures to
148
+ capture online RSVP responses.
149
+ email:
150
+ - hi@ryanricard.com
151
+ executables: []
152
+ extensions: []
153
+ extra_rdoc_files: []
154
+ files:
155
+ - MIT-LICENSE
156
+ - Rakefile
157
+ - app/assets/javascripts/rsvp/application.js
158
+ - app/assets/javascripts/rsvp/response_tabs.js
159
+ - app/assets/stylesheets/rsvp/application.css
160
+ - app/controllers/rsvp/application_controller.rb
161
+ - app/controllers/rsvp/response_controller.rb
162
+ - app/controllers/rsvp/session_controller.rb
163
+ - app/helpers/rsvp/application_helper.rb
164
+ - app/models/rsvp/family.rb
165
+ - app/models/rsvp/invitation.rb
166
+ - app/models/rsvp/member.rb
167
+ - app/models/rsvp/person.rb
168
+ - app/models/rsvp/person/adult_female.rb
169
+ - app/models/rsvp/person/adult_male.rb
170
+ - app/models/rsvp/person/young_female.rb
171
+ - app/models/rsvp/person/young_male.rb
172
+ - app/models/rsvp/response.rb
173
+ - app/models/rsvp/salutation.rb
174
+ - app/models/rsvp/salutation/husband_and_wife.rb
175
+ - app/models/rsvp/salutation/husband_wife_and_family.rb
176
+ - app/models/rsvp/salutation/lieutenant_colonel_and_wife.rb
177
+ - app/models/rsvp/salutation/male_doctor_and_wife.rb
178
+ - app/models/rsvp/salutation/single_female.rb
179
+ - app/models/rsvp/salutation/single_female_and_guest.rb
180
+ - app/models/rsvp/salutation/single_male.rb
181
+ - app/models/rsvp/salutation/single_male_and_guest.rb
182
+ - app/models/rsvp/salutation/widow.rb
183
+ - app/models/rsvp/salutation/widow_and_family.rb
184
+ - app/models/rsvp/salutation/widower.rb
185
+ - app/models/rsvp/salutation/widower_and_family.rb
186
+ - app/views/layouts/rsvp/application.html.erb
187
+ - app/views/rsvp/response/_show.html.erb
188
+ - app/views/rsvp/response/confirmation.html.erb
189
+ - app/views/rsvp/response/index.html.erb
190
+ - app/views/rsvp/response/show.html.erb
191
+ - app/views/rsvp/session/index.html.erb
192
+ - config/cucumber.yml
193
+ - config/routes.rb
194
+ - db/migrate/20140106042028_create_rsvp_people.rb
195
+ - db/migrate/20140106042630_create_rsvp_families.rb
196
+ - db/migrate/20140106042748_create_rsvp_members.rb
197
+ - db/migrate/20140106042845_create_rsvp_invitations.rb
198
+ - db/migrate/20140106043014_create_rsvp_responses.rb
199
+ - db/migrate/20140106043143_create_rsvp_salutations.rb
200
+ - lib/generators/rsvp/USAGE
201
+ - lib/generators/rsvp/views_generator.rb
202
+ - lib/rsvp.rb
203
+ - lib/rsvp/engine.rb
204
+ - lib/rsvp/version.rb
205
+ - lib/tasks/cucumber.rake
206
+ - lib/tasks/rsvp_tasks.rake
207
+ homepage: http://github.com/ryanricard/rsvp
208
+ licenses:
209
+ - MIT
210
+ metadata: {}
211
+ post_install_message:
212
+ rdoc_options: []
213
+ require_paths:
214
+ - lib
215
+ required_ruby_version: !ruby/object:Gem::Requirement
216
+ requirements:
217
+ - - ! '>='
218
+ - !ruby/object:Gem::Version
219
+ version: '0'
220
+ required_rubygems_version: !ruby/object:Gem::Requirement
221
+ requirements:
222
+ - - ! '>='
223
+ - !ruby/object:Gem::Version
224
+ version: '0'
225
+ requirements: []
226
+ rubyforge_project:
227
+ rubygems_version: 2.2.1
228
+ signing_key:
229
+ specification_version: 4
230
+ summary: Rsvp is a Rails mountable engine to collects online RSVP responses.
231
+ test_files: []