Reading JavaScript variable in Ruby through curl request - ruby-on-rails

I need to read the GBP rate from this javascript file: http://cdn.shopify.com/s/javascripts/currencies.js. I want to be able to get the js variable as JSON so that I can easily access the variable I need with its index. I tried a couple of ways as follows with eventually no success.
Way 1
Source: https://docs.ruby-lang.org/en/2.0.0/Net/HTTP.html
My code:
uri = URI('http://cdn.shopify.com/s/javascripts/currencies.js')
#response = Net::HTTP.get(uri) # => String
Result: I get the result as a string and reading the GBP rate from the string is difficult and probably not the correct way.
Way 2
Source: curl request in ruby
My Code:
url = 'http://cdn.shopify.com/s/javascripts/currencies.js'
mykey = 'demo'
uri = URI(url)
request = Net::HTTP::Get.new(uri.path)
request['Content-Type'] = 'application/xml'
request['Accept'] = 'application/xml'
request['X-OFFERSDB-API-KEY'] = mykey
#response = Net::HTTP.new(uri.host,uri.port) do |http|
http.request(request)
end
Result: This returns me Net::HTTP:0x007f2480874050 which looks like a memory address, definitely not what I want.
In addition, I've included require 'net/http', require 'json' in my controller in either case.
I am very new to Ruby and I don't know how to figure this out. So looking for someone who can help.

This is a bit of a weird request, IMO, but Rails can do it. Rails comes with a library called execjs automatically, which lets you run javascript from ruby. So, you have some javascript you want to run in that file, but you also want to return specific key from that javascript, so something like this should do it:
# Expanding upon 'Way 1', which got you the javascript as a string
uri = URI('http://cdn.shopify.com/s/javascripts/currencies.js')
response = Net::HTTP.get(uri)
gbp_rate = ExecJS.exec "#{response}; return Currency.rates.GBP;"
p gbp_rate # => 1.40045
I just want to reiterate (from their FAQ in the README) though:
Can ExecJS be used to sandbox scripts?
No, ExecJS shouldn't be used for any security related sandboxing. Since runtimes are automatically detected, each runtime has different sandboxing properties. You shouldn't use ExecJS.eval on any inputs you wouldn't feel comfortable Ruby eval()ing.
This file looks safe, but just keep it in mind, you are actually executing this javascript.
Personally, I would look to see if there's an API somewhere that can give you this value more easily, or if it doesn't change often (I have never used Shopify so don't know how much this changes) just hardcode it in the app as a config value and update it manually. Just feels cleaner, to me.

Related

How to use external API in Ruby in Rails

I need to use an external API in my app in order to have companies informations. Beginning and having never used API in ruby, I don't know where to start. Maybe there is a gem for it but I have found 2 API that returns me JSON : https://datainfogreffe.fr/api/v1/documentation and https://firmapi.com/ (they're in french sorry about that).
Does someone have a good tutorial or hints to help me begin ?
The final need is to retrieve companies datas just by giving the company ID.
You can use Net::HTTP to call APIs in Ruby on Rails.
uri = URI(url)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Post.new(uri.path, {'Content-Type' => 'application/json'})
request.body = {} # SOME JSON DATA e.g {msg: 'Why'}.to_json
response = http.request(request)
body = JSON.parse(response.body) # e.g {answer: 'because it was there'}
http://ruby-doc.org/stdlib-2.3.1/libdoc/net/http/rdoc/Net/HTTP.html
You can use gem for calling REST APIs in ruby.
Also, if you want to find any ruby gem for any purpose you can have a look at this.
You can have a look at this to get company details.
You need to use HTTP client library. There are a few popular libraries:
HTTParty
Faraday
Built-in Net::HTTP
Rest-Client
HTTPClient
You can take a look and compare them on Ruby Toolbox:
https://www.ruby-toolbox.com/categories/http_clients
Faraday is the most popular one. But it is the heaviest also because it covers most cases. So check documentation for each and depending on your task pick one that works the best.

Ruby library with least footprint to host a very simple single endpoint API

