merb 0.3.7 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (173) hide show
  1. data/README +25 -26
  2. data/Rakefile +48 -36
  3. data/app_generators/merb/USAGE +5 -0
  4. data/app_generators/merb/merb_generator.rb +107 -0
  5. data/app_generators/merb/templates/Rakefile +99 -0
  6. data/{examples/skeleton/dist → app_generators/merb/templates}/app/controllers/application.rb +1 -1
  7. data/app_generators/merb/templates/app/controllers/exceptions.rb +13 -0
  8. data/{examples/skeleton/dist → app_generators/merb/templates}/app/helpers/global_helper.rb +0 -0
  9. data/{examples/skeleton/dist/app/mailers → app_generators/merb/templates/app/mailers/views}/layout/application.erb +0 -0
  10. data/app_generators/merb/templates/app/views/exceptions/internal_server_error.html.erb +207 -0
  11. data/app_generators/merb/templates/app/views/exceptions/not_acceptable.html.erb +38 -0
  12. data/app_generators/merb/templates/app/views/exceptions/not_found.html.erb +40 -0
  13. data/app_generators/merb/templates/app/views/layout/application.html.erb +11 -0
  14. data/app_generators/merb/templates/config/boot.rb +11 -0
  15. data/app_generators/merb/templates/config/dependencies.rb +41 -0
  16. data/{examples/skeleton/dist/conf → app_generators/merb/templates/config}/environments/development.rb +0 -0
  17. data/{examples/skeleton/dist/conf → app_generators/merb/templates/config}/environments/production.rb +0 -0
  18. data/{examples/skeleton/dist/conf → app_generators/merb/templates/config}/environments/test.rb +0 -0
  19. data/app_generators/merb/templates/config/merb.yml +64 -0
  20. data/app_generators/merb/templates/config/merb_init.rb +16 -0
  21. data/app_generators/merb/templates/config/plugins.yml +1 -0
  22. data/app_generators/merb/templates/config/router.rb +32 -0
  23. data/{lib/merb/core_ext/merb_array.rb → app_generators/merb/templates/config/upload.conf} +0 -0
  24. data/app_generators/merb/templates/public/images/merb.jpg +0 -0
  25. data/app_generators/merb/templates/public/merb.fcgi +6 -0
  26. data/app_generators/merb/templates/public/stylesheets/master.css +119 -0
  27. data/app_generators/merb/templates/script/destroy +28 -0
  28. data/app_generators/merb/templates/script/generate +28 -0
  29. data/{examples/skeleton → app_generators/merb/templates}/script/stop_merb +0 -0
  30. data/app_generators/merb/templates/script/win_script.cmd +1 -0
  31. data/app_generators/merb/templates/spec/spec.opts +6 -0
  32. data/app_generators/merb/templates/spec/spec_helper.rb +10 -0
  33. data/app_generators/merb/templates/test/test_helper.rb +13 -0
  34. data/app_generators/merb_plugin/USAGE +5 -0
  35. data/app_generators/merb_plugin/merb_plugin_generator.rb +64 -0
  36. data/app_generators/merb_plugin/templates/LICENSE +20 -0
  37. data/app_generators/merb_plugin/templates/README +4 -0
  38. data/app_generators/merb_plugin/templates/Rakefile +35 -0
  39. data/app_generators/merb_plugin/templates/TODO +5 -0
  40. data/app_generators/merb_plugin/templates/merbtasks.rb +6 -0
  41. data/app_generators/merb_plugin/templates/sampleplugin.rb +10 -0
  42. data/app_generators/merb_plugin/templates/sampleplugin_spec.rb +7 -0
  43. data/app_generators/merb_plugin/templates/spec_helper.rb +2 -0
  44. data/bin/merb +1 -1
  45. data/lib/autotest/discover.rb +3 -0
  46. data/lib/autotest/merb_rspec.rb +79 -0
  47. data/lib/merb.rb +72 -93
  48. data/lib/merb/{merb_abstract_controller.rb → abstract_controller.rb} +28 -5
  49. data/lib/merb/caching/action_cache.rb +65 -29
  50. data/lib/merb/caching/fragment_cache.rb +9 -4
  51. data/lib/merb/caching/store/file_cache.rb +22 -14
  52. data/lib/merb/caching/store/memory_cache.rb +26 -8
  53. data/lib/merb/{merb_constants.rb → constants.rb} +9 -7
  54. data/lib/merb/controller.rb +178 -0
  55. data/lib/merb/core_ext.rb +13 -11
  56. data/lib/merb/core_ext/array.rb +0 -0
  57. data/lib/merb/core_ext/{merb_class.rb → class.rb} +0 -0
  58. data/lib/merb/core_ext/{merb_enumerable.rb → enumerable.rb} +0 -0
  59. data/lib/merb/core_ext/get_args.rb +52 -0
  60. data/lib/merb/core_ext/{merb_hash.rb → hash.rb} +40 -11
  61. data/lib/merb/core_ext/{merb_inflections.rb → inflections.rb} +0 -0
  62. data/lib/merb/core_ext/{merb_inflector.rb → inflector.rb} +1 -1
  63. data/lib/merb/core_ext/{merb_kernel.rb → kernel.rb} +56 -3
  64. data/lib/merb/core_ext/mash.rb +88 -0
  65. data/lib/merb/core_ext/{merb_module.rb → module.rb} +0 -0
  66. data/lib/merb/core_ext/{merb_numeric.rb → numeric.rb} +0 -0
  67. data/lib/merb/core_ext/{merb_object.rb → object.rb} +10 -47
  68. data/lib/merb/core_ext/string.rb +56 -0
  69. data/lib/merb/core_ext/{merb_symbol.rb → symbol.rb} +0 -0
  70. data/lib/merb/dispatcher.rb +109 -0
  71. data/lib/merb/{merb_drb_server.rb → drb_server.rb} +0 -0
  72. data/lib/merb/erubis_ext.rb +10 -0
  73. data/lib/merb/exceptions.rb +173 -0
  74. data/lib/merb/generators/merb_app/merb_app.rb +5 -25
  75. data/lib/merb/generators/merb_generator_helpers.rb +317 -0
  76. data/lib/merb/generators/merb_plugin.rb +19 -0
  77. data/lib/merb/logger.rb +65 -0
  78. data/lib/merb/{merb_mail_controller.rb → mail_controller.rb} +102 -49
  79. data/lib/merb/{merb_mailer.rb → mailer.rb} +31 -27
  80. data/lib/merb/mixins/{basic_authentication_mixin.rb → basic_authentication.rb} +3 -3
  81. data/lib/merb/mixins/{controller_mixin.rb → controller.rb} +131 -112
  82. data/lib/merb/mixins/{erubis_capture_mixin.rb → erubis_capture.rb} +12 -21
  83. data/lib/merb/mixins/{form_control_mixin.rb → form_control.rb} +6 -12
  84. data/lib/merb/mixins/render.rb +401 -0
  85. data/lib/merb/mixins/responder.rb +378 -0
  86. data/lib/merb/mixins/{view_context_mixin.rb → view_context.rb} +65 -10
  87. data/lib/merb/mixins/web_controller.rb +29 -0
  88. data/lib/merb/{merb_handler.rb → mongrel_handler.rb} +59 -38
  89. data/lib/merb/part_controller.rb +19 -0
  90. data/lib/merb/plugins.rb +16 -0
  91. data/lib/merb/rack_adapter.rb +37 -0
  92. data/lib/merb/request.rb +421 -0
  93. data/lib/merb/router.rb +576 -0
  94. data/lib/merb/{merb_server.rb → server.rb} +275 -71
  95. data/lib/merb/session.rb +10 -10
  96. data/lib/merb/session/cookie_store.rb +125 -0
  97. data/lib/merb/session/{merb_mem_cache_session.rb → mem_cache_session.rb} +22 -9
  98. data/lib/merb/session/{merb_memory_session.rb → memory_session.rb} +15 -11
  99. data/lib/merb/template.rb +35 -8
  100. data/lib/merb/template/erubis.rb +16 -10
  101. data/lib/merb/template/haml.rb +33 -20
  102. data/lib/merb/template/markaby.rb +16 -14
  103. data/lib/merb/template/xml_builder.rb +8 -4
  104. data/lib/merb/test/{merb_fake_request.rb → fake_request.rb} +11 -5
  105. data/lib/merb/test/helper.rb +31 -0
  106. data/lib/merb/test/hpricot.rb +136 -0
  107. data/lib/merb/test/{merb_multipart.rb → multipart.rb} +1 -1
  108. data/lib/merb/test/rspec.rb +93 -0
  109. data/lib/merb/{merb_upload_handler.rb → upload_handler.rb} +5 -6
  110. data/lib/merb/{merb_upload_progress.rb → upload_progress.rb} +1 -1
  111. data/lib/merb/{merb_view_context.rb → view_context.rb} +27 -42
  112. data/lib/{merb_tasks.rb → tasks.rb} +0 -0
  113. data/lib/tasks/merb.rake +21 -11
  114. data/merb_default_generators/model/USAGE +0 -0
  115. data/merb_default_generators/model/model_generator.rb +16 -0
  116. data/merb_default_generators/model/templates/new_model_template.erb +5 -0
  117. data/merb_default_generators/resource_controller/USAGE +0 -0
  118. data/merb_default_generators/resource_controller/resource_controller_generator.rb +26 -0
  119. data/merb_default_generators/resource_controller/templates/controller.rb +30 -0
  120. data/merb_default_generators/resource_controller/templates/edit.html.erb +1 -0
  121. data/merb_default_generators/resource_controller/templates/helper.rb +5 -0
  122. data/merb_default_generators/resource_controller/templates/index.html.erb +1 -0
  123. data/merb_default_generators/resource_controller/templates/new.html.erb +1 -0
  124. data/merb_default_generators/resource_controller/templates/show.html.erb +1 -0
  125. data/merb_generators/controller/USAGE +5 -0
  126. data/merb_generators/controller/controller_generator.rb +16 -0
  127. data/merb_generators/controller/templates/controller.rb +8 -0
  128. data/merb_generators/controller/templates/helper.rb +5 -0
  129. data/merb_generators/controller/templates/index.html.erb +3 -0
  130. data/merb_generators/resource/USAGE +0 -0
  131. data/merb_generators/resource/resource_generator.rb +60 -0
  132. data/rspec_generators/merb_controller_test/merb_controller_test_generator.rb +67 -0
  133. data/rspec_generators/merb_controller_test/templates/controller_spec.rb +8 -0
  134. data/rspec_generators/merb_controller_test/templates/edit_spec.rb +12 -0
  135. data/rspec_generators/merb_controller_test/templates/helper_spec.rb +5 -0
  136. data/rspec_generators/merb_controller_test/templates/index_spec.rb +12 -0
  137. data/rspec_generators/merb_controller_test/templates/new_spec.rb +12 -0
  138. data/rspec_generators/merb_controller_test/templates/show_spec.rb +5 -0
  139. data/rspec_generators/merb_model_test/merb_model_test_generator.rb +26 -0
  140. data/rspec_generators/merb_model_test/templates/model_spec_template.erb +7 -0
  141. data/script/destroy +14 -0
  142. data/script/generate +14 -0
  143. data/test_unit_generators/merb_controller_test/merb_controller_test_generator.rb +53 -0
  144. data/test_unit_generators/merb_controller_test/templates/functional_test.rb +17 -0
  145. data/test_unit_generators/merb_controller_test/templates/helper_test.rb +9 -0
  146. data/test_unit_generators/merb_model_test/merb_model_test_generator.rb +29 -0
  147. data/test_unit_generators/merb_model_test/templates/model_test_unit_template.erb +9 -0
  148. metadata +172 -94
  149. data/examples/README_EXAMPLES +0 -10
  150. data/examples/skeleton/Rakefile +0 -68
  151. data/examples/skeleton/dist/app/views/layout/application.herb +0 -12
  152. data/examples/skeleton/dist/conf/database.yml +0 -23
  153. data/examples/skeleton/dist/conf/merb.yml +0 -57
  154. data/examples/skeleton/dist/conf/merb_init.rb +0 -24
  155. data/examples/skeleton/dist/conf/router.rb +0 -22
  156. data/examples/skeleton/dist/conf/upload.conf +0 -5
  157. data/examples/skeleton/dist/schema/migrations/001_add_sessions_table.rb +0 -14
  158. data/examples/skeleton/script/new_migration +0 -21
  159. data/lib/merb/core_ext/merb_string.rb +0 -18
  160. data/lib/merb/merb_controller.rb +0 -206
  161. data/lib/merb/merb_dispatcher.rb +0 -87
  162. data/lib/merb/merb_exceptions.rb +0 -319
  163. data/lib/merb/merb_part_controller.rb +0 -42
  164. data/lib/merb/merb_plugins.rb +0 -293
  165. data/lib/merb/merb_request.rb +0 -165
  166. data/lib/merb/merb_router.rb +0 -309
  167. data/lib/merb/merb_yaml_store.rb +0 -31
  168. data/lib/merb/mixins/render_mixin.rb +0 -283
  169. data/lib/merb/mixins/responder_mixin.rb +0 -159
  170. data/lib/merb/session/merb_ar_session.rb +0 -131
  171. data/lib/merb/vendor/paginator/README.txt +0 -84
  172. data/lib/merb/vendor/paginator/paginator.rb +0 -124
  173. data/lib/tasks/db.rake +0 -55
