How to change Stripe's API version for testing, etc - ruby-on-rails

We're managing an old Rails app that uses Stripe but our Stripe version 26 months behind the current API. We're looking to upgrade to the current Stripe API but because many changes will affect our system, we'd really like a way to test out the changes before we change the live API that our live site is using.
So I have two questions:
1) When working with the API we rely heavily on the distinction between Live and Test modes. Is there any way to upgrade the Test mode API only (without upgrading Live) so we can identify and correct for any breakage without actually breaking the user experience?
2) Is it possible to upgrade the API one version at a time, rather than all-at-once, to make the transition more manageable for us?

It's extremely poorly documented, but it turns out you can change the Stripe API version to any version you want on a per-request basis by setting Stripe.api_version = 'YYYY-MM-DD' before sending a request using the Ruby bindings (https://stripe.com/docs/api/ruby#versioning), or by sending a Stripe-Version HTTP header.
So we'll plan to configure our specs to use the latest API version for all requests, and test for breakage that way.

Below is one-way to override the Stripe version at a fine-grained level within your code.
This works by overriding the Stripe.api_version accessor method to look for a version in a thread local variable, or if it doesn't find one, falls back to the original behaviour. Stripe.api_version is used as the value of the Stripe-Version HTTP header in lib/stripe.rb.
Note this is for stripe gem version 1.58.0 and has not been tested with other versions:
First, create the file config/initializers/stripe_api_version_overrider.rb with contents:
module StripeAPIVersionOverrider
def api_version
Thread.current[:__stripe_api_version_override] || super
end
def with_api_version(version, &block)
original_version = api_version
Thread.current[:__stripe_api_version_override] = version
block.call
ensure
Thread.current[:__stripe_api_version_override] = original_version
end
end
Stripe.singleton_class.prepend(StripeAPIVersionOverrider)
Next, in your code where you want to use a different version of the Stripe API, wrap it in a block passed to Stripe.with_api_version:
Stripe.with_api_version "2016-07-06" do
# API versions prior to 2016-07-06 did not support
# retrieving canceled subscriptions.
Stripe::Subscription.retrieve(subscription_id)
end
Run bin/spring stop to ensure these changes will be loaded into your development environment.

Related

slack-ruby-client - RealTime on_complete': not_allowed_token_type (Slack::Web::Api::Errors::NotAllowedTokenType)

I want to implement Socketmode on Slack and communicate that, with my ruby project which uses this gem slack-ruby-client.
I did exactly what the document says, but I got this error:
on_complete': not_allowed_token_type (Slack::Web::Api::Errors::NotAllowedTokenType) .
NOTE:
according to the Slack document
for real-time(socket-mode) token, we must use an App-level token, but I see on_complete': not_allowed_token_type (Slack::Web::Api::Errors::NotAllowedTokenType) error.
when changing the type of token from App-level to User-level, the error change to on_complete': missing_scope (Slack::Web::Api::Errors::MissingScope)
my simplified code is:
Slack::Web::Client.configure do |config|
config.token = ENV['SLACK_API_TOKEN_USER']
end
Slack::RealTime::Client.configure do |conf|
conf.token = ENV['SLACK_API_TOKEN_APP']
end
module Slack
client = Slack::RealTime::Client.new
client.start!
end
also, I tried to create a legacy Bot and use that token. unexpectedly everything went fine !!!! but I don't want use the legacy one.
Connect a bot to the Slack Real Time Messaging API. Please note,
this is a legacy custom integration - an outdated way for teams to
integrate with Slack. These integrations lack newer features and they
will be deprecated and possibly removed in the future. We do not
recommend their use. Instead, we suggest that you check out their
replacement: Slack apps
You need to add the scope to that token. I don't know exactly which scope is needed for that feature. Each token is associated with one or several scopes to configure what the token can and can't do.

Rails pub/sub with ActiveMQ

