mack 0.0.3

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 (55) hide show
  1. data/README +43 -0
  2. data/bin/mack +60 -0
  3. data/bin/templates/Rakefile.template +6 -0
  4. data/bin/templates/app/controllers/default_controller.rb.template +7 -0
  5. data/bin/templates/app/helpers/application_helper.rb.template +2 -0
  6. data/bin/templates/app/views/default/index.html.erb.template +3 -0
  7. data/bin/templates/app/views/layouts/application.html.erb.template +15 -0
  8. data/bin/templates/config/app_config/default.yml.template +7 -0
  9. data/bin/templates/config/app_config/development.yml.template +0 -0
  10. data/bin/templates/config/app_config/production.yml.template +0 -0
  11. data/bin/templates/config/app_config/test.yml.template +0 -0
  12. data/bin/templates/config/boot.rb.template +6 -0
  13. data/bin/templates/config/database.yml.template +20 -0
  14. data/bin/templates/config/routes.rb.template +7 -0
  15. data/bin/templates/config/thin.ru.template +1 -0
  16. data/bin/templates/config/thin.yml.template +8 -0
  17. data/bin/templates/public/favicon.ico +0 -0
  18. data/bin/templates/public/stylesheets/scaffold.css.template +74 -0
  19. data/core_extensions/hash.rb +9 -0
  20. data/core_extensions/module.rb +29 -0
  21. data/core_extensions/nil.rb +8 -0
  22. data/core_extensions/object.rb +9 -0
  23. data/core_extensions/string.rb +28 -0
  24. data/errors/errors.rb +79 -0
  25. data/initialize/configuration.rb +99 -0
  26. data/initialize/configure_logging.rb +24 -0
  27. data/initialize/configure_orm_support.rb +23 -0
  28. data/initialize/console.rb +13 -0
  29. data/initialize/initializer.rb +88 -0
  30. data/initialize/server/simple_server.rb +21 -0
  31. data/lib/utils/html.rb +88 -0
  32. data/lib/utils/server.rb +27 -0
  33. data/mack.rb +124 -0
  34. data/mack_tasks.rb +16 -0
  35. data/routing/route_map.rb +268 -0
  36. data/routing/urls.rb +54 -0
  37. data/sea_level/controller_base.rb +293 -0
  38. data/sea_level/cookie_jar.rb +67 -0
  39. data/sea_level/filter.rb +63 -0
  40. data/sea_level/helpers/view_helpers/html_helpers.rb +33 -0
  41. data/sea_level/helpers/view_helpers/orm_helpers.rb +72 -0
  42. data/sea_level/request.rb +83 -0
  43. data/sea_level/response.rb +6 -0
  44. data/sea_level/session.rb +33 -0
  45. data/sea_level/view_binder.rb +101 -0
  46. data/tasks/cachetastic_tasks.rake +69 -0
  47. data/tasks/log_tasks.rake +9 -0
  48. data/tasks/mack_tasks.rake +15 -0
  49. data/tasks/rake_helpers.rb +24 -0
  50. data/tasks/rake_rules.rake +19 -0
  51. data/tasks/script_tasks.rake +44 -0
  52. data/tasks/test_tasks.rake +7 -0
  53. data/test_extensions/test_assertions.rb +47 -0
  54. data/test_extensions/test_helpers.rb +84 -0
  55. metadata +173 -0
