Skip to content

Commit e64acb3

Browse files
committed
Initial commit.
0 parents  commit e64acb3

18 files changed

+635
-0
lines changed

MIT-LICENSE

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
Copyright (c) 2009 Mark W. Foster, fosterinfo[z]gmail.com (replace [z] with @)
2+
3+
Permission is hereby granted, free of charge, to any person obtaining
4+
a copy of this software and associated documentation files (the
5+
"Software"), to deal in the Software without restriction, including
6+
without limitation the rights to use, copy, modify, merge, publish,
7+
distribute, sublicense, and/or sell copies of the Software, and to
8+
permit persons to whom the Software is furnished to do so, subject to
9+
the following conditions:
10+
11+
The above copyright notice and this permission notice shall be
12+
included in all copies or substantial portions of the Software.
13+
14+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

README

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
seeded-generation plugin by Mark W. Foster
2+
==========================================
3+
4+
This plugin extends any model and scaffold generators to stub individual seeds
5+
files that correspond to a model and its module directory structure. It also
6+
overrides rake db:seed so that models can be individually seeded
7+
using rake db:seed with the model name as an option. The plugin also includes
8+
a generator that just stubs seeds files for existing models.
9+
10+
The db/seeds.rb file is updated when models are generated to require the individual
11+
model seeds files so that rake db:seed executes all the required seed files. Extended
12+
model and scaffold generators include an option --skip-seeds that blocks stubbing
13+
a seeds file for the model and an option --seeds-only that only stubs a
14+
seeds file for the model.
15+
16+
Two default seeded generators are built as part of the install:
17+
18+
seeded_model and seeded_scaffold.
19+
20+
Type script/generate seeded, script/generate seeds_for, script/seeded_model or
21+
script/seeded_scaffold for more usage information.
22+
23+
Uninstalling the plugin leaves any extended generators and the db:seed
24+
override working. To clear all plugin functionality, refer to the
25+
notes in the ../lib/seeded_generation folder after uninstalling the plugin.
26+
27+
The plugin also installs functionality from the plugin OverrideRakeTask
28+
by Eugene Bolshakov found at: git://github.com/eugene bolshakov/override_rake_task.git
29+
30+
and an updated version of ActiveRecord::Base.create_or_update by Michael Bleigh
31+
32+
http://www.intridea.com/2008/2/19/activerecord-base-create_or_update-on-steroids-2?blog=company
33+
34+
Example
35+
=======
36+
37+
script/generate seeded my_model_generator
38+
39+
creates a new seeded_my_model_generator generator that can then be used just like the
40+
my_model_generator generator it is based on in the following fashion:
41+
42+
script/generate seeded_my_model_generator MyModule::MyModel
43+
44+
creates generates all the standard model directories and stubs and includes
45+
the stub ../db/seeds/my_module/my_model_seeds.rb and adds
46+
require 'my_module/my_model_seeds' to the db/seeds.rb file.
47+
48+
script/generate seeded_my_model_generator MyModule::MyModel --skip-seeds
49+
50+
is just the base generator.
51+
52+
script/generate seeded_my_model_generator MyModule::MyModel --only-seeds
53+
54+
only adds the file ../db/seeds/my_module/my_model_seeds.rb and adds
55+
require 'my_module/my_model_seeds' to the db/seeds.rb file.
56+
57+
This has the same functionality of the included generator seeds_for:
58+
59+
script/generate seeds_for MyModule::MyModel
60+
61+
which creates only a file db/seeds/my_module/my_model_seeds.rb and
62+
adds a require statement to seeds.db.
63+
64+
rake db:seed runs all seed files required in db/seeds.rb and
65+
any other seed code there.
66+
67+
rake db:seed MODELS=MyModule1::MyModel1, MyModule1::MyModel2 only loads seeds for the
68+
specified models if they have corresponding seeds.rb files generated.
69+
70+
Copyright (c) 2009 Mark W. Foster, released under the MIT license
71+
fosterinfo[z]gmail.com (replace [z] with @)

Rakefile

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
require 'rake'
2+
require 'rake/testtask'
3+
require 'rake/rdoctask'
4+
5+
desc 'Default: run unit tests.'
6+
task :default => :test
7+
8+
desc 'Test the seeded_generator plugin.'
9+
Rake::TestTask.new(:test) do |t|
10+
t.libs << 'lib'
11+
t.libs << 'test'
12+
t.pattern = 'test/**/*_test.rb'
13+
t.verbose = true
14+
end
15+
16+
desc 'Generate documentation for the seeded_generator plugin.'
17+
Rake::RDocTask.new(:rdoc) do |rdoc|
18+
rdoc.rdoc_dir = 'rdoc'
19+
rdoc.title = 'SeededGenerator'
20+
rdoc.options << '--line-numbers' << '--inline-source'
21+
rdoc.rdoc_files.include('README')
22+
rdoc.rdoc_files.include('lib/**/*.rb')
23+
end

generators/seeded/USAGE

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
Description:
2+
Extends an existing model or scaffold generator to stub out
3+
an individual seeds file for its model and adds it as a
4+
required file in seeds.db. Pass the underscored generator
5+
name to be converted to a seeded generator.
6+
7+
Examples:
8+
`./script/generate seeded model`
9+
10+
creates a seeded_model generator.
11+
12+
`./script/generate seeded scaffold`
13+
14+
creates a seeded_scaffold generator.
15+
16+
`./script/generate seeded my_model_generator`
17+
18+
creates a seeded_my_model_generator.
19+
20+
`./script/generate seeded my_scaffold_generator`
21+
22+
creates a seeded_my_scaffold_generator.
+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# SeededGenerator Commands
2+
require 'rails_generator/base'
3+
4+
# Name methods
5+
Rails::Generator::NamedBase.class_eval do
6+
7+
#The path to the original generator.
8+
def original_generator_path
9+
# Only calculate the original path once
10+
unless @original_path
11+
#Find the source of the original generator
12+
begin
13+
@original_path = Rails::Generator::Base.instance(file_name, ['no_options'], {}).spec.path
14+
rescue
15+
raise_missing_generator(file_name)
16+
end
17+
end
18+
@original_path
19+
end
20+
21+
def template_path
22+
File.join('lib/generators', "seeded_#{file_name}", 'templates')
23+
end
24+
25+
def generator_path
26+
File.join('lib/generators', "seeded_#{file_name}")
27+
end
28+
29+
def original_template_path
30+
File.join(original_generator_path, 'templates')
31+
end
32+
33+
private
34+
def raise_missing_generator(class_name)
35+
message = <<-end_message
36+
The generator '#{file_name}' does not exist in your application and is not used by Ruby on Rails.
37+
Please choose an alternative and run this generator again.
38+
end_message
39+
40+
raise UsageError, message
41+
end
42+
end
43+

generators/seeded/seeded_generator.rb

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# Generator that modifies existing generators to create individual
2+
# model seeds stubs.
3+
require File.join(File.dirname(__FILE__), 'lib/seeded_helper')
4+
class SeededGenerator < Rails::Generator::NamedBase
5+
6+
def manifest
7+
# Check for seeded generator class naming collisions.
8+
if class_name.include?('Seeded')
9+
raise "The generator #{class_name.underscore} is already seeded."
10+
end
11+
12+
record do |m|
13+
# Create generator and template directories.
14+
m.directory generator_path
15+
m.directory template_path
16+
17+
# Create generator
18+
m.template 'generator.rb', File.join(generator_path, "seeded_#{file_name}_generator.rb")
19+
20+
# Copy seeded generator templates
21+
m.file 'seeds.rb', File.join(template_path, 'seeds.rb')
22+
23+
# Copy base generator templates
24+
Dir.foreach(original_template_path) do |f|
25+
m.file file_name + ':' + f, File.join(template_path, f), :collision => :skip unless File.directory?(f)
26+
end
27+
28+
# Copy the usage file
29+
m.file file_name + ':' + '../USAGE', File.join(generator_path, 'USAGE'), :collision => :skip
30+
31+
unless options[:command] == :destroy
32+
# Update it if it is a scaffold USAGE statement
33+
m.gsub_file File.join(generator_path,'USAGE'), "from model and migration" do
34+
"from model, migration and seeds"
35+
end
36+
37+
# Update it if it is a model USAGE statement
38+
m.gsub_file File.join(generator_path,'USAGE'), ", and a migration in\n db/migrate." do
39+
", a migration in\n db/migrate, and a seed in db/seeds."
40+
end
41+
42+
m.gsub_file File.join(generator_path,'USAGE'), "creates an Account model, test, fixture, and migration:" do
43+
"creates an Account model, test, fixture, migration, and seeds:"
44+
end
45+
46+
m.gsub_file File.join(generator_path,'USAGE'), "Migration: db/migrate/XXX_add_accounts.rb" do
47+
"Migration: db/migrate/XXX_add_accounts.rb\n Seeds: db/seeds/account_seeds.rb"
48+
end
49+
end
50+
end
51+
end
52+
53+
protected
54+
def banner
55+
"Usage: #{$0} seeded generator_name"
56+
end
57+
58+
end
+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Extends functionality in the <%=file_name%> generator to create model
2+
# seeds files and directories.
3+
4+
class Seeded<%=class_name%>Generator < <%=class_name%>Generator
5+
6+
default_options[:skip_seeds] = false
7+
default_options[:seeds_only] = false
8+
9+
alias base_add_options! add_options!
10+
alias base_manifest manifest
11+
12+
def manifest
13+
if !options[:seeds_only]
14+
m = base_manifest
15+
else
16+
m = record {}
17+
end
18+
unless options[:skip_seeds]
19+
# Generate the seeds stub directory mirroring the model directory structure.
20+
m.directory File.join('db/seeds', class_path)
21+
22+
# Generate the seeds stub
23+
m.template 'seeds.rb', File.join('db/seeds/', class_path, "#{file_name}_seeds.rb")
24+
end
25+
26+
# Register the seeds stub in seeds.rb at the end of the file
27+
m.gsub_file('db/seeds.rb', File.read(File.join(RAILS_ROOT, 'db/seeds.rb'))) do |s|
28+
s + "\nrequire '#{file_path}_seeds'"
29+
end if options[:command] == :create && !options[:skip_seeds]
30+
m.gsub_file('db/seeds.rb', /\nrequire '#{file_path}_seeds'/mi, '') if options[:command] == :destroy
31+
m
32+
end
33+
34+
protected
35+
def banner
36+
"Usage: #{$0} seeded_<%=file_name%> ModelName [field:type, field:type]"
37+
end
38+
39+
def add_options!(opt)
40+
base_add_options!(opt)
41+
opt.on("--skip-seeds",
42+
"Don't generate a seeds file for this model.") { |v| options[:skip_seeds] = v }
43+
opt.on("--seeds-only",
44+
"Only generate a seeds file for this model.") { |v| options[:seeds_only] = v }
45+
end
46+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#Creates commands accessed by the manifest method in seeded generators.
2+
Rails::Generator::Commands::Create.class_eval do
3+
def require_seeds(seed_path)
4+
logger.seeds "#{seed_path}_seeds"
5+
unless options[:pretend]
6+
seed_file = File.join(Rails.root, 'db', 'seeds.rb')
7+
#Add to the end of the file
8+
File.open(seed_file, 'a+') { |f| f.write("\nrequire '#{seed_path}_seeds'") }
9+
end
10+
end
11+
end
12+
13+
Rails::Generator::Commands::Destroy.class_eval do
14+
include FileUtils
15+
def require_seeds(*seed_path)
16+
look_for = "\nrequire '#{seed_path}_seeds'"
17+
logger.seeds "#{seed_path}_seeds"
18+
gsub_file 'db/seeds.rb', /(#{look_for})/mi, ''
19+
end
20+
end
21+
22+
Rails::Generator::Commands::List.class_eval do
23+
def require_seeds(*seed_path)
24+
logger.seeds "#{seed_path}_seeds"
25+
end
26+
end
27+
28+
# New name
29+
Rails::Generator::NamedBase.class_eval do
30+
def seeds_path
31+
class_path.empty? ? file_name : File.join(class_path, file_name)
32+
end
33+
end

generators/seeded/templates/seeds.rb

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# This file should contain all the record creation needed to seed the database model with its default values.
2+
# The data can then be loaded with the rake db:seed (or created alongside the db with db:setup).
3+
#
4+
# Examples (with ActiveRecord validation):
5+
#
6+
# Using controllers:
7+
# cities = City.create([{ :name => 'Chicago' }, { :name => 'Copenhagen' }])
8+
# <%=class_name%>.create(:name => 'Daley', :city => cities.first)
9+
#
10+
# Using models:
11+
# [ {:name => 'Bob', :city => 'Seattle '},
12+
# {:name => 'George', :city => 'Zurich'} ].each do |seed|
13+
# <%=class_name%>.create_or_update_by_name(seed)
14+
# end
15+
#
16+
# { 'employee' => ['Robert', 'Sales'],
17+
# 'manager' => ['Renee', 'Manufacturing'] }.each_pair do |key, val|
18+
# <%=class_name%>.create_or_update_by_key(:key => key, :name => val[0], :dept => val[1])
19+
# end
20+
#
21+
# Using comma delimited file with ActiveRecord validation:
22+
# File.read(my_text_file).split("\n").each do |seed|
23+
# val = seed.split(",")
24+
# <%=class_name%>.create_or_update_by_name(:name => val[0], :dept => val[1])
25+
# end
26+
#
27+
# To seed this model individually, run rake db:seed MODELS=<%=class_name%>
28+
#
29+
require '<%=file_path%>'

generators/seeds_for/USAGE

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
Description:
2+
Stubs out a model seeds file in the directory db/seeds and adds
3+
it as a required file in ../db/seeds.db. Pass the model name,
4+
either CamelCased or under_scored.
5+
6+
Examples:
7+
`./script/generate seed_model account`
8+
9+
creates an Account seeds file:
10+
Seeds: db/seeds/account_seeds.rb
11+
12+
`./script/generate model post title:string body:text published:boolean`
13+
14+
creates a post_seeds file.

0 commit comments

Comments
 (0)