space_object 0.1.1 → 0.1.3

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 CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- NGZkZTdlNzAxMjA1YjIxOTA5YTk2NGY0MjY1ZjUzOWMxYTg0N2EyNA==
4
+ MTU2ZjBhNWE0NWVhZGZhMzM1OTQxMTUzNjYyNDlhMzU1ZTk2ZGQxNQ==
5
5
  data.tar.gz: !binary |-
6
- ZjBmZWI0OGQxZjRiMzEzNjNjMzliNDRjOTE4Mzk5NTAzNmYwOGU3YQ==
6
+ MDQ3OWFiOWIyMTIyZjFiODI2NmVlOGEzMGY1MWIyOGM0OTNjNGIyZQ==
7
7
  !binary "U0hBNTEy":
8
8
  metadata.gz: !binary |-
9
- OTc1ZmY5ZjY2MjcyOGQ5N2IwOWNkMzg4Zjc3OTU5ZDYwZDY1NTJkMjk3MDE4
10
- MGIzNmQ0NGNiMmNlYzAxMGU0MmYwN2E1ZGU4MjFjZWFiZjFiMTY3NzNmMjMw
11
- OTIzMmNhY2JkNjc3YjRhOThmZDNkNmJkY2JlMTAzNmUwZWUxNDY=
9
+ YzcxNWE1N2QxMzczNmEyMzk3M2Q4Yjg0M2EyZmM2OGE0MDI1NGRlZmE5MjZl
10
+ NGIzYTIzMWMzMTExYTc2NWU1ZGFmNjFkYmIzNTYyNTg5ZWY4N2Q1OTA4Yzc1
11
+ ODk5YjRjNGZkM2EyZDYzMjQzMzc1MGI3NzE2ZmQ2MGQ5ZDY5Mjg=
12
12
  data.tar.gz: !binary |-
13
- MWEwM2E4YmJiM2I1MzZhNjE3MWY0ZjhiNThkMjZlNzBkZjgyMjZkZTg5MDk0
14
- NjViN2JhMjU2NzU3MDczOGFlZmU2N2RjODk3NzU3MGM1MWI2NTVmNjc2MTg3
15
- NWI2NWU2NGViMjBlYTNmMmE2ZDMzNDMxY2FiYzdhMzA3OWIwMzU=
13
+ MmNjNDY2YTRjMjZkOTY2NzQ1YmU5MmE5OTdlZWJiMWIwNGYwMWNlMmY4ODJi
14
+ ZGQ2Yzg0YTI3N2I2NmJjZDIwYjRlY2NhYTU5MzZkMGU1MjBiODc0NzY4M2Ey
15
+ MjViYjg1MDFmYTk2MmUyNjZkYWI4NTJkMTY5MTQ2ZjZlNDBjZmY=
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- space_object (0.0.1)
4
+ space_object (0.1.3)
5
5
  activesupport (~> 4.0)
6
6
 
7
7
  GEM
@@ -1,6 +1,72 @@
1
1
  require 'active_support/ordered_hash'
2
+ require 'space_object/core_ext/object/space_object'
2
3
 
3
4
  module SpaceObject
4
5
  class Base < ActiveSupport::OrderedHash
6
+ def [](key)
7
+ key = convert_key!(key)
8
+ unless key[' ']
9
+ super(key)
10
+ else
11
+ first_key = key[/^[^ ]+/]
12
+ value = self[first_key]
13
+
14
+ return nil if hash.nil?
15
+ rest_keys = key[(first_key.length + 1)..-1]
16
+ value[rest_keys]
17
+ end
18
+ end
19
+
20
+ def []=(key, value)
21
+ key = convert_key!(key)
22
+ unless key[' ']
23
+ super(key, convert_value!(value))
24
+ else
25
+ first_key = key[/^[^ ]+/]
26
+ value = (self[first_key] ||= self.class.new)
27
+ value[(first_key.length + 1)..-1] = value
28
+ end
29
+ end
30
+
31
+ alias_method :store, :[]=
32
+
33
+ def default(key = nil)
34
+ super(key ? convert_key!(key) : nil)
35
+ end
36
+
37
+ def default=(val)
38
+ super(key ? convert_key!(key) : nil)
39
+ end
40
+
41
+ def fetch(key, *extras)
42
+ key = convert_key!(key)
43
+ first_key = key[/^[^ ]+/]
44
+
45
+ value = self[first_key]
46
+ if key[' '].nil? || hash.nil?
47
+ super(key, *extras)
48
+ else
49
+ value.fetch(first_key, *extras)
50
+ end
51
+ end
52
+
53
+ protected
54
+ def convert_key(key)
55
+ key.to_nested_space_key
56
+ end
57
+
58
+ def convert_key!(key)
59
+ raise(ArgumentError, "#{key.class} cannot be stored as a key in a #{self.class}") unless key.respond_to?(:to_nested_space_key)
60
+ convert_key(key)
61
+ end
62
+
63
+ def convert_value(val)
64
+ val.to_space_value
65
+ end
66
+
67
+ def convert_value!(val)
68
+ raise(ArgumentError, "#{val.class} cannot be stored as a key in a #{self.class}") unless val.respond_to?(:to_space_value)
69
+ convert_value(val)
70
+ end
5
71
  end
