stripe_saas 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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.asc +159 -0
- data/Rakefile +37 -0
- data/app/assets/javascripts/stripe_saas/application.js +13 -0
- data/app/assets/stylesheets/stripe_saas/application.css +15 -0
- data/app/concerns/stripe_saas/feature.rb +23 -0
- data/app/concerns/stripe_saas/plan.rb +45 -0
- data/app/concerns/stripe_saas/plan_feature.rb +25 -0
- data/app/concerns/stripe_saas/subscription.rb +182 -0
- data/app/controllers/stripe_saas/application_controller.rb +5 -0
- data/app/controllers/stripe_saas/subscriptions_controller.rb +200 -0
- data/app/helpers/stripe_saas/application_helper.rb +26 -0
- data/app/views/stripe_saas/subscriptions/_card.html.erb +51 -0
- data/app/views/stripe_saas/subscriptions/_card_form.html.erb +42 -0
- data/app/views/stripe_saas/subscriptions/_pricing_table.html.erb +43 -0
- data/app/views/stripe_saas/subscriptions/edit.html.erb +7 -0
- data/app/views/stripe_saas/subscriptions/index.html.erb +2 -0
- data/app/views/stripe_saas/subscriptions/new.html.erb +1 -0
- data/app/views/stripe_saas/subscriptions/show.html.erb +15 -0
- data/app/views/stripe_saas/subscriptions/unauthorized.html.erb +1 -0
- data/config/environment.rb +0 -0
- data/config/routes.rb +10 -0
- data/lib/generators/stripe_saas/install_generator.rb +60 -0
- data/lib/generators/stripe_saas/templates/app/models/feature.rb +8 -0
- data/lib/generators/stripe_saas/templates/app/models/plan.rb +9 -0
- data/lib/generators/stripe_saas/templates/app/models/plan_feature.rb +6 -0
- data/lib/generators/stripe_saas/templates/app/models/subscription.rb +5 -0
- data/lib/generators/stripe_saas/templates/config/initializers/stripe_saas.rb +7 -0
- data/lib/generators/stripe_saas/views_generator.rb +20 -0
- data/lib/stripe_saas.rb +9 -0
- data/lib/stripe_saas/configuration.rb +51 -0
- data/lib/stripe_saas/engine.rb +41 -0
- data/lib/stripe_saas/version.rb +3 -0
- data/lib/tasks/stripe_saas_tasks.rake +11 -0
- data/spec/concerns/plan_spec.rb +50 -0
- data/spec/dummy/README.rdoc +28 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/assets/javascripts/application.js +13 -0
- data/spec/dummy/app/assets/stylesheets/application.css +15 -0
- data/spec/dummy/app/controllers/application_controller.rb +5 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/models/plan.rb +7 -0
- data/spec/dummy/app/models/subscription.rb +5 -0
- data/spec/dummy/app/models/user.rb +8 -0
- data/spec/dummy/app/views/layouts/application.html.erb +16 -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/bin/setup +29 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +27 -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 +41 -0
- data/spec/dummy/config/environments/production.rb +79 -0
- data/spec/dummy/config/environments/test.rb +42 -0
- data/spec/dummy/config/initializers/assets.rb +11 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/spec/dummy/config/initializers/devise.rb +259 -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 +4 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/stripe_saas.rb +7 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/devise.en.yml +60 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/routes.rb +10 -0
- data/spec/dummy/config/secrets.yml +22 -0
- data/spec/dummy/db/development.sqlite3 +0 -0
- data/spec/dummy/db/migrate/20150101233243_devise_create_users.rb +42 -0
- data/spec/dummy/db/migrate/20150102001921_create_subscriptions.rb +14 -0
- data/spec/dummy/db/migrate/20150102001930_create_plans.rb +19 -0
- data/spec/dummy/db/schema.rb +61 -0
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/log/development.log +170 -0
- data/spec/dummy/log/test.log +110 -0
- data/spec/dummy/public/404.html +67 -0
- data/spec/dummy/public/422.html +67 -0
- data/spec/dummy/public/500.html +66 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/integration/navigation_test.rb +9 -0
- data/spec/rails_helper.rb +23 -0
- data/spec/spec_helper.rb +22 -0
- metadata +278 -0
@@ -0,0 +1,200 @@
|
|
1
|
+
module StripeSaas
|
2
|
+
class SubscriptionsController < ApplicationController
|
3
|
+
before_filter :load_owner
|
4
|
+
before_filter :show_existing_subscription, only: [:index, :new, :create], unless: :no_owner?
|
5
|
+
before_filter :load_subscription, only: [:show, :cancel, :edit, :update]
|
6
|
+
before_filter :load_plans, only: [:index, :edit]
|
7
|
+
|
8
|
+
def load_plans
|
9
|
+
@plans = ::Plan.order(:price_cents)
|
10
|
+
end
|
11
|
+
|
12
|
+
def unauthorized
|
13
|
+
render status: 401, template: "stripe_saas/subscriptions/unauthorized"
|
14
|
+
false
|
15
|
+
end
|
16
|
+
|
17
|
+
# subscription.subscription_owner
|
18
|
+
def load_owner
|
19
|
+
unless params[:owner_id].nil?
|
20
|
+
if current_owner.present?
|
21
|
+
|
22
|
+
# we need to try and look this owner up via the find method so that we're
|
23
|
+
# taking advantage of any override of the find method that would be provided
|
24
|
+
# by older versions of friendly_id. (support for newer versions default behavior
|
25
|
+
# below.)
|
26
|
+
searched_owner = current_owner.class.find(params[:owner_id]) rescue nil
|
27
|
+
|
28
|
+
# if we couldn't find them that way, check whether there is a new version of
|
29
|
+
# friendly_id in place that we can use to look them up by their slug.
|
30
|
+
# in christoph's words, "why?!" in my words, "warum?!!!"
|
31
|
+
# (we debugged this together on skype.)
|
32
|
+
if searched_owner.nil? && current_owner.class.respond_to?(:friendly)
|
33
|
+
searched_owner = current_owner.class.friendly.find(params[:owner_id]) rescue nil
|
34
|
+
end
|
35
|
+
|
36
|
+
if current_owner.try(:id) == searched_owner.try(:id)
|
37
|
+
@owner = current_owner
|
38
|
+
else
|
39
|
+
customer = Subscription.find_customer(searched_owner)
|
40
|
+
customer_2 = Subscription.find_customer(current_owner)
|
41
|
+
# susbscription we are looking for belongs to the same user but to a different
|
42
|
+
# subscription owner
|
43
|
+
# e.g. user -> account -> subscription
|
44
|
+
# same user but different accounts for example
|
45
|
+
|
46
|
+
if customer_2.try(:id) == customer.try(:id)
|
47
|
+
@owner = searched_owner
|
48
|
+
else
|
49
|
+
return unauthorized
|
50
|
+
end
|
51
|
+
end
|
52
|
+
else
|
53
|
+
return unauthorized
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def no_owner?
|
59
|
+
@owner.nil?
|
60
|
+
end
|
61
|
+
|
62
|
+
def load_subscription
|
63
|
+
# config.subscriptions_owned_by = :account
|
64
|
+
# config.customer_accessor = :owner
|
65
|
+
ownership_attribute = :"#{StripeSaas.subscriptions_owned_by}_id"
|
66
|
+
@subscription = ::Subscription.where(ownership_attribute => current_owner.id).find_by_id(params[:id]) ||
|
67
|
+
::Subscription.where(ownership_attribute => @owner.id).find_by_id(params[:id])
|
68
|
+
return @subscription.present? ? @subscription : unauthorized
|
69
|
+
end
|
70
|
+
|
71
|
+
# the following two methods allow us to show the pricing table before someone has an account.
|
72
|
+
# by default these support devise, but they can be overriden to support others.
|
73
|
+
def current_owner
|
74
|
+
# e.g. "self.current_user"
|
75
|
+
send "current_#{StripeSaas.subscriptions_owned_by}"
|
76
|
+
end
|
77
|
+
|
78
|
+
def redirect_to_sign_up
|
79
|
+
# this is a Devise default variable and thus should not change its name
|
80
|
+
# when we change subscription owners from :user to :company
|
81
|
+
session["user_return_to"] = new_subscription_path(plan: params[:plan])
|
82
|
+
devise_scope = (StripeSaas.devise_scope || StripeSaas.subscriptions_owned_by).to_s
|
83
|
+
redirect_to new_registration_path(devise_scope)
|
84
|
+
end
|
85
|
+
|
86
|
+
def index
|
87
|
+
# don't bother showing the index if they've already got a subscription.
|
88
|
+
if current_owner and current_owner.subscription.present?
|
89
|
+
redirect_to stripe_saas.edit_owner_subscription_path(current_owner, current_owner.subscription)
|
90
|
+
end
|
91
|
+
|
92
|
+
# Load all plans.
|
93
|
+
@plans = ::Plan.order(:display_order).all
|
94
|
+
|
95
|
+
# Don't prep a subscription unless a user is authenticated.
|
96
|
+
unless no_owner?
|
97
|
+
# we should also set the owner of the subscription here.
|
98
|
+
@subscription = ::Subscription.new({StripeSaas.owner_id_sym => @owner.id})
|
99
|
+
@subscription.subscription_owner = @owner
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
def new
|
105
|
+
if no_owner?
|
106
|
+
|
107
|
+
if defined?(Devise)
|
108
|
+
|
109
|
+
# by default these methods support devise.
|
110
|
+
if current_owner
|
111
|
+
redirect_to new_owner_subscription_path(current_owner, plan: params[:plan])
|
112
|
+
else
|
113
|
+
redirect_to_sign_up
|
114
|
+
end
|
115
|
+
|
116
|
+
else
|
117
|
+
raise "This feature depends on Devise for authentication."
|
118
|
+
end
|
119
|
+
|
120
|
+
else
|
121
|
+
@subscription = ::Subscription.new
|
122
|
+
@subscription.plan = ::Plan.find_by_stripe_id(params[:plan])
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def show_existing_subscription
|
127
|
+
if @owner.subscription.present?
|
128
|
+
redirect_to owner_subscription_path(@owner, @owner.subscription)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def create
|
133
|
+
@subscription = ::Subscription.new(subscription_params)
|
134
|
+
@subscription.subscription_owner = @owner
|
135
|
+
|
136
|
+
if @subscription.save
|
137
|
+
flash[:notice] = after_new_subscription_message
|
138
|
+
redirect_to after_new_subscription_path
|
139
|
+
else
|
140
|
+
flash[:error] = 'There was a problem processing this transaction.'
|
141
|
+
render :new
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def show
|
146
|
+
end
|
147
|
+
|
148
|
+
def cancel
|
149
|
+
flash[:notice] = "You've successfully cancelled your subscription."
|
150
|
+
@subscription.plan_id = nil
|
151
|
+
@subscription.save
|
152
|
+
redirect_to owner_subscription_path(@owner, @subscription)
|
153
|
+
end
|
154
|
+
|
155
|
+
def edit
|
156
|
+
end
|
157
|
+
|
158
|
+
def update
|
159
|
+
new_plan_id = subscription_params[:plan_id]
|
160
|
+
new_plan = ::Plan.find(new_plan_id)
|
161
|
+
|
162
|
+
if @subscription.plan.free? && !new_plan.free? && subscription_params[:credit_card_token].nil?
|
163
|
+
flash[:notice] = "Please enter payment information to upgrade."
|
164
|
+
redirect_to edit_owner_subscription_path(@owner, @subscription, update: 'card', plan: new_plan_id)
|
165
|
+
else
|
166
|
+
if @subscription.update_attributes(subscription_params)
|
167
|
+
flash[:notice] = "You've successfully updated your subscription."
|
168
|
+
redirect_to edit_owner_subscription_path(@owner, @subscription)
|
169
|
+
else
|
170
|
+
flash[:error] = 'There was a problem processing this transaction.'
|
171
|
+
render :edit
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
private
|
177
|
+
|
178
|
+
def subscription_params
|
179
|
+
# If strong_parameters is around, use that.
|
180
|
+
if defined?(ActionController::StrongParameters)
|
181
|
+
params.require(:subscription).permit(:plan_id, :stripe_id, :current_price, :credit_card_token, :card_type, :last_four)
|
182
|
+
else
|
183
|
+
# Otherwise, let's hope they're using attr_accessible to protect their models!
|
184
|
+
params[:subscription]
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
def after_new_subscription_path
|
189
|
+
controller = ::ApplicationController.new
|
190
|
+
controller.respond_to?(:after_new_subscription_path) ?
|
191
|
+
controller.try(:after_new_subscription_path, @owner, @subscription) : owner_subscription_path(@owner, @subscription)
|
192
|
+
end
|
193
|
+
|
194
|
+
def after_new_subscription_message
|
195
|
+
controller = ::ApplicationController.new
|
196
|
+
controller.respond_to?(:new_subscription_notice_message) ?
|
197
|
+
controller.try(:new_subscription_notice_message) : "You've been successfully upgraded."
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module StripeSaas
|
2
|
+
module ApplicationHelper
|
3
|
+
include MoneyRails::ActionViewExtension
|
4
|
+
|
5
|
+
def plan_price(plan)
|
6
|
+
"#{humanized_money_with_symbol(plan.price, :no_cents => false)}/#{plan_interval(plan)}"
|
7
|
+
end
|
8
|
+
|
9
|
+
def plan_interval(plan)
|
10
|
+
case plan.interval
|
11
|
+
when "month"
|
12
|
+
"month"
|
13
|
+
when "year"
|
14
|
+
"year"
|
15
|
+
when "week"
|
16
|
+
"week"
|
17
|
+
when "6-month"
|
18
|
+
"half-year"
|
19
|
+
when "3-month"
|
20
|
+
"quarter"
|
21
|
+
else
|
22
|
+
"month"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
<% content_for :stripe_saas do %>
|
2
|
+
<script type="text/javascript" src="https://js.stripe.com/v2/"></script>
|
3
|
+
<% end %>
|
4
|
+
|
5
|
+
<%= render 'card_form', url: url, title: title %>
|
6
|
+
|
7
|
+
<script type="text/javascript">
|
8
|
+
Stripe.setPublishableKey("<%= StripeSaas.stripe_publishable_key %>");
|
9
|
+
|
10
|
+
var stripeResponseHandler = function (status, response) {
|
11
|
+
|
12
|
+
if (response.error) {
|
13
|
+
// show the errors on the form
|
14
|
+
$(".payment-errors").text(response.error.message).show();
|
15
|
+
$(".submit-button").removeAttr("disabled");
|
16
|
+
} else {
|
17
|
+
var $form = $("#payment-form");
|
18
|
+
// token contains id, last4, and card type
|
19
|
+
// insert the token into the form so it gets submitted to the server
|
20
|
+
$cc_token_field = $('<input type="hidden" name="subscription[credit_card_token]" />').val(response.id);
|
21
|
+
$last_four_field = $('<input type="hidden" name="subscription[last_four]" />').val(response.card.last4);
|
22
|
+
$card_brand = $('<input type="hidden" name="subscription[card_type]" />').val(response.card.brand);
|
23
|
+
//
|
24
|
+
$form.append($cc_token_field, $last_four_field, $card_brand);
|
25
|
+
|
26
|
+
$form.get(0).submit();
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
$(document).ready(function() {
|
31
|
+
// By default, don't show errors.
|
32
|
+
$(".payment-errors").hide()
|
33
|
+
|
34
|
+
$("#payment-form").submit(function(event) {
|
35
|
+
|
36
|
+
// disable the submit button to prevent repeated clicks
|
37
|
+
$('.submit-button').attr("disabled", "disabled");
|
38
|
+
|
39
|
+
Stripe.createToken({
|
40
|
+
number: $('.card-number').val(),
|
41
|
+
cvc: $('.card-cvc').val(),
|
42
|
+
exp_month: $('.card-expiry-month').val(),
|
43
|
+
exp_year: $('.card-expiry-year').val()
|
44
|
+
}, stripeResponseHandler);
|
45
|
+
|
46
|
+
// prevent the form from submitting with the default action
|
47
|
+
event.preventDefault();
|
48
|
+
});
|
49
|
+
});
|
50
|
+
|
51
|
+
</script>
|
@@ -0,0 +1,42 @@
|
|
1
|
+
<%= form_for @subscription, url: url, html: {id: 'payment-form', class: 'form-horizontal'} do |f| %>
|
2
|
+
|
3
|
+
<fieldset>
|
4
|
+
|
5
|
+
<legend><%= title %></legend>
|
6
|
+
|
7
|
+
<div class="control-group">
|
8
|
+
<label class="control-label">Card Number</label>
|
9
|
+
<div class="controls">
|
10
|
+
<input type="text" size="20" autocomplete="off" class="card-number"/>
|
11
|
+
</div>
|
12
|
+
</div>
|
13
|
+
|
14
|
+
<div class="control-group">
|
15
|
+
<label class="control-label">Expiration (MM/YYYY)</label>
|
16
|
+
<div class="controls">
|
17
|
+
<input type="text" size="2" class="card-expiry-month input-mini"/>
|
18
|
+
<span> / </span>
|
19
|
+
<input type="text" size="4" class="card-expiry-year input-mini"/>
|
20
|
+
</div>
|
21
|
+
</div>
|
22
|
+
|
23
|
+
<div class="control-group">
|
24
|
+
<label class="control-label">CVC</label>
|
25
|
+
<div class="controls">
|
26
|
+
<input type="text" size="4" autocomplete="off" class="card-cvc input-small"/>
|
27
|
+
</div>
|
28
|
+
</div>
|
29
|
+
|
30
|
+
<div class="alert alert-error payment-errors"></div>
|
31
|
+
<%= f.hidden_field :plan_id, value: params[:plan] || @subscription.plan_id %>
|
32
|
+
|
33
|
+
</fieldset>
|
34
|
+
|
35
|
+
<div class="control-group">
|
36
|
+
<div class="controls">
|
37
|
+
<button type="submit" class="btn btn-primary submit-button">Upgrade Your Account</button>
|
38
|
+
<%= link_to "Cancel", owner_subscriptions_path(@owner), class: 'btn' %>
|
39
|
+
</div>
|
40
|
+
</div>
|
41
|
+
|
42
|
+
<% end %>
|
@@ -0,0 +1,43 @@
|
|
1
|
+
<ul class="thumbnails pricing-table">
|
2
|
+
<% @plans.each do |plan| %>
|
3
|
+
<li class="span3 plan <%= 'plan-primary' if plan.highlight? %>">
|
4
|
+
<div class="thumbnail">
|
5
|
+
<div class="caption">
|
6
|
+
<h3><%= plan.name %></h3>
|
7
|
+
<h4><%= plan_price(plan) %></h4>
|
8
|
+
<div class="call-to-action">
|
9
|
+
<% if @subscription.nil? %>
|
10
|
+
<%= link_to 'Sign Up', stripe_saas.new_subscription_path(plan: plan.stripe_id), class: "btn btn-success btn-large" %>
|
11
|
+
<% elsif @subscription.persisted? %>
|
12
|
+
<% if @subscription.plan == plan %>
|
13
|
+
<%= form_for @subscription, url: owner_subscription_path(@owner, @subscription) do |f| %>
|
14
|
+
<%= f.submit 'Selected', class: "btn btn-large", disabled: 'disabled' %>
|
15
|
+
<% end %>
|
16
|
+
<% else %>
|
17
|
+
<%= form_for @subscription, url: owner_subscription_path(@owner, @subscription) do |f| %>
|
18
|
+
<%= f.hidden_field :plan_id, value: plan.id %>
|
19
|
+
<%= f.submit @subscription.describe_difference(plan), class: "btn btn-success btn-large" %>
|
20
|
+
<% end %>
|
21
|
+
<% end %>
|
22
|
+
<% else %>
|
23
|
+
<%= link_to 'Upgrade', new_owner_subscription_path(@owner, plan: plan.stripe_id), class: "btn btn-success btn-large" %>
|
24
|
+
<% end %>
|
25
|
+
</div>
|
26
|
+
<ul class="features">
|
27
|
+
<ul>
|
28
|
+
<% plan.plan_features.each do |plan_feature| %>
|
29
|
+
<li>
|
30
|
+
<% if plan_feature.feature.feature_type == 'boolean' %>
|
31
|
+
<%= plan_feature.value > 0 ? number_with_delimiter(plan_feature.value) : "No" %> <%= plan_feature.feature.description %>
|
32
|
+
<% else %>
|
33
|
+
<%= pf.value ? '✔' : '✖' %> <%= pf.feature.description %>
|
34
|
+
<% end %>
|
35
|
+
</li>
|
36
|
+
<% end %>
|
37
|
+
</ul>
|
38
|
+
</ul>
|
39
|
+
</div>
|
40
|
+
</div>
|
41
|
+
</li>
|
42
|
+
<% end %>
|
43
|
+
</ul>
|
@@ -0,0 +1,7 @@
|
|
1
|
+
<% if params['update'] == 'card' %>
|
2
|
+
<%= render 'card', title: "Update Your Payment Information", url: owner_subscription_path(@owner, @subscription) %>
|
3
|
+
<% else %>
|
4
|
+
<h1>What Plan Is Best For You?</h1>
|
5
|
+
<%= render 'pricing_table' %>
|
6
|
+
<p>You can also <%= link_to 'cancel your subscription', cancel_owner_subscription_path(@owner, @subscription), method: :post %>.</p>
|
7
|
+
<% end %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= render 'card', title: "Upgrade Your Account", url: owner_subscriptions_path(@owner) %>
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<% if @subscription.plan.present? %>
|
2
|
+
<h2>You're Subscribed!</h2>
|
3
|
+
<p>You're currently subscribed to the <%= @subscription.plan.name %> plan.</p>
|
4
|
+
<%= link_to 'Choose Another Plan', edit_owner_subscription_path(@owner, @subscription), class: 'btn' %>
|
5
|
+
<% else %>
|
6
|
+
<h2>No Subscription</h2>
|
7
|
+
<p>You are not subscribed to a paid plan.</p>
|
8
|
+
<%= link_to 'Choose A Plan', edit_owner_subscription_path(@owner, @subscription), class: 'btn' %>
|
9
|
+
<% end %>
|
10
|
+
|
11
|
+
<br><br>
|
12
|
+
|
13
|
+
<h4>Payment Information</h4>
|
14
|
+
<p>The card on file for your account ends with <%= @subscription.last_four %>.</p>
|
15
|
+
<%= link_to 'Update Payment Information', edit_owner_subscription_path(@owner, @subscription, update: 'card'), class: 'btn' %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<h1>Unauthorized</h1>
|
File without changes
|
data/config/routes.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
|
3
|
+
module StripeSaas
|
4
|
+
class InstallGenerator < Rails::Generators::Base
|
5
|
+
|
6
|
+
def self.source_paths
|
7
|
+
[StripeSaas::Engine.root, File.expand_path("../templates", __FILE__)]
|
8
|
+
end
|
9
|
+
|
10
|
+
include Rails::Generators::Migration
|
11
|
+
|
12
|
+
argument :subscription_owner_model, :type => :string, :required => true, :desc => "Owner of the subscription"
|
13
|
+
desc "StripeSaas installation generator"
|
14
|
+
|
15
|
+
# Override the attr_accessor generated by 'argument' so that
|
16
|
+
# subscription_owner_model is always returned lowercase.
|
17
|
+
def subscription_owner_model
|
18
|
+
@subscription_owner_model.downcase
|
19
|
+
end
|
20
|
+
|
21
|
+
def install
|
22
|
+
|
23
|
+
unless defined?(StripeSaas)
|
24
|
+
gem("stripe_saas")
|
25
|
+
end
|
26
|
+
|
27
|
+
require "securerandom"
|
28
|
+
@api_key = SecureRandom.uuid
|
29
|
+
|
30
|
+
template "config/initializers/stripe_saas.rb"
|
31
|
+
|
32
|
+
# Generate subscription.
|
33
|
+
generate("model", "subscription stripe_id:string plan_id:integer last_four:string card_type:string current_price_cents:integer #{subscription_owner_model}_id:integer")
|
34
|
+
template "app/models/subscription.rb"
|
35
|
+
|
36
|
+
# Add the plans.
|
37
|
+
generate("model", "plan stripe_id:string name:string price_cents:integer interval:string interval_count:integer trial_period_days:integer metadata_as_json:text statement_descriptor:text highlight:boolean display_order:integer")
|
38
|
+
template "app/models/plan.rb"
|
39
|
+
|
40
|
+
# Add features
|
41
|
+
generate("model", "feature name:string description:string feature_type:string unit:string display_order:integer")
|
42
|
+
template "app/models/feature.rb"
|
43
|
+
|
44
|
+
# Add Plan Features
|
45
|
+
generate("model", "plan_feature value:string display_value:string plan_id:integer feature_id:integer")
|
46
|
+
template "app/models/plan_feature.rb"
|
47
|
+
|
48
|
+
# Update the owner relationship.
|
49
|
+
inject_into_class "app/models/#{subscription_owner_model}.rb", Plan, "has_one :subscription\n"
|
50
|
+
|
51
|
+
route <<-RUBY
|
52
|
+
mount StripeSaas::Engine, at: 'stripe_saas'
|
53
|
+
scope module: 'stripe_saas' do
|
54
|
+
get 'pricing' => 'subscriptions#index', as: 'pricing'
|
55
|
+
end
|
56
|
+
RUBY
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|