How do I setup geocoder with google_premier? - ruby-on-rails

I've read the docs for the geocoder gem which state you can set a key, client and channel when using Google Premier.
According to some other posts I've read here, it's now possible to use an API key and still not pay as long as you're below the free threshold. We need to do this as we host with Heroku and we keep hitting our daily limit. We're not ourselves, but without any sort of other identification, we're probably reaching a limit identified by IP shared with other Heroku sites. Using a key will help identify us and therefore keep us from hitting a limit.
However, when I look at the sign up pages for the Google API, there are a baffling array of client ids, api keys and secrets, for installed apps, web apps and so on. Which combination is the one required to make geocoder burst into life?

To answer the question :
When subscribing to Google Premier, you should have received a client id starting by gme- and a key (see https://developers.google.com/maps/documentation/business/articles/prelaunch_checklist#welcome_letter)
The third argument needed by geocoder is the channel, that can be any kind of string (see https://developers.google.com/maps/documentation/business/guide#Channels )
You need to add the list of authorised urls originating the requests in the Google Portal (see https://developers.google.com/maps/documentation/business/guide#URLs ).
From the Geocoder doc, you can use a setting like :
# -*- encoding : utf-8 -*-
Geocoder.configure do |config|
config.lookup = :google_premier
config.api_key = ["gme-client-id","key", "channel"]
config.timeout = 10
config.units = :km
end
But it would probably be a better choice to use client-side geocoding like recommended here : https://developers.google.com/maps/articles/geocodestrat?hl=fr#client

This worked for me:
Geocoder.configure(
:lookup => :google_premier,
:api_key => [ 'GOOGLE_CRYPTO_KEY', 'GOOGLE_CLIENT_ID', 'GOOGLE_CHANNEL' ],
:timeout => 5,
:units => :km,
)
You'll need to substitute in the corresponding values from your Google Maps for Business welcome email. Channel is a value of your choosing.

Related

Ruby Geocoder for google business

Im using the Geocoder gem for ruby. With V2 of the google maps API for business you could pass in your API key in config/initializers/geocoder.rb in V3 of the API they no longer give you an API key but rather a client-id which is basically a cryptographic key that you use to create a signature for the url. Since I cannot obtain an API Key I dont quite know how to do the latter. Has anyone ran into this problem? If so could you please point me in a direction other than googles documentation.
The following config should work(Replace with your own information):
# -*- encoding : utf-8 -*-
Geocoder.configure do |config|
config.lookup = :google_premier
config.api_key = [ 'GOOGLE_CRYPTO_KEY', 'GOOGLE_CLIENT_ID', 'GOOGLE_CHANNEL' ]
config.timeout = 10
config.units = :km
end

Best way to upload files to Box.com programmatically

I've read the whole Box.com developers api guide and spent hours on the web researching this particular question but I can't seem to find a definitive answer and I don't want to start creating a solution if I'm going down the wrong path. We have a production environment where as once we are finished working with files our production software system zips them up and saves them into a local server directory for archival purposes. This local path cannot be changed. My question is how can I programmatically upload these files to our Box.com account so we can archive these on the cloud? Everything I've read regarding this involves using OAuth2 to gain access to our account which I understand but it also requires the user to login. Since this is an internal process that is NOT exposed to outside users I want to be able to automate this otherwise it would not be feasable for us. I have no issues creating the programs to trigger everytime a new files gets saved all I need is to streamline the Box.com access.
I just went through the exact same set of questions and found out that currently you CANNOT bypass the OAuth process. However, their refresh token is now valid for 60 days which should make any custom setup a bit more sturdy. I still think, though, that having to use OAuth for an Enterprise setup is a very brittle implementation -- for the exact reason you stated: it's not feasible for some middleware application to have to rely on an OAuth authentication process.
My Solution:
Here's what I came up with. The following are the same steps as outlined in various box API docs and videos:
use this URL https://www.box.com/api/oauth2/authorize?response_type=code&client_id=[YOUR_CLIENT_ID]&state=[box-generated_state_security_token]
(go to https://developers.box.com/oauth/ to find the original one)
paste that URL into the browser and GO
authenticate and grant access
grab the resulting URL: http://0.0.0.0/?state=[box-generated_state_security_token]&code=[SOME_CODE]
and note the "code=" value.
open POSTMAN or Fiddler (or some other HTTP sniffer) and enter the following:
URL: https://www.box.com/api/oauth2/token
create URL encoded post data:
grant_type=authorization_code
client_id=[YOUR CLIENT ID]
client_secret=[YOUR CLIENT SECRET]
code= < enter the code from step 4 >
send the request and retrieve the resulting JSON data:
{
"access_token": "[YOUR SHINY NEW ACCESS TOKEN]",
"expires_in": 4255,
"restricted_to": [],
"refresh_token": "[YOUR HELPFUL REFRESH TOKEN]",
"token_type": "bearer"
}
In my application I save both auth token and refresh token in a format where I can easily go and replace them if something goes awry down the road. Then, I check my authentication each time I call into the API. If I get an authorization exception back I refresh my token programmatically, which you can do! Using the BoxApi.V2 .NET SDK this happens like so:
var authenticator = new TokenProvider(_clientId, _clientSecret);
// calling the 'RefreshAccessToken' method in the SDK
var newAuthToken = authenticator.RefreshAccessToken([YOUR EXISTING REFRESH TOKEN]);
// write the new token back to my data store.
Save(newAuthToken);
Hope this helped!
If I understand correctly you want the entire process to be automated so it would not require a user login (i.e run a script and the file is uploaded).
Well, it is possible. I am a rookie developer so excuse me if I'm not using the correct terms.
Anyway, this can be accomplished by using cURL.
First you need to define some variables, your user credentials (username and password), your client id and client secret given by Box (found in your app), your redirect URI and state (used for extra safety if I understand correctly).
The oAuth2.0 is a 4 step authentication process and you're going to need to go through each step individually.
The first step would be setting a curl instance:
curl_setopt_array($curl, array(
CURLOPT_URL => "https://app.box.com/api/oauth2/authorize",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "content-type: application/x-www-form-urlencoded",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS =>
"response_type=code&client_id=".$CLIENT_ID."&state=".$STATE,
));
This will return an html text with a request token, you will need it for the next step so I would save the entire output to a variable and grep the tag with the request token (the tag has a "name" = "request_token" and a "value" which is the actual token).
Next step you will need to send another curl request to the same url, this time the post fields should include the request token, user name and password as follows:
CURLOPT_POSTFIELDS => "response_type=code&client_id=".$CLIENT_ID."&state=".$STATE."&request_token=".$REQ_TOKEN."&login=".$USER_LOGIN."&password=".$PASSWORD
At this point you should also set a cookie file:
CURLOPT_COOKIEFILE => $COOKIE, (where $COOKIE is the path to the cookie file)
This will return another html text output, use the same method to grep the token which has the name "ic".
For the next step you're going to need to send a post request to the same url. It should include the postfields:
response_type=code&client_id=".$CLIENT_ID."&state=".$STATE."&redirect_uri=".$REDIRECT_URI."&doconsent=doconsent&scope=root_readwrite&ic=".$IC
Be sure to set the curl request to use the cookie file you set earlier like this:
CURLOPT_COOKIEFILE => $COOKIE,
and include the header in the request:
CURLOPT_HEADER => true,
At step (if done by browser) you will be redirected to a URL which looks as described above:
http://0.0.0.0(*redirect uri*)/?state=[box-generated_state_security_token]&code=[SOME_CODE] and note the "code=" value.
Grab the value of "code".
Final step!
send a new cur request to https//app.box.com/api/oauth2/token
This should include fields:
CURLOPT_POSTFIELDS => "grant_type=authorization_code&code=".$CODE."&client_id=".$CLIENT_ID."&client_secret=".$CLIENT_SECRET,
This will return a string containing "access token", "Expiration" and "Refresh token".
These are the tokens needed for the upload.
read about the use of them here:
https://box-content.readme.io/reference#upload-a-file
Hope this is somewhat helpful.
P.S,
I separated the https on purpuse (Stackoverflow wont let me post an answer with more than 1 url :D)
this is for PHP cURL. It is also possible to do the same using Bash cURL.
For anyone looking into this recently, the best way to do this is to create a Limited Access App in Box.
This will let you create an access token which you can use for server to server communication. It's simple to then upload a file (example in NodeJS):
import box from "box-node-sdk";
import fs from "fs";
(async function (){
const client = box.getBasicClient(YOUR_ACCESS_TOKEN);
await client.files.uploadFile(BOX_FOLDER_ID, FILE_NAME, fs.createReadStream(LOCAL_FILE_PATH));
})();
Have you thought about creating a box 'integration' user for this particular purpose. It seems like uploads have to be made with a Box account. It sounds like you are trying to do an anonymous upload. I think box, like most services, including stackoverflow don't want anonymous uploads.
You could create a system user. Go do the Oauth2 dance and store just the refresh token somewhere safe. Then as the first step of your script waking up go use the refresh token and store the new refresh token. Then upload all your files.

s3 bucket..The bucket you are attempting to access must be addressed using the specified endpoint. Please send all future requests to this endpoint

Hi I'm using below code to get the size of a bucket.Researched all over but the only way was to loop through each file.While looping through ,some buckets seems to created in a different region and I'm ending up with above error
AWS::S3::PermanentRedirect: The bucket you are attempting to access must be addressed using the specified endpoint. Please send all future requests to this endpoint. from /home//.rvm/gems/ruby-1.9.2-p180/gems/aws-s3-0.6.2/lib/aws/s3/error.rb:38:in `raise'
The end point is us-west-1,
Need help in fixing the above issue also how do I switch my code dynamically to region where my bucket belongs to. Also need suggestion on adding exception in case of failure Below is my code.
Please feel free to comment.
def get_bucket
s3 = AWS::S3::Base.establish_connection!(:access_key_id => #config[:ACCESS_KEY_ID], :secret_access_key => #config[:SECRET_ACCESS_KEY])
if !s3.nil?
AWS::S3::Service.buckets.each do |bucket|
puts bucket.inspect
if !bucket.nil?
size = 0
# I'm harding coding below bucket names, for code not to fail
if ![
'cf-templates-m01ixtvp0jr0-us-west-1',
'cf-templates-m01ixtvp0jr0-us-west-2',
'elasticbeanstalk-us-west-1-767904627276',
'elasticbeanstalk-us-west-1-akiai7bucgnrthi66w6a',
'medidata-rave-cdn'
].include? bucket.name
bucket_size = AWS::S3::Bucket.find(bucket.name)
if !bucket_size.nil?
bucket_size.each do |obj|
if !obj.nil?
size += obj.size.to_i
end
end
end
end
load_bucket(bucket.name,bucket.creation_date,size,#config[:ACCOUNT_NAME])
end
end
end
end
The problem is that buckets can exist in different regions, and while you can list all buckets from the same connection (unlike other AWS entities that are locked to the location they were created in), other operations on buckets require you to log in to the specific "endpoint" (region) to which they are constrained.
My solution is to check where the bucket is located and then re-login to that region:
s3 = AWS::S3.new(#awscreds)
if s3.buckets[bucket].location_constraint != #awscreds[:region] then
# need to re-login, otherwise the S3 upload will fail
s3 = AWS::S3.new(#awscreds.merge(region: s3.buckets[bucket].location_constraint))
end
I don't understand how you're building the URL to access your bucket.
If it's in US-Standard, you can say http://s3.amazonaws.com/BUCKETNAME/path/to/file. If it's anywhere else, that doesn't work (non-coincidentally, you're limited to domain-allowed characters (lowercase and numbers only) for bucket names) and you use http://BUCKETNAME.s3.amazonaws.com/path/to/file.
This article may be of help: http://docs.aws.amazon.com/general/latest/gr/rande.html

Can't get views by insightTrafficSourceType — YouTube Analytics API

So I'm using the 'google-api-client' gem with Rails, and I'm attempting to call the URL below in order to get video views by day and insightTrafficSourceType. This is a call that appears to be allowable from the Available Reports documentation page.
Additionally, I found that I was able to make this call by using the API Explorer tool provided by Google.
URL:
https://www.googleapis.com/youtube/analytics/v1beta1/reports?metrics=views&ids=channel==CHANNEL_ID&dimensions=day,insightTrafficSourceType&filter=video==VIDEO_ID&start-date=2013-01-15&end-date=2013-01-16&start-time=1970-01-01
Result:
{
:error=>
{
"errors"=>[
{
"domain"=>"global",
"reason"=>"invalid",
"message"=>"Unknown identifier (insightTrafficSourceType) given in field parameters.dimensions."
}
],
"code"=>400,
"message"=>"Unknown identifier (insightTrafficSourceType) given in field parameters.dimensions."
}
}
I'm not sure what extra data I can provide in the initial description of this bug, but as stated before I am making the call to the API with the Google::APIClient Ruby library. The actual code itself looks like this:
client.execute(
:api_method => api.reports.query,
:parameters => options
)
You are still referencing the old beta API, i.e., in your URL, you have 'v1beta' and you should have 'v1' there. Try replacing that and running it again. Also, you can look at the api explorer to see the exact URL that should be generated in live examples with your acct (once you enable OAuth) here:
https://developers.google.com/youtube/analytics/v1/
(Look at the bottom of the page.)
Finally, start-time isn't a parameter listed on the production version of the API, so you will want to remove that as well.

Does Geocoder gem work with google API key?

I am using ruby geocoder gem for my project and as the project is growing I am starting to look into connecting to the Google API key. After adding this to the project:
Geocoder.configure do |config|
# geocoding service (see below for supported options):
config.lookup = :google
# to use an API key:
config.api_key = 'my_key'
# geocoding service request timeout, in seconds (default 3):
config.timeout = 5
end
I get Google Geocoding API error: request denied. when I start the application. From reading around, it seems like others switch over to yahoo if they choose to continue using the gem. Can I configure the gem to work with google api key? Mainly, I would like to keep an eye out for the amount of daily queries to avoid going over the limit.
Geocoder supports Google api keys for Google Premier accounts only.
Its found here in the readme on github: https://github.com/alexreisner/geocoder#google-google-google_premier
If you have a Google Premier api key you just need to put this in an intializer:
# config/initializers/geocoder.rb
Geocoder.configure(:lookup => :google_premier, :api_key => "...")
And your Geocoder will use your premier key.
I had this issue today and managed to solve it by setting use_https e.g.
Geocoder.configure(
timeout: 15,
api_key: "YOUR_KEY",
use_https: true
)
create a file: config/initializers/geocoder.rb and setup like this:
Geocoder.configure(
lookup: :google_premier,
api_key: ['api_key', 'client_id', 'client_id_type'],
)
Geocoder works fine with the free tier of their Map API. However, to make it work I had to register a key using this page specifically.
https://console.developers.google.com/flows/enableapi?apiid=geocoding_backend&keyType=SERVER_SIDE
And set up the configuration
# config/initializers/geocoder.rb
Geocoder.configure(
api_key: 'KEY_HERE',
use_https: true
)
By default Geocoder uses Google's geocoding API to fetch coordinates and street addresses. So, I think that a Google API key should work on the initializer.
I hope this work for you.
Geocoder.configure(
# geocoding service
lookup: :google,
# geocoding service request timeout (in seconds)
timeout: 3,
# default units
units: :km
)
This work for me. You can call API from rails console with geocoder doc at http://www.rubygeocoder.com/ than call it from view /my_map/show.html.erb replace address or city etc with <%= #place.address %>
If anyone is still looking at this, for some reason the Google API changed and Geocoder no longer works with the standard config file. However, you can simply not use the Geocoder gem for geocoding and reverse geocoding (don't use Geocoder.search) and use any http request gem to directly call the google api, as of this moment using RestClient the api call would be
response = RestClient.get 'https://maps.googleapis.com/maps/api/geocode/json?address=' + sanitized_query + '&key=' + your_key
where sanitized query can be either an address like Cupertino, CA or a lat=x, lng=y string for geocoding or reverse geocoding. It is not necessary to get a Google premier account.

Resources