DEV Community

John Paul Fababaer
John Paul Fababaer

Posted on

Sprint 5: Creating Sample Data

When creating an application, it is helpful to generate a sample data that populates our tables. In doing so, we can visualize how we want our users to interact with our application.

Taking an example from our Industrial Photogram, here's an example of a "sample_data" rake task:

desc "Fill the database tables with some sample data"
task example_sample_data: :environment do
  starting = Time.now

  if Rails.env.development?
    FollowRequest.delete_all
    Comment.delete_all
    Like.delete_all
    Photo.delete_all
    User.delete_all
  end

  12.times do
    name = Faker::Name.first_name
    User.create(
      email: "#{name}@example.com",
      password: "password",
      username: name.downcase,
      private: [true, false].sample,
    )
  end

  users = User.all

  users.each do |first_user|
    users.each do |second_user|
      next if first_user == second_user
      if rand < 0.75
        first_user.sent_follow_requests.create(
          recipient: second_user,
          status: FollowRequest.statuses.values.sample
        )
      end

      if rand < 0.75
        second_user.sent_follow_requests.create(
          recipient: first_user,
          status: FollowRequest.statuses.values.sample
        )
      end
    end
  end

  users.each do |user|
    rand(15).times do
      photo = user.own_photos.create(
        caption: Faker::Quote.jack_handey,
        image: "https://robohash.org/#{rand(9999)}"
      )

      user.followers.each do |follower|
        if rand < 0.5 && !photo.fans.include?(follower)
          photo.fans << follower
        end

        if rand < 0.25
          photo.comments.create(
            body: Faker::Quote.jack_handey,
            author: follower
          )
        end
      end
    end
  end

  ending = Time.now
  p "It took #{(ending - starting).to_i} seconds to create sample data."
  p "There are now #{User.count} users."
  p "There are now #{FollowRequest.count} follow requests."
  p "There are now #{Photo.count} photos."
  p "There are now #{Like.count} likes."
  p "There are now #{Comment.count} comments."
end
Enter fullscreen mode Exit fullscreen mode

Let's break this down.

1.

desc "Fill the database tables with some sample data"
task example_sample_data: :environment do
  starting = Time.now
Enter fullscreen mode Exit fullscreen mode

-Line 1: "desc" stands for description. Essentially, in this line we are giving a proper description of what the task would do when called.

-Line 2: we use the "task" method which takes in a Hash argument. The key is a Symbol of the name of our task "sample_data" and the value for this should be ":environment". This makes the Rails environment have access to all models, gems, and initializers.

-Line 3: Using the Time class to create a timestamp. (We will later call another Time.now so we can determine how long it took to create the sample data.

2.

if Rails.env.development?
  FollowRequest.delete_all
  Comment.delete_all
  Like.delete_all
  Photo.delete_all
  User.delete_all
end
Enter fullscreen mode Exit fullscreen mode

-This enables us to destroy previous iterations of the sample data every time we call on this task in the terminal. Use it with caution since we do NOT want to destroy records associated with the user = wrap the whole delete_all logic inside an if statement.

3.

  12.times do
    name = Faker::Name.first_name
    User.create(
      email: "#{name}@example.com",
      password: "password",
      username: name.downcase,
      private: [true, false].sample,
    )
  end
Enter fullscreen mode Exit fullscreen mode

-This block of code utilizes the gem "Faker" to generate randomized data. In this case, we are trying to create randomized "first_name". Before we decide what properties we want to define, it is a good idea to reference the corresponding model to know which columns need to filled.

-Afterwards, it is just up to you to define the Ruby logic needed to fill up each column of an Instance.

4.

users = User.all

  users.each do |first_user|
    users.each do |second_user|
      next if first_user == second_user
      if rand < 0.75
        first_user.sent_follow_requests.create(
          recipient: second_user,
          status: FollowRequest.statuses.values.sample
        )
      end

      if rand < 0.75
        second_user.sent_follow_requests.create(
          recipient: first_user,
          status: FollowRequest.statuses.values.sample
        )
      end
    end
  end
Enter fullscreen mode Exit fullscreen mode

-The idea behind this code block is to iterate through the 12 randomly generated Users to have the chance (75%) to send follow requests to other users + randomly define the status of that follow request (pending, accepted, or rejected).

5.

users.each do |user|
    rand(15).times do
      photo = user.own_photos.create(
        caption: Faker::Quote.jack_handey,
        image: "https://robohash.org/#{rand(9999)}"
      )

      user.followers.each do |follower|
        if rand < 0.5 && !photo.fans.include?(follower)
          photo.fans << follower
        end

        if rand < 0.25
          photo.comments.create(
            body: Faker::Quote.jack_handey,
            author: follower
          )
        end
      end
    end
  end
Enter fullscreen mode Exit fullscreen mode

There are 3 different things happening within this code block:

-Part 1: randomly determine how many photos the block variable "user" is going to post. In it, we use the faker gem + robohash to randomly generate values for our caption and image column, respectively.

-Part 2: if a follower of the user does NOT like the photo and the rand() method returns true, add the follower to the fans record, which is a list of User Instances that liked the photo.

-Part 3: give the follower a 25% chance to leave a randomly generated comment (via Faker) in the photo. Also populate the author_id column with the user_id.

  1. Finally, the hardest part.
  ending = Time.now
  p "It took #{(ending - starting).to_i} seconds to create sample data."
  p "There are now #{User.count} users."
  p "There are now #{FollowRequest.count} follow requests."
  p "There are now #{Photo.count} photos."
  p "There are now #{Like.count} likes."
  p "There are now #{Comment.count} comments."
end
Enter fullscreen mode Exit fullscreen mode

-As said before, we create another Time.now to take a timestamp of when the whole sample_data process ends. The remaining "print" lines is to show us that we created the sample data we wanted for our application.

It is always useful to create a sample_data task in order to aid in our development process. Make sure you are aware of the columns you want to fill out by referencing the models you created previously.

CY@!

Top comments (0)