Stubbing instance method for OpenTok object - ruby-on-rails

The gem I'm using to integrate OpenTok in my Rails application is at: https://github.com/opentok/Opentok-Ruby-SDK. I based the core of the application on this example: http://www.tokbox.com/blog/building-a-video-party-app-with-ruby-on-rails.
In the relevant part of code, I'm creating an #opentok object in the config_opentok method:
def config_opentok
if #api_key.nil? or #api_secret.nil?
if Rails.env.development?
#api_key = API_KEY
#api_secret = API_SECRET
else
#api_key = ENV['API_KEY']
#api_secret = ENV['API_SECRET']
end
end
if #opentok.nil?
#opentok = OpenTok::OpenTokSDK.new(#api_key, #api_secret)
end
end
And I'm creating a session with the following code:
config_opentok
if Rails.env.development?
session = #opentok.create_session('localhost')
else
session = #opentok.create_session(request.remote_addr)
end
The trouble is, the create_session seems to throw an error
SocketError: getaddrinfo: nodename nor servname provided, or not known
whenever I run my Rspec tests without an internet connection. So I'd like to stub that method so that it returns just a hash {:sessionId => 1}. But I'm having trouble figuring out how to stub the method. I can't just stub the OpenTok module or the OpenTok::OpenTokSDK class. How would I go about stubbing the create_session method?

here's what I've been doing that works:
First, what I tend to do is to initialize the OpenTok object when the app loads so I'm not creating an OpenTok object on every request. To do this, I create a ruby file (apis.rb) in my config/initializers folder.
My apis.rb looks like this:
TB_KEY = ENV['TB_KEY']
TB_SECRET = ENV['TB_SECRET']
OTSDK = OpenTok::OpenTokSDK.new TB_KEY, TB_SECRET
In my controller, to generate a session I'll simply call OTSDK.createSession, similar to what you already have.
To test with rspec, you can simply write in your test file:
OTSDK.stub(:createSession).and_return( {:sessionId => "1MX_2A3453095J0TJ30..."} )
If you run rspec with wifi turned off calling createSession should no longer throw an error.
Here's the documentation for rspec stubbing: http://rubydoc.info/gems/rspec-mocks/frames
Good Luck!

The trouble is, the create_session seems to throw an error whenever I run my Rspec tests without an internet connection.
Instead of attempting to stub, why not give your tests a mock internet connection with VCR?
After initial set up, VCR lets you run all of your tests as if you were actively connected to the internet. This allows you to run tests offline, speeds up all the tests that needed an active connection, and gives you a consistent set of results.
If you have a subscription to RailsCasts, Ryan made a video about VCR in episode 291

Related

RoR - Validate string on website, no error

In my Ruby on Rails app I have build a function to validate if a piece of javascript is added to a certain website. When I run this code I don't get any errors in my log, but my app says:
We're sorry, but something went wrong.
If you are the application owner check the logs for more information.
But when I check the logs I don't see any errors. The code I have used is the following:
def validate_installation
data = HTTParty.get(self.website)
url = "http://www.smartnotif.com/sn.js"
if data.body.include? url
return true
else
return false
end
end
When I run this code on my local development machine it runs fine, but when I try to runs this production machine on DigitalOcean I have this problem with the same code, no errors.
Try to include
require 'httparty'
Restart rails server
rails s
Also check the permission of log folder, why it is not writing error in log folder
Also try: Use self keyword as you are calling it as class method
def self.validate_installation
data = HTTParty.get(self.website)
url = "http://www.smartnotif.com/sn.js"
if data.body.include? url
return true
else
return false
end
end

#<Mongoid::Locker::LockError: could not get lock> in mongoid-locker rails

I applied "mongoid-locker" gem on my app but during concurrent request it got failed and got error "LockError: could not get lock".So can anyone help me out.
By default, with_lock does not wait for other locks to complete, so if you actually have a concurrent access, you will get the LockError raised if you don't tell it to wait.
Try it like so:
object = Object.first
object.with_lock wait:true do
object.foo = "bar"
object.save!
end

