ArtemisApi

This is a simple API wrapper for the Artemis API.

Installation

Add this line to your application's Gemfile:

gem 'artemis_api'

If you want to ensure the most up to date version, you can also use the gem straight from the repository:

gem 'artemis_api', :git => 'https://github.com/artemis-ag/artemis_api'

And then execute:

$ bundle

Or install it yourself as:

$ gem install artemis_api

Usage

Instantiating your Client

In order to use this gem, you will need to be set up as a developer in the Artemis Portal. If you're not, please contact Artemis CS in order to get that settled.

Once you have developer access, go to Settings and choose "OAuth 2.0 Applications" at the bottom of the sidebar to set up an application by entering the name and redirect URI you wish to use. You will then be provided with an application ID and a secret ID, which you will need in order to authenticate with Artemis.

The first step to actually using this gem is to instantiate an instance of ArtemisApi::Client and there are two different ways to do so depending on if you're handling OAuth in your own app or not.

If you intend to do a full OAuth flow, we recommend using the OAuth2 gem. After authenticating with OAuth and generating your access token and refresh token, you can use them to instantiate your Client instance. You'll also need to pass in the expires_at for when your token will expire. That looks like this:

options = {app_id: 'your_artemis_application_id',
           app_secret: 'your_artemis_secret_id',
           base_uri: 'https://portal.artemisag.com'}

client = ArtemisApi::Client.new(access_token: 'your_access_token',
                                refresh_token: 'your_refresh_token',
                                expires_at: token_expires_at,
                                options: options)

Instead of passing in options, you can set those values as ENV variables called ENV['ARTEMIS_OAUTH_APP_ID'], ENV['ARTEMIS_OAUTH_APP_SECRET'] and ENV['ARTEMIS_BASE_URI']

They will be automatically detected and then you don't have to pass in any options:

client = ArtemisApi::Client.new(access_token: 'your_access_token',
                                refresh_token: 'your_refresh_token',
                                expires_at: token_expires_at)

Alternatively, if you're working on a command line tool or otherwise not intending to implement a full OAuth flow, you can generate an authorization code directly and use this code to obtain an access token and a refresh token. Do this by creating an OAuth application in your Artemis settings with urn:ietf:wg:oauth:2.0:oob as the callback url. Then, clicking the Authorize button directly on Artemis Portal beside it on your application show page will provide you directly with an authorization code. Pass it into the Client instantiator like this. (The same rules apply about either passing in options or setting your ENV variables.)

client = ArtemisApi::Client.new(auth_code: 'your_generated_authorization_code')

This authorization code is only valid for one use. If you want to keep connecting using the same authorization grant, you need to save the values of client.access_token, client.refresh_token and client.expires_at and use them when reinstantiating client in the future.

Requesting data from Artemis

Once you have a client instance, you can use it to request information from Artemis.

To get user information about the Artemis User that is associated with your application ID:

client.current_user

Or alternatively, you can make the call directly to the User class:

ArtemisApi::User.get_current(client: client)

(Please note that we use named parameters in most of our function calls.)

You can use either method to get a list of all Artemis Organizations or Facilities that you have access to:

client.organizations
client.facilities

ArtemisApi::Organization.find_all(client: client)
ArtemisApi::Facility.find_all(client: client)

To get facility information about a single Artemis Organization or Facility that you have access to, by its Artemis ID:

client.organization(1)
client.facility(2)

ArtemisApi::Organization.find(id: 1, client: client)
ArtemisApi::Facility.find(id: 2, client: client)

Other models are scoped by facility, so you have to include the Facility id in the call. (You can also get information about other Artemis Users besides your own account this way.)

To get all Users associated with the Facility with an ID of 2, again there are two methods. You can call directly to the User class, or you can query through a facility.

client.facility(2).users

ArtemisApi::User.find_all(facility_id: 2, client: client)

To get a single User, with id 12, which must also be associated with Facility 2:

client.facility(2).user(12)

ArtemisApi::User.find(id: 12, facility_id: 2, client: client)

You can get info about Batches, Zones, SeedingUnits, HarvestUnits and Subscriptions in the same manner. Here are a couple examples, but the syntax is all the same.

client.facility(2).batches
client.facility(2).batch(22)

ArtemisApi::Batch.find_all(facility_id: 2, client: client)
ArtemisApi::Batch.find(id: 22, facility_id: 2, client: client)

