# imag-ruby A Ruby gem for scripting imag modules. ## How does this work? Well, as we have some problems with lifetimes here, we have a fairly complex codebase in this crate. ### The Problem The Problem is, that `libimagstore::store::FileLockEntry<'a>` has a lifetime. If we would wrap this object into a ruru wrapper and pass to the Ruby code, we couldn't guarantee anymore that the lifetime holds. The problem is simple, you see... ### The solution? Never pass anything to the Ruby code. Yes, exactly. The Ruby code only sees 'handles'. It never actually gets the `Store` object either. We move the `Store` Object into a `Cache` object (actually, the Ruby code could have multiple `Store` objects to work with this way) and return a `StoreHandle` to the Ruby code (which is a UUID underneath). Also, the Ruby code never actually touches a `FileLockEntry` - it only gets a Handle for each `FileLockEntry` - which is a tuple of the `StoreHandle` and the `libimagstore::storeid::StoreId` for the Entry. Each operation on a `FileLockEntry` is then wrapped by this very library. Each time `FileLockEntry` is touched, this library fetches the appropriate `Store` object from the static `Cache`, then fetches the `FileLockEntry` object from it, does the operation and then drops the object (which implies that the actual `FileLockEntry` is `update()`d!). ### The Hell? Yes, I know this is a lot of overhead. But what are we talking about here? This is Ruby code we're talking about here, so speed is not our concern. You could argue this is a hell of complexity introduced in this library and yes it is. If there are bugs (and I bet there are) they would be complex as hell. But that's it... if you have a better approach, please file a PR. ## Tests? We have tests Ruby scripts in `./test`, they are not executed by travis-ci, as we need Ruby `2.3.0` for this and travis has `2.2.0` as latest version. But I hope we get it in travis soonish. ## Ruby gem? This crate will contain both the Rust bindings for imag using `ruru` and a bunch of wrapper code for the actual `imag` gem. We are not there yet, though. ### Why another layer of indirection? As "ruru" does not yet support modules (which is sad btw) we would end up with functions for all the things. E.G.: `imag_runtime_setup()` instead of `Imag::Runtime::setup()` I want to add a Ruby gem to wrap these things. So basically a piece of Ruby which uses `imag.rb` (the Rust gem) to build `imag` as a gem which then exports a fine module system. ### Ideas for module system: ```text Imag (Module) Runtime (Class) Store (Class) Entry (Class) EntryHeader (Class) EntryContent (Class (inherits from String)) StoreId (Class) ``` I would name the types the same as in the Rust codebase, to avoid confusion. Only exception would be the `Entry` class, which would be a `FileLockEntry` underneath. If we adapt `libimagentrytag` and the other `libimagentry*` libraries, we would extend this type. ## More plans I want to pull these libraries into the Ruby bindings: * libimagentryedit * libimagentryfilter * libimagentrylink * libimagentrylist * libimagentrymarkdown * libimagentrytag * libimagentryview Which all provide functions on top of `libimagstore::store::{FileLock,}Entry`, so we will implement them on `Imag::Entry`.