blobject 0.1.5 → 0.1.9

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.
data/.pryrc ADDED
@@ -0,0 +1,7 @@
1
+ $:.push File.expand_path('../lib', __FILE__)
2
+ require 'ruby-debug'
3
+ require 'blobject'
4
+
5
+ def reload!
6
+ load 'blobject.rb'
7
+ end
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format documentation
@@ -0,0 +1,20 @@
1
+
2
+ EXAMPLES
3
+ > to/from yaml
4
+ > with controller params
5
+ > JSON response
6
+ > DSL
7
+ > Config
8
+ >>> can make config maintainable by translating it
9
+
10
+
11
+ > benefits: configuration ease
12
+ > using hashes with config/json and active record because of key symbolization
13
+
14
+
15
+
16
+ EXTRAS:
17
+
18
+ > load_config, monitor for changes
19
+
20
+ automatically handle json request params into blobjects
@@ -14,9 +14,10 @@ Gem::Specification.new do |s|
14
14
 
15
15
  s.rubyforge_project = "blobject"
16
16
 
17
- s.add_dependency 'wirble'
18
- s.add_dependency 'shoulda'
19
-
17
+
18
+ s.add_development_dependency 'rspec'
19
+ s.add_development_dependency 'ruby-debug19'
20
+
20
21
  s.files = `git ls-files`.split("\n")
21
22
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
22
23
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
@@ -1,175 +1,169 @@
1
- Dir["#{File.dirname __FILE__}/blobject/*.rb"].each {|file| require "#{file}" }
1
+ require 'blobject/version'
2
2
 
3
3
  def blobject *parameters, &block
4
4
  Blobject.new *parameters, &block
5
- end
5
+ end
6
6
 
7
- # similar to OpenStruct
8
- # b.foo.bar = 8 automatically creates a blobject called "foo" on "b"
9
- # to check whether a variable is defined use the '?' syntax i.e: b.is_it_here? => nil, b.foo? == b.foo
10
- # calling an unassigned member returns a new blobject unless the blobject is frozen
11
- # a frozen blobject cannot be assigned new members or populated from a hash
12
- # does no cycle checking, intended for use in serialization
13
7
  class Blobject
14
- class AssignToFrozenBlobjectException < Exception; end
15
8
 
16
- public
17
-
18
- def frozen?
19
- @blobject_frozen == true
9
+ def initialize hash = {}, &block
10
+ @hash = {}
11
+ merge hash
12
+
13
+ @modifying = false
14
+ self.modify &block if block_given?
20
15
  end
21
16
 
22
- def freeze
23
- @blobject_frozen = true
24
- self
25
- end
26
- def unfreeze
27
- @blobject_frozen = false
28
- self
29
- end
30
- def defrost
31
- unfreeze
32
- end
33
-
34
- def initialize hash_of_initial_values_or_an_object={}, array_of_methods_to_copy_data_from_object=[]
35
- @values = {}
36
-
37
- if (hash_of_initial_values_or_an_object.class == Hash)
38
- merge_hash hash_of_initial_values_or_an_object
39
- else
40
- array_of_methods_to_copy_data_from_object.each do |accessor|
41
- @values[accessor.to_s] = hash_of_initial_values_or_an_object.send accessor
42
- end
43
- end
44
-
45
- if block_given?
46
- yield self
47
- end
48
- self
49
- end
50
-
51
- def method_missing(sym, *args, &block)
52
- # fixes for ruby 1.9.2, otherwise blobjects can't be used in arrays that may have the flatten method called
53
- super if [:to_ary].include? sym
17
+ def modify &block
54
18
 
55
- str = sym.to_s
19
+ __r_modify_set__ true
56
20
 
57
- assignment = /.*(?=\=$)/.match str
58
- question = /.*(?=\?$)/.match str
21
+ exception = nil
59
22
 
60
- if question
61
- !@values[question.to_s].nil?
62
- elsif assignment
63
- raise AssignToFrozenBlobjectException if @blobject_frozen
64
- @values[assignment.to_s] = args[0]
65
- else
66
- #return the value or a new blobject
67
- value = @values[str]
23
+ begin
24
+ self.instance_eval &block
25
+ rescue Exception => e
26
+ exception = e
27
+ end
28
+
29
+ __r_modify_set__ false
30
+
31
+ raise exception unless exception.nil?
32
+ return self
33
+ end
34
+
35
+ def method_missing sym, *params, &block
36
+
37
+ if match = /^has_(?<name>.+)\?/.match(sym)
38
+ return @hash.has_key? match[:name].to_sym
39
+ end
40
+
41
+ modify_getter = -> { params.length == 0 && @modifying }
42
+ modify_assign = -> { params.length == 1 && @modifying }
43
+
44
+ if @modifying
68
45
 
69
- return value unless value.nil?
70
- return nil if frozen?
71
- @values[str] = Blobject.new
72
- return @values[str]
46
+ case params.length
47
+ when 0 # get
48
+ return @hash[sym] if @hash.has_key? sym
49
+
50
+ child = Blobject.new
51
+ parent = self
52
+
53
+ child.__r_modify_set__ true
54
+
55
+ store_in_parent = lambda {
56
+
57
+ parent_hash = parent.instance_variable_get '@hash'
58
+ parent_hash[sym] = child
59
+
60
+ parent_store_in_parent = parent.instance_variable_get :@__store_in_parent__
61
+ parent_store_in_parent.call unless parent_store_in_parent.nil?
62
+
63
+ child.method(:remove_instance_variable).call(:@__store_in_parent__)
64
+ }
65
+
66
+ child.instance_variable_set :@__store_in_parent__, store_in_parent
67
+
68
+ return block_given? ? child.modify(&block) : child
69
+ when 1 # set
70
+ @hash[sym] = params[0]
71
+
72
+ store_in_parent = @__store_in_parent__
73
+ store_in_parent.call unless store_in_parent.nil?
74
+
75
+ return self
76
+ end
77
+ else
78
+ return @hash[sym] if @hash.has_key? sym
73
79
  end
80
+
81
+ super
74
82
  end
75
83
 
76
- def merge_hash hash
77
- raise "cannot populate a frozen blobject" if @blobject_frozen
84
+ def merge hash
78
85
 
79
86
  hash.each do |key, value|
80
-
81
- if value.class==Hash
82
- value = Blobject.new value
83
- end
84
-
85
- if value.class==Array
86
- value = Blobject.blobjectify_array value
87
- end
88
-
89
- @values[key.to_s] = value
87
+ @hash[key.to_s.to_sym] = self.class.__blobjectify__ value
90
88
  end
89
+
91
90
  self
92
- end
91
+ end
92
+
93
+ def empty?
94
+ @hash.empty?
95
+ end
96
+
97
+ def [] key
98
+ @hash[key]
99
+ end
100
+
101
+ def []= key, value
102
+ send key, value
103
+ end
93
104
 
94
105
  def to_hash
95
- h = {}
96
- @values.each do |key, value|
97
- if value.class==Blobject
98
- h[key] = value.to_hash
99
- elsif value.class==Array
100
- h[key] = Blobject.deblobjectify_array value
101
- else
102
- h[key] = value
103
- end
104
- end
105
- h
106
+ Marshal.load(Marshal.dump(@hash))
106
107
  end
107
108
 
108
- #builds a hash for json conversion
109
- def as_json *ps
110
- to_hash
109
+ def from_hash hash
110
+ Blobject.new hash
111
111
  end
112
112
 
113
- def self.from_json json, freeze=true
114
- h = ActiveSupport::JSON.decode(json)
115
- if h.class==Hash
116
- b = Blobject.new h
117
- b.freeze if freeze
118
- return b
119
- elsif h.class==Array
120
- return blobjectify_array h
121
- else
122
- return h
123
- end
124
- end
125
-
126
- def self.blobjectify_array array
127
- array.map do |e|
128
- if e.class==Hash
129
- Blobject.new(e)
130
- elsif e.class==Array
131
- blobjectify_array(e)
132
- else
133
- e
134
- end
135
- end
113
+ def to_yaml *params
114
+ @hash.to_yaml *params
136
115
  end
137
116
 
138
- def self.deblobjectify_array array
139
- array.map do |e|
140
- if e.class==Blobject
141
- e.to_hash
142
- elsif e.class==Array
143
- deblobjectify_array(e)
144
- else
145
- e
146
- end
147
- end
117
+ def self.from_yaml yaml
118
+ __blobjectify__ YAML.load(yaml)
148
119
  end
149
120
 
150
- def [] key
151
- @values[key]
121
+ def to_json *params
122
+ @hash.to_json *params
152
123
  end
153
124
 
154
- def []= key, value
155
- @values[key] = value
125
+ def self.from_json json
126
+ __blobjectify__ JSON.load(json)
156
127
  end
157
128
 
158
- def blank?
159
- empty?
129
+ def dup
130
+ Blobject.new to_hash
160
131
  end
161
132
 
162
- def empty?
163
- @values.empty? || @values.values.empty? || !@values.values.any? do |v|
164
- #if the value is a Blobject, Hash or Array return
165
- #true if it is not empty.
166
- #else just return true, the value is regarded as not empty.
167
- if [Blobject, Array, Hash].include?(v.class)
168
- !v.empty?
169
- else
170
- true
133
+ def inspect
134
+ @hash.inspect
135
+ end
136
+
137
+
138
+
139
+ protected
140
+
141
+ def self.__blobjectify__ obj
142
+
143
+ if obj.instance_of?(Hash)
144
+
145
+ obj.each do |key, value|
146
+ obj[key] = __blobjectify__ value
147
+ end
148
+
149
+ return self.new obj
150
+ end
151
+
152
+ if obj.instance_of?(Array)
153
+ return obj.map do |e|
154
+ __blobjectify__ e
155
+ end
156
+ end
157
+
158
+ obj
159
+ end
160
+
161
+ def __r_modify_set__ modifying
162
+ @modifying = modifying
163
+ @hash.values.each do |child|
164
+ if child.class <= Blobject
165
+ child.__r_modify_set__ modifying
171
166
  end
172
167
  end
173
168
  end
174
-
175
- end
169
+ end
@@ -1,3 +1,3 @@
1
1
  class Blobject
