merb 0.3.7 → 0.4.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 (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