@@ -0,0 +1,67 @@
1
+ module Mack
2
+
3
+ # Examples:
4
+ # class MyAwesomeController < Mack::Controller::Base
5
+ # def index
6
+ # cookies[:id] = 1
7
+ # render(:text => "Hello!")
8
+ # end
9
+ #
10
+ # def show
11
+ # render(:text => "The id in the cookie is: #{cookies[:id]}")
12
+ # end
13
+ # end
14
+ class CookieJar
15
+
16
+ attr_reader :all_cookies # :nodoc:
17
+ attr_reader :request # :nodoc:
18
+ attr_reader :response # :nodoc:
19
+
20
+ def initialize(request, response) # :nodoc:
21
+ @request = request
22
+ @response = response
23
+ @all_cookies = request.cookies
24
+ end
25
+
26
+ # Returns the value of a cookie as a String, or nil it doesn't exist.
27
+ # This will check both the incoming cookies on the request, as well as
28
+ # any cookies that have been set as part of the current action.
29
+ def [](key)
30
+ return nil if key.nil?
31
+ # check both the incoming cookies and the outgoing cookies to see if
32
+ # the cookie we're looking for exists.
33
+ c = (self.all_cookies[key.to_s] || self.all_cookies[key.to_sym])
34
+ return c if c.is_a?(String)
35
+ return c[:value] if c.is_a?(Hash)
36
+ return nil
37
+ end
38
+
39
+ # Set a cookie with a specified value.
40
+ def []=(key, value)
41
+ key = key.to_s
42
+ unless value.is_a?(Hash)
43
+ value = {:value => value}
44
+ end
45
+ value = app_config.mack.cookie_values.merge(value)
46
+ self.all_cookies[key] = value
47
+ self.response.set_cookie(key, value)
48
+ end
49
+
50
+ # Deletes a cookie.
51
+ def delete(key)
52
+ key = key.to_s
53
+ self.all_cookies.delete(key)
54
+ self.response.delete_cookie(key)
55
+ end
56
+
57
+ # Returns both cookies that came in as part of the request, as well as those set
58
+ # on to the response. This is useful when you set a cookie in a filter or an action
59
+ # and want to access it in another filter or action before the request/response has
60
+ # been fully completed.
61
+ def all
62
+ self.all_cookies
63
+ end
64
+
65
+ end # CookieJar
66
+
67
+ end # Mack
@@ -0,0 +1,63 @@
1
+ module Mack
2
+ module Controller
3
+ # A wrapper class to hold calls to filter methods for Controllers.
4
+ # This class should never be called by itself. Instead there are helper
5
+ # methods in Mack::Controller::Base to do this for.
6
+ #
7
+ # Examples:
8
+ # class MyAwesomeController < Mack::Controller::Base
9
+ # # all actions in this controller will have this filter run:
10
+ # before_filter: authenticate
11
+ # # only the show and index actions in this controller will have this filter run:
12
+ # before_filter: load_side_bar, :only => [:show, :index]
13
+ # # all actions, except for the create action will have this filter run.
14
+ # after_filter: write_to_log, :except => :create
15
+ # end
16
+ #
17
+ # Filter methods need to be scoped to the controller that is to run them.
18
+ # There are three different filters available: <tt>before</tt>, <tt>after</tt> and <tt>after_render</tt>.
19
+ #
20
+ # <tt>before</tt> filters get run before an action is called. This is a great place to set up common
21
+ # elements needed for your action. Things like authentication should be done here, etc...
22
+ #
23
+ # <tt>after</tt> filters get run after an action has been called. This is a great place to set up common
24
+ # elements for a view, that depend on stuff from inside your action. Because nothing has been 'rendered'
25
+ # yet, you still can add new instance variables, and alter ones created in the action.
26
+ #
27
+ # <tt>after_render</tt> filters get run after the rendering of the action has happened. At this point
28
+ # there is an instance variable, <tt>@final_rendered_action</tt>, that is available on which work can be done.
29
+ # This variable will have any layouts rendered to, any ERB will have been processed, etc... It should be the final
30
+ # String that will get rendered to the screen. This is a great place to do things like write a log, gzip, etc...
31
+ class Filter
32
+
33
+ attr_reader :filter_method
34
+ attr_reader :action_list
35
+
36
+ def initialize(filter_method, action_list = {})
37
+ @filter_method = filter_method
38
+ clean_action_list(action_list)
39
+ end
40
+
41
+ def run?(action)
42
+ return true if action_list.empty?
43
+ if action_list[:only]
44
+ return action_list[:only].include?(action)
45
+ elsif action_list[:except]
46
+ return !action_list[:except].include?(action)
47
+ end
48
+ return false
49
+ end
50
+
51
+ private
52
+ def clean_action_list(action_list)
53
+ if action_list[:only]
54
+ action_list[:only] = [action_list[:only]].flatten
55
+ elsif action_list[:except]
56
+ action_list[:except] = [action_list[:except]].flatten
57
+ end
58
+ @action_list = action_list
59
+ end
60
+
61
+ end # Fitler
62
+ end # Controller
63
+ end # Mack
@@ -0,0 +1,33 @@
1
+ module Mack
2
+ module ViewHelpers
3
+ module HtmlHelpers
4
+
5
+ # This is just an alias to Mack::Utils::Html.
6
+ #
7
+ # Examples:
8
+ # <%= link_to("http://www.mackframework.com") %> # => <a href="http://www.mackframework.com">http://www.mackframework.com</a>
9
+ # <%= link_to("Mack", "http://www.mackframework.com") %> # => <a href="http://www.mackframework.com">Mack</a>
10
+ # <%= link_to("Mack", "http://www.mackframework.com", :target => "_blank") %> # => <a href="http://www.mackframework.com" target="_blank">Mack</a>
11
+ # <%= link_to("Mack", "http://www.mackframework.com", :target => "_blank", :rel => :nofollow) %> # => <a href="http://www.mackframework.com" target="_blank" rel="nofollow">Mack</a>
12
+ # If you pass in :method as an option it will be a JavaScript form that will post to the specified link with the
13
+ # methd specified.
14
+ # <%= link_to("Mack", "http://www.mackframework.com", :method => :delete) %>
15
+ # If you use the :method option you can also pass in a :confirm option. The :confirm option will generate a
16
+ # javascript confirmation window. If 'OK' is selected the the form will submit. If 'cancel' is selected, then
17
+ # nothing will happen. This is extremely useful for 'delete' type of links.
18
+ # <%= link_to("Mack", "http://www.mackframework.com", :method => :delete, :confirm => "Are you sure?") %>
19
+ def link_to(link_text, url = link_text, html_options = {})
20
+ Mack::Utils::Html.href(link_text, url, html_options)
21
+ end
22
+
23
+ # A wrapper method for views that calls out to Mack::Utils::Html.
24
+ #
25
+ # Examples:
26
+ # <%= html.b("hello") %> # => <b>hello</b>
27
+ def html
28
+ Mack::Utils::Html
29
+ end
30
+
31
+ end # HtmlHelpers
32
+ end # ViewHelpers
33
+ end # Mack
@@ -0,0 +1,72 @@
1
+ if using_activerecord?
2
+ class ActiveRecord::Base # :nodoc:
3
+ def business_display_name
4
+ self.class.name#.titlecase
5
+ end
6
+ end
7
+ end
8
+
9
+ if using_data_mapper?
10
+ class DataMapper::Base # :nodoc:
11
+ def business_display_name
12
+ self.class.name#.titlecase
13
+ end
14
+ end
15
+ end
16
+
17
+ module Mack
18
+ module ViewHelpers
19
+ module OrmHelpers
20
+ DEFAULT_PARTIAL = %{
21
+ <div>
22
+ <div class="errorExplanation" id="errorExplanation">
23
+ <h2>Oi, there were errors! Fix `em!</h2>
24
+ <ul>
25
+ <% for error in errors %>
26
+ <li><%= error %></li>
27
+ <% end %>
28
+ </ul>
29
+ </div>
30
+ </div>
31
+ }
32
+
33
+ def error_messages_for(object_names = [], view_partial = nil)
34
+ object_names = [object_names]
35
+ object_names.flatten!
36
+ app_errors = []
37
+ object_names.each do |name|
38
+ object = instance_variable_get("@#{name}")
39
+ if object
40
+ object.errors.each do |key, value|
41
+ if value.match(/^\^/)
42
+ app_errors << value[1..value.length]
43
+ else
44
+ if key.class == String and key == "base"
45
+ app_errors << "#{value}"
46
+ else
47
+ app_errors << "#{object.business_display_name} #{key.underscore.split('_').join(' ').humanize} #{value}"
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ File.join(MACK_VIEWS, "application", "_error_messages.html.erb")
54
+ unless app_errors.empty?
55
+ if view_partial.nil?
56
+ if File.exist?(File.join(MACK_VIEWS, "application", "_error_messages.html.erb"))
57
+ render :partial => "application/error_messages", :locals => {:errors => app_errors}
58
+ else
59
+ render :text => DEFAULT_PARTIAL, :locals => {:errors => app_errors}
60
+ end
61
+ else
62
+ render :partial => view_partial, :locals => {:errors => app_errors}
63
+ end
64
+ else
65
+ ""
66
+ end
67
+ end
68
+
69
+ # self.include_safely_into(Mack::ViewBinder)
70
+ end # OrmHelpers
71
+ end # ViewHelpers
72
+ end # Mack
@@ -0,0 +1,83 @@
1
+ module Mack
2
+ class Request < Rack::Request
3
+
4
+ def initialize(env) # :nodoc:
5
+ super(env)
6
+ @mack_params = {}
7
+ parse_params(rack_params)
8
+ end
9
+
10
+ alias_method :rack_params, :params # :nodoc:
11
+
12
+ # Returns all parameters associated with this request.
13
+ def all_params
14
+ @mack_params
15
+ end
16
+
17
+ # Merges another Hash with the parameters for this request.
18
+ def merge_params(opts = {})
19
+ parse_params(opts)
20
+ end
21
+
22
+ # Gives access to the session. See Mack::Session for more information.
23
+ attr_accessor :session
24
+
25
+ # Examples:
26
+ # http://example.org
27
+ # https://example.org
28
+ # http://example.org:8080
29
+ def full_host
30
+ u = self.scheme.dup
31
+ u << "://"
32
+ u << self.host.dup
33
+ unless self.port == 80 || self.port == 443
34
+ u << ":#{self.port}"
35
+ end
36
+ u
37
+ end
38
+
39
+ # Examples:
40
+ # http://example.org:80
41
+ # https://example.org:443
42
+ # http://example.org:8080
43
+ def full_host_with_port
44
+ full_host << ":#{self.port}"
45
+ end
46
+
47
+ # Gives access to the request parameters. This includes 'get' parameters, 'post' parameters
48
+ # as well as parameters from the routing process. The parameter will also be 'unescaped'
49
+ # when it is returned.
50
+ #
51
+ # Example:
52
+ # uri: '/users/1?foo=bar'
53
+ # route: '/users/:id' => {:controller => 'users', :action => 'show'}
54
+ # parameters: {:controller => 'users', :action => 'show', :id => 1, :foo => "bar"}
55
+ def params(key)
56
+ p = (@mack_params[key.to_sym] || @mack_params[key.to_s])
57
+ unless p.nil?
58
+ p = p.to_s if p.is_a?(Symbol)
59
+ if p.is_a?(String)
60
+ p = Rack::Utils.unescape(p)
61
+ elsif p.is_a?(Hash)
62
+ p.each_pair {|k,v| p[k] = Rack::Utils.unescape(v)}
63
+ end
64
+ end
65
+ p
66
+ end
67
+
68
+ private
69
+ def parse_params(ps)
70
+ ps.each_pair do |k, v|
71
+ if k.to_s.match(/.+\[.+\]/)
72
+ nv = k.to_s.match(/.+\[(.+)\]/).captures.first
73
+ nk = k.to_s.match(/(.+)\[.+\]/).captures.first
74
+ @mack_params[nk.to_sym] = {} if @mack_params[nk.to_sym].nil?
75
+ @mack_params[nk.to_sym].merge!(nv.to_sym => v)
76
+ else
77
+ @mack_params[k.to_sym] = v
78
+ end
79
+ end
80
+ end
81
+
82
+ end
83
+ end
@@ -0,0 +1,6 @@
1
+ module Mack
2
+ # Right now Mack::Response is just a wrapper around Rack::Response.
3
+ # Down the line this may be used to spice up the response.
4
+ class Response < Rack::Response
5
+ end
6
+ end
@@ -0,0 +1,33 @@
1
+ module Mack
2
+
3
+ # A holder for the session information. This objects gets stored using the Cachetastic system.
4
+ # For more information about how Cachetastic works see the RDoc for that gem.
5
+ # The session cookie name defaults to: _mack_session_id but can be changed using the application_configuration
6
+ # system like such:
7
+ # mack::session_id: _my_cool_app_sess_id
8
+ class Session
9
+
10
+ attr_reader :id # The id of the session.
11
+
12
+ def initialize(id)
13
+ @id = id
14
+ @sess_hash = {}
15
+ end
16
+
17
+ # Finds what you're looking for in the session, if it exists.
18
+ # If what you're looking for doesn't exist, it returns nil.
19
+ def [](key)
20
+ sess_hash[key.to_sym]
21
+ end
22
+
23
+ # Sets a value into the session.
24
+ def []=(key, value)
25
+ sess_hash[key.to_sym] = value
26
+ end
27
+
28
+ private
29
+ attr_reader :sess_hash # :nodoc:
30
+
31
+ end # Session
32
+
33
+ end # Mack
@@ -0,0 +1,101 @@
1
+ # require 'erubis'
2
+ # This class is used to do all the view level bindings.
3
+ # It allows for seperation between the controller and the view levels.
4
+ class Mack::ViewBinder
5
+
6
+ attr_accessor :controller # Allows access to the controller.
7
+ attr_accessor :options # Allows access to any options passed into the Binder.
8
+
9
+ def initialize(cont, opts = {})
10
+ self.controller = cont
11
+ self.options = {:locals => {}}.merge(opts)
12
+ transfer_vars(@controller)
13
+ end
14
+
15
+ # Returns the binding for this class.
16
+ def view_binding
17
+ binding
18
+ end
19
+
20
+ # If a method can not be found then the :locals key of
21
+ # the options is used to find the variable.
22
+ def method_missing(sym, *args)
23
+ self.options[:locals][sym]
24
+ end
25
+
26
+ # Handles rendering calls both in the controller and in the view.
27
+ # For full details of render examples see Mack::Controller::Base render.
28
+ # Although the examples there are all in controllers, they idea is still
29
+ # the same for views.
30
+ #
31
+ # Examples in the view:
32
+ # <%= render(:text => "Hello") %>
33
+ # <%= render(:action => "show") %>
34
+ # <%= render(:partial => :latest_news) %>
35
+ def render(options = {})
36
+ if options[:action]
37
+ begin
38
+ # Try to render the action:
39
+ return render_file(options[:action], options)
40
+ rescue Errno::ENOENT => e
41
+ begin
42
+ # If the action doesn't exist on disk, try to render it from the public directory:
43
+ t = render_file(options[:action], {:dir => MACK_PUBLIC, :ext => ".html", :layout => false}.merge(options))
44
+ # Because it's being served from public don't wrap a layout around it!
45
+ # self.controller.instance_variable_get("@render_options").merge!({:layout => false})
46
+ return t
47
+ rescue Errno::ENOENT => ex
48
+ end
49
+ # Raise the original exception because something bad has happened!
50
+ raise e
51
+ end
52
+ elsif options[:text]
53
+ return Mack::ViewBinder.render(options[:text], self.controller, options)
54
+ elsif options[:partial]
55
+ return render_file(options[:partial], {:is_partial => true}.merge(options))
56
+ elsif options[:public]
57
+ t = render_file(options[:public], {:dir => MACK_PUBLIC, :ext => ".html", :layout => false}.merge(options))
58
+ # self.controller.instance_variable_get("@render_options").merge!({:layout => false})
59
+ return t
60
+ else
61
+ raise Mack::UnknownRenderOption.new(options)
62
+ end
63
+ end
64
+
65
+ private
66
+ def render_file(f, options = {})
67
+ options = {:is_partial => false, :ext => ".html.erb", :dir => MACK_VIEWS}.merge(options)
68
+ partial = f.to_s
69
+ parts = partial.split("/")
70
+ if parts.size == 1
71
+ # it's local to this controller
72
+ partial = "_" << partial if options[:is_partial]
73
+ partial = File.join(options[:dir], self.controller.controller_name, partial + options[:ext])
74
+ else
75
+ # it's elsewhere
76
+ parts[parts.size - 1] = "_" << parts.last if options[:is_partial]
77
+ partial = File.join(options[:dir], parts.join("/") + options[:ext])
78
+ end
79
+ return Mack::ViewBinder.render(File.open(partial).read, self.controller, options)
80
+ end
81
+
82
+ # Transfer instance variables from the controller to the view.
83
+ def transfer_vars(x)
84
+ x.instance_variables.each do |v|
85
+ self.instance_variable_set(v, x.instance_variable_get(v))
86
+ end
87
+ end
88
+
89
+ class << self
90
+
91
+ # Creates a Mack::ViewBinder and then passes the io through ERB
92
+ # and returns a String. The io can be either an IO object or a String.
93
+ def render(io, controller, options = {})
94
+ vb = Mack::ViewBinder.new(controller, options)
95
+ return ERB.new(io).result(vb.view_binding)
96
+ # return Erubis::Eruby.new(io).result(vb.view_binding)
97
+ end
98
+
99
+ end
100
+
101
+ end