【问题标题】:Rails faker gem produces same product nameRails faker gem 产生相同的产品名称
【发布时间】:2017-07-07 07:05:40
【问题描述】:

我正在尝试使用 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

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

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-4 random-sample faker


    【解决方案1】:

    要获得唯一的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) }
    

    【讨论】:

    • 这个工作的原因是因为你定义了一个“块”来执行。否则 ruby​​ 会很乐意一遍又一遍地重用相同的字符串。
    【解决方案2】:

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

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

    【讨论】:

    • 这没有做任何事情,我将:name 验证行中的uniqueness: true 替换为您所说的,我编辑了item.rb 以显示所有验证
    【解决方案3】:

    经过一些实验,我发现了这一点,显然循环在某些方面就像一个函数,就范围而言。如果在循环中初始化局部变量,循环外的函数将看不到它。在这种情况下,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 
    

    【讨论】:

      猜你喜欢
      • 2019-06-18
      • 2018-09-09
      • 2019-07-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多