payola-payments 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (121) hide show
  1. checksums.yaml +8 -8
  2. data/Rakefile +7 -11
  3. data/app/assets/javascripts/payola.js +1 -0
  4. data/app/assets/javascripts/payola/checkout_button.js +62 -0
  5. data/app/controllers/payola/application_controller.rb +2 -0
  6. data/app/controllers/payola/transactions_controller.rb +48 -58
  7. data/app/helpers/payola/price_helper.rb +7 -0
  8. data/{lib → app/models/concerns}/payola/sellable.rb +11 -1
  9. data/app/models/payola/affiliate.rb +5 -0
  10. data/app/models/payola/coupon.rb +5 -0
  11. data/app/models/payola/sale.rb +15 -4
  12. data/app/models/payola/stripe_webhook.rb +5 -0
  13. data/app/services/payola/charge_card.rb +6 -5
  14. data/app/services/payola/create_sale.rb +9 -5
  15. data/app/views/payola/transactions/_checkout.html.erb +48 -0
  16. data/app/views/payola/transactions/_form.html.erb +141 -0
  17. data/app/views/payola/transactions/iframe.html.erb +2 -0
  18. data/app/views/payola/transactions/new.html.erb +1 -0
  19. data/app/views/payola/transactions/show.html.erb +5 -0
  20. data/app/views/payola/transactions/wait.html.erb +25 -0
  21. data/config/routes.rb +0 -3
  22. data/db/migrate/20141001170138_create_payola_sales.rb +4 -4
  23. data/db/migrate/20141001203541_create_payola_stripe_webhooks.rb +9 -0
  24. data/db/migrate/20141002013618_create_payola_coupons.rb +10 -0
  25. data/db/migrate/20141002013701_create_payola_affiliates.rb +11 -0
  26. data/db/migrate/20141002203725_add_stripe_customer_id_to_sale.rb +6 -0
  27. data/lib/payola.rb +30 -5
  28. data/lib/payola/engine.rb +8 -0
  29. data/lib/payola/version.rb +1 -1
  30. data/lib/payola/worker.rb +22 -4
  31. data/spec/concerns/sellable_spec.rb +32 -0
  32. data/spec/controllers/payola/transactions_controller_spec.rb +7 -0
  33. data/{test → spec}/dummy/README.rdoc +0 -0
  34. data/{test → spec}/dummy/Rakefile +0 -0
  35. data/{test → spec}/dummy/app/assets/javascripts/application.js +1 -0
  36. data/spec/dummy/app/assets/javascripts/buy.js +2 -0
  37. data/{test → spec}/dummy/app/assets/stylesheets/application.css +0 -0
  38. data/spec/dummy/app/assets/stylesheets/buy.css +4 -0
  39. data/{test → spec}/dummy/app/controllers/application_controller.rb +0 -0
  40. data/spec/dummy/app/controllers/buy_controller.rb +7 -0
  41. data/{test → spec}/dummy/app/helpers/application_helper.rb +0 -0
  42. data/spec/dummy/app/helpers/buy_helper.rb +2 -0
  43. data/spec/dummy/app/models/product.rb +7 -0
  44. data/spec/dummy/app/views/buy/index.html.erb +1 -0
  45. data/{test → spec}/dummy/app/views/layouts/application.html.erb +2 -1
  46. data/{test → spec}/dummy/bin/bundle +0 -0
  47. data/{test → spec}/dummy/bin/rails +0 -0
  48. data/{test → spec}/dummy/bin/rake +0 -0
  49. data/{test → spec}/dummy/config.ru +0 -0
  50. data/{test → spec}/dummy/config/application.rb +0 -0
  51. data/{test → spec}/dummy/config/boot.rb +0 -0
  52. data/{test → spec}/dummy/config/database.yml +0 -0
  53. data/{test → spec}/dummy/config/environment.rb +0 -0
  54. data/{test → spec}/dummy/config/environments/development.rb +0 -0
  55. data/{test → spec}/dummy/config/environments/production.rb +0 -0
  56. data/{test → spec}/dummy/config/environments/test.rb +0 -0
  57. data/{test → spec}/dummy/config/initializers/assets.rb +0 -0
  58. data/{test → spec}/dummy/config/initializers/backtrace_silencers.rb +0 -0
  59. data/{test → spec}/dummy/config/initializers/cookies_serializer.rb +0 -0
  60. data/{test → spec}/dummy/config/initializers/filter_parameter_logging.rb +0 -0
  61. data/{test → spec}/dummy/config/initializers/inflections.rb +0 -0
  62. data/{test → spec}/dummy/config/initializers/mime_types.rb +0 -0
  63. data/spec/dummy/config/initializers/payola.rb +5 -0
  64. data/{test → spec}/dummy/config/initializers/session_store.rb +0 -0
  65. data/{test → spec}/dummy/config/initializers/wrap_parameters.rb +0 -0
  66. data/{test → spec}/dummy/config/locales/en.yml +0 -0
  67. data/{test → spec}/dummy/config/routes.rb +1 -1
  68. data/{test → spec}/dummy/config/secrets.yml +0 -0
  69. data/spec/dummy/db/development.sqlite3 +0 -0
  70. data/spec/dummy/db/migrate/20141001230848_create_products.rb +11 -0
  71. data/spec/dummy/db/schema.rb +76 -0
  72. data/spec/dummy/db/test.sqlite3 +0 -0
  73. data/spec/dummy/log/development.log +7452 -0
  74. data/spec/dummy/log/test.log +9849 -0
  75. data/{test → spec}/dummy/public/404.html +0 -0
  76. data/{test → spec}/dummy/public/422.html +0 -0
  77. data/{test → spec}/dummy/public/500.html +0 -0
  78. data/{test → spec}/dummy/public/favicon.ico +0 -0
  79. data/spec/dummy/spec/controllers/buy_controller_spec.rb +5 -0
  80. data/spec/dummy/spec/factories/products.rb +9 -0
  81. data/spec/dummy/tmp/cache/assets/development/sprockets/0e585aeb88c1555ae8f5292f7c7a9068 +0 -0
  82. data/spec/dummy/tmp/cache/assets/development/sprockets/0f0c99469c51f1b2d76b08f481781d09 +0 -0
  83. data/spec/dummy/tmp/cache/assets/development/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
  84. data/spec/dummy/tmp/cache/assets/development/sprockets/1b54952339cbc96811097cee5f8923b4 +0 -0
  85. data/spec/dummy/tmp/cache/assets/development/sprockets/1cbc4f4790f2067a2c161c1eb480f276 +0 -0
  86. data/spec/dummy/tmp/cache/assets/development/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
  87. data/spec/dummy/tmp/cache/assets/development/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
  88. data/spec/dummy/tmp/cache/assets/development/sprockets/5afa4bc970e0bc781b3500c696ba25ff +0 -0
  89. data/spec/dummy/tmp/cache/assets/development/sprockets/664efeb51d1b486dcfc30d142db56f3c +0 -0
  90. data/spec/dummy/tmp/cache/assets/development/sprockets/68a3bbdc64a0729b5896fa1e33fce4b1 +0 -0
  91. data/spec/dummy/tmp/cache/assets/development/sprockets/aea159adbc0944b120d91d5b578612ba +0 -0
  92. data/spec/dummy/tmp/cache/assets/development/sprockets/b83da90cb58011313e13a97a4a41cb6e +0 -0
  93. data/spec/dummy/tmp/cache/assets/development/sprockets/c0b954b40f2881a6d286061bc069643e +0 -0
  94. data/spec/dummy/tmp/cache/assets/development/sprockets/c5b3877d49b39932a7557611cefca9a6 +0 -0
  95. data/spec/dummy/tmp/cache/assets/development/sprockets/ca491e325ff6948be9292f701aa4ce64 +0 -0
  96. data/spec/dummy/tmp/cache/assets/development/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
  97. data/spec/dummy/tmp/cache/assets/development/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
  98. data/spec/dummy/tmp/cache/assets/development/sprockets/d9856638a3c7b9cfd9d1b884e3b33982 +0 -0
  99. data/spec/dummy/tmp/cache/assets/development/sprockets/ddba6e841f28d3005e828fbfffd18b74 +0 -0
  100. data/spec/dummy/tmp/cache/assets/development/sprockets/df935e399019055729aa968bd7062096 +0 -0
  101. data/spec/dummy/tmp/cache/assets/development/sprockets/ef82c31948061751bb026663b54484e1 +0 -0
  102. data/spec/dummy/tmp/cache/assets/development/sprockets/f0b5d4bea0c6cdd1904e1e9a0a45532f +0 -0
  103. data/spec/dummy/tmp/cache/assets/development/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
  104. data/spec/dummy/tmp/cache/assets/development/sprockets/f8018075b7aca72974f4014bbbc75ab5 +0 -0
  105. data/spec/factories/payola_affiliates.rb +9 -0
  106. data/spec/factories/payola_coupons.rb +8 -0
  107. data/spec/factories/product.rb +7 -0
  108. data/spec/factories/sales.rb +7 -0
  109. data/spec/models/payola/sale_spec.rb +71 -0
  110. data/spec/models/payola/stripe_webhook_spec.rb +17 -0
  111. data/spec/payola_spec.rb +93 -0
  112. data/spec/services/payola/charge_card_spec.rb +37 -0
  113. data/spec/services/payola/create_sale_spec.rb +64 -0
  114. data/spec/spec_helper.rb +73 -0
  115. data/spec/worker_spec.rb +36 -0
  116. metadata +275 -81
  117. data/test/fixtures/payola/sales.yml +0 -11
  118. data/test/integration/navigation_test.rb +0 -10
  119. data/test/models/payola/sale_test.rb +0 -9
  120. data/test/payola_test.rb +0 -7
  121. data/test/test_helper.rb +0 -15
