Is there any way to generate guarantee unique value? May be by passing some base unique value.
Now, then I run my tests they sometimes fails because of duplicating names, because Faker::Name.name return random value and sometimes two calls return duplicated values.
I think it may be fixed by passing some my unique value. As I see it:
Faker::Name.name(1) # Always returns value "Jane"
Faker::Name.name(2) # Always returns value "Mary"
Perhaps I'm missing something here but why not just assign the names manually yourself if you need them to be unique and you always want the same values?
Or you could have some function like this in your test helper:
def gen_unique_name(other_name)
name = Faker::Name.name
if name == other_name
gen_unique_name(other_name)
end
name
end
@james-ai because, actually, I don't need to use same value, I need unique value each time I call Faker::Name.name. Now it may return same value for 2-3 calls.
Ah, I see, I did miss something.
So you would do something like the following:
We generate two random, distinct integers. Let's say 4, and 7
(1..10).to_a.sample(2)
person1 = Faker::Name.first_name(4)
person2 = Faker::Name.first_name(7)
You could modify fetch to take an index (default nil), but the downside here is that you'd need to add the index argument to each method that you want to be able to call an indexed item.
# Helper for the common approach of grabbing a translation
# with an array of values and selecting one of them.
def fetch(key, index = nil)
fetched = translate("faker.#{key}")
if index
# You'll need to handle the case where the returned object is nil
fetched = fetched[index] if fetched.class == Array
else
fetched = fetched.sample if fetched.respond_to?(:sample)
end
if fetched.match(/^\//) and fetched.match(/\/$/) # A regex
regexify(fetched)
else
fetched
end
end
module Faker
class Name < Base
flexible :name
class << self
def name
parse('name.name')
end
def first_name(index = nil); fetch('name.first_name', index); end
def last_name(index = nil); fetch('name.last_name', index); end
def prefix; fetch('name.prefix'); end
def suffix; fetch('name.suffix'); end
# Generate a buzzword-laden job title
# Wordlist from http://www.bullshitjob.com/title/
def title; fetch('name.title.descriptor') + ' ' + fetch('name.title.level') + ' ' + fetch('name.title.job'); end
end
end
end
For the parse method I guess you can do something similar.
Using FactoryGirl, In some of my factories I use sequence in combination with Faker:
sequence(:name) { |n| "#{Faker::Company.name}#{n}" }
sequence(:email) { |n| "#{n}#{Faker::Internet.email}" }
Depending on what you want, this might be a good solution.
I'm using the same workaround as @Carpetsmoker, but something like the following would be nice:
Faker.unique_mode = true
assert(Faker::Company.name != Faker::Company.name)
Faker.unique_mode = false
assert(
Faker::Company.name != Faker::Company.name ||
Faker::Company.name == Faker::Company.name
)
I'm aware that this probably requires quite some effort...
Would it be useful to make/find a gem that can ensure the uniqueness of a non unique data source? To avoid collisions without having ugly numbers.
For example with an email generated by Faker. That would have the cost of storing the existing emails in a Hash but that seems usable.
What do you think?
@tuxayo +1
PHP Faker has a modifier to get unique values (Faker.unique.name):
Stumbled on this because I'm doing something similar for a rails view where common input values need to return the same name. I realize this issue is pretty old, but figured I'd add this in case it was useful for someone else. I ended up with the following helper wrapped around Faker:
def unique_name(author)
hash = Digest::MD5.hexdigest author.to_s
RequestStore.store[:names] ||= {}
RequestStore.store[:names][hash] ||= Faker::Name.first_name
end
RequestStore was there to make sure there is no thread collision with servers like Puma/thin. A hash cache would do fine if that wasn't a concern.
Most helpful comment
Using FactoryGirl, In some of my factories I use
sequencein combination withFaker:Depending on what you want, this might be a good solution.