6
72
  end
@@ -0,0 +1,100 @@
1
+ # List of classes to encode mirrors JSON encodable objects in ActiveSupport
2
+
3
+ require 'time'
4
+ require 'space_object/string_encodable'
5
+
6
+ class Array
7
+ def to_space_object
8
+ each_with_index.map do |item, index|
9
+ {index => item}.to_space_object
10
+ end
11
+ end
12
+
13
+ def to_space_value
14
+ to_space_object
15
+ end
16
+ end
17
+
18
+ class Date
19
+ include SpaceObject::StringEncodable
20
+ end
21
+
22
+ class DateTime
23
+ include SpaceObject::StringEncodable
24
+ end
25
+
26
+ module Enumerable
27
+ def to_space_object
28
+ to_a.to_space_object
29
+ end
30
+
31
+ def to_space_value
32
+ to_space_object
33
+ end
34
+ end
35
+
36
+ class FalseClass
37
+ include SpaceObject::StringEncodable
38
+ end
39
+
40
+ class Hash
41
+ def to_space_object
42
+ SpaceObject::Encoder.new(self).encode
43
+ end
44
+ end
45
+
46
+ class NilClass
47
+ include SpaceObject::StringEncodable
48
+ end
49
+
50
+ class Numeric
51
+ include SpaceObject::StringEncodable
52
+ end
53
+
54
+ class Object
55
+ # Highly inspired by ActiveSupport
56
+ def to_space_object
57
+ hash = respond_to?(:to_hash) ? to_hash : insance_values
58
+ hash.to_space_object
59
+ end
60
+
61
+ def to_space_value
62
+ to_space_object
63
+ end
64
+ end
65
+
66
+ class Process::Status
67
+ include SpaceObject::StringEncodable
68
+ end
69
+
70
+ class Regexp
71
+ include SpaceObject::StringEncodable
72
+ end
73
+
74
+ class String
75
+ include SpaceObject::StringEncodable
76
+ end
77
+
78
+ class Symbol
79
+ include SpaceObject::StringEncodable
80
+ end
81
+
82
+ class Struct
83
+ # Highly inspired by ActiveSupport
84
+ def to_space_object
85
+ hash = Hash[members.zip(values)]
86
+ hash.to_space_object
87
+ end
88
+
89
+ def to_space_value
90
+ to_space_object
91
+ end
92
+ end
93
+
94
+ class Time
95
+ include SpaceObject::StringEncodable
96
+ end
97
+
98
+ class TrueClass
99
+ include SpaceObject::StringEncodable
100
+ end
@@ -0,0 +1,2 @@
1
+ class SpaceObject::EncodeError < StandardError
2
+ end
@@ -0,0 +1,22 @@
1
+ require 'space_object/base'
2
+
3
+ module SpaceObject
4
+ class Encoder
5
+ def initialize(object, options = {})
6
+ self.object = object
7
+ @as_key = !options.has_key?(:key) || options[:key]
8
+ end
9
+
10
+ def encode
11
+ raise(ArgumentError, "#{@object} is not a Hash") unless @object.is_a?(Hash)
12
+ @object.inject(Base.new) do |space, (key, val)|
13
+ space[key.to_space_key] = val.to_space_value
14
+ space
15
+ end
16
+ end
17
+
18
+ def object=(object)
19
+ @object = object
20
+ end
21
+ end
22
+ end
@@ -19,6 +19,9 @@ module SpaceObject
19
19
  @document = @document.strip.gsub(/(\r\n|\n\r|\n\n+)/, "\n")
20
20
  end
21
21
 
22
+ def populate_space(space, str)
23
+ end
24
+
22
25
  def parse_string(str)
23
26
  str.split(DELIMITER).inject(Base.new) do |obj, space|