@@ -0,0 +1,141 @@
1
+ <div class="well payment-well" style="margin-bottom: 0px;">
2
+ <%= form_tag payola.buy_path(product_class: sale.product.product_class, permalink: permalink), :class => '', :id => 'payment-form' do %>
3
+ <% if coupon %>
4
+ <input type="hidden" name="coupon_code" value="<%= coupon.code %>" />
5
+ <% end %>
6
+ <div class="row">
7
+ <label class="control-label" for="email">Email Address <span class="label pull-right" style="margin-right: 8px">Secure <img src="<%= asset_path('lock.png') %>" style="height: 13px"></span></label>
8
+ <input autofocus="true" type="email" name="email" id="email" placeholder="you@example.com" class="payment-input"/>
9
+ </div>
10
+ <div class="row">
11
+ <label class="control-label" for="number">Card Number <span class="pull-right" style="margin-right: 8px"><img src="<%= asset_path('visa.png') %>" style="height: 15px;"><img src="<%= asset_path('mastercard.png') %>" style="height: 15px;"><img src="<%= asset_path('amex.png') %>" style="height: 15px;"><img src="<%= asset_path('discover.png') %>" style="height: 15px;"></span></label>
12
+ <input type="text" size="20" data-stripe="number" id="number" placeholder="1234 5678 9012 3456" pattern="[\d ]*" class="payment-input"/>
13
+ </div>
14
+ <div class="row">
15
+ <div style="float: left">
16
+ <label class="control-label" for="cvc">CV Code</label>
17
+ <input type="text" style="width: 3em" size="3" data-stripe="cvc" id="cvc" placeholder="123" pattern="\d*"/>
18
+ <img id="card-image" src="<%= asset_path('credit.png') %>" style="height: 30px; padding-left: 10px; margin-top: -10px">
19
+ </div>
20
+ <div style="float: right; margin-right: 8px">
21
+ <label class="control-label">Expiry Date</label>
22
+ <input style="width: 2em" type="text" size="2" id="exp-month" data-stripe="exp-month" placeholder="MM" pattern="\d*"/>
23
+ <span> / </span>
24
+ <input style="width: 3em" type="text" size="4" id="exp-year" data-stripe="exp-year" placeholder="YYYY" pattern="\d*"/>
25
+ </div>
26
+ </div>
27
+ <div class="row" style="margin-top: 20px">
28
+ <div class="price" style="margin-top: 20px; float: left"><%= price %></div>
29
+ <div style="float: right; margin-right: 8px;text-align:center">
30
+ <div class="btn btn-success btn-large" disabled="disabled" style="display: none; width: 70px; height: 20px;" id="spinner-button"><img src="<%= asset_path('green_spinner_2.gif') %>" style="height: 15px;"></div>
31
+ <button type="submit" class="btn btn-success btn-large" id="pay-button">Pay Now</button><br>
32
+ </div>
33
+ </div>
34
+ <% end %>
35
+ </div>
36
+ <div class="payment-well" style="margin-top: 0px; margin-bottom: 0px;">
37
+ <div class="row">
38
+ <div id="powered-by-stripe" style="<%= sale.errors.any? ? 'display: none;' : '' %> margin-left: auto; margin-right: auto; text-align: center; margin-top: 15px;">
39
+ <img src="<%= asset_path('powered_by_stripe.png') %>">
40
+ </div>
41
+ <div id="payment-errors" class="alert payment-alert" style="<%= sale.errors.any? ? '' : 'display: none;' %> margin-bottom: 0px;">
42
+ <% sale.errors.full_messages.each do |msg| %>
43
+ <span><%= msg %></span>
44
+ <% end %>
45
+ </div>
46
+ </div>
47
+ </div>
48
+ <script type="text/javascript" src="https://js.stripe.com/v2/"></script>
49
+ <script type="text/javascript">
50
+ $(function(){
51
+
52
+ Stripe.setPublishableKey('<%= stripe_key %>');
53
+
54
+ $('#number').payment('formatCardNumber');
55
+ $('#cvc').payment('formatCardCVC');
56
+ $('#exp-month').payment('restrictNumeric');
57
+ $('#exp-year').payment('restrictNumeric');
58
+ $('#number').keyup(function(event) {
59
+ var number = $('#number').val();
60
+ var cardType = $.payment.cardType(number);
61
+ var img = $('#card-image')[0];
62
+ if (cardType === 'visa') {
63
+ $('#cvc').attr("placeholder", "123");
64
+ img.src = "<%= asset_path('visa.png') %>";
65
+ } else if (cardType === 'mastercard') {
66
+ $('#cvc').attr("placeholder", "123");
67
+ img.src = "<%= asset_path('mastercard.png') %>";
68
+ } else if (cardType === 'discover') {
69
+ $('#cvc').attr("placeholder", "123");
70
+ img.src = "<%= asset_path('discover.png') %>";
71
+ } else if (cardType === 'amex') {
72
+ $('#cvc').attr("placeholder", "1234");
73
+ img.src = "<%= asset_path('amex.png') %>";
74
+ } else if (cardType === 'dinersclub') {
75
+ $('#cvc').attr("placeholder", "123");
76
+ img.src = "<%= asset_path('diners.png') %>";
77
+ } else if (cardType === 'maestro') {
78
+ $('#cvc').attr("placeholder", "123");
79
+ img.src = "<%= asset_path('maestro.png') %>";
80
+ } else if (cardType === 'laser') {
81
+ $('#cvc').attr("placeholder", "123");
82
+ img.src = "<%= asset_path('laser.png') %>";
83
+ } else {
84
+ $('#cvc').attr("placeholder", "123");
85
+ img.src = "<%= asset_path('credit.png')%>";
86
+ }
87
+ });
88
+
89
+ $('#payment-form').submit(function(event) {
90
+ var form = $(this);
91
+ form.find('button').prop('disabled', true);
92
+ Stripe.createToken(form, stripeResponseHandler);
93
+ $('#pay-button').hide();
94
+ $('#spinner-button').show();
95
+ $('#pay-button').prop('disabled', false);
96
+ return false;
97
+ });
98
+
99
+ function stripeResponseHandler(status, response) {
100
+ var form = $('#payment-form');
101
+ if (response.error) {
102
+ showError(response.error.message);
103
+ } else {
104
+ var token = response.id;
105
+ form.append($('<input type="hidden" name="stripeToken">').val(token));
106
+ $.ajax({
107
+ type: "POST",
108
+ url: "<%= payola.buy_url(product_class: sale.product.product_class, permalink: sale.product.permalink) %>",
109
+ data: $('#payment-form').serialize(),
110
+ success: function(data) { poll(data.guid, 60) },
111
+ error: function(data) { showError(data.responseJSON.error) }
112
+ });
113
+ }
114
+ }
115
+
116
+ function showError(error) {
117
+ var form = $('#payment-form');
118
+ $('#payment-errors').html(error);
119
+ $('#payment-errors').show();
120
+ $('#pay-button').show();
121
+ $('#powered-by-stripe').hide();
122
+ $('#spinner-button').hide();
123
+ }
124
+
125
+ function poll(guid, num_retries_left) {
126
+ if (num_retries_left == 0) {
127
+ showError("This seems to be taking too long. Email <a href=\"mailto:<%= Payola.support_email %>\"><%= Payola.support_email %></a> and reference transaction <strong>" + guid + "</strong>.");
128
+ return;
129
+ }
130
+ $.get("/payola/status/" + guid, function(data) {
131
+ if (data.status === "finished") {
132
+ window.location = "/payola/confirm/" + guid;
133
+ } else if (data.status === "errored") {
134
+ showError(data.error)
135
+ } else {
136
+ setTimeout(function() { poll(guid, num_retries_left - 1) }, 500);
137
+ }
138
+ });
139
+ }
140
+ });
141
+ </script>
@@ -0,0 +1,2 @@
1
+ <%= render 'form', :username => @product.user.username, stripe_key: @product.user.stripe_publishable_key, :permalink => @product.permalink, :sale => @sale, :price => formatted_price(@price), :coupon => @coupon %>
2
+
@@ -0,0 +1 @@
1
+ <%= render 'form', stripe_key: Payola.publishable_key, permalink: @product.permalink, sale: @sale, price: formatted_price(@price), coupon: @coupon %>
@@ -0,0 +1,5 @@
1
+ <h1>Thanks!</h1>
2
+
3
+ <p>Thanks for buying "<%= @product.name %>". You'll receive an email shortly with your receipt and download link.</p>
4
+
5
+
@@ -0,0 +1,25 @@
1
+ Please wait...
2
+
3
+ <div id="errors" style="display:none;"></div>
4
+
5
+ <script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
6
+
7
+ <script type="text/javascript">
8
+ $(function() {
9
+ function poll(guid, num_retries_left) {
10
+ if (num_retries_left == 0) {
11
+ $('#errors').html('Taking too long...');
12
+ }
13
+ $.get("/payola/status/" + guid, function(data) {
14
+ if (data.status === "finished") {
15
+ window.location = "/payola/confirm/" + guid;
16
+ } else if (data.status === "errored") {
17
+ $('#errors').html(data.error)
18
+ } else {
19
+ setTimeout(function() { poll(guid, num_retries_left - 1) }, 500);
20
+ }
21
+ });
22
+ }
23
+ poll("<%= @guid %>", 60);
24
+ });
25
+ </script>
data/config/routes.rb CHANGED
@@ -1,9 +1,6 @@
1
1
  Payola::Engine.routes.draw do