@@ -0,0 +1,10 @@
1
+ require 'erubis'
2
+ module Erubis
3
+ class MEruby < Erubis::Eruby
4
+ include PercentLineEnhancer
5
+ include StringBufferEnhancer
6
+ end
7
+ def self.load_yaml_file(file, binding = binding)
8
+ YAML::load(Erubis::MEruby.new(IO.read(File.expand_path(file))).result(binding))
9
+ end
10
+ end
@@ -0,0 +1,173 @@
1
+ begin
2
+ require 'coderay'
3
+ rescue LoadError => ex
4
+ end
5
+
6
+ module Merb
7
+ # ControllerExceptions are a way of simplifying controller code by placing
8
+ # exceptional logic back into the MVC pattern.
9
+ #
10
+ # When a ControllerException is raised within your application merb will
11
+ # attempt to re-route the request to your Exceptions controller to render
12
+ # the error in a friendly mannor.
13
+ #
14
+ # For example you might have an action in your app that raises NotFound
15
+ # if a some resource was not available
16
+ #
17
+ # def show
18
+ # product = Product.find(params[:id])
19
+ # raise NotFound if product.nil?
20
+ # [...]
21
+ # end
22
+ #
23
+ # This would halt execution of your action and re-route it over to your
24
+ # Exceptions controller which might look something like
25
+ #
26
+ # class Exceptions < Application
27
+ # def not_found
28
+ # render :layout => :none
29
+ # end
30
+ # end
31
+ #
32
+ # As usual the not_found action will look for a template in
33
+ # app/views/exceptions/not_found.html.erb
34
+ #
35
+ # Note: All standard ControllerExceptions have an HTTP status code associated
36
+ # with them which is sent to the browser when the action it is rendered.
37
+ #
38
+ # Note: If you do not specifiy how to handle raised ControllerExceptions
39
+ # or an unhandlable exception occurs within your customised exception action
40
+ # then they will be rendered using the built-in error template
41
+ # in development mode this "built in" template will show stack-traces for
42
+ # any of the ServerError family of exceptions (you can force the stack-trace
43
+ # to display in production mode using the :exception_details config option in
44
+ # merb.yml)
45
+ #
46
+ #
47
+ # Internal Exceptions
48
+ #
49
+ # Any other rogue errors (not ControllerExceptions) that occur during the
50
+ # execution of you app will be converted into the ControllerException
51
+ # InternalServerError, and like all ControllerExceptions can be caught
52
+ # on your Exceptions controller.
53
+ #
54
+ # InternalServerErrors return status 500, a common use for cusomizing this
55
+ # action might be to send emails to the development team, warning that their
56
+ # application have exploded. Mock example:
57
+ #
58
+ # def internal_server_error
59
+ # MySpecialMailer.deliver(
60
+ # "team@cowboys.com",
61
+ # "Exception occured at #{Time.now}",
62
+ # params[:exception])
63
+ # render :inline => 'Something is wrong, but the team are on it!'
64
+ # end
65
+ #
66
+ # Note: The special param[:exception] is available in all Exception actions
67
+ # and contains the ControllerException that was raised (this is handy if
68
+ # you want to display the associated message or display more detailed info)
69
+ #
70
+ #
71
+ # Extending ControllerExceptions
72
+ #
73
+ # To extend the use of the ControllerExceptions one may extend any of the
74
+ # HTTPError classes.
75
+ #
76
+ # As an example we can create an exception called AdminAccessRequired.
77
+ #
78
+ # class AdminAccessRequired < Merb::ControllerExceptions::Unauthorized; end
79
+ #
80
+ # Add the required action to our Exceptions controller
81
+ #
82
+ # class Exceptions < Application
83
+ # def admin_access_required
84
+ # render
85
+ # end
86
+ # end
87
+ #
88
+ # In app/views/exceptions/admin_access_required.rhtml
89
+ #
90
+ # <h1>You're not an administrator!</h1>
91
+ # <p>You tried to access <%= @tried_to_access %> but that URL is
92
+ # restricted to administrators.</p>
93
+ #
94
+ module ControllerExceptions
95
+ class Base < StandardError
96
+ def name
97
+ self.class.to_s.snake_case.split('::').last
98
+ end
99
+ end
100
+
101
+ class Informational < Merb::ControllerExceptions::Base; end
102
+ class Continue < Merb::ControllerExceptions::Informational; STATUS = 100; end
103
+ class SwitchingProtocols < Merb::ControllerExceptions::Informational; STATUS = 101; end
104
+ class Successful < Merb::ControllerExceptions::Base; end
105
+ class OK < Merb::ControllerExceptions::Successful; STATUS = 200; end
106
+ class Created < Merb::ControllerExceptions::Successful; STATUS = 201; end
107
+ class Accepted < Merb::ControllerExceptions::Successful; STATUS = 202; end
108
+ class NonAuthoritativeInformation < Merb::ControllerExceptions::Successful; STATUS = 203; end
109
+ class NoContent < Merb::ControllerExceptions::Successful; STATUS = 204; end
110
+ class ResetContent < Merb::ControllerExceptions::Successful; STATUS = 205; end
111
+ class PartialContent < Merb::ControllerExceptions::Successful; STATUS = 206; end
112
+ class Redirection < Merb::ControllerExceptions::Base; end
113
+ class MultipleChoices < Merb::ControllerExceptions::Redirection; STATUS = 300; end
114
+ class MovedPermanently < Merb::ControllerExceptions::Redirection; STATUS = 301; end
115
+ class MovedTemporarily < Merb::ControllerExceptions::Redirection; STATUS = 302; end
116
+ class SeeOther < Merb::ControllerExceptions::Redirection; STATUS = 303; end
117
+ class NotModified < Merb::ControllerExceptions::Redirection; STATUS = 304; end
118
+ class UseProxy < Merb::ControllerExceptions::Redirection; STATUS = 305; end
119
+ class TemporaryRedirect < Merb::ControllerExceptions::Redirection; STATUS = 307; end
120
+ class ClientError < Merb::ControllerExceptions::Base; end
121
+ class BadRequest < Merb::ControllerExceptions::ClientError; STATUS = 400; end
122
+ class Unauthorized < Merb::ControllerExceptions::ClientError; STATUS = 401; end
123
+ class PaymentRequired < Merb::ControllerExceptions::ClientError; STATUS = 402; end
124
+ class Forbidden < Merb::ControllerExceptions::ClientError; STATUS = 403; end
125
+ class NotFound < Merb::ControllerExceptions::ClientError; STATUS = 404; end
126
+ class ActionNotFound < Merb::ControllerExceptions::NotFound; end
127
+ class TemplateNotFound < Merb::ControllerExceptions::NotFound; end
128
+ class LayoutNotFound < Merb::ControllerExceptions::NotFound; end
129
+ class MethodNotAllowed < Merb::ControllerExceptions::ClientError; STATUS = 405; end
130
+ class NotAcceptable < Merb::ControllerExceptions::ClientError; STATUS = 406; end
131
+ class ProxyAuthenticationRequired < Merb::ControllerExceptions::ClientError; STATUS = 407; end
132
+ class RequestTimeout < Merb::ControllerExceptions::ClientError; STATUS = 408; end
133
+ class Conflict < Merb::ControllerExceptions::ClientError; STATUS = 409; end
134
+ class Gone < Merb::ControllerExceptions::ClientError; STATUS = 410; end
135
+ class LengthRequired < Merb::ControllerExceptions::ClientError; STATUS = 411; end
136
+ class PreconditionFailed < Merb::ControllerExceptions::ClientError; STATUS = 412; end
137
+ class RequestEntityTooLarge < Merb::ControllerExceptions::ClientError; STATUS = 413; end
138
+ class RequestURITooLarge < Merb::ControllerExceptions::ClientError; STATUS = 414; end
139
+ class UnsupportedMediaType < Merb::ControllerExceptions::ClientError; STATUS = 415; end
140
+ class RequestRangeNotSatisfiable < Merb::ControllerExceptions::ClientError; STATUS = 416; end
141
+ class ExpectationFailed < Merb::ControllerExceptions::ClientError; STATUS = 417; end
142
+ class ServerError < Merb::ControllerExceptions::Base; end
143
+ class NotImplemented < Merb::ControllerExceptions::ServerError; STATUS = 501; end
144
+ class BadGateway < Merb::ControllerExceptions::ServerError; STATUS = 502; end
145
+ class ServiceUnavailable < Merb::ControllerExceptions::ServerError; STATUS = 503; end
146
+ class GatewayTimeout < Merb::ControllerExceptions::ServerError; STATUS = 504; end
147
+ class HTTPVersionNotSupported < Merb::ControllerExceptions::ServerError; STATUS = 505; end
148
+ class InternalServerError < Merb::ControllerExceptions::ServerError; STATUS = 500
149
+ DEFAULT_TEMPLATE = ::Merb::Dispatcher::DEFAULT_ERROR_TEMPLATE
150
+
151
+ def initialize(exception = nil)
152
+ @exception = exception
153
+ @coderay = CodeRay rescue nil
154
+ end
155
+
156
+ def backtrace
157
+ @exception ? @exception.backtrace : backtrace
158
+ end
159
+
160
+ def message
161
+ @exception ? @exception.message : message
162
+ end
163
+ end
164
+ end
165
+
166
+ # PLEASE STOP REMOVING THIS ONE GUYS! It's used to show exceptions in the log file
167
+ # this is the second time I've had to add it back.
168
+ def self.exception(e)
169
+ "#{ e.message } - (#{ e.class })\n" <<
170
+ "#{(e.backtrace or []).join("\n")}"
171
+ end
172
+
173
+ end
@@ -4,33 +4,13 @@ require 'find'
4
4
  module Merb
