{"id":13774112,"url":"https://github.com/extism/ruby-sdk","last_synced_at":"2025-04-08T07:32:23.314Z","repository":{"id":194439690,"uuid":"690702894","full_name":"extism/ruby-sdk","owner":"extism","description":"Extism Ruby Host SDK","archived":false,"fork":false,"pushed_at":"2024-04-05T22:03:21.000Z","size":9082,"stargazers_count":8,"open_issues_count":2,"forks_count":1,"subscribers_count":5,"default_branch":"main","last_synced_at":"2024-05-18T20:43:19.787Z","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":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/extism.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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":"2023-09-12T17:46:03.000Z","updated_at":"2024-06-24T02:52:22.354Z","dependencies_parsed_at":null,"dependency_job_id":"69a123a5-ee56-492c-9307-28e741a8ef5d","html_url":"https://github.com/extism/ruby-sdk","commit_stats":null,"previous_names":["extism/ruby-sdk"],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/extism%2Fruby-sdk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/extism%2Fruby-sdk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/extism%2Fruby-sdk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/extism%2Fruby-sdk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/extism","download_url":"https://codeload.github.com/extism/ruby-sdk/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247796296,"owners_count":20997545,"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-08-03T17:01:23.799Z","updated_at":"2025-04-08T07:32:21.561Z","avatar_url":"https://github.com/extism.png","language":"Ruby","readme":"# Extism Ruby Host SDK\n\nThis repo contains the ruby gem for integrating with the [Extism](https://extism.org/) runtime. Install this library into your host ruby application to run Extism plug-ins.\n\n## Installation\n\n### Install the Extism Runtime Dependency\n\nFor this library, you first need to install the Extism Runtime. You can [download the shared object directly from a release](https://github.com/extism/extism/releases) or use the [Extism CLI](https://github.com/extism/cli) to install it:\n\n```bash\nsudo extism lib install latest\n\n#=\u003e Fetching https://github.com/extism/extism/releases/download/v0.5.2/libextism-aarch64-apple-darwin-v0.5.2.tar.gz\n#=\u003e Copying libextism.dylib to /usr/local/lib/libextism.dylib\n#=\u003e Copying extism.h to /usr/local/include/extism.h\n```\n\n### Install the Gem\n\nAdd this library to your [Gemfile](https://bundler.io/):\n\n```ruby\ngem 'extism', '~\u003e 1.0.0'\n```\n\nOr if installing on the system level:\n\n```\ngem install extism\n```\n\n## Getting Started\n\nThis guide should walk you through some of the concepts in Extism and this ruby library.\n\n\u003e *Note*: You should be able to follow this guide by copy pasting the code into `irb`.\n\n### Creating A Plug-in\n\nThe primary concept in Extism is the [plug-in](https://extism.org/docs/concepts/plug-in). You can think of a plug-in as a code module stored in a `.wasm` file.\n\nSince you may not have an Extism plug-in on hand to test, let's load a demo plug-in from the web:\n\n```ruby\n# First require the library\nrequire \"extism\"\n\nurl = \"https://github.com/extism/plugins/releases/latest/download/count_vowels.wasm\"\nmanifest = Extism::Manifest.from_url url\nplugin = Extism::Plugin.new(manifest)\n```\n\n\u003e **Note**: See [the Manifest docs](https://extism.github.io/ruby-sdk/Extism/Manifest.html) as it has a rich schema and a lot of options.\n\n### Calling A Plug-in's Exports\n\nThis plug-in was written in Rust and it does one thing, it counts vowels in a string. As such, it exposes one \"export\" function: `count_vowels`. We can call exports using [Extism::Plugin#call](https://extism.github.io/ruby-sdk/Extism/Plugin.html#call-instance_method):\n\n```ruby\nplugin.call(\"count_vowels\", \"Hello, World!\")\n# =\u003e {\"count\": 3, \"total\": 3, \"vowels\": \"aeiouAEIOU\"}\n```\n\nAll exports have a simple interface of bytes-in and bytes-out. This plug-in happens to take a string and return a JSON encoded string with a report of results.\n\n### Plug-in State\n\nPlug-ins may be stateful or stateless. Plug-ins can maintain state b/w calls by the use of variables. Our count vowels plug-in remembers the total number of vowels it's ever counted in the \"total\" key in the result. You can see this by making subsequent calls to the export:\n\n```ruby\nplugin.call(\"count_vowels\", \"Hello, World!\")\n# =\u003e {\"count\": 3, \"total\": 6, \"vowels\": \"aeiouAEIOU\"}\nplugin.call(\"count_vowels\", \"Hello, World!\")\n# =\u003e {\"count\": 3, \"total\": 9, \"vowels\": \"aeiouAEIOU\"}\n```\n\nThese variables will persist until this plug-in is freed or you initialize a new one.\n\n### Configuration\n\nPlug-ins may optionally take a configuration object. This is a static way to configure the plug-in. Our count-vowels plugin takes an optional configuration to change out which characters are considered vowels. Example:\n\n```ruby\nplugin = Extism::Plugin.new(manifest)\nplugin.call(\"count_vowels\", \"Yellow, World!\")\n# =\u003e {\"count\": 3, \"total\": 3, \"vowels\": \"aeiouAEIOU\"}\n\nplugin = Extism::Plugin.new(manifest, config: { vowels: \"aeiouyAEIOUY\" })\nplugin.call(\"count_vowels\", \"Yellow, World!\")\n# =\u003e {\"count\": 4, \"total\": 4, \"vowels\": \"aeiouAEIOUY\"}\n```\n\n### Host Functions\n\nLet's extend our count-vowels example a little bit: Instead of storing the `total` in an ephemeral plug-in var, let's store it in a persistent key-value store!\n\nWasm can't use our KV store on it's own. This is where [Host Functions](https://extism.org/docs/concepts/host-functions) come in.\n\n[Host functions](https://extism.org/docs/concepts/host-functions) allow us to grant new capabilities to our plug-ins from our application. They are simply some ruby methods you write which can be passed down and invoked from any language inside the plug-in.\n\nLet's load the manifest like usual but load up this `count_vowels_kvstore` plug-in:\n\n```ruby\nurl = \"https://github.com/extism/plugins/releases/latest/download/count_vowels_kvstore.wasm\"\nmanifest = Extism::Manifest.from_url(url)\n```\n\n\u003e *Note*: The source code for this is [here](https://github.com/extism/plugins/blob/main/count_vowels_kvstore/src/lib.rs) and is written in rust, but it could be written in any of our PDK languages.\n\nUnlike our previous plug-in, this plug-in expects you to provide host functions that satisfy our its import interface for a KV store.\n\nIn the ruby sdk, we have a concept for this called a [Host Environment](https://extism.github.io/ruby-sdk/Extism/HostEnvironment.html). An environment is an instance of a class that implements any host functions your plug-in needs.\n\nWe want to expose two functions to our plugin, `kv_write(key: String, value: Bytes)` which writes a bytes value to a key and `kv_read(key: String) -\u003e Bytes` which reads the bytes at the given `key`.\n\n```ruby\n# pretend this is Redis or something :)\nKV_STORE = {}\n\nclass KvEnvironment\n  include Extism::HostEnvironment\n\n  # We need to describe the wasm function signature of each host function\n  # to register them to this environment\n  register_import :kv_read, [Extism::ValType::PTR], [Extism::ValType::PTR]\n  register_import :kv_write, [Extism::ValType::PTR, Extism::ValType::PTR], []\n\n  def kv_read(plugin, inputs, outputs, _user_data)\n    key = plugin.input_as_string(inputs.first)\n    val = KV_STORE[key] || [0].pack('V') # get 4 LE bytes for 0 default\n    puts \"Read from key=#{key}\"\n    plugin.output_string(outputs.first, val)\n  end\n\n  def kv_write(plugin, inputs, _outputs, _user_data)\n    key = plugin.input_as_string(inputs.first)\n    val = plugin.input_as_string(inputs[1])\n    puts \"Writing value=#{val.unpack1('V')} from key=#{key}\"\n    KV_STORE[key] = val\n  end\nend\n```\n\n\u003e *Note*: In order to write host functions you should get familiar with the methods on the [Extism::CurrentPlugin](https://extism.github.io/ruby-sdk/Extism/CurrentPlugin.html) class. The `plugin` parameter is an instance of this class.\n\nNow we just need to create a new host environment and pass it in when loading the plug-in. Here our environment initializer takes no arguments, but you could imagine putting some customer specific instance variables in there:\n\n```ruby\nenv = KvEnvironment.new\nplugin = Extism::Plugin.new(manifest, environment: env)\n```\n\nNow we can invoke the event:\n\n```ruby\nplugin.call(\"count_vowels\", \"Hello, World!\")\n# =\u003e Read from key=count-vowels\"\n# =\u003e Writing value=3 from key=count-vowels\"\n# =\u003e {\"count\": 3, \"total\": 3, \"vowels\": \"aeiouAEIOU\"}\nplugin.call(\"count_vowels\", \"Hello, World!\")\n# =\u003e Read from key=count-vowels\"\n# =\u003e Writing value=6 from key=count-vowels\"\n# =\u003e {\"count\": 3, \"total\": 6, \"vowels\": \"aeiouAEIOU\"}\n```\n","funding_links":[],"categories":["\u003ca name=\"extism\"\u003e\u003c/a\u003e[Extism](https://github.com/extism/extism) \u003csup\u003e[top⇈](#contents)\u003c/sup\u003e","Ruby"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fextism%2Fruby-sdk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fextism%2Fruby-sdk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fextism%2Fruby-sdk/lists"}