2
- match '/buy/:product_class/:permalink' => 'transactions#new', via: :get, as: :show_buy
3
2
  match '/buy/:product_class/:permalink' => 'transactions#create', via: :post, as: :buy
4
3
  match '/confirm/:guid' => 'transactions#show', via: :get, as: :confirm
5
- match '/pickup/:guid' => 'transactions#pickup', via: :get, as: :pickup
6
- match '/iframe/:username/:permalink' => 'transactions#iframe', via: :get, as: :buy_iframe
7
4
  match '/status/:guid' => 'transactions#status', via: :get, as: :status
8
5
 
9
6
  mount StripeEvent::Engine => '/events'
@@ -25,9 +25,9 @@ class CreatePayolaSales < ActiveRecord::Migration
25
25
  t.timestamps
26
26
  end
27
27
 
28
- add_index "sales", ["coupon_id"], name: "index_sales_on_coupon_id", using: :btree
29
- add_index "sales", ["product_id", "product_type"], name: "index_sales_on_product", using: :btree
30
- add_index "sales", ["email"], name: "index_sales_on_email", using: :btree
31
- add_index "sales", ["guid"], name: "index_sales_on_guid", using: :btree
28
+ add_index "payola_sales", ["coupon_id"], name: "index_payola_sales_on_coupon_id", using: :btree
29
+ add_index "payola_sales", ["product_id", "product_type"], name: "index_payola_sales_on_product", using: :btree
30
+ add_index "payola_sales", ["email"], name: "index_payola_sales_on_email", using: :btree
31
+ add_index "payola_sales", ["guid"], name: "index_payola_sales_on_guid", using: :btree
32
32
  end
