The db:seed rake task in Rails is a nice addition and we use it a lot. The trouble is, you end up writing a lot of redundant code to check if records exist and stuff like that. Not very DRY, not very Rails.
Seed-Fu is a nice plugin that works very well, but it replaces the new db:seed rake task, and this solution is far more light-weight. You add another file to your db folder, seeds-helper.rb, and just require it at the top of seeds.rb.
Here’s the contents of seeds-helper.rb:
class SeedsHelper def self.seed(model_class, *keys, &block) s = SeedsHelper.new(model_class) s.parse_keys(*keys) yield s s.plant end def initialize(model_class) @model_class = model_class @keys = [] @data = {} end def parse_keys(*keys) keys = [:id] if keys.empty? keys.each do |key| raise "'#{key}' is not defined in #{@model_class}" unless @model_class.column_names.include?(key.to_s) @keys << key.to_sym end end def plant r = find_record @data.each do |key, value| r.send("#{key}=", value) end raise "Error Seeding: #{r.inspect}" unless r.save(false) puts r.inspect return r end def find_record results = @model_class.find(:all, :conditions => conditions_hash) if results.any? return results.first else return @model_class.new end end def conditions_hash @keys.inject({}) {|a, c| a[c] = @data[c]; a } end def method_missing(method_name, *args) if args.size == 1 and (match = method_name.to_s.match(/(.*)=$/)) @data[match[1].to_sym] = args[0] else super end end end class ActiveRecord::Base def self.seed(*keys, &block) SeedsHelper.seed(self, *keys, &block) end end
You can now use the seed-fu magic in seeds.rb:
require 'db/seeds_helper.rb' Account.seed(:username) do |t| t.username = "adrian.oconnor" t.name = "Adrian O'Connor" end
The active record model object is extended with a seed method. This takes a list of symbols that act as the key — if the values passed in match the keys in an existing record, it’ll replace it, otherwise it’ll create a new record. Pretty clever stuff.
If you like this, you should definitely check the full seed-fu plugin. You can find it here: http://github.com/mbleigh/seed-fu. I just like having a single additional file that is only used by seeds.rb.
Tags: Uncategorized
