data_bindings 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/Gemfile +0 -1
- data/data_bindings.gemspec +2 -2
- data/lib/data_bindings.rb +1 -2
- data/lib/data_bindings/adapters/params.rb +4 -8
- data/lib/data_bindings/generator.rb +14 -4
- data/lib/data_bindings/version.rb +1 -1
- data/lib/ext/hashie.rb +110 -0
- data/test/class_test.rb +25 -0
- metadata +23 -36
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/data_bindings.gemspec
CHANGED
@@ -5,7 +5,7 @@ require "data_bindings/version"
|
|
5
5
|
Gem::Specification.new do |s|
|
6
6
|
s.name = "data_bindings"
|
7
7
|
s.version = DataBindings::VERSION
|
8
|
-
s.authors = ["Joshual Hull"]
|
8
|
+
s.authors = ["Joshual Hull", "Benjamin Coe"]
|
9
9
|
s.email = ["joshbuddy@gmail.com"]
|
10
10
|
s.homepage = "http://github.com/joshbuddy/data_bindings"
|
11
11
|
s.summary = %q{Bind data to and from things}
|
@@ -18,7 +18,7 @@ Gem::Specification.new do |s|
|
|
18
18
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
19
|
s.require_paths = ["lib"]
|
20
20
|
|
21
|
-
s.add_runtime_dependency 'hashie', '= 2.0.0.beta'
|
21
|
+
# s.add_runtime_dependency 'hashie', '= 2.0.0.beta' NOTE: re-add after this is really published
|
22
22
|
|
23
23
|
# specify any dependencies here; for example:
|
24
24
|
s.add_development_dependency 'bson'
|
data/lib/data_bindings.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'hashie'
|
1
|
+
require 'ext/hashie'
|
2
2
|
|
3
3
|
require 'data_bindings/util'
|
4
4
|
require 'data_bindings/generator'
|
@@ -24,7 +24,6 @@ module DataBindings
|
|
24
24
|
class << self
|
25
25
|
# Sends all methods calls to DefaultGenerator
|
26
26
|
def method_missing(m, *args, &blk)
|
27
|
-
DefaultGeneratorInstance.send(:build!)
|
28
27
|
DefaultGeneratorInstance.send(m, *args, &blk)
|
29
28
|
end
|
30
29
|
|
@@ -11,14 +11,10 @@ module DataBindings
|
|
11
11
|
|
12
12
|
|
13
13
|
def parse_nested_query(qs, d = nil)
|
14
|
-
|
15
|
-
|
16
|
-
(qs || '').split(d ? /[#{d}] */n : /[&;] */n).each do |p|
|
14
|
+
(qs || '').split(d ? /[#{d}] */n : /[&;] */n).inject({}) do |params, p|
|
17
15
|
k, v = p.split('=', 2).map { |s| CGI::unescape(s) }
|
18
16
|
normalize_params(params, k, v)
|
19
17
|
end
|
20
|
-
|
21
|
-
return params
|
22
18
|
end
|
23
19
|
|
24
20
|
private
|
@@ -26,9 +22,9 @@ module DataBindings
|
|
26
22
|
name =~ %r(\A[\[\]]*([^\[\]]+)\]*)
|
27
23
|
k = $1 || ''
|
28
24
|
after = $' || ''
|
29
|
-
|
30
|
-
return if k.empty?
|
31
|
-
|
25
|
+
|
26
|
+
return params if k.empty?
|
27
|
+
|
32
28
|
if after == ""
|
33
29
|
params[k] = v
|
34
30
|
elsif after == "[]"
|
@@ -44,7 +44,7 @@ module DataBindings
|
|
44
44
|
# @yield [*Object] All arguments passed to the method used to invoke this reader
|
45
45
|
def reader(name, &blk)
|
46
46
|
@reader_module.define_singleton_method(name, &blk)
|
47
|
-
|
47
|
+
build!
|
48
48
|
end
|
49
49
|
|
50
50
|
# Defines a writer
|
@@ -73,7 +73,7 @@ module DataBindings
|
|
73
73
|
# @param [Object] The adapter
|
74
74
|
def register(name, cls)
|
75
75
|
@adapters[name] = cls
|
76
|
-
|
76
|
+
build!
|
77
77
|
end
|
78
78
|
|
79
79
|
# Resets the generator to a blank state
|
@@ -97,10 +97,21 @@ module DataBindings
|
|
97
97
|
@native_constructors ||= {}
|
98
98
|
end
|
99
99
|
|
100
|
+
def class_for(name, superclass = Object, &blk)
|
101
|
+
cls = Class.new(superclass, &blk)
|
102
|
+
for_native(name) { |props|
|
103
|
+
inst = cls.allocate
|
104
|
+
props.each do |k, v|
|
105
|
+
inst.instance_variable_set(:"@#{k}", v)
|
106
|
+
end
|
107
|
+
inst.send(:initialize)
|
108
|
+
inst
|
109
|
+
}
|
110
|
+
end
|
111
|
+
|
100
112
|
private
|
101
113
|
# @api private
|
102
114
|
def build!
|
103
|
-
return if @built
|
104
115
|
@adapters.each do |name, cls|
|
105
116
|
unless @adapter_classes[name]
|
106
117
|
@adapter_classes[name] = cls.to_s.split('::').inject(Object) {|const, n| const.const_get(n)}
|
@@ -118,7 +129,6 @@ module DataBindings
|
|
118
129
|
end
|
119
130
|
end
|
120
131
|
end
|
121
|
-
@build = true
|
122
132
|
end
|
123
133
|
end
|
124
134
|
|
data/lib/ext/hashie.rb
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
module Hashie
|
2
|
+
module Extensions
|
3
|
+
# IndifferentAccess gives you the ability to not care
|
4
|
+
# whether your hash has string or symbol keys. Made famous
|
5
|
+
# in Rails for accessing query and POST parameters, this
|
6
|
+
# is a handy tool for making sure your hash has maximum
|
7
|
+
# utility.
|
8
|
+
#
|
9
|
+
# One unique feature of this mixin is that it will recursively
|
10
|
+
# inject itself into sub-hash instances without modifying
|
11
|
+
# the actual class of the sub-hash.
|
12
|
+
#
|
13
|
+
# @example
|
14
|
+
# class MyHash < Hash
|
15
|
+
# include Hashie::Extensions::MergeInitializer
|
16
|
+
# include Hashie::Extensions::IndifferentAccess
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# h = MyHash.new(:foo => 'bar', 'baz' => 'blip')
|
20
|
+
# h['foo'] # => 'bar'
|
21
|
+
# h[:foo] # => 'bar'
|
22
|
+
# h[:baz] # => 'blip'
|
23
|
+
# h['baz'] # => 'blip'
|
24
|
+
#
|
25
|
+
module IndifferentAccess
|
26
|
+
def self.included(base)
|
27
|
+
base.class_eval do
|
28
|
+
alias_method :regular_writer, :[]=
|
29
|
+
alias_method :[]=, :indifferent_writer
|
30
|
+
%w(default update fetch delete key? values_at).each do |m|
|
31
|
+
alias_method "regular_#{m}", m
|
32
|
+
alias_method m, "indifferent_#{m}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# This will inject indifferent access into an instance of
|
38
|
+
# a hash without modifying the actual class. This is what
|
39
|
+
# allows IndifferentAccess to spread to sub-hashes.
|
40
|
+
def self.inject!(hash)
|
41
|
+
(class << hash; self; end).send :include, Hashie::Extensions::IndifferentAccess
|
42
|
+
hash.convert!
|
43
|
+
end
|
44
|
+
|
45
|
+
# Injects indifferent access into a duplicate of the hash
|
46
|
+
# provided. See #inject!
|
47
|
+
def self.inject(hash)
|
48
|
+
inject!(hash.dup)
|
49
|
+
end
|
50
|
+
|
51
|
+
def convert_key(key)
|
52
|
+
key.to_s
|
53
|
+
end
|
54
|
+
|
55
|
+
# Iterates through the keys and values, reconverting them to
|
56
|
+
# their proper indifferent state. Used when IndifferentAccess
|
57
|
+
# is injecting itself into member hashes.
|
58
|
+
def convert!
|
59
|
+
keys.each do |k|
|
60
|
+
regular_writer convert_key(k), convert_value(self.regular_delete(k))
|
61
|
+
end
|
62
|
+
self
|
63
|
+
end
|
64
|
+
|
65
|
+
def convert_value(value)
|
66
|
+
if hash_lacking_indifference?(value)
|
67
|
+
Hashie::Extensions::IndifferentAccess.inject(value.dup)
|
68
|
+
elsif value.is_a?(::Array)
|
69
|
+
value.dup.replace(value.map { |e| convert_value(e) })
|
70
|
+
else
|
71
|
+
value
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def indifferent_default(key = nil)
|
76
|
+
return self[convert_key(key)] if key?(key)
|
77
|
+
regular_default(key)
|
78
|
+
end
|
79
|
+
|
80
|
+
def indifferent_update(other_hash)
|
81
|
+
return regular_update(other_hash) if hash_with_indifference?(other_hash)
|
82
|
+
other_hash.each_pair do |k,v|
|
83
|
+
self[k] = v
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def indifferent_writer(key, value); regular_writer convert_key(key), convert_value(value) end
|
88
|
+
def indifferent_fetch(key, *args); regular_fetch convert_key(key), *args end
|
89
|
+
def indifferent_delete(key); regular_delete convert_key(key) end
|
90
|
+
def indifferent_key?(key); regular_key? convert_key(key) end
|
91
|
+
def indifferent_values_at(*indices); indices.map{|i| self[i] } end
|
92
|
+
|
93
|
+
def indifferent_access?; true end
|
94
|
+
|
95
|
+
protected
|
96
|
+
|
97
|
+
def hash_lacking_indifference?(other)
|
98
|
+
other.is_a?(::Hash) &&
|
99
|
+
!(other.respond_to?(:indifferent_access?) &&
|
100
|
+
other.indifferent_access?)
|
101
|
+
end
|
102
|
+
|
103
|
+
def hash_with_indifference?(other)
|
104
|
+
other.is_a?(::Hash) &&
|
105
|
+
other.respond_to?(:indifferent_access?) &&
|
106
|
+
other.indifferent_access?
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
data/test/class_test.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require File.expand_path("../test_helper", __FILE__)
|
2
|
+
|
3
|
+
describe "Data Bindings classes" do
|
4
|
+
before do
|
5
|
+
@generator = DataBindings::DefaultGenerator.new
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "class generation" do
|
9
|
+
it "should create a basic class" do
|
10
|
+
@generator.type(:person) do
|
11
|
+
property :name
|
12
|
+
property :favorite_food
|
13
|
+
end
|
14
|
+
@generator.class_for(:person) do
|
15
|
+
def to_s
|
16
|
+
"#{@name} likes to eat #{@favorite_food}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
josh = @generator.from_ruby('name' => 'josh', 'favorite_food' => 'lasagna').bind(:person).to_native
|
21
|
+
assert_equal "josh likes to eat lasagna", josh.to_s
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
metadata
CHANGED
@@ -1,41 +1,39 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: data_bindings
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 27
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 2
|
10
|
+
version: 0.0.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Joshual Hull
|
14
|
+
- Benjamin Coe
|
14
15
|
autorequire:
|
15
16
|
bindir: bin
|
16
17
|
cert_chain: []
|
17
18
|
|
18
|
-
date: 2012-02-
|
19
|
+
date: 2012-02-02 00:00:00 Z
|
19
20
|
dependencies:
|
20
21
|
- !ruby/object:Gem::Dependency
|
21
|
-
name:
|
22
|
+
name: bson
|
22
23
|
prerelease: false
|
23
24
|
requirement: &id001 !ruby/object:Gem::Requirement
|
24
25
|
none: false
|
25
26
|
requirements:
|
26
|
-
- - "
|
27
|
+
- - ">="
|
27
28
|
- !ruby/object:Gem::Version
|
28
|
-
hash:
|
29
|
+
hash: 3
|
29
30
|
segments:
|
30
|
-
- 2
|
31
31
|
- 0
|
32
|
-
|
33
|
-
|
34
|
-
version: 2.0.0.beta
|
35
|
-
type: :runtime
|
32
|
+
version: "0"
|
33
|
+
type: :development
|
36
34
|
version_requirements: *id001
|
37
35
|
- !ruby/object:Gem::Dependency
|
38
|
-
name:
|
36
|
+
name: multi_json
|
39
37
|
prerelease: false
|
40
38
|
requirement: &id002 !ruby/object:Gem::Requirement
|
41
39
|
none: false
|
@@ -49,7 +47,7 @@ dependencies:
|
|
49
47
|
type: :development
|
50
48
|
version_requirements: *id002
|
51
49
|
- !ruby/object:Gem::Dependency
|
52
|
-
name:
|
50
|
+
name: nokogiri
|
53
51
|
prerelease: false
|
54
52
|
requirement: &id003 !ruby/object:Gem::Requirement
|
55
53
|
none: false
|
@@ -63,7 +61,7 @@ dependencies:
|
|
63
61
|
type: :development
|
64
62
|
version_requirements: *id003
|
65
63
|
- !ruby/object:Gem::Dependency
|
66
|
-
name:
|
64
|
+
name: builder
|
67
65
|
prerelease: false
|
68
66
|
requirement: &id004 !ruby/object:Gem::Requirement
|
69
67
|
none: false
|
@@ -77,7 +75,7 @@ dependencies:
|
|
77
75
|
type: :development
|
78
76
|
version_requirements: *id004
|
79
77
|
- !ruby/object:Gem::Dependency
|
80
|
-
name:
|
78
|
+
name: httparty
|
81
79
|
prerelease: false
|
82
80
|
requirement: &id005 !ruby/object:Gem::Requirement
|
83
81
|
none: false
|
@@ -91,7 +89,7 @@ dependencies:
|
|
91
89
|
type: :development
|
92
90
|
version_requirements: *id005
|
93
91
|
- !ruby/object:Gem::Dependency
|
94
|
-
name:
|
92
|
+
name: minitest
|
95
93
|
prerelease: false
|
96
94
|
requirement: &id006 !ruby/object:Gem::Requirement
|
97
95
|
none: false
|
@@ -105,7 +103,7 @@ dependencies:
|
|
105
103
|
type: :development
|
106
104
|
version_requirements: *id006
|
107
105
|
- !ruby/object:Gem::Dependency
|
108
|
-
name:
|
106
|
+
name: rake
|
109
107
|
prerelease: false
|
110
108
|
requirement: &id007 !ruby/object:Gem::Requirement
|
111
109
|
none: false
|
@@ -119,7 +117,7 @@ dependencies:
|
|
119
117
|
type: :development
|
120
118
|
version_requirements: *id007
|
121
119
|
- !ruby/object:Gem::Dependency
|
122
|
-
name:
|
120
|
+
name: fakeweb
|
123
121
|
prerelease: false
|
124
122
|
requirement: &id008 !ruby/object:Gem::Requirement
|
125
123
|
none: false
|
@@ -133,7 +131,7 @@ dependencies:
|
|
133
131
|
type: :development
|
134
132
|
version_requirements: *id008
|
135
133
|
- !ruby/object:Gem::Dependency
|
136
|
-
name:
|
134
|
+
name: yard
|
137
135
|
prerelease: false
|
138
136
|
requirement: &id009 !ruby/object:Gem::Requirement
|
139
137
|
none: false
|
@@ -147,7 +145,7 @@ dependencies:
|
|
147
145
|
type: :development
|
148
146
|
version_requirements: *id009
|
149
147
|
- !ruby/object:Gem::Dependency
|
150
|
-
name:
|
148
|
+
name: redcarpet
|
151
149
|
prerelease: false
|
152
150
|
requirement: &id010 !ruby/object:Gem::Requirement
|
153
151
|
none: false
|
@@ -161,7 +159,7 @@ dependencies:
|
|
161
159
|
type: :development
|
162
160
|
version_requirements: *id010
|
163
161
|
- !ruby/object:Gem::Dependency
|
164
|
-
name:
|
162
|
+
name: tnetstring
|
165
163
|
prerelease: false
|
166
164
|
requirement: &id011 !ruby/object:Gem::Requirement
|
167
165
|
none: false
|
@@ -174,20 +172,6 @@ dependencies:
|
|
174
172
|
version: "0"
|
175
173
|
type: :development
|
176
174
|
version_requirements: *id011
|
177
|
-
- !ruby/object:Gem::Dependency
|
178
|
-
name: tnetstring
|
179
|
-
prerelease: false
|
180
|
-
requirement: &id012 !ruby/object:Gem::Requirement
|
181
|
-
none: false
|
182
|
-
requirements:
|
183
|
-
- - ">="
|
184
|
-
- !ruby/object:Gem::Version
|
185
|
-
hash: 3
|
186
|
-
segments:
|
187
|
-
- 0
|
188
|
-
version: "0"
|
189
|
-
type: :development
|
190
|
-
version_requirements: *id012
|
191
175
|
description: Bind data to and from things.
|
192
176
|
email:
|
193
177
|
- joshbuddy@gmail.com
|
@@ -219,8 +203,10 @@ files:
|
|
219
203
|
- lib/data_bindings/unbound.rb
|
220
204
|
- lib/data_bindings/util.rb
|
221
205
|
- lib/data_bindings/version.rb
|
206
|
+
- lib/ext/hashie.rb
|
222
207
|
- test/array_test.rb
|
223
208
|
- test/bson_test.rb
|
209
|
+
- test/class_test.rb
|
224
210
|
- test/converter_test.rb
|
225
211
|
- test/data_bindings_test.rb
|
226
212
|
- test/fixtures/1.json
|
@@ -268,6 +254,7 @@ summary: Bind data to and from things
|
|
268
254
|
test_files:
|
269
255
|
- test/array_test.rb
|
270
256
|
- test/bson_test.rb
|
257
|
+
- test/class_test.rb
|
271
258
|
- test/converter_test.rb
|
272
259
|
- test/data_bindings_test.rb
|
273
260
|
- test/fixtures/1.json
|