2
- VERSION = "0.1.5"
3
- end
2
+ VERSION = '0.1.9'
3
+ end
@@ -0,0 +1,150 @@
1
+ require 'spec_helper'
2
+ require 'blobject'
3
+
4
+ describe Blobject do
5
+
6
+ let(:blobject){Blobject.new}
7
+
8
+ it 'should not be able to assign to a blobject outside of a modify block using =' do
9
+ expect {
10
+ blobject.name = 'hello'
11
+
12
+ }.to raise_error
13
+ end
14
+
15
+ it 'should not be able to assign to a blobject outside of a modify block without =' do
16
+ expect {
17
+ blobject.name 'hello'
18
+ }.to raise_error
19
+ end
20
+
21
+ it 'should raise an error when call members that have not been assign' do
22
+
23
+ expect {
24
+ blobject.meow
25
+ }.to raise_error(NoMethodError)
26
+ end
27
+
28
+ describe '#empty?' do
29
+ it 'should return true on an empty blobject' do
30
+ blobject.should be_empty
31
+ end
32
+
33
+ it 'should return false on an non-empty blobject' do
34
+ blobject.modify { name "Barry" }
35
+ blobject.should_not be_empty
36
+ end
37
+ end
38
+
39
+ describe '#modify' do
40
+
41
+ it 'should store assignment of variables to any depth in the object graph' do
42
+
43
+ b = blobject.modify do
44
+ variable 'hello'
45
+ deep.object.graph.member 123
46
+ end
47
+
48
+ blobject.variable.should == 'hello'
49
+ blobject.deep.object.graph.member.should == 123
50
+ end
51
+
52
+ it 'should not handle more than one parameter' do
53
+ expect {
54
+ blobject.modify do
55
+ name(1, 2)
56
+ end
57
+ }.to raise_error(NoMethodError)
58
+ end
59
+
60
+ it 'should return an empty blobject when a non-existing member is called' do
61
+ blobject.modify do
62
+ b = name
63
+ name.should be_instance_of Blobject
64
+ name.should be_empty
65
+ end
66
+ end
67
+
68
+ it 'should allow assignment chaining' do
69
+ blobject.modify do
70
+ name.first('Barry').last('Watkins')
71
+ end
72
+
73
+ blobject.name.first.should == 'Barry'
74
+ blobject.name.last.should == 'Watkins'
75
+ end
76
+
77
+ it 'should return self' do
78
+ rtn = blobject.modify {}
79
+ rtn.should equal blobject
80
+ end
81
+
82
+ it 'should allow for nested modification blocks' do
83
+
84
+ blobject.modify do
85
+ name do
86
+ first 'barry'
87
+ last 'mcdoodle'
88
+ end
89
+ end
90
+
91
+ blobject.name.first.should == 'barry'
92
+ blobject.name.last.should == 'mcdoodle'
93
+
94
+ end
95
+ end
96
+
97
+ describe '#has_<name>' do
98
+
99
+ it 'should return true when we have a member of name' do
100
+ blobject.modify {name 'barry'}
101
+ blobject.should have_name
102
+ end
103
+
104
+ it 'should return false otherwise' do
105
+ blobject.should_not have_name
106
+ end
107
+ end
108
+
109
+ describe '#[]' do
110
+ it 'allows get via hash like dereferencing' do
111
+ blobject.modify {name 'rod'}
112
+ blobject[:name].should == 'rod'
113
+ end
114
+
115
+ it 'nil should be returned for a key miss' do
116
+ blobject[:name].should == nil
117
+ end
118
+ end
119
+
120
+ describe '#[]=' do
121
+ it 'should relay to send' do
122
+ blobject.should_receive(:send).with(:name, 'barry')
123
+ blobject[:name] = 'barry'
124
+ end
125
+ end
126
+
127
+ describe '#merge' do
128
+ let(:data) do
129
+ { :one => 1,
130
+ :rest => [2,3,4,5,6,{:number => 7},8,9,0],
131
+ :nested => {
132
+ :structure => 'of values'
133
+ } }
134
+ end
135
+
136
+ it 'should return self' do
137
+ blobject.merge({}).should equal blobject
138
+ end
139
+
140
+ it 'should populate itself with the hash' do
141
+ blobject.merge data
142
+
143
+ blobject.one.should == 1
144
+ blobject.rest[5].should be_instance_of(Blobject)
145
+ blobject.rest[5].number.should == 7
146
+ blobject.nested.structure.should == 'of values'
147
+ end
148
+ end
149
+
150
+ end
@@ -0,0 +1,12 @@
1
+ $:.push File.expand_path('../lib', __FILE__)
2
+
3
+ require 'rspec'
4
+ require 'ruby-debug'
5
+
6
+ RSpec.configure do |config|
7
+
8
+ end
9
+
10
+ module SpecHelper
11
+
12
+ end
data/test.rb ADDED
@@ -0,0 +1,6 @@
1
+ class Myobject < Blobject
2
+ allow :name
3
+
4
+
5
+ end
6
+
metadata CHANGED
@@ -1,89 +1,84 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: blobject
3
- version: !ruby/object:Gem::Version
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.9
4
5
  prerelease:
5
- version: 0.1.5
6
6
  platform: ruby
7
- authors:
7
+ authors:
8
8
  - Sam Taylor
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
-
13
- date: 2011-04-14 00:00:00 +01:00
14
- default_executable:
15
- dependencies:
16
- - !ruby/object:Gem::Dependency
17
- name: wirble
18
- prerelease: false
19
- requirement: &id001 !ruby/object:Gem::Requirement
12
+ date: 2011-09-30 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: &2156185800 !ruby/object:Gem::Requirement
20
17
  none: false
21
- requirements:
22
- - - ">="
23
- - !ruby/object:Gem::Version
24
- version: "0"
25
- type: :runtime
26
- version_requirements: *id001
27
- - !ruby/object:Gem::Dependency
28
- name: shoulda
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
29
23
  prerelease: false
30
- requirement: &id002 !ruby/object:Gem::Requirement
24
+ version_requirements: *2156185800
25
+ - !ruby/object:Gem::Dependency
26
+ name: ruby-debug19
27
+ requirement: &2156182880 !ruby/object:Gem::Requirement
31
28
  none: false
32
- requirements:
33
- - - ">="
34
- - !ruby/object:Gem::Version
35
- version: "0"
36
- type: :runtime
37
- version_requirements: *id002
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *2156182880
38
36
  description: Blobject provides a free flowing syntax for creating blobs of data.
