All begin when I started using Mollie, it's a PSP (Payment Service Provider) like Stripe and it has a ruby wrapper, but if you want to test payments in a development environment (localhost) you need a valid URL so they can reach you via webhook (if you want to validate the payment, the webhook URL parameter is mandatory).
The solution was easy I just create an ngrok tunnel and I change the default_url_options
with an environment variable depending if I was working on something that needed only my local machine or other services.
For running my app with mollie webhooks i needed to do this:
- Start ngrok
- Change
ENV
variables for the new ngrokhttps
url - Start my app
- Start Sidekiq (for background jobs)
IMO it's not to much but at some point becomes annoying so I decided to make it easier for me, now i only have:
- Start my app
- Start Sidekiq
Here it is how to did it:
- Install ngrok v2+ in your computer
- Add
ngrok-tunnel
in your Gemfile
group :development do
gem 'ngrok-tunnel'
# Cool stuff for later but not really needed
gem 'tty-box'
end
- In
puma.rb
we add this code at the bottom
if ENV["IS_DEV_ENV"]
begin
options = {
# App port
addr: ENV.fetch("PORT") { 3000 },
# ngrok system files
config: File.join(ENV["HOME"], ".ngrok2", "ngrok.yml"),
}
# In case that you have a pay plan you can create
# tunnels with custom subdomains
options[:subdomain] = ENV["NGROK_SUBDOMAIN"] if ENV["NGROK_SUBDOMAIN"]
# Region (since I only work in the EU is hardcoded)
options[:region] = "eu"
# Create tunnel
Ngrok::Tunnel.start(options)
# Create cool box
box = TTY::Box.frame(width: 50, height: 10, padding: 2, title: {top_left: "<NGROK>", bottom_right: "</NGROK>"}, style: {fg: :green, bg: :black, border: {fg: :green, bg: :black}}) do
"STATUS: #{Ngrok::Tunnel.status}\nPORT: #{Ngrok::Tunnel.port}\nHTTP: #{Ngrok::Tunnel.ngrok_url}\nHTTPS: #{Ngrok::Tunnel.ngrok_url_https}\n"
end
rescue => error
box = TTY::Box.frame(width: 50, height: 5, align: :center, padding: 1, title: {top_left: "<NGROK>", bottom_right: "</NGROK>"}, style: {fg: :red, bg: :black, border: {fg: :red, bg: :black}}) do
"I couldn't create the tunnel ;("
end
end
puts "\n#{box}\n"
end
Let's comment this code:
-
ENV["IS_DEV_ENV"]
: SinceRails.env.development?
is not loaded (at least in Heroku) in this point of the app we are using an environment variable that is only set in yoursecrets.yml
orapplication.yml
only in thedevelopment
section and it needs to be set to true.
development:
IS_DEV_ENV: "true"
- In the
options
hash we have the app port and the home directory where the ngrok files are located. -
options[:subdomain]
In case that you are an ngrok subscriber you can have a custom subdomain so I left the code here just in case I became a subscriber one day. -
options[:region]
This is not in an ENV variable because we are based in the EU and we don't work outside of it, so I just hardcoded EU but you can choose between:- us - United States (Ohio)
- eu - Europe (Frankfurt)
- ap - Asia/Pacific (Singapore)
- au - Australia (Sydney)
- WHAT'S IN THE
box
????!!! just to make it cooler (at least for me) it's showing a nice box with the ngrok information.
- In case ngrok cannot be connected we use the box to show that we cannot connect
Change the varibles
You maybe don't need this if you just want to test Mollie payments but for me was nice to have.
To change the config dynamically I choose a way that I think it's far from okey but it works (yeah i know it's running on every request). In the application_controller.rb
I added this method:
before_action :set_ngrok_urls, if: "Rails.env.development?"
def set_ngrok_urls
if Ngrok::Tunnel.running?
# Getting current url
url = Ngrok::Tunnel.ngrok_url_https
# Variable hash
default_url_options = {host: url}
# Overwriting current variables
Rails.application.config.action_controller.asset_host = url
Rails.application.config.action_mailer.asset_host = url
Rails.application.routes.default_url_options = default_url_options
Rails.application.config.action_mailer.default_url_options = default_url_options
end
end
So what I'm doing here is in case that the environment is development I'm executing the function set_ngrok_urls
and checks if ngrok is connected.
Then I get the current ngrok https URL and I create a hash (this hash is needed for the routes and the mailer default URL's) the two first only use the url.
That will be all, hope this works for some people and please if I did something very wrong leave a comment.
Bibliography
- Autostart Ngrok With Rails: https://stuff-things.net/2016/10/12/autostart-ngrok-with-rails/
Top comments (1)
Great article! As a free ngrok user we added the default URL options to the bottom of our puma.rb rather than in application.rb and it works great.
We also updated some of our other systems, such as mailgun inbound routes in the same space