saaz 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +33 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE +21 -0
  5. data/MIT-LICENSE +20 -0
  6. data/README.md +11 -0
  7. data/Rakefile +32 -0
  8. data/Readme.md +11 -0
  9. data/app/assets/images/saaz/.keep +0 -0
  10. data/app/assets/javascripts/saaz.js.coffee +1 -0
  11. data/app/assets/javascripts/saaz/application.js.coffee +13 -0
  12. data/app/assets/javascripts/saaz/forms.js.coffee.erb +57 -0
  13. data/app/assets/stylesheets/saaz.css.scss +1 -0
  14. data/app/assets/stylesheets/saaz/_vars.css.scss +0 -0
  15. data/app/assets/stylesheets/saaz/application.css.scss +13 -0
  16. data/app/assets/stylesheets/saaz/customers.css.scss +24 -0
  17. data/app/assets/stylesheets/saaz/devmode.css.scss +5 -0
  18. data/app/controllers/saaz/application_controller.rb +2 -0
  19. data/app/controllers/saaz/customers_controller.rb +74 -0
  20. data/app/helpers/saaz/application_helper.rb +4 -0
  21. data/app/helpers/saaz/customers_helper.rb +4 -0
  22. data/app/models/saaz/customer.rb +47 -0
  23. data/app/models/saaz/subscription.rb +42 -0
  24. data/app/views/layouts/saaz/application.html.erb +14 -0
  25. data/app/views/saaz/customers/_form.html.erb +28 -0
  26. data/app/views/saaz/customers/edit.html.erb +11 -0
  27. data/app/views/saaz/customers/new.html.erb +8 -0
  28. data/config/routes.rb +2 -0
  29. data/db/migrate/20140709194435_add_customers.rb +9 -0
  30. data/db/migrate/20140709194448_add_subscriptions.rb +10 -0
  31. data/lib/saaz.rb +19 -0
  32. data/lib/saaz/configuration.rb +30 -0
  33. data/lib/saaz/engine.rb +5 -0
  34. data/lib/saaz/stripe_object.rb +66 -0
  35. data/lib/saaz/version.rb +3 -0
  36. data/lib/tasks/saaz_tasks.rake +4 -0
  37. data/saaz.gemspec +25 -0
  38. data/spec/dummy/README.rdoc +28 -0
  39. data/spec/dummy/Rakefile +6 -0
  40. data/spec/dummy/app/assets/images/.keep +0 -0
  41. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  42. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  43. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  44. data/spec/dummy/app/controllers/concerns/.keep +0 -0
  45. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  46. data/spec/dummy/app/mailers/.keep +0 -0
  47. data/spec/dummy/app/models/.keep +0 -0
  48. data/spec/dummy/app/models/concerns/.keep +0 -0
  49. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  50. data/spec/dummy/bin/bundle +3 -0
  51. data/spec/dummy/bin/rails +4 -0
  52. data/spec/dummy/bin/rake +4 -0
  53. data/spec/dummy/config.ru +4 -0
  54. data/spec/dummy/config/application.rb +23 -0
  55. data/spec/dummy/config/boot.rb +5 -0
  56. data/spec/dummy/config/database.yml +25 -0
  57. data/spec/dummy/config/environment.rb +5 -0
  58. data/spec/dummy/config/environments/development.rb +29 -0
  59. data/spec/dummy/config/environments/production.rb +80 -0
  60. data/spec/dummy/config/environments/test.rb +36 -0
  61. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  62. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  63. data/spec/dummy/config/initializers/inflections.rb +16 -0
  64. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  65. data/spec/dummy/config/initializers/secret_token.rb +12 -0
  66. data/spec/dummy/config/initializers/session_store.rb +3 -0
  67. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  68. data/spec/dummy/config/locales/en.yml +23 -0
  69. data/spec/dummy/config/routes.rb +4 -0
  70. data/spec/dummy/lib/assets/.keep +0 -0
  71. data/spec/dummy/log/.keep +0 -0
  72. data/spec/dummy/public/404.html +58 -0
  73. data/spec/dummy/public/422.html +58 -0
  74. data/spec/dummy/public/500.html +57 -0
  75. data/spec/dummy/public/favicon.ico +0 -0
  76. data/spec/integration/navigation_test.rb +10 -0
  77. data/spec/saaz_test.rb +7 -0
  78. data/spec/test_helper.rb +15 -0
  79. data/test/controllers/saaz/saaz/customers_controller_test.rb +9 -0
  80. data/test/helpers/saaz/saaz/customers_helper_test.rb +6 -0
  81. metadata +250 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5745996b9ee32aad4cda2200ac7121d1615aac2e
