How to customize stub request using Faraday? - ruby-on-rails

I'm trying to customize stubs via Faraday and have a little problem with setting request_body and request_headers. All test works and are green, but I'm still getting message by Rubymine: „Found extra argument“ and that part of the code is underlined in red. I would like to get rid of it. Just how to customize body and headers in right way, please?
Actual problem
I have tried to customize it like this:
conn = Faraday.new(url: "url") do |faraday|
faraday.response :raise_error
end
conn.get("url") do |req|
req.body: {body: "body"}
req.headers: {headers: "headers"}
end
But it did not work.

Thank you for the feedback.
This is a known problem, please follow the RUBY-30140/False-positive-found-extra-argument-warning-with-Faraday.get(see help if you are not familiar with YouTrack).
I've requested this issue to include in one of our nearest maintenance sprint. Sorry for inconveniences:(
Best regards
Anna Kutarba.
JetBrains
https://jetbrains.com
The Drive to Develop

Related

Cause of google vision API HTTP Forbidden error? Ruby (Rails)

I have been trying to get the google vision API to work in my rails application but keep getting a Net::HTTPForbidden response. I'm not really sure what is causing it since everything I have seems to be setup properly, I've tried generating new keys and still get the same error, any help would be appreciated. I replaced my API key with 'XXXXX_MY_API_KEY_XXXXX' in this post for obvious reasons, so that is not the issue, also have tried directly pasting in an image url in place of the 'img_url' so I don't think that that is related to the issue either.
require 'net/http'
require 'uri'
require 'json'
def transcribe(img_url)
uri = URI.parse('https://vision.googleapis.com/v1/images:annotate?key=' + 'XXXXX_MY_API_KEY_XXXXX')
request = Net::HTTP::Post.new(uri)
request.content_type = 'application/json'
request.body = JSON.dump(
'requests' => [
{
'image' => {
'source' => {
'imageUri' => img_url
}
},
'features' => [
{
'type' => 'TEXT_DETECTION',
'maxResults' => 1,
'model' => 'builtin/latest'
}
]
}
]
)
req_options = {
use_ssl: uri.scheme == 'https'
}
response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
http.request(request)
end
p response
p response.code
p response.body
end
Ok, so after hours of messing around with this I finally figured out the issue. When you first try to use the api they will return a link to you that you have to visit to activate the specific API (vision in my case), I could not find this page through the ui on the google cloud control panel, only through the link. Even though the API key was active and unrestricted with billing setup it would not function without activating the specific API. Because I had commented out the response code/body I was only getting the status code for my API call and was not seeing the rest of the response, preventing me from finding the proper activation link.
This was a massive lapse of judgement on my part, hopefully this will help anyone who runs into a similar issue or is looking to integrate google vision API into a rails app and stumbles upon this thread, the code shown above works totally fine and is a much simpler approach to using the API when compared to the client library, just make sure that you have the specific API that you want to use enabled. Just because the API key is not restricted does not mean that you can simply use any of their APIs, I made sure to 'fix' (uncomment) the code I posted for anyone else who may find it useful.

What are some guidelines for creating HTTP requests in a Rails app?