24
27
  key, value = if matches = KEY_LINE.match(space)
@@ -28,7 +31,7 @@ module SpaceObject
28
31
  offset = matches[1].length + 1
29
32
  [matches[1], space[offset..-1].gsub(NEST_SPACING, "\n")]
30
33
  end
31
- key and obj[key] = value
34
+ (key.nil? || key.empty?) or obj[key] = value
32
35
  obj
33
36
  end
34
37
  end
@@ -0,0 +1,19 @@
1
+ require 'space_object/encode_error'
2
+
3
+ module SpaceObject
4
+ module StringEncodable
5
+ def to_nested_space_key
6
+ to_s
7
+ end
8
+
9
+ def to_space_key
10
+ str = to_nested_space_key
11
+ raise(EncodeError, "`#{str}' contains spaces and cannot be used as a key") if str[' ']
12
+ str
13
+ end
14
+
15
+ def to_space_value
16
+ to_s
17
+ end
18
+ end
19
+ end
@@ -1,4 +1,4 @@
1
1
  module SpaceObject
2
2
  # space_object version
3
- VERSION = "0.1.1"
3
+ VERSION = "0.1.3"
4
4
  end
data/lib/space_object.rb CHANGED
@@ -1,9 +1,15 @@
1
1
  require 'space_object/version'
2
+ require 'space_object/encode_error'
2
3
  require 'space_object/base'
3
4
  require 'space_object/parser'
5
+ require 'space_object/encoder'
4
6
 
5
7
  module SpaceObject
6
8
  class << self
9
+ def encode(object)
10
+ Encoder.new(object).encode
11
+ end
12
+
7
13
  def parse(document)
8
14
  Parser.new(document).parse
9
15
  end
@@ -1,7 +1,41 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe SpaceObject::Base do
4
- it 'is an ActiveSupport::OrderedHash' do
5
- expect(subject).to be_an(ActiveSupport::OrderedHash)
4
+ let(:key) { 'foo' }
5
+ let(:not_contained) { 'baz' }
6
+ let(:value) { 'bar' }
7
+
8
+ it 'is an Enumerable' do
9
+ expect(subject).to be_an(Enumerable)
10
+ end
11
+
12
+ describe '[]' do
13
+ subject { SpaceObject.encode({key => value}) }
14
+
15
+ it 'returns nil if the key does not exist' do
16
+ expect(subject[not_contained]).to be_nil
17
+ end
18
+
19
+ it 'returns the value for a key which exists' do
20
+ expect(subject[key]).to eq(value)
21
+ end
22
+
23
+ it 'can query with a key which implements #to_s' do
24
+ expect(subject[key.to_sym]).to eq(subject[key])
25
+ end
26
+ end
27
+
28
+ describe '[]=' do
29
+ subject { SpaceObject::Base.new }
30
+
31
+ it 'can assign with a non-nested key' do
32
+ subject[key] = value
33
+ expect(subject[key]).to eq(value)
34
+ end
35
+
36
+ it 'can assign with a key which implements #to_s' do
37
+ subject[key.to_sym] = value
38
+ expect(subject[key]).to eq(value)
39
+ end
6
40
  end
7
41
  end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ describe SpaceObject::Encoder do
4
+ let(:valid_example) { {:hello => 'world', 'foo' => :bar, 'foobar' => {'baz' => 'zip'}} }
5
+ let(:invalid_example) { { 'keys are not allowed' => 'value' } }
6
+ let(:wrong_class) { ['foo'] }
7
+
8
+ describe '#encode' do
9
+ it 'only encodes Hash objects' do
10
+ expect { SpaceObject::Encoder.new(wrong_class).encode }.to raise_error(ArgumentError)
11
+ end
12
+
13
+ it 'encodes a compliant Hash as a SpaceObject::Base' do |variable|
14
+ space = SpaceObject::Encoder.new(valid_example).encode
15
+ expect(space['hello']).to eq('world')
16
+ expect(space['foo']).to eq('bar')
17
+ expect(space['foobar baz']).to eq('zip')
18
+ end
19
+
20
+ it 'raises a SpaceObject::EncodeError if an invalid key is present' do
21
+ expect { SpaceObject::Encoder.new(invalid_example).encode }.to raise_error(SpaceObject::EncodeError)
22
+ end
23
+ end
24
+ end
@@ -19,22 +19,22 @@ describe SpaceObject::Parser do
19
19
  end
20
20
 
21
21
  context 'when given a key-value pair' do