client.facility(2).seeding_units
client.facility(2).seeding_unit(4)

ArtemisApi::SeedingUnit.find_all(facility_id: 2, client: client)
ArtemisApi::SeedingUnit.find(id: 4, facility_id: 2, client: client)

Completions, Harvests and Discards can be queried through a Batch object in a similar way. Again, you can also call directly to the class. Note that in the above examples, querying through facility or the class will give you the exact same results: that isn't true in this case. Querying through the batch will return only objects associated with that batch, while doing a find_all on the class will give you all objects associated with the entire facility.

client.facility(2).batch(22).harvests
client.facility(2).batch(22).discards
client.facility(2).batch(22).completions

client.facility(2).batch(22).harvest(47)

ArtemisApi::Harvest.find_all(facility_id: 2, client: client)
ArtemisApi::Harvest.find(id: 47, facility_id: 2, client: client)

Additionally, Items are scoped by both Facility and Batch, so both are required even if you call directly to the Item class. There is also an optional seeding_unit_id param if you query through a batch.

client.facility(2).batch(22).items
client.facility(2).batch(22).items(seeding_unit_id: 17)

ArtemisApi::Item.find_all(facility_id: 2, batch_id: 22, client: client)

Once you have queried info about a certain object, it will be stored in a hash called objects that exists on your active client object. Then, if you have to query the same object again, it can be pulled from that hash instead of doing another actual call to the API, to speed up performance. If you need to actually hit the API again for the most updated information, you can force the query like this:

facility = ArtemisApi::Facility.find(id: 2, client: client, force: true)

Additionally, you can optionally include other models in your call that have a relationship with the model you're querying. They will then be included in the payload and added into the objects hash for your client for easier querying in the future.

ArtemisApi::Facility.find(id: 2, client: client, include: "users")
ArtemisApi::Batch.find(id: 22, facility_id: 2, client: client, include: "completions")

We also support filtering on several models: Batch, Completion, Discard, Harvest, Zone, Item. It is another optional param and it expects a hash. Here's what that should look like.

ArtemisApi::Batch.find_all(facility_id: 2, client: client, filters: {search: 'genovese basil'})
ArtemisApi::Batch.find_all(facility_id: 2, client: client, filters: {ids: [2, 4, 6, 11]})
ArtemisApi::Batch.find_all(facility_id: 2, client: client, filters: {date_type: 'seeded_at', date_window: "2019-10-31 17:06:42 -0400,2019-11-15 17:06:42 -0500"})

ArtemisApi::Completion.find_all(facility_id: 2, client: client, filters: {crop_batch_ids: [5]})
ArtemisApi::Harvest.find_all(facility_id: 2, client: client, filters: {crop_batch_ids: [5, 7]})
ArtemisApi::Discard.find_all(facility_id: 2, client: client, filters: {crop_batch_ids: [6, 7, 9]})
ArtemisApi::Zone.find_all(facility_id: 2, client: client, filters: {seeding_unit_id: 3})
ArtemisApi::Item.find_all(facility_id: 2, batch_id: 22, client: client, filters: {seeding_unit_id: 8})

Note that when you filter by ids or crop_batch_ids, you must pass in an array even if it only has one element.

Pagination is also supported on batches, and is also an optional param that expects a hash. We use the limit/offset method of pagination.

ArtemisApi::Batch.find_all(facility_id: 2, client: client, page: {limit: 10, offset: 60})

The Artemis API is currently mainly read only, but we do support the creation of Subscriptions. These are used to set up webhooks that will make a callback to you whenever a Completion or Batch gets created or updated in the given facility. They require a subject, which can currently be either completions or batches, and a destination, which is the url that you want the callback to hit. There are two ways to make that call:

ArtemisApi::Subscription.create(facility_id: 2,
                                subject: 'completions',
                                destination: 'https://test-app-url.artemisag.io/v1/webhook',
                                client: client)

facility.create_subscription(subject: 'completions', destination: 'https://test-app-url.artemisag.io/v1/webhook')

You can also delete one of your own Subscriptions. Trying to delete a Subscription that isn't associated with your user account will fail.

ArtemisApi::Subscription.delete(id: 1, facility_id: 2, client: client)

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rake test to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

To 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.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/artemis-ag/artemis_api. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.

License

The gem is available as open source under the terms of the MIT License.

Code of Conduct

Everyone interacting in the ArtemisApi project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.