Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby on Rails Seed Data

I am Ruby/Rails newbie. I am currently learning about the Rails console and databases using Rake and the seeds.rb file.

I am supposed to:

  • Add a post with a unique title and body to seeds.rb.
  • Before creating a unique post, verify it exists in the database. Only seed the post if it doesn't.
  • Run rake db:seed a couple times, start your Rails console and confirm that your unique post has only been seeded once.
  • Repeat to create a unique comment and confirm that it is also only seeded once.

Honestly I don't know how to start working on this. I am supposed to add a post using the rails console or directly from the seeds.rb file? Any guidance will be greatly appreciated.

like image 723
mp_jr Avatar asked Mar 06 '15 21:03

mp_jr


People also ask

What is seed data in rails?

Rails seed files are a useful way of populating a database with the initial data needed for a Rails project. The Rails db/seeds. rb file contains plain Ruby code and can be run with the Rails-default rails db:seed task.

How do I run seeds in rails?

Using a custom Rails task to seed actual data To seed actual data, it is best to create a custom Rails task. Let's generate one to add genres. First generate the model and then migrate the database. Finally create the task.

What is Seeds rb file?

The seeds.rb file is where the seed data is stored, but you need to run the appropriate rake task to actually use the seed data. Using rake -T in your project directory shows information about following tasks: rake db:seed. Load the seed data from db/seeds.rb.


1 Answers

Despite the intention of seed-ing - that this is meant to be run once, to populate the database - there is no technical constrain preventing you from running rake db:seed command couple times. Even without cleaning/recreating your database.

In that case, try following code for db/seeds.rb

post_atrributes = [
  { title: "Sample Title 1", body: "Sample body 1" },
  { title: "Sample Title 2", body: "Sample body 2" },
  { title: "Sample Title 3", body: "Sample body 3" },
]

post_attributes.each do |attributes|
  Post.create(attributes) unless Post.where(attributes).first
end

First of all, we're defining an array of attributes for each Post, to be created.

Later, we're iterating through that array (with post_attributes.each do |attributes|), and trying create a new Post, unless one with specified attributes found.

In Rails, there is quite fancy method first_or_create, which does exactly that - queries database for specified attributes (where(attributes)), and if nothing found - creates new record based on provided attributes.

post_atrributes = [
  { title: "Sample Title 1", body: "Sample body 1" },
  { title: "Sample Title 2", body: "Sample body 2" },
  { title: "Sample Title 3", body: "Sample body 3" },
]

post_attributes.each do |attributes|
  Post.where(attributes).first_or_create
end

At this point, you can "seed" the database with rake db:seed and check what is stored in database (after running rails console) by:

Post.all.map(&:title)

Assuming you had empty database before running rake db:seed, it should contain only 3 Posts. The ones specified with attributes in post_attributes.

Now, if you try to modify your db/seeds.rb again, adding an attributes for one more Post:

post_atrributes = [
  { title: "Sample Title 1", body: "Sample body 1" },
  { title: "Sample Title 2", body: "Sample body 2" },
  { title: "Sample Title 3", body: "Sample body 3" },
  { title: "Another Post", body: "WOW!" },
]

post_attributes.each do |attributes|
  Post.where(attributes).first_or_create
end

After running rake db:seed, and checking in console:

Post.all.map(&:title)

You can see, that only one new Post has been created. The one with title "Another Post".

In your question I understood, that when creating new Post, both attributes - title and body have be unique, so if you try to perform the same for attributes like:

post_atrributes = [
  { title: "Sample Title 1", body: "Sample body 1" },
  { title: "Sample Title 1", body: "Sample body 2" },
]

This will create two separate Posts, because they have different body attributes defined.

For Comments you can do similar thing.

Again, as jBeas mentioned earlier - seed-ing has different purpose, but if this is only exercise to play with ActiveRecord - this is one of ways how you can tackle the problem.

Hope that helps!

like image 138
Paweł Dawczak Avatar answered Sep 29 '22 20:09

Paweł Dawczak