stripe_local 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (150) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +35 -0
  4. data/Rakefile +29 -0
  5. data/app/assets/javascripts/stripe_local/application.js +13 -0
  6. data/app/assets/javascripts/stripe_local/cards.js +2 -0
  7. data/app/assets/javascripts/stripe_local/charges.js +2 -0
  8. data/app/assets/javascripts/stripe_local/coupons.js +2 -0
  9. data/app/assets/javascripts/stripe_local/customers.js +2 -0
  10. data/app/assets/javascripts/stripe_local/discounts.js +2 -0
  11. data/app/assets/javascripts/stripe_local/invoices.js +2 -0
  12. data/app/assets/javascripts/stripe_local/line_items.js +2 -0
  13. data/app/assets/javascripts/stripe_local/plans.js +2 -0
  14. data/app/assets/javascripts/stripe_local/subscriptions.js +2 -0
  15. data/app/assets/stylesheets/stripe_local/application.css +13 -0
  16. data/app/assets/stylesheets/stripe_local/cards.css +4 -0
  17. data/app/assets/stylesheets/stripe_local/charges.css +4 -0
  18. data/app/assets/stylesheets/stripe_local/coupons.css +4 -0
  19. data/app/assets/stylesheets/stripe_local/customers.css +4 -0
  20. data/app/assets/stylesheets/stripe_local/discounts.css +4 -0
  21. data/app/assets/stylesheets/stripe_local/invoices.css +4 -0
  22. data/app/assets/stylesheets/stripe_local/line_items.css +4 -0
  23. data/app/assets/stylesheets/stripe_local/plans.css +4 -0
  24. data/app/assets/stylesheets/stripe_local/subscriptions.css +4 -0
  25. data/app/callbacks/stripe_local/plan_sync.rb +33 -0
  26. data/app/controllers/stripe_local/application_controller.rb +4 -0
  27. data/app/controllers/stripe_local/cards_controller.rb +6 -0
  28. data/app/controllers/stripe_local/charges_controller.rb +6 -0
  29. data/app/controllers/stripe_local/coupons_controller.rb +6 -0
  30. data/app/controllers/stripe_local/customers_controller.rb +6 -0
  31. data/app/controllers/stripe_local/discounts_controller.rb +6 -0
  32. data/app/controllers/stripe_local/invoices_controller.rb +6 -0
  33. data/app/controllers/stripe_local/line_items_controller.rb +6 -0
  34. data/app/controllers/stripe_local/plans_controller.rb +6 -0
  35. data/app/controllers/stripe_local/subscriptions_controller.rb +6 -0
  36. data/app/controllers/stripe_local/webhooks_controller.rb +13 -0
  37. data/app/helpers/stripe_local/application_helper.rb +4 -0
  38. data/app/helpers/stripe_local/cards_helper.rb +4 -0
  39. data/app/helpers/stripe_local/charges_helper.rb +4 -0
  40. data/app/helpers/stripe_local/coupons_helper.rb +4 -0
  41. data/app/helpers/stripe_local/customers_helper.rb +4 -0
  42. data/app/helpers/stripe_local/discounts_helper.rb +4 -0
  43. data/app/helpers/stripe_local/invoices_helper.rb +4 -0
  44. data/app/helpers/stripe_local/line_items_helper.rb +4 -0
  45. data/app/helpers/stripe_local/plans_helper.rb +4 -0
  46. data/app/helpers/stripe_local/subscriptions_helper.rb +4 -0
  47. data/app/mixins/stripe_local/object_adapter.rb +33 -0
  48. data/app/mixins/stripe_local/sync_plans.rb +39 -0
  49. data/app/models/stripe_local/balance.rb +48 -0
  50. data/app/models/stripe_local/card.rb +39 -0
  51. data/app/models/stripe_local/charge.rb +63 -0
  52. data/app/models/stripe_local/coupon.rb +21 -0
  53. data/app/models/stripe_local/customer.rb +98 -0
  54. data/app/models/stripe_local/discount.rb +36 -0
  55. data/app/models/stripe_local/invoice.rb +68 -0
  56. data/app/models/stripe_local/line_item.rb +56 -0
  57. data/app/models/stripe_local/plan.rb +41 -0
  58. data/app/models/stripe_local/subscription.rb +50 -0
  59. data/app/models/stripe_local/transaction.rb +45 -0
  60. data/app/models/stripe_local/transfer.rb +48 -0
  61. data/app/validators/email_pattern_validator.rb +7 -0
  62. data/app/validators/full_name_pattern_validator.rb +7 -0
  63. data/app/validators/legal_name_pattern_validator.rb +7 -0
  64. data/app/validators/phone_pattern_validator.rb +17 -0
  65. data/app/validators/plan_id_pattern_validator.rb +7 -0
  66. data/app/validators/slug_pattern_validator.rb +38 -0
  67. data/app/validators/state_abbreviation_validator.rb +13 -0
  68. data/app/validators/stripe_type_validator.rb +7 -0
  69. data/app/validators/zip_type_validator.rb +8 -0
  70. data/app/views/layouts/stripe_local/application.html.erb +14 -0
  71. data/config/routes.rb +22 -0
  72. data/db/migrate/20131122063517_load_stripe_tables.rb +200 -0
  73. data/lib/stripe_local/engine.rb +7 -0
  74. data/lib/stripe_local/version.rb +3 -0
  75. data/lib/stripe_local/webhook/subscriber.rb +34 -0
  76. data/lib/stripe_local/webhook/types.rb +45 -0
  77. data/lib/stripe_local/webhook.rb +55 -0
  78. data/lib/stripe_local/webhooks.rb +20 -0
  79. data/lib/stripe_local.rb +48 -0
  80. data/lib/tasks/stripe_local_tasks.rake +4 -0
  81. data/spec/dummy/README.rdoc +28 -0
  82. data/spec/dummy/Rakefile +6 -0
  83. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  84. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  85. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  86. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  87. data/spec/dummy/app/models/client.rb +4 -0
  88. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  89. data/spec/dummy/bin/bundle +3 -0
  90. data/spec/dummy/bin/rails +4 -0
  91. data/spec/dummy/bin/rake +4 -0
  92. data/spec/dummy/config/application.rb +21 -0
  93. data/spec/dummy/config/boot.rb +5 -0
  94. data/spec/dummy/config/database.yml +17 -0
  95. data/spec/dummy/config/environment.rb +5 -0
  96. data/spec/dummy/config/environments/development.rb +29 -0
  97. data/spec/dummy/config/environments/production.rb +80 -0
  98. data/spec/dummy/config/environments/test.rb +36 -0
  99. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  100. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  101. data/spec/dummy/config/initializers/inflections.rb +16 -0
  102. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  103. data/spec/dummy/config/initializers/secret_token.rb +12 -0
  104. data/spec/dummy/config/initializers/session_store.rb +3 -0
  105. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  106. data/spec/dummy/config/locales/en.yml +23 -0
  107. data/spec/dummy/config/routes.rb +4 -0
  108. data/spec/dummy/config.ru +4 -0
  109. data/spec/dummy/db/migrate/20131102200937_create_clients.rb +11 -0
  110. data/spec/dummy/db/migrate/20131122104223_add_stripe_customer_id_to_clients.rb +5 -0
  111. data/spec/dummy/db/schema.rb +236 -0
  112. data/spec/dummy/log/development.log +1290 -0
  113. data/spec/dummy/log/test.log +7041 -0
  114. data/spec/dummy/public/404.html +58 -0
  115. data/spec/dummy/public/422.html +58 -0
  116. data/spec/dummy/public/500.html +57 -0
  117. data/spec/dummy/public/favicon.ico +0 -0
  118. data/spec/dummy/spec/spec_helper.rb +42 -0
  119. data/spec/fixtures/client_params.json +18 -0
  120. data/spec/fixtures/credit_card.json +18 -0
  121. data/spec/fixtures/stripe_local/balance_transactions.yml +25 -0
  122. data/spec/fixtures/stripe_local/cards.yml +21 -0
  123. data/spec/fixtures/stripe_local/charges.yml +37 -0
  124. data/spec/fixtures/stripe_local/coupons.yml +23 -0
  125. data/spec/fixtures/stripe_local/customers.yml +21 -0
  126. data/spec/fixtures/stripe_local/discounts.yml +13 -0
  127. data/spec/fixtures/stripe_local/invoices.yml +37 -0
  128. data/spec/fixtures/stripe_local/line_items.yml +19 -0
  129. data/spec/fixtures/stripe_local/plans.yml +17 -0
  130. data/spec/fixtures/stripe_local/subscriptions.yml +25 -0
  131. data/spec/fixtures/stripe_local/transfers.yml +17 -0
  132. data/spec/models/stripe_local/balance_spec.rb +47 -0
  133. data/spec/models/stripe_local/card_spec.rb +13 -0
  134. data/spec/models/stripe_local/charge_spec.rb +13 -0
  135. data/spec/models/stripe_local/customer_spec.rb +17 -0
  136. data/spec/models/stripe_local/invoice_spec.rb +17 -0
  137. data/spec/models/stripe_local/plan_spec.rb +33 -0
  138. data/spec/models/stripe_local/subscription_spec.rb +15 -0
  139. data/spec/models/stripe_local/transaction_spec.rb +14 -0
  140. data/spec/models/stripe_local/transfer_spec.rb +13 -0
  141. data/spec/spec_helper.rb +19 -0
  142. data/spec/webhook_fixtures/balance_transaction.json +23 -0
  143. data/spec/webhook_fixtures/charge.succeeded.json +45 -0
  144. data/spec/webhook_fixtures/customer.created.json +41 -0
  145. data/spec/webhook_fixtures/customer.subscription.created.json +27 -0
  146. data/spec/webhook_fixtures/customer_creation_response.json +66 -0
  147. data/spec/webhook_fixtures/invoice.payment_succeeded.json +55 -0
  148. data/spec/webhook_fixtures/plan.created.json +12 -0
  149. data/spec/webhook_fixtures/transfer.json +32 -0
  150. metadata +403 -0