22
- it_has_behavior 'correctness', 'key value', SpaceObject::Base.try_convert({'key' => 'value'})
22
+ it_has_behavior 'correctness', 'key value', SpaceObject.encode({'key' => 'value'})
23
23
  end
24
24
 
25
25
  context 'when given multiple key-value pairs' do
26
- it_has_behavior 'correctness', "1 2\na b", SpaceObject::Base.try_convert({'1' => '2', 'a' => 'b'})
26
+ it_has_behavior 'correctness', "1 2\na b", SpaceObject.encode({'1' => '2', 'a' => 'b'})
27
27
  end
28
28
 
29
29
  context 'when given a nested space' do
30
30
  document = "foo\n" +
31
31
  " bar\n" +
32
32
  " baz foobar"
33
- expected = SpaceObject::Base.try_convert({
34
- 'foo' => SpaceObject::Base.try_convert({
35
- 'bar' => SpaceObject::Base.new,
33
+ expected = SpaceObject.encode({
34
+ 'foo' => {
35
+ 'bar' => {},
36
36
  'baz' => 'foobar'
37
- })
37
+ }
38
38
  })
39
39
  it_has_behavior 'correctness', document, expected
40
40
  end
@@ -5,21 +5,45 @@ describe SpaceObject do
5
5
  expect(subject.const_get('VERSION')).not_to be_empty
6
6
  end
7
7
 
8
+ describe(:encode) do
9
+ let(:hash) { {'foo' => 'bar'} }
10
+ let(:encoder) { SpaceObject::Encoder.new(hash) }
11
+
12
+ before(:each) {
13
+ @instance = encoder
14
+ @instance.stub(:encode)
15
+ SpaceObject::Encoder.stub(:new).and_return(@instance)
16
+
17
+ SpaceObject.encode(hash)
18
+ }
19
+
20
+ it "creates a new SpaceObject::Encoder" do
21
+ expect(SpaceObject::Encoder).to have_received(:new).with(hash)
22
+ end
23
+
24
+ it "calls SpaceObject::Parser#encode" do
25
+ expect(@instance).to have_received(:encode)
26
+ end
27
+ end
28
+
8
29
  describe "::parse" do
9
30
  let(:test_document) { 'foo bar' }
31
+ let(:parser) { SpaceObject::Parser.new(test_document) }
10
32
 
11
33
  before(:each) {
12
- @instance = SpaceObject::Parser.new(test_document)
34
+ @instance = parser
35
+ @instance.stub(:parse)
13
36
  SpaceObject::Parser.stub(:new).and_return(@instance)
37
+
38
+ SpaceObject.parse(test_document)
14
39
  }
15
40
 
16
41
  it "creates a new SpaceObject::Parser" do
17
- SpaceObject.parse(test_document) and expect(SpaceObject::Parser).to have_received(:new).with(test_document)
42
+ expect(SpaceObject::Parser).to have_received(:new).with(test_document)
18
43
  end
19
44
 
20
45
  it "calls SpaceObject::Parser#parse" do
21
- @instance.stub(:parse)
22
- SpaceObject.parse(test_document) and expect(@instance).to have_received(:parse)
46
+ expect(@instance).to have_received(:parse)
23
47
  end
24
48
  end
25
49
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: space_object
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Fruchtman
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-11-06 00:00:00.000000000 Z
11
+ date: 2013-11-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rdoc
@@ -83,10 +83,15 @@ files:
83
83
  - Rakefile
84
84
  - lib/space_object.rb
85
85
  - lib/space_object/base.rb
86
+ - lib/space_object/core_ext/object/space_object.rb
87
+ - lib/space_object/encode_error.rb
88
+ - lib/space_object/encoder.rb
86
89
  - lib/space_object/parser.rb
90
+ - lib/space_object/string_encodable.rb
87
91
  - lib/space_object/version.rb
88
92
  - space_object.gemspec
89
93
  - spec/space_object/base_spec.rb
94
+ - spec/space_object/encoder_spec.rb
90
95
  - spec/space_object/parser_spec.rb
91
96
  - spec/space_object_spec.rb
92
97
  - spec/spec_helper.rb
@@ -116,6 +121,7 @@ specification_version: 4
116
121
  summary: A lightweight language for objects
117
122
  test_files:
118
123
  - spec/space_object/base_spec.rb
124
+ - spec/space_object/encoder_spec.rb
119
125
  - spec/space_object/parser_spec.rb
120
126
  - spec/space_object_spec.rb
121
127
  - spec/spec_helper.rb