6
\$\begingroup\$

I'm seeding my database with a relatively complex data model.

Constraints: Every meal has exactly one main dish (marked as is_main in intermediate table).

Here is my seeds.rb file:

User.create!(name:  "User", #create normal user
             surname: "Name",
             email: "[email protected]",
             password:              "11111111",
             password_confirmation: "11111111",
             zip: 188661)

5.times do |n| #create remaining users
    name = Faker::Name.first_name
    surname = Faker::Name.last_name
    email = Faker::Internet.safe_email
    password="11111111"
    password_confirmation="11111111"
    zip=Faker::Number.between(111111, 999999)
    address=Faker::Address.street_address
    room=Faker::Number.between(1, 1000)
    telephone=Faker::PhoneNumber.cell_phone

    User.create!(
        name: name,
        surname: surname,
        email: email,
        password: password,
        password_confirmation: password_confirmation,
        zip: zip,
        address: address,
        room: room,
        telephone: telephone)
end

User.ids.each do |n| #create cook profile for all users
    about=Faker::Lorem.paragraphs(2)
    about_kitchen=Faker::Lorem.paragraphs(1)
    how_to_find = Faker::Lorem.paragraphs(1)

    CookProfile.create!(
        about: about,
        about_kitchen: about_kitchen,
        how_to_find: how_to_find,
        user_id: n) 
end


30.times do |n| #create 30 different dishes 
    name = Faker::Company.buzzword
    description = Faker::Lorem.paragraphs(1)
    price = Faker::Number.between(3000, 20000)
    cook_profile_id = CookProfile.ids[Faker::Number.between(0, CookProfile.count-1)]

    Dish.create!(
             cook_profile_id: cook_profile_id,
             name: name,
             description: description,
             price: price)
end


8.times do |n|  
    date_ready  = Faker::Date.forward(10)
    hours_before_stopping_orders = Faker::Number.between(2, 5)
    is_free_delivery = Faker::Boolean.boolean
    time_before_take_away = Faker::Time.between(2.days.ago, Time.now, :day)
    time_ready = Faker::Time.between(2.days.ago, Time.now, :day)

    Meal.create!(
             is_publish: true,
             date_ready: date_ready,
             hours_before_stopping_orders: hours_before_stopping_orders,
             is_free_delivery: is_free_delivery,
             time_before_take_away: time_before_take_away,
             time_ready: time_ready)
end


p=Array.new #one meal contain exactly one main dish
cook_ids=Array.new 
Dish.all.each do |n|
    meal_id=Meal.ids[Faker::Number.between(0, Meal.count-1)]
    if cook_ids.include? n.cook_profile_id
        pp=MealDishConnection.joins(:dish).where({dishes: {cook_profile_id: n.cook_profile_id}}).select(:meal_id)
        meal_id=pp[Faker::Number.between(0, pp.count-1)].meal_id
    else
        cook_ids<<n.cook_profile_id 
        result=Meal.ids-p
        meal_id=result.shuffle.first
    end


    if p.include? meal_id

                MealDishConnection.create!(
                     dish_id: n.id,
                     max_amount_of_dishes: 5,
                     meal_id: meal_id,
                     is_main:false)
    else
                p<<meal_id
                MealDishConnection.create!(
                     dish_id: n.id,
                     max_amount_of_dishes: 5,
                     meal_id: meal_id,
                     is_main:true)
    end
 end
\$\endgroup\$
0

1 Answer 1

1
\$\begingroup\$

I would suggest using the FactoryGirl to accomplish this. To give you some ideas:

User Factory

FactoryGirl.define do

  factory :user do
    name { Faker::Name.first_name }
    surname { Faker::Name.last_name }
    email { "#{first_name}.#{last_name}@#{Faker::Internet.domain_name}".downcase }
    password { Faker::Lorem.word }
    password_confirmation { "#{password}" }
    zip { Faker::Number.between(111111, 999999) }
    # ... assign other attributes

    factory :john do
      name 'John'
      surname 'Smith'
      email '[email protected]'
      password '11111111'
      password_confirmation '11111111'
      zip '188661'
    end

    factory :user_with_cook_profile_and_dishes do
      after(:create) do |user|
        create(:cook_profile_with_dishes, user: user)
      end
    end

  end
end

Profile Factory

FactoryGirl.define do
  factory :cook_profile do
    about { Faker::Lorem.paragraphs(2) }
    about_kitchen {Faker::Lorem.paragraphs(1) }
    how_to_find { Faker::Lorem.paragraphs(1) }

    factory :cook_profile_with_dishes do
      after(:create) do |cook_profile|
        (1..5).times do
          meal = create(:meal_with_main_dish)
          main_dish = meal.main_dish # You'll have to implement something that can get the main dish from a meal
          main_dish.cook_profile = self
        end
      end
    end

  end
end

Dish Factory

FactoryGirl.define do
  factory :dish do
    name { Faker::Company.buzzword }
    #... assign rest of attributes
  end
end

Meal Factory

FactoryGirl.define do
  factory :meal do
    date_ready { Faker::Date.forward(10) }
    # ... assign rest of attributes (description, price )

    factory :meal_with_main_dish do
      after(:create) do |meal|
        create(:dish, meal: meal)
      end
    end
  end
end

Then, your seeds.rb file could simply become:

FactoryGirl.create(:john)
30.times { FactoryGirl.create(:user_with_cook_profile_and_dishes) }
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.