5
5
 
6
6
  class AppGenerator
7
- SKELETON_DIR = File.expand_path File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'examples/skeleton')
8
-
9
7
  def self.run(path)
10
- @path = path
11
- @path = File.expand_path(@path)
12
- if File.exists? @path
13
- STDERR.puts "ERROR: Path #{@path} already exists! Aborting!"
14
- exit 1
15
- end
8
+ require 'rubygems'
9
+ require 'rubigen'
16
10
 
17
- puts "Copying skeleton app to '#@path'"
18
- # Unpacks 'test.tar' to 'x', creating 'x' if necessary.
19
- FileUtils.cp_r(SKELETON_DIR, @path)
20
- Find.find(@path) do |f|
21
- FileUtils.rm_rf(f) if /\.svn$/ =~ f
22
- end
23
- public_path = File.expand_path(File.join(@path, "dist", "public"))
24
- mailer_path = File.expand_path(File.join(@path, "dist", "app", "mailers"))
25
- app_path = File.expand_path(File.join(@path, "dist", "app"))
26
- FileUtils.mkdir_p(["#{mailer_path}/helpers",
27
- "#{mailer_path}/views",
28
- "#{@path}/log",
29
- "#{app_path}/models",
30
- "#{public_path}/javascripts",
31
- "#{public_path}/stylesheets",
32
- "#{public_path}/images"])
33
- puts 'Done'
11
+ require 'rubigen/scripts/generate'
12
+ RubiGen::Base.use_application_sources!
13
+ RubiGen::Scripts::Generate.new.run([path], :generator => 'merb', :backtrace => true)
34
14
  end
