mack 0.7.0.1 → 0.7.1

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 (58) hide show
  1. data/CHANGELOG +34 -0
  2. data/README +6 -13
  3. data/bin/env_handler.rb +10 -0
  4. data/bin/gem_load_path.rb +25 -0
  5. data/bin/mack +1 -0
  6. data/bin/mackery +22 -0
  7. data/bin/mackery-console +16 -0
  8. data/bin/mackery-server +41 -0
  9. data/lib/mack.rb +7 -1
  10. data/lib/mack/controller/controller.rb +5 -4
  11. data/lib/mack/controller/request.rb +19 -1
  12. data/lib/mack/errors/errors.rb +8 -8
  13. data/lib/mack/generators/controller_generator/controller_generator.rb +1 -1
  14. data/lib/mack/generators/mack_application_generator/templates/app/views/layouts/application.html.erb.template +1 -2
  15. data/lib/mack/generators/mack_application_generator/templates/config/app_config/default.yml.template +2 -0
  16. data/lib/mack/generators/mack_application_generator/templates/config/database.yml.template +6 -6
  17. data/lib/mack/generators/passenger_generator/passenger_generator.rb +2 -0
  18. data/lib/mack/generators/passenger_generator/templates/config.ru.template +5 -0
  19. data/lib/mack/generators/passenger_generator/templates/tmp/README.template +2 -0
  20. data/lib/mack/initialization/application.rb +39 -36
  21. data/lib/mack/initialization/boot_loader.rb +174 -0
  22. data/lib/mack/initialization/configuration.rb +83 -95
  23. data/lib/mack/initialization/console.rb +11 -0
  24. data/lib/mack/initialization/environment.rb +16 -0
  25. data/lib/mack/initialization/helpers.rb +26 -24
  26. data/lib/mack/initialization/logging.rb +81 -81
  27. data/lib/mack/initialization/plugins.rb +14 -11
  28. data/lib/mack/initialization/server/simple_server.rb +3 -3
  29. data/lib/mack/rendering/type/base.rb +1 -1
  30. data/lib/mack/rendering/type/layout.rb +1 -1
  31. data/lib/mack/rendering/type/partial.rb +1 -1
  32. data/lib/mack/rendering/type/public.rb +1 -1
  33. data/lib/mack/rendering/type/template.rb +1 -1
  34. data/lib/mack/runner.rb +2 -2
  35. data/lib/mack/runner_helpers/session.rb +3 -3
  36. data/lib/mack/sessions/cookie_session_store.rb +44 -0
  37. data/lib/mack/{controller → sessions}/session.rb +0 -0
  38. data/lib/mack/sessions/session_store_base.rb +62 -0
  39. data/lib/mack/sessions/test_session_store.rb +38 -0
  40. data/lib/mack/tasks/mack_server_tasks.rake +8 -21
  41. data/lib/mack/tasks/mack_tasks.rake +33 -6
  42. data/lib/mack/tasks/rake_rules.rake +8 -0
  43. data/lib/mack/tasks/test_tasks.rake +39 -15
  44. data/lib/mack/testing/helpers.rb +6 -39
  45. data/lib/mack/utils/content_length_handler.rb +45 -0
  46. data/lib/mack/utils/forgery_detector.rb +152 -0
  47. data/lib/mack/utils/gem_manager.rb +22 -1
  48. data/lib/mack/utils/paths.rb +154 -0
  49. data/lib/mack/utils/server.rb +8 -6
  50. data/lib/mack/version.rb +1 -1
  51. data/lib/mack/view_helpers/asset_helpers.rb +50 -0
  52. data/lib/mack/view_helpers/form_helpers.rb +52 -6
  53. data/lib/mack/view_helpers/link_helpers.rb +6 -3
  54. data/lib/mack_app.rb +12 -14
  55. data/lib/mack_core.rb +35 -14
  56. data/lib/mack_tasks.rb +35 -20
  57. metadata +23 -27
  58. data/lib/mack/tasks/cachetastic_tasks.rake +0 -58
@@ -45,17 +45,34 @@ module Mack
45
45
  end
46
46
  end
47
47
 
48
+ # Requires the gem and any libs that you've specified.
49
+ def do_task_requires
50
+ @required_gem_list.each do |g|
51
+ begin
52
+ if g.version?
53
+ gem(g.name, g.version)
54
+ else
55
+ gem(g.name)
56
+ end
57
+ g.tasks.each { |l| require l.to_s } if g.tasks?
58
+ rescue Exception => e
59
+ end
60
+ end
61
+ end
62
+
48
63
  private
49
64
  class GemObject # :nodoc:
50
65
  attr_accessor :name
51
66
  attr_accessor :version
52
67
  attr_accessor :libs
68
+ attr_accessor :tasks
53
69
  attr_accessor :source
54
70
 
55
71
  def initialize(name, options = {})
56
72
  self.name = name
57
73
  self.version = options[:version]
58
74
  self.libs = [options[:libs]].flatten.compact
75
+ self.tasks = [options[:tasks], "#{name}_tasks"].flatten.compact
59
76
  self.source = options[:source]
60
77
  end
61
78
 
@@ -66,7 +83,7 @@ module Mack
66
83
  end
67
84
 
68
85
  def libs?
69
- !self.libs.empty?
86
+ self.libs.any?
70
87
  end
71
88
 
72
89
  def version?
@@ -77,6 +94,10 @@ module Mack
77
94
  !self.source.blank?
78
95
  end
79
96
 
97
+ def tasks?
98
+ self.tasks.any?
99
+ end
100
+
80
101
  end
81
102
 
82
103
  end # GemManager
@@ -0,0 +1,154 @@
1
+ module Mack
2
+ module Paths
3
+
4
+ # <MACK_PROJECT_ROOT>
5
+ def self.root(*files)
6
+ File.join(Mack.root, files)
7
+ end
8
+
9
+ # <MACK_PROJECT_ROOT>/public
10
+ def self.public(*files)
11
+ Mack::Paths.root("public", files)
12
+ end
13
+
14
+ # <MACK_PROJECT_ROOT>/public/images
15
+ def self.images(*files)
16
+ Mack::Paths.public("images", files)
17
+ end
18
+
19
+ # <MACK_PROJECT_ROOT>/public/javascripts
20
+ def self.javascripts(*files)
21
+ Mack::Paths.public("javascripts", files)
22
+ end
23
+
24
+ # <MACK_PROJECT_ROOT>/public/stylesheets
25
+ def self.stylesheets(*files)
26
+ Mack::Paths.public("stylesheets", files)
27
+ end
28
+
29
+ # <MACK_PROJECT_ROOT>/app
30
+ def self.app(*files)
31
+ Mack::Paths.root("app", files)
32
+ end
33
+
34
+ # <MACK_PROJECT_ROOT>/log
35
+ def self.log(*files)
36
+ Mack::Paths.root("log", files)
37
+ end
38
+
39
+ # <MACK_PROJECT_ROOT>/test
40
+ def self.test(*files)
41
+ Mack::Paths.root("test", files)
42
+ end
43
+
44
+ # <MACK_PROJECT_ROOT>/tmp
45
+ def self.tmp(*files)
46
+ Mack::Paths.root("tmp", files)
47
+ end
48
+
49
+ # <MACK_PROJECT_ROOT>/test/models
50
+ def self.model_tests(*files)
51
+ Mack::Paths.test("models", files)
52
+ end
53
+
54
+ # <MACK_PROJECT_ROOT>/test/controllers
55
+ def self.controller_tests(*files)
56
+ Mack::Paths.test("controllers", files)
57
+ end
58
+
59
+ def self.test_helpers(*files)
60
+ Mack::Paths.test("helpers", files)
61
+ end
62
+
63
+ # <MACK_PROJECT_ROOT>/test/helpers/controllers
64
+ def self.controller_helper_tests(*files)
65
+ Mack::Paths.test_helpers("controllers", files)
66
+ end
67
+
68
+ # <MACK_PROJECT_ROOT>/test/helpers/views
69
+ def self.view_helper_tests(*files)
70
+ Mack::Paths.test_helpers("views", files)
71
+ end
72
+
73
+ # <MACK_PROJECT_ROOT>/app/views
74
+ def self.views(*files)
75
+ Mack::Paths.app("views", files)
76
+ end
77
+
78
+ # <MACK_PROJECT_ROOT>/app/views/layouts
79
+ def self.layouts(*files)
80
+ Mack::Paths.views("layouts", files)
81
+ end
82
+
83
+ # <MACK_PROJECT_ROOT>/app/controllers
84
+ def self.controllers(*files)
85
+ Mack::Paths.app("controllers", files)
86
+ end
87
+
88
+ # <MACK_PROJECT_ROOT>/app/models
89
+ def self.models(*files)
90
+ Mack::Paths.app("models", files)
91
+ end
92
+
93
+ # <MACK_PROJECT_ROOT>/app/helpers
94
+ def self.helpers(*files)
95
+ Mack::Paths.app("helpers", files)
96
+ end
97
+
98
+ # <MACK_PROJECT_ROOT>/app/helpers/controllers
99
+ def self.controller_helpers(*files)
100
+ Mack::Paths.helpers("controllers", files)
101
+ end
102
+
103
+ # <MACK_PROJECT_ROOT>/app/helpers/views
104
+ def self.view_helpers(*files)
105
+ Mack::Paths.helpers("views", files)
106
+ end
107
+
108
+ # <MACK_PROJECT_ROOT>/lib
109
+ def self.lib(*files)
110
+ Mack::Paths.root("lib", files)
111
+ end
112
+
113
+ # <MACK_PROJECT_ROOT>/lib/tasks
114
+ def self.tasks(*files)
115
+ Mack::Paths.lib("tasks", files)
116
+ end
117
+
118
+ # <MACK_PROJECT_ROOT>/db
119
+ def self.db(*files)
120
+ Mack::Paths.root("db", files)
121
+ end
122
+
123
+ # <MACK_PROJECT_ROOT>/db/migrations
124
+ def self.migrations(*files)
125
+ Mack::Paths.db("migrations", files)
126
+ end
127
+
128
+ # <MACK_PROJECT_ROOT>/config
129
+ def self.config(*files)
130
+ Mack::Paths.root("config", files)
131
+ end
132
+
133
+ # <MACK_PROJECT_ROOT>/config/app_config
134
+ def self.app_config(*files)
135
+ Mack::Paths.config("app_config", files)
136
+ end
137
+
138
+ # <MACK_PROJECT_ROOT>/config/initializers
139
+ def self.initializers(*files)
140
+ Mack::Paths.config("initializers", files)
141
+ end
142
+
143
+ # <MACK_PROJECT_ROOT>/vendor
144
+ def self.vendor(*files)
145
+ Mack::Paths.root("vendor", files)
146
+ end
147
+
148
+ # <MACK_PROJECT_ROOT>/vendor/plugins
149
+ def self.plugins(*files)
150
+ Mack::Paths.vendor("plugins", files)
151
+ end
152
+
153
+ end # Paths
154
+ end # Mack
@@ -1,33 +1,35 @@
1
1
  module Mack
2
2
  module Utils
3
-
3
+
4
4
  # Houses a registry of Rack runners that should be called before the Mack::Runner.
5
5
  class RunnersRegistry < Mack::Utils::RegistryList
6
6
  end
7
-
7
+
8
8
  module Server
9
-
9
+
10
10
  # This method wraps all the necessary components of the Rack system around
11
11
  # Mack::Runner. This can be used build your own server around the Mack framework.
12
12
  def self.build_app
13
13
  # Mack framework:
14
14
  app = Mack::Runner.new
15
-
15
+
16
16
  Mack::Utils::RunnersRegistry.registered_items.each do |runner|
17
17
  app = runner.new(app)
18
18
  end
19
-
19
+
20
20
  # Any urls listed will go straight to the public directly and will not be served up via the app:
21
21
  app = Rack::Static.new(app, :urls => ["/css", "/images", "/files", "/images", "/stylesheets", "/javascripts", "/media", "/favicon.ico"], :root => "public")
22
+ app = Mack::Utils::ContentLengthHandler.new(app)
22
23
  app = Rack::Lint.new(app) if app_config.mack.use_lint
23
24
  app = Rack::ShowStatus.new(app)
24
25
  app = Rack::ShowExceptions.new(app) if app_config.mack.show_exceptions
25
26
  app = Rack::Recursive.new(app)
27
+
26
28
  # This will reload any edited classes if the cache_classes config setting is set to true.
27
29
  app = Rack::Reloader.new(app, 1) unless app_config.mack.cache_classes
28
30
  app
29
31
  end
30
-
32
+
31
33
  end # Server
32
34
  end # Utils
33
35
  end # Mack
@@ -1,3 +1,3 @@
1
1
  module Mack
2
- VERSION = '0.7.0.1' unless const_defined?("VERSION")
2
+ VERSION = '0.7.1' unless const_defined?("VERSION")
3
3
  end
@@ -0,0 +1,50 @@
1
+ module Mack
2
+ class AssetHelpers # :nodoc:
3
+ include Singleton
4
+
5
+ #
6
+ # Set the asset hosts for this app. It supports the following format:
7
+ # - plain string: the string literal will be considered as the asset hosts (e.g. 'http://assets.foo.com')
8
+ # - formatted string: to support asset host distribution (e.g. 'http://asset%d.foo.com')
9
+ # - a proc object: to support custom asset hosts generation (e.g. Proc.new { |source| 'assets.foo.com' }
10
+ #
11
+ # The max number of distribution can be set from app_config's asset_hosts_max_distribution.
12
+ # The default value is 4
13
+ #
14
+ def asset_hosts=(host)
15
+ @hosts = host
16
+ end
17
+
18
+ #
19
+ # Return the max number of asset hosts distribution
20
+ #
21
+ def max_distribution
22
+ return app_config.asset_hosts_max_distribution.to_i || 4
23
+ end
24
+
25
+ #
26
+ # Return the asset hosts for this application.
27
+ #
28
+ def asset_hosts(source = '')
29
+ ret_val = ''
30
+
31
+ # if no explicit asset_host setting, then use the one defined in app_config (if exists)
32
+ host = @hosts || app_config.asset_hosts
33
+ host = '' if host.nil?
34
+
35
+ if host.kind_of?(Proc)
36
+ ret_val = host.call(source)
37
+ else
38
+ ret_val = sprintf(host, rand(max_distribution))
39
+ end
40
+ return ret_val
41
+ end
42
+
43
+ #
44
+ # Clear previously set configuration for asset hosts
45
+ #
46
+ def reset!
47
+ @hosts = nil
48
+ end
49
+ end
50
+ end
@@ -3,6 +3,19 @@ module Mack
3
3
  # A useful collection of helpers for forms.
4
4
  module FormHelpers
5
5
 
6
+ #
7
+ # Get the secret token to be added in an HTML form.
8
+ # This is to ensure that your form is valid.
9
+ #
10
+ # Only call this method if you generate the form manually.
11
+ # If you use the form() method to generate your form, then
12
+ # the authenticity token is already included in your form.
13
+ #
14
+ def form_authenticity_field
15
+ str = %{<input type="hidden" name="__authenticity_token" value="#{Mack::Utils::AuthenticityTokenDispenser.instance.dispense_token(request.session.id)}" />}
16
+ end
17
+
18
+
6
19
  # Examples:
7
20
  # <% form(users_create_url) do -%>
8
21
  # # form stuff here...
@@ -31,6 +44,7 @@ module Mack
31
44
  end
32
45
  concat("<form#{build_options(options)}>\n", block.binding)
33
46
  concat(meth, block.binding) unless meth.blank?
47
+ concat(form_authenticity_field, block.binding) if !app_config.mack.disable_forgery_detector
34
48
  yield
35
49
  concat("\n</form>", block.binding)
36
50
  # content_tag(:form, options, &block)
@@ -38,22 +52,54 @@ module Mack
38
52
 
39
53
  # Generates a button with a form around it and will set the request method to delete.
40
54
  def delete_button(url, value = "Delete", form_options = {}, button_options = {})
41
- if button_options[:confirm]
42
- button_options[:onclick] = "if (confirm('#{button_options[:confirm]}')) {submit();}; return false;"
43
- button_options.delete(:confirm)
44
- end
45
55
  t = "\n" << hidden_field(:_method, :value => :delete)
46
56
  t << "\n" << submit_button(value, button_options)
47
57
  t << "\n"
48
58
  content_tag(:form, {:action => url, :method => :post}.merge(form_options), t)
49
59
  end
50
60
 
51
- alias_deprecated_method :submit_tag, :submit_button, '0.7.0'
52
-
53
61
  # Examples:
54
62
  # <%= submit_button %> # => <input type="submit" value="Submit" />
55
63
  # <%= submit_button "Login" %> # => <input type="submit" value="Login" />
64
+ # You can disable the button after clicking it. In essence, this will work as follows:
65
+ # <%= submit_button "Login", :disable_with => "Please wait..." %>
66
+ # # => <input type="submit" value="Login" onclick="this.disabled=true;this.value='Please wait...';this.form.submit();" />
67
+ # Even though :disable_with will work on the onclick parameter, you can add your own onclick behaviour to the mix, as follows:
68
+ # <%= submit_button "Login", :disable_with => "Please wait...", :onclick => "alert('test')" %>
69
+ # # => <input type="submit" value="Login" onclick="this.disabled=true;this.value='Please wait...';alert('test');this.form.submit();" />
70
+ #
71
+ # Please note that if the form.submit() returns false the button's value will be restored to
72
+ # its initial value. This behaviour is acheived through the injection of a couple bits of JS
73
+ # into the onlick existing parameter. These bits are injected after the disabled value, and
74
+ # all existing onclick behaviour that you define in the :onlick option. The included JS bits
75
+ # are as follows:
76
+ # "result = (this.form.onsubmit ? (this.form.onsubmit() ? this.form.submit() : false) : this.form.submit())",
77
+ # "if (result == false) { this.value = this.getAttribute('originalValue'); this.disabled = false }",
78
+ # "return result;"
56
79
  def submit_button(value = "Submit", options = {}, *original_args)
80
+ if options[:confirm]
81
+ onclick = "if (confirm('#{options.delete(:confirm)}')) {submit();}; return false;"
82
+ onclick << ";#{options.delete(:onclick)}" if options.has_key?(:onclick)
83
+ options[:onclick] = onclick
84
+ end
85
+ # processing the disable with option, which will be embebed in the onclick parameter.
86
+ if disable_with = options.delete(:disable_with)
87
+ disable_with = "this.innerHTML='#{disable_with}'"
88
+
89
+ # Making sure that we keep the content of the onclick option, should it exist.
90
+ disable_with << ";#{options.delete(:onclick)}" if options.has_key?(:onclick)
91
+
92
+ # Setting the onlick option.
93
+ options[:onclick] = [
94
+ "this.setAttribute('originalValue', this.innerHTML)",
95
+ "this.disabled=true",
96
+ disable_with,
97
+ "result = (this.form.onsubmit ? (this.form.onsubmit() ? this.form.submit() : false) : this.form.submit())",
98
+ "if (result == false) { this.innerHTML = this.getAttribute('originalValue'); this.disabled = false }",
99
+ "return result;",
100
+ ].join(";")
101
+ end
102
+
57
103
  # non_content_tag(:input, {:type => :submit, :value => value}.merge(options))
58
104
  content_tag(:button, {:type => :submit}.merge(options), value)
59
105
  end
@@ -129,7 +129,8 @@ module Mack
129
129
  link = ""
130
130
  files.each do |name|
131
131
  file_name = !name.to_s.end_with?(".js") ? "#{name}.js" : "#{name}"
132
- link += "<javascript src=\"#{get_resource_root}/javascripts/#{file_name}?#{Time.now.to_i}\" type=\"#{options[:type]}\" />\n"
132
+ resource = "/javascripts/#{file_name}"
133
+ link += "<javascript src=\"#{get_resource_root(resource)}#{resource}?#{Time.now.to_i}\" type=\"#{options[:type]}\" />\n"
133
134
  end
134
135
  return link
135
136
  end
@@ -153,16 +154,18 @@ module Mack
153
154
  link = ""
154
155
  files.each do |name|
155
156
  file_name = !name.to_s.end_with?(".css") ? "#{name}.css" : "#{name}"
156
- link += "<link href=\"#{get_resource_root}/stylesheets/#{file_name}\" media=\"#{options[:media]}\" rel=\"#{options[:rel]}\" type=\"#{options[:type]}\" />\n"
157
+ resource = "/stylesheets/#{file_name}"
158
+ link += "<link href=\"#{get_resource_root(resource)}#{resource}\" media=\"#{options[:media]}\" rel=\"#{options[:rel]}\" type=\"#{options[:type]}\" />\n"
157
159
  end
158
160
 
159
161
  return link
160
162
  end
161
163
 
162
164
  private
163
- def get_resource_root
165
+ def get_resource_root(resource)
164
166
  path = ""
165
167
  path = "#{app_config.mack.distributed_site_domain}" if app_config.mack.distributed_site_domain
168
+ path = Mack::AssetHelpers.instance.asset_hosts(resource) if path.empty?
166
169
  return path
167
170
  end
168
171
 
@@ -1,20 +1,18 @@
1
- require 'ruby-debug'
2
-
3
1
  fl = File.join(File.dirname(__FILE__), "mack")
2
+ require File.join(fl, "initialization", "application.rb")
3
+ require File.join(fl, "initialization", "helpers.rb")
4
+ require File.join(fl, "initialization", "plugins.rb")
4
5
 
5
- require File.join(fl, "initialization", "configuration.rb")
6
+ boot_load(:start_mack_application, :configuration, :print_hello_banner, :lib, :routes, :app_files, :helpers, :runner) do
7
+ Mack::Environment.load
8
+ Mack.logger.debug "Initialization of Mack Application Environment finished."
9
+ end
6
10
 
7
- unless Mack::Configuration.initialized_application
8
-
9
- Mack.logger.debug "Starting application in #{Mack.env} mode."
11
+ boot_load(:print_hello_banner, :configuration) do
12
+ Mack.reset_logger!
10
13
  Mack.logger.debug "Mack root: #{Mack.root}"
11
14
  Mack.logger.debug "Mack version: #{Mack::VERSION}"
15
+ Mack.logger.debug "Starting application in #{Mack.env} mode."
16
+ end
12
17
 
13
- require File.join(fl, "initialization", "application.rb")
14
-
15
- require File.join(fl, "initialization", "helpers.rb")
16
-
17
- Mack::Configuration.initialized_application = true if Mack::Configuration.initialized_application.nil?
18
-
19
- Mack.logger.debug "Initialization of Mack Application Environment finished."
20
- end
18
+ Mack::BootLoader.run(:start_mack_application)