workarea-cyber_source 1.0.3
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/.editorconfig +20 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +37 -0
- data/.github/ISSUE_TEMPLATE/documentation-request.md +17 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
- data/.gitignore +14 -0
- data/.rails-rubocop.yml +140 -0
- data/.rubocop.yml +8 -0
- data/CHANGELOG.md +39 -0
- data/CODE_OF_CONDUCT.md +3 -0
- data/CONTRIBUTING.md +3 -0
- data/Gemfile +11 -0
- data/LICENSE +52 -0
- data/README.md +27 -0
- data/Rakefile +59 -0
- data/app/models/workarea/payment/authorize/credit_card.decorator +45 -0
- data/app/models/workarea/payment/capture/credit_card.decorator +14 -0
- data/app/models/workarea/payment/purchase/credit_card.decorator +48 -0
- data/app/models/workarea/payment/refund/credit_card.decorator +14 -0
- data/app/models/workarea/payment/store_credit_card.decorator +13 -0
- data/bin/rails +20 -0
- data/config/initializers/gateway.rb +1 -0
- data/lib/active_merchant/billing/bogus_cyber_source_gateway.rb +97 -0
- data/lib/active_merchant/billing/cyber_source_fix.rb +34 -0
- data/lib/workarea/cyber_source.rb +36 -0
- data/lib/workarea/cyber_source/engine.rb +8 -0
- data/lib/workarea/cyber_source/version.rb +5 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/bin/setup +38 -0
- data/test/dummy/bin/update +29 -0
- data/test/dummy/bin/yarn +11 -0
- data/test/dummy/config.ru +5 -0
- data/test/dummy/config/application.rb +28 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/cable.yml +10 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +56 -0
- data/test/dummy/config/environments/production.rb +91 -0
- data/test/dummy/config/environments/test.rb +44 -0
- data/test/dummy/config/initializers/application_controller_renderer.rb +8 -0
- data/test/dummy/config/initializers/assets.rb +14 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/cookies_serializer.rb +5 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +4 -0
- data/test/dummy/config/initializers/workarea.rb +5 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +33 -0
- data/test/dummy/config/puma.rb +56 -0
- data/test/dummy/config/routes.rb +5 -0
- data/test/dummy/config/secrets.yml +32 -0
- data/test/dummy/config/spring.rb +6 -0
- data/test/dummy/db/seeds.rb +2 -0
- data/test/dummy/log/.keep +0 -0
- data/test/dummy/package.json +5 -0
- data/test/integration/workarea/cyber_source_integration_test.rb +191 -0
- data/test/models/workarea/payment/authorize/credit_card_test.decorator +68 -0
- data/test/models/workarea/payment/capture/credit_card_test.decorator +17 -0
- data/test/models/workarea/payment/purchase/credit_card_test.decorator +60 -0
- data/test/models/workarea/payment/refund/credit_card_test.decorator +17 -0
- data/test/models/workarea/payment/store_credit_card_test.decorator +15 -0
- data/test/support/workarea/cyber_source_support_vcr_config.rb +23 -0
- data/test/support/workarea/workarea_3_2_backports.rb +57 -0
- data/test/teaspoon_env.rb +6 -0
- data/test/test_helper.rb +11 -0
- data/test/vcr_cassettes/cyber_source/auth_capture.yml +254 -0
- data/test/vcr_cassettes/cyber_source/auth_capture_refund.yml +323 -0
- data/test/vcr_cassettes/cyber_source/auth_void.yml +250 -0
- data/test/vcr_cassettes/cyber_source/purchase_refund.yml +251 -0
- data/test/vcr_cassettes/cyber_source/purchase_void.yml +247 -0
- data/test/vcr_cassettes/cyber_source/store_auth.yml +179 -0
- data/test/vcr_cassettes/cyber_source/store_purchase.yml +180 -0
- data/workarea-cyber_source.gemspec +19 -0
- metadata +133 -0
@@ -0,0 +1,45 @@
|
|
1
|
+
module Workarea
|
2
|
+
decorate Payment::Authorize::CreditCard, with: :cyber_source do
|
3
|
+
decorated { delegate :address, to: :tender }
|
4
|
+
|
5
|
+
def initialize(tender, transaction, options = {})
|
6
|
+
super
|
7
|
+
@options = @options.merge(
|
8
|
+
email: email,
|
9
|
+
billing_address: billing_address,
|
10
|
+
order_id: order_id
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
def complete!
|
15
|
+
return unless Payment::StoreCreditCard.new(tender, options).save!
|
16
|
+
|
17
|
+
transaction.response = handle_active_merchant_errors do
|
18
|
+
gateway.authorize(transaction.amount.cents, tender.token, options)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def order_id
|
25
|
+
tender.payment.id
|
26
|
+
end
|
27
|
+
|
28
|
+
def email
|
29
|
+
return unless tender.profile.present?
|
30
|
+
|
31
|
+
tender.profile.email
|
32
|
+
end
|
33
|
+
|
34
|
+
def billing_address
|
35
|
+
{
|
36
|
+
address1: address.street,
|
37
|
+
address2: address.street_2,
|
38
|
+
city: address.city,
|
39
|
+
state: address.region,
|
40
|
+
country: address.country.try(:alpha2),
|
41
|
+
zip: address.postal_code
|
42
|
+
}
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Workarea
|
2
|
+
decorate Payment::Capture::CreditCard, with: :cyber_source do
|
3
|
+
def complete!
|
4
|
+
validate_reference!
|
5
|
+
|
6
|
+
transaction.response = handle_active_merchant_errors do
|
7
|
+
gateway.capture(
|
8
|
+
transaction.amount.cents,
|
9
|
+
transaction.reference.response.authorization
|
10
|
+
)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Workarea
|
2
|
+
decorate Payment::Purchase::CreditCard, with: :cyber_source do
|
3
|
+
decorated { delegate :address, to: :tender }
|
4
|
+
|
5
|
+
def initialize(tender, transaction, options = {})
|
6
|
+
super
|
7
|
+
@options = @options.merge(
|
8
|
+
email: email,
|
9
|
+
billing_address: billing_address,
|
10
|
+
order_id: order_id
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
def complete!
|
15
|
+
return unless Payment::StoreCreditCard.new(tender, options).save!
|
16
|
+
|
17
|
+
transaction.response = handle_active_merchant_errors do
|
18
|
+
gateway.purchase(transaction.amount.cents, tender.token, options)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def order_id
|
25
|
+
tender.payment.id
|
26
|
+
end
|
27
|
+
|
28
|
+
def email
|
29
|
+
return unless tender.profile.present?
|
30
|
+
|
31
|
+
tender.profile.email
|
32
|
+
end
|
33
|
+
|
34
|
+
def billing_address
|
35
|
+
{
|
36
|
+
name: nil,
|
37
|
+
company: nil,
|
38
|
+
address1: address.street,
|
39
|
+
address2: address.street_2,
|
40
|
+
city: address.city,
|
41
|
+
state: address.region,
|
42
|
+
country: address.country.try(:alpha2),
|
43
|
+
zip: address.postal_code,
|
44
|
+
phone: nil
|
45
|
+
}
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Workarea
|
2
|
+
decorate Payment::Refund::CreditCard, with: :cyber_source do
|
3
|
+
def complete!
|
4
|
+
validate_reference!
|
5
|
+
|
6
|
+
transaction.response = handle_active_merchant_errors do
|
7
|
+
gateway.refund(
|
8
|
+
transaction.amount.cents,
|
9
|
+
transaction.reference.response.authorization
|
10
|
+
)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Workarea
|
2
|
+
decorate Payment::StoreCreditCard, with: :cyber_source do
|
3
|
+
def perform!
|
4
|
+
return true if @credit_card.token.present?
|
5
|
+
|
6
|
+
response = handle_active_merchant_errors do
|
7
|
+
gateway.store(@credit_card.to_active_merchant, @options)
|
8
|
+
end
|
9
|
+
|
10
|
+
@credit_card.token = response.authorization
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
data/bin/rails
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# This command will automatically be run when you run "rails" with Rails gems
|
3
|
+
# installed from the root of your application.
|
4
|
+
|
5
|
+
ENGINE_ROOT = File.expand_path("../..", __FILE__)
|
6
|
+
ENGINE_PATH = File.expand_path("../../lib/workarea/cyber_source/engine", __FILE__)
|
7
|
+
APP_PATH = File.expand_path("../../test/dummy/config/application", __FILE__)
|
8
|
+
|
9
|
+
# Set up gems listed in the Gemfile.
|
10
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", __FILE__)
|
11
|
+
require "bundler/setup" if File.exist?(ENV["BUNDLE_GEMFILE"])
|
12
|
+
|
13
|
+
require "action_controller/railtie"
|
14
|
+
require "action_view/railtie"
|
15
|
+
require "action_mailer/railtie"
|
16
|
+
require "rails/test_unit/railtie"
|
17
|
+
require "sprockets/railtie"
|
18
|
+
require "teaspoon-mocha"
|
19
|
+
|
20
|
+
require "rails/engine/commands"
|
@@ -0,0 +1 @@
|
|
1
|
+
Workarea::CyberSource.auto_configure_gateway
|
@@ -0,0 +1,97 @@
|
|
1
|
+
module ActiveMerchant
|
2
|
+
module Billing
|
3
|
+
class BogusCyberSourceGateway < BogusGateway
|
4
|
+
def store(paysource, options = {})
|
5
|
+
authorization = ";5118839074516426404010;Ahj/7wSTFX4pmYA85bCqKhDdq4ZOWjNklxakXpGAKXFqRekZpABykhk0kyro9JiuKBOTFX4pmYA85bCqAAAA5wQ4;store;;;5118839074516426404010"
|
6
|
+
case normalize(paysource)
|
7
|
+
when /1$/
|
8
|
+
Response.new(true, SUCCESS_MESSAGE, { billingid: "1" }, { test: true, authorization: authorization })
|
9
|
+
when /2$/
|
10
|
+
Response.new(false, FAILURE_MESSAGE, { billingid: nil, error: FAILURE_MESSAGE }, { test: true, error_code: STANDARD_ERROR_CODE[:processing_error] })
|
11
|
+
else
|
12
|
+
raise Error, error_message(paysource)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def authorize(money, credit_card_or_subscription, options = {})
|
17
|
+
case normalize(credit_card_or_subscription)
|
18
|
+
when /1$/, "5118839074516426404010"
|
19
|
+
succuessful_auth_response
|
20
|
+
when /2$/
|
21
|
+
Response.new(false, FAILURE_MESSAGE, { authorized_amount: money, error: FAILURE_MESSAGE }, { test: true, error_code: STANDARD_ERROR_CODE[:processing_error] })
|
22
|
+
else
|
23
|
+
raise Error, error_message(credit_card_or_subscription)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def purchase(money, credit_card_or_subscription, options = {})
|
28
|
+
case normalize(credit_card_or_subscription)
|
29
|
+
when /1$/, "5118839074516426404010"
|
30
|
+
succuessful_purchase_response
|
31
|
+
when /2$/
|
32
|
+
Response.new(false, FAILURE_MESSAGE, { authorized_amount: money, error: FAILURE_MESSAGE }, { test: true, error_code: STANDARD_ERROR_CODE[:processing_error] })
|
33
|
+
else
|
34
|
+
raise Error, error_message(credit_card_or_subscription)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def normalize(paysource)
|
41
|
+
if paysource.respond_to?(:account_number) && (paysource.try(:number).blank? || paysource.number.blank?)
|
42
|
+
paysource.account_number
|
43
|
+
elsif paysource.respond_to?(:number)
|
44
|
+
paysource.number.split(";")[6] || paysource.number
|
45
|
+
else
|
46
|
+
paysource.to_s.split(";")[6] || paysource.to_s
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def succuessful_auth_response
|
51
|
+
authorization = "5a216efd87c68b548a1856df;5118839077736067504008;Ahj/7wSTFX4pnG3edheIKhDdq4ZOWbVqlwethj1gKXB62GPXpAn6OUkMmkmVdHpMVxQJyYq/FM427zsLxAAA6xxJ;authorize;500;;"
|
52
|
+
params = {
|
53
|
+
"merchantReferenceCode" => "5a1d848387c68b268bf205f9",
|
54
|
+
"requestID" => "5118839077736067504008",
|
55
|
+
"decision" => "ACCEPT",
|
56
|
+
"reasonCode" => "100",
|
57
|
+
"message" => "Successful transaction",
|
58
|
+
"requestToken" => "Ahj/7wSTFX4pnG3edheIKhDdq4ZOWbVqlwethj1gKXB62GPXpAn6OUkMmkmVdHpMVxQJyYq/FM427zsLxAAA6xxJ",
|
59
|
+
"currency" => "USD",
|
60
|
+
"amount" => "5.00",
|
61
|
+
"authorizationCode" => "831000",
|
62
|
+
"avsCode" => "Y",
|
63
|
+
"avsCodeRaw" => "Y",
|
64
|
+
"authorizedDateTime" => "2017-11-28T15:45:07Z",
|
65
|
+
"processorResponse" => "000",
|
66
|
+
"paymentNetworkTransactionID" => "558196000003814",
|
67
|
+
"cardCategory" => "A",
|
68
|
+
"ownerMerchantID" => "weblinc"
|
69
|
+
}
|
70
|
+
Response.new(true, SUCCESS_MESSAGE, params, test: true, authorization: authorization)
|
71
|
+
end
|
72
|
+
|
73
|
+
def succuessful_purchase_response
|
74
|
+
authorization = "5a609ec187c68b520db767eb;5161970476206134104008;Ahj//wSTF9S7HtFYm4/IESDdm1ZtGbZvKhyKjhnKtJcl3RY7YClyXdFjt6QJ+j6jDJpJl6MVzT24YE5MX1Lse0Vibj8g0UyQ;purchase;500;;"
|
75
|
+
params = {
|
76
|
+
"merchantReferenceCode" => "5a5f54b787c68be6e7c6a553",
|
77
|
+
"requestID" => "5161970476206134104008",
|
78
|
+
"decision" => "ACCEPT",
|
79
|
+
"reasonCode" => "100",
|
80
|
+
"message" => "Successful transaction",
|
81
|
+
"requestToken" => "Ahj//wSTF9S7HtFYm4/IESDdm1ZtGbZvKhyKjhnKtJcl3RY7YClyXdFjt6QJ+j6jDJpJl6MVzT24YE5MX1Lse0Vibj8g0UyQ",
|
82
|
+
"currency" => "USD",
|
83
|
+
"amount" => "5.00",
|
84
|
+
"authorizationCode" => "888888",
|
85
|
+
"avsCode" => "X",
|
86
|
+
"avsCodeRaw" => "I1",
|
87
|
+
"authorizedDateTime" => "2018-01-17T13:50:47Z",
|
88
|
+
"processorResponse" => "100",
|
89
|
+
"reconciliationID" => "73534367JCHT83JZ",
|
90
|
+
"ownerMerchantID" => "a",
|
91
|
+
"requestDateTime" => "2018-01-17T13:50:47Z"
|
92
|
+
}
|
93
|
+
Response.new(true, SUCCESS_MESSAGE, params, test: true, authorization: authorization)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
ActiveMerchant::Billing::CyberSourceGateway.class_eval do
|
2
|
+
def add_payment_method_or_subscription(xml, money, payment_method_or_reference, options)
|
3
|
+
if payment_method_or_reference.is_a?(String)
|
4
|
+
add_address(xml, nil, options[:billing_address], options)
|
5
|
+
add_purchase_data(xml, money, true, options)
|
6
|
+
add_subscription(xml, options, payment_method_or_reference)
|
7
|
+
elsif card_brand(payment_method_or_reference) == 'check'
|
8
|
+
add_address(xml, payment_method_or_reference, options[:billing_address], options)
|
9
|
+
add_purchase_data(xml, money, true, options)
|
10
|
+
add_check(xml, payment_method_or_reference)
|
11
|
+
else
|
12
|
+
add_address(xml, payment_method_or_reference, options[:billing_address], options)
|
13
|
+
add_address(xml, payment_method_or_reference, options[:shipping_address], options, true)
|
14
|
+
add_purchase_data(xml, money, true, options)
|
15
|
+
add_creditcard(xml, payment_method_or_reference)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def build_void_request(identification, options)
|
20
|
+
order_id, request_id, request_token, action, money, currency = identification.split(";")
|
21
|
+
options[:order_id] = order_id
|
22
|
+
|
23
|
+
xml = Builder::XmlMarkup.new :indent => 2
|
24
|
+
# normal active merchant only has if capture, but purchases should be the same as captures
|
25
|
+
# a pr was submited to active merchant, remove this if it ever gets mergex / fixed upstream
|
26
|
+
if action == "capture" || action == "purchase"
|
27
|
+
add_void_service(xml, request_id, request_token)
|
28
|
+
else
|
29
|
+
add_purchase_data(xml, money, true, options.merge(:currency => currency || default_currency))
|
30
|
+
add_auth_reversal_service(xml, request_id, request_token)
|
31
|
+
end
|
32
|
+
xml.target!
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require "workarea"
|
2
|
+
require "workarea/storefront"
|
3
|
+
require "workarea/admin"
|
4
|
+
require "active_merchant/billing/bogus_cyber_source_gateway"
|
5
|
+
require "active_merchant/billing/cyber_source_fix"
|
6
|
+
|
7
|
+
require "workarea/cyber_source/engine"
|
8
|
+
require "workarea/cyber_source/version"
|
9
|
+
|
10
|
+
module Workarea
|
11
|
+
module CyberSource
|
12
|
+
def self.auto_configure_gateway
|
13
|
+
if Rails.application.secrets.cyber_source.present?
|
14
|
+
if ENV["HTTP_PROXY"].present?
|
15
|
+
uri = URI.parse(ENV["HTTP_PROXY"])
|
16
|
+
ActiveMerchant::Billing::CyberSourceGateway.proxy_address = uri.host
|
17
|
+
ActiveMerchant::Billing::CyberSourceGateway.proxy_port = uri.port
|
18
|
+
end
|
19
|
+
|
20
|
+
self.gateway = ActiveMerchant::Billing::CyberSourceGateway.new(
|
21
|
+
Rails.application.secrets.cyber_source.deep_symbolize_keys
|
22
|
+
)
|
23
|
+
else
|
24
|
+
self.gateway = ActiveMerchant::Billing::BogusCyberSourceGateway.new
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.gateway
|
29
|
+
Workarea.config.gateways.credit_card
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.gateway=(gateway)
|
33
|
+
Workarea.config.gateways.credit_card = gateway
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/test/dummy/Rakefile
ADDED
data/test/dummy/bin/rake
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require "pathname"
|
3
|
+
require "fileutils"
|
4
|
+
include FileUtils
|
5
|
+
|
6
|
+
# path to your application root.
|
7
|
+
APP_ROOT = Pathname.new File.expand_path("../../", __FILE__)
|
8
|
+
|
9
|
+
def system!(*args)
|
10
|
+
system(*args) || abort("\n== Command #{args} failed ==")
|
11
|
+
end
|
12
|
+
|
13
|
+
chdir APP_ROOT do
|
14
|
+
# This script is a starting point to setup your application.
|
15
|
+
# Add necessary setup steps to this file.
|
16
|
+
|
17
|
+
puts "== Installing dependencies =="
|
18
|
+
system! "gem install bundler --conservative"
|
19
|
+
system("bundle check") || system!("bundle install")
|
20
|
+
|
21
|
+
# Install JavaScript dependencies if using Yarn
|
22
|
+
# system('bin/yarn')
|
23
|
+
|
24
|
+
|
25
|
+
# puts "\n== Copying sample files =="
|
26
|
+
# unless File.exist?('config/database.yml')
|
27
|
+
# cp 'config/database.yml.sample', 'config/database.yml'
|
28
|
+
# end
|
29
|
+
|
30
|
+
puts "\n== Preparing database =="
|
31
|
+
system! "bin/rails db:setup"
|
32
|
+
|
33
|
+
puts "\n== Removing old logs and tempfiles =="
|
34
|
+
system! "bin/rails log:clear tmp:clear"
|
35
|
+
|
36
|
+
puts "\n== Restarting application server =="
|
37
|
+
system! "bin/rails restart"
|
38
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require "pathname"
|
3
|
+
require "fileutils"
|
4
|
+
include FileUtils
|
5
|
+
|
6
|
+
# path to your application root.
|
7
|
+
APP_ROOT = Pathname.new File.expand_path("../../", __FILE__)
|
8
|
+
|
9
|
+
def system!(*args)
|
10
|
+
system(*args) || abort("\n== Command #{args} failed ==")
|
11
|
+
end
|
12
|
+
|
13
|
+
chdir APP_ROOT do
|
14
|
+
# This script is a way to update your development environment automatically.
|
15
|
+
# Add necessary update steps to this file.
|
16
|
+
|
17
|
+
puts "== Installing dependencies =="
|
18
|
+
system! "gem install bundler --conservative"
|
19
|
+
system("bundle check") || system!("bundle install")
|
20
|
+
|
21
|
+
puts "\n== Updating database =="
|
22
|
+
system! "bin/rails db:migrate"
|
23
|
+
|
24
|
+
puts "\n== Removing old logs and tempfiles =="
|
25
|
+
system! "bin/rails log:clear tmp:clear"
|
26
|
+
|
27
|
+
puts "\n== Restarting application server =="
|
28
|
+
system! "bin/rails restart"
|
29
|
+
end
|