Search code examples
ruby-on-railsrubyrakerails-migrationsrails-engines

Why do Migrations and Seeds for Mountable Engines need to be explicitly Loaded?


So I have been reading up on Ruby on Rails Engine guide migrations + seeds and it seems that in order to have seeds run on the Engine they need to be added in the application using it

(Example using the dummy app)

add MyEngine::Engine.load_seed to Engine/test/dummy/db/seeds.rb

My question is why do we need to do this surely they should be isolated from the main application anyway? (they do not relate and are only seeding the Engines database)

NB: If you are after some more context I have added the devise gem (/engine) to my Engine and the seed data is just creating a user under the context of my Engine for login to its interface


Solution

  • There are two parts of sharing seed data and schema for an engine: the schema migrations and the seed data itself.

    As an engine, there are two ways to encapsulate db migrations within the engine but have them run correctly within the Rails app:

    • Physically copy migration files into Rails db/migrate directory
    • Patch Rails migration load paths to add engine migration directory:

      config.paths["db/migrate"] += config.paths["db/migrate"].expanded

    ... within an initializer

    You can find a good discussion of migrations within engines here: https://blog.pivotal.io/labs/labs/leave-your-migrations-in-your-rails-engines

    Sharing seed data is a bit less elegant. DB seed data is loaded from the single db/seeds.rb file, so including custom seed data via engine code requires hooking into the Engine code from the seed file, such as your code above:

    MyEngine::Engine.load_seed
    

    There aren't any hacks or simpler ways to do that. You could probably automate prepending/appending that code into db/seeds.rb in your engine install/setup task.