35
15
 
36
16
  end
@@ -0,0 +1,317 @@
1
+ # Provides some basic generator support that is generally required in various
2
+ # Generators
3
+
4
+ module Merb
5
+ module GeneratorHelpers
6
+
7
+ class ModelGeneratorBase < RubiGen::Base
8
+
9
+ default_options :author => nil
10
+ attr_reader :name, :model_attributes
11
+ attr_accessor :model_template_name, :model_test_generator_name, :migration_generator_name
12
+
13
+ def initialize(runtime_args, runtime_options = {})
14
+ super
15
+ usage if args.empty?
16
+ @class_name = args.shift.snake_case.to_const_string
17
+ extract_options
18
+ end
19
+
20
+ def manifest
21
+ unless @class_name
22
+ puts banner
23
+ exit 1
24
+ end
25
+ record do |m|
26
+
27
+ # ensure there are no other definitions of this model already defined.
28
+ m.class_collisions(@class_name)
29
+ # Ensure appropriate folder(s) exists
30
+ m.directory 'app/models'
31
+ #
32
+ model_filename = @class_name.snake_case
33
+ spec_filename = @class_name.snake_case.pluralize
34
+ table_name = spec_filename
35
+
36
+
37
+ # Create stubs
38
+ m.template model_template_name,
39
+ "app/models/#{model_filename}.rb",
40
+ :assigns => { :class_name => @class_name,
41
+ :table_attributes => model_attributes}
42
+
43
+ # Check to see if a scope has been set for which test framework to use.
44
+ # If we try to run the dependency without an :rspec or :test_unit scope an
45
+ # error will be raised.
46
+ scopes = RubiGen::Base.sources.select{ |s| s.is_a?( RubiGen::PathFilteredSource )}.first.filters
47
+ if scopes.include?(:rspec) || scopes.include?(:test_unit)
48
+ unless options[:skip_testing]
49
+ m.dependency model_test_generator_name, [@class_name]
50
+ end
51
+ else
52
+ puts "\nSelect a scope for :rspec or :test_unit in script/generate if you want to generate test stubs\n\n"
53
+ end
54
+
55
+ unless options[:skip_migration]
56
+ m.dependency migration_generator_name,["add_model_#{spec_filename}"], :table_name => table_name, :table_attributes => model_attributes
57
+ end
58
+
59
+ end
60
+ end
61
+
62
+ protected
63
+ def banner
64
+ <<-EOS
65
+ Creates a new model for merb
66
+
67
+ USAGE: #{$0} #{spec.name} NameOfModel [field:type field:type]
68
+
69
+ Example:
70
+ #{$0} #{spec.name} person
71
+
72
+ If you already have 3 migrations, this will create the AddModelPeople migration in
73
+ schema/migration/004_add_model_people.rb
74
+
75
+ Options:
76
+ --skip-migration will not create a migration file
77
+
78
+ EOS
79
+ end
80
+
81
+ def add_options!(opts)
82
+ opts.separator ''
83
+ opts.separator 'Options:'
84
+ # For each option below, place the default
85
+ # at the top of the file next to "default_options"
86
+ # opts.on("-a", "--author=\"Your Name\"", String,
87
+ # "Some comment about this option",
88
+ # "Default: none") { |options[:author]| }
89
+ # opts.on("-v", "--version", "Show the #{File.basename($0)} version number and quit.")
90
+ opts.on( "--skip-migration", "Don't generate a migration for this model") { |options[:skip_migration]| }
91
+ opts.on( "--skip-testing", "Don't generate a test or spec file for this model") { |options[:skip_testing]| }
92
+ end
93
+
94
+ def extract_options
95
+ # for each option, extract it into a local variable (and create an "attr_reader :author" at the top)
96
+ # Templates can access these value via the attr_reader-generated methods, but not the
97
+ # raw instance variable value.
98
+ # @author = options[:author]
99
+ # get the attributes into a format that can be used.
100
+ attribute = Struct.new(:name, :type)
101
+ @model_attributes = args.map{ |b| b.split(":").size > 1 ? attribute.new(*b.split(":")) : nil }.compact
102
+ end
103
+ end
104
+
105
+ class MigrationGeneratorBase < RubiGen::Base
106
+
107
+ default_options :author => nil
108
+
109
+ attr_reader :name
110
+ attr_accessor :migration_template_name
111
+
112
+ def initialize(runtime_args, runtime_options = {})
113
+ super
114
+ usage if args.empty?
115
+ @class_name = args.shift
116
+ options[:table_name] ||= runtime_options[:table_name]
117
+ extract_options
118
+ end
119
+
120
+ def manifest
121
+ unless @class_name
122
+ puts banner
123
+ exit 1
124
+ end
125
+ record do |m|
126
+ # Ensure appropriate folder(s) exists
127
+ m.directory 'schema/migrations'
128
+
129
+ # Create stubs
130
+ highest_migration = Dir[Dir.pwd+'/schema/migrations/*'].map{|f| File.basename(f) =~ /^(\d+)/; $1}.max
131
+ filename = format("%03d_%s", (highest_migration.to_i+1), @class_name.snake_case)
132
+ m.template "new_migration.erb", "schema/migrations/#{filename}.rb",
133
+ :assigns => { :class_name => @class_name,
134
+ :table_name => options[:table_name],
135
+ :table_attributes => options[:table_attributes] }
136
+
137
+ end
138
+ end
139
+
140
+ protected
141
+ def banner
142
+ <<-EOS
143
+ Creates a new migration for merb
144
+
145
+ USAGE: #{$0} #{spec.name} NameOfMigration [field:type field:type]
146
+
147
+ Example:
148
+ #{$0} #{spec.name} AddPeople
149
+
150
+ If you already have 3 migrations, this will create the AddPeople migration in
151
+ schema/migration/004_add_people.rb
152
+
153
+ #{$0} #{spec.name} project --table-name projects_table name:string created_at:timestamp
154
+
155
+ This will create a migration that creates a table call projects_table with these attributes:
156
+ string :name
157
+ timestamp :created_at
158
+
159
+ EOS
160
+ end
161
+
162
+ def add_options!(opts)
163
+ opts.separator ''
164
+ opts.separator 'Options:'
165
+ # For each option below, place the default
166
+ # at the top of the file next to "default_options"
167
+ # opts.on("-a", "--author=\"Your Name\"", String,
168
+ # "Some comment about this option",
169
+ # "Default: none") { |options[:author]| }
170
+ # opts.on("-v", "--version", "Show the #{File.basename($0)} version number and quit.")
171
+ opts.on( "--table-name=\"table_name_for_migration\"",
172
+ String,
173
+ "Include a create table with the given table name"){ |options[:table_name]| }
174
+ end
175
+
176
+ def extract_options
177
+ # for each option, extract it into a local variable (and create an "attr_reader :author" at the top)
178
+ # Templates can access these value via the attr_reader-generated methods, but not the
179
+ # raw instance variable value.
180
+ # @author = options[:author]
181
+ if !options[:table_attributes]
182
+ attribute = Struct.new(:name, :type)
183
+ options[:table_attributes] = args.map{ |b| b.split(":").size == 2 ? attribute.new(*b.split(":")) : nil }.compact
184
+ end
185
+ end
186
+ end
187
+
188
+ class MerbModelTestGenerator < RubiGen::Base
189
+
190
+ default_options :author => nil
191
+
192
+ attr_reader :name, :model_test_template_name, :model_test_path_name, :model_test_file_suffix
193
+
194
+ def initialize(runtime_args, runtime_options = {})
195
+ super
196
+ usage if args.empty?
197
+ @class_name = args.shift.snake_case.to_const_string
198
+ extract_options
199
+ end
200
+
201
+ def manifest
202
+ unless @class_name
203
+ puts banner
204
+ exit 1
205
+ end
206
+ record do |m|
207
+ # ensure there are no other definitions of this model already defined.
208
+ # Ensure appropriate folder(s) exists
209
+ m.directory model_test_path_name
210
+ #
211
+ model_filename = @class_name.snake_case
212
+
213
+ # Create stubs
214
+ m.template model_test_template_name,
215
+ "#{model_test_path_name}/#{model_filename}_#{model_test_file_suffix}.rb",
216
+ :assigns => {:class_name => @class_name}
217
+ end
218
+ end
219
+
220
+ protected
221
+
222
+
223
+ def add_options!(opts)
224
+ # opts.separator ''
225
+ # opts.separator 'Options:'
226
+ # For each option below, place the default
227
+ # at the top of the file next to "default_options"
228
+ # opts.on("-a", "--author=\"Your Name\"", String,
229
+ # "Some comment about this option",
230
+ # "Default: none") { |options[:author]| }
231
+ # opts.on("-v", "--version", "Show the #{File.basename($0)} version number and quit.")
232
+ end
233
+
234
+ def extract_options
235
+ # for each option, extract it into a local variable (and create an "attr_reader :author" at the top)
236
+ # Templates can access these value via the attr_reader-generated methods, but not the
237
+ # raw instance variable value.
238
+ # @author = options[:author]
239
+ end
240
+ end
241
+
242
+ # Pass the following options are available to this generatrs
243
+ class ControllerGeneratorBase < RubiGen::Base
244
+
245
+ default_options :author => nil
246
+
247
+ attr_reader :name, :class_name, :file_name
248
+
249
+ def initialize(runtime_args, runtime_options = {})
250
+ super
251
+ usage if args.empty?
252
+ @name = args.shift
253
+ @class_name = @name.camel_case #.pluralize
254
+ @file_name = @name.snake_case #.pluralize
255
+ @engine = runtime_options[:engine] || "erb" # set by subclasses only
256
+ @template_actions = runtime_options[:actions] || %w[index] # Used by subclasses only
257
+ @test_generator = runtime_options[:test_stub_generator] || "merb_controller_test"
258
+ extract_options
259
+ end
260
+
261
+ def manifest
262
+ record do |m|
263
+
264
+ # ensure there are no other definitions of this model already defined.
265
+ m.class_collisions(@class_name)
266
+
267
+ m.directory "app/controllers"
268
+ m.template "controller.rb", "app/controllers/#{file_name}.rb", :assigns => {:actions => @template_actions}
269
+
270
+ m.directory "app/views/#{file_name}"
271
+
272
+ # Include templates if they exist
273
+ @template_actions.each do |the_action|
274
+ template_name = "#{the_action}.html.#{@engine}"
275
+ template_path = "/" + source_path(spec.name).split("/")[0..-2].join("/")
276
+
277
+ if File.exists?(File.join(template_path,template_name))
278
+ m.template template_name, "app/views/#{file_name}/#{template_name}"
279
+ end
280
+ end
281
+
282
+ m.directory "app/helpers/"
283
+ m.template "helper.rb", "app/helpers/#{file_name}_helper.rb"
284
+ m.dependency @test_generator, [name], :destination => destination_root, :template_actions => @template_actions
285
+ end
286
+ end
287
+
288
+ protected
289
+ def banner
290
+ <<-EOS
291
+ Creates a Merb controller
292
+
293
+ USAGE: #{$0} #{spec.name} name"
294
+ EOS
295
+ end
296
+
297
+ def add_options!(opts)
298
+ # opts.separator ''
299
+ # opts.separator 'Options:'
300
+ # For each option below, place the default
301
+ # at the top of the file next to "default_options"
302
+ # opts.on("-a", "--author=\"Your Name\"", String,
303
+ # "Some comment about this option",
304
+ # "Default: none") { |options[:author]| }
305
+ # opts.on("-v", "--version", "Show the #{File.basename($0)} version number and quit.")
306
+ end
307
+
308
+ def extract_options
309
+ # for each option, extract it into a local variable (and create an "attr_reader :author" at the top)
310
+ # Templates can access these value via the attr_reader-generated methods, but not the
311
+ # raw instance variable value.
312
+ # @author = options[:author]
313
+ end
314
+ end
315
+
316
+ end
317
+ end