I am relatively new to writing code against REST APIs. It is possible I am analyzing the wrong problem here, so feel free to give big picture advice. The other twist is that the API I want to use is not yet configured, so I can't test.
I need to write some Rails code to create webhooks on the Jive API. Jive's docs show how to register the webservice via a curl request. I want to build the code as an admin function of my app in case we need to recreate the webhook for any reason.
Here are the Jive Docs.
Based on this guide, I'm thinking I need something like (I expect this example to sent a POST request to "sample.jiveon.com/api/core/v3/webhooks"):
#host = "sample.jiveon.com/api/core/v3"
#port = "443"
#post_ws = "/webhooks"
#payload ={
"events" => "document",
"callback" => "my_app/jive_listener",
"object" => "my/jive/space"
}.to_json
def post
req = Net::HTTP::Post.new(#post_ws, initheader = {'Content-Type' =>'application/json'})
req['Authorization'] = "Bearer my_key"
req.body = #payload
response = Net::HTTP.new(#host, #port).start {|http| http.request(req) }
end
end
Thanks.
It would be better to use gem like 'rest-client(https://github.com/rest-client/rest-client)'
Above gem does the many stuff, which you might be doing manually using bare ruby library. It depends on need of yours.

Ruby Asana Gem - Get all tasks with particular tag

Im using the Ruby Asana gem https://github.com/rbright/asana.
As per the documentation, in my controller I have:
tag = Asana::Tag.find(6498432136675)
#waiting_tasks = tag.tasks
However, this returns:
Failed. Response code = 400. Response message = Bad Request.
I have confirmed that the id is correct. If i use:
puts tag.inspect
I get the following:
#<Asana::Tag:0x007f94432af498 #attributes={"id"=>6498432136675, "created_at"=>"2013-07-14T10:05:13.070Z", "name"=>"Waiting for", "notes"=>"", "workspace"=>#<Asana::Workspace:0x007f94432aea98 #attributes={"id"=>6399696678844, "name"=>"Ministry of Crazy Ideas"}, #prefix_options={}, #persisted=false>, "color"=>"light-teal", "followers"=>[]}, #prefix_options={}, #persisted=true>
I dont understand why this is not returning the tasks as documented in the read me. If anyone can shed any light on this I would be hugely grateful.
Sounds like it's most likely a bug in the ruby gem. However, it could be an underlying API issue. Try curl -u <YOUR API KEY>: https://app.asana.com/api/1.0/tags/6498432136675/tasks - if that works, the gem isn't constructing the right URL (aka, that one). If it still returns a 400, the issue may be with the API.

Receive an email with Actionmailer and read the plain body text

I am using IMAP to receive some emails from gmail and then parse them with the new Rails 3 ActionMailer receive method.
raw_email = imap.uid_fetch(uid, ['RFC822']).first.attr['RFC822']
email = UserMailer.receive(raw_email)
email is now a Mail::Message Class and to:, :from and :subject works fine. However I can't figure out how to get the plain text from the body. Before Rails 3 I could use the tmail_body_extractors plugin to get the plain body.
How would you do this with Rails 3?
Jakobinsky:
email.body.raw_source is a bit closer be still gives me a lot of garbage.
"--001636310325efcc88049508323d\r\nContent-Type: text/plain;
charset=ISO-8859-1\r\nContent-Transfer-Encoding:
quoted-printable\r\n\r\nThis is some body
content\r\n\r\n--=20\r\nVenlig Hilsen\r\nAsbj=F8rn
Morell\r\n\r\n--001636310325efcc88049508323d\r\nContent-Type:
text/html; charset=ISO-8859-1\r\nContent-Transfer-Encoding:
quoted-printable\r\n\r\naf mail-- Venlig
HilsenAsbj=F8rn
Morell\r\n\r\n--001636310325efcc88049508323d--"
Should I roll my own helpers for cleaning up the raw_source or is there already a method ,gem or helper for that?
See the answer on this question:
Rails - Mail, getting the body as Plain Text
In short the solution is:
plain_part = message.multipart? ? (message.text_part ? message.text_part.body.decoded : nil) : message.body.decoded
But I recommend reading the full answer as it is very good and comprehensive.
You can extract the plain body from body.parts. There is still however some headers left in the body:
if body.multipart?
body.parts.each do |p|
if p.mime_type == "text/plain"
body = p.body
end
end
end
body.to_s
You should be able to retrieve the body as simple as email.body.raw_source.
I haven't tested it myself, but you can take a look as the source code for ActionMailer:: Message#body.

What's the best way to use SOAP with Ruby?

A client of mine has asked me to integrate a 3rd party API into their Rails app. The only problem is that the API uses SOAP. Ruby has basically dropped SOAP in favor of REST. They provide a Java adapter that apparently works with the Java-Ruby bridge, but we'd like to keep it all in Ruby, if possible. I looked into soap4r, but it seems to have a slightly bad reputation.
So what's the best way to integrate SOAP calls into a Rails app?
I built Savon to make interacting with SOAP webservices via Ruby as easy as possible.
I'd recommend you check it out.
We used the built in soap/wsdlDriver class, which is actually SOAP4R.
It's dog slow, but really simple. The SOAP4R that you get from gems/etc is just an updated version of the same thing.
Example code:
require 'soap/wsdlDriver'
client = SOAP::WSDLDriverFactory.new( 'http://example.com/service.wsdl' ).create_rpc_driver
result = client.doStuff();
That's about it
We switched from Handsoap to Savon.
Here is a series of blog posts comparing the two client libraries.
I also recommend Savon. I spent too many hours trying to deal with Soap4R, without results. Big lack of functionality, no doc.
Savon is the answer for me.
Try SOAP4R
SOAP4R
Getting Started with SOAP4R
And I just heard about this on the Rails Envy Podcast (ep 31):
WS-Deathstar SOAP walkthrough
Just got my stuff working within 3 hours using Savon.
The Getting Started documentation on Savon's homepage was really easy to follow - and actually matched what I was seeing (not always the case)
Kent Sibilev from Datanoise had also ported the Rails ActionWebService library to Rails 2.1 (and above).
This allows you to expose your own Ruby-based SOAP services.
He even has a scaffold/test mode which allows you to test your services using a browser.
I have used HTTP call like below to call a SOAP method,
require 'net/http'
class MyHelper
def initialize(server, port, username, password)
#server = server
#port = port
#username = username
#password = password
puts "Initialised My Helper using #{#server}:#{#port} username=#{#username}"
end
def post_job(job_name)
puts "Posting job #{job_name} to update order service"
job_xml ="<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ns=\"http://test.com/Test/CreateUpdateOrders/1.0\">
<soapenv:Header/>
<soapenv:Body>
<ns:CreateTestUpdateOrdersReq>
<ContractGroup>ITE2</ContractGroup>
<ProductID>topo</ProductID>
<PublicationReference>#{job_name}</PublicationReference>
</ns:CreateTestUpdateOrdersReq>
</soapenv:Body>
</soapenv:Envelope>"
#http = Net::HTTP.new(#server, #port)
puts "server: " + #server + "port : " + #port
request = Net::HTTP::Post.new(('/XISOAPAdapter/MessageServlet?/Test/CreateUpdateOrders/1.0'), initheader = {'Content-Type' => 'text/xml'})
request.basic_auth(#username, #password)
request.body = job_xml
response = #http.request(request)
puts "request was made to server " + #server
validate_response(response, "post_job_to_pega_updateorder job", '200')
end
private
def validate_response(response, operation, required_code)
if response.code != required_code
raise "#{operation} operation failed. Response was [#{response.inspect} #{response.to_hash.inspect} #{response.body}]"
end
end
end
/*
test = MyHelper.new("mysvr.test.test.com","8102","myusername","mypassword")
test.post_job("test_201601281419")
*/
Hope it helps. Cheers.
I have used SOAP in Ruby when i've had to make a fake SOAP server for my acceptance tests. I don't know if this was the best way to approach the problem, but it worked for me.
I have used Sinatra gem (I wrote about creating mocking endpoints with Sinatra here) for server and also Nokogiri for XML stuff (SOAP is working with XML).
So, for the beginning I have create two files (e.g. config.rb and responses.rb) in which I have put the predefined answers that SOAP server will return.
In config.rb I have put the WSDL file, but as a string.
##wsdl = '<wsdl:definitions name="StockQuote"
targetNamespace="http://example.com/stockquote.wsdl"
xmlns:tns="http://example.com/stockquote.wsdl"
xmlns:xsd1="http://example.com/stockquote.xsd"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns="http://schemas.xmlsoap.org/wsdl/">
.......
</wsdl:definitions>'
In responses.rb I have put samples for responses that SOAP server will return for different scenarios.
##login_failure = "<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<LoginResponse xmlns="http://tempuri.org/">
<LoginResult xmlns:a="http://schemas.datacontract.org/2004/07/WEBMethodsObjects" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<a:Error>Invalid username and password</a:Error>
<a:ObjectInformation i:nil="true"/>
<a:Response>false</a:Response>
</LoginResult>
</LoginResponse>
</s:Body>
</s:Envelope>"
So now let me show you how I have actually created the server.
require 'sinatra'
require 'json'
require 'nokogiri'
require_relative 'config/config.rb'
require_relative 'config/responses.rb'
after do
# cors
headers({
"Access-Control-Allow-Origin" => "*",
"Access-Control-Allow-Methods" => "POST",
"Access-Control-Allow-Headers" => "content-type",
})
# json
content_type :json
end
#when accessing the /HaWebMethods route the server will return either the WSDL file, either and XSD (I don't know exactly how to explain this but it is a WSDL dependency)
get "/HAWebMethods/" do
case request.query_string
when 'xsd=xsd0'
status 200
body = ##xsd0
when 'wsdl'
status 200
body = ##wsdl
end
end
post '/HAWebMethods/soap' do
request_payload = request.body.read
request_payload = Nokogiri::XML request_payload
request_payload.remove_namespaces!
if request_payload.css('Body').text != ''
if request_payload.css('Login').text != ''
if request_payload.css('email').text == some username && request_payload.css('password').text == some password
status 200
body = ##login_success
else
status 200
body = ##login_failure
end
end
end
end
I hope you'll find this helpful!
I was having the same issue, switched to Savon and then just tested it on an open WSDL (I used http://www.webservicex.net/geoipservice.asmx?WSDL) and so far so good!
https://github.com/savonrb/savon

Resources