blobject 0.1.5 → 0.1.9

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