Rails: Avoiding duplication errors in Factory Girl…am I doing it wrong?

前端 未结 4 948
花落未央
花落未央 2021-01-31 16:00

Suppose I have a model user, which has a uniqueness constraint on the email field

If I call Factory(:user) once all is well, but i

4条回答
  •  北恋
    北恋 (楼主)
    2021-01-31 16:06

    If you only need to generate a few values for attributes, you can also add a method to String, which keeps track of the prior strings used for an attribute. You could then do something like this:

    factory :user do
      fullname { Faker::Name.name.unique('user_fullname') }
    end
    

    I use this approach for seeding. I wanted to avoid sequence numbers, because they do not look realistic.

    Here the String extension which makes this happen:

    class String
      # Makes sure that the current string instance is unique for the given id.
      # If you call unique multiple times on equivalent strings, this method will suffix it with a upcounting number.
      # Example:
      #     puts "abc".unique("some_attribute") #=> "abc"
      #     puts "abc".unique("some_attribute") #=> "abc-1"
      #     puts "abc".unique("some_attribute") #=> "abc-2"
      #     puts "abc".unique("other") #=> "abc"
      #
      # Internal: 
      #  We keep a data structure of the following format:
      #     @@unique_values = {
      #       "some_for_id" => { "used_string_1" : 1, "used_string_2": 2 } # the numbers represent the counter to be used as suffix for the next item
      #     }
      def unique(for_id)
        @@unique_values ||= {} # initialize structure in case this method was never called before
        @@unique_values[for_id] ||= {} # initialize structure in case we have not seen this id yet
        counter = @@unique_values[for_id][self] || 0
        result = (counter == 0) ? self : "#{self}-#{counter}"
        counter += 1
        @@unique_values[for_id][self] = counter
        return result
      end
    
    end
    

    Caution: This should not be used for lots of attributes, since we track all prior strings (optimizations possible).

提交回复
热议问题