moneta 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (212) hide show
  1. data/.gitignore +7 -0
  2. data/.travis.yml +39 -0
  3. data/Gemfile +61 -0
  4. data/LICENSE +2 -2
  5. data/README.md +450 -0
  6. data/Rakefile +29 -51
  7. data/SPEC.md +75 -0
  8. data/benchmarks/run.rb +195 -0
  9. data/lib/action_dispatch/middleware/session/moneta_store.rb +11 -0
  10. data/lib/active_support/cache/moneta_store.rb +55 -0
  11. data/lib/moneta.rb +121 -67
  12. data/lib/moneta/adapters/activerecord.rb +87 -0
  13. data/lib/moneta/adapters/cassandra.rb +91 -0
  14. data/lib/moneta/adapters/client.rb +69 -0
  15. data/lib/moneta/adapters/cookie.rb +35 -0
  16. data/lib/moneta/adapters/couch.rb +57 -0
  17. data/lib/moneta/adapters/datamapper.rb +75 -0
  18. data/lib/moneta/adapters/dbm.rb +25 -0
  19. data/lib/moneta/adapters/file.rb +79 -0
  20. data/lib/moneta/adapters/fog.rb +51 -0
  21. data/lib/moneta/adapters/gdbm.rb +25 -0
  22. data/lib/moneta/adapters/hbase.rb +101 -0
  23. data/lib/moneta/adapters/leveldb.rb +35 -0
  24. data/lib/moneta/adapters/localmemcache.rb +28 -0
  25. data/lib/moneta/adapters/lruhash.rb +85 -0
  26. data/lib/moneta/adapters/memcached.rb +11 -0
  27. data/lib/moneta/adapters/memcached_dalli.rb +69 -0
  28. data/lib/moneta/adapters/memcached_native.rb +70 -0
  29. data/lib/moneta/adapters/memory.rb +10 -0
  30. data/lib/moneta/adapters/mongo.rb +50 -0
  31. data/lib/moneta/adapters/null.rb +30 -0
  32. data/lib/moneta/adapters/pstore.rb +69 -0
  33. data/lib/moneta/adapters/redis.rb +68 -0
  34. data/lib/moneta/adapters/riak.rb +57 -0
  35. data/lib/moneta/adapters/sdbm.rb +35 -0
  36. data/lib/moneta/adapters/sequel.rb +79 -0
  37. data/lib/moneta/adapters/sqlite.rb +65 -0
  38. data/lib/moneta/adapters/tokyocabinet.rb +41 -0
  39. data/lib/moneta/adapters/yaml.rb +15 -0
  40. data/lib/moneta/base.rb +78 -0
  41. data/lib/moneta/builder.rb +39 -0
  42. data/lib/moneta/cache.rb +84 -0
  43. data/lib/moneta/expires.rb +71 -0
  44. data/lib/moneta/lock.rb +25 -0
  45. data/lib/moneta/logger.rb +61 -0
  46. data/lib/moneta/mixins.rb +65 -0
  47. data/lib/moneta/net.rb +18 -0
  48. data/lib/moneta/optionmerger.rb +39 -0
  49. data/lib/moneta/proxy.rb +86 -0
  50. data/lib/moneta/server.rb +81 -0
  51. data/lib/moneta/shared.rb +60 -0
  52. data/lib/moneta/stack.rb +78 -0
  53. data/lib/moneta/transformer.rb +159 -0
  54. data/lib/moneta/transformer/config.rb +42 -0
  55. data/lib/moneta/transformer/helper.rb +37 -0
  56. data/lib/moneta/version.rb +5 -0
  57. data/lib/moneta/wrapper.rb +33 -0
  58. data/lib/rack/cache/moneta.rb +93 -0
  59. data/lib/rack/moneta_cookies.rb +64 -0
  60. data/lib/rack/session/moneta.rb +63 -0
  61. data/moneta.gemspec +19 -0
  62. data/spec/action_dispatch/fixtures/session_autoload_test/foo.rb +10 -0
  63. data/spec/action_dispatch/session_moneta_store_spec.rb +196 -0
  64. data/spec/active_support/cache_moneta_store_spec.rb +197 -0
  65. data/spec/generate.rb +1489 -0
  66. data/spec/helper.rb +91 -0
  67. data/spec/moneta/adapter_activerecord_spec.rb +32 -0
  68. data/spec/moneta/adapter_cassandra_spec.rb +30 -0
  69. data/spec/moneta/adapter_client_spec.rb +19 -0
  70. data/spec/moneta/adapter_cookie_spec.rb +18 -0
  71. data/spec/moneta/adapter_couch_spec.rb +18 -0
  72. data/spec/moneta/adapter_datamapper_spec.rb +49 -0
  73. data/spec/moneta/adapter_dbm_spec.rb +18 -0
  74. data/spec/moneta/adapter_file_spec.rb +18 -0
  75. data/spec/moneta/adapter_fog_spec.rb +23 -0
  76. data/spec/moneta/adapter_gdbm_spec.rb +18 -0
  77. data/spec/moneta/adapter_hbase_spec.rb +18 -0
  78. data/spec/moneta/adapter_leveldb_spec.rb +18 -0
  79. data/spec/moneta/adapter_localmemcache_spec.rb +18 -0
  80. data/spec/moneta/adapter_lruhash_spec.rb +31 -0
  81. data/spec/moneta/adapter_memcached_dalli_spec.rb +30 -0
  82. data/spec/moneta/adapter_memcached_native_spec.rb +31 -0
  83. data/spec/moneta/adapter_memcached_spec.rb +30 -0
  84. data/spec/moneta/adapter_memory_spec.rb +39 -0
  85. data/spec/moneta/adapter_mongo_spec.rb +18 -0
  86. data/spec/moneta/adapter_pstore_spec.rb +21 -0
  87. data/spec/moneta/adapter_redis_spec.rb +30 -0
  88. data/spec/moneta/adapter_riak_spec.rb +22 -0
  89. data/spec/moneta/adapter_sdbm_spec.rb +18 -0
  90. data/spec/moneta/adapter_sequel_spec.rb +18 -0
  91. data/spec/moneta/adapter_sqlite_spec.rb +18 -0
  92. data/spec/moneta/adapter_tokyocabinet_bdb_spec.rb +18 -0
  93. data/spec/moneta/adapter_tokyocabinet_hdb_spec.rb +18 -0
  94. data/spec/moneta/adapter_yaml_spec.rb +21 -0
  95. data/spec/moneta/cache_file_memory_spec.rb +34 -0
  96. data/spec/moneta/cache_memory_null_spec.rb +23 -0
  97. data/spec/moneta/expires_file_spec.rb +76 -0
  98. data/spec/moneta/expires_memory_spec.rb +65 -0
  99. data/spec/moneta/lock_spec.rb +42 -0
  100. data/spec/moneta/null_adapter_spec.rb +26 -0
  101. data/spec/moneta/optionmerger_spec.rb +92 -0
  102. data/spec/moneta/proxy_expires_memory_spec.rb +55 -0
  103. data/spec/moneta/proxy_redis_spec.rb +23 -0
  104. data/spec/moneta/shared_spec.rb +30 -0
  105. data/spec/moneta/simple_activerecord_spec.rb +51 -0
  106. data/spec/moneta/simple_activerecord_with_expires_spec.rb +52 -0
  107. data/spec/moneta/simple_cassandra_spec.rb +52 -0
  108. data/spec/moneta/simple_client_tcp_spec.rb +67 -0
  109. data/spec/moneta/simple_client_unix_spec.rb +53 -0
  110. data/spec/moneta/simple_couch_spec.rb +51 -0
  111. data/spec/moneta/simple_couch_with_expires_spec.rb +52 -0
  112. data/spec/moneta/simple_datamapper_spec.rb +53 -0
  113. data/spec/moneta/simple_datamapper_with_expires_spec.rb +54 -0
  114. data/spec/moneta/simple_datamapper_with_repository_spec.rb +53 -0
  115. data/spec/moneta/simple_dbm_spec.rb +51 -0
  116. data/spec/moneta/simple_dbm_with_expires_spec.rb +52 -0
  117. data/spec/moneta/simple_file_spec.rb +51 -0
  118. data/spec/moneta/simple_file_with_expires_spec.rb +52 -0
  119. data/spec/moneta/simple_fog_spec.rb +56 -0
  120. data/spec/moneta/simple_fog_with_expires_spec.rb +58 -0
  121. data/spec/moneta/simple_gdbm_spec.rb +51 -0
  122. data/spec/moneta/simple_gdbm_with_expires_spec.rb +52 -0
  123. data/spec/moneta/simple_hashfile_spec.rb +51 -0
  124. data/spec/moneta/simple_hashfile_with_expires_spec.rb +52 -0
  125. data/spec/moneta/simple_hbase_spec.rb +51 -0
  126. data/spec/moneta/simple_hbase_with_expires_spec.rb +52 -0
  127. data/spec/moneta/simple_leveldb_spec.rb +51 -0
  128. data/spec/moneta/simple_leveldb_with_expires_spec.rb +52 -0
  129. data/spec/moneta/simple_localmemcache_spec.rb +51 -0
  130. data/spec/moneta/simple_localmemcache_with_expires_spec.rb +52 -0
  131. data/spec/moneta/simple_lruhash_spec.rb +51 -0
  132. data/spec/moneta/simple_lruhash_with_expires_spec.rb +52 -0
  133. data/spec/moneta/simple_memcached_dalli_spec.rb +52 -0
  134. data/spec/moneta/simple_memcached_native_spec.rb +52 -0
  135. data/spec/moneta/simple_memcached_spec.rb +52 -0
  136. data/spec/moneta/simple_memory_spec.rb +51 -0
  137. data/spec/moneta/simple_memory_with_compress_spec.rb +51 -0
  138. data/spec/moneta/simple_memory_with_expires_spec.rb +52 -0
  139. data/spec/moneta/simple_memory_with_json_key_serializer_spec.rb +37 -0
  140. data/spec/moneta/simple_memory_with_json_serializer_spec.rb +28 -0
  141. data/spec/moneta/simple_memory_with_json_value_serializer_spec.rb +35 -0
  142. data/spec/moneta/simple_memory_with_prefix_spec.rb +51 -0
  143. data/spec/moneta/simple_memory_with_snappy_compress_spec.rb +51 -0
  144. data/spec/moneta/simple_mongo_spec.rb +51 -0
  145. data/spec/moneta/simple_mongo_with_expires_spec.rb +52 -0
  146. data/spec/moneta/simple_null_spec.rb +36 -0
  147. data/spec/moneta/simple_pstore_spec.rb +51 -0
  148. data/spec/moneta/simple_pstore_with_expires_spec.rb +52 -0
  149. data/spec/moneta/simple_redis_spec.rb +52 -0
  150. data/spec/moneta/simple_riak_spec.rb +55 -0
  151. data/spec/moneta/simple_riak_with_expires_spec.rb +56 -0
  152. data/spec/moneta/simple_sdbm_spec.rb +51 -0
  153. data/spec/moneta/simple_sdbm_with_expires_spec.rb +52 -0
  154. data/spec/moneta/simple_sequel_spec.rb +51 -0
  155. data/spec/moneta/simple_sequel_with_expires_spec.rb +52 -0
  156. data/spec/moneta/simple_sqlite_spec.rb +51 -0
  157. data/spec/moneta/simple_sqlite_with_expires_spec.rb +52 -0
  158. data/spec/moneta/simple_tokyocabinet_spec.rb +51 -0
  159. data/spec/moneta/simple_tokyocabinet_with_expires_spec.rb +52 -0
  160. data/spec/moneta/simple_yaml_spec.rb +50 -0
  161. data/spec/moneta/simple_yaml_with_expires_spec.rb +51 -0
  162. data/spec/moneta/stack_file_memory_spec.rb +25 -0
  163. data/spec/moneta/stack_memory_file_spec.rb +24 -0
  164. data/spec/moneta/transformer_bencode_spec.rb +30 -0
  165. data/spec/moneta/transformer_bert_spec.rb +30 -0
  166. data/spec/moneta/transformer_bson_spec.rb +30 -0
  167. data/spec/moneta/transformer_bzip2_spec.rb +27 -0
  168. data/spec/moneta/transformer_json_spec.rb +30 -0
  169. data/spec/moneta/transformer_lzma_spec.rb +27 -0
  170. data/spec/moneta/transformer_lzo_spec.rb +27 -0
  171. data/spec/moneta/transformer_marshal_base64_spec.rb +54 -0
  172. data/spec/moneta/transformer_marshal_escape_spec.rb +54 -0
  173. data/spec/moneta/transformer_marshal_hmac_spec.rb +54 -0
  174. data/spec/moneta/transformer_marshal_md5_spec.rb +54 -0
  175. data/spec/moneta/transformer_marshal_md5_spread_spec.rb +54 -0
  176. data/spec/moneta/transformer_marshal_prefix_spec.rb +54 -0
  177. data/spec/moneta/transformer_marshal_rmd160_spec.rb +54 -0
  178. data/spec/moneta/transformer_marshal_sha1_spec.rb +54 -0
  179. data/spec/moneta/transformer_marshal_sha256_spec.rb +54 -0
  180. data/spec/moneta/transformer_marshal_sha384_spec.rb +54 -0
  181. data/spec/moneta/transformer_marshal_sha512_spec.rb +54 -0
  182. data/spec/moneta/transformer_marshal_truncate_spec.rb +54 -0
  183. data/spec/moneta/transformer_marshal_uuencode_spec.rb +54 -0
  184. data/spec/moneta/transformer_msgpack_spec.rb +30 -0
  185. data/spec/moneta/transformer_ox_spec.rb +51 -0
  186. data/spec/moneta/transformer_quicklz_spec.rb +27 -0
  187. data/spec/moneta/transformer_snappy_spec.rb +27 -0
  188. data/spec/moneta/transformer_tnet_spec.rb +30 -0
  189. data/spec/moneta/transformer_yaml_spec.rb +51 -0
  190. data/spec/moneta/transformer_zlib_spec.rb +27 -0
  191. data/spec/monetaspecs.rb +2663 -0
  192. data/spec/rack/cache_moneta_spec.rb +355 -0
  193. data/spec/rack/moneta_cookies_spec.rb +81 -0
  194. data/spec/rack/session_moneta_spec.rb +305 -0
  195. metadata +359 -56
  196. data/README +0 -51
  197. data/TODO +0 -4
  198. data/lib/moneta/basic_file.rb +0 -111
  199. data/lib/moneta/berkeley.rb +0 -53
  200. data/lib/moneta/couch.rb +0 -63
  201. data/lib/moneta/datamapper.rb +0 -117
  202. data/lib/moneta/file.rb +0 -91
  203. data/lib/moneta/lmc.rb +0 -52
  204. data/lib/moneta/memcache.rb +0 -52
  205. data/lib/moneta/memory.rb +0 -11
  206. data/lib/moneta/mongodb.rb +0 -58
  207. data/lib/moneta/redis.rb +0 -49
  208. data/lib/moneta/rufus.rb +0 -41
  209. data/lib/moneta/s3.rb +0 -162
  210. data/lib/moneta/sdbm.rb +0 -33
  211. data/lib/moneta/tyrant.rb +0 -58
  212. data/lib/moneta/xattr.rb +0 -58
