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.
Files changed (62) hide show
  1. data/CHANGELOG +11 -0
  2. data/MANIFEST +77 -0
  3. data/MIT-LICENSE +22 -0
  4. data/README +21 -0
  5. data/bin/console +4 -0
  6. data/bin/destroy +4 -0
  7. data/bin/generate +4 -0
  8. data/bin/muding +16 -0
  9. data/bin/server +5 -0
  10. data/configs/boot.rb +4 -0
  11. data/configs/databases/mysql.yml +47 -0
  12. data/configs/databases/oracle.yml +30 -0
  13. data/configs/databases/postgresql.yml +44 -0
  14. data/configs/databases/sqlite2.yml +16 -0
  15. data/configs/databases/sqlite3.yml +16 -0
  16. data/doc/README_FOR_MUD +3 -0
  17. data/fresh_rakefile +4 -0
  18. data/helpers/mud.rb +8 -0
  19. data/helpers/mud_helper.rb +4 -0
  20. data/helpers/test_helper.rb +29 -0
  21. data/lib/acts/container.rb +70 -0
  22. data/lib/acts/expireable.rb +82 -0
  23. data/lib/commands/destroy.rb +7 -0
  24. data/lib/commands/generate.rb +7 -0
  25. data/lib/commands/server.rb +45 -0
  26. data/lib/commands/update.rb +5 -0
  27. data/lib/controller.rb +132 -0
  28. data/lib/handle.rb +42 -0
  29. data/lib/model.rb +11 -0
  30. data/lib/muding.rb +46 -0
  31. data/lib/muding_generator.rb +22 -0
  32. data/lib/muding_generator/base.rb +162 -0
  33. data/lib/muding_generator/commands.rb +519 -0
  34. data/lib/muding_generator/generators/applications/app/USAGE +14 -0
  35. data/lib/muding_generator/generators/applications/app/app_generator.rb +132 -0
  36. data/lib/muding_generator/generators/components/controller/USAGE +30 -0
  37. data/lib/muding_generator/generators/components/controller/controller_generator.rb +38 -0
  38. data/lib/muding_generator/generators/components/controller/templates/controller.rb +7 -0
  39. data/lib/muding_generator/generators/components/controller/templates/functional_test.rb +18 -0
  40. data/lib/muding_generator/generators/components/controller/templates/helper.rb +2 -0
  41. data/lib/muding_generator/generators/components/controller/templates/view.rhtml +2 -0
  42. data/lib/muding_generator/generators/components/migration/USAGE +14 -0
  43. data/lib/muding_generator/generators/components/migration/migration_generator.rb +7 -0
  44. data/lib/muding_generator/generators/components/migration/templates/migration.rb +7 -0
  45. data/lib/muding_generator/generators/components/model/USAGE +19 -0
  46. data/lib/muding_generator/generators/components/model/model_generator.rb +34 -0
  47. data/lib/muding_generator/generators/components/model/templates/fixtures.yml +5 -0
  48. data/lib/muding_generator/generators/components/model/templates/migration.rb +11 -0
  49. data/lib/muding_generator/generators/components/model/templates/model.rb +2 -0
  50. data/lib/muding_generator/generators/components/model/templates/unit_test.rb +10 -0
  51. data/lib/muding_generator/lookup.rb +210 -0
  52. data/lib/muding_generator/manifest.rb +53 -0
  53. data/lib/muding_generator/options.rb +140 -0
  54. data/lib/muding_generator/scripts.rb +83 -0
  55. data/lib/muding_generator/scripts/destroy.rb +7 -0
  56. data/lib/muding_generator/scripts/generate.rb +7 -0
  57. data/lib/muding_generator/scripts/update.rb +12 -0
  58. data/lib/muding_generator/simple_logger.rb +46 -0
  59. data/lib/muding_generator/spec.rb +44 -0
  60. data/lib/ruby_version_check.rb +12 -0
  61. data/lib/tasks/migrate.rake +33 -0
  62. metadata +149 -0
