Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails 3.2: Adding seed tasks from a mountable engine

I have a rails application using rake db:seed too fill in some of the basics in my DB to start working. This works through a little infrastructure and a fixtures.rb someone else wrote to load a YAML into the DB.
What I'm trying to do is take this infrastructure and move it into my own gem so that I can use it again elsewhere, this requires me both to have some of my own gem's models be inserted through the gem's seed task (which I want to have run from calling db:seed or something similar in the main app) and that the main app push some of the gem's models using it's own seed. The second part of this I already have working, it was a simple fix in the fixtures.rb file I was given. The things I want to do now:

  • Move fixtures.rb into the gem: I still don't have any of the source running this in the gem. Now to do this I can probably require the file from the [MyGem::Engine.root, 'lib', ...].join then call a method there with a path to load YAML files from into the DB, which I don't see why it shouldn't work.
  • Get rake db:seed to run a task defined in my gem. I've added .rake files under lib/tasks of my gem (it's an engine) and I can't seem to call them from the main app rakefile though.
    To make myself clear, what I want to do is through the gem (not the main app - or with 1 line of code in the main app) add a dependency onto the main apps seed task, so that when someone runs rake db:seed in the main app the gem will run additional seeding without the main app developer even having to know about them.

The dirty solution that I want to avoid is loading the .rake files from the gem inside the main app, or loading a seeds.rb in the gem from the one in the main app.

So what I'm asking is basically how to make the rake db:seed task do things defined within my gemified engine just by having the gem required in the gemfile?

like image 601
Shrewd Avatar asked Aug 28 '12 14:08

Shrewd


2 Answers

So shortly after asking this I figured it out. First step was taken from here: How to add a gems tasks to the main app

Then inside a task file

#lib/task/some_task.rake
Rake::Task['db:seed'].enhance ['my_seed_task']

#lib/tasks/my_seed_task.rake
task 'my_seed_task' do
  ...
end

And now when in the main app I run rake db:seed it runs whatever my_seed_task defines as a perquisite.

like image 71
Shrewd Avatar answered Oct 28 '22 17:10

Shrewd


Try instead to extend Rails::Generators::Base.

This is the mechanism as given in the docs:

"Each public method in the generator is executed when a generator is invoked"

so

class DbGenerator < Rails::Generators::Base
  source_root File.expand_path('../../../../db', __FILE__)

  def copy_seeds_file
    copy_file 'seeds.rb', 'db/seeds.rb'
  end

  def copy_seeds_dir
    Dir.foreach seeds_dir do |file|
      copy_file "seeds/#{file}", "db/seeds/#{file}"  unless file.match /^\./
    end
  end

  def seeds_dir
    File.expand_path 'seeds', self.class.source_root
  end
end

This approach will allow all gem-based seed data to copy into the app dir for the db:seed run

like image 21
New Alexandria Avatar answered Oct 28 '22 18:10

New Alexandria