33
33
  end
@@ -0,0 +1,9 @@
1
+ class CreatePayolaStripeWebhooks < ActiveRecord::Migration
2
+ def change
3
+ create_table :payola_stripe_webhooks do |t|
4
+ t.string :stripe_id
5
+
6
+ t.timestamps
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,10 @@
1
+ class CreatePayolaCoupons < ActiveRecord::Migration
2
+ def change
3
+ create_table :payola_coupons do |t|
4
+ t.string :code
5
+ t.integer :percent_off
6
+
7
+ t.timestamps
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,11 @@
1
+ class CreatePayolaAffiliates < ActiveRecord::Migration
2
+ def change
3
+ create_table :payola_affiliates do |t|
4
+ t.string :code
5
+ t.string :email
6
+ t.integer :percent
7
+
8
+ t.timestamps
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,6 @@
1
+ class AddStripeCustomerIdToSale < ActiveRecord::Migration
2
+ def change
3
+ add_column :payola_sales, :stripe_customer_id, :string
4
+ add_index :payola_sales, :stripe_customer_id
5
+ end
6
+ end
data/lib/payola.rb CHANGED
@@ -1,9 +1,11 @@
1
1
  require "payola/engine"
2
2
  require "payola/worker"
3
+ require 'stripe_event'
4
+ require 'jquery-rails'
3
5
 
