2015-03-22 4 views
1

Я пытаюсь использовать рельсы Faker gem для создания уникальных имен продуктов для создания образцов моделей товаров в базе данных. Я использовал Faker несколько раз, но по какой-то причине я не могу создавать новые названия продуктов. Я создал функцию nameMaker, чтобы избежать возможных ранних повторов, но я получаю недействительность записи сразу после одной вставки. Кто-нибудь знает, как я могу это исправить?Rails faker gem производит то же название продукта

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 

ответ

0

Я понял это после некоторых экспериментов, по-видимому, цикл в какой-то степени действует как функция с точки зрения определения области. Если вы инициализируете локальную переменную в цикле, функция вне цикла не увидит ее. В этом случае name всегда возвращает строку Item из функции Item.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 
0

Вы можете добавить validates_uniqueness_of :name в вашей модели. Когда вы запускаете метод семени, если уже существует такое же имя, оно будет вызывать ошибку и переходить к следующему.

Существует вероятность, что у вас не будет точно 98 Items. Вы можете увеличить количество раз или отредактировать самого Faker.

+0

Это не делает ничего, я заменил 'уникальность: истина' в строке': name', с которой вы сказали, я отредактировал 'item.rb', чтобы показать все проверки – user2361174

3

Чтобы получить уникальный 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) } 
+1

Причина, по которой это работает, потому что вы определенно g - «блок» для выполнения. В противном случае ruby ​​просто будет счастлив повторно использовать одну и ту же строку снова и снова. –