I'd like my Rails app to be able to listen and publish to ActiveMQ queues.
This article gives examples of how to use a ruby STOMP client, and a gem activemessaging that integrates that client into a Rails app. The functionality there seems ideal, but the activemessaging gem seems to no longer be maintained.
There are lots of resources on using rabbitMQ instead of ActiveMQ, but I'm trying to improve my Rails app's integration with an existing Java stack that's already using ActiveMQ.
So does anyone know of a gem I can use to achieve similar functionality to that of the activemessaging gem? I can't find one, so failing that:
How would I initialise a Stomp client with a persistent connection to my activeMQ instance inside the context of my Rails app, such that 1) The lifecycle of the client is tied to that of the ruby process running my app, not the request-response procedure, and 2) I get to consume to messages using code such as Active Record models or service objects defined in my app?
Thanks in advance.
According to the ActiveMessaging project website:
ActiveMessaging is a generic framework to ease using messaging, but is not tied to any particular messaging system - in fact, it now has support for Stomp, AMQP, beanstalk, Amazon Simple Queue Service (SQS), JMS (using StompConnect or direct on JRuby), WebSphere MQ...
So, it's an interface to simplify integration between various messaging protocols and/or providers. However, since your using a standardized messaging protocol (i.e. STOMP) you don't really need it.
I recommend you simply use this STOMP gem which is referenced in the original article.
STOMP, as the name suggests, is a very simple protocol. You should be able to use it however you need in your application.
As there's so little out there on this topic I thought I'd share the solution I came up with. Having established that using the STOMP gem directly is the way forward let me re-iterate the key challenges:
How would I initialise a Stomp client with a persistent connection to
my activeMQ instance inside the context of my Rails app, such that
1) The lifecycle of the client is tied to that of the ruby process
running my app, not the request-response procedure, and
2) I get to consume to messages using code such as Active Record models or service
objects defined in my app?
Part 1) turned out to be a bad idea. I managed to achieve this using a Rails initializer, which worked fine on my local. However, when I ran it in a staging environment I found that my message listeners died mysteriously. What seems to happen is that production web servers spawn the app (running the initializers), fork the process (without running them) and kill processes at random, eventually killing the listeners without ever having replaced them.
Instead, I used the daemons gem to create a background process that's easy to start and stop. My code in lib/daemons/message_listener.rb looked something like this:
require 'daemons'
# Usage (from daemons dir):
# ruby message_listener start
# ruby message_listener status
# ruby message_listener stop
# See https://github.com/thuehlinger/daemons for full docs.
# Require this to get your app code
require_relative '../../config/environment'
Daemons.run_proc('listener.rb') do
client = nil
at_exit do
begin
client.close
rescue # probably means there's no connection to close, do nothing to handle it.
end
end
client = Stomp::Client.new(your_config_options)
# Your message handling code using your rails app goes here
loop do
# I'd expected that subscribing to a stomp queue would be blocking,
# but it doesn't seem to be.
sleep(0.001)
end
end

Thread safety in rails with slack-api gem

I have just started using rails. In my app I have to access Slack apis, so I am using the slack-api gem. The way to configure that is
Slack.configure do |config|
config.token = "token"
end
I am wondering since the token is configured at class level 'Slack', would that cause any inconsistent behaviour? One request might set it to value A and before it is done, another request may set it to value B.
While Ruby web frameworks are generally single-threaded, this is not always the case. So it likely will cause problems if the token is different across multiple requests, will be hard to reason about or become a problem in the long run.
Try the newer gem, https://github.com/dblock/slack-ruby-client which will take a token in the initializer, ie. Slack::Web::Client.new(token: 'token') or Slack::RealTime::Client.new(token: 'token'), should avoid the problem altogether.

Refresh data with API every X minutes

Ruby on Rails 4.1.4
I made an interface to a Twitch gem, to fetch information of the current stream, mainly whether it is online or not, but also stuff like the current title and game being played.
Since the website has a lot of traffic, I can't make a request every time a user walks in, so instead I need to cache this information.
Cached information is stored as a class variable ##stream_data inside class: Twitcher.
I've made a rake task to update this using cronjobs, calling Twitcher.refresh_stream, but naturally that is not running within my active process (to which every visitor is connecting to) but instead a separate process. So the ##stream_data on the actual app is always empty.
Is there a way to run code, within my currently running rails app, every X minutes? Or a better approach, for that matter.
Thank you for your time!
This sounds like a good call for caching
Rails.cache.fetch("stream_data", expires_in: 5.minutes) do
fetch_new_data
end
If the data is in the cache and is not old then it will be returned without executing the block, if not the block is used to populate the cache.
The default cache store just keeps things in memory so doesn't fix your problem: you'll need to pick a cache store that is shared across your processes. Both redis and memcached (via the dalli gem) are popular choices.
Check out Whenever (basically a ruby interface to cron) to invoke something on a regular schedule.
I actually had a similar problem with using google analytics. Google analytics requires that you have an API key for each request. However the api key would expire every hour. If you requested a new api key for every google analytics request, it'd be very slow per request.
So what I did was make another class variable ##expires_at. Now in every method that made a request to google analytics, I would check ##expires_at.past?. If it was true, then I would refresh the api key and set ##expires_at = 45.minutes.from_now.
You can do something like this.
def method_that_needs_stream_data
renew_data if ##expires_at.past?
# use ##stream_data
end
def renew_data
# renew ##stream_data here
##expires_at = 5.minutes.from_now
end
Tell me how it goes.

Detect user agent in Rails 4 - read HTTP header

I just switched from PHP to Ruby on Rails and was wondering if there was a way to detect the clients device/user agent (reading the HTTP header) in order to serve different versions of the site depending on the request it gets. In PHP I have been using Mobile Detect to do so. The general idea is to only serve files that are needed for each particular version. Thats why a client side approach is not that effective.
Is there a way to do something similar with Ruby 2.0.0 and Rails 4.0.0 ?
Maybe there is a gem to handle cases like that?
Check the request method, where you can get a ActionDispatch::Request where you have all the request parameters, including the user agent.
request.user_agent

Resources