I have a very simple number crunching Ruby function that I want to make available via a web API. The API is essentially a single endpoint, e.g. http://example.com/crunch/<number> and it returns JSON output.
I can obviously install Rails and implement this quickly. I require no more help from a 'framework' other than to handle HTTP for me. No ORM, MVC and other frills.
On the far end, I can write some Ruby code to listen on a port and accept GET request and parse HTTP headers etc. etc. I don't want to re-invent that wheel either.
What can I use to expose a minimal API to the web using something with the least footprint/dependencies. I read about Sinatra, Ramaze, etc., but I believe there can be a way to do something even simpler. Can I just hack some code on top of Rack to do what I am trying to do?
Or in other words, what will be the simplest Ruby equivalent of the following code in nodejs:
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
var ans = crunch(number);
res.end(ans);
}).listen(1337, "127.0.0.1");
console.log('Server running at http://127.0.0.1:1337/');
You seem like you want to use Rack directly. "Rack from the Beginning" is a decent tutorial that should get you started.
It'll probably look something like this:
class CrunchApp
def self.crunch(crunchable)
# top-secret crunching
end
def self.call(env)
crunchy_stuff = input(env)
[200, {}, crunch(crunchy_stuff)]
end
private
def self.input(env)
request = Rack::Request.new(env)
request.params['my_input']
end
end
Rack::Server.start app: CrunchApp
But I must say, using that instead of something like Sinatra seems silly unless this is just a fun project to play with things. See their 'Hello World':
require 'sinatra'
get '/hi' do
"Hello World!"
end
Ruby-Grape is a good option for your use case. It has a minimal implementation over Rack that allow the creation of simple REST-API endpoints.
Cuba is another good option with a thin layer over Rack itself.sample post
If you are familiar with Rails you can use the Rails API gem which is very well documented with minor overhead. Remember also that Rails-API will be part of Rails 5.
Last, but not last you can implement it on Rack directly.

Ruby on Rails Directory Path

I need to print Ruby on Rails complete url in my application. in details
with RAILS_ROOT I m getting a url like this
D:/projects/rails_app/projectname/data/default.jpg
But for my application I need a path like this
http://localhost:3000/data/default.jpg
Please help me to solve this issue. I am using Rails 2
Thanks
Today we use URI. Simply require the library and you will be able to parse your current dynamic and static URI any way you please. For example I have a function that can read URI parameters like so...
#{RAILS_ROOT}/app/helpers/application_helper.rb (The literal path string of the file depicted below)
def read_uri(parameter)
require 'uri'
#raw_uri = URI.parse(request.original_fullpath)
#uri_params_raw = #raw_uri.query
if #uri_params_raw =~ /\=/
#uri_vars = #uri_params_raw.split('=')
return #uri_vars[parameter]
end
return false
end
This should split all URI parameters into an array that gives the requested (numeric) "parameter".
I believe that simply the URI.parse(request.original_fullpath) should work for you.
I come from using a minimum of rails 4.2.6 with this method so, I hope it works for anyone who might view this later on. Oh, and just as a disclaimer: I wasn't so wise to rails at the time of posting this.

Is a framework required for Ruby to accept POST requests?

