{"id":21555027,"url":"https://github.com/algonauti/google_maps_juice","last_synced_at":"2025-04-10T10:10:59.835Z","repository":{"id":56874965,"uuid":"143913791","full_name":"algonauti/google_maps_juice","owner":"algonauti","description":"Drink Google Maps Services with ease! :tropical_drink: :earth_americas:","archived":false,"fork":false,"pushed_at":"2020-07-17T14:27:04.000Z","size":116,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":5,"default_branch":"master","last_synced_at":"2024-04-29T17:20:48.649Z","etag":null,"topics":["geocoding","google","google-maps-api","ruby","rubygem","timezone"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/algonauti.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-08-07T18:44:31.000Z","updated_at":"2020-07-17T14:23:05.000Z","dependencies_parsed_at":"2022-08-20T22:00:35.886Z","dependency_job_id":null,"html_url":"https://github.com/algonauti/google_maps_juice","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/algonauti%2Fgoogle_maps_juice","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/algonauti%2Fgoogle_maps_juice/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/algonauti%2Fgoogle_maps_juice/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/algonauti%2Fgoogle_maps_juice/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/algonauti","download_url":"https://codeload.github.com/algonauti/google_maps_juice/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248198888,"owners_count":21063628,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["geocoding","google","google-maps-api","ruby","rubygem","timezone"],"created_at":"2024-11-24T08:00:40.239Z","updated_at":"2025-04-10T10:10:59.815Z","avatar_url":"https://github.com/algonauti.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# GoogleMapsJuice\n\n**Drink Google Maps Services with ease!** :tropical_drink: :earth_americas:\n\n[![Build Status](https://travis-ci.org/algonauti/google_maps_juice.svg?branch=master)](https://travis-ci.org/algonauti/google_maps_juice)\n[![Coverage Status](https://coveralls.io/repos/github/algonauti/google_maps_juice/badge.svg?branch=master)](https://coveralls.io/github/algonauti/google_maps_juice?branch=master)\n\nThis gem aims at progressively covering a fair amount of those widely-used services that are part of the Google Maps Platform, such as: [Geocoding](https://developers.google.com/maps/documentation/geocoding/intro), [Time Zone](https://developers.google.com/maps/documentation/timezone/intro), [Directions](https://developers.google.com/maps/documentation/directions/intro), etc. with some key ideas:\n\n1. Allowing \"standard\" requests, meaning: sending the same params documented by Google.\n2. Allowing \"smart\" requests, meaning: with more \"developer-friendly\" params, and/or improved error handling.\n3. Return full Google responses, but also provide methods to easily inspect the most relevant info.\n4. Provide error handling.\n\n\n`GoogleMapsJuice` currently covers:\n\n* Geocoding\n* Time Zone\n* Directions\n\nContributors are welcome!\n\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n```ruby\ngem 'google_maps_juice'\n```\n\nAnd then execute:\n\n    $ bundle\n\nOr install it yourself as:\n\n    $ gem install google_maps_juice\n\n\n## Google API Key\n\nYou can set your Google API key with the following one-liner:\n\n```ruby\nGoogleMapsJuice.configure { |c| c.api_key = 'my-api-key' }`\n```\n\nIn a Rails application, that would typically go in an initializer.\n\n\n### Multiple API keys\n\nIf you need to use multiple API keys, you have two options:\n\n* a) pass an `api_key` named param to the endpoint class method, e.g.\n\n```ruby\nGoogleMapsJuice::Geocoding.geocode(params, api_key: 'my-api-key')\n```\n\n* b) create your own `GoogleMapsJuice::Client` instance(s) and use it to create your endpoint object(s), e.g.\n\n```ruby\nclient = GoogleMapsJuice::Client.new(api_key: 'my-api-key')\ngeocoding = GoogleMapsJuice::Geocoding.new(client)\nresponse = geocoding.geocode(params)\n```\n\nThis is especially useful in some \"hybrid\" scenario, where an API key is shared by a group of requests, but another group uses a different key: a `client` object would then be instantiated and reused for each group.\n\n\n## Error Handling\n\nIf Google servers respond with a non-successful HTTP status code, i.e. `4xx` or `5xx`, a `GoogleMapsJuice::ResponseError` is raised with a message of the form `'HTTP 503 - Error details as returned by the server'`.\n\nAPI errors are also handled, based on the `status` attribute of Google's JSON response, and the optional `error_message` attribute.\n\n* `GoogleMapsJuice::ZeroResults` is raised when `status` is `'ZERO_RESULTS'`\n* `GoogleMapsJuice::ApiLimitError` is raised when `status` is `'OVER_DAILY_LIMIT'` or `'OVER_QUERY_LIMIT'`\n* `GoogleMapsJuice::ResponseError` is raised when `status` is not `OK` with a message of the form `API \u003cstatus\u003e - \u003cerror_message\u003e`\n\n\n## Geocoding\n\n### Standard Geocoding\n\nThe simplest geocoding requests accept an address:\n\n```ruby\nresponse = GoogleMapsJuice::Geocoding.geocode(address: '8955 Lantana Rd, Lake Worth, FL 33467, USA')\n```\n\nSupported params are the ones accepted by Google's endpoint: `address`, `components`, `bounds`, `language`, `region`; at least one between `address` and `components` is required. Learn more [here](https://developers.google.com/maps/documentation/geocoding/intro#geocoding). `GoogleMapsJuice` will raise an `ArgumentError` if some unsupported param is passed, or when none of the required params are passed.\n\n\n### Smart Geocoding\n\n**Motivation**\n\nFor best geocoding results, the `address` param should be formatted according to the local language. This is often a hard task for an application that needs to geocode addresses stored as separate fields. Luckily, Google offers the `components` param which accepts individual address fields; however, it's annoying to build it and it's not fault tolerant. For example, an error on `postal_code` makes geocoding of a whole address fail.\n\nPurpose of `i_geocode` method is twofold:\n\n1. Providing a simpler method interface for leveraging Google's `components` param\n2. Providing an approximate geocoding result when some address component is wrong\n\nHere an example call with all supported params:\n\n```ruby\nresponse = GoogleMapsJuice::Geocoding.i_geocode(\n  {\n    address: '8955 Lantana Rd',\n    locality: 'Lake Worth',\n    administrative_area: 'FL',\n    postal_code: '33467',\n    country: 'US'\n  }, sleep_before_retry: 0.15\n)\n```\n\n**Accepted params:**\n\n* At least one between `address` and `country` is required\n* `locality`, `administrative_area`, `postal_code` and `country` expect the same content as described in [Component Filtering](https://developers.google.com/maps/documentation/geocoding/intro#ComponentFiltering)\n* `address` can also include more info than street number and name, as long as they do not contrast with other params passed\n* An optional `sleep_before_retry` param sets seconds between geocoding attempts (see below); defaults to zero.\n* `GoogleMapsJuice` will raise an `ArgumentError` if some unsupported param is passed, or when none of the required params are passed.\n\n**How it works**\n\nOn its 1st attempt, `i_geocode` sends all received params to Google's endpoint, properly formatted. If a `GoogleMapsJuice::ZeroResults` is raised, it removes a param and retries until no error is raised. Params are removed in the following order:\n\n* `postal_code`\n* `address`\n* `locality`\n* `administrative_area`\n\nAs a consequence:\n\n* In the best case, `i_geocode` will send 1 request to Google API\n* In the worst case, `i_geocode` will send 4 requests to Google API\n\n\n### Geocoding Response\n\nBoth `geocode` and `i_geocode` methods return a `GoogleMapsJuice::Geocoding::Response`. It's a `Hash` representation of Google's JSON response. However, it also provides many useful methods:\n\n* `latitude`, `longitude`: geographic coordinates as `float` numbers\n\n* `street_number`, `route`, `locality`, `postal_code`, `administrative_area_level_1`, `country`: all of these methods return a `Hash` with 2 keys: `'short_name'` and `'long_name'`\n\n* `partial_match?`: boolean, `true` if some param (of the last geocoding attempt) partially matched\n\n* `precision`: can be one of: `'street_number'`, `'route'`, `'locality'`, `'postal_code'`, `'administrative_area_level_1'`, `'country'` and represents the most-specific matching component\n\n\n## Time Zone\n\n[Google's Time Zone API](https://developers.google.com/maps/documentation/timezone/intro#Requests) returns the time zone of a given geographic location; it also accepts a timestamp, in order to determine whether DST should be applied or not.\n\nGoogleMapsJuice provides the `GoogleMapsJuice::Timezone.by_location` method. Compared to Google's raw API request, it provides simpler params and some validations, in order to avoid sending requests when they would fail for sure (and then save money!) - to learn more see `spec/unit/timezone_spec.rb`.\n\n**Accepted params:**\n\n* Both `latitude` and `longitude` are mandatory\n* `timestamp` is optional and defaults to `Time.now`\n* `language` is optional\n\n\n### Time Zone Response\n\nThe `by_location` method returns a `GoogleMapsJuice::Timezone::Response`. It's a `Hash` representation of Google's JSON response. However, it also provides a few useful methods:\n\n* `timezone_id`: unique name as defined in [IANA Time Zone Database](https://www.iana.org/time-zones)\n\n* `timezone_name`: the long form name of the time zone\n\n* `raw_offset`: the offset from UTC in seconds\n\n* `dst_offset`: the offset for daylight-savings time in seconds\n\n\n## Directions\n\n[Google's Directions API](https://developers.google.com/maps/documentation/directions/intro#DirectionsRequests) returns the possible routes of given origin and destination geographic locations; Google's API accepts address, textual latitude/longitude value, or place ID of which you wish to calculate directions. Currently this gem implements only latitude/longitude mode.\n`GoogleMapsJuice` will raise an `ArgumentError` if some unsupported param is passed, or when none of the required params are passed.\n\n```ruby\nresponse = GoogleMapsJuice::Directions.find(origin: '41.8892732,12.4921921', destination: '41.9016488,12.4583003')\n```\n\nCompared to Google's raw API request, it provides validation of both origin and destination, in order to avoid sending requests when they would fail for sure - to learn more see `spec/unit/directions_spec.rb`.\n\n**Accepted params:**\n\n* Both `origin` and `destination` are mandatory\n* `origin` is composed by `latitude` and `longitude`, comma separated float values\n* `destination` same format as `origin`\n\n\n### Directions Response\n\nThe `find` method returns a `GoogleMapsJuice::Directions::Response`. It's a `Hash` representation of Google's JSON response. However, it also provides a few useful methods:\n\n* `results`: the `Hash` raw result\n\n* `routes`: an `Array` of `GoogleMapsJuice::Directions::Response::Route` objects\n\n* `first`: the first `Route` of the `routes` `List`\n\nAs described in [Google's Directions API](https://developers.google.com/maps/documentation/directions/intro#Routes), the response contains all possible routes. Each route has some attributes and one or more *legs*, wich in turn have one or more *steps*.\nIf no waypoints are passed, the route response will contain a single leg. Since `GoogleMapsJuice::Directions` doesn't handles waypoints yet, only the first leg is considered for each route.\nThe `GoogleMapsJuice::Directions::Response::Route` is a representation of a response route and provides methods to access all route's attributes:\n\n* `summary`: a brief description of the route\n\n* `legs`: all legs of the route, generally a single one\n\n* `steps`: all steps of the first route's leg\n\n* `duration`: time duration of the first route's leg\n\n* `distance`: distance between origin and destination of first route's leg\n\n* `start_location`: `latitude`/`longitude` of the origin first route's leg\n\n* `end_location`: `latitude`/`longitude` of the destination first route's leg\n\n* `start_address`: address of the origin first route's leg\n\n* `end_address`: address of the destination first route's leg\n\n\n## Development\n\nAfter checking out the repo, run `bin/setup` to install dependencies. Create a `.env` file and save your Google API key there; if you want to use a different key for testing, put it in `.env.test` and it will override the one in `.env`.\n\nRun `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.\n\nTo install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags and push the `.gem` file to [rubygems.org](https://rubygems.org).\n\n\n### Implementing a new endpoint\n\nAll endpoints must be subclasses of `GoogleMapsJuice::Endpoint`; methods that implement \"standard\" Google API calls have a common structure, described by the `invoke` method in the `SomeEndpoint` test class in `spec/unit/endpoint_spec.rb`.\n\nAll new endpoints' methods must return subclasses of `GoogleMapsJuice::Endpoint::Response` as their response objects, since it contains methods needed for error handling.\n\n\n## Contributing\n\nBug reports and pull requests are welcome on GitHub at https://github.com/algonauti/google_maps_juice.\n\n\n## License\n\nThe gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falgonauti%2Fgoogle_maps_juice","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falgonauti%2Fgoogle_maps_juice","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falgonauti%2Fgoogle_maps_juice/lists"}