@@ -0,0 +1,82 @@
1
+ #TODO: rewrite this class to allow individual objects to have their own configurations..
2
+ module Acts #:nodoc:
3
+ module Expireable
4
+ def self.included(base) # :nodoc:
5
+ base.extend ClassMethods
6
+ end
7
+
8
+ module ClassMethods
9
+ def acts_as_expireable(options = {})
10
+ config = {:respawn => false, :lifespan => 10.seconds, :delay=> 0.seconds}
11
+ config.update options if options.is_a?(Hash)
12
+
13
+ unless expireable? # don't let AR call this twice
14
+ cattr_accessor :respawn, :lifespan, :delay
15
+ self.respawn = config[:respawn]
16
+ self.lifespan = config[:lifespan]
17
+ self.delay = config[:delay]
18
+ Thread.new do
19
+ while true
20
+
21
+ #puts "Checking Expireables."
22
+ #self.find(:all).each do |s|
23
+ # puts "Expires at:" + s.expires_at.to_s
24
+ # s.destroy
25
+ #end
26
+
27
+ puts Time.now.to_s
28
+
29
+ self.find(:all, :conditions => ["spawn_at <= ? and expires_at >= ?", Time.now, Time.now]).each do |expireable|
30
+ expireable.spawn
31
+ end
32
+ self.find(:all, :conditions => ["expires_at <= ?", Time.now]).each do |expireable|
33
+ expireable.expire
34
+ end
35
+ sleep 0.5
36
+ end
37
+ end
38
+ end
39
+ before_create :setup_expireable
40
+ include InstanceMethods
41
+ rescue
42
+ puts $!
43
+ end
44
+
45
+ def expireable?
46
+ self.included_modules.include?(InstanceMethods)
47
+ end
48
+ end
49
+
50
+ module InstanceMethods #:nodoc:
51
+ def self.included(base) # :nodoc:
52
+ base.extend ClassMethods
53
+ end
54
+
55
+ def expire
56
+ self.on_expire if respond_to? :on_expire
57
+ self.destroy
58
+ if self.class.respawn
59
+ self.on_respawn if respond_to? :on_respawn
60
+ self.class.new.save
61
+ end
62
+ end
63
+
64
+ def spawn
65
+ if !spawned?
66
+ self.on_spawn if respond_to? :on_spawn
67
+ self.spawn_at = nil
68
+ save
69
+ end
70
+ end
71
+
72
+ def setup_expireable
73
+ self.expires_at = Time.now + self.class.lifespan
74
+ self.spawn_at = Time.now + self.class.delay
75
+ end
76
+
77
+ def spawned?
78
+ self.spawn_at == nil
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,7 @@
1
+ require "#{MUDING_ROOT}/config/environment"
2
+ require 'muding_generator'
3
+ require 'muding_generator/scripts/destroy'
4
+
5
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
6
+ Muding::Generator::Scripts::Destroy.new.run(ARGV)
7
+
@@ -0,0 +1,7 @@
1
+ require "#{MUDING_ROOT}/config/environment"
2
+ require 'muding_generator'
3
+ require 'muding_generator/scripts/generate'
4
+
5
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
6
+ Muding::Generator::Scripts::Generate.new.run(ARGV)
7
+
@@ -0,0 +1,45 @@
1
+ %w[socket handle].each { |lib| require lib }
2
+
3
+ log = Log4r::Logger.new 'main'
4
+ log.outputters = Log4r::Outputter.stdout
5
+
6
+ begin
7
+ server = TCPServer.new('localhost', 4000)
8
+ threads = []
9
+
10
+ #The procedures for shuting down the server
11
+ graceful_shutdown = Proc.new do
12
+ #shuting down the game right now is as simple as exiting.
13
+ #later we probably want to backup save the active records
14
+ #or something
15
+ exit
16
+ end
17
+
18
+ #what to do if our server receives a OS signal to shut down
19
+ handle_signalled_shutdown = Proc.new do |sig|
20
+ log.warn "Caught " + Signal.list.invert[sig] + " Signal... Shutting Down"
21
+ graceful_shutdown.call
22
+ end
23
+
24
+ #trap the signals we want to handle a shutdown for.
25
+ [:INT,:TERM,:KILL].each do |sig|
26
+ Signal.trap sig, handle_signalled_shutdown
27
+ end
28
+
29
+ log.info "Accepting Connections..."
30
+ while session = server.accept
31
+ threads << Thread.new(session) do |s|
32
+ begin
33
+ Handle.this session
34
+ rescue
35
+ log.error "Top Level Thread Error. You should never see this."
36
+ log.error $!
37
+ end
38
+ end
39
+ end
40
+
41
+ graceful_shutdown.call
42
+ rescue
43
+ log.fatal "Top Level Server Error. You should never see this."
44
+ log.fatal $!
45
+ end
@@ -0,0 +1,5 @@
1
+ require "#{MUDING_ROOT}/config/environment"
2
+ require 'muding_generator'
3
+ require 'muding_generator/scripts/update'
4
+ Muding::Generator::Scripts::Update.new.run(ARGV)
5
+
@@ -0,0 +1,132 @@
1
+ module Controller
2
+ Log = Log4r::Logger.new 'controller'
3
+ Log.outputters = Log4r::Outputter.stdout
4
+
5
+ class Base
6
+ attr_accessor :input, :body, :rendered
7
+ attr_accessor :new_route, :default_command, :prompt
8
+
9
+ @@before_view = {}
10
+
11
+ #route_to is the command that routes a connection's input to the
12
+ #next command controller, or default command.
13
+ #
14
+ # route_to :route =>StartController, :command=>:begin, :prompt=>">"
15
+ # This will make the user's next input goto the StartController
16
+ # with the command "begin". After rendering the command
17
+ # it will output ">" to the user.
18
+ #
19
+ # route_to :view=>"password"
20
+ #
21
+ # This will keep the user's route the same. After rendering the command
22
+ # it will output the content of the password view rendered in the context
23
+ # of the command's binding. The directory for the password view will
24
+ # be the same as the Controller.
25
+ def route_to(options={})
26
+ config = {:controller => self.class, :command => nil, :prompt => "", :view => :default}
27
+ config.update options if options.is_a?(Hash)
28
+
29
+ self.new_route = config[:controller]
30
+ self.default_command = config[:command]
31
+ self.prompt = config[:prompt] if config[:prompt] != ""
32
+ self.prompt = render_template(before_view_file) if config[:view] == :default && @@before_view[config[:command]]
33
+ end
34
+
35
+ #TODO: Implement this.
36
+ #Should jump to next controller method right away, instead of waiting for new input.
37
+ #r(302,'','Location'=>URL(*a))
38
+ #by right away I mean after the command finishes running.
39
+ def redirect_to(options={})
40
+ config = {:route => self.class, :command => nil, :prompt => "", :view => :default}
41
+ config.update options if options.is_a?(Hash)
42
+
43
+ end
44
+
45
+ def render(options = {})
46
+ raise "Double Render Error" if self.rendered
47
+
48
+ self.rendered = true
49
+ return if options[:nothing]
50
+ if options[:text]
51
+ @body = options[:text]
52
+ return
53
+ end
54
+ @body = render_template(view_file)
55
+
56
+ @body += self.prompt if self.prompt
57
+ end
58
+
59
+ def initialize(command, s = {}) #:nodoc:
60
+ @method = command.downcase
61
+ @session = s
62
+ end
63
+
64
+ def route
65
+ return self.class
66
+ end
67
+
68
+ def view_file
69
+ command_file = @method + ".rhtml"
70
+ load_and_read_file(command_file)
71
+ end
72
+
73
+ def before_view_file
74
+ command_file = @@before_view[default_command].to_s + ".rhtml"
75
+ load_and_read_file(command_file)
76
+ end
77
+
78
+ def load_and_read_file(file_name)
79
+ file = File.open(File.join(view_dir, file_name))
80
+ file.read
81
+ rescue Errno::ENOENT
82
+ puts $!
83
+ return "Could not find the proper view for this command"
84
+ end
85
+
86
+ def view_dir
87
+ File.join("mud","views",route.to_s.downcase.chomp("controller"))
88
+ end
89
+
90
+ def render_template(vf)
91
+ ERB.new(vf, nil, '-').result(binding)
92
+ end
93
+
94
+ def service(*a)
95
+ send(@method, *a) if respond_to? @method
96
+ if !self.rendered
97
+ render
98
+ end
99
+ self
100
+ end
101
+
102
+ def session()
103
+ return @session
104
+ end
105
+
106
+ def to_s
107
+ "#{@body}"
108
+ end
109
+
110
+ def Base.before_view
111
+ return @@before_view
112
+ end
113
+ end
114
+
115
+ class NotFound < Base
116
+ def get(p)
117
+ render :text=>"#{p} Could not be found."
118
+ end
119
+ end
120
+
121
+ class ServerError < Base
122
+ def get
123
+ render :text=>"Command problem, check the logs."
124
+ end
125
+ end
126
+
127
+ #Load all the controllers.
128
+ load "./mud/controllers/mud.rb"
129
+ Dir["./mud/controllers/*_controller.rb"].sort.each { |ext| load ext.to_s }
130
+ end
131
+
132
+
@@ -0,0 +1,42 @@
1
+ require 'muding'
2
+
3
+ #This class handles connections. It stores session information
4
+ #about the connection. It keeps track of where the connection is currently sending it's input to.
5
+ class Handle
6
+ Log = Log4r::Logger.new 'handle'
7
+ Log.outputters = Log4r::Outputter.stdout
8
+
9
+ @@handles = [] #All of the connections.
10
+
11
+ attr_accessor :route, :session, :default_command, :peer
12
+
13
+ def Handle.this s
14
+ @@handles << h = Handle.new(s)
15
+ h.start_handling
16
+ end
17
+
18
+ def initialize peer
19
+ self.session = {:handle=>self}
20
+ self.peer = peer
21
+ self.route = MudController
22
+ end
23
+
24
+ def start_handling
25
+ response = Muding.run("begin", self)
26
+
27
+ while true
28
+ peer.puts response.body
29
+ self.route = response.new_route if response.new_route
30
+
31
+ self.default_command = nil
32
+ self.default_command = response.default_command if response.default_command
33
+ response = Muding.run(peer.gets, self)
34
+ end
35
+ rescue Errno::EPIPE
36
+ Log.info "Connection " + self.object_id.to_s + " Severed"
37
+ end
38
+
39
+ def message(message_string)
40
+ peer.puts message_string
41
+ end
42
+ end
@@ -0,0 +1,11 @@
1
+ Dir["./lib/acts/*.rb"].sort.each { |ext| load ext.to_s }
2
+
3
+ ActiveRecord::Base.establish_connection(YAML.load_file("config/database.yml")["development"])
4
+
5
+ ActiveRecord::Base.send :include, Acts::Expireable
6
+ ActiveRecord::Base.send :include, Acts::Container
7
+
8
+ Base = ActiveRecord::Base
9
+ Base.logger = Log4r::Logger.new 'ActiveRecord::Base' #not outputing anywhere?
10
+
11
+ Dir["./mud/models/*.rb"].sort.each { |ext| load ext.to_s }
@@ -0,0 +1,46 @@
1
+ %w[active_record socket erb log4r].each { |lib| require lib }
2
+ %w[model controller].each { |lib| require(lib) }
3
+
4
+ module Muding
5
+ Log = Log4r::Logger.new 'muding'
6
+ Log.outputters = Log4r::Outputter.stdout
7
+
8
+ class << self
9
+ def run(input, handle)
10
+ unless input
11
+ raise Errno::EPIPE.new("Nil String to Pipe")
12
+ end
13
+ default_command = handle.default_command
14
+ session = handle.session
15
+ route = handle.route
16
+
17
+ reload_controller_code
18
+
19
+
20
+ # if we don't have a default command we need to figure
21
+ # out what the command is.
22
+ #
23
+ # format: "command [args]"
24
+ unless default_command
25
+ string_array = input.split(" ")
26
+ command = string_array.shift
27
+ args = string_array.to_s
28
+ else
29
+ command = default_command.to_s
30
+ args = input
31
+ end
32
+
33
+ return route.new(command, session).service(*args)
34
+
35
+ rescue Errno::EPIPE
36
+ raise
37
+ rescue Exception => x
38
+ Log.warn x
39
+ return Controllers::ServerError.new("get",session).service()
40
+ end
41
+ def reload_controller_code
42
+ load "./mud/controllers/mud.rb"
43
+ Dir["./mud/controllers/*_controller.rb"].sort.each { |ext| load ext }
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,22 @@
1
+ $:.unshift(File.dirname(__FILE__))
2
+ $:.unshift(File.dirname(__FILE__) + "/../../activesupport/lib")
3
+
4
+ begin
5
+ require 'active_support'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require_gem 'activesupport'
9
+ end
10
+
11
+ require 'muding_generator/base'
12
+ require 'muding_generator/lookup'
13
+ require 'muding_generator/commands'
14
+
15
+ Muding::Generator::Base.send(:include, Muding::Generator::Lookup)
16
+ Muding::Generator::Base.send(:include, Muding::Generator::Commands)
17
+
18
+ # Set up a default logger for convenience.
19
+ require 'muding_generator/simple_logger'
20
+ Muding::Generator::Base.logger = Muding::Generator::SimpleLogger.new(STDOUT)
21
+
22
+
@@ -0,0 +1,162 @@
1
+ require File.dirname(__FILE__) + '/options'
2
+ require File.dirname(__FILE__) + '/manifest'
3
+ require File.dirname(__FILE__) + '/spec'
4
+
5
+ module Muding
6
+ module Generator
7
+ class GeneratorError < StandardError; end
8
+ class UsageError < GeneratorError; end
9
+
10
+ class Base
11
+ include Options
12
+
13
+ default_options :collision => :ask, :quiet => false
14
+
15
+ cattr_accessor :logger
16
+
17
+ class_inheritable_accessor :spec
18
+
19
+ attr_reader :source_root, :destination_root, :args
20
+
21
+ def initialize(runtime_args, runtime_options = {})
22
+ @args = runtime_args
23
+ parse!(@args, runtime_options)
24
+
25
+ # Derive source and destination paths.
26
+ @source_root = options[:source] || File.join(spec.path, 'templates')
27
+ if options[:destination]
28
+ @destination_root = options[:destination]
29
+ elsif defined? ::RAILS_ROOT
30
+ @destination_root = ::RAILS_ROOT
31
+ end
32
+
33
+ # Silence the logger if requested.
34
+ logger.quiet = options[:quiet]
35
+
36
+ # Raise usage error if help is requested.
37
+ usage if options[:help]
38
+ end
39
+
40
+ # Generators must provide a manifest. Use the record method to create
41
+ # a new manifest and record your generator's actions.
42
+ def manifest
43
+ raise NotImplementedError, "No manifest for '#{spec.name}' generator."
44
+ end
45
+
46
+ # Return the full path from the source root for the given path.
47
+ # Example for source_root = '/source':
48
+ # source_path('some/path.rb') == '/source/some/path.rb'
49
+ #
50
+ # The given path may include a colon ':' character to indicate that
51
+ # the file belongs to another generator. This notation allows any
52
+ # generator to borrow files from another. Example:
53
+ # source_path('model:fixture.yml') = '/model/source/path/fixture.yml'
54
+ def source_path(relative_source)
55
+ # Check whether we're referring to another generator's file.
56
+ name, path = relative_source.split(':', 2)
57
+
58
+ # If not, return the full path to our source file.
59
+ if path.nil?
60
+ File.join(source_root, name)
61
+
62
+ # Otherwise, ask our referral for the file.
63
+ else
64
+ # FIXME: this is broken, though almost always true. Others'
65
+ # source_root are not necessarily the templates dir.
66
+ File.join(self.class.lookup(name).path, 'templates', path)
67
+ end
68
+ end
69
+
70
+ # Return the full path from the destination root for the given path.
71
+ # Example for destination_root = '/dest':
72
+ # destination_path('some/path.rb') == '/dest/some/path.rb'
73
+ def destination_path(relative_destination)
74
+ File.join(destination_root, relative_destination)
75
+ end
76
+
77
+ protected
78
+ # Convenience method for generator subclasses to record a manifest.
79
+ def record
80
+ Muding::Generator::Manifest.new(self) { |m| yield m }
81
+ end
82
+
83
+ # Override with your own usage banner.
84
+ def banner
85
+ "Usage: #{$0} #{spec.name} [options]"
86
+ end
87
+
88
+ # Read USAGE from file in generator base path.
89
+ def usage_message
90
+ File.read(File.join(spec.path, 'USAGE')) rescue ''
91
+ end
92
+ end
93
+
94
+
95
+ # The base generator for named components: models, controllers, mailers,
96
+ # etc. The target name is taken as the first argument and inflected to
97
+ # singular, plural, class, file, and table forms for your convenience.
98
+ # The remaining arguments are aliased to actions for controller and
99
+ # mailer convenience.
100
+ #
101
+ # If no name is provided, the generator raises a usage error with content
102
+ # optionally read from the USAGE file in the generator's base path.
103
+ #
104
+ # See Rails::Generator::Base for a discussion of Manifests and Commands.
105
+ class NamedBase < Base
106
+ attr_reader :name, :class_name, :singular_name, :plural_name, :table_name
107
+ attr_reader :class_path, :file_path, :class_nesting, :class_nesting_depth
108
+ alias_method :file_name, :singular_name
109
+ alias_method :actions, :args
110
+
111
+ def initialize(runtime_args, runtime_options = {})
112
+ super
113
+
114
+ # Name argument is required.
115
+ usage if runtime_args.empty?
116
+
117
+ @args = runtime_args.dup
118
+ base_name = @args.shift
119
+ assign_names!(base_name)
120
+ end
121
+
122
+ protected
123
+ # Override with your own usage banner.
124
+ def banner
125
+ "Usage: #{$0} #{spec.name} #{spec.name.camelize}Name [options]"
126
+ end
127
+
128
+ private
129
+ def assign_names!(name)
130
+ @name = name
131
+ base_name, @class_path, @file_path, @class_nesting, @class_nesting_depth = extract_modules(@name)
132
+ @class_name_without_nesting, @singular_name, @plural_name = inflect_names(base_name)
133
+ @table_name = ActiveRecord::Base.pluralize_table_names ? plural_name : singular_name
134
+ if @class_nesting.empty?
135
+ @class_name = @class_name_without_nesting
136
+ else
137
+ @class_name = "#{@class_nesting}::#{@class_name_without_nesting}"
138
+ end
139
+ end
140
+
141
+ # Extract modules from filesystem-style or ruby-style path:
142
+ # good/fun/stuff
143
+ # Good::Fun::Stuff
144
+ # produce the same results.
145
+ def extract_modules(name)
146
+ modules = name.include?('/') ? name.split('/') : name.split('::')
147
+ name = modules.pop
148
+ path = modules.map { |m| m.underscore }
149
+ file_path = (path + [name.underscore]).join('/')
150
+ nesting = modules.map { |m| m.camelize }.join('::')
151
+ [name, path, file_path, nesting, modules.size]
152
+ end
153
+
154
+ def inflect_names(name)
155
+ camel = name.camelize
156
+ under = camel.underscore
157
+ plural = under.pluralize
158
+ [camel, under, plural]
159
+ end
160
+ end
161
+ end
162
+ end