@@ -0,0 +1,7 @@
1
+ attic
2
+ spec/tmp
3
+ *~
4
+ *.swp
5
+ *.rdb
6
+ benchmarks/bench.*
7
+ Gemfile.lock
@@ -0,0 +1,39 @@
1
+ rvm:
2
+ - 1.8.7
3
+ - 1.9.3
4
+ # - ruby-head
5
+ - jruby
6
+ - rbx-18mode
7
+ - rbx-19mode
8
+ services:
9
+ - riak
10
+ - couchdb
11
+ - redis-server
12
+ - cassandra
13
+ - memcached
14
+ - mongodb
15
+ before_install:
16
+ - sudo apt-get install -qq libtokyocabinet8 libtokyocabinet-dev liblzo2-dev
17
+ env:
18
+ - "TASK=test:parallel"
19
+ - "TASK=test:non_parallel"
20
+ - "TASK=benchmarks"
21
+ matrix:
22
+ allow_failures:
23
+ # - rvm: ruby-head
24
+ - rvm: jruby
25
+ - rvm: rbx-18mode
26
+ - rvm: rbx-19mode
27
+ # Parallel tests do not work on jruby
28
+ exclude:
29
+ - rvm: jruby
30
+ env: "TASK=test:parallel"
31
+ - rvm: 1.8.7
32
+ env: "TASK=benchmarks"
33
+ - rvm: jruby
34
+ env: "TASK=benchmarks"
35
+ - rvm: rbx-18mode
36
+ env: "TASK=benchmarks"
37
+ - rvm: rbx-19mode
38
+ env: "TASK=benchmarks"
39
+ script: "bundle exec rake $TASK"
data/Gemfile ADDED
@@ -0,0 +1,61 @@
1
+ source :rubygems
2
+ gemspec
3
+
4
+ def alternatives(gems)
5
+ if defined?(JRUBY_VERSION)
6
+ [gems[:jruby]].flatten.compact.each {|g| gem g }
7
+ else
8
+ [gems[:mri]].flatten.compact.each {|g| gem g }
9
+ end
10
+ end
11
+
12
+ # Testing
13
+ gem 'rake'
14
+ gem 'rspec'
15
+ gem 'parallel_tests'
16
+
17
+ # Serializer used by Transformer
18
+ gem 'tnetstring'
19
+ gem 'bencode'
20
+ gem 'multi_json'
21
+ alternatives :mri => 'bson_ext', :jruby => 'bson'
22
+ alternatives :mri => 'ox'
23
+ alternatives :mri => 'msgpack', :jruby => 'msgpack-jruby'
24
+ alternatives :mri => 'bert'
25
+
26
+ # Compressors used by Transformer
27
+ alternatives :mri => 'bzip2-ruby'
28
+ alternatives :mri => 'ruby-lzma'
29
+ alternatives :mri => 'lzoruby'
30
+ alternatives :mri => 'snappy'
31
+ # QuickLZ segfaults because of an assertion, fix this before activating it again
32
+ # alternatives :mri => 'qlzruby'
33
+
34
+ # Backends
35
+ gem 'dm-core'
36
+ gem 'dm-migrations'
37
+ gem 'dm-sqlite-adapter'
38
+ gem 'fog'
39
+ gem 'activerecord', '>= 3.2.9'
40
+ gem 'redis'
41
+ gem 'mongo'
42
+ gem 'couchrest'
43
+ gem 'sequel'
44
+ gem 'dalli'
45
+ gem 'riak-client'
46
+ gem 'cassandra'
47
+ #gem 'hbaserb'
48
+ #gem 'localmemcache'
49
+ alternatives :mri => 'leveldb-ruby'
50
+ alternatives :mri => 'tokyocabinet'
51
+ alternatives :mri => 'memcached', :jruby => 'jruby-memcached'
52
+ alternatives :mri => 'sqlite3', :jruby => %w(jdbc-sqlite3 activerecord-jdbc-adapter activerecord-jdbcsqlite3-adapter)
53
+ alternatives :jruby => %w(ffi gdbm) # gdbm for jruby needs ffi
54
+
55
+ # Rack integration testing
56
+ gem 'rack'
57
+ gem 'rack-cache'
58
+
59
+ # Rails integration testing
60
+ gem 'actionpack'
61
+ gem 'minitest'
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2009 Yehuda Katz
1
+ Copyright (c) 2009 Yehuda Katz, 2012 Daniel Mendler
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
@@ -17,4 +17,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
17
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
18
  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
