Skip to content

Commit

Permalink
Prepare release cl-ohm-0.2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
rudolfochrist committed Apr 29, 2016
1 parent 1adfb4f commit a5b3636
Show file tree
Hide file tree
Showing 3 changed files with 4 additions and 181 deletions.
2 changes: 1 addition & 1 deletion README.org
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ Sets, lists and counters are stored implicitly after their mutation. If you chan

* API Documentation

See [[https://htmlpreview.github.io/?https://github.com/rudolfochrist/cl-ohm/blob/master/docs/cl-ohm-0.1.0.html#CL-OHM][CL-OHM HTML Documentation]].
See [[https://htmlpreview.github.io/?https://github.com/rudolfochrist/cl-ohm/blob/master/docs/cl-ohm-0.2.0.html#CL-OHM][CL-OHM HTML Documentation]].

* Running the tests

Expand Down
2 changes: 1 addition & 1 deletion cl-ohm.asd
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
(in-package :asdf-user)

(defsystem #:cl-ohm
:version "0.1.0"
:version "0.2.0"
:description "An object-hash mapping for Redis in Common Lisp"
:author "Sebastian Christ <rudolfo.christ@gmail.com>"
:mailto "rudolfo.christ@gmail.com"
Expand Down
181 changes: 2 additions & 179 deletions docs/cl-ohm-0.1.0.html → docs/cl-ohm-0.2.0.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,190 +20,13 @@
<body>
<header>
<h1>cl-ohm</h1>
<span class="version">0.1.0</span>
<span class="version">0.2.0</span>
<p class="description">An object-hash mapping for Redis in Common Lisp</p>
</header>
<div id="content">
<article>

<span><p><a href="http://quickdocs.org/cl-ohm/"><img src="file:http://quickdocs.org/badge/cl-ohm.svg" alt=""/></a>
<a href="https://opensource.org/licenses/MIT"><img src="file:https://img.shields.io/badge/License-MIT-yellow.svg" alt=""/></a>
<a href="https://travis-ci.org/rudolfochrist/cl-ohm">&lt;file:https://travis-ci.org/rudolfochrist/cl-ohm.svg?branch=master&gt;</a>
<a href="https://coveralls.io/github/rudolfochrist/cl-ohm?branch=master">&lt;file:https://coveralls.io/repos/github/rudolfochrist/cl-ohm/badge.svg?branch=master&gt;</a></p>

<p>This is an implementation of <a href="http://ohm.keyvalue.org/">Ohm</a> in Common
Lisp with some inspiration from <a href="http://eudoxia.me/crane/">Crane</a> and
<a href="https://github.com/fukamachi/datafly">datafly</a>.</p>

<p>Ohm is an object-hash mapping for <a href="http://redis.io/">Redis</a>.</p>

<h1>Usage</h1>

<h2>Starting and connecting Redis</h2>

<p>First of all, Redis must be up and running. You can start Redis with the
command line</p>

<pre><code>$ redis-server</code></pre>

<p>Then load <code>CL-OHM</code>:</p>

<pre><code>(ql:quickload :cl-ohm)</code></pre>

<p>Without configuration Redis runs on <code>localhost:6379</code>. If you're using a
different host or port you have to configure <code>CL-OHM</code>. For example, if
Redis is running on <code>198.162.55.12</code> on port <code>12455</code> than you must setup
CL-OHM like this:</p>

<pre><code>(<a href="#CL-OHM:SETUP-REDIS-CONNECTION">ohm:setup-redis-connection</a> :host #(198 162 55 12) :port 12455)</code></pre>

<h2>Mapping objects to Redis</h2>

<p>Use <code><a href="#CL-OHM:DEFINE-OHM-MODEL">ohm:define-ohm-model</a></code> to specify your models.</p>

<pre><code>(<a href="#CL-OHM:DEFINE-OHM-MODEL">ohm:define-ohm-model</a> person ()
:attributes ((first-name :indexp t)
(last-name :indexp t)
(email :uniquep t)))</code></pre>

<p>You can create new persisted objects with <code><a href="#CL-OHM:CREATE">CREATE</a></code>:</p>

<pre><code>(<a href="#CL-OHM:CREATE">ohm:create</a> 'person :first-name &quot;John&quot; :last-name &quot;McCarthy&quot;)</code></pre>

<p>Attributes are setfable like ordinary objects slots (Note: if you don't
provide readers or writers for an attribute, an accessor will be
created) but has to be <strong>explicitly saved to be persisted</strong>.</p>

<pre><code>(<a href="#CL-OHM:CREATE">ohm:create</a> 'person :first-name &quot;Bill&quot;)
(<a href="http://l1sp.org/cl/setf">setf</a> (first-name *) &quot;William&quot;)
(<a href="#CL-OHM:SAVE">ohm:save</a> **)</code></pre>

<h2>Loading objects from the data store</h2>

<p>When you know an object's ID then you can load it with <code><a href="#CL-OHM:FILTER-ID">filter-id</a></code></p>

<pre><code>(<a href="#CL-OHM:FILTER-ID">ohm:filter-id</a> 'person &quot;5&quot;)
;;; or
(<a href="#CL-OHM:FILTER-ID">ohm:filter-id</a> 'person 5)</code></pre>

<h3>Indexes</h3>

<p>For each attribute marked with <code>:INDEXP</code> and index gets created. With
this index it is possible to load objects by their values.</p>

<pre><code>(<a href="#CL-OHM:FILTER">ohm:filter</a> 'person :first-name &quot;Bill&quot;)</code></pre>

<p>This load all objects with <code>first-name=Bill</code>. Indexed attributes can be
combined in <code><a href="#CL-OHM:FILTER">FILTER</a></code>.</p>

<pre><code>(<a href="#CL-OHM:FILTER">ohm:filter</a> 'person :first-name &quot;Bill&quot; :last-name &quot;Miller&quot;)</code></pre>

<p>If you omit any attribute specifiers from <code><a href="#CL-OHM:FILTER">FILTER</a></code> than all objects for
the given type are retrieved.</p>

<pre><code>(<a href="#CL-OHM:FILTER">ohm:filter</a> 'person)</code></pre>

<h2>Unique values</h2>

<p>Each attribute marked as <code>:UNIQUEP</code> must be unique for all instances of
a given model. Considering the <code>person</code> model from above this means two
instances cannot have the same <code>email</code>. <code>:UNIQUEP</code> also creates an
index, query-able with <code><a href="#CL-OHM:FILTER-WITH">FILTER-WITH</a></code>.</p>

<pre><code>(<a href="#CL-OHM:FILTER-WITH">ohm:filter-with</a> 'person :email &quot;e@example.org&quot;)</code></pre>

<p>This load the <code>person</code> object with <code>email=e@example.org</code></p>

<h2>Counters</h2>

<p>Counters let you count atomically.</p>

<pre><code>(<a href="#CL-OHM:DEFINE-OHM-MODEL">ohm:define-ohm-model</a> candidate (person)
:counters (votes))

(<a href="http://l1sp.org/cl/let">let</a> ((candidate (<a href="#CL-OHM:CREATE">create</a> 'candidate :first-name &quot;Bill&quot;)))
(<a href="#CL-OHM:INCR">ohm:incr</a> (votes candidate))
(<a href="#CL-OHM:INCR">ohm:incr</a> (votes candidate))

(<a href="#CL-OHM:COUNTER">ohm:counter</a> (votes candidate)) ;=&gt; 2

(<a href="#CL-OHM:DECR">ohm:decr</a> (votes candidate) 2)

(<a href="#CL-OHM:COUNTER">ohm:counter</a> (votes candidate))) ;=&gt; 0</code></pre>

<h2>Sets and Lists</h2>

<p>Each model can define sets or lists as attributes. Sets and lists can
hold other persisted objects defined by <code><a href="#CL-OHM:DEFINE-OHM-MODEL">DEFINE-OHM-MODEL</a></code>. Therefore
you most provide the set's or list's element-type.</p>

<pre><code>(<a href="#CL-OHM:DEFINE-OHM-MODEL">ohm:define-ohm-model</a> tag ()
:attributes ((name :indexp t)))

(<a href="#CL-OHM:DEFINE-OHM-MODEL">ohm:define-ohm-model</a> post ()
:lists ((authors :element-type person))
:sets ((tags :element-type tag)))</code></pre>

<p><code>CL-OHM</code> persisted objects are internally stored in sets.</p>

<pre><code>(<a href="#CL-OHM:CREATE">ohm:create</a> 'person :first-name &quot;Donald&quot; :last-name &quot;Duck&quot;)
(<a href="#CL-OHM:FILTER">ohm:filter</a> 'person) ;=&gt; #&lt;CL-OHM::OHM-SET {1009FAB643}&gt;</code></pre>

<p>This lets you combine the <code>FITLER</code> function with set operations.</p>

<h3>Set operations</h3>

<p>Creating some test data:</p>

<pre><code>(<a href="#CL-OHM:CREATE">ohm:create</a> 'person :first-name &quot;Donald&quot; :last-name &quot;Duck&quot;)
(<a href="#CL-OHM:CREATE">ohm:create</a> 'person :first-name &quot;Daisy&quot; :last-name &quot;Duck&quot;)
(<a href="#CL-OHM:CREATE">ohm:create</a> 'person :first-name &quot;Gladstone&quot; :last-name &quot;Gander&quot;)</code></pre>

<p>Creating the union of persons named <strong>Duck</strong> and persons named
<strong>Gander</strong>:</p>

<pre><code>(<a href="#CL-OHM:ELEMENTS">ohm:elements</a> (<a href="#CL-OHM:UNION">ohm:union</a> (<a href="#CL-OHM:FILTER">ohm:filter</a> 'person :last-name &quot;Duck&quot;)
(<a href="#CL-OHM:FILTER">ohm:filter</a> 'person :last-name &quot;Gander&quot;)))</code></pre>

<p>Use <code><a href="#CL-OHM:EXCEPT">EXCEPT</a></code> to exclude objects with specific properties. Say, exclude
persons named <strong>Gander</strong> from all persons:</p>

<pre><code>(<a href="#CL-OHM:ELEMENTS">ohm:elements</a> (<a href="#CL-OHM:EXCEPT">ohm:except</a> (<a href="#CL-OHM:FILTER">ohm:filter</a> 'person) ; all persons
(<a href="#CL-OHM:FILTER">ohm:filter</a> 'person :last-name &quot;Gander&quot;)))</code></pre>

<p>Use <code><a href="#CL-OHM:COMBINE">COMBINE</a></code> to limit the resulting set. Say, all persons with last
name <strong>Duck</strong> and first name <strong>Donald</strong>:</p>

<pre><code>(<a href="#CL-OHM:ELEMENTS">ohm:elements</a> (<a href="#CL-OHM:COMBINE">ohm:combine</a> (<a href="#CL-OHM:FILTER">ohm:filter</a> 'person :last-name &quot;Duck&quot;)
(<a href="#CL-OHM:FILTER">ohm:filter</a> 'person :first-name &quot;Donald&quot;)))</code></pre>

<h2>Persistence Strategy</h2>

<p>Sets, lists and counters are stored implicitly after their mutation. If
you change normal attributes (with <code><a href="http://l1sp.org/cl/setf">SETF</a></code>) then those objects have to be
persisted with <code><a href="#CL-OHM:SAVE">SAVE</a></code>.</p>

<h1>API Documentation</h1>

<p>See <a href="http://rudolfochrist.github.com/cl-ohm">HTML Documentation</a>. There
is also an <a href="docs/cl-ohm.info">info file</a> for Emacs.</p>

<h1>Running the tests</h1>

<p>CL-OHM uses
<a href="https://common-lisp.net/project/fiveam/docs/index.html">FiveAM</a> for
testing. Please installed it with</p>

<pre><code>(ql:quickload :fiveam)</code></pre>

<p>Then you can run the test through ASDF:</p>

<pre><code>(asdf:test-system :cl-ohm)</code></pre>

<h1>License</h1>

<p><a href="LICENSE">MIT Copyright (c) 2016 Sebastian Christ</a></p>
</span>
<span/>

</article>
<article>
Expand Down

0 comments on commit a5b3636

Please sign in to comment.