1

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

种子.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

项目.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
4

3 回答 3

4

要获得唯一的name,请将 faker 括在括号中。例如

 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) }
于 2017-02-08T11:25:36.703 回答
0

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

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 
于 2015-03-22T21:59:58.380 回答
0

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

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

于 2015-03-22T07:19:10.740 回答