4
+ data.tar.gz: 8eb119720c4d4c6a79ec8c855c9440358c4ba168
5
+ SHA512:
6
+ metadata.gz: 3267182eb0f530ea197a6d0521a6c6880f37d7402a13882f3feb9a608c89bd7d51012c30280dac8a830be0842af45bd1f0d6f643988e9b577e78e9337d718eb4
7
+ data.tar.gz: e2c65903c3b4890b73ee42949900883565bc486264248705f407f4b109e3da4dc5461e1a8ca7265d207da0453a18f00e8c186af251c8c55a48d81db13b3b1533
@@ -0,0 +1,33 @@
1
+ .bundle/
2
+ log/*.log
3
+ pkg/
4
+ test/dummy/db/*.sqlite3
5
+ test/dummy/db/*.sqlite3-journal
6
+ test/dummy/log/*.log
7
+ test/dummy/tmp/
8
+ test/dummy/.sass-cache
9
+
10
+ *.rbc
11
+ capybara-*.html
12
+ .rspec
13
+ /log
14
+ /tmp
15
+ /db/*.sqlite3
16
+ /public/system
17
+ /coverage/
18
+ /spec/tmp
19
+ **.orig
20
+ rerun.txt
21
+ pickle-email-*.html
22
+ config/initializers/secret_token.rb
23
+ config/secrets.yml
24
+
25
+ ## Environment normalisation:
26
+ /.bundle
27
+ /vendor/bundle
28
+
29
+ # these should all be checked in to normalise the environment:
30
+ # Gemfile.lock, .ruby-version, .ruby-gemset
31
+
32
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
33
+ .rvmrc
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+ gem 'rails', '4.0.2'
3
+
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Revelry
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,20 @@
1
+ Copyright 2014 YOURNAME
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.
@@ -0,0 +1,11 @@
1
+ # Installation
2
+
3
+ In your Gemfile:
4
+ ```
5
+ gem 'saaz'
6
+ ```
7
+
8
+ From the shell:
9
+ ```
10
+ rake saaz:install:migrations
11
+ ```
@@ -0,0 +1,32 @@
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 = 'Saaz'
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("../test/dummy/Rakefile", __FILE__)
18
+ load 'rails/tasks/engine.rake'
19
+
20
+
21
+
22
+ require 'rake/testtask'
23
+
24
+ Rake::TestTask.new(:test) do |t|
25
+ t.libs << 'lib'
26
+ t.libs << 'test'
27
+ t.pattern = 'test/**/*_test.rb'
28
+ t.verbose = false
29
+ end
30
+
31
+
32
+ task default: :test
@@ -0,0 +1,11 @@
1
+ # Installation
2
+
3
+ In your Gemfile:
4
+ ```
5
+ gem 'saaz'
6
+ ```
7
+
8
+ From the shell:
9
+ ```
10
+ rake saaz:install:migrations
11
+ ```
File without changes
@@ -0,0 +1 @@
1
+ #= require saaz/application
@@ -0,0 +1,13 @@
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_tree .
@@ -0,0 +1,57 @@
1
+ window.saazLoadScript = (u)->
2
+ body = document.querySelector('body')
3
+ body.innerHTML = body.innerHTML + "<script src=\"#{u}\"><\/scr"+"ipt>"
4
+
5
+ class SaazCardForm
6
+ constructor: ($, el)->
7
+ @$el = $(el)
8
+ @el = el
9
+ @on @$el, 'submit', @.handleSubmit
10
+
11
+ @setupStripe()
12
+
13
+ on: (el, eventType, handler)->
14
+ el.on eventType, handler.bind(@)
15
+
16
+ handleSubmit: (event)->
17
+ event.preventDefault()
18
+ @$el.find('button').prop('disabled', true)
19
+ Stripe.card.createToken(@$el, @handleResponse.bind(@))
20
+
21
+ handleResponse: (status, response)->
22
+ if response.error
23
+ @$el.find('.payment-errors').text(response.error.message)
24
+ @$el.find('button').prop('disabled', false)
25
+ else
26
+ token = response.id
27
+ @$el.append($('<input type="hidden" name="stripeToken" />').val(token))
28
+ @$el.get(0).submit()
29
+
30
+ prefillForm: ()->
31
+ $('.SaazCustomerCard').val('4242424242424242')
32
+ $('.SaazCustomerCVC').val('123')
33
+ $('.SaazExpirationRow__month').val('07')
34
+ $('.SaazExpirationRow__year').val((new Date()).getYear()+1901)
35
+ $('.SaazFloatingBox').prepend('<div class="SaazDevMode">Development Mode &mdash; Prefilled</div>')
36
+
37
+ setupStripe: ()->
38
+ unless Stripe?
39
+ $.getScript 'https://js.stripe.com/v2/', ()->
40
+ Stripe.setPublishableKey('<%= Saaz.config.publishable_key.html_safe %>')
41
+ <% if Rails.env.development? %>
42
+ @prefillForm()
43
+ <% end %>
44
+
45
+
46
+ saazSetup = ($)->
47
+ # Load jQuery if it is not available
48
+ unless window.jQuery?
49
+ window.saazLoadScript('//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js')
50
+ $.noConflict()
51
+
52
+ new SaazCardForm($, '.jsSaazCustomerForm')
53
+
54
+ innerOnLoad = window.onload
55
+ window.onload = ()->
56
+ innerOnLoad() if innerOnLoad
57
+ saazSetup(jQuery)
@@ -0,0 +1 @@
1
+ //= require saaz/application
@@ -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,24 @@
1
+ @import "vars";
2
+
3
+ .SaazExpirationRow {
4
+ display: flex;
5
+ }
6
+
7
+ .SaazExpirationRow__month {
8
+ display: inline-block;
9
+ width: 35%;
10
+ flex: 2;
11
+ }
12
+
13
+ .SaazExpirationRow__year {
14
+ display: inline-block;
15
+ width: 50%;
16
+ flex: 4;
17
+ }
18
+
19
+ .SaazExpirationRow__separator {
20
+ display: inline-block;
21
+ width: 15%;
22
+ flex: 1;
23
+ text-align: center;
24
+ }
@@ -0,0 +1,5 @@
1
+ .SaazDevMode {
2
+ text-align: center;
3
+ background-size: 16px 16px;
4
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, .2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .2) 50%, rgba(255, 255, 255, .2) 75%, transparent 75%, transparent);
5
+ }
@@ -0,0 +1,2 @@
1
+ class Saaz::ApplicationController < ApplicationController
2
+ end
@@ -0,0 +1,74 @@
1
+ require_dependency 'saaz/application_controller'
2
+
3
+ class Saaz::CustomersController < ApplicationController
4
+ respond_to :json, :html
5
+
6
+ def new
7
+ set_resource_for_new
8
+ end
9
+
10
+ def create
11
+ set_resource_for_create
12
+ @resource.set_customers_on_subscription
13
+ save_and_respond(@resource)
14
+ after_create
15
+ end
16
+
17
+ def edit
18
+ set_resource_for_edit
19
+ end
20
+
21
+ def update
22
+ set_resource_for_update
23
+ @resource.cards.create(card: params[:stripeToken])
24
+ @resource.assign_attributes(resource_params)
25
+ save_and_respond(@resource)
26
+ after_update
27
+ end
28
+
29
+ protected
30
+
31
+ def set_resource_for_new
32
+ @resource = Saaz.config.customer_resource_class.new
33
+ end
34
+
35
+ def set_resource_for_create
36
+ @resource = Saaz.config.customer_resource_class.new(resource_params)
37
+ end
38
+
39
+ def set_resource_for_edit
40
+ set_resource_for_update
41
+ end
42
+
43
+ def set_resource_for_update
44
+ @resource = current_user.customer
45
+ end
46
+
47
+ def after_create
48
+ current_user.customer = @resource
49
+ current_user.save!
50
+ end
51
+
52
+ def after_update; end
53
+
54
+ def save_and_respond(resource)
55
+ unless resource.save
56
+ flash[:danger] = resource.errors.full_messages.to_sentence
57
+ end
58
+
59
+ respond_with resource do |fmt|
60
+ fmt.html { redirect_to :back }
61
+ fmt.json
62
+ end
63
+ end
64
+
65
+ def resource_param_name
66
+ Saaz.config.customer_resource_class.name.underscore.to_sym
67
+ end
68
+
69
+ def resource_params
70
+ params.require(resource_param_name).
71
+ merge(stripe_token: params[:stripeToken]).
72
+ permit(:stripe_token, subscriptions_attributes: [ :plan_id ])
73
+ end
74
+ end
@@ -0,0 +1,4 @@
1
+ module Saaz
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Saaz
2
+ module Saaz::CustomersHelper
3
+ end
4
+ end
@@ -0,0 +1,47 @@
1
+ class Saaz::Customer < ActiveRecord::Base
2
+ include Saaz::StripeObject
3
+
4
+ attr_accessor :stripe_token, :stripe_description
5
+
6
+ has_many :subscriptions, class_name: 'Saaz::Subscription'
7
+ accepts_nested_attributes_for :subscriptions
8
+
9
+ before_validation :create_stripe
10
+
11
+ validates_associated :subscriptions
12
+ validates :stripe_id, presence: true
13
+
14
+ def to_stripe
15
+ @stripe_instance ||= to_stripe_uncached
16
+ end
17
+
18
+ def to_stripe_uncached
19
+ retval = Stripe::Customer.retrieve(stripe_id)
20
+ delegate_all_to_stripe(retval)
21
+ retval
22
+ end
23
+
24
+ def set_customers_on_subscription
25
+ subscriptions.each do |sub|
26
+ sub.customer = self.becomes(Saaz::Customer)
27
+ end
28
+ end
29
+
30
+ def default_card_string
31
+ card = self.cards.retrieve(self.default_card)
32
+ "#{card.brand} ending in #{card.last4}"
33
+ end
34
+
35
+ protected
36
+
37
+ def create_stripe
38
+ return if stripe_id.present?
39
+
40
+ opts = {}
41
+ opts[:description] = stripe_description unless stripe_description.nil?
42
+ opts[:card] = stripe_token unless stripe_token.nil?
43
+
44
+ cust_obj = Stripe::Customer.create opts
45
+ self.stripe_id = cust_obj.id
46
+ end
47
+ end
@@ -0,0 +1,42 @@
1
+ class Saaz::Subscription < ActiveRecord::Base
2
+ include Saaz::StripeObject
3
+
4
+ attr_accessor :plan_id
5
+
6
+ belongs_to :customer, class_name: 'Saaz::Customer'
7
+
8
+ before_validation :create_stripe
9
+
10
+ validate :stripe_id, presence: true
11
+ validate :customer, presence: true
12
+
13
+ def to_stripe
14
+ @stripe_instance ||= to_stripe_uncached
15
+ end
16
+
17
+ def to_stripe_uncached
18
+ retval = customer.to_stripe.subscriptions.retrieve(stripe_id)
19
+ delegate_all_to_stripe(retval)
20
+ retval
21
+ end
22
+
23
+ def plan_id
24
+ retval = @plan_id
25
+ retval ||= to_stripe.plan.id rescue nil
26
+ retval
27
+ end
28
+
29
+ def cancel_stripe
30
+ to_stripe.delete(at_period_end: true)
31
+ end
32
+
33
+ protected
34
+
35
+ def create_stripe
36
+ return if stripe_id.present?
37
+
38
+ customer.create_stripe
39
+ sub_obj = customer.to_stripe.subscriptions.create(plan: plan_id)
40
+ self.stripe_id = sub_obj.id
41
+ end
42
+ end