4
6
  module Payola
5
7
  class << self
6
- attr_accessor :publishable_key, :secret_key, :secret_key_retriever, :background_worker
8
+ attr_accessor :publishable_key, :secret_key, :secret_key_retriever, :background_worker, :event_filter, :support_email, :sellables
7
9
 
8
10
  def configure(&block)
9
11
  raise ArgumentError, "must provide a block" unless block_given?
@@ -28,16 +30,39 @@ module Payola
28
30
 
29
31
  def queue!(sale)
30
32
  if background_worker.is_a? Symbol
31
- Payola::Worker.find(:symbol).call(sale)
33
+ Payola::Worker.find(background_worker).call(sale)
32
34
  elsif background_worker.respond_to?(:call)
33
35
  background_worker.call(sale)
34
36
  else
35
37
  Payola::Worker.autofind.call(sale)
36
38
  end
37
39
  end
40
+
41
+ def reset!
42
+ StripeEvent.event_retriever = Retriever
43
+
44
+ self.background_worker = nil
45
+ self.event_filter = lambda { |event| event }
46
+ self.publishable_key = ENV['STRIPE_PUBLISHABLE_KEY']
47
+ self.secret_key = ENV['STRIPE_SECRET_KEY']
48
+ self.secret_key_retriever = lambda { |sale| Payola.secret_key }
49
+ self.support_email = 'sales@example.com'
50
+ self.sellables = {}
51
+ end
52
+
53
+ def register_sellable(klass)
54
+ sellables[klass.product_class] = klass
55
+ end
56
+ end
57
+
58
+ class Retriever
59
+ def self.call(params)
60
+ return nil if StripeWebhook.exists?(stripe_id: params[:id])
61
+ StripeWebhook.create!(stripe_id: params[:id])
62
+ event = Stripe::Event.retrieve(params[:id])
63
+ Payola.event_filter(event)
64
+ end
38
65
  end
