0

I have my migration files, which creates the initial schema for the database, and, I have my seed files, which populates the initial schema, with random data, and set types.

My understanding of the migrations and seeds is that, whenever a new team member joins, he can just run them and be up to speed with all db changes and the require data for the product to work, plus, you can apply changes to stg and prod by running migration files.

But, as my project has advanced, new types of data has been emerging and the only way to apply them was to create a migration that will run inserts into the database.

The problem that I have is that the way artisan works with migrations and seeds is that it first runs all migrations, and then, it runs all the seeds, and there does not seems to be a way for me to specify the order in which they should be run. So, if I run a migrate:refresh --seed I get into errors because it applies the latest migrations, which inserts new data (that might or might not, depend on types inserted in the seeds) before the seed has inserted his own data.

One solution we tried is to update the seeds as well, and check before applying changes in migrations that inserts data, but this has become very troublesome to maintain.

What is the expected use of the migrations and seeds for this scenario?

Update To try to make it more clear: Lets say I have a migration to create users: Users:{id, name, type} And I have my seed to create users.

I run both, and I have a users table with a bunch of users.

Time goes by, and we decide that we need a table for user_types. A migration is created, that will create the new table, and populate the data of the new user types and updates to match the current user.type to user.type_id.

Devs runs the migrations and they have theyre db all up to date.

A new dev joins the team. He runs the migrations. And then the seeds. It breaks.

Now, if we update the seeds to match the latest, we will run into duplicated data for the user_types table. To avoid this we will need to have some sort of defensive code in the migration to not run things if there is no data, and update if there it is.

The question is, is this the right way of using the migrations? How do you push a data change to all devs, withouth having to re run the seeds?

Maytham Fahmi
  • 31,138
  • 14
  • 118
  • 137
lebobbi
  • 2,147
  • 17
  • 20
  • Maybe I misunderstand but I fail to think of a scenario where the database structure can or should depend on the actual data. Are they foreign key issues by chance where you need to create the parent data before creating child data? – user1669496 Mar 17 '16 at 17:42
  • I updated the description with an scenario – lebobbi Mar 17 '16 at 17:58
  • Seeders are supposed to rerun. Every seeder has a `Model::truncate()` as a starting point. – user2094178 Mar 17 '16 at 21:10

2 Answers2

2

I think migrations should not depend on any data in seeds. And seeds should expect the latest migration schema. So, whenever your schema changes, you should update seeds accordingly and do a migrate:fresh --seed. At least, that's what I'm doing.

As you are already doing that, I wonder what makes it a "troublesome process" for you. Can you elaborate?

neochief
  • 569
  • 4
  • 6
  • Yeah, the thing is that, we expect the migrations to help us avoid doing that: having to refresh every time a new change is made. So that we can run the migrations on stg or even prod, to add new types, modify existing, tables, etc. – lebobbi Mar 17 '16 at 17:57
  • 1
    Well, you suppose to never seed in production database. Seeding is for testing only. So, if you have some stuff in seeds that is supposed to be created on the production after release, I bet you should move it to migration. @user3158900 added a great answer, which clarifies part about erasing before seeding. – neochief Mar 17 '16 at 18:35
1

From your explanation, I think I understand.

The first thing your seeders should do is delete everything so you always start with an empty database, at least where the seeders should be concerned.

I'd also take a closer look at the docs https://laravel.com/docs/5.2/seeding specifically the section "Using Model Factories".

public function run()
{
    factory(App\User::class, 50)->create()->each(function($u) {
        $u->posts()->save(factory(App\Post::class)->make());
    });
}

In this case, you'd do something similar except you'd start at the top which for you is user_types, then for each type it creates, it would generate however many users you need. This seems a bit different from your current process where it sounds like you have a seeder file for each table.

This way, you have the parent/child relationships handled and made very clear in the code and it's very easy to add additional items in the future. Additionally, because you are essentially starting from scratch each time the seeders run, you can be sure this will work for new and existing devs.

user1669496
  • 32,176
  • 9
  • 73
  • 65
  • I guess, I will still need to check before inserting or modifying data in migrations for already seeded users right? – lebobbi Mar 17 '16 at 18:43