How do I mock S3Object.read do |chunk| using rspec

I'm new to ruby and rspec.
I have a module that interacts with S3 in ruby.
In my code I :
create a new S3 instance : s3 = AWS::S3.new()
Get my bucket : #s3bucket = s3.buckets[#bucket]
Retrieve my S3Object : object = #s3bucket.objects[key]
Finally, I save the object to a local file:
File.open(local_filename, 'wb') do |s3file|
object.read do |chunk|
return completed if stop?
s3file.write(chunk)
end
My code works well, but I'm having problems unit testing it,
specifically I'm having problems mocking the object.read do |chunk| part.
No matter what I try the chunk turns out empty.
Can some one help?
Thanks.
try this:
s3_object = class_double("S3Object")
allow(s3_object).to receive(:read).and_return(<what ever you want>)
If you need to need to store API responses in your tests without making multiple calls, check out https://github.com/vcr/vcr
If you want to mock this:
create a new S3 instance : s3 = AWS::S3.new()
you do
allow_any_instance_of(AWS::S3).to_receive(:new).and_return(<the return value of the method>)
You can use VCR as suggested previously but you will run into issues if you are working on a team and you run your tests at the same time as another team member if you both have deleted the same cassette.

Ruby timeout does not work in Rails?

I'm having an issue trying to get a timeout when connecting via TCPSocket to a remote resource that isn't available. It just hangs indefinitely without timing out. Ideally I'd want it to try reconnect every 2 minutes or so, but the TCPSocket.new call seems to block. I've tried using timeout() but that doesn't do anything either. Trying the same call in an IRB instance works perfectly fine, but when it's in Rails, it fails. Anyone have a work around for this?
My code looks something as follows:
def self.connect!
##connection = TCPSocket.new IP, 4449
end
def self.send(cmd)
puts "send "
unless ##connection
self.connect!
end
loop do
begin
##connection.puts(cmd)
return
rescue IOError
sleep(self.get_reconnect_delay)
self.connect!
end
end
end
Unfortunately, there is currently no way to set timeouts on TCPSocket directly.
See http://bugs.ruby-lang.org/issues/5101 for the feature request. You will have use the basic Socket class and set socket options.

What kind of exception is raised by ActiveRecord::lock!?

I am using lock! in my code and want to catch the exception thrown if lock! fails for some reason (e.g. cannot get the lock). What kind of exceptions can lock! throw? I checked the ruby docs but couldn't find the specific Exception classes.
Thanks.
When in doubt, probe.
Consider the following pair of functions:
def long_hold
ActiveRecord::Base.transaction do
u = User.find(220)
u.lock!
sleep 100.seconds
u.email="foo#bar.com"
u.save!
end
end
def short_hold
ActiveRecord::Base.transaction do
u = User.find(220)
u.lock!
u.email="foo#bar.com"
u.save!
end
end
In my setup (OSX 10.11, ruby 2.2.4, rails 4.2, postgres 9.5), running long_hold in one rails console and then running short_hold in a second console, I observe short_hold blocks until long_hold completes; moreover, instrumenting the code with puts, we see that while long_hold is sleeping, short_hold is waiting to acquire the lock.
Assuming no caveats about the independence of rails consoles, this suggests that no exceptions are thrown if a second process tries to lock a row that is already locked, but that process blocks until the first completes.
Here is the source for that locking call. It calls reload and its source looks like this:
# File lib/active_record/base.rb, line 2333
2333: def reload(options = nil)
2334: clear_aggregation_cache
2335: clear_association_cache
2336: #attributes.update(self.class.find(self.id, options).instance_variable_get('#attributes'))
2337: #attributes_cache = {}
2338: self
2339: end
so when you call reload(:lock => lock) as the call to lock does it it really updating the attributes of that record.
There are a lot of different situations here. You could try to lock a record that dosnt exist, or lock one that has been locked elsewhere. What error are you interested in catching?

Resources