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.
- data/README +25 -26
- data/Rakefile +48 -36
- data/app_generators/merb/USAGE +5 -0
- data/app_generators/merb/merb_generator.rb +107 -0
- data/app_generators/merb/templates/Rakefile +99 -0
- data/{examples/skeleton/dist → app_generators/merb/templates}/app/controllers/application.rb +1 -1
- data/app_generators/merb/templates/app/controllers/exceptions.rb +13 -0
- data/{examples/skeleton/dist → app_generators/merb/templates}/app/helpers/global_helper.rb +0 -0
- data/{examples/skeleton/dist/app/mailers → app_generators/merb/templates/app/mailers/views}/layout/application.erb +0 -0
- data/app_generators/merb/templates/app/views/exceptions/internal_server_error.html.erb +207 -0
- data/app_generators/merb/templates/app/views/exceptions/not_acceptable.html.erb +38 -0
- data/app_generators/merb/templates/app/views/exceptions/not_found.html.erb +40 -0
- data/app_generators/merb/templates/app/views/layout/application.html.erb +11 -0
- data/app_generators/merb/templates/config/boot.rb +11 -0
- data/app_generators/merb/templates/config/dependencies.rb +41 -0
- data/{examples/skeleton/dist/conf → app_generators/merb/templates/config}/environments/development.rb +0 -0
- data/{examples/skeleton/dist/conf → app_generators/merb/templates/config}/environments/production.rb +0 -0
- data/{examples/skeleton/dist/conf → app_generators/merb/templates/config}/environments/test.rb +0 -0
- data/app_generators/merb/templates/config/merb.yml +64 -0
- data/app_generators/merb/templates/config/merb_init.rb +16 -0
- data/app_generators/merb/templates/config/plugins.yml +1 -0
- data/app_generators/merb/templates/config/router.rb +32 -0
- data/{lib/merb/core_ext/merb_array.rb → app_generators/merb/templates/config/upload.conf} +0 -0
- data/app_generators/merb/templates/public/images/merb.jpg +0 -0
- data/app_generators/merb/templates/public/merb.fcgi +6 -0
- data/app_generators/merb/templates/public/stylesheets/master.css +119 -0
- data/app_generators/merb/templates/script/destroy +28 -0
- data/app_generators/merb/templates/script/generate +28 -0
- data/{examples/skeleton → app_generators/merb/templates}/script/stop_merb +0 -0
- data/app_generators/merb/templates/script/win_script.cmd +1 -0
- data/app_generators/merb/templates/spec/spec.opts +6 -0
- data/app_generators/merb/templates/spec/spec_helper.rb +10 -0
- data/app_generators/merb/templates/test/test_helper.rb +13 -0
- data/app_generators/merb_plugin/USAGE +5 -0
- data/app_generators/merb_plugin/merb_plugin_generator.rb +64 -0
- data/app_generators/merb_plugin/templates/LICENSE +20 -0
- data/app_generators/merb_plugin/templates/README +4 -0
- data/app_generators/merb_plugin/templates/Rakefile +35 -0
- data/app_generators/merb_plugin/templates/TODO +5 -0
- data/app_generators/merb_plugin/templates/merbtasks.rb +6 -0
- data/app_generators/merb_plugin/templates/sampleplugin.rb +10 -0
- data/app_generators/merb_plugin/templates/sampleplugin_spec.rb +7 -0
- data/app_generators/merb_plugin/templates/spec_helper.rb +2 -0
- data/bin/merb +1 -1
- data/lib/autotest/discover.rb +3 -0
- data/lib/autotest/merb_rspec.rb +79 -0
- data/lib/merb.rb +72 -93
- data/lib/merb/{merb_abstract_controller.rb → abstract_controller.rb} +28 -5
- data/lib/merb/caching/action_cache.rb +65 -29
- data/lib/merb/caching/fragment_cache.rb +9 -4
- data/lib/merb/caching/store/file_cache.rb +22 -14
- data/lib/merb/caching/store/memory_cache.rb +26 -8
- data/lib/merb/{merb_constants.rb → constants.rb} +9 -7
- data/lib/merb/controller.rb +178 -0
- data/lib/merb/core_ext.rb +13 -11
- data/lib/merb/core_ext/array.rb +0 -0
- data/lib/merb/core_ext/{merb_class.rb → class.rb} +0 -0
- data/lib/merb/core_ext/{merb_enumerable.rb → enumerable.rb} +0 -0
- data/lib/merb/core_ext/get_args.rb +52 -0
- data/lib/merb/core_ext/{merb_hash.rb → hash.rb} +40 -11
- data/lib/merb/core_ext/{merb_inflections.rb → inflections.rb} +0 -0
- data/lib/merb/core_ext/{merb_inflector.rb → inflector.rb} +1 -1
- data/lib/merb/core_ext/{merb_kernel.rb → kernel.rb} +56 -3
- data/lib/merb/core_ext/mash.rb +88 -0
- data/lib/merb/core_ext/{merb_module.rb → module.rb} +0 -0
- data/lib/merb/core_ext/{merb_numeric.rb → numeric.rb} +0 -0
- data/lib/merb/core_ext/{merb_object.rb → object.rb} +10 -47
- data/lib/merb/core_ext/string.rb +56 -0
- data/lib/merb/core_ext/{merb_symbol.rb → symbol.rb} +0 -0
- data/lib/merb/dispatcher.rb +109 -0
- data/lib/merb/{merb_drb_server.rb → drb_server.rb} +0 -0
- data/lib/merb/erubis_ext.rb +10 -0
- data/lib/merb/exceptions.rb +173 -0
- data/lib/merb/generators/merb_app/merb_app.rb +5 -25
- data/lib/merb/generators/merb_generator_helpers.rb +317 -0
- data/lib/merb/generators/merb_plugin.rb +19 -0
- data/lib/merb/logger.rb +65 -0
- data/lib/merb/{merb_mail_controller.rb → mail_controller.rb} +102 -49
- data/lib/merb/{merb_mailer.rb → mailer.rb} +31 -27
- data/lib/merb/mixins/{basic_authentication_mixin.rb → basic_authentication.rb} +3 -3
- data/lib/merb/mixins/{controller_mixin.rb → controller.rb} +131 -112
- data/lib/merb/mixins/{erubis_capture_mixin.rb → erubis_capture.rb} +12 -21
- data/lib/merb/mixins/{form_control_mixin.rb → form_control.rb} +6 -12
- data/lib/merb/mixins/render.rb +401 -0
- data/lib/merb/mixins/responder.rb +378 -0
- data/lib/merb/mixins/{view_context_mixin.rb → view_context.rb} +65 -10
- data/lib/merb/mixins/web_controller.rb +29 -0
- data/lib/merb/{merb_handler.rb → mongrel_handler.rb} +59 -38
- data/lib/merb/part_controller.rb +19 -0
- data/lib/merb/plugins.rb +16 -0
- data/lib/merb/rack_adapter.rb +37 -0
- data/lib/merb/request.rb +421 -0
- data/lib/merb/router.rb +576 -0
- data/lib/merb/{merb_server.rb → server.rb} +275 -71
- data/lib/merb/session.rb +10 -10
- data/lib/merb/session/cookie_store.rb +125 -0
- data/lib/merb/session/{merb_mem_cache_session.rb → mem_cache_session.rb} +22 -9
- data/lib/merb/session/{merb_memory_session.rb → memory_session.rb} +15 -11
- data/lib/merb/template.rb +35 -8
- data/lib/merb/template/erubis.rb +16 -10
- data/lib/merb/template/haml.rb +33 -20
- data/lib/merb/template/markaby.rb +16 -14
- data/lib/merb/template/xml_builder.rb +8 -4
- data/lib/merb/test/{merb_fake_request.rb → fake_request.rb} +11 -5
- data/lib/merb/test/helper.rb +31 -0
- data/lib/merb/test/hpricot.rb +136 -0
- data/lib/merb/test/{merb_multipart.rb → multipart.rb} +1 -1
- data/lib/merb/test/rspec.rb +93 -0
- data/lib/merb/{merb_upload_handler.rb → upload_handler.rb} +5 -6
- data/lib/merb/{merb_upload_progress.rb → upload_progress.rb} +1 -1
- data/lib/merb/{merb_view_context.rb → view_context.rb} +27 -42
- data/lib/{merb_tasks.rb → tasks.rb} +0 -0
- data/lib/tasks/merb.rake +21 -11
- data/merb_default_generators/model/USAGE +0 -0
- data/merb_default_generators/model/model_generator.rb +16 -0
- data/merb_default_generators/model/templates/new_model_template.erb +5 -0
- data/merb_default_generators/resource_controller/USAGE +0 -0
- data/merb_default_generators/resource_controller/resource_controller_generator.rb +26 -0
- data/merb_default_generators/resource_controller/templates/controller.rb +30 -0
- data/merb_default_generators/resource_controller/templates/edit.html.erb +1 -0
- data/merb_default_generators/resource_controller/templates/helper.rb +5 -0
- data/merb_default_generators/resource_controller/templates/index.html.erb +1 -0
- data/merb_default_generators/resource_controller/templates/new.html.erb +1 -0
- data/merb_default_generators/resource_controller/templates/show.html.erb +1 -0
- data/merb_generators/controller/USAGE +5 -0
- data/merb_generators/controller/controller_generator.rb +16 -0
- data/merb_generators/controller/templates/controller.rb +8 -0
- data/merb_generators/controller/templates/helper.rb +5 -0
- data/merb_generators/controller/templates/index.html.erb +3 -0
- data/merb_generators/resource/USAGE +0 -0
- data/merb_generators/resource/resource_generator.rb +60 -0
- data/rspec_generators/merb_controller_test/merb_controller_test_generator.rb +67 -0
- data/rspec_generators/merb_controller_test/templates/controller_spec.rb +8 -0
- data/rspec_generators/merb_controller_test/templates/edit_spec.rb +12 -0
- data/rspec_generators/merb_controller_test/templates/helper_spec.rb +5 -0
- data/rspec_generators/merb_controller_test/templates/index_spec.rb +12 -0
- data/rspec_generators/merb_controller_test/templates/new_spec.rb +12 -0
- data/rspec_generators/merb_controller_test/templates/show_spec.rb +5 -0
- data/rspec_generators/merb_model_test/merb_model_test_generator.rb +26 -0
- data/rspec_generators/merb_model_test/templates/model_spec_template.erb +7 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/test_unit_generators/merb_controller_test/merb_controller_test_generator.rb +53 -0
- data/test_unit_generators/merb_controller_test/templates/functional_test.rb +17 -0
- data/test_unit_generators/merb_controller_test/templates/helper_test.rb +9 -0
- data/test_unit_generators/merb_model_test/merb_model_test_generator.rb +29 -0
- data/test_unit_generators/merb_model_test/templates/model_test_unit_template.erb +9 -0
- metadata +172 -94
- data/examples/README_EXAMPLES +0 -10
- data/examples/skeleton/Rakefile +0 -68
- data/examples/skeleton/dist/app/views/layout/application.herb +0 -12
- data/examples/skeleton/dist/conf/database.yml +0 -23
- data/examples/skeleton/dist/conf/merb.yml +0 -57
- data/examples/skeleton/dist/conf/merb_init.rb +0 -24
- data/examples/skeleton/dist/conf/router.rb +0 -22
- data/examples/skeleton/dist/conf/upload.conf +0 -5
- data/examples/skeleton/dist/schema/migrations/001_add_sessions_table.rb +0 -14
- data/examples/skeleton/script/new_migration +0 -21
- data/lib/merb/core_ext/merb_string.rb +0 -18
- data/lib/merb/merb_controller.rb +0 -206
- data/lib/merb/merb_dispatcher.rb +0 -87
- data/lib/merb/merb_exceptions.rb +0 -319
- data/lib/merb/merb_part_controller.rb +0 -42
- data/lib/merb/merb_plugins.rb +0 -293
- data/lib/merb/merb_request.rb +0 -165
- data/lib/merb/merb_router.rb +0 -309
- data/lib/merb/merb_yaml_store.rb +0 -31
- data/lib/merb/mixins/render_mixin.rb +0 -283
- data/lib/merb/mixins/responder_mixin.rb +0 -159
- data/lib/merb/session/merb_ar_session.rb +0 -131
- data/lib/merb/vendor/paginator/README.txt +0 -84
- data/lib/merb/vendor/paginator/paginator.rb +0 -124
- data/lib/tasks/db.rake +0 -55
|
File without changes
|
|
@@ -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
|
-
|
|
11
|
-
|
|
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
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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
|