pigeon_hole 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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: