Genny likes making things up. Unlike other faker libraries this one is based around generating whole data structures using JSONSchema as a basis.
This gem can be used without any additional gems. The following gems will be used if they can be loaded, but not having them installed/in your bundle will reduce functionality rather than prevent the library from working:
- json-schema - for JSONSchema validation
- faker - for better hinted strings
Extending the core classes to have the genny
class method is handy, but may not be desired. If you wish to use this style then you must initialise it:
Genny::String.genny
# => "pymliestqk"
String.respond_to?(:genny)
# => false
Genny.extend_core
# => [NilClass, URI, Time, Date, Array, Float, String, Regexp, Integer, Hash]
String.respond_to?(:genny)
# => true
String.genny
# => "oniqpsxubm"
Genny::String.genny
# => "fusmtzavyi"
Genny::String.genny(format: "ipv4")
# => "171.199.220.179"
# You can define your own formats
Genny::String.format("tla") do |opts|
3.times.map { ('A'..'Z').to_a.sample }.join
end
Genny::String.genny(format: "tla")
# => "XSE"
# Genny makes JSONSchema a first class... class. It acts like a hash but has a genny instance method.
# If the json-schema gem can be loaded then the new method will raise an error if it's an invalid schema.
js = JSONSchema.new(
"type" => "object",
"properties" => {
"key" => {
"type" => "string"
}
}
)
# => {"type"=>"object", "properties"=>{"key"=>{"type"=>"string"}}, "definitions"=>{}}
js.genny
# => {"key"=>"gcqhsanwzd"}
A generated array will always be empty unless a :items
option has been defined. Any class in that array that responds to genny
may be picked as the prototype for an element of the generated array.
Genny::Array.genny
# => []
Genny::Array.genny(items: [Genny::String, Genny::Integer])
# => ["mcztjgoriq", "nohfcavjyz", 739]
Genny::Array.genny(
items: JSONSchema.new(
"type" => "object",
"properties" => {
"key" => {
"type" => "string"
}
}
)
)
# => ["mcztjgoriq", "nohfcavjyz", 739]
# Hinting for strings allows you to try and indicate what kind of string you'd like back.
Genny::String.genny(hint: "first name")
# => "Dean"
Genny::String.genny(hint: "name")
# => "Garrison O'Kon"
# And when an object value type is a string, the key will be used as a hint
JSONSchema.new(
"type" => "object",
"properties" => {
"name" => {
"type" => "string"
}
}
).genny
# => { "name" => "Everett Schmitt" }
# You can define your own hinters. Hints defined earlier will take precidence
Genny::String.hint do |opts|
next unless opts[:hint].include?("answer")
"42"
end
Genny::String.genny(hint: "the answer")
# => "42"
Genny::Integer.genny
# => 5
Genny::Integer.genny(maximum: 100)
# => 88
Genny::Integer.genny(minimum: 90, maximum: 100)
# => 92
Genny::Float.genny
# => 234.2934215006394
Genny::Float.genny(minimum: 90, maximum: 100)
# => 96.6691946757789
Genny::Date.genny
# => #<Date: 1987-03-01 ((2446856j,0s,0n),+0s,2299161j)>
Genny::Time.genny
# => 1988-11-23 05:48:04 UTC
# These are also a format of string (for JSONSchema purposes)
Genny::String.genny(format: "date")
# => "1975-07-24"
Genny::String.genny(format: "date-time")
# => "1994-10-11T07:32:55Z"
There being no core Boolean
class this must be called directly even if the core classes have been extended.
Genny::Boolean.genny
# => false
Genny::Boolean.genny
# => true
Genny::URI.genny
# => #<URI::HTTP:0x007f8c1c164f90 URL:http://example.com/erichqlvjx>
# URIs are also a format of string (for JSONSchema purposes)
Genny::String.genny(format: "uri")
# => "http://example.com/itgxsewckm"
Generating a regular expression is a bit useless (it always returns /.*/
which matches most strings) but there is also an instance genny
method defined which will, when I implement it, make a best effort at creating a string which matches the given regular expression.
Genny::Regexp.genny
# => /.*/
/[a-f0-9]{2}/.extend(Genny::Regexp).genny
# => "a7"
Genny.extend_core
/[a-f0-9]{2}/.genny
# => "5c"
# You can also specify regular expressions as formats for strings
Genny::String.genny(format: "^979\\d{10}$")
# => "9790607263440"
Please note: Regular expression support is not guaranteed. I mean, I'm parsing regular expressions with regular expressions and that way madness lies.
If you're calling genny
on a regular expression instance, be sure to rescue NotImplementedError
exceptions, which will be thrown if the generated string doesn't match the Regexp.
If you're generating a string with a format that looks like a regular expression, the worst that will happen is a string will be returned as if no format
had been specified. If you need a specific regular expression to work and don't feel like driving yourself insane, you can specfify a format
with the regular expression you need and write your own code to generate it:
Genny::String.format("^(?!un)") do |opts|
Genny::String.genny.sub(/^un/, '')
end
Genny::String.genny(format: "^(?!un)")
# => "doesntstartwithun"
Yes please! Pull requests would be lovely.
I am @jphastings and I work at blinkbox Books, do get in touch.
Also, let's have none of this gif/jif nonsense. Unless it sounds ugly in your language, you have just finished reading the documentation for /jeni/ ;)