39
- email:
37
+ email:
40
38
  - sjltaylor@gmail.com
41
39
  executables: []
42
-
43
40
  extensions: []
44
-
45
41
  extra_rdoc_files: []
46
-
47
- files:
42
+ files:
48
43
  - .gitignore
44
+ - .pryrc
45
+ - .rspec
49
46
  - Gemfile
50
47
  - README.markdown
51
48
  - Rakefile
49
+ - TODO.txt
52
50
  - blobject.gemspec
53
51
  - blobject.png
54
52
  - blobject.psd
55
53
  - lib/blobject.rb
56
54
  - lib/blobject/version.rb
57
- - test/helper.rb
58
- - test/test_blobject.rb
59
- has_rdoc: true
55
+ - spec/blobject_spec.rb
56
+ - spec/spec_helper.rb
57
+ - test.rb
60
58
  homepage: https://github.com/sjltaylor/blobject
61
59
  licenses: []
62
-
63
60
  post_install_message:
64
61
  rdoc_options: []
65
-
66
- require_paths:
62
+ require_paths:
67
63
  - lib
68
- required_ruby_version: !ruby/object:Gem::Requirement
64
+ required_ruby_version: !ruby/object:Gem::Requirement
69
65
  none: false
70
- requirements:
71
- - - ">="
72
- - !ruby/object:Gem::Version
73
- version: "0"
74
- required_rubygems_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ required_rubygems_version: !ruby/object:Gem::Requirement
75
71
  none: false
76
- requirements:
77
- - - ">="
78
- - !ruby/object:Gem::Version
79
- version: "0"
72
+ requirements:
73
+ - - ! '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
80
76
  requirements: []
81
-
82
77
  rubyforge_project: blobject
83
- rubygems_version: 1.5.0
78
+ rubygems_version: 1.8.10
84
79
  signing_key:
85
80
  specification_version: 3
86
81
  summary: serializable object builder
87
- test_files:
88
- - test/helper.rb
89
- - test/test_blobject.rb
82
+ test_files:
83
+ - spec/blobject_spec.rb
84
+ - spec/spec_helper.rb
@@ -1,19 +0,0 @@
1
- require 'rubygems'
2
- require 'bundler'
3
-
4
- begin
5
- Bundler.setup(:default, :development)
6
- rescue Bundler::BundlerError => e
7
- $stderr.puts e.message
8
- $stderr.puts "Run `bundle install` to install missing gems"
9
- exit e.status_code
10
- end
11
- require 'test/unit'
12
- require 'shoulda'
13
-
14
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
15
- $LOAD_PATH.unshift(File.dirname(__FILE__))
16
- require 'blobject'
17
-
18
- class Test::Unit::TestCase
19
- end
@@ -1,45 +0,0 @@
1
- require 'helper'
2
-
3
- class TestBlobject < Test::Unit::TestCase
4
- should "not be empty? if the blobject has data" do
5
- b = Blobject.new
6
- b.data = 'LOOK! some data. :)'
7
- assert !b.empty?
8
- end
9
-
10
- should "not be empty if the blobject complex with real data" do
11
- b = Blobject.new
12
- b.colors.red = '#ff0000'
13
- assert !b.empty?
14
- end
15
-
16
- should 'report empty when there are no descendants' do
17
- assert Blobject.new.empty?
18
- end
19
-
20
- should 'report empty? as true when descendants are empty Hash, Array or Blobjects' do
21
- b = Blobject.new
22
- b.array = []
23
- b.hash = {}
24
- b.blobject = Blobject.new
25
- assert b.empty?
26
- end
27
-
28
- should 'report empty? as false when descendants include a non-empty Array' do
29
- b = Blobject.new
30
- b.array = [1,2,3,4,5]
31
- assert !b.empty?
32
- end
33
-
34
- should 'report empty? as false when descendants include a non-empty Hash' do
35
- b = Blobject.new
36
- b.hash = {:key1 => 1, :key2 =>2, :key3 => 3}
37
- assert !b.empty?
38
- end
39
-
40
- should 'report empty? as false when descendants include a non-empty Blobject' do
41
- b = Blobject.new
42
- b.blobject = Blobject.new :initial_data => [1,2,3]
43
- assert !b.empty?
44
- end
45
- end