pigeon_hole 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9f679f4b70108c6d3d567f1905462749de53dd26
4
+ data.tar.gz: c98c767931a8f0e1799e7db0d743c484ac46abf7
5
+ SHA512:
6
+ metadata.gz: 7fa933c8432ae976cc51a96f9ca01355d9ccdece601844411207752f629cb5a31fc89337827c91944426dd5b2e971d1351e44131185f09bc046eeedc00ca9e49
7
+ data.tar.gz: d3384729d4a8a7bdd0cf82a6099fea598fdfb62da7fea3e66dc7a4e0242c203b43e9db9539aaf721c101bebd4124a2088acc14f66d9efe8cf4d7f8969d2149f6
@@ -0,0 +1,29 @@
1
+ module PigeonHole
2
+ class JSONDate < SimpleDelegator
3
+ # Deserializes JSON string by converting Julian year <tt>y</tt>, month
4
+ # <tt>m</tt>, day <tt>d</tt> and Day of Calendar Reform <tt>sg</tt> to Date.
5
+ def self.json_create(object)
6
+ Date.civil(*object.values_at('y', 'm', 'd', 'sg'))
7
+ end
8
+
9
+ #alias start sg unless method_defined?(:start)
10
+
11
+ # Returns a hash, that will be turned into a JSON object and represent this
12
+ # object.
13
+ def as_json(*)
14
+ {
15
+ JSON.create_id => self.class.name,
16
+ 'y' => year,
17
+ 'm' => month,
18
+ 'd' => day,
19
+ 'sg' => start,
20
+ }
21
+ end
22
+
23
+ # Stores class name (Date) with Julian year <tt>y</tt>, month <tt>m</tt>, day
24
+ # <tt>d</tt> and Day of Calendar Reform <tt>sg</tt> as JSON string
25
+ def to_json(*args)
26
+ as_json.to_json(*args)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,41 @@
1
+ module PigeonHole
2
+ class JSONDateTime < SimpleDelegator
3
+ # Deserializes JSON string by converting year <tt>y</tt>, month <tt>m</tt>,
4
+ # day <tt>d</tt>, hour <tt>H</tt>, minute <tt>M</tt>, second <tt>S</tt>,
5
+ # offset <tt>of</tt> and Day of Calendar Reform <tt>sg</tt> to DateTime.
6
+ def self.json_create(object)
7
+ args = object.values_at('y', 'm', 'd', 'H', 'M', 'S')
8
+ of_a, of_b = object['of'].split('/')
9
+ if of_b and of_b != '0'
10
+ args << DateTime.send(:Rational, of_a.to_i, of_b.to_i)
11
+ else
12
+ args << of_a
13
+ end
14
+ args << object['sg']
15
+ DateTime.civil(*args)
16
+ end
17
+
18
+ # Returns a hash, that will be turned into a JSON object and represent this
19
+ # object.
20
+ def as_json(*)
21
+ {
22
+ JSON.create_id => self.class.name,
23
+ 'y' => year,
24
+ 'm' => month,
25
+ 'd' => day,
26
+ 'H' => hour,
27
+ 'M' => min,
28
+ 'S' => sec,
29
+ 'of' => offset.to_s,
30
+ 'sg' => start,
31
+ }
32
+ end
33
+
34
+ # Stores class name (DateTime) with Julian year <tt>y</tt>, month <tt>m</tt>,
35
+ # day <tt>d</tt>, hour <tt>H</tt>, minute <tt>M</tt>, second <tt>S</tt>,
36
+ # offset <tt>of</tt> and Day of Calendar Reform <tt>sg</tt> as JSON string
37
+ def to_json(*args)
38
+ as_json.to_json(*args)
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,22 @@
1
+ module PigeonHole
2
+ class JSONSymbol < SimpleDelegator
3
+ # Returns a hash, that will be turned into a JSON object and represent this
4
+ # object.
5
+ def as_json(*)
6
+ {
7
+ JSON.create_id => self.class.name,
8
+ 's' => to_s,
9
+ }
10
+ end
11
+
12
+ # Stores class name (Symbol) with String representation of Symbol as a JSON string.
13
+ def to_json(*a)
14
+ as_json.to_json(*a)
15
+ end
16
+
17
+ # Deserializes JSON string by converting the <tt>string</tt> value stored in the object to a Symbol
18
+ def self.json_create(o)
19
+ o['s'].to_sym
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,34 @@
1
+ module PigeonHole
2
+ class JSONTime < SimpleDelegator
3
+ # Deserializes JSON string by converting time since epoch to Time
4
+ def self.json_create(object)
5
+ if usec = object.delete('u') # used to be tv_usec -> tv_nsec
6
+ object['n'] = usec * 1000
7
+ end
8
+ if method_defined?(:tv_nsec)
9
+ Time.at(object['s'], Time.Rational(object['n'], 1000))
10
+ else
11
+ Time.at(object['s'], object['n'] / 1000)
12
+ end
13
+ end
14
+
15
+ # Returns a hash, that will be turned into a JSON object and represent this
16
+ # object.
17
+ def as_json(*)
18
+ nanoseconds = [ tv_usec * 1000 ]
19
+ respond_to?(:tv_nsec) and nanoseconds << tv_nsec
20
+ nanoseconds = nanoseconds.max
21
+ {
22
+ JSON.create_id => self.class.name,
23
+ 's' => tv_sec,
24
+ 'n' => nanoseconds,
25
+ }
26
+ end
27
+
28
+ # Stores class name (Time) with number of seconds since epoch and number of
29
+ # microseconds for Time as JSON string
30
+ def to_json(*args)
31
+ as_json.to_json(*args)
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,40 @@
1
+ require 'json'
2
+
3
+ module PigeonHole
4
+ class TypedJSON
5
+ def self.generate(obj, *args)
6
+ hash_dup = each_with_parent(obj)
7
+ JSON.generate(hash_dup, *args)
8
+ end
9
+
10
+ def self.map_to_json(obj)
11
+ case obj
12
+ when Time
13
+ JSONTime.new(obj)
14
+ when DateTime
15
+ JSONDateTime.new(obj)
16
+ when Date
17
+ JSONDate.new(obj)
18
+ when Symbol
19
+ JSONSymbol.new(obj)
20
+ else
21
+ obj
22
+ end
23
+ end
24
+
25
+ def self.each_with_parent(hash, result=nil)
26
+ duplicated_hash = {} || result
27
+
28
+ hash.each do |k, v|
29
+ case v
30
+ when Hash
31
+ duplicated_hash[k] = each_with_parent(v, duplicated_hash)
32
+ else
33
+ duplicated_hash[k] = map_to_json(v)
34
+ end
35
+ end
36
+
37
+ duplicated_hash
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,19 @@
1
+ module PigeonHole
2
+ require_relative 'pigeon_hole/typed_json'
3
+ require_relative 'pigeon_hole/json_date'
4
+ require_relative 'pigeon_hole/json_date_time'
5
+ require_relative 'pigeon_hole/json_symbol'
6
+ require_relative 'pigeon_hole/json_time'
7
+
8
+ def self.generate(obj, *args)
9
+ TypedJSON.generate(obj, *args)
10
+ end
11
+
12
+ def self.parse(string)
13
+ load(string)
14
+ end
15
+
16
+ def self.load(string)
17
+ JSON.load(string)
18
+ end
19
+ end
@@ -0,0 +1,99 @@
1
+ require 'spec_helper'
2
+
3
+ describe "serializing dates" do
4
+ let(:date) { random_date }
5
+
6
+ subject { PigeonHole.generate(date: date) }
7
+
8
+ it "serializes hash into a string" do
9
+ result = subject
10
+ expect(result).to_not be_empty
11
+ end
12
+
13
+ it "can be deserialized to a date time" do
14
+ result = subject
15
+ hash = PigeonHole.parse(result)
16
+ expect(hash).to eq({ "date" => date })
17
+ expect(hash["date"]).to be_a(Date)
18
+ end
19
+ end
20
+
21
+ describe "serializing times" do
22
+ let(:time) { random_time }
23
+
24
+ subject { PigeonHole.generate(time: time) }
25
+
26
+ it "serializes hash into a string" do
27
+ result = subject
28
+ expect(result).to_not be_empty
29
+ end
30
+
31
+ it "can be deserialized to a time" do
32
+ result = subject
33
+ hash = PigeonHole.parse(result)
34
+ expect(hash).to eq({ "time" => time })
35
+ expect(hash["time"]).to be_a(Time)
36
+ end
37
+ end
38
+
39
+ describe "serializing datetimes" do
40
+ let(:date_time) { random_date_time }
41
+
42
+ subject { PigeonHole.generate(date_time: date_time) }
43
+
44
+ it "serializes hash into a string" do
45
+ result = subject
46
+ expect(result).to_not be_empty
47
+ end
48
+
49
+ it "can be deserialized to a date_time" do
50
+ result = subject
51
+ hash = PigeonHole.parse(result)
52
+ expect(hash["date_time"]).to be_a(DateTime)
53
+ expect(hash["date_time"].to_date).to eq(date_time.to_date)
54
+ expect(hash["date_time"].to_time.to_i).to eq(date_time.to_time.to_i)
55
+ end
56
+ end
57
+
58
+ describe "serializing symbols" do
59
+ let(:symbol) { :a_symbol }
60
+
61
+ subject { PigeonHole.generate(symbol: symbol) }
62
+
63
+ it "serializes hash into a string" do
64
+ result = subject
65
+ expect(result).to_not be_empty
66
+ end
67
+
68
+ it "can be deserialized to a symbol" do
69
+ result = subject
70
+ hash = PigeonHole.parse(result)
71
+ expect(hash).to eq({ "symbol" => symbol })
72
+ expect(hash["symbol"]).to be_a(Symbol)
73
+ end
74
+ end
75
+
76
+ describe "serializing nested hashes" do
77
+ let(:expected) do
78
+ {
79
+ foo: {
80
+ bar: random_time,
81
+ baz: :temp
82
+ }
83
+ }
84
+ end
85
+
86
+ subject { PigeonHole.generate(expected) }
87
+
88
+ it "serializes hash into a string" do
89
+ result = subject
90
+ expect(result).to_not be_empty
91
+ end
92
+
93
+ it "can be deserialized to a symbol" do
94
+ result = subject
95
+ hash = PigeonHole.parse(result)
96
+
97
+ expect(symbolize_hash(hash)).to eq(expected)
98
+ end
99
+ end
@@ -0,0 +1,33 @@
1
+ require 'rake'
2
+ require 'rspec'
3
+
4
+ require "#{Rake.application.original_dir}/lib/pigeon_hole"
5
+
6
+ include PigeonHole
7
+
8
+ def random_integer
9
+ rand(9999)
10
+ end
11
+
12
+ def random_time
13
+ Time.now - random_integer
14
+ end
15
+
16
+ def random_date
17
+ Date.today - random_integer
18
+ end
19
+
20
+ def random_date_time
21
+ DateTime.now
22
+ end
23
+
24
+ def symbolize_hash(obj)
25
+ if obj.is_a?(Hash)
26
+ obj.inject({}) do |memo, (k,v)|
27
+ memo[k.to_sym] = symbolize_hash(v)
28
+ memo
29
+ end
30
+ else
31
+ obj
32
+ end
33
+ end
metadata ADDED
@@ -0,0 +1,54 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pigeon_hole
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Stephen Binns
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-07-13 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description:
14
+ email:
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - lib/pigeon_hole.rb
20
+ - lib/pigeon_hole/json_date.rb
21
+ - lib/pigeon_hole/json_date_time.rb
22
+ - lib/pigeon_hole/json_symbol.rb
23
+ - lib/pigeon_hole/json_time.rb
24
+ - lib/pigeon_hole/typed_json.rb
25
+ - spec/integration_spec.rb
26
+ - spec/spec_helper.rb
27
+ homepage: http://www.cronofy.com
28
+ licenses:
29
+ - MIT
30
+ metadata: {}
31
+ post_install_message:
32
+ rdoc_options: []
33
+ require_paths:
34
+ - lib
35
+ required_ruby_version: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ required_rubygems_version: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
45
+ requirements: []
46
+ rubyforge_project:
47
+ rubygems_version: 2.6.1
48
+ signing_key:
49
+ specification_version: 4
50
+ summary: Opt-in typed serialization for complex JSON types
51
+ test_files:
52
+ - spec/integration_spec.rb
53
+ - spec/spec_helper.rb
54
+ has_rdoc: