mack 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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