undefined method `batch_change_message_visibility' with AWS-SDK for Ruby - ruby

I'm trying to write a ruby script to change a message error but I'm getting the error batch_change_message_visibility is not a defined method.
Here is the code :
require 'rubygems'
require 'aws-sdk'
sqs = AWS::SQS.new(
:access_key_id => access_key,
:secret_access_key => access_secret)
queue = sqs.queues.named(queue_name)
messages = []
messages << { :message => message_handle, :visibility_timeout => 5 }
queue.batch_change_message_visibility(messages)
Any idea ? Thanks !

The method is called batch_change_visibility - the documentation has the wrong method name.

Related

modular Sinatra App, setting error handling & configuration globally

I am using Sinatra to build a small Ruby API, and I would like to get some of the errors and configurations set to work at a global level so that i don't need to set them at the start of each of the classes.
My structure is this:
content_api.rb
require 'sinatra/base'
require 'sinatra/namespace'
require 'sinatra/json'
require 'service_dependencies'
require 'api_helpers'
require 'json'
module ApiApp
class ContentApi < Sinatra::Base
helpers Sinatra::JSON
helpers ApiApp::ApiHelpers
include ApiApp::ServiceDependencies
before do
content_type :json
end
get '/' do
content = content_service.get_all_content
content.to_json
end
get '/audio' do
package =content_service.get_type 'Audio'
package.to_json
end
get '/video' do
package =content_service.get_type 'Video'
package.to_json
end
get '/document' do
package =content_service.get_type 'Document'
package.to_json
end
end
end
config.ru:
$LOAD_PATH.unshift *Dir[File.join(File.dirname(__FILE__), '/src/**')]
$LOAD_PATH.unshift *Dir[File.join(File.dirname(__FILE__), '/src/api/**')]
require 'content_api'
require 'package_api'
require 'utility_api'
require 'sinatra/base'
configure do
set :show_exceptions => false
end
error { |err| Rack::Response.new([{'error' => err.message}.to_json], 500, {'Content-type' => 'application/json'}).finish }
Rack::Mount::RouteSet.new do |set|
set.add_route ApiApp::ContentApi, {:path_info => %r{^/catalogue*}}, {}, :catalogue
set.add_route ApiApp::PackageApi, {:path_info => %r{^/package*}}, {}, :package
set.add_route ApiApp::UtilityApi, {:path_info => %r{^/health_check*}}, {}, :health_check
end
When I run this, it will run okay, but when I force a 500 error (shut down MongoDb) I get a standard html type error that states:
<p id="explanation">You're seeing this error because you have
enabled the <code>show_exceptions</code> setting.</p>
If I add the
configure do
set :show_exceptions => false
end
error { |err| Rack::Response.new([{'error' => err.message}.to_json], 500, {'Content-type' => 'application/json'}).finish }
inside the content_api.rb file, then I get a JSON error returned as I would like to receive.
however, as I am building this modular, I don't want to be repeating myself at the top of each class.
Is there a simple way to make this work?
The simplest way to do this would be to reopen Sinatra::Base and add the code there:
class Sinatra::Base
set :show_exceptions => false
error { |err|
Rack::Response.new(
[{'error' => err.message}.to_json],
500,
{'Content-type' => 'application/json'}
).finish
}
end
This is probably not advisable though, and will cause problems if your app includes other non-json modules.
A better solution might be to create a Sinatra extension that you could use in your modules.
module JsonExceptions
def self.registered(app)
app.set :show_exceptions => false
app.error { |err|
Rack::Response.new(
[{'error' => err.message}.to_json],
500,
{'Content-type' => 'application/json'}
).finish
}
end
end
You would then use it by registering it in your modules:
# require the file where it is defined first
class ContentApi < Sinatra::Base
register JsonExceptions
# ... as before
end
As an alternative, inheritance:
class JsonErrorController < Sinatra::Base
configure do
set :show_exceptions => false
end
error { |err| Rack::Response.new([{'error' => err.message}.to_json], 500, {'Content-type' => 'application/json'}).finish }
end
class ContentApi < JsonErrorController
# rest of code follows…
end
From Sinatra Up and Running p73:
Not only settings, but every aspect of a Sinatra class will be
inherited by its subclasses. This includes defined routes, all the
error handlers, extensions, middleware, and so on.

Obtaining a render Argument Error: What is the correct syntax or usage?

I am new to Ruby, Sinatra and Pusher so this is a basic question. I am attempting to authenticate a Pusher Client (using iOS demo code https://github.com/lukeredpath/libPusher). The server code below fails with error when the iOS client attempts to join a presence channel:
ArgumentError - wrong number of arguments (1 for 2):
/Users/waveocean/.rvm/gems/ruby-1.9.3-p327/gems/sinatra-1.3.3/lib/sinatra/base.rb:665:in `render'
web.rb:13:in `auth'
web.rb:26:in `block in <main>'
/Users/waveocean/.rvm/gems/ruby-1.9.3-p327/gems/sinatra-1.3.3/lib/sinatra/base.rb:1265:in `call'
... snipped for brevity ...
Here is the code:
require 'sinatra'
require 'pusher'
require 'thin'
Thin::HTTP_STATUS_CODES[403] = "FORBIDDEN"
Pusher.app_id = 'MY-APP-ID'
Pusher.key = 'MY-KEY'
Pusher.secret = 'MY-SECRET'
def auth
response = Pusher[params[:channel_name]].authenticate(params[:socket_id], {:user_id => 101})
render :json => response
end
use Rack::Auth::Basic, "Protected Area" do |username, password|
username == 'foo' && password == 'bar'
end
post '/presence/auth' do
if params[:channel_name] == 'presence-demo'
auth
else
# render :text => "Forbidden", :status => '403'
response.status = 403
end
end
Can someone provide a suggestion or correct usage of render?
Here's is what I discovered. render is associated with Rails, and not strictly Ruby. To respond to the Sinatra route, use the following in the auth method:
def auth
response = Pusher[params[:channel_name]].authenticate(params[:socket_id], {:user_id => 101})
[200, {"Content-Type" => "application/json"}, response.to_json]
end
As it turns out, the Pusher iOS project demo provides a Scripts/auth_server.rb file with the required implementation. It is documented with the installation instructions here: https://github.com/lukeredpath/libPusher/wiki/Adding-libPusher-to-your-project .

How to use mocha outside of unit tests?

I'm trying to use mocha outside of unit tests to mock an Net::HTTPResponse object. here is a simple example:
#!/usr/bin/env ruby -w
require 'net/http'
require 'rubygems'
require 'mocha'
response = mock('Net::HTTPResponse')
response.stubs(:code => '500', :message => "Failed", :content_type => "text/plaint", :body => '')
I get this error:
undefined method `mock' for main:Object (NoMethodError)
I'd recommend using the fakeweb gem for this. It's designed to stub out http requests.
require 'rubygems'
require 'fakeweb'
FakeWeb.register_uri(:get, "http://something.com/", :body => "", :status => ["500", "Server Error"])
More info: https://github.com/chrisk/fakeweb

