saaz 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +33 -0
- data/Gemfile +4 -0
- data/LICENSE +21 -0
- data/MIT-LICENSE +20 -0
- data/README.md +11 -0
- data/Rakefile +32 -0
- data/Readme.md +11 -0
- data/app/assets/images/saaz/.keep +0 -0
- data/app/assets/javascripts/saaz.js.coffee +1 -0
- data/app/assets/javascripts/saaz/application.js.coffee +13 -0
- data/app/assets/javascripts/saaz/forms.js.coffee.erb +57 -0
- data/app/assets/stylesheets/saaz.css.scss +1 -0
- data/app/assets/stylesheets/saaz/_vars.css.scss +0 -0
- data/app/assets/stylesheets/saaz/application.css.scss +13 -0
- data/app/assets/stylesheets/saaz/customers.css.scss +24 -0
- data/app/assets/stylesheets/saaz/devmode.css.scss +5 -0
- data/app/controllers/saaz/application_controller.rb +2 -0
- data/app/controllers/saaz/customers_controller.rb +74 -0
- data/app/helpers/saaz/application_helper.rb +4 -0
- data/app/helpers/saaz/customers_helper.rb +4 -0
- data/app/models/saaz/customer.rb +47 -0
- data/app/models/saaz/subscription.rb +42 -0
- data/app/views/layouts/saaz/application.html.erb +14 -0
- data/app/views/saaz/customers/_form.html.erb +28 -0
- data/app/views/saaz/customers/edit.html.erb +11 -0
- data/app/views/saaz/customers/new.html.erb +8 -0
- data/config/routes.rb +2 -0
- data/db/migrate/20140709194435_add_customers.rb +9 -0
- data/db/migrate/20140709194448_add_subscriptions.rb +10 -0
- data/lib/saaz.rb +19 -0
- data/lib/saaz/configuration.rb +30 -0
- data/lib/saaz/engine.rb +5 -0
- data/lib/saaz/stripe_object.rb +66 -0
- data/lib/saaz/version.rb +3 -0
- data/lib/tasks/saaz_tasks.rake +4 -0
- data/saaz.gemspec +25 -0
- data/spec/dummy/README.rdoc +28 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/assets/images/.keep +0 -0
- data/spec/dummy/app/assets/javascripts/application.js +13 -0
- data/spec/dummy/app/assets/stylesheets/application.css +13 -0
- data/spec/dummy/app/controllers/application_controller.rb +5 -0
- data/spec/dummy/app/controllers/concerns/.keep +0 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/mailers/.keep +0 -0
- data/spec/dummy/app/models/.keep +0 -0
- data/spec/dummy/app/models/concerns/.keep +0 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +23 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +29 -0
- data/spec/dummy/config/environments/production.rb +80 -0
- data/spec/dummy/config/environments/test.rb +36 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +12 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/routes.rb +4 -0
- data/spec/dummy/lib/assets/.keep +0 -0
- data/spec/dummy/log/.keep +0 -0
- data/spec/dummy/public/404.html +58 -0
- data/spec/dummy/public/422.html +58 -0
- data/spec/dummy/public/500.html +57 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/integration/navigation_test.rb +10 -0
- data/spec/saaz_test.rb +7 -0
- data/spec/test_helper.rb +15 -0
- data/test/controllers/saaz/saaz/customers_controller_test.rb +9 -0
- data/test/helpers/saaz/saaz/customers_helper_test.rb +6 -0
- metadata +250 -0
checksums.yaml
ADDED
@@ -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
|
data/.gitignore
ADDED
@@ -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
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.
|
data/MIT-LICENSE
ADDED
@@ -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.
|
data/README.md
ADDED
data/Rakefile
ADDED
@@ -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
|
data/Readme.md
ADDED
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 — 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
|
File without changes
|
@@ -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,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,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
|