Rails faker gem 生产相同的产品名称

Rails faker gem produces same product name

我正在尝试使用 rails Faker gem 来生成唯一的产品名称,以便在数据库中制作示例项目模型。我已经多次使用 Faker,但出于某种原因我无法产生新的产品名称。我已经制作了 nameMaker 函数以避免可能的早期重复,但我在一次插入后得到了一个记录失效。有谁知道我该如何解决这个问题?

seed.rb:

98.times do |n|
    name = Item.nameMaker
    description = Faker::Lorem.sentence(1)
    price = Item.priceMaker
    item = Item.create!(
        name: name,
        description: description,
        price: price)
    end

item.rb:

class Item < ActiveRecord::Base
    validates :name, presence: true, length: { maximum: 100 }
    validates :description, presence: true,
        length: { maximum: 1000 }
    VALID_PRICE_REGEX = /\A\d+(?:\.\d{0,3})?\z/
    validates :price, presence: true,
        :format => { with: VALID_PRICE_REGEX },
        :numericality => {:greater_than => 0}
    validates_uniqueness_of :name  

    def Item.nameMaker
        loop do
            name = Item.newName
            break if Item.find_by(name: name).nil?
        end
        return name
    end

    def Item.newName
        Faker::Commerce.product_name
    end 
end

您可以在模型中添加 validates_uniqueness_of :name。当你 运行 seed 方法时,如果已经存在相同的名称,它会抛出错误并跳到下一个。

您可能不会正好有 98 Items。您可以增加次数或编辑 Faker 本身。

经过一些实验我弄明白了,显然循环在某些方面就像一个函数一样作用域。如果在循环中初始化局部变量,循环外的函数将看不到它。在这种情况下,name 总是从 Item.nameMaker 函数返回字符串 Item。因此,第一次尝试总是会成功,而第二次尝试将获得验证限制。

def Item.nameMaker
    loop do
        name = Faker::Commerce.product_name # 'Random Product Name'
        puts "Name: #{name}" # "Name: Random Product Name"
        item = Item.find_by(name: name)
        if item.nil?
        puts "#{name} not found" # "Random Product Name not found"
        break
        else 
        end
    end
    puts "Returning Name #{name}" # "Returning Name Item"
    return name
end 

我设法通过在循环外初始化局部变量来解决这个问题。通过这样做,出于某种原因,整个函数现在对同一个局部变量具有可见性。

def Item.nameMaker
    name = "" #initializing
    loop do
        name = Faker::Commerce.product_name # 'Random Product Name'
        puts "Name: #{name}" # "Name: Random Product Name"
        item = Item.find_by(name: name)
        if item.nil?
        puts "#{name} not found" # "Random Product Name not found"
        break
        else 
        end
    end
    puts "Returning Name #{name}" # "Returning Random Product Name"
    return name
end 

要获得独一无二的 name,请将伪造者括在括号中。例如

 name { Faker::Commerce.product_name }

为此,您还可以使用工厂女孩,当您想要创建 98 个不同的项目时,您可以使用

    factories/item.rb

FactoryGirl.define do
  factory :item do
    name { Faker::Commerce.product_name }
    description { Faker::Lorem.sentence(1) }
    price Faker::Commerce.price
  end
end

在您的规范文件中

let(:item) { create_list(:item, 98) }