Putting Variable with in single quotes? - ruby

Hi all I am making a request to the Campaign Monitor API and the data has to be held with in single quotes as a string but in JSON format. As it has to be single quotes I am unable to put in any variable values. Below is the code.
response = HTTParty.post(url,
:basic_auth => auth, :body => '{
"EmailAddress":"js#mike.com",
"Name":"#{#fname}",
"CustomFields":[
{
"Key":"firstName",
"Value":"#{#fname}"
},
{
"Key":"country",
"Value":"#{#country}"
}
],
"Resubscribe":true,
"RestartSubscriptionBasedAutoresponders":true
}')
I have tried a few different methods such as breaking the string up and piecing it back together with the variable with in double quotes but that has failed as well for the request to be successful it has to be exact.

Instead of building a JSON structure by hand, you can build a Ruby hash and convert it to JSON:
require 'json'
data = {
'EmailAddress' => 'js#mike.com',
'Name' => #fname,
'CustomFields' => [
{ 'Key' => 'firstName', 'Value' => #fname },
{ 'Key' => 'country', 'Value' => #country }
],
'Resubscribe' => true,
'RestartSubscriptionBasedAutoresponders' => true
}
response = HTTParty.post(url, basic_auth: auth, body: data.to_json)
Also note that there's a Ruby gem for the Campaign Monitor API: createsend-ruby
Using the gem, the above code translates to:
custom_fields = [
{ 'Key' => 'firstName', 'Value' => #fname },
{ 'Key' => 'country', 'Value' => #country }
]
response = CreateSend::Subscriber.add(auth, list_id, 'js#mike.com', #fname, custom_fields, true, true)

you can try with heredoc :
response = HTTParty.post(url,
:basic_auth => auth, :body => <<-BODY_CONTENT
{
"EmailAddress":"js#mike.com",
"Name":"#{#fname}",
"CustomFields":[
{
"Key":"firstName",
"Value":"#{#fname}"
},
{
"Key":"country",
"Value":"#{#country}"
}
],
"Resubscribe":true,
"RestartSubscriptionBasedAutoresponders":true
}
BODY_CONTENT
)

You can use heredoc as explained here
Double-quoting rules are also followed if you put double quotes around
the identifier. However, do not put double quotes around the
terminator.
puts <<"QUIZ"
Student: #{name}
1.\tQuestion: What is 4+5?
\tAnswer: The sum of 4 and 5 is #{4+5}
QUIZ

You can use here documents:
name = 'John'
<<EOS
This is #{name}
EOS
Alternatively you can use flexible quotes, they can handle both ' and " characters:
name = 'John'
%{
This is #{name}
}
Flexible quoting works with %() and %!! as well.

Related

How do I add attributes to a nested XML array using Savon?

I am using savon version 2.2 to call some SOAP services. For simple services everything is working OK. However one service has a complex structure like the example below with both repeating groups and attributes on each group:
<sch:RequestControl>
<sch:requestID>6989668868</sch:requestID>
</sch:RequestControl>
<sch:InquiryParam>
<sch:crmParam name="AccountNumber">1234567</sch:crmParam>
<sch:crmParam name="History">1</sch:crmParam>
</sch:InquiryParam>
My current message looks like this:
<RequestControl>
<requestID>6989668868</requestID>
</RequestControl>
<InquiryParam>
<crmParam>1234567</crmParam>
<attributes>
<crmParam>
<name>AccountNumber</name>
</crmParam>
</attributes>
</InquiryParam>
<InquiryParam>
<crmParam>1</crmParam>
<attributes>
<crmParam>
<name>History</name>
</crmParam>
</attributes>
</InquiryParam>
The above is produced using this logic:
message = { :RequestControl =>
{ :requestID => 6989668868 },
:InquiryParam => [
{ :crmParam => { :content! => #account_number } ,
:attributes => { "crmParam" => {"name" => "AccountNumber"} } },
{ :crmParam => { :content! => #history } ,
:attributes => { "crmParam" => {"name" => "History"} } } ]
}
I've tried various combinations using :crmParam => { :content! => #account_number, :attributes => {'name'=>'AccountNumber'} } and similar based on the savon and gyoku documentation but have run onto a brick wall in getting the XML to format like the example. I know I can brute force the message by assigning it to xml but that makes it difficult to see what's going on.
Can anyone suggest a fix to have the attributes inside the crmParam tags?
I'm not sure Savon handles a Ruby array as you'd like, but the following script should give you a better idea what you can do.
require 'savon'
c = Savon.client(endpoint: "http://www.example.com",
namespace: "urn:ns.example.com",
log: true,
log_level: :debug,
pretty_print_xml: true)
r = c.call(:call,
:message => {
:InquiryParam => [
{"crmParam" => 123,
:attributes! => { "crmParam" => { "name" => "AccountNumber" }}},
{"crmParam" => 456,
:attributes! => { "crmParam" => { "name" => "history" }}}
]
}

How can I implement this POST request using HTTParty?

I am having difficulty making a POST request to an API endpoint using Ruby's HTTParty library. The API I'm interacting with is the Gittip API and their endpoint requires authentication. I have been able to successfully make an authenticated GET request using HTTParty.
You can see in the example code:
user = "gratitude_test"
api_key = "5962b93a-5bf7-4cb6-ae6f-aa4114c5e4f2"
# I have included real credentials since the above is merely a test account.
HTTParty.get("https://www.gittip.com/#{user}/tips.json",
{ :basic_auth => { :username => api_key } })
That request works and returns the following as expected:
[
{
"amount" => "1.00",
"platform" => "gittip",
"username" => "whit537"
},
{
"amount" => "0.25",
"platform" => "gittip",
"username" => "JohnKellyFerguson"
}
]
However, I have been unable to make a successful POST request using HTTParty. The Gittip API describes making a POST request using curl as follows:
curl https://www.gittip.com/foobar/tips.json \
-u API_KEY: \
-X POST \
-d'[{"username":"bazbuz", "platform":"gittip", "amount": "1.00"}]' \
-H"Content-Type: application/json"
I have tried (unsuccessfully) structuring my code using HTTParty as follows:
user = "gratitude_test"
api_key = "5962b93a-5bf7-4cb6-ae6f-aa4114c5e4f2"
HTTParty.post("https://www.gittip.com/#{user}/tips.json",
{
:body => [ { "amount" => "0.25", "platform" => "gittip", "username" => "whit537" } ],
:basic_auth => { :username => api_key },
:headers => { 'Content-Type' => 'application/json' }
})
The first argument is the url and the second argument is an options hash. When I run the code above, I get the following error:
NoMethodError: undefined method `bytesize' for [{"amount"=>"0.25", "platform"=>"gittip", "username"=>"whit537"}]:Array
from /Users/John/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/net/http/generic_request.rb:179:in `send_request_with_body'
I have tried various other combinations of structuring the API call, but can't figure out how to get it to work. Here's another such example, where I do not user an array as part of the body and convert the contents to_json.
user = "gratitude_test"
api_key = "5962b93a-5bf7-4cb6-ae6f-aa4114c5e4f2"
HTTParty.post("https://www.gittip.com/#{user}/tips.json",
{
:body => { "amount" => "0.25", "platform" => "gittip", "username" => "whit537" }.to_json,
:basic_auth => { :username => api_key },
:headers => { 'Content-Type' => 'application/json' }
})
Which returns the following (a 500 error):
<html>
<head>
<title>500 Internal Server Error</title>
</head>
<body>\n Internal server error, program!\n <pre></pre>
</body>
</html>
I'm not really familiar with curl, so I'm not sure if I am incorrectly translating things to HTTParty.
Any help would be appreciated. Thanks.
Just a guess, but it looks like you're passing a hash in the body when JSON is expected.
Try replacing the :body declaration with:
:body => [{ "amount" => "0.25",
"platform" => "gittip",
"username" => "whit537" }].to_json
Edit:
I suggested the to_json serializer, but misplaced it by putting it after the hash instead of the array and removing the array altogether. The example uses multiple records, so the array is necessary.
After looking at this thread, it looks like Gittip is picky about the accept header.
:headers => { 'Content-Type' => 'application/json', 'Accept' => 'application/json'}
So, the full suggestion is:
HTTParty.post("https://www.gittip.com/#{user}/tips.json",
{
:body => [ { "amount" => "0.25", "platform" => "gittip", "username" => "whit537" } ].to_json,
:basic_auth => { :username => api_key },
:headers => { 'Content-Type' => 'application/json', 'Accept' => 'application/json'}
})

Perl 2D array comparison issues

I'm coding a perl script that audits a library and compares the list of installed software with a list from another machine to ensure that they are working off of the same stuff. I've taken the raw data and placed it into two, 2-dimensional arrays of size Nx4 where N is the number of software titles. For example:
[Fileset1], [1.0.2.3], [COMMITTED], [Description of file]
[Fileset2], [2.4.2.2], [COMMITTED], [Description of a different file]
....
I now need to compare the two lists to find discrepancies, whether they be missing files of level differences. Not being a perl pro yet, the only way I can conceive of doing this is to compare each element of the first array against each element of the other array to look first for matching filesets with different levels or no matching filesets at all. The I would have to repeat the process with the other list to ensure that I'd found all possible differences. Obviously with this procedure I'm looking at efficiency of greater than n^2. I was wondering if there was some application of grep that I could make use of or something similar to avoid this when comparing libraries with upwards of 20,000 entries.
In short, I need to compare two 2 dimensional arrays and keep track of the differences for each list, instead of merely finding the intersection of the two.
Thanks in advance for the help!
The output is a little unwieldy, but I like Data::Diff for tasks like this:
use Data::Diff 'Diff';
use Data::Dumper;
#a = ( ["Fileset1", "1.0.2.3", "COMMITTED", "Description of file" ],
["Fileset2", "2.4.2.2", "COMMITTED", "Description of a different file" ],
["Fileset3", "1.2.3.4", "COMMITTED", "Description of a different file" ] );
#b = ( ["Fileset1", "1.0.2.3", "COMMITTED", "Description of file" ],
["Fileset2", "2.4.2.99", "COMMITTED", "Description of a different file" ] );
$out = Diff(\#a,\#b);
print Dumper($out);
Result:
$VAR1 = {
'diff' => [
{
'uniq_a' => [
'2.4.2.2'
],
'same' => [
{
'same' => 'COMMITTED',
'type' => ''
},
{
'same' => 'Description of a different file',
'type' => ''
},
{
'same' => 'Fileset2',
'type' => ''
}
],
'type' => 'ARRAY',
'uniq_b' => [
'2.4.2.99'
]
}
],
'uniq_a' => [
[
'Fileset3',
'1.2.3.4',
'COMMITTED',
'Description of a different file'
]
],
'same' => [
{
'same' => [
{
'same' => '1.0.2.3',
'type' => ''
},
{
'same' => 'COMMITTED',
'type' => ''
},
{
'same' => 'Description of file',
'type' => ''
},
{
'same' => 'Fileset1',
'type' => ''
}
],
'type' => 'ARRAY'
}
],
'type' => 'ARRAY'
};

How to avoid uri encoding on JSON when posting from Ruby?

I am trying to write a simple http post which will send a json body to a restful api. I am using the following code:
data = {'EmailAddress' => email, 'Name' => 'bobby', 'CustomFields' => [ {'Key' => 'Country', 'Value' => 'canada'}, {'Key' => 'City', 'Value' => 'vancouver'} ], 'Resubscribe' => true }.to_json
require 'net/http'
net = Net::HTTP.new("api.createsend.com", 80)
request = Net::HTTP::Post.new("/api/v3/subscribers/#{#list}.json")
request.basic_auth(#api, 'magic')
request.set_form_data(:body => data)
response = net.start do |http|
http.request(request)
end
puts response.code
puts response.read_body
The trouble I am having is the body is going to the server as a string and not as hex. Here is what I am sending:
body=%7b%22EmailAddress%22%3a%223%40blah.com%22%2c%22Name%22%3a%22bobby%22%2c%22CustomFields%22%3a%5b%7b%22Key%22%3a%22Country%22%2c%22Value%22%3a%22canada%22%7d%2c%7b%22Key%22%3a%22City%22%2c%22Value%22%3a%22vancouver%22%7d%5d%2c%22Resubscribe%22%3atrue%7d
Here is what I want to send:
{
"EmailAddress": "3#blah.com",
"Name": "bobby",
"CustomFields" : [
{
"Key":"Country",
"Value":"canada"
},
{
"Key":"City",
"Value":"vancouver"
}
],
"Resubscribe": true
}
How can I pack this data so it is not going out as a string?
Instead of:
request.set_form_data(:body => data)
Try it like this:
request.body = data
net/http should not be uri-encoding the post body, if you see that happening then maybe something else along the way is doing it or maybe you're just mistaken.

Using Typhoeus to POST an array to a URL

I'm using Typhoeus to post a hash to my API url. It's actually an array containing a set of hashes. Here's effectively what I'm doing:
companies = Array.new
company = { 'name' => 'Company 1' , 'company_url' => 'http://company.com' }
companies.push(company)
company2 = {'name' => 'Company 2' , 'company_url' => 'http://company2.com' }
companies.push(company2)
request = Typhoeus::Request.post("http://myapi.com/1.0/startups/create_batch",
:username => 'user',
:password => 'password',
:auth_method => :basic,
:params => {'companies' => companies} )
print "Create_batch response "+request.body
Once I run the script I get the output which states "Create_batch response Disallowed Key Characters.". I'm not sure what it's referencing at this point. I've looked over the text output of what print companies shows up but I don't see any strange code.
Anybody have any insights on what I should do?

Resources