hash_builder 0.1.0
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 +7 -0
- data/.gitignore +5 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +47 -0
- data/LICENSE.txt +22 -0
- data/README.md +203 -0
- data/Rakefile +1 -0
- data/benchmark.rb +57 -0
- data/hash_builder.gemspec +27 -0
- data/lib/hash_builder/template.rb +39 -0
- data/lib/hash_builder/version.rb +3 -0
- data/lib/hash_builder.rb +51 -0
- data/spec/hash_builder/template_spec.rb +29 -0
- data/spec/hash_builder_spec.rb +64 -0
- data/spec/spec_helper.rb +1 -0
- metadata +132 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 9d558232e333db81f54b2908babff87135a04524
|
4
|
+
data.tar.gz: 9a7ab805dfed411cd2692581801583b55e2c4589
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 855bc8140cfd594a54e0f9ac6bfcf601c5fc108e0821f2f0cb8d55285d078718e1de2235996037b8c2e04a66a156021edd7106ea93e6355020362929516a8791
|
7
|
+
data.tar.gz: 261c27848fa2040eddde40c2beec7346c56ab35aee6d2bb0a4645f31c13f2c62d43817bcd6e0a78efe78db832f54b92f6fb49072f367b67ddd5d6db9a4b19267
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
hash_builder (0.1.0)
|
5
|
+
exec_env
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: https://rubygems.org/
|
9
|
+
specs:
|
10
|
+
activesupport (4.0.1)
|
11
|
+
i18n (~> 0.6, >= 0.6.4)
|
12
|
+
minitest (~> 4.2)
|
13
|
+
multi_json (~> 1.3)
|
14
|
+
thread_safe (~> 0.1)
|
15
|
+
tzinfo (~> 0.3.37)
|
16
|
+
atomic (1.1.14)
|
17
|
+
diff-lcs (1.2.4)
|
18
|
+
exec_env (0.1.0)
|
19
|
+
i18n (0.6.5)
|
20
|
+
json (1.8.1)
|
21
|
+
json_builder (3.1.7)
|
22
|
+
activesupport (>= 2.0.0)
|
23
|
+
json
|
24
|
+
minitest (4.7.5)
|
25
|
+
multi_json (1.8.2)
|
26
|
+
rake (10.1.0)
|
27
|
+
rspec (2.14.1)
|
28
|
+
rspec-core (~> 2.14.0)
|
29
|
+
rspec-expectations (~> 2.14.0)
|
30
|
+
rspec-mocks (~> 2.14.0)
|
31
|
+
rspec-core (2.14.4)
|
32
|
+
rspec-expectations (2.14.0)
|
33
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
34
|
+
rspec-mocks (2.14.1)
|
35
|
+
thread_safe (0.1.3)
|
36
|
+
atomic
|
37
|
+
tzinfo (0.3.38)
|
38
|
+
|
39
|
+
PLATFORMS
|
40
|
+
ruby
|
41
|
+
|
42
|
+
DEPENDENCIES
|
43
|
+
bundler (~> 1.4)
|
44
|
+
hash_builder!
|
45
|
+
json_builder
|
46
|
+
rake (~> 10.1)
|
47
|
+
rspec
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Marten Lienen
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,203 @@
|
|
1
|
+
# HashBuilder
|
2
|
+
|
3
|
+
This gem allows you to build hashes in a way, that is totally copied from
|
4
|
+
[json_builder](https://github.com/dewski/json_builder). I created this,
|
5
|
+
because json_builder does not allow extraction of partials, which I rely
|
6
|
+
heavily on, to keep my JSON generation DRY.
|
7
|
+
And while I was at it, I found it a good idea to increase the abstraction
|
8
|
+
level and build hashes instead of JSON because, this allows for easier
|
9
|
+
manipulation of the results, application in more different circumstances
|
10
|
+
and you can generate JSON and YAML with the well known `to_json` and
|
11
|
+
`to_yaml` methods from it.
|
12
|
+
|
13
|
+
## Installation
|
14
|
+
|
15
|
+
Add this line to your application's Gemfile:
|
16
|
+
|
17
|
+
gem 'hash_builder'
|
18
|
+
|
19
|
+
And then execute:
|
20
|
+
|
21
|
+
$ bundle
|
22
|
+
|
23
|
+
Or install it yourself as:
|
24
|
+
|
25
|
+
$ gem install hash_builder
|
26
|
+
|
27
|
+
## Usage
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
require "hash_builder"
|
31
|
+
require "json"
|
32
|
+
require "yaml"
|
33
|
+
|
34
|
+
hash = HashBuilder.build do
|
35
|
+
url "https://github.com/CQQL"
|
36
|
+
name "CQQL"
|
37
|
+
age 21
|
38
|
+
|
39
|
+
interests [:ruby, :clojure] do |n|
|
40
|
+
name n
|
41
|
+
end
|
42
|
+
|
43
|
+
loves do
|
44
|
+
example do
|
45
|
+
code :yes
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
#=> {:url=>"https://github.com/CQQL", :name=>"CQQL", :age=>21, :interests=>[{:name=>:ruby}, {:name=>:clojure}], :loves=>{:example=>{:code=>:yes}}}
|
50
|
+
|
51
|
+
hash.to_json
|
52
|
+
#=> "{\"url\":\"https://github.com/CQQL\",\"name\":\"CQQL\",\"age\":21,\"interests\":[{\"name\":\"ruby\"},{\"name\":\"clojure\"}],\"loves\":{\"example\":{\"code\":\"yes\"}}}"
|
53
|
+
|
54
|
+
hash.to_yaml
|
55
|
+
#=> "---\n:url: https://github.com/CQQL\n:name: CQQL\n:age: 21\n:interests:\n- :name: :ruby\n- :name: :clojure\n:loves:\n :example:\n :code: :yes\n"
|
56
|
+
```
|
57
|
+
|
58
|
+
## Usage with rails
|
59
|
+
|
60
|
+
To use HashBuilder in a rails app, add the gem to your Gemfile.
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
gem "hash_builder"
|
64
|
+
```
|
65
|
+
|
66
|
+
From then on HashBuilder will render `.json_builder` templates as
|
67
|
+
JSON. But there is a special case in that HashBuilder actually renders
|
68
|
+
partials as hashes instead of JSON strings so that you can use them to
|
69
|
+
create nested data structures instead of strings to use in templates.
|
70
|
+
|
71
|
+
```ruby
|
72
|
+
class HashController < ApplicationController
|
73
|
+
def index
|
74
|
+
@users = [
|
75
|
+
{ name: "CQQL", quote: "Emacs > Vim" },
|
76
|
+
{ name: "Joshua Bloch", quote: "The cleaner and nicer the program, the faster it's going to run. And if it doesn't, it'll be easy to make it fast." }
|
77
|
+
]
|
78
|
+
end
|
79
|
+
end
|
80
|
+
```
|
81
|
+
|
82
|
+
```ruby
|
83
|
+
# hash/index.json_builder
|
84
|
+
num_users @users.size
|
85
|
+
|
86
|
+
users @users.map { |u| render partial: "user", locals: { user: u } }
|
87
|
+
```
|
88
|
+
|
89
|
+
```ruby
|
90
|
+
# hash/_user.json_builder
|
91
|
+
name user[:name]
|
92
|
+
name_length user[:name].size
|
93
|
+
quote user[:quote]
|
94
|
+
```
|
95
|
+
|
96
|
+
A request to `/hash/` returns the following JSON response
|
97
|
+
|
98
|
+
```json
|
99
|
+
{
|
100
|
+
"num_users": 2,
|
101
|
+
"users": [
|
102
|
+
{
|
103
|
+
"name": "CQQL",
|
104
|
+
"name_length": 4,
|
105
|
+
"quote": "Emacs > Vim"
|
106
|
+
},
|
107
|
+
{
|
108
|
+
"name": "Joshua Bloch",
|
109
|
+
"name_length": 12,
|
110
|
+
"quote": "The cleaner and nicer the program, the faster it's going to run. And if it doesn't, it'll be easy to make it fast."
|
111
|
+
}
|
112
|
+
]
|
113
|
+
}
|
114
|
+
```
|
115
|
+
|
116
|
+
## Performance
|
117
|
+
|
118
|
+
There is a [benchmark script](./benchmark.rb), that returns the
|
119
|
+
following results on my machine
|
120
|
+
|
121
|
+
```
|
122
|
+
$ ruby benchmark.rb
|
123
|
+
user system total real
|
124
|
+
HashBuilder 0.650000 0.070000 0.720000 ( 0.714533)
|
125
|
+
HashBuilder + JSON.generate 1.290000 0.060000 1.350000 ( 1.352620)
|
126
|
+
HashBuilder + to_json 4.650000 0.070000 4.720000 ( 4.716388)
|
127
|
+
JSONBuilder 1.780000 0.090000 1.870000 ( 1.872545)
|
128
|
+
```
|
129
|
+
|
130
|
+
For some reason transforming hashes to JSON with `to_json` is really slow.
|
131
|
+
|
132
|
+
## Tradeoffs
|
133
|
+
|
134
|
+
This is built with [exec_env](https://github.com/CQQL/exec_env), so
|
135
|
+
there is quite a lot of ruby magic going on under the hood. As long as
|
136
|
+
you only use lexical bingings in your block, you won't notice
|
137
|
+
anything.
|
138
|
+
|
139
|
+
```ruby
|
140
|
+
def render_user (user)
|
141
|
+
HashBuilder.build do
|
142
|
+
name user.name
|
143
|
+
end
|
144
|
+
end
|
145
|
+
```
|
146
|
+
|
147
|
+
But your dynamic bindings will be lost, because the block is executed
|
148
|
+
in another context.
|
149
|
+
|
150
|
+
```ruby
|
151
|
+
class User
|
152
|
+
attr_accessor :email
|
153
|
+
|
154
|
+
def to_hash
|
155
|
+
HashBuilder.build do
|
156
|
+
# email accessor is not available here.
|
157
|
+
email_address email # => Error
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
```
|
162
|
+
|
163
|
+
This can be fixed however by explicitly passing a scop.e
|
164
|
+
|
165
|
+
```ruby
|
166
|
+
class User
|
167
|
+
attr_accessor :email
|
168
|
+
|
169
|
+
def to_hash
|
170
|
+
HashBuilder.build(scope: self) do
|
171
|
+
# All is fine now.
|
172
|
+
email_address email
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
```
|
177
|
+
|
178
|
+
But there is yet another problem. If you tried to set the hash key
|
179
|
+
`email`, you would receive an error because the line `email email`
|
180
|
+
would actually expand to `user.email(user.email)` if `user` is the
|
181
|
+
user object, because `user` responds to `email`. The quite ugly
|
182
|
+
workaround looks like this
|
183
|
+
|
184
|
+
```ruby
|
185
|
+
class User
|
186
|
+
attr_accessor :email
|
187
|
+
|
188
|
+
def to_hash
|
189
|
+
HashBuilder.build(scope: self) do
|
190
|
+
# Bypass scope and local variables
|
191
|
+
xsend :email, email
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
```
|
196
|
+
|
197
|
+
## Contributing
|
198
|
+
|
199
|
+
1. Fork it
|
200
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
201
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
202
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
203
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/benchmark.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
require "benchmark"
|
2
|
+
require "json"
|
3
|
+
require "hash_builder"
|
4
|
+
require "json_builder"
|
5
|
+
|
6
|
+
template = (-> {
|
7
|
+
name "Garrett Bjerkhoel"
|
8
|
+
birthday Time.local(1991, 9, 14)
|
9
|
+
|
10
|
+
street do
|
11
|
+
address "1143 1st Ave"
|
12
|
+
address2 "Apt 200"
|
13
|
+
city "New York"
|
14
|
+
state "New York"
|
15
|
+
zip 10065
|
16
|
+
end
|
17
|
+
|
18
|
+
skills do
|
19
|
+
ruby true
|
20
|
+
asp false
|
21
|
+
php true
|
22
|
+
mysql true
|
23
|
+
mongodb true
|
24
|
+
haproxy true
|
25
|
+
marathon false
|
26
|
+
end
|
27
|
+
|
28
|
+
single_skills ['ruby', 'php', 'mysql', 'mongodb', 'haproxy']
|
29
|
+
booleans [true, true, false, nil]
|
30
|
+
})
|
31
|
+
|
32
|
+
runs = 15000
|
33
|
+
Benchmark.bm(28) do |bench|
|
34
|
+
bench.report("HashBuilder") do
|
35
|
+
runs.times do
|
36
|
+
HashBuilder.build(&template)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
bench.report("HashBuilder + JSON.generate") do
|
41
|
+
runs.times do
|
42
|
+
JSON.generate(HashBuilder.build(&template))
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
bench.report("HashBuilder + to_json") do
|
47
|
+
runs.times do
|
48
|
+
HashBuilder.build(&template).to_json
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
bench.report("JSONBuilder") do
|
53
|
+
runs.times do
|
54
|
+
JSONBuilder::Compiler.generate(&template)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'hash_builder/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "hash_builder"
|
8
|
+
spec.version = HashBuilder::VERSION
|
9
|
+
spec.authors = ["Marten Lienen"]
|
10
|
+
spec.email = ["marten.lienen@gmail.com"]
|
11
|
+
spec.description = %q{Build hashes with the full power of ruby at your fingertips}
|
12
|
+
spec.summary = %q{The readme has examples}
|
13
|
+
spec.homepage = "https://github.com/CQQL/hash_builder"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.4"
|
22
|
+
spec.add_development_dependency "rake", "~> 10.1"
|
23
|
+
spec.add_development_dependency "rspec"
|
24
|
+
spec.add_development_dependency "json_builder"
|
25
|
+
|
26
|
+
spec.add_dependency "exec_env"
|
27
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module HashBuilder
|
2
|
+
# Renders templates with '.json_builder' extension.
|
3
|
+
#
|
4
|
+
# If the template is a normal view, it will render a JSON string.
|
5
|
+
# If the template however is a partial, it renders a Hash so that
|
6
|
+
# json_builder files can use partials.
|
7
|
+
class Template
|
8
|
+
def self.default_format
|
9
|
+
Mime::JSON
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.call (template)
|
13
|
+
render_code = <<-RUBY
|
14
|
+
HashBuilder.build(scope: self, locals: local_assigns) do
|
15
|
+
#{template.source}
|
16
|
+
end
|
17
|
+
RUBY
|
18
|
+
if !is_partial?(template)
|
19
|
+
# ActiveModel defines #as_json in a way, that is not compatible
|
20
|
+
# with JSON.
|
21
|
+
if defined?(ActiveModel)
|
22
|
+
render_code = "ActiveSupport::JSON.encode(#{render_code})"
|
23
|
+
else
|
24
|
+
render_code = "JSON.generate(#{render_code})"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
render_code
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.is_partial? (template)
|
32
|
+
template.virtual_path.split("/").last.start_with?("_")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
if defined?(ActionView)
|
38
|
+
ActionView::Template.register_template_handler :json_builder, HashBuilder::Template
|
39
|
+
end
|
data/lib/hash_builder.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require "exec_env"
|
2
|
+
|
3
|
+
require "hash_builder/version"
|
4
|
+
require "hash_builder/template"
|
5
|
+
|
6
|
+
module HashBuilder
|
7
|
+
# Build a Hash.
|
8
|
+
#
|
9
|
+
# args - Arguments to be passed to the hash
|
10
|
+
# scope - Method calls in the block will be sent to scope object
|
11
|
+
# locals - Local variables to be injected into the block
|
12
|
+
#
|
13
|
+
# Examples
|
14
|
+
#
|
15
|
+
# HashBuilder.build(locals: {foo: 1}) do
|
16
|
+
# foo foo
|
17
|
+
# bar 2
|
18
|
+
# end
|
19
|
+
# # => { foo: 1, bar: 2}
|
20
|
+
def self.build (args: [], scope: nil, locals: {}, &block)
|
21
|
+
env = ExecEnv::Env.new
|
22
|
+
env.scope = scope
|
23
|
+
env.locals = locals
|
24
|
+
|
25
|
+
block_result = env.exec(*args, &block)
|
26
|
+
|
27
|
+
messages = env.messages
|
28
|
+
|
29
|
+
if messages.size > 0
|
30
|
+
hash = {}
|
31
|
+
|
32
|
+
messages.each do |(name, args, block)|
|
33
|
+
arg = args.first
|
34
|
+
|
35
|
+
if args.size == 1 && block && arg.is_a?(Enumerable) && !arg.is_a?(Hash)
|
36
|
+
hash[name] = arg.map do |*objects|
|
37
|
+
HashBuilder.build(args: objects, scope: scope, locals: locals, &block)
|
38
|
+
end
|
39
|
+
elsif block
|
40
|
+
hash[name] = HashBuilder.build(scope: scope, locals: locals, &block)
|
41
|
+
elsif args.size == 1
|
42
|
+
hash[name] = arg
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
hash
|
47
|
+
else
|
48
|
+
block_result
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "json"
|
2
|
+
|
3
|
+
class ViewStub
|
4
|
+
def local_assigns
|
5
|
+
{}
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
describe HashBuilder::Template do
|
10
|
+
let(:view) { ViewStub.new }
|
11
|
+
|
12
|
+
it "should render a template into a JSON string" do
|
13
|
+
template = double("template", source: "foo 1\nbar 'test'", virtual_path: "test/index")
|
14
|
+
|
15
|
+
code = HashBuilder::Template.call(template)
|
16
|
+
json = view.instance_eval(code)
|
17
|
+
|
18
|
+
expect(JSON.parse(json)).to eq({ "foo" => 1, "bar" => "test" })
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should render a hash if the template is a partial" do
|
22
|
+
template = double("template", source: "foo 1\nbar 'test'", virtual_path: "test/_index")
|
23
|
+
|
24
|
+
code = HashBuilder::Template.call(template)
|
25
|
+
hash = view.instance_eval(code)
|
26
|
+
|
27
|
+
expect(hash).to eq({ foo: 1, bar: "test" })
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
describe HashBuilder do
|
2
|
+
it "should construct a simple hash" do
|
3
|
+
hash = HashBuilder.build do
|
4
|
+
key "A test key"
|
5
|
+
|
6
|
+
number 1337
|
7
|
+
end
|
8
|
+
|
9
|
+
expect(hash).to eq({ key: "A test key", number: 1337 })
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should construct nested hashes" do
|
13
|
+
hash = HashBuilder.build do
|
14
|
+
level1 "Easy"
|
15
|
+
|
16
|
+
container do
|
17
|
+
level2 "Harder"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
expect(hash).to eq({ level1: "Easy", container: { level2: "Harder" } })
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should iterate over enumerables if arg and block is given" do
|
25
|
+
hash = HashBuilder.build do
|
26
|
+
numbers (0..3).to_a do |num|
|
27
|
+
i num
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
expect(hash).to eq({ numbers: [{ i: 0 }, { i: 1 }, { i: 2 }, { i: 3 }] })
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should pass the environment into nested blocks" do
|
35
|
+
scope = Object.new
|
36
|
+
scope.instance_variable_set(:@id, 13)
|
37
|
+
|
38
|
+
hash = HashBuilder.build(locals: { user: "CQQL" }, scope: scope) do
|
39
|
+
user do
|
40
|
+
name user
|
41
|
+
id @id
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
expect(hash).to eq({ user: { id: 13, name: "CQQL" } })
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should not set keys that have no explicit value" do
|
49
|
+
hash = HashBuilder.build do
|
50
|
+
read
|
51
|
+
write 1
|
52
|
+
end
|
53
|
+
|
54
|
+
expect(hash).to eq({ write: 1 })
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should allow setting keys to nil" do
|
58
|
+
hash = HashBuilder.build do
|
59
|
+
foo nil
|
60
|
+
end
|
61
|
+
|
62
|
+
expect(hash).to eq({ foo: nil })
|
63
|
+
end
|
64
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "hash_builder"
|
metadata
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: hash_builder
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Marten Lienen
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-11-27 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.4'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.4'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.1'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.1'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: json_builder
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: exec_env
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description: Build hashes with the full power of ruby at your fingertips
|
84
|
+
email:
|
85
|
+
- marten.lienen@gmail.com
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- .gitignore
|
91
|
+
- .rspec
|
92
|
+
- Gemfile
|
93
|
+
- Gemfile.lock
|
94
|
+
- LICENSE.txt
|
95
|
+
- README.md
|
96
|
+
- Rakefile
|
97
|
+
- benchmark.rb
|
98
|
+
- hash_builder.gemspec
|
99
|
+
- lib/hash_builder.rb
|
100
|
+
- lib/hash_builder/template.rb
|
101
|
+
- lib/hash_builder/version.rb
|
102
|
+
- spec/hash_builder/template_spec.rb
|
103
|
+
- spec/hash_builder_spec.rb
|
104
|
+
- spec/spec_helper.rb
|
105
|
+
homepage: https://github.com/CQQL/hash_builder
|
106
|
+
licenses:
|
107
|
+
- MIT
|
108
|
+
metadata: {}
|
109
|
+
post_install_message:
|
110
|
+
rdoc_options: []
|
111
|
+
require_paths:
|
112
|
+
- lib
|
113
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
119
|
+
requirements:
|
120
|
+
- - '>='
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: '0'
|
123
|
+
requirements: []
|
124
|
+
rubyforge_project:
|
125
|
+
rubygems_version: 2.1.5
|
126
|
+
signing_key:
|
127
|
+
specification_version: 4
|
128
|
+
summary: The readme has examples
|
129
|
+
test_files:
|
130
|
+
- spec/hash_builder/template_spec.rb
|
131
|
+
- spec/hash_builder_spec.rb
|
132
|
+
- spec/spec_helper.rb
|