Is there a way to use a flat .rb file to accept POST requests, or do I need to use a framework like Rails or Sinatra to accept the request?
I'm thinking along the lines of how I can use a flat .php file to accept POST requests, and use the $_REQUEST[] variable to access passed data.
Even more specifically, I'm trying to learn a bit of Ruby by porting over one of my Twilio apps from PHP. The app accepts SMS, processes the message sent, and sends a reply based on the body of the message received.
While using PHP, I can set the SMS Request URL in the Twilio site to my PHP file. The PHP file uses the $_REQUEST[] array to use the message that was received. (It seems like the Ruby equivalent to this is params[].)
Here's a quick example of the PHP version of what I'm talking about:
<?php
require "twilio.php"; // Twilio Library
$ApiVersion = "2010-04-01"; // Twilio API Version
$AccountSid = "SID"; // Twilio SID
$AuthToken = "TOKEN"; // Twilio Token
// Instantiate a new Twilio Rest Client
$client = new TwilioRestClient($AccountSid, $AuthToken);
// Get message body & who it's from, for the SMS that was just received
$SMSbody = mysql_real_escape_string($_REQUEST['Body']);
if ($SMScode == "codeword"){
$SMSresponse = "You know the code.";
}
else{
$SMSresponse = "You do not know the code.";
}
// Twilio response to the sender
header("content-type: text/xml");
echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
?>
<Response>
<Sms><?php echo $SMSresponse;?></Sms>
</Response>
Here's my attempt at a Ruby equivalent, which is probably offensively bad:
require "rubygems"
require "twilio-ruby"
#account_sid = "SID"
#auth_token = "TOKEN"
smsbody = params['body']
#client = Twilio::REST::Client.new(#account_sid, #auth_token)
#account = #client.accounts.get(#account_sid)
if smsbody == "codeword"
smsreply = "You know the code"
else
smsreply = "You do not know the code"
response = Twilio::TwiML::Response.new do |r|
r.Sms smsreply
end
# print the result
puts response.text
This results in the Twilio debugging dashboard stating that the reply was more than 160 characters. This is because the reply is the full Ruby code, not the result of having ran the Ruby code. This makes me think that the POST request isn't being accepted correctly...
You don't need to use a framework, and based on your description Rails would definitely be overkill for you. However, using a lightweight framework can make some aspects a bit nicer. I'd recommend looking at Camping if you haven't already - it is intended for single file apps.
Based on the existing answers, and all the other research I've done, it doesn't seem like there's one single Answer to this question. It's another one of those TIMTOWTDI situations. Here's a summary of what I've learned so far, though…
The ability to drop PHP files into Apache & have it work properly is made possible by mod_php, which is enabled by default (making it seem seamless).
The params[] array is actually a Rails-specific helper. To get the same functionality, one would have to parse the request body (STDIN) on their own (perhaps with the CGI.parse function provided by the CGI module).
There seem to be a few options in my case:
Use Passenger to let Apache run a Rack-based Ruby app (like Camping,
Sinatra, or Rack)
Use a pure Ruby web server like Unicorn or Thin
Call the Ruby script via PHP's passthru function
The way forward for someone who wants to stick to strictly-Ruby (not using the PHP passthru function) without straying too far away from the familiarity of Apache might be to use Passenger with either Camping or Sinatra.
How do you execute that code? As far as I know the params hash is Rails specific, you can't use it in a simple script like that.
Coming to your question you can't simply drop a ruby file inside your server and expect that it will be executed. It will be simply returned as a text file to the browser.
To execute ruby code in a webserver you need at least rack and a server capable of executing rack applications or an apache module which process ruby. This is not a simple setup like php.
You have two choices here:
Play with ruby console and/or ruby command line, i.e. from the shell run ruby your-script-name to execute it or type irb to start a ruby console. It's one of most powerful ruby feature, one of the thing that make me love ruby.
If you really want to execute your script in a webserver context and you have php installed, you can exec your ruby script calling it from php.
This is an example on how to do that supposing your file is named program.rb, add the shebang line as first line and use the ARGV array instead of the params hash:
#!/usr/bin/env ruby
^^^^ Add this line as first line of your script ^^^^
require "rubygems"
require "twilio-ruby"
...
smsbody = ARGV[0] # ARGV[0] is the first command line parameter
Make it executable with chmod +x program.rb, and then call it from your php script with
passthru("/path/to/your/ruby/program.rb ". escapeshellarg($_REQUEST['Body']));
in this way the output from passthru (the output of your ruby program) will be sent to the browser.

Rails 3 application/octet-stream

I am working on an application where I use paperclip for uploading images, then the image is manipulated in a flash app and returned to my application using application/octet-stream. The problem is that the parameters from flash are not available using params. I have seen examples where something like
File.open(..,..) {|f| f.write(request.body) }
but when I do this, the file is damaged some how.
How can I handle this in rails 3?
After you make sure that the request parameters have hit the Rails application, you may want to ensure that there were no parsing problems. Try to add these lines in you controller's action:
def update # (or whatever)
logger.debug "params: #{params.inspect}"
# I hope you do not test this using very large files ;)
logger.debug "request.raw_post: #{request.raw_post.inspect}"
# ...
end
Maybe the variable names got changed somehow? Maybe something escaped the parameter string one time too much?
Also, you have said that the file into which you want to save the request body is damaged. How exactly?
The request.body object does not need to be String. It may be a StringIO, for example, so you may want to type this:
File.open(..,..) {|f| f.write(request.body.read) }

Resources