Handle the PUT method in WEBrick

How do I handle PUT requests in WEBrick?
I have tried defining a do_PUT() method in an AbstractServlet class but the method is never invoked.
I had the same problem and got it working by creating my own custom WEBrick::HTTPProxyServer and adding the put method in that.
require "webrick"
require "webrick/httpproxy"
require 'cgi'
class CustomWEBrickProxyServer < WEBrick::HTTPProxyServer
def do_PUT(req, res)
perform_proxy_request(req, res) do |http, path, header|
http.put(path, req.body || "", header)
end
end
# This method is not needed for PUT but I added for completeness
def do_OPTIONS(req, res)
res['allow'] = "GET,HEAD,POST,OPTIONS,CONNECT,PUT"
end
end
Then you need to start your proxy server using your own Custom class.
my_proxy_server = CustomWEBrickProxyServer.new :Port=> proxy_port,
:ProxyVia => forward_proxy,
:ProxyURI => forward_proxy,
:RequestCallback => method(:request_callback),
:ProxyContentHandler => method(:response_callback),
:AccessLog => method(:access_log)

consume soap service with ruby and savon

I'm trying to use ruby and Savon to consume a web service.
The test service is http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2
require 'rubygems'
require 'savon'
client = Savon::Client.new "http://www.webservicex.net/stockquote.asmx?WSDL"
client.get_quote do |soap|
soap.body = {:symbol => "AAPL"}
end
Which returns an SOAP exception. Inspecting the soap envelope, it looks to me that the soap request doesn't have the correct namespace(s).
Can anyone suggest what I can do to make this work?
I have the same problem with other web service endpoints as well.
Thanks,
This is a problem with the way Savon handles Namespaces. See this answer Why is "wsdl" namespace interjected into action name when using savon for ruby soap communication?
You can resolve this by specifically calling soap.input and passing it an array, the first element is the method and the second is a hash containing the namespace(s)
require 'rubygems'
require 'savon'
client = Savon::Client.new "http://www.webservicex.net/stockquote.asmx?WSDL"
client.get_quote do |soap|
soap.input = [
"GetQuote",
{ "xmlns" => "http://www.webserviceX.NET/" }
]
soap.body = {:symbol => "AAPL"}
end
You might find the latest gem uses the method "request" followed by the symbol reference to the method required.
require 'rubygems'
require 'savon'
client = Savon::Client.new "http://www.webservicex.net/stockquote.asmx?WSDL"
client.request :get_quote do |soap|
soap.input = [
"GetQuote",
{ "xmlns" => "http://www.webserviceX.NET/" }
]
soap.body = {:symbol => "AAPL"}
end

Resources