sander6-daijobu 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +60 -1
- data/lib/daijobu/adapter.rb +10 -0
- data/lib/daijobu/adapters/mem_cache.rb +7 -0
- data/lib/daijobu/adapters/tokyo_cabinet.rb +5 -0
- data/lib/daijobu/adapters/tokyo_tyrant.rb +5 -0
- data/lib/daijobu/client.rb +27 -0
- data/lib/daijobu/errors.rb +6 -0
- data/lib/daijobu/namespace_proxy.rb +17 -5
- data/lib/daijobu/scheme.rb +13 -0
- data/lib/daijobu/scheme_set.rb +18 -1
- data/lib/daijobu/schemes/eval.rb +6 -0
- data/lib/daijobu/schemes/json.rb +9 -0
- data/lib/daijobu/schemes/marshal.rb +4 -0
- data/lib/daijobu/schemes/raw.rb +7 -1
- data/lib/daijobu/schemes/yaml.rb +8 -0
- metadata +1 -1
data/README.rdoc
CHANGED
@@ -1,6 +1,65 @@
|
|
1
1
|
= Daijobu
|
2
2
|
|
3
|
-
|
3
|
+
=== "Oh no! Another key-value-store wrapper!"
|
4
|
+
|
5
|
+
Don't worry, Daijobu isn't about that. Rather, it wraps the serialization/deserialzation layer of accessing key-value stores, specifically Tokyo Cabinet, but I guess with some work it could work with other things.
|
6
|
+
|
7
|
+
=== "So how's it work?"
|
8
|
+
|
9
|
+
Make a new, inappropriately-named Daijobu::Client object and give it your store (supported stores are MemCache, Rufus::Tokyo::Cabinet, and Rufus::Tokyo::Tyrant), and then the scheme or schemes you want to use for serialization.
|
10
|
+
|
11
|
+
rufus = Rufus::Tokyo::Cabinet.new('casket.tch')
|
12
|
+
daijobu = Daijobu::Client.new(rufus, :schemes => :json)
|
13
|
+
|
14
|
+
You can now use the regular hash getter and setter methods ([] and []=) without worrying about serialization.
|
15
|
+
|
16
|
+
The supported schemes are :marshal (using Marshal), :json (using JSON from the json gem), :yaml (using YAML), :eval (using Kernel::eval), and :raw (using nothing).
|
17
|
+
|
18
|
+
Because some schemes are very strict, and sometimes what gets dumped can't be parsed back (for example, unparsing an integer using JSON), you can specify a set of schemes. If one doesn't work, it'll try the next in the list until it succeeds in parsing.
|
19
|
+
|
20
|
+
Daijobu::Client.new(rufus, :schemes => [:json, :yaml, :eval])
|
21
|
+
|
22
|
+
Daijobu doesn't do any real format-checking; if, say, Marshal.load throws an error, for whatever reason, it'll just rescue and move on to the next scheme. The success of this gem all hinges on the fact that the supported serialization formats don't have much to do with one another (except for JSON and YAML, of course), and you shouldn't ever end up parsing Ruby code as JSON accidentally, or at least not in unintended ways.
|
23
|
+
|
24
|
+
You can set different read and write schemes, too. This would be useful, say, if you wanted to change the serialization format.
|
25
|
+
|
26
|
+
Daijobu::Client.new(rufus, :read => :json, :write => :raw)
|
27
|
+
|
28
|
+
One last cool thing that I threw in just because: the key names in a key-value store are often namespaced. You can call these namespaces as methods on a Client object to automatically prepend that namespace to any keys asked for.
|
29
|
+
|
30
|
+
daijobu = Daijobu::Client.new(rufus, :read => :json, :write => :raw)
|
31
|
+
daijobu.namespace['123'] # => looks for 'namespace:123'
|
32
|
+
daijobu.name.space['123'] # => looks for 'name:space:123'
|
33
|
+
|
34
|
+
You can set the separator (defaults to ':' because that's what I was using) on the Daijobu::NamespaceProxy class.
|
35
|
+
|
36
|
+
Daijobu::NamespaceProxy.default_separator = '/'
|
37
|
+
daijobu.name.space['123'] # => looks for 'name/space/123'
|
38
|
+
|
39
|
+
And a last bit of syntatical sugar: you can leave off the brackets when asking for namespaced keys.
|
40
|
+
|
41
|
+
daijobu.namespace '123' # => looks for 'namespace:123'
|
42
|
+
daijobu.name.space '123' # => looks for 'name:space:123'
|
43
|
+
|
44
|
+
=== "Anything else I should know?"
|
45
|
+
|
46
|
+
Pretty much only the getting and setting APIs are implemented for the supported adapters, so fancier stuff like iterating over keys isn't there yet.
|
47
|
+
|
48
|
+
Multi-get is also kind of janky right now for MemCache, due to a flaw in the memcache-client gem that assumes Marshal.load'ing on get_multi. Keys are therefore fetched one at a time.
|
49
|
+
|
50
|
+
=== "What does the future hold for Daijobu?"
|
51
|
+
|
52
|
+
I plan to eventually switch out my home-rolled adapters for a more complete and more-intelligently-written backend, like Moneta, but last time I checked it was broken and I needed this gem to do work right now.
|
53
|
+
|
54
|
+
Until then, I'm thinking of putting in support for user-defined adapters as a stopgap, basically any object that responds to #get(key) and #set(key, value).
|
55
|
+
|
56
|
+
Less of a priority is support for user-defined serialization schemes that respond to #parse(string) and #unparse(object).
|
57
|
+
|
58
|
+
I also plan to take a look at ActiveRecord::Base#serialize to see if I can do something with that, because reading and writing YAML is like dying every day.
|
59
|
+
|
60
|
+
=== "What's with the name?"
|
61
|
+
|
62
|
+
It's my understanding that "daijobu" is Japanese for "I'm fine" or "It's okay". The hardest thing about making gems is deciding what to call them, and that's the first thing that popped into my head.
|
4
63
|
|
5
64
|
== Copyright
|
6
65
|
|
data/lib/daijobu/adapter.rb
CHANGED
@@ -1,6 +1,16 @@
|
|
1
1
|
module Daijobu
|
2
|
+
|
3
|
+
# Daijobu::Adapter is the parent module of the various adapter classes.
|
2
4
|
module Adapter
|
3
5
|
|
6
|
+
# Given an object, returns a new instance of the corresponding adapter based on the
|
7
|
+
# object's class.
|
8
|
+
#
|
9
|
+
# MemCache => Daijobu::Adapter::MemCacheAdapter
|
10
|
+
# Rufus::Tokyo::Cabinet => Daijobu::Adapter::TokyoCabinetAdapter
|
11
|
+
# Rufus::Tokyo::Tyrant => Daijobu::Adapter::TokyoTyrantAdapter
|
12
|
+
#
|
13
|
+
# Raises Daijobu::InvalidAdapter if given a object it doesn't know about.
|
4
14
|
def self.get(casket)
|
5
15
|
if defined?(MemCache) && casket.is_a?(MemCache)
|
6
16
|
Daijobu::Adapter::MemCacheAdapter.new(casket)
|
@@ -2,12 +2,17 @@ module Daijobu
|
|
2
2
|
|
3
3
|
module Adapter
|
4
4
|
|
5
|
+
# Daijobu::Adapter::MemCacheAdapter wraps getting and setting to a MemCache store.
|
6
|
+
# Note that you can use MemCache to talk to a Tokyo Tyrant server, since they
|
7
|
+
# speak the same language.
|
5
8
|
class MemCacheAdapter
|
6
9
|
|
10
|
+
# Daijobu::Adapter::MemCacheAdapter.new takes a MemCache object.
|
7
11
|
def initialize(store)
|
8
12
|
@store = store
|
9
13
|
end
|
10
14
|
|
15
|
+
# Gets the key or keys given. Multiple values will be returned in a hash.
|
11
16
|
def get(*keys)
|
12
17
|
if keys.size == 0
|
13
18
|
nil
|
@@ -18,12 +23,14 @@ module Daijobu
|
|
18
23
|
end
|
19
24
|
end
|
20
25
|
|
26
|
+
# Sets the key to the given value (using MemCache#add).
|
21
27
|
def set(key, value)
|
22
28
|
@store.add(key, value, 0, true)
|
23
29
|
end
|
24
30
|
|
25
31
|
private
|
26
32
|
|
33
|
+
# Gets a single key. Used internally.
|
27
34
|
def get_one(key)
|
28
35
|
@store.get(key, true)
|
29
36
|
end
|
@@ -2,12 +2,16 @@ module Daijobu
|
|
2
2
|
|
3
3
|
module Adapter
|
4
4
|
|
5
|
+
# Daijobu::Adapter::TokyoCabinetAdapter wraps getting and setting to a Rufus::Tokyo::Cabinet store.
|
5
6
|
class TokyoCabinetAdapter
|
6
7
|
|
8
|
+
# Daijobu::Adapter::TokyoCabinetAdapter.new takes a Rufus::Tokyo::Cabinet object.
|
7
9
|
def initialize(store)
|
8
10
|
@store = store
|
9
11
|
end
|
10
12
|
|
13
|
+
# Gets the key or keys given, using Cabinet#[] or Cabinet#lget.
|
14
|
+
# Multiple values should be returned in a hash, but that's really up to the Cabinet object.
|
11
15
|
def get(*keys)
|
12
16
|
if keys.size == 0
|
13
17
|
nil
|
@@ -18,6 +22,7 @@ module Daijobu
|
|
18
22
|
end
|
19
23
|
end
|
20
24
|
|
25
|
+
# Sets the key to the given value (using Cabinet#[]=).
|
21
26
|
def set(key, value)
|
22
27
|
@store[key] = value
|
23
28
|
end
|
@@ -2,12 +2,16 @@ module Daijobu
|
|
2
2
|
|
3
3
|
module Adapter
|
4
4
|
|
5
|
+
# Daijobu::Adapter::TokyoTyrantAdapter wraps getting and setting to a Rufus::Tokyo::Tyrant store.
|
5
6
|
class TokyoTyrantAdapter
|
6
7
|
|
8
|
+
# Daijobu::Adapter::TokyoTyrantAdapter.new takes a Rufus::Tokyo::Tyrant object.
|
7
9
|
def initialize(store)
|
8
10
|
@store = store
|
9
11
|
end
|
10
12
|
|
13
|
+
# Gets the key or keys given, using Tyrant#[] or Tyrant#lget.
|
14
|
+
# Multiple values should be returned in a hash, but that's really up to Tyrant object.
|
11
15
|
def get(*keys)
|
12
16
|
if keys.size == 0
|
13
17
|
nil
|
@@ -18,6 +22,7 @@ module Daijobu
|
|
18
22
|
end
|
19
23
|
end
|
20
24
|
|
25
|
+
# Sets the key to the given value (using Tyrant#[]=).
|
21
26
|
def set(key, value)
|
22
27
|
@store[key] = value
|
23
28
|
end
|
data/lib/daijobu/client.rb
CHANGED
@@ -1,30 +1,57 @@
|
|
1
1
|
module Daijobu
|
2
|
+
|
3
|
+
# The unfortunately-named Daijobu::Client is the serialization wrapper for key-value stores.
|
2
4
|
class Client
|
3
5
|
|
6
|
+
# Client.new takes a key-value store as its first argument, and then a hash of serialization schemes.
|
7
|
+
#
|
8
|
+
# Options:
|
9
|
+
# :schemes => the scheme or schemes used to read and write, in order
|
10
|
+
# :read => the scheme or schemes used to read, in order. Trumped by :schemes
|
11
|
+
# :write => the scheme or schemes used to write, in order. Trumped by :schemes
|
4
12
|
def initialize(casket, options = {})
|
5
13
|
@adapter = Daijobu::Adapter.get(casket)
|
6
14
|
@read_schemes = Daijobu::SchemeSet.new(options[:schemes] || options[:read])
|
7
15
|
@write_schemes = Daijobu::SchemeSet.new(options[:schemes] || options[:write])
|
8
16
|
end
|
9
17
|
|
18
|
+
# Getter for keys. The actual getting method is handled by the specific Adapter object.
|
19
|
+
# You can ask for multiple keys at once, in which case this returns a hash of key => value.
|
10
20
|
def [](*keys)
|
11
21
|
__parse__(@adapter.get(*keys.collect { |key| key.to_s }))
|
12
22
|
end
|
13
23
|
|
24
|
+
# Setter for keys. The actual setting method is handled by the specific Adapter object.
|
14
25
|
def []=(key, value)
|
15
26
|
@adapter.set(key.to_s, __unparse__(value))
|
16
27
|
end
|
17
28
|
|
29
|
+
# Any missing method is assumed to be a namespace for keys to get. The NamespaceProxy object
|
30
|
+
# returned also implements the same kind of method_missing, so namespaces can be chained together.
|
31
|
+
#
|
32
|
+
# client.namespace['key'] # => gets key 'namespace:key'
|
33
|
+
# client.name.space['key'] # => gets key 'name:space:key'
|
34
|
+
# client.namespace['key'] = 'value' # => sets key 'namespace:key'
|
35
|
+
#
|
36
|
+
# As an added bit of syntactic sugar, you can leave the brackets off when getting keys this way.
|
37
|
+
#
|
38
|
+
# client.namespace 'key' # => same as client.namespace['key']
|
39
|
+
#
|
40
|
+
# See NamespaceProxy for more details about setting the separator.
|
18
41
|
def method_missing(name, *args)
|
19
42
|
args.empty? ? Daijobu::NamespaceProxy.new(self, name) : Daijobu::NamespaceProxy.new(self, name)[*args]
|
20
43
|
end
|
21
44
|
|
22
45
|
private
|
23
46
|
|
47
|
+
# Tries to parse (load) the string using each of the reading schemes in order.
|
48
|
+
# The actual parsing is done by the specific Scheme object.
|
24
49
|
def __parse__(str)
|
25
50
|
@read_schemes.parse(str)
|
26
51
|
end
|
27
52
|
|
53
|
+
# Tries to unparse (dump) the object using each of the writing schemes in order.
|
54
|
+
# The actual unparsing is done by the specific Scheme object.
|
28
55
|
def __unparse__(obj)
|
29
56
|
@write_schemes.unparse(obj)
|
30
57
|
end
|
data/lib/daijobu/errors.rb
CHANGED
@@ -1,11 +1,17 @@
|
|
1
1
|
module Daijobu
|
2
2
|
|
3
|
+
# The superclass of all the errors that Daijobu raises.
|
3
4
|
class Error < StandardError; end
|
4
5
|
|
6
|
+
# Raised when asking for a scheme that doesn't exist.
|
7
|
+
# Supported schemes are :marshal, :json, :yaml, :eval, and :raw.
|
5
8
|
class UnknownScheme < Daijobu::Error; end
|
6
9
|
|
10
|
+
# Raised when the key-value-store object doesn't have a appropriate adapter.
|
11
|
+
# Supported stores are MemCache, Rufus::Tokyo::Cabinet, and Rufus::Tokyo::Tyrant.
|
7
12
|
class InvalidAdapter < Daijobu::Error; end
|
8
13
|
|
14
|
+
# Raised when all of the (un)parsing schemes fail.
|
9
15
|
class NoFallbackScheme < Daijobu::Error; end
|
10
16
|
|
11
17
|
end
|
@@ -2,31 +2,43 @@ module Daijobu
|
|
2
2
|
class NamespaceProxy
|
3
3
|
|
4
4
|
@@default_separator = ':'
|
5
|
+
|
6
|
+
# Getter for the default separator. Default is ':'
|
5
7
|
def self.default_separator
|
6
8
|
@@default_separator
|
7
9
|
end
|
8
10
|
|
11
|
+
# Setter for the default separator. I use ':', but a lot of people like '/'.
|
9
12
|
def self.default_separator=(separator)
|
10
13
|
@@default_separator = separator
|
11
14
|
end
|
12
|
-
|
15
|
+
|
16
|
+
# NamespaceProxy.new takes an owner (a Daijobu::Client), a namespace, and a separator (defaults
|
17
|
+
# to @@default_separator).
|
18
|
+
# NamespaceProxy objects are typically created using Daijobu::Client#method_missing, so you're
|
19
|
+
# rarely going to instantiate one of these on your own.
|
13
20
|
def initialize(owner, namespace, separator = @@default_separator)
|
14
21
|
@owner = owner
|
15
22
|
@namespace = namespace.to_s
|
16
23
|
@separator = separator
|
17
24
|
end
|
18
|
-
|
25
|
+
|
26
|
+
# Sends #[] back to the owner, prepending the key given with the namespace and separator.
|
19
27
|
def [](key)
|
20
28
|
@owner["#{@namespace}#{@separator}#{key}"]
|
21
29
|
end
|
22
|
-
|
30
|
+
|
31
|
+
# Sends #[]= back to the owner, prepending the key given with the namespace and separator.
|
23
32
|
def []=(key, value)
|
24
33
|
@owner["#{@namespace}#{@separator}#{key}"] = value
|
25
34
|
end
|
26
|
-
|
35
|
+
|
36
|
+
# Any missing method is assumed to be yet another namespace.
|
27
37
|
def method_missing(namespace, *args)
|
28
38
|
separator = args.shift || @@default_separator
|
29
|
-
|
39
|
+
@namespace = "#{@namespace}#{@separator}#{namespace}"
|
40
|
+
@separator = separator
|
41
|
+
self
|
30
42
|
end
|
31
43
|
end
|
32
44
|
end
|
data/lib/daijobu/scheme.rb
CHANGED
@@ -1,6 +1,17 @@
|
|
1
1
|
module Daijobu
|
2
|
+
|
3
|
+
# The Scheme module is the parent of the various serialization schemes.
|
2
4
|
module Scheme
|
3
5
|
|
6
|
+
# Given a name, returns a new instance of the corresponding scheme.
|
7
|
+
#
|
8
|
+
# :marshal => Daijobu::Scheme::Marshal
|
9
|
+
# :json => Daijobu::Scheme::JSON
|
10
|
+
# :yaml => Daijobu::Scheme::YAML
|
11
|
+
# :eval => Daijobu::Scheme::Eval
|
12
|
+
# :raw => Daijobu::Scheme::Raw
|
13
|
+
#
|
14
|
+
# Raises Daijobu::UnknownScheme if given a name it can't handle.
|
4
15
|
def self.get(name)
|
5
16
|
case name
|
6
17
|
when :marshal
|
@@ -11,6 +22,8 @@ module Daijobu
|
|
11
22
|
Daijobu::Scheme::YAML.new
|
12
23
|
when :eval
|
13
24
|
Daijobu::Scheme::Eval.new
|
25
|
+
when :raw
|
26
|
+
Daijobu::Scheme::Raw.new
|
14
27
|
else
|
15
28
|
raise Daijobu::UnknownScheme
|
16
29
|
end
|
data/lib/daijobu/scheme_set.rb
CHANGED
@@ -1,10 +1,14 @@
|
|
1
1
|
module Daijobu
|
2
|
+
|
3
|
+
# A SchemeSet holds a bundle of schemes, and has logic for iterating over them.
|
2
4
|
class SchemeSet
|
3
5
|
|
4
6
|
DEFAULT = [ :marshal, :json, :yaml, :eval ]
|
5
7
|
|
6
8
|
attr_reader :current
|
7
|
-
|
9
|
+
|
10
|
+
# SchemeSet.new takes a single symbol or array of symbols and initializes a new Scheme
|
11
|
+
# object of the appropriate type for each one.
|
8
12
|
def initialize(schemes = nil)
|
9
13
|
schemes = Array(schemes)
|
10
14
|
schemes = DEFAULT if schemes.empty?
|
@@ -12,6 +16,11 @@ module Daijobu
|
|
12
16
|
@current = 0
|
13
17
|
end
|
14
18
|
|
19
|
+
# Returns the next scheme object in the stack. Raises Daijobu::NoFallbackScheme when there
|
20
|
+
# are no more schemes.
|
21
|
+
#
|
22
|
+
# And yes, I know it's kind of weird to call this method #next when the first invocation
|
23
|
+
# returns the first scheme, but it made sense at the time.
|
15
24
|
def next
|
16
25
|
scheme = @schemes[@current]
|
17
26
|
raise NoFallbackScheme unless scheme
|
@@ -19,10 +28,15 @@ module Daijobu
|
|
19
28
|
return scheme
|
20
29
|
end
|
21
30
|
|
31
|
+
# Resets the stack of schemes, so that the next invocation of #next returns the first scheme
|
32
|
+
# (I know, I know).
|
22
33
|
def reset
|
23
34
|
@current = 0
|
24
35
|
end
|
25
36
|
|
37
|
+
# Tries the parse (load) the string with each scheme in turn.
|
38
|
+
# Assumes (defensibly) that parsing failed if any non Daijobu::Error exceptions are raised
|
39
|
+
# and moves on to the next scheme.
|
26
40
|
def parse(str)
|
27
41
|
begin
|
28
42
|
obj = self.next.parse(str)
|
@@ -37,6 +51,9 @@ module Daijobu
|
|
37
51
|
obj
|
38
52
|
end
|
39
53
|
|
54
|
+
# Tries the unparse (dump) the string with each scheme in turn.
|
55
|
+
# Assumes (defensibly) that unparsing failed if any non Daijobu::Error exceptions are raised
|
56
|
+
# and moves on to the next scheme.
|
40
57
|
def unparse(obj)
|
41
58
|
begin
|
42
59
|
str = self.next.unparse(obj)
|
data/lib/daijobu/schemes/eval.rb
CHANGED
@@ -1,11 +1,17 @@
|
|
1
1
|
module Daijobu
|
2
2
|
module Scheme
|
3
|
+
|
4
|
+
# Daijobu::Scheme::Eval is the serialization for pure Ruby code.
|
5
|
+
# Theoretically, then, anything could be put into and taken out of a key-value-store,
|
6
|
+
# provided that they're always rehydrated into an appropriate binding.
|
3
7
|
class Eval
|
4
8
|
|
9
|
+
# Parses by #eval'ing the string.
|
5
10
|
def parse(str)
|
6
11
|
str.nil? ? nil : eval(str)
|
7
12
|
end
|
8
13
|
|
14
|
+
# Unparses by #inspect'ing the object.
|
9
15
|
def unparse(obj)
|
10
16
|
obj.inspect
|
11
17
|
end
|
data/lib/daijobu/schemes/json.rb
CHANGED
@@ -2,12 +2,21 @@ require 'json'
|
|
2
2
|
|
3
3
|
module Daijobu
|
4
4
|
module Scheme
|
5
|
+
|
6
|
+
# Daijobu::Scheme::JSON is the serialization for JSON.
|
7
|
+
# Uses the native (C) json gem, which is respectably fast.
|
5
8
|
class JSON
|
6
9
|
|
10
|
+
# Parses the string using JSON.parse.
|
11
|
+
# JSON is pretty strict, and it dies whenever the object doesn't have an enclosing
|
12
|
+
# structure (i.e. an array or tuple). You might have problems parsing bare strings,
|
13
|
+
# integers, booleans, and nulls. It's weird, though, because JSON doesn't seem to have
|
14
|
+
# a problem unparsing these things. Just a heads-up.
|
7
15
|
def parse(str)
|
8
16
|
str.nil? ? nil : ::JSON.parse(str)
|
9
17
|
end
|
10
18
|
|
19
|
+
# Unparses the object using JSON.unparse.
|
11
20
|
def unparse(obj)
|
12
21
|
::JSON.unparse(obj)
|
13
22
|
end
|
@@ -1,11 +1,15 @@
|
|
1
1
|
module Daijobu
|
2
2
|
module Scheme
|
3
|
+
|
4
|
+
# Daijobu::Scheme::Marshal is the serialization for Ruby binary code.
|
3
5
|
class Marshal
|
4
6
|
|
7
|
+
# Parses the string using Marshal.load.
|
5
8
|
def parse(str)
|
6
9
|
str.nil? ? nil : ::Marshal.load(str)
|
7
10
|
end
|
8
11
|
|
12
|
+
# Unparses the object using Marshal.dump.
|
9
13
|
def unparse(obj)
|
10
14
|
::Marshal.dump(obj)
|
11
15
|
end
|
data/lib/daijobu/schemes/raw.rb
CHANGED
@@ -1,11 +1,17 @@
|
|
1
1
|
module Daijobu
|
2
2
|
module Scheme
|
3
|
+
|
4
|
+
# Daijobu::Scheme::Raw is the serialization for nothing. Seriously, it doesn't do anything.
|
5
|
+
# It's rather dubious why you'd use this scheme for reading (if you're just going to be reading
|
6
|
+
# as raw, why use this gem at all?), but writing raw is useful sometimes.
|
3
7
|
class Raw
|
4
|
-
|
8
|
+
|
9
|
+
# Doesn't parse anything. Just returns the string.
|
5
10
|
def parse(str)
|
6
11
|
str
|
7
12
|
end
|
8
13
|
|
14
|
+
# Doesn't unparse anything. Just returns the object.
|
9
15
|
def unparse(obj)
|
10
16
|
obj
|
11
17
|
end
|
data/lib/daijobu/schemes/yaml.rb
CHANGED
@@ -2,12 +2,20 @@ require 'yaml'
|
|
2
2
|
|
3
3
|
module Daijobu
|
4
4
|
module Scheme
|
5
|
+
|
6
|
+
# Daijobu::Scheme::YAML is the serialization for YAML.
|
7
|
+
# Due to the strictness of the JSON module, you'll often have more luck parsing JSON containing
|
8
|
+
# bare objects (strings, integers, booleans, etc. without an enclosing structure) using YAML
|
9
|
+
# than with JSON, but YAML's a lot slower. That being said, it makes a good fallback scheme to use
|
10
|
+
# when JSON starts dying.
|
5
11
|
class YAML
|
6
12
|
|
13
|
+
# Parses the string using YAML.load.
|
7
14
|
def parse(str)
|
8
15
|
str.nil? ? nil : ::YAML.load(str)
|
9
16
|
end
|
10
17
|
|
18
|
+
# Unparses the object using YAML.dump.
|
11
19
|
def unparse(obj)
|
12
20
|
::YAML.dump(obj)
|
13
21
|
end
|