19
  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,450 @@
1
+ # Moneta: A unified interface for key/value stores
2
+
3
+ [![Build Status](https://secure.travis-ci.org/minad/moneta.png?branch=master)](http://travis-ci.org/minad/moneta) [![Dependency Status](https://gemnasium.com/minad/moneta.png?travis)](https://gemnasium.com/minad/moneta) [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/minad/moneta)
4
+
5
+ Moneta provides a standard interface for interacting with various kinds of key/value stores. Moneta is very feature rich:
6
+
7
+ * Supports a lot of backends (See below)
8
+ * Supports proxies (Similar to [Rack middlewares](http://rack.github.com/))
9
+ * Custom serialization via `Moneta::Transformer` proxy (Marshal/JSON/YAML and many more)
10
+ * Custom key transformation via `Moneta::Transformer` proxy
11
+ * Value compression via `Moneta::Transformer` proxy (Zlib, Snappy, LZMA, ...)
12
+ * Expiration for all stores (Added via proxy `Moneta::Expires` if not supported natively)
13
+ * Atomic incrementation and decrementation for most stores (Method `#increment`)
14
+ * Includes a very simple key/value server (`Moneta::Server`) and client (`Moneta::Adapters::Client`)
15
+ * Integration with [Rails](http://rubyonrails.org/), [Rack](http://rack.github.com/) as cookie and session store and [Rack-Cache](https://github.com/rtomayko/rack-cache)
16
+
17
+ Moneta is tested thoroughly using [Travis-CI](http://travis-ci.org/minad/moneta).
18
+
19
+ ## Links
20
+
21
+ * Source: <http://github.com/minad/moneta>
22
+ * Bugs: <http://github.com/minad/moneta/issues>
23
+ * API documentation:
24
+ * Latest Gem: <http://rubydoc.info/gems/moneta/frames>
25
+ * GitHub master: <http://rubydoc.info/github/minad/moneta/master/frames>
26
+
27
+ ## Supported backends
28
+
29
+ Out of the box, it supports the following backends:
30
+
31
+ * Memory:
32
+ * In-memory store (`:Memory`)
33
+ * LRU hash - prefer this over :Memory! (`:LRUHash`)
34
+ * LocalMemCache (`:LocalMemCache`)
35
+ * Memcached store (`:Memcached`, `:MemcachedNative` and `:MemcachedDalli`)
36
+ * Relational Databases:
37
+ * DataMapper (`:DataMapper`)
38
+ * ActiveRecord (`:ActiveRecord`)
39
+ * Sequel (`:Sequel`)
40
+ * Sqlite3 (`:Sqlite`)
41
+ * Filesystem:
42
+ * PStore (`:PStore`)
43
+ * YAML store (`:YAML`)
44
+ * Filesystem directory store (`:File`)
45
+ * Filesystem directory store which spreads files in subdirectories using md5 hash (`:HashFile`)
46
+ * Key/value databases:
47
+ * Berkeley DB (`:DBM`)
48
+ * Cassandra (`:Cassandra`)
49
+ * GDBM (`:GDBM`)
50
+ * HBase (`:HBase`)
51
+ * LevelDB (`:LevelDB`)
52
+ * Redis (`:Redis`)
53
+ * Riak (`:Riak`)
54
+ * SDBM (`:SDBM`)
55
+ * TokyoCabinet (`:TokyoCabinet`)
56
+ * Document databases:
57
+ * CouchDB (`:Couch`)
58
+ * MongoDB (`:Mongo`)
59
+ * Other
60
+ * Moneta key/value server client (`:Client` works with `Moneta::Server`)
61
+ * Fog cloud storage which supports Amazon S3, Rackspace, etc. (`:Fog`)
62
+ * Storage which doesn't store anything (`:Null`)
63
+
64
+ Some of the backends are not exactly based on key/value stores, e.g. the relational ones. These
65
+ are useful if you already use the corresponding backend in your application. You get a key/value
66
+ store for free then without installing any additional services and you still have the possibility
67
+ to upgrade to a real key/value store.
68
+
69
+ ## Proxies
70
+
71
+ In addition it supports proxies (Similar to [Rack middlewares](http://rack.github.com/)) which
72
+ add additional features to storage backends:
73
+
74
+ * `Moneta::Proxy` and `Moneta::Wrapper` proxy base classes
75
+ * `Moneta::Expires` to add expiration support to stores which don't support it natively. Add it in the builder using `use :Expires`.
76
+ * `Moneta::Stack` to stack multiple stores (Read returns result from first where the key is found, writes go to all stores). Add it in the builder using `use :Stack`.
77
+ * `Moneta::Transformer` transforms keys and values (Marshal, YAML, JSON, Base64, MD5, ...). Add it in the builder using `use :Transformer`.
78
+ * `Moneta::Cache` combine two stores, one as backend and one as cache (e.g. `Moneta::Adapters::File` + `Moneta::Adapters::Memory`). Add it in the builder using `use :Cache`.
79
+ * `Moneta::Lock` to make store thread safe. Add it in the builder using `use :Lock`.
80
+ * `Moneta::Logger` to log database accesses. Add it in the builder using `use :Logger`.
81
+ * `Moneta::Shared` to share a store between multiple processes. Add it in the builder using `use :Shared`.
82
+
83
+ ## Supported serializers and compressors (`Moneta::Transformer`)
84
+
85
+ Supported serializers:
86
+
87
+ * BEncode (`:bencode`)
88
+ * BERT (`:bert`)
89
+ * BSON (`:bson`)
90
+ * JSON (`:json`)
91
+ * Marshal (`:marshal`)
92
+ * MessagePack (`:msgpack`)
93
+ * Ox (`:ox`)
94
+ * TNetStrings (`:tnet`)
95
+ * YAML (`:yaml`)
96
+
97
+ Supported value compressors:
98
+
99
+ * LZMA (`:lzma`)
100
+ * LZO (`:lzo`)
101
+ * Snappy (`:snappy`)
102
+ * QuickLZ (`:quicklz`)
103
+ * Zlib (`:zlib`)
104
+
105
+ Special transformers:
106
+
107
+ * Digests (MD5, Shas, ...)
108
+ * Add prefix to keys (`:prefix`)
109
+ * HMAC to verify values (`:hmac`, useful for `Rack::MonetaCookies`)
110
+
111
+ ## Moneta API
112
+
113
+ ~~~
114
+ #initialize(options) options differs per-store, and is used to set up the store.
115
+
116
+ #[](key) retrieve a key. If the key is not available, return nil.
117
+
118
+ #load(key, options = {}) retrieve a key. If the key is not available, return nil.
119
+
120
+ #fetch(key, options = {}, &block) retrieve a key. If the key is not available, execute the
121
+ block and return its return value.
122
+
123
+ #fetch(key, value, options = {}) retrieve a key. If the key is not available, return the value,
124
+
125
+ #[]=(key, value) set a value for a key. If the key is already used, clobber it.
126
+ keys set using []= will never expire.
127
+
128
+ #store(key, value, options = {}) same as []=, but you can supply options.
129
+
130
+ #delete(key, options = {}) delete the key from the store and return the current value.
131
+
132
+ #key?(key, options = {}) true if the key exists, false if it does not.
133
+
134
+ #increment(key, amount = 1, options = {}) increment numeric value. This is a atomic operation
135
+ which is not supported by all stores. Returns current value.
136
+
137
+ #clear(options = {}) clear all keys in this store.
138
+
139
+ #close close database connection.
140
+ ~~~
141
+
142
+ The Moneta API is purposely extremely similar to the Hash API. In order so support an
143
+ identical API across stores, it does not support iteration or partial matches.
144
+
145
+ ### Creating a Store
146
+
147
+ There is a simple interface to create a store using `Moneta.new`:
148
+
149
+ ~~~ ruby
150
+ store = Moneta.new(:Memcached, :server => 'localhost:11211')
151
+ ~~~
152
+
153
+ If you want to have control over the proxies, you have to use `Moneta.build`:
154
+
155
+ ~~~ ruby
156
+ store = Moneta.build do
157
+ # Adds expires proxy
158
+ use :Expires
159
+ # Transform key using Marshal and Base64 and value using Marshal
160
+ use :Transformer, :key => [:marshal, :base64], :value => :marshal
161
+ # Memory backend
162
+ adapter :Memory
163
+ end
164
+ ~~~
165
+
166
+ ### Expiration
167
+
168
+ The Cassandra, Memcached and Redis backends supports expires values directly:
169
+
170
+ ~~~ ruby
171
+ cache = Moneta::Adapters::Memcached.new
172
+
173
+ # Or using the builder...
174
+ cache = Moneta.build do
175
+ adapter :Memcached
176
+ end
177
+
178
+ # Expires in 60 seconds
179
+ cache.store(key, value, :expires => 60)
180
+
181
+ # Update expires time if value is found
182
+ cache.load(key, :expires => 30)
183
+ cache.key?(key, :expires => 30)
184
+ ~~~
185
+
186
+ You can add the expires feature to other backends using the Expires proxy:
187
+
188
+ ~~~ ruby
189
+ # Using the :expires option
190
+ cache = Moneta.new(:File, :dir => '...', :expires => true)
191
+
192
+ # or manually by using the proxy...
193
+ cache = Moneta::Expires.new(Moneta::Adapters::File.new(:dir => '...'))
194
+
195
+ # or using the builder...
196
+ cache = Moneta.build do
197
+ use :Expires
198
+ adapter :File, :dir => '...'
199
+ end
200
+ ~~~
201
+
202
+ ### Incrementation and raw access
203
+
204
+ The stores support the `#increment` which allows atomic increments of unsigned integer values. If you increment
205
+ a non existing value, it will be created. If you increment a non integer value an exception will be raised.
206
+
207
+ ~~~ ruby
208
+ store.increment('counter') => 1 # counter created
209
+ store.increment('counter') => 2
210
+ store.increment('counter', -1) => 1
211
+ store.increment('counter', 13) => 14
212
+ store.increment('counter', 0) => 14
213
+ store['name'] = 'Moneta'
214
+ store.increment('name') => Exception
215
+ ~~~
216
+
217
+ If you want to access the counter value you have to use raw access to the datastore. This is only important
218
+ if you have a `Moneta::Transformer` somewhere in your proxy chain which transforms the values e.g. with `Marshal`.
219
+
220
+ ~~~ ruby
221
+ store.increment('counter') => 1 # counter created
222
+ store.load('counter', :raw => true) => '1'
223
+
224
+ store.store('counter', '10', :raw => true)
225
+ store.increment('counter') => 11
226
+ ~~~
227
+
228
+ Fortunately there is a nicer way to do this using some syntactic sugar!
229
+
230
+ ~~~ ruby
231
+ store.increment('counter') => 1 # counter created
232
+ store.raw['counter'] => '1'
233
+ store.raw.load('counter') => '1'
234
+
235
+ store.raw['counter'] = '10'
236
+ store.increment('counter') => 11
237
+ ~~~
238
+
239
+ You can also keep the `raw` store in a variable and use it like this:
240
+
241
+ ~~~ ruby
242
+ counters = store.raw
243
+
244
+ counters.increment('counter') => 1 # counter created
245
+ counters['counter'] => '1'
246
+ counters.load('counter') => '1'
247
+
248
+ counters['counter'] = '10'
249
+ counters.increment('counter') => 11
250
+ ~~~
251
+
252
+ Stores which support incrementation (you have to use `Moneta::Lock` if you want to use the store in a multithreading environment.)
253
+
254
+ * ActiveRecord
255
+ * File
256
+ * HBase
257
+ * LRUHash
258
+ * LevelDB
259
+ * Memcached
260
+ * Memory
261
+ * Redis
262
+ * SDBM/DBM/GDBM
263
+ * Sequel
264
+ * Sqlite
265
+ * TokyoCabinet
266
+ * YAML/PStore
267
+
268
+ Stores which don't support incrementation:
269
+
270
+ * Cassandra
271
+ * Couch
272
+ * DataMapper
273
+ * Fog
274
+ * LocalMemCache
275
+ * Mongo
276
+ * Riak
277
+
278
+ ### Syntactic sugar and option merger
279
+
280
+ For raw data access as described before the class `Moneta::OptionMerger` is used. It works like this:
281
+
282
+ ~~~ ruby
283
+ # All methods after `with` get the options passed
284
+ store.with(:raw => true).load('key')
285
+
286
+ # You can also specify the methods
287
+ store.with(:raw => true, :only => :load).load('key')
288
+ store.with(:raw => true, :except => [:key?, :increment]).load('key')
289
+
290
+ # Syntactic sugar for raw access
291
+ store.raw.load('key')
292
+
293
+ # Access substore where all keys get a prefix
294
+ substore = store.prefix('sub')
295
+ substore['key'] = 'value'
296
+ store['key'] => nil
297
+ store['subkey'] => 'value'
298
+
299
+ # Set expiration time for all keys
300
+ short_lived_store = long_lived_store.expires(60)
301
+ short_lived_store['key'] = 'value'
302
+ ~~~
303
+
304
+ ## Framework Integration
305
+
306
+ Inspired by [redis-store](https://github.com/jodosha/redis-store) there exist integration classes for [Rails](http://rubyonrails.org/), [Rack](http://rack.github.com/) and [Rack-Cache](https://github.com/rtomayko/rack-cache).
307
+
308
+ ### Rack session store
309
+
310
+ Use Moneta as a [Rack](http://rack.github.com/) session store:
311
+
312
+ ~~~ ruby
313
+ require 'rack/session/moneta'
314
+
315
+ # Use only the adapter name
316
+ use Rack::Session::Moneta, :store => :Redis
317
+
318
+ # Use Moneta.new
319
+ use Rack::Session::Moneta, :store => Moneta.new(:Memory, :expires => true)
320
+
321
+ # Use the Moneta builder
322
+ use Rack::Session::Moneta do
323
+ use :Expires
324
+ adapter :Memory
325
+ end
326
+ ~~~
327
+
328
+ ### Rack cache
329
+
330
+ Use Moneta as a [Rack-Cache](https://github.com/rtomayko/rack-cache) store:
331
+
332
+ ~~~ ruby
333
+ require 'rack/cache/moneta'
334
+
335
+ use Rack::Cache,
336
+ :metastore => 'moneta://Memory?expires=true',
337
+ :entitystore => 'moneta://Memory?expires=true'
338
+
339
+ # Or used named Moneta stores
340
+ Rack::Cache::Moneta['named_metastore'] = Moneta.build do
341
+ use :Expires
342
+ adapter :Memory
343
+ end
344
+ use Rack::Cache,
345
+ :metastore => 'moneta://named_metastore',
346
+ :entity_store => 'moneta://named_entitystore'
347
+ ~~~
348
+
349
+ ### Rack cookies
350
+
351
+ Use Moneta to store cookies in [Rack](http://rack.github.com/). It uses the `Moneta::Adapters::Cookie`. You might
352
+ wonder what the purpose of this store or Rack middleware is: It makes it possible
353
+ to use all the transformers on the cookies (e.g. `:prefix`, `:marshal` and `:hmac` for value verification).
354
+
355
+ ~~~ ruby
356
+ require 'rack/moneta_cookies'
357
+
358
+ use Rack::MonetaCookies, :domain => 'example.com', :path => '/path'
359
+ run lambda do |env|
360
+ req = Rack::Request.new(env)
361
+ req.cookies #=> is now a Moneta store!
362
+ env['rack.request.cookie_hash'] #=> is now a Moneta store!
363
+ req.cookies['key'] #=> retrieves 'key'
364
+ req.cookies['key'] = 'value' #=> sets 'key'
365
+ req.cookies.delete('key') #=> removes 'key'
366
+ [200, {}, []]
367
+ end
368
+ ~~~
369
+
370
+ ### Rails session store
371
+
372
+ Add the session store in your application configuration `config/environments/*.rb`.
373
+
374
+ ~~~ ruby
375
+ require 'moneta'
376
+
377
+ # Only by adapter name
378
+ config.cache_store :moneta_store, :store => :Memory
379
+
380
+ # Use Moneta.new
381
+ config.cache_store :moneta_store, :store => Moneta.new(:Memory)
382
+
383
+ # Use the Moneta builder
384
+ config.cache_store :moneta_store, :store => Moneta.build do
385
+ use :Expires
386
+ adapter :Memory
387
+ end
388
+ ~~~
389
+
390
+ ### Rails cache store
391
+
392
+ Add the cache store in your application configuration `config/environments/*.rb`. Unfortunately the
393
+ Moneta cache store doesn't support matchers. If you need these features use a different server-specific implementation.
394
+
395
+ ~~~ ruby
396
+ require 'moneta'
397
+
398
+ # Only by adapter name
399
+ config.cache_store :moneta_store, :store => :Memory
400
+
401
+ # Use Moneta.new
402
+ config.cache_store :moneta_store, :store => Moneta.new(:Memory)
403
+
404
+ # Use the Moneta builder
405
+ config.cache_store :moneta_store, :store => Moneta.build do
406
+ use :Expires
407
+ adapter :Memory
408
+ end
409
+ ~~~
410
+
411
+ ## Advanced - Build your own key value server
412
+
413
+ You can use Moneta to build your own key/value server which is shared between
414
+ multiple processes. If you run the following code in two different processes,
415
+ they will share the same data which will also be persistet in the database `shared.db`.
416
+
417
+ ~~~ ruby
418
+ require 'moneta'
419
+
420
+ store = Moneta.build do
421
+ use :Transformer, :key => :marshal, :value => :marshal
422
+ use :Shared do
423
+ use :Cache do
424
+ cache do
425
+ adapter :LRUHash
426
+ end
427
+ backend do
428
+ adapter :GDBM, :file => 'shared.db'
429
+ end
430
+ end
431
+ end
432
+ end
433
+ ~~~
434
+
435
+ ## More information
436
+
437
+ * http://yehudakatz.com/2009/02/12/whats-the-point/
438
+ * http://yehudakatz.com/2009/02/12/initial-release-of-moneta-unified-keyvalue-store-api/
439
+
440
+ ## Alternatives
441
+
442
+ * [Horcrux](https://github.com/technoweenie/horcrux): Used at github, supports batch operations but only Memcached backend
443
+ * [ToyStore](https://github.com/jnunemaker/toystore): ORM mapper for key/value stores
444
+ * [ToyStore Adapter](https://github.com/jnunemaker/adapter): Adapter to key/value stores used by ToyStore, Moneta can be used directly with the ToyStore Memory adapter
445
+
446
+ ## Authors
447
+
448
+ * Daniel Mendler
449
+ * Hannes Georg
450
+ * Originally by Yehuda Katz and contributors