39
66
 
40
- self.publishable_key = ENV['STIRPE_PUBLISHABLE_KEY']
41
- self.secret_key = ENV['STRIPE_SECRET_KEY']
42
- self.secret_key_retriever = lambda { |sale| Payola.secret_key }
67
+ self.reset!
43
68
  end
data/lib/payola/engine.rb CHANGED
@@ -1,5 +1,13 @@
1
1
  module Payola
2
2
  class Engine < ::Rails::Engine
3
3
  isolate_namespace Payola
4
+ engine_name 'payola'
5
+
6
+ config.generators do |g|
7
+ g.test_framework :rspec, fixture: false
8
+ g.fixture_replacement :factory_girl, dir: 'spec/factories'
9
+ g.assets false
10
+ g.helper false
11
+ end
4
12
  end
5
13
  end
@@ -1,3 +1,3 @@
1
1
  module Payola
2
- VERSION = "0.0.1"
2
+ VERSION = "0.1.0"
3
3
  end
data/lib/payola/worker.rb CHANGED
@@ -4,7 +4,7 @@ module Payola
4
4
  attr_accessor :registry
5
5
 
6
6
  def find(symbol)
7
- if registry.has_key? symobl
7
+ if registry.has_key? symbol
8
8
  return registry[symbol]
9
9
  else