@@ -0,0 +1,98 @@
1
+ module StripeLocal
2
+ class Customer < ActiveRecord::Base
3
+ include ObjectAdapter
4
+
5
+ self.primary_key = :id
6
+
7
+ has_one :model, inverse_of: :customer, class_name: "::#{StripeLocal::model_class}"
8
+
9
+ has_many :cards, inverse_of: :customer
10
+
11
+ has_many :invoices, inverse_of: :customer
12
+
13
+ has_many :charges, inverse_of: :customer
14
+
15
+ has_one :subscription, inverse_of: :customer
16
+
17
+ has_one :plan, through: :subscription, source: :plan
18
+
19
+ class<<self
20
+ #=!=#>>>
21
+ #
22
+ # this is the primary interface for subscribing.
23
+ #
24
+ # [params]
25
+ # * +card+ (required) -> the token returned by stripe.js
26
+ # * +plan+ (required) -> the id of the plan being subscribed to
27
+ # * +email+ (optional) -> the client's email address
28
+ # * +description+ (optional) -> a description to attach to the stripe object for future reference
29
+ # * +coupon+ (optional) -> the id of a coupon if the subscription should be discounted
30
+ # * +lines+ (optional) -> an array of (amount,description) tuples
31
+ # ```
32
+ # :card => "tok_abc123",
33
+ # :plan => "MySaaS",
34
+ # :email => subscriber.email,
35
+ # :description => "a one year subscription to our flagship service at $99.00 per month"
36
+ # :lines => [
37
+ # [ 20000, "a one time setup fee of $200.00 for new members" ]
38
+ # ]
39
+ # ```
40
+ # *returns:* _Stripe_::_Customer_._id_ which should be assign to the +:stripe_customer_id+
41
+ # field generated when bootstrapping Engine integration.
42
+ #
43
+ #=¡=#>>>
44
+ def signup params
45
+ plan = params.delete( :plan )
46
+ lines = params.delete( :lines ) || []
47
+
48
+ customer = Stripe::Customer.create( params )
49
+
50
+ lines.each do |item|
51
+ customer.add_invoice_item( {currency: 'usd'}.merge item )
52
+ end
53
+
54
+ customer.update_subscription({ plan: plan })
55
+ create( customer ).id
56
+ end
57
+
58
+ def create params
59
+ super normalize params
60
+ end
61
+
62
+ def normalize params
63
+ params.each_with_object({}) do |(k,v),h|
64
+ key = case k.to_sym
65
+ when :cards then create_each_card( v.data ) and next
66
+ when :subscription then create_subscript( v ) and next
67
+ when ->(x){attribute_method? x} then k.to_sym
68
+ else next
69
+ end
70
+ h[key] = v
71
+ end
72
+ end
73
+
74
+ def create_each_card cards
75
+ cards.each do |card|
76
+ StripeLocal::Card.create card.to_hash
77
+ end
78
+ end
79
+
80
+ def create_subscript o
81
+ StripeLocal::Subscription.create( o.to_hash ) unless o.nil?
82
+ end
83
+ end
84
+
85
+ #=!=>>>
86
+ # ~<Schema>~
87
+ # t.string :id
88
+ # t.integer :account_balance
89
+ # t.string :default_card
90
+ # t.boolean :delinquent
91
+ # t.string :description
92
+ # t.string :email
93
+ # t.text :metadata
94
+ # t.timestamps
95
+
96
+ #=¡=>>>
97
+ end
98
+ end
@@ -0,0 +1,36 @@
1
+ module StripeLocal
2
+ class Discount < ActiveRecord::Base
3
+ include ObjectAdapter
4
+
5
+ time_writer :start, :end
6
+
7
+ class<<self
8
+ def create object
9
+ super normalize object
10
+ end
11
+
12
+ def normalize attrs
13
+ attrs.each_with_object({}) do |(k,v),h|
14
+ key = case k.to_sym
15
+ when :customer then :customer_id
16
+ when :coupon then h[:coupon_id] = v.id and next
17
+ when ->(x){ attribute_method? x } then k.to_sym
18
+ else next
19
+ end
20
+ if v.is_a?(Numeric) && v > 1000000000
21
+ h[key] = Time.at( v )
22
+ else
23
+ h[key] = v
24
+ end
25
+ end
26
+ end
27
+ end
28
+
29
+ #=!=#>>>
30
+ # string :coupon_id
31
+ # string :customer_id
32
+ # datetime :start
33
+ # datetime :end
34
+ #=¡=#>>>
35
+ end
36
+ end
@@ -0,0 +1,68 @@
1
+ module StripeLocal
2
+ class Invoice < ActiveRecord::Base
3
+ include ObjectAdapter
4
+
5
+ has_many :lines, inverse_of: :invoice, class_name: "LineItem"
6
+ belongs_to :charge, inverse_of: :invoice
7
+ belongs_to :customer, inverse_of: :invoices
8
+
9
+ self.primary_key = :id
10
+
11
+ time_writer :date, :period_start, :period_end, :next_payment_attempt
12
+
13
+ class<<self
14
+ def create object
15
+ super normalize( object )
16
+ end
17
+
18
+ def normalize attrs
19
+ attrs.each_with_object({}) do |(k,v),h|
20
+ key = case k.to_sym
21
+ when :customer then :customer_id
22
+ when :charge then :charge_id
23
+ when :lines then v.data.each do |item|
24
+ StripeLocal::LineItem.create item.to_hash.merge({invoice_id: attrs.id})
25
+ end and next
26
+ when ->(x){attribute_method? x} then k.to_sym
27
+ else next
28
+ end
29
+ if v.is_a?(Numeric) && v > 1000000000
30
+ h[key] = Time.at( v )
31
+ else
32
+ h[key] = v
33
+ end
34
+ end
35
+ end
36
+
37
+ def succeed inv
38
+ #TODO: implement this
39
+ end
40
+
41
+ def fail inv
42
+ #TODO: implement this
43
+ end
44
+ end
45
+
46
+
47
+ #=!=#>>>
48
+ # string :id
49
+ # string :customer_id
50
+ # integer :amount_due
51
+ # integer :subtotal
52
+ # integer :total
53
+ # boolean :attempted
54
+ # integer :attempt_count
55
+ # boolean :paid
56
+ # boolean :closed
57
+ # datetime :date
58
+ # datetime :period_start
59
+ # datetime :period_end
60
+ # string :currency
61
+ # integer :starting_balance
62
+ # integer :ending_balance
63
+ # string :charge_id
64
+ # integer :discount
65
+ # datetime :next_payment_attempt
66
+ #=¡=#>>>
67
+ end
68
+ end
@@ -0,0 +1,56 @@
1
+ module StripeLocal
2
+ class LineItem < ActiveRecord::Base
3
+ include ObjectAdapter
4
+
5
+ self.primary_key = :id
6
+
7
+ belongs_to :invoice, inverse_of: :lines
8
+
9
+ belongs_to :plan, inverse_of: :line_items
10
+
11
+ time_writer :period_start, :period_end
12
+
13
+ def metadata= hash
14
+ MultiJson.dump hash
15
+ end
16
+
17
+ def metadata
18
+ MultiJson.load read_attribute( :metadata ), symbolize_keys: true
19
+ end
20
+
21
+ class<<self
22
+ def create attr_hash
23
+ super normalize( attr_hash )
24
+ end
25
+
26
+ def normalize attrs
27
+ attrs.each_with_object({}) do |(k,v),h|
28
+ key = case k.to_sym
29
+ when :invoice then :invoice_id
30
+ when :plan then h[:plan_id] = v.id and next
31
+ when :type then h[:subscription] = (v == "subscription" ? true : false) and next
32
+ when :period then h[:period_start] = Time.at(v.start) and h[:period_end] = Time.at(v.end) and next
33
+ when ->(x){attribute_method? x} then k.to_sym
34
+ else next
35
+ end
36
+ h[key] = v
37
+ end
38
+ end
39
+ end
40
+
41
+ #=!=#>>>
42
+ # string :id
43
+ # string :invoice_id
44
+ # boolean :subscription
45
+ # integer :amount
46
+ # string :currency
47
+ # boolean :proration
48
+ # datetime :period_start
49
+ # datetime :period_end
50
+ # integer :quantity
51
+ # string :plan_id
52
+ # string :description
53
+ # text :metadata
54
+ #=¡=#>>>
55
+ end
56
+ end
@@ -0,0 +1,41 @@
1
+ module StripeLocal
2
+ class Plan < ActiveRecord::Base
3
+ include SyncPlans
4
+
5
+ self.primary_key = :id
6
+
7
+ has_many :subscriptions, inverse_of: :plan
8
+
9
+ class<<self
10
+ def create object
11
+ if found = find_by( id: object[:id] )
12
+ found.update_attributes synced: true
13
+ else
14
+ super normalize object
15
+ end
16
+ end
17
+
18
+ def normalize attrs
19
+ attrs.each_with_object({}) do |(k,v),h|
20
+ key = case k.to_sym
21
+ when :livemode then h[:synced] = true and next
22
+ when ->(x){ attribute_method? x } then k.to_sym
23
+ else next
24
+ end
25
+ h[key] = v
26
+ end
27
+ end
28
+ end
29
+
30
+ #=!=#>>>
31
+ # string :id
32
+ # string :name
33
+ # integer :amount
34
+ # string :interval
35
+ # integer :interval_count
36
+ # integer :trial_period_days
37
+ # string :currency
38
+ # boolean :synced
39
+ #=¡=#>>>
40
+ end
41
+ end
@@ -0,0 +1,50 @@
1
+ module StripeLocal
2
+ class Subscription < ActiveRecord::Base
3
+ include ObjectAdapter
4
+
5
+ belongs_to :customer, inverse_of: :subscription
6
+
7
+ belongs_to :plan, inverse_of: :subscription
8
+
9
+ time_writer :start, :canceled_at, :current_period_start,
10
+ :current_period_end, :trial_start, :trial_end, :ended_at
11
+
12
+
13
+ class<<self
14
+ def create object
15
+ super normalize( object )
16
+ end
17
+
18
+ def normalize attrs
19
+ attrs.each_with_object({}) do |(k,v),h|
20
+ key = case k.to_sym
21
+ when :id then next
22
+ when :customer then :customer_id
23
+ when :plan then h[:plan_id] = v.id and next
24
+ when ->(x){attribute_method? x} then k.to_sym
25
+ else next
26
+ end
27
+ if v.is_a?(Numeric) && v > 1000000000
28
+ h[key] = Time.at( v )
29
+ else
30
+ h[key] = v
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+
37
+ #=!=#>>>
38
+ # string :customer_id
39
+ # string :plan_id
40
+ # string :status
41
+ # datetime :start
42
+ # datetime :canceled_at
43
+ # datetime :ended_at
44
+ # datetime :current_period_start
45
+ # datetime :current_period_end
46
+ # datetime :trial_start
47
+ # datetime :trial_end
48
+ #=¡=#>>>
49
+ end
50
+ end
@@ -0,0 +1,45 @@
1
+ module StripeLocal
2
+ class Transaction < ActiveRecord::Base
3
+ include ObjectAdapter
4
+
5
+ self.primary_key = :id
6
+
7
+ time_writer :created, :available_on
8
+
9
+ class<<self
10
+ def create object
11
+ super normalize( object )
12
+ end
13
+
14
+ def normalize attrs
15
+ attrs.each_with_object({}) do |(k,v),h|
16
+ key = case k.to_sym
17
+ when :source then :source_id
18
+ when :type then :source_type
19
+ when ->(x){attribute_method? x} then k.to_sym
20
+ else next
21
+ end
22
+ if v.is_a?(Numeric) && v > 1000000000
23
+ h[key] = Time.at( v )
24
+ else
25
+ h[key] = v
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+
32
+ #=!=#>>>
33
+ # string :id
34
+ # integer :amount
35
+ # datetime :available_on
36
+ # datetime :created
37
+ # integer :fee
38
+ # integer :net
39
+ # string :source_id
40
+ # string :source_type
41
+ # string :status
42
+ # string :description
43
+ #=¡=#>>>
44
+ end
45
+ end
@@ -0,0 +1,48 @@
1
+ module StripeLocal
2
+ class Transfer < ActiveRecord::Base
3
+ include ObjectAdapter
4
+
5
+ has_one :transaction, as: :source
6
+
7
+ self.primary_key = :id
8
+
9
+ time_writer :date
10
+
11
+ def metadata= hash
12
+ MultiJson.dump hash
13
+ end
14
+
15
+ def metadata
16
+ MultiJson.load read_attribute( :metadata ), symbolize_keys: true
17
+ end
18
+
19
+ class<<self
20
+ def create object
21
+ super normalize( object )
22
+ end
23
+
24
+ def normalize attrs
25
+ attrs.each_with_object({}) do |(k,v),h|
26
+ key = case k.to_sym
27
+ when :balance_transaction then :transaction_id
28
+ when :date then h[:date] = Time.at(v) and next
29
+ when ->(x){attribute_method? x} then k.to_sym
30
+ else next
31
+ end
32
+ h[key] = v
33
+ end
34
+ end
35
+ end
36
+
37
+
38
+ #=!=#>>>
39
+ # string :id
40
+ # integer :amount
41
+ # datetime :date
42
+ # string :status
43
+ # string :transaction_id
44
+ # string :description
45
+ # text :metadata
46
+ #=¡=#>>>
47
+ end
48
+ end
@@ -0,0 +1,7 @@
1
+ class EmailPatternValidator < ActiveModel::EachValidator
2
+ def validate_each(record, attribute, value)
3
+ unless value.match(/^([\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*[\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+@((((([a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z])\.)+[a-z]{2,6})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)$/i)
4
+ record.errors[attribute] << "Not a valid email address"
5
+ end unless value.blank?
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ class FullNamePatternValidator < ActiveModel::EachValidator
2
+ def validate_each(record, attribute, value)
3
+ if value.nil? || !value.squeeze(" ").strip.match(/\A\S+?\s\S+?\Z/i)
4
+ record.errors[attribute] << "First & Last names separated by a space"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ class LegalNamePatternValidator < ActiveModel::EachValidator
2
+ def validate_each(record, attribute, value)
3
+ if value.nil? || !value.match(/\A\S+?\s\S+?(?:\s\S+?)?\Z/i)
4
+ record.errors[attribute] << "must be in the form \"First Last\", \"First Middle Last\", or \"First M Last\" (no prefixes or suffixes)"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,17 @@
1
+ class PhonePatternValidator < ActiveModel::EachValidator
2
+ def validate_each(record, attribute, value)
3
+ if !value.blank?
4
+ first_normalize value
5
+ unless value.match(/^((\d){10})$/i)
6
+ record.errors[attribute] << "10 digit phone number, area-code first, no country code please."
7
+ end
8
+ end
9
+ end
10
+
11
+ private
12
+
13
+ def first_normalize number
14
+ number.to_phone
15
+ end
16
+
17
+ end
@@ -0,0 +1,7 @@
1
+ class PlanIdPatternValidator < ActiveModel::EachValidator
2
+ def validate_each record, attribute, value
3
+ if value.nil? || !value.match(/^(([\w\-]{0,62})?)$/i)
4
+ record.errors[attribute] << "accepts alphanumeric characters, '-', and '_' only. no spaces"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,38 @@
1
+ class SlugPatternValidator < ActiveModel::EachValidator
2
+ def validate_each record, attribute, value
3
+ if value.blank?
4
+ record.errors[attribute] << "cannot be blank"
5
+ else
6
+ return string_replaced value
7
+ end
8
+ end
9
+
10
+ def string_replaced value
11
+ email_removal_for_morons value
12
+ intelligently_de_dot value
13
+ finish_normalizing value
14
+ value
15
+ end
16
+
17
+ private
18
+
19
+ def finish_normalizing str
20
+ str.gsub!(/\W/,'-')
21
+ str.gsub!(/(\W\-|\-\W|\-)+/,'-')
22
+ str.gsub!(/(\A\-|\-\Z)/,'')
23
+ str
24
+ end
25
+
26
+ def intelligently_de_dot str
27
+ str.gsub!(/([A-Z])\.([a-z])/,'\1-\2')
28
+ str.gsub!(/([A-Z])\./,'\1')
29
+ str
30
+ end
31
+
32
+ def email_removal_for_morons str
33
+ str.gsub(/^(.*)?@([^@]*)?\.([^@\.]*)$/, '\1' )
34
+ pattern = ("" == $1) ? '\2-\3' : '\1'
35
+ str.gsub!(/^(.*)?@([^@]*)?\.([^@\.]*)$/, pattern )
36
+ str
37
+ end
38
+ end
@@ -0,0 +1,13 @@
1
+ class StateAbbreviationValidator < ActiveModel::EachValidator
2
+ def validate_each record, attribute, value
3
+ unless value.blank?
4
+ if value.size > 2
5
+ value = STATES_HASH.fetch( value.downcase, 'invalid' )
6
+ record[attribute] = value
7
+ end
8
+ unless value.in? STATES_HASH.values
9
+ record.errors[attribute] << "not a state of this great nation"
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,7 @@
1
+ class StripeTypeValidator < ActiveModel::EachValidator
2
+ def validate_each(record, attribute, value)
3
+ if value.nil? || !value.in?( %w(individual corporation) )
4
+ record.errors[attribute] << "must specify either individual or corporate"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,8 @@
1
+ class ZipTypeValidator < ActiveModel::EachValidator
2
+ def validate_each(record, attribute, value)
3
+ unless value.blank?
4
+ record[attribute] = value.to_i
5
+ return value = value.to_i + 0
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>StripeLocal</title>
5
+ <%= stylesheet_link_tag "stripe_local/application", media: "all" %>
6
+ <%= javascript_include_tag "stripe_local/application" %>
7
+ <%= csrf_meta_tags %>
8
+ </head>
9
+ <body>
10
+
11
+ <%= yield %>
12
+
13
+ </body>
14
+ </html>
data/config/routes.rb ADDED
@@ -0,0 +1,22 @@
1
+ StripeLocal::Engine.routes.draw do
2
+ resources :charges
3
+
4
+ resources :line_items
5
+
6
+ resources :invoices
7
+
8
+ resources :subscriptions
9
+
10
+ resources :discounts
11
+
12
+ resources :coupons
13
+
14
+ resources :plans
15
+
16
+ resources :cards
17
+
18
+ resources :customers
19
+
20
+ post 'webhook/events', to: 'webhooks#events'
21
+
22
+ end