Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Faker::Json #1156

Merged
merged 11 commits into from
Sep 18, 2018
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,10 @@ Style/DateTime:
Enabled: false
Style/Documentation:
Enabled: false
Style/EvalWithLocation:
Exclude:
- 'lib/faker/json.rb'

Security/Eval:
Exclude:
- 'lib/faker/json.rb'
64 changes: 64 additions & 0 deletions doc/json.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Faker::Json

**shallow_json(width_int, options_hash)** -> JSON formated string

Takes a width_int and options_hash where the number of key value pairs in the
returned JSON string is equal to the width_int.

`options_hash = {key: Class.method, value: Class.method}` where Class is
any class in the Faker gem. For example if you wanted random names for keys
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it should be if you want random names for keys instead of wanted?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! I will fix it.

and random Star Wars quotes for values you would write the options_hash as follows
```ruby
options_hash = { key: 'Name.first_name', value: 'StarWars.quote' }
```

It is important to note that you do not need to append your Faker Gem Class calls
with `Faker::`

```ruby
Faker::Json.shallow_json(3, key: 'RockBand.name', value: 'Seinfeld.quote')
# =>
{"Parliament Funkadelic":"They're real, and they're spectacular.",
"Fleetwood Mac":"I'm not a lesbian. I hate men, but I'm not a lesbian.",
"The Roots":"It became very clear to me sitting out there today that every decision
I've made in my entire life has been wrong. My life is the complete opposite of everything
I want it to be. Every instinct I have, in every aspect of life, be it something to wear,
something to eat - it's all been wrong."}
```

**add_depth_to_json(JSON, width_int, options_hash)** -> JSON

Functions exactly as `Json#shallow_json()` except it takes in a JSON as an
additional argument and returns that JSON with new generated nested JSONs in
place of the lowest nested values. It is important to note that the JSON must
be a JSON and not a hash.

```ruby
json = Faker::Json.shallow_json(3, key: 'Name.first_name', value: 'Name.last_name')
puts json # =>
{"Alisha":"Olson","Everardo":"DuBuque","Bridgette":"Turner"}

json2 = Faker::Json.add_depth_to_json(json, 2, key: 'Name.first_name', value: 'Name.last_name')
puts json2 # =>
{"Alisha":{"Daisy":"Trantow","Oda":"Haag"},
"Everardo":{"Javier":"Marvin","Eliseo":"Schuppe"},
"Bridgette":{"Jorge":"Kertzmann","Lelah":"MacGyver"}}

json3 = Faker::Json.add_depth_to_json(json2, 4, key: 'Name.first_name', value: 'Name.last_name')
puts json3 # =>
{"Alisha":
{"Daisy":
{"Bulah":"Wunsch","Cristian":"Champlin","Lester":"Bartoletti","Greg":"Jacobson"},
"Oda":
{"Salvatore":"Kuhlman","Aubree":"Okuneva","Larry":"Schmitt","Velva":"Gibson"}},
"Everardo":
{"Javier":
{"Eduardo":"Orn","Laila":"Kub","Thad":"Legros","Dion":"Wilderman"},
"Eliseo":
{"Olin":"Hilpert","Marisa":"Greenfelder","Karlee":"Schmitt","Judd":"Larkin"}},
"Bridgette":
{"Jorge":
{"Eloy":"Pfeffer","Kody":"Hansen","Paxton":"Lubowitz","Abe":"Lesch"},
"Lelah":
{"Rick":"Wiza","Bonita":"Bayer","Gardner":"Auer","Felicity":"Abbott"}}}
```
70 changes: 70 additions & 0 deletions lib/faker/json.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
module Faker
class Json < Base
require 'json'

class << self
def shallow_json(width = 3, options = { key: 'Name.first_name', value: 'Name.first_name' })
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we convert to keyword arguments?

def shallow_json(width: 3, options: { key: 'Name.first_name', value: 'Name.first_name' })

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I should have some time this weekend to make the change

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can skip this review for now because we have an open PR that plans to convert these parameters to keyword arguments #605. This PR should be merged in faker v2.0. I think the contributor will need to rebase and fix several other methods and your module will be included, so we don't need to do this change right now.

options[:key] = options[:key].prepend('Faker::')
options[:value] = options[:value].prepend('Faker::')

hash = build_shallow_hash(width, options)
JSON.generate(hash)
end

def add_depth_to_json(json = shallow_json, width = 3, options = { key: 'Name.first_name', value: 'Name.first_name' })
options[:key] = options[:key].prepend('Faker::')
options[:value] = options[:value].prepend('Faker::')

hash = JSON.parse(json)
hash.each do |key, _|
add_hash_to_bottom(hash, [key], width, options)
end
JSON.generate(hash)
end

private

def build_shallow_hash(width, options)
key = options[:key]
value = options[:value]

hash = {}
width.times do
hash[eval(key)] = eval(value)
end
hash
end

def add_hash_to_bottom(hash, key_array, width, options)
key_string = build_keys_from_array(key_array)
if eval("hash#{key_string}").is_a?(::Hash)
eval("hash#{key_string}").each do |key, _|
key_array << key
add_hash_to_bottom(hash, key_array, width, options)
end
else
add_hash(key_array, hash, width, options)
key_array.pop
end
end

def add_hash(key_array, hash, width, options)
string_to_eval = 'hash'
key_array.length.times do |index|
string_to_eval << "['#{key_array[index]}']"
end
string_to_eval << " = #{build_shallow_hash(width, options)}"
eval(string_to_eval)
hash
end

def build_keys_from_array(key_array)
key_string = ''
key_array.each do |value|
key_string << "['#{value}']"
end
key_string
end
end
end
end
27 changes: 27 additions & 0 deletions test/test_faker_json.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
require File.expand_path(File.dirname(__FILE__) + '/test_helper.rb')

class TestFakerJson < Test::Unit::TestCase
require 'json'

def setup
@tester = Faker::Json
end

def test_shallow_json
json = Faker::Json.shallow_json(3, key: 'Name.first_name', value: 'Name.first_name')
assert JSON.parse(json).flatten.length.equal?(6)
end

def test_add_depth_to_json
json = Faker::Json.shallow_json(3, key: 'Name.first_name', value: 'Name.first_name')
json = Faker::Json.add_depth_to_json(json, 3, key: 'Name.first_name', value: 'Name.first_name')
assert JSON.parse(json).flatten[1].flatten.length.equal?(6)
assert JSON.parse(json).flatten[3].flatten.length.equal?(6)
assert JSON.parse(json).flatten[5].flatten.length.equal?(6)

json = Faker::Json.add_depth_to_json(json, 3, key: 'Name.first_name', value: 'Name.first_name')
assert JSON.parse(json).flatten[1].flatten[1].flatten.length.equal?(6)
assert JSON.parse(json).flatten[3].flatten[3].flatten.length.equal?(6)
assert JSON.parse(json).flatten[5].flatten[5].flatten.length.equal?(6)
end
end