10
10
  raise "No such worker type: #{symbol}"
@@ -22,7 +22,13 @@ module Payola
22
22
  end
23
23
  end
24
24
 
25
- class Sidekiq
25
+ class BaseWorker
26
+ def perform(guid)
27
+ Sale.where(guid: guid).first.process!
28
+ end
29
+ end
30
+
31
+ class Sidekiq < BaseWorker
26
32
  def self.can_run?
27
33
  defined?(::Sidekiq::Worker)
28
34
  end
@@ -33,8 +39,20 @@ module Payola
33
39
  end
34
40
  end
35
41
 
36
- registry = {
37
- sidekiq: Payola::Worker::Sidekiq
42
+ class SuckerPunch < BaseWorker
43
+ def self.can_run?
44
+ defined?(::SuckerPunch::Job)
45
+ end
46
+
47
+ def self.call(sale)
48
+ self.send(:include, ::SuckerPunch::Job)
49
+ self.new.async.perform(sale.guid)
50
+ end
51
+ end
52
+
53
+ self.registry = {
54
+ sidekiq: Payola::Worker::Sidekiq,
55
+ sucker_punch: Payola::Worker::SuckerPunch
38
56
  }
39
57
  end
40
58
  end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ module Payola
4
+ describe Sellable do
5
+ describe "validations" do
6
+ it "should validate" do
7
+ product = build(:product)
8
+ expect(product.valid?).to be true
9
+ end
10
+ it "should validate name" do
11
+ product = build(:product, name: nil)
12
+ expect(product.valid?).to be false
13
+ end
14
+ it "should validate permalink" do
15
+ product = build(:product, permalink: false)
16
+ expect(product.valid?).to be false
17
+ end
18
+ end
19
+
20
+ describe "#product_class" do
21
+ it "should return the underscore'd version of the class" do
22
+ expect(build(:product).product_class).to eq 'product'
23
+ end
24
+ end
25
+
26
+ describe "#sellable?" do
27
+ it "should return true" do
28
+ expect(Product.sellable?).to be true
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ module Payola
4
+ describe TransactionsController do
5
+
6
+ end
7
+ end
File without changes
File without changes
@@ -11,3 +11,4 @@
11
11
  // about supported directives.
12
12
  //
13
13
  //= require_tree .
14
+ //= require payola
@@ -0,0 +1,2 @@
1
+ // Place all the behaviors and hooks related to the matching controller here.
2
+ // All this logic will automatically be available in application.js.
@@ -0,0 +1,4 @@
1
+ /*
2
+ Place all the styles related to the matching controller here.
3
+ They will automatically be included in application.css.
4
+ */