{"id":23433924,"url":"https://github.com/ioki-mobility/ioki-ruby","last_synced_at":"2025-10-12T07:22:18.341Z","repository":{"id":37861885,"uuid":"423816400","full_name":"ioki-mobility/ioki-ruby","owner":"ioki-mobility","description":"Ruby Client for ioki APIs","archived":false,"fork":false,"pushed_at":"2024-10-29T08:11:14.000Z","size":2160,"stargazers_count":7,"open_issues_count":20,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-10-29T09:27:39.243Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/ioki-mobility.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-11-02T11:26:13.000Z","updated_at":"2024-10-29T08:11:17.000Z","dependencies_parsed_at":"2023-10-16T18:56:30.590Z","dependency_job_id":"17abe1a6-2cfb-4f68-b7d7-2236e83a35f3","html_url":"https://github.com/ioki-mobility/ioki-ruby","commit_stats":null,"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ioki-mobility%2Fioki-ruby","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ioki-mobility%2Fioki-ruby/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ioki-mobility%2Fioki-ruby/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ioki-mobility%2Fioki-ruby/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ioki-mobility","download_url":"https://codeload.github.com/ioki-mobility/ioki-ruby/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248651085,"owners_count":21139741,"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":[],"created_at":"2024-12-23T11:35:36.252Z","updated_at":"2025-10-12T07:22:18.246Z","avatar_url":"https://github.com/ioki-mobility.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Ioki - Client\n\nThe ioki client is made to conveniently use all of Ioki's several APIs and parse the results into ruby objects to be \nused in other ruby code.\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n```ruby\ngem 'ioki-ruby'\n```\n\nAnd then execute:\n\n    $ bundle install\n\nOr install it yourself as:\n\n    $ gem install ioki-ruby\n\nIt's recommended to configure using shared git hooks from `.git-hooks` by running:\n\n`git config core.hooksPath .git-hooks`\n\n## Example Usage\n\nBasic usage of a `Ioki::Client`\n```ruby\n  platform_client = Ioki::PlatformClient.new\n\n  providers = platform_client.providers\n  # returns a list of Ioki::Model::Platform::Provider instances\n\n  products = platform_client.products\n  # returns a list of Ioki::Model::Platform::Product instances\n\n  stations = platform_client.stations(products.first, paginate: true)\n  # stations are a scoped endpoint within products, so the interface requires\n  # either a product or a product id as the first parameter.\n  # This call will then fetch the index of stations. Use `paginate: true` to\n  # receive pagination information in the response. Otherwise, only the data of\n  # the first page is returned.\n  unless stations.meta.last_page\n    next_page = stations.meta.page + 1\n    stations = platform_client.stations(products.first, params: {page: next_page}, paginate: true)\n  end\n\n  new_station = Ioki::Model::Platform::Station.new(\n    location_name: 'Test',\n    station_type: 'virtual',\n    lat: stations.data.first.lat,\n    lng: stations.data.first.lng\n  )\n\n  created_station = platform_client.create_station(products.first, new_station)\n\n  # created_station has an id. it is a new model instance and has nothing to do\n  # with the new_station that got passed in - it is simply parsed back from\n  # the response body internally.\n\n  platform_client.delete_station(products.first, created_station)\n  # will delete the formerly created station\n\n  stations = platform_client.stations(products.first, auto_paginate: true)\n  # This example shows auto_pagination, which keeps calling the index until the\n  # last page was fetched. Bear in mind, that auto_pagination might be extremely\n  # expensive.\n  first_station = stations.first\n```\n\nSee `spec/ioki/examples` for more examples.\n\n## Configuration\nIf a project requires only a specific client setup, one can set the defaults on\nthe config (Ioki.config) via calling `Ioki.configure`; for example within a Rails\ninitializer you could do it like this:\n\n```ruby\n  # frozen_string_literal: true\n\n  Rails.application.reloader.to_prepare do\n    Ioki.configure do |cfg|\n      cfg.http_adapter          = Rails.env.test? ? :test : :faraday\n      cfg.verbose_output        = Rails.env.development? || Rails.env.test?\n      cfg.logger                = Rails.logger\n      cfg.api_base_url          = 'https://demo.io.ki/api/'\n      cfg.api_client_identifier = 'com.ioki.example.client'\n      cfg.api_client_version    = '0.0.1'\n      cfg.api_bleeding_edge     = false\n\n      # As you should not put secrets into your source code, you probably want\n      # to NOT use these:\n      # cfg.api_client_secret = ...\n      # cfg.api_token = ...\n    end\n  end\n```\n\nThe `Ioki::Configuration` will also try to load defaults from the ENV, so one can\nuse ENV variables, to inject data - this is especially useful for the api_token\nand api_client_secret. You can setup these ENV variables:\n\n```ruby\n  ENV['IOKI_HTTP_ADAPTER']\n  ENV['IOKI_VERBOSE_OUTPUT']\n  ENV['IOKI_API_BASE_URL']\n  ENV['IOKI_API_VERSION']\n  ENV['IOKI_API_CLIENT_IDENTIFIER']\n  ENV['IOKI_API_CLIENT_SECRET']\n  ENV['IOKI_API_CLIENT_VERSION']\n  ENV['IOKI_API_TOKEN']\n  ENV['IOKI_API_BLEEDING_EDGE']\n  ENV['IOKI_OAUTH_APP_ID']\n  ENV['IOKI_OAUTH_APP_SECRET']\n  ENV['IOKI_OAUTH_APP_URL']\n  ENV['IOKI_RETRY_COUNT']\n  ENV['IOKI_RETRY_SLEEP_SECONDS']\n  ENV['IOKI_IGNORE_DEPRECATED_ATTRIBUTES']\n  ENV['IOKI_PROXY_URL']\n  ENV['IOKI_VERIFY_SSL']\n```\n\nor define them for one of the three supported apis with a prefix:\n\n```ruby\nENV['IOKI_PLATFORM_API_CLIENT_IDENTIFIER']\nENV['IOKI_PASSENGER_API_VERSION'] \n...\n```\n\nValues passed directly into `Ioki::Client.new` constructor take precedence over\nthe values in `Ioki.config`. Ioki.config will respect the values set up by\n`Ioki.configure`. If not set, it will take the ENV value and finally fall back\nfor most configurable attributes to a baked in default.\n\n## Serialization\n\nioki-ruby's main task is to serialize models to JSON and send the serialized representation to the API. All attributes changes are tracked and only changed attributes are serialized and sent to the API.\n\nMake sure that all required attributes are properly set on the model, as ioki-ruby currently does not validate the serialized data before sending it to the API.\n\nPlease note that in certain cases sending an attribute with the value `nil` results in a different behavior than not sending the attribute at all. You therefore have to ensure to only set the attributes which are meant to be sent to the API.\n\nExample:\n\n```ruby\nirb(main):002\u003e line = Ioki::Model::Operator::Line.new(slug: 'my-line')\n=\u003e Ioki::Model::Operator::Line:3400 @attributes={:slug=\u003e\"my-line\"}\nirb(main):003\u003e line.serialize\n=\u003e {:slug=\u003e\"my-line\"}\n\nirb(main):004\u003e line.changed_attributes\n=\u003e {:slug=\u003e\"my-line\"}\nirb(main):005\u003e line.attributes\n=\u003e\n{:type=\u003enil,\n :id=\u003enil,\n :created_at=\u003enil,\n :updated_at=\u003enil,\n :name=\u003enil,\n :mode=\u003enil,\n :route_number=\u003enil,\n :skip_time_window_check=\u003enil,\n :slug=\u003e\"my-line\",\n :variant=\u003enil,\n :line_stops=\u003enil}\n\n# Set attributes to `nil` if you want to explicitly send `nil` to the API.\nirb(main):007\u003e line.slug = nil\n=\u003e nil\nirb(main):008\u003e line.serialize\n=\u003e {:slug=\u003enil}\n\n# If you do not want to send an attribute to the API, but already have set it\n# before, use `clear_myattribute_change`. Replace `myattribute` with the name\n# of the attribute.\nirb(main):009\u003e line.clear_slug_change\n=\u003e nil\nirb(main):010\u003e line.serialize\n=\u003e {}\n```\n\n## Webhooks\n\nWebhooks are a way to receive updates about changes when they happen on the\nbackend servers. They are **pushed** to your application, where the other APIs\nare **pulled** from the backend. In this regard they are very different from\nthe Platform/Driver/Passenger/Operator API. What they have in common, is that\nthe data is serialized in a specific manner, which ioki-ruby can turn into a\nmodel in the Ioki::Model::Webhooks module.\n\nWhen you have the requests POST body in a `params` hash, you can convert that\nto an `Event` instance, which has a `model` attribute which is the deserialized\nwebhook `data` as a model:\n\n```ruby\n  @event = Ioki::Webhooks::Event.new params\n  @model = @event.model\n  # The event also gives you access to other attributes:\n  puts @event.provider_id\n  puts @event.event_type\n  puts @event.created_at\n```\n\nBecause the data is pushed to your application via the internet to a public\nendpoint in your application, the webhook data is signed by the ioki webhooks\nAPI to authenticate it using a preshared secret, which you need to provide.\n\n```\n# Set ENV['IOKI_WEBHOOK_SIGNATURE_KEY'] first...\n# Then run the validation on the request\n\nIoki::Webhooks::SignatureValidator.new(\n  body:          request.body.read,\n  signature:     request.headers['X-Signature'],\n  signature_key: ENV.fetch('IOKI_WEBHOOK_SIGNATURE_KEY', nil)\n).call\n\n```\n\n## Logger\n\nThe logger can be set to any object that implements the ruby `Logger` contract,\ni.e. responding to #debug and alike. If no logger is set up no logging occurs.\nA simple logger to standard out looks like this:\n\n```ruby\nrequire 'logger'\n\nIoki::Configuration.new(\n  logger:         Logger.new(STDOUT),\n  logger_options: { headers: true, bodies: false, log_level: :info }\n)\n```\n\n## Development\n\nAfter checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. If you have access to the open API definitions of iokis APIs you can add `driver_api.json`, `passenger_api.json` and/or `driver_api.json` to `fixtures/open_api_definitions` and the specs will check if the models are compatible with the current API version. 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\nYou can use `rake c` to start an interactive console. If you make code changes entering `reload!` in the console will load the current files again.\n\n## Release\n\nChange the version number in 'lib/ioki/version.rb' to `1.2.3`. We use semantic versioning: https://semver.org/\n\nOnce this version number has been pushed to github, you have to tag that commit with the same version number. This can be done locally or on github.com when creating the release.\n\n### Create the tag locally\n\nTag the commit in which you changed the version number and push it to github\n\n```\ngit tag -a '1.2.3' 0000COMMITHASHID00000000COMMITHASHID0000 -m 'Releasing Version 1.2.3'\ngit push --atomic origin main '1.2.3'\n```\n\n### Create the release\n\nHow to create the release, with or without creating a tag on github is described here:\n\nhttps://docs.github.com/en/repositories/releasing-projects-on-github/managing-releases-in-a-repository\n\nPlease do make use of the release notes feature to automatically create a changelog.\n\n## Testing\n\nioki-ruby uses Faraday under the hood to make requests to the API.\n\nIf you would like to make those request with fast predictable results in you test suite, you can pass in your own [Faraday::Connection stub](https://lostisland.github.io/faraday/adapters/testing).\n\n\n```ruby\n  let(:client)       { Ioki::Client.new(config, Ioki::PlatformApi) }\n  let(:config)       { Ioki::Configuration.new http_adapter: http_adapter }\n  let(:http_adapter) { Faraday.new('https://example.com/api') { |f| f.adapter :test, stubs } }\n  let(:stubs)        { Faraday::Adapter::Test::Stubs.new }\n\n  it 'can retrieve provider data from the providers endpoint' do\n    stubs.get(\"/api/platform/providers\") do |env|\n      [ 200, {}, { 'data' =\u003e [{ 'id' =\u003e '123', 'city' =\u003e 'Somewhere'}] } ]\n    end\n    expect(client.providers.first).to be_a Ioki::Model::Platform::Provider\n    expect(client.providers.first.city).to eq('Somewhere')\n  end\n```\n\n### OpenApi specifications\n\nIf you're allowed to access the OpenAPI-specifications for the three APIs you can place them in `spec/fixtures/open_api_definitions`. `open_api_spec` will then compare theses specs with the matching models. You can define `specification_scope` on the model to set the prefix the specs are looking for in the OpenApi-schema file and `schema_path` if the name of the schema is not the snake_case version of the class name and define `unvalidated true` to mark that no specification exists for a model.\nSometimes it's also helpful to disable the check for specific attributes. You can pass `unvalidated: true` as an option to the `attribute` definition.\n\n## Mailing\n\nIf ioki-ruby is integrated into a Rails app, a mailer is provided which can be used to send emails.\n\nTo activate it globally in your app, add the following to your environment configuration files (e.g. `config/environments/development.rb`):\n\n```ruby\nRails.application.configure do\n  config.action_mailer.delivery_method = :ioki\nend\n```\n\nWhen sending an email, you need to pass a `provider` and a `platform_client`:\n\n```ruby\nclass MyMailer \u003c ApplicationMailer\n  def welcome_message\n    mail(\n      subject: 'Welcome to our app!'\n    ).tap do |message|\n      message.ioki_options = {\n        provider_id:      my_provider_api_id,       # required\n        platform_client:  my_ioki_platform_client,  # required\n        delivery_context: 'standard',               # optional\n        user_id:          my_user_id                # optional\n      }\n    end\n  end\nend\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fioki-mobility%2Fioki-ruby","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fioki-mobility%2Fioki-ruby","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fioki-mobility%2Fioki-ruby/lists"}