rsvp 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []