muding 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +11 -0
- data/MANIFEST +77 -0
- data/MIT-LICENSE +22 -0
- data/README +21 -0
- data/bin/console +4 -0
- data/bin/destroy +4 -0
- data/bin/generate +4 -0
- data/bin/muding +16 -0
- data/bin/server +5 -0
- data/configs/boot.rb +4 -0
- data/configs/databases/mysql.yml +47 -0
- data/configs/databases/oracle.yml +30 -0
- data/configs/databases/postgresql.yml +44 -0
- data/configs/databases/sqlite2.yml +16 -0
- data/configs/databases/sqlite3.yml +16 -0
- data/doc/README_FOR_MUD +3 -0
- data/fresh_rakefile +4 -0
- data/helpers/mud.rb +8 -0
- data/helpers/mud_helper.rb +4 -0
- data/helpers/test_helper.rb +29 -0
- data/lib/acts/container.rb +70 -0
- data/lib/acts/expireable.rb +82 -0
- data/lib/commands/destroy.rb +7 -0
- data/lib/commands/generate.rb +7 -0
- data/lib/commands/server.rb +45 -0
- data/lib/commands/update.rb +5 -0
- data/lib/controller.rb +132 -0
- data/lib/handle.rb +42 -0
- data/lib/model.rb +11 -0
- data/lib/muding.rb +46 -0
- data/lib/muding_generator.rb +22 -0
- data/lib/muding_generator/base.rb +162 -0
- data/lib/muding_generator/commands.rb +519 -0
- data/lib/muding_generator/generators/applications/app/USAGE +14 -0
- data/lib/muding_generator/generators/applications/app/app_generator.rb +132 -0
- data/lib/muding_generator/generators/components/controller/USAGE +30 -0
- data/lib/muding_generator/generators/components/controller/controller_generator.rb +38 -0
- data/lib/muding_generator/generators/components/controller/templates/controller.rb +7 -0
- data/lib/muding_generator/generators/components/controller/templates/functional_test.rb +18 -0
- data/lib/muding_generator/generators/components/controller/templates/helper.rb +2 -0
- data/lib/muding_generator/generators/components/controller/templates/view.rhtml +2 -0
- data/lib/muding_generator/generators/components/migration/USAGE +14 -0
- data/lib/muding_generator/generators/components/migration/migration_generator.rb +7 -0
- data/lib/muding_generator/generators/components/migration/templates/migration.rb +7 -0
- data/lib/muding_generator/generators/components/model/USAGE +19 -0
- data/lib/muding_generator/generators/components/model/model_generator.rb +34 -0
- data/lib/muding_generator/generators/components/model/templates/fixtures.yml +5 -0
- data/lib/muding_generator/generators/components/model/templates/migration.rb +11 -0
- data/lib/muding_generator/generators/components/model/templates/model.rb +2 -0
- data/lib/muding_generator/generators/components/model/templates/unit_test.rb +10 -0
- data/lib/muding_generator/lookup.rb +210 -0
- data/lib/muding_generator/manifest.rb +53 -0
- data/lib/muding_generator/options.rb +140 -0
- data/lib/muding_generator/scripts.rb +83 -0
- data/lib/muding_generator/scripts/destroy.rb +7 -0
- data/lib/muding_generator/scripts/generate.rb +7 -0
- data/lib/muding_generator/scripts/update.rb +12 -0
- data/lib/muding_generator/simple_logger.rb +46 -0
- data/lib/muding_generator/spec.rb +44 -0
- data/lib/ruby_version_check.rb +12 -0
- data/lib/tasks/migrate.rake +33 -0
- metadata +149 -0
@@ -0,0 +1,53 @@
|
|
1
|
+
module Muding
|
2
|
+
module Generator
|
3
|
+
|
4
|
+
# Manifest captures the actions a generator performs. Instantiate
|
5
|
+
# a manifest with an optional target object, hammer it with actions,
|
6
|
+
# then replay or rewind on the object of your choice.
|
7
|
+
#
|
8
|
+
# Example:
|
9
|
+
# manifest = Manifest.new { |m|
|
10
|
+
# m.make_directory '/foo'
|
11
|
+
# m.create_file '/foo/bar.txt'
|
12
|
+
# }
|
13
|
+
# manifest.replay(creator)
|
14
|
+
# manifest.rewind(destroyer)
|
15
|
+
class Manifest
|
16
|
+
attr_reader :target
|
17
|
+
|
18
|
+
# Take a default action target. Yield self if block given.
|
19
|
+
def initialize(target = nil)
|
20
|
+
@target, @actions = target, []
|
21
|
+
yield self if block_given?
|
22
|
+
end
|
23
|
+
|
24
|
+
# Record an action.
|
25
|
+
def method_missing(action, *args, &block)
|
26
|
+
@actions << [action, args, block]
|
27
|
+
end
|
28
|
+
|
29
|
+
# Replay recorded actions.
|
30
|
+
def replay(target = nil)
|
31
|
+
send_actions(target || @target, @actions)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Rewind recorded actions.
|
35
|
+
def rewind(target = nil)
|
36
|
+
send_actions(target || @target, @actions.reverse)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Erase recorded actions.
|
40
|
+
def erase
|
41
|
+
@actions = []
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
def send_actions(target, actions)
|
46
|
+
actions.each do |method, args, block|
|
47
|
+
target.send(method, *args, &block)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
module Muding
|
4
|
+
module Generator
|
5
|
+
module Options
|
6
|
+
def self.append_features(base)
|
7
|
+
super
|
8
|
+
base.extend(ClassMethods)
|
9
|
+
class << base
|
10
|
+
if respond_to?(:inherited)
|
11
|
+
alias_method :inherited_without_options, :inherited
|
12
|
+
end
|
13
|
+
alias_method :inherited, :inherited_with_options
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
module ClassMethods
|
18
|
+
def inherited_with_options(sub)
|
19
|
+
inherited_without_options(sub) if respond_to?(:inherited_without_options)
|
20
|
+
sub.extend(Muding::Generator::Options::ClassMethods)
|
21
|
+
end
|
22
|
+
|
23
|
+
def mandatory_options(options = nil)
|
24
|
+
if options
|
25
|
+
write_inheritable_attribute(:mandatory_options, options)
|
26
|
+
else
|
27
|
+
read_inheritable_attribute(:mandatory_options) or write_inheritable_attribute(:mandatory_options, {})
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def default_options(options = nil)
|
32
|
+
if options
|
33
|
+
write_inheritable_attribute(:default_options, options)
|
34
|
+
else
|
35
|
+
read_inheritable_attribute(:default_options) or write_inheritable_attribute(:default_options, {})
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Merge together our class options. In increasing precedence:
|
40
|
+
# default_options (class default options)
|
41
|
+
# runtime_options (provided as argument)
|
42
|
+
# mandatory_options (class mandatory options)
|
43
|
+
def full_options(runtime_options = {})
|
44
|
+
default_options.merge(runtime_options).merge(mandatory_options)
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
# Each instance has an options hash that's populated by #parse.
|
50
|
+
def options
|
51
|
+
@options ||= {}
|
52
|
+
end
|
53
|
+
attr_writer :options
|
54
|
+
|
55
|
+
protected
|
56
|
+
# Convenient access to class mandatory options.
|
57
|
+
def mandatory_options
|
58
|
+
self.class.mandatory_options
|
59
|
+
end
|
60
|
+
|
61
|
+
# Convenient access to class default options.
|
62
|
+
def default_options
|
63
|
+
self.class.default_options
|
64
|
+
end
|
65
|
+
|
66
|
+
# Merge together our instance options. In increasing precedence:
|
67
|
+
# default_options (class default options)
|
68
|
+
# options (instance options)
|
69
|
+
# runtime_options (provided as argument)
|
70
|
+
# mandatory_options (class mandatory options)
|
71
|
+
def full_options(runtime_options = {})
|
72
|
+
self.class.full_options(options.merge(runtime_options))
|
73
|
+
end
|
74
|
+
|
75
|
+
# Parse arguments into the options hash. Classes may customize
|
76
|
+
# parsing behavior by overriding these methods:
|
77
|
+
# #banner Usage: ./script/generate [options]
|
78
|
+
# #add_options! Options:
|
79
|
+
# some options..
|
80
|
+
# #add_general_options! General Options:
|
81
|
+
# general options..
|
82
|
+
def parse!(args, runtime_options = {})
|
83
|
+
self.options = {}
|
84
|
+
|
85
|
+
@option_parser = OptionParser.new do |opt|
|
86
|
+
opt.banner = banner
|
87
|
+
add_options!(opt)
|
88
|
+
add_general_options!(opt)
|
89
|
+
opt.parse!(args)
|
90
|
+
end
|
91
|
+
|
92
|
+
return args
|
93
|
+
ensure
|
94
|
+
self.options = full_options(runtime_options)
|
95
|
+
end
|
96
|
+
|
97
|
+
# Raise a usage error. Override usage_message to provide a blurb
|
98
|
+
# after the option parser summary.
|
99
|
+
def usage(message = usage_message)
|
100
|
+
raise UsageError, "#{@option_parser}\n#{message}"
|
101
|
+
end
|
102
|
+
|
103
|
+
def usage_message
|
104
|
+
''
|
105
|
+
end
|
106
|
+
|
107
|
+
# Override with your own usage banner.
|
108
|
+
def banner
|
109
|
+
"Usage: #{$0} [options]"
|
110
|
+
end
|
111
|
+
|
112
|
+
# Override to add your options to the parser:
|
113
|
+
# def add_options!(opt)
|
114
|
+
# opt.on('-v', '--verbose') { |value| options[:verbose] = value }
|
115
|
+
# end
|
116
|
+
def add_options!(opt)
|
117
|
+
end
|
118
|
+
|
119
|
+
# Adds general options like -h and --quiet. Usually don't override.
|
120
|
+
def add_general_options!(opt)
|
121
|
+
opt.separator ''
|
122
|
+
opt.separator 'General Options:'
|
123
|
+
|
124
|
+
opt.on('-p', '--pretend', 'Run but do not make any changes.') { |v| options[:pretend] = v }
|
125
|
+
opt.on('-f', '--force', 'Overwrite files that already exist.') { options[:collision] = :force }
|
126
|
+
opt.on('-s', '--skip', 'Skip files that already exist.') { options[:collision] = :skip }
|
127
|
+
opt.on('-q', '--quiet', 'Suppress normal output.') { |v| options[:quiet] = v }
|
128
|
+
opt.on('-t', '--backtrace', 'Debugging: show backtrace on errors.') { |v| options[:backtrace] = v }
|
129
|
+
opt.on('-h', '--help', 'Show this help message.') { |v| options[:help] = v }
|
130
|
+
opt.on('-c', '--svn', 'Modify files with subversion. (Note: svn must be in path)') do
|
131
|
+
options[:svn] = `svn status`.inject({}) do |opt, e|
|
132
|
+
opt[e.chomp[7..-1]] = true
|
133
|
+
opt
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/options'
|
2
|
+
|
3
|
+
module Muding
|
4
|
+
module Generator
|
5
|
+
module Scripts
|
6
|
+
|
7
|
+
# Generator scripts handle command-line invocation. Each script
|
8
|
+
# responds to an invoke! class method which handles option parsing
|
9
|
+
# and generator invocation.
|
10
|
+
class Base
|
11
|
+
include Options
|
12
|
+
default_options :collision => :ask, :quiet => false
|
13
|
+
|
14
|
+
# Run the generator script. Takes an array of unparsed arguments
|
15
|
+
# and a hash of parsed arguments, takes the generator as an option
|
16
|
+
# or first remaining argument, and invokes the requested command.
|
17
|
+
def run(args = [], runtime_options = {})
|
18
|
+
begin
|
19
|
+
parse!(args.dup, runtime_options)
|
20
|
+
rescue OptionParser::InvalidOption => e
|
21
|
+
# Don't cry, script. Generators want what you think is invalid.
|
22
|
+
end
|
23
|
+
|
24
|
+
# Generator name is the only required option.
|
25
|
+
unless options[:generator]
|
26
|
+
usage if args.empty?
|
27
|
+
options[:generator] ||= args.shift
|
28
|
+
end
|
29
|
+
|
30
|
+
# Look up generator instance and invoke command on it.
|
31
|
+
Muding::Generator::Base.instance(options[:generator], args, options).command(options[:command]).invoke!
|
32
|
+
rescue => e
|
33
|
+
puts e
|
34
|
+
puts " #{e.backtrace.join("\n ")}\n" if options[:backtrace]
|
35
|
+
raise SystemExit
|
36
|
+
end
|
37
|
+
|
38
|
+
protected
|
39
|
+
# Override with your own script usage banner.
|
40
|
+
def banner
|
41
|
+
"Usage: #{$0} [options] generator [args]"
|
42
|
+
end
|
43
|
+
|
44
|
+
def usage_message
|
45
|
+
usage = "\nInstalled Generators\n"
|
46
|
+
Muding::Generator::Base.sources.each do |source|
|
47
|
+
label = source.label.to_s.capitalize
|
48
|
+
names = source.names
|
49
|
+
usage << " #{label}: #{names.join(', ')}\n" unless names.empty?
|
50
|
+
end
|
51
|
+
|
52
|
+
usage << <<end_blurb
|
53
|
+
|
54
|
+
More are available at http://rubyonrails.org/show/Generators
|
55
|
+
1. Download, for example, login_generator.zip
|
56
|
+
2. Unzip to directory #{Dir.user_home}/.rails/generators/login
|
57
|
+
to use the generator with all your Rails apps
|
58
|
+
end_blurb
|
59
|
+
|
60
|
+
if Object.const_defined?(:RAILS_ROOT)
|
61
|
+
usage << <<end_blurb
|
62
|
+
or to #{File.expand_path(RAILS_ROOT)}/generators/login
|
63
|
+
to use with this app only.
|
64
|
+
end_blurb
|
65
|
+
end
|
66
|
+
|
67
|
+
usage << <<end_blurb
|
68
|
+
3. Run generate with no arguments for usage information
|
69
|
+
#{$0} login
|
70
|
+
|
71
|
+
Generator gems are also available:
|
72
|
+
1. gem search -r generator
|
73
|
+
2. gem install login_generator
|
74
|
+
3. #{$0} login
|
75
|
+
|
76
|
+
end_blurb
|
77
|
+
return usage
|
78
|
+
end
|
79
|
+
end # Base
|
80
|
+
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Muding
|
2
|
+
module Generator
|
3
|
+
class SimpleLogger # :nodoc:
|
4
|
+
attr_reader :out
|
5
|
+
attr_accessor :quiet
|
6
|
+
|
7
|
+
def initialize(out = $stdout)
|
8
|
+
@out = out
|
9
|
+
@quiet = false
|
10
|
+
@level = 0
|
11
|
+
end
|
12
|
+
|
13
|
+
def log(status, message, &block)
|
14
|
+
@out.print("%12s %s%s\n" % [status, ' ' * @level, message]) unless quiet
|
15
|
+
indent(&block) if block_given?
|
16
|
+
end
|
17
|
+
|
18
|
+
def indent(&block)
|
19
|
+
@level += 1
|
20
|
+
if block_given?
|
21
|
+
begin
|
22
|
+
block.call
|
23
|
+
ensure
|
24
|
+
outdent
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def outdent
|
30
|
+
@level -= 1
|
31
|
+
if block_given?
|
32
|
+
begin
|
33
|
+
block.call
|
34
|
+
ensure
|
35
|
+
indent
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
def method_missing(method, *args, &block)
|
42
|
+
log(method.to_s, args.first, &block)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Muding
|
2
|
+
module Generator
|
3
|
+
# A spec knows where a generator was found and how to instantiate it.
|
4
|
+
# Metadata include the generator's name, its base path, and the source
|
5
|
+
# which yielded it (PathSource, GemSource, etc.)
|
6
|
+
class Spec
|
7
|
+
attr_reader :name, :path, :source
|
8
|
+
|
9
|
+
def initialize(name, path, source)
|
10
|
+
@name, @path, @source = name, path, source
|
11
|
+
end
|
12
|
+
|
13
|
+
# Look up the generator class. Require its class file, find the class
|
14
|
+
# in ObjectSpace, tag it with this spec, and return.
|
15
|
+
def klass
|
16
|
+
unless @klass
|
17
|
+
require class_file
|
18
|
+
@klass = lookup_class
|
19
|
+
@klass.spec = self
|
20
|
+
end
|
21
|
+
@klass
|
22
|
+
end
|
23
|
+
|
24
|
+
def class_file
|
25
|
+
"#{path}/#{name}_generator.rb"
|
26
|
+
end
|
27
|
+
|
28
|
+
def class_name
|
29
|
+
"#{name.camelize}Generator"
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
# Search for the first Class descending from Rails::Generator::Base
|
34
|
+
# whose name matches the requested class name.
|
35
|
+
def lookup_class
|
36
|
+
ObjectSpace.each_object(Class) do |obj|
|
37
|
+
return obj if obj.ancestors.include?(Muding::Generator::Base) and
|
38
|
+
obj.name.split('::').last == class_name
|
39
|
+
end
|
40
|
+
raise NameError, "Missing #{class_name} class in #{class_file}"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
min_release = "1.8.4 (2005-11-01)"
|
2
|
+
ruby_release = "#{RUBY_VERSION} (#{RUBY_RELEASE_DATE})"
|
3
|
+
|
4
|
+
if ruby_release < min_release
|
5
|
+
abort <<-end_message
|
6
|
+
|
7
|
+
muding requires Ruby version #{min_release} or later.
|
8
|
+
You're running #{ruby_release}; please upgrade to continue.
|
9
|
+
|
10
|
+
end_message
|
11
|
+
end
|
12
|
+
|
@@ -0,0 +1,33 @@
|
|
1
|
+
#what environment are we working with?
|
2
|
+
task :environment do
|
3
|
+
require File.join('lib', 'muding')
|
4
|
+
end
|
5
|
+
|
6
|
+
task :migrate do
|
7
|
+
Rake::Task["db:migrate"].invoke
|
8
|
+
end
|
9
|
+
|
10
|
+
namespace :db do
|
11
|
+
desc "Migrate the database through scripts in db/migrate. Target specific version with VERSION=x"
|
12
|
+
task :migrate => :environment do
|
13
|
+
ActiveRecord::Migrator.migrate("db/migrate/", ENV["VERSION"] ? ENV["VERSION"].to_i : nil)
|
14
|
+
Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby
|
15
|
+
end
|
16
|
+
|
17
|
+
namespace :schema do
|
18
|
+
desc "Create a db/schema.rb file that can be portably used against any DB supported by AR"
|
19
|
+
task :dump => :environment do
|
20
|
+
require 'active_record/schema_dumper'
|
21
|
+
File.open(ENV['SCHEMA'] || "db/schema.rb", "w") do |file|
|
22
|
+
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
desc "Load a schema.rb file into the database"
|
27
|
+
task :load => :environment do
|
28
|
+
file = ENV['SCHEMA'] || "db/schema.rb"
|
29
|
+
load(file)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|