mack 0.2.0.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,10 @@
1
+ ===0.3.0
2
+ * Ticket: #8 Xml Builder Support
3
+ * Ticket: #7 Ability to drive certain content based on 'format'
4
+ * Ticket: #9 Added a global encryption system to make encrypting/decrypting of strings easy to use.
5
+ * gem: builder 2.1.2
6
+ * gem: crypt 1.1.4
7
+
1
8
  ===0.2.0.1
2
9
  * gem: cachetastic 1.4.1
3
10
  * gem: application_configuration 1.2.1
data/bin/mack CHANGED
@@ -1,3 +1,4 @@
1
+ #!/usr/local/bin/ruby
1
2
  require 'fileutils'
2
3
  require 'optparse'
3
4
  require 'optparse/time'
@@ -0,0 +1,15 @@
1
+ module Kernel
2
+
3
+ # A helper method that calls Mack::Utils::Crypt::Keeper with the specified worker
4
+ # and calls the encrypt method on that worker.
5
+ def _encrypt(value, worker = :default)
6
+ Mack::Utils::Crypt::Keeper.instance.worker(worker).encrypt(value)
7
+ end
8
+
9
+ # A helper method that calls Mack::Utils::Crypt::Keeper with the specified worker
10
+ # and calls the decrypt method on that worker.
11
+ def _decrypt(value, worker = :default)
12
+ Mack::Utils::Crypt::Keeper.instance.worker(worker).decrypt(value)
13
+ end
14
+
15
+ end
@@ -35,4 +35,22 @@ class String
35
35
  Mack::Utils::Inflector.instance.singularize(self)
36
36
  end
37
37
 
38
+ # Maps to Kernel _encrypt
39
+ #
40
+ # Examples:
41
+ # "Hello World".encrypt
42
+ # "Hello World".encrypt(:my_crypt)
43
+ def encrypt(worker = :default)
44
+ _encrypt(self, worker)
45
+ end
46
+
47
+ # Maps to Kernel _decrypt
48
+ #
49
+ # Examples:
50
+ # some_encrypted_string.decrypt
51
+ # some_encrypted_string.decrypt(:my_crypt)
52
+ def decrypt(worker = :default)
53
+ _decrypt(self, worker)
54
+ end
55
+
38
56
  end
@@ -82,7 +82,7 @@ module Mack
82
82
  "mack::use_lint" => true,
83
83
  "mack::show_exceptions" => true,
84
84
  "mack::session_id" => "_mack_session_id",
85
- "mack::rendering_systems" => [:action, :text, :partial, :public, :url],
85
+ "mack::rendering_systems" => [:action, :text, :partial, :public, :url, :xml],
86
86
  "mack::cookie_values" => {
87
87
  "path" => "/"
88
88
  },
@@ -6,6 +6,8 @@ require 'application_configuration'
6
6
  require 'cachetastic'
7
7
  require 'fileutils'
8
8
  require 'log4r'
9
+ require 'crypt/rijndael'
10
+ require 'singleton'
9
11
 
10
12
  # Set up Mack constants, if they haven't already been set up.
11
13
  unless Object.const_defined?("MACK_ENV")
data/lib/mack.rb CHANGED
@@ -119,7 +119,7 @@ module Mack
119
119
  url = route[:redirect_to]
120
120
  options = self.request.all_params
121
121
  options.merge!(route)
122
- options - [:controller, :action, :redirect_to, :method, :status]
122
+ options - [:controller, :action, :redirect_to, :method, :status, :format]
123
123
  url = url_for_pattern(url, options)
124
124
  self.response.status = status
125
125
  self.response[:location] = url
@@ -35,10 +35,15 @@ module Mack
35
35
  raise MethodNotImplemented.new("render")
36
36
  end
37
37
 
38
+ # Maps to the view_binder's param method. See also Mack::ViewBinder params.
39
+ def params(key)
40
+ self.view_binder.params(key)
41
+ end
42
+
38
43
  private
39
44
  # Used to render a file from disk.
40
45
  def render_file(f, options = {})
41
- options = {:is_partial => false, :ext => ".html.erb", :dir => MACK_VIEWS}.merge(options)
46
+ options = {:is_partial => false, :ext => ".#{self.params(:format)}.erb", :dir => MACK_VIEWS}.merge(options)
42
47
  partial = f.to_s
43
48
  parts = partial.split("/")
44
49
  if parts.size == 1
@@ -10,7 +10,7 @@ module Mack
10
10
  rescue Errno::ENOENT => e
11
11
  begin
12
12
  # If the action doesn't exist on disk, try to render it from the public directory:
13
- t = render_file(options[:action], {:dir => MACK_PUBLIC, :ext => ".html", :layout => false}.merge(options))
13
+ t = render_file(options[:action], {:dir => MACK_PUBLIC, :ext => ".#{params(:format)}", :layout => false}.merge(options))
14
14
  # Because it's being served from public don't wrap a layout around it!
15
15
  # self.controller.instance_variable_get("@render_options").merge!({:layout => false})
16
16
  return t
@@ -0,0 +1,24 @@
1
+ module Mack
2
+ module Rendering
3
+ # Used when someone calls render(:xml => "rss_feed")
4
+ class Xml < Base
5
+
6
+ def render
7
+ begin
8
+ # Try to render the action:
9
+ return render_file(options[:xml], options.merge(:format => :xml, :ext => ".xml.erb"))
10
+ rescue Errno::ENOENT => e
11
+ begin
12
+ # If the action doesn't exist on disk, try to render it from the public directory:
13
+ t = render_file(options[:xml], {:dir => MACK_PUBLIC, :ext => ".xml.erb", :layout => false}.merge(options.merge(:format => :xml)))
14
+ return t
15
+ rescue Errno::ENOENT => ex
16
+ end
17
+ # Raise the original exception because something bad has happened!
18
+ raise e
19
+ end
20
+ end
21
+
22
+ end
23
+ end
24
+ end
@@ -223,6 +223,12 @@ module Mack
223
223
  end
224
224
  s = segs.join("/")
225
225
  s = "/" if s.blank?
226
+ if s.match(".:format")
227
+ s.gsub!(/\.:format/, "(\\..+|$)")
228
+ else
229
+ s << "(\\..+|$)"
230
+ end
231
+
226
232
  rx = /^#{s}$/
227
233
  rx
228
234
  end # regex_from_pattern
@@ -249,7 +255,13 @@ module Mack
249
255
  end
250
256
 
251
257
  def options_with_embedded_parameters(uri)
252
- opts = self.options
258
+ opts = {:format => :html}.merge(self.options)
259
+ m = uri.match(/\..+$/)
260
+ if m
261
+ m = m.to_s
262
+ opts[:format]= m[1..m.size].to_sym
263
+ uri.gsub!(/\..+$/, "")
264
+ end
253
265
  split_uri = uri.split("/")
254
266
  self.embedded_parameters.each_with_index do |val, ind|
255
267
  unless val.nil?
data/lib/routing/urls.rb CHANGED
@@ -18,12 +18,20 @@ module Mack
18
18
  def url_for_pattern(url, options = {})
19
19
  u = url.dup
20
20
  unused_params = []
21
+ format = nil
21
22
  options.each_pair do |k, v|
22
- vp = Rack::Utils.escape(v.to_param)
23
- if u.gsub!(":#{k}", vp).nil?
24
- unused_params << "#{Rack::Utils.escape(k)}=#{vp}"
23
+ unless k.to_sym == :format
24
+ vp = Rack::Utils.escape(v.to_param)
25
+ if u.gsub!(":#{k}", vp).nil?
26
+ unused_params << "#{Rack::Utils.escape(k)}=#{vp}"
27
+ end
28
+ else
29
+ format = v
25
30
  end
26
31
  end
32
+ if format
33
+ u << ".#{format}"
34
+ end
27
35
  unless unused_params.empty?
28
36
  u << "?" << unused_params.sort.join("&")
29
37
  end
@@ -31,6 +31,7 @@ module Mack
31
31
  @controller_name = params(:controller)
32
32
  @action_name = params(:action)
33
33
  @cookies = cookies
34
+ @wants_list = []
34
35
  end
35
36
 
36
37
  # Gives access to all the parameters for this request.
@@ -198,6 +199,36 @@ module Mack
198
199
  render(:text => redirect_html(request.path_info, url, options[:status]))
199
200
  end
200
201
 
202
+ # In an action wants will run blocks of code based on the content type that has
203
+ # been requested.
204
+ #
205
+ # Examples:
206
+ # class MyAwesomeController < Mack::Controller::Base
207
+ # def hello
208
+ # wants(:html) do
209
+ # render(:text => "<html>Hello World</html>")
210
+ # end
211
+ # wants(:xml) do
212
+ # render(:text => "<xml><greeting>Hello World</greeting></xml>")
213
+ # end
214
+ # end
215
+ # end
216
+ #
217
+ # If you were to go to: /my_awesome/hello you would get:
218
+ # "<html>Hello World</html>"
219
+ #
220
+ # If you were to go to: /my_awesome/hello.html you would get:
221
+ # "<html>Hello World</html>"
222
+ #
223
+ # If you were to go to: /my_awesome/hello.xml you would get:
224
+ # "<xml><greeting>Hello World</greeting></xml>"
225
+ def wants(header_type, &block)
226
+ header_type = header_type.to_sym
227
+ if header_type == params(:format).to_sym
228
+ yield
229
+ end
230
+ end
231
+
201
232
  # Returns true/false depending on whether the render action has been called yet.
202
233
  def render_performed?
203
234
  @render_performed
@@ -237,7 +268,13 @@ module Mack
237
268
  end
238
269
  else layout
239
270
  # use the layout specified by the layout method
240
- return Mack::ViewBinder.new(self).render(@render_options.merge({:action => "layouts/#{layout}"}))
271
+ begin
272
+ return Mack::ViewBinder.new(self).render(@render_options.merge({:action => "layouts/#{layout}"}))
273
+ rescue Errno::ENOENT => e
274
+ # if the layout doesn't exist, we don't care.
275
+ rescue Exception => e
276
+ raise e
277
+ end
241
278
  end
242
279
  # end
243
280
  @content_for_layout
@@ -28,6 +28,14 @@ module Mack
28
28
  Mack::Utils::Html
29
29
  end
30
30
 
31
+ # A wrapper to Mack::Utils::Html rss method.
32
+ #
33
+ # Example:
34
+ # <%= rss_tag(posts_index_url(:format => :xml)) %>
35
+ def rss_tag(url)
36
+ Mack::Utils::Html.rss(url)
37
+ end
38
+
31
39
  end # HtmlHelpers
32
40
  end # ViewHelpers
33
41
  end # Mack
@@ -1,3 +1,4 @@
1
+ require 'builder'
1
2
  # require 'erubis'
2
3
  # This class is used to do all the view level bindings.
3
4
  # It allows for seperation between the controller and the view levels.
@@ -10,6 +11,8 @@ class Mack::ViewBinder
10
11
  self.controller = cont
11
12
  self.options = {:locals => {}}.merge(opts)
12
13
  transfer_vars(@controller)
14
+ @xml_output = ""
15
+ @xml = Builder::XmlMarkup.new(:target => @xml_output, :indent => 1)
13
16
  end
14
17
 
15
18
  # Returns the binding for this class.
@@ -23,6 +26,15 @@ class Mack::ViewBinder
23
26
  self.options[:locals][sym]
24
27
  end
25
28
 
29
+ # Maps to the controller's param method. See also Mack::Controller::Base params.
30
+ def params(key)
31
+ self.controller.params(key)
32
+ end
33
+
34
+ def xml
35
+ @xml
36
+ end
37
+
26
38
  # Handles rendering calls both in the controller and in the view.
27
39
  # For full details of render examples see Mack::Controller::Base render.
28
40
  # Although the examples there are all in controllers, they idea is still
@@ -62,7 +74,12 @@ class Mack::ViewBinder
62
74
  # and returns a String. The io can be either an IO object or a String.
63
75
  def render(io, controller, options = {})
64
76
  vb = Mack::ViewBinder.new(controller, options)
65
- return ERB.new(io).result(vb.view_binding)
77
+ # TODO: find a nicer way of doing this:
78
+ if ((controller.params(:format).to_sym == :xml) || options[:format] == :xml) && (options[:action] || options[:xml])
79
+ return eval(io, vb.view_binding)
80
+ else
81
+ return ERB.new(io).result(vb.view_binding)
82
+ end
66
83
  # return Erubis::Eruby.new(io).result(vb.view_binding)
67
84
  end
68
85
 
@@ -0,0 +1,28 @@
1
+ module Mack
2
+ module Utils # :nodoc:
3
+ module Crypt # :nodoc:
4
+ # The default worker is one that is used when no other worker is specified or the
5
+ # specified worker does not exist. It uses the Crypt::Rijndael library and get's
6
+ # it's secret key from app_config.default_secret_key
7
+ class DefaultWorker
8
+
9
+ def initialize
10
+ @aes_key = ::Crypt::Rijndael.new(app_config.default_secret_key || (String.randomize(40)))
11
+ end
12
+
13
+ # Encrypts a string using the Crypt::Rijndael library and the secret key found in
14
+ # app_config.default_secret_key
15
+ def encrypt(x)
16
+ @aes_key.encrypt_string(x)
17
+ end
18
+
19
+ # Decrypts a string using the Crypt::Rijndael library and the secret key found in
20
+ # app_config.default_secret_key
21
+ def decrypt(x)
22
+ @aes_key.decrypt_string(x)
23
+ end
24
+
25
+ end # DefaultWorker
26
+ end # Crypt
27
+ end # Utils
28
+ end # Mack
@@ -0,0 +1,46 @@
1
+ module Mack
2
+ module Utils
3
+ module Crypt
4
+ # A singleton class that holds/manages all the workers for the system.
5
+ #
6
+ # A worker must be defined as Mack::Utils::Crypt::<name>Worker and must
7
+ # define an encrypt(value) method and a decrypt(value) method.
8
+ #
9
+ # Example:
10
+ # class Mack::Utils::Crypt::ReverseWorker
11
+ # def encrypt(x)
12
+ # x.reverse
13
+ # end
14
+ #
15
+ # def decrypt(x)
16
+ # x.reverse
17
+ # end
18
+ # end
19
+ class Keeper
20
+ include Singleton
21
+
22
+ def initialize
23
+ @crypt_workers_cache = {}
24
+ end
25
+
26
+ # Returns a worker object to handle the encrytion/decryption.
27
+ # If the specified worker doesn't exist then Mack::Utils::Crypt::DefaultWorker
28
+ # is returned.
29
+ def worker(key = :default)
30
+ worker = @crypt_workers_cache[key.to_sym]
31
+ if worker.nil?
32
+ worker_klass = key.to_s.camelcase + "Worker"
33
+ if Mack::Utils::Crypt.const_defined?(worker_klass)
34
+ worker = "Mack::Utils::Crypt::#{worker_klass}".constantize.new
35
+ else
36
+ worker = Mack::Utils::Crypt::DefaultWorker.new
37
+ end
38
+ @crypt_workers_cache[key.to_sym] = worker
39
+ end
40
+ worker
41
+ end
42
+
43
+ end # Keeper
44
+ end # Crypt
45
+ end # Utils
46
+ end # Mack
data/lib/utils/html.rb CHANGED
@@ -46,6 +46,14 @@ module Mack
46
46
 
47
47
  alias_method :a, :href
48
48
 
49
+ # A wrapper to generate an auto discovery tag so browsers no the page contains an RSS feed.
50
+ #
51
+ # Example:
52
+ # <%= Mack::Utils::Html.rss(posts_index_url(:format => :xml)) %>
53
+ def rss(url)
54
+ "<link rel=\"alternate\" type=\"application/rss+xml\" title=\"RSS\" href=\"#{url}\">"
55
+ end
56
+
49
57
  # Wraps the content_tag method.
50
58
  #
51
59
  # Examples:
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mack
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - markbates
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-03-14 00:00:00 -04:00
12
+ date: 2008-03-19 00:00:00 -04:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -66,6 +66,24 @@ dependencies:
66
66
  - !ruby/object:Gem::Version
67
67
  version: 0.7.0
68
68
  version:
69
+ - !ruby/object:Gem::Dependency
70
+ name: builder
71
+ version_requirement:
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - "="
75
+ - !ruby/object:Gem::Version
76
+ version: 2.1.2
77
+ version:
78
+ - !ruby/object:Gem::Dependency
79
+ name: crypt
80
+ version_requirement:
81
+ version_requirements: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - "="
84
+ - !ruby/object:Gem::Version
85
+ version: 1.1.4
86
+ version:
69
87
  description: "mack was developed by: markbates"
70
88
  email: mark@mackframework.com
71
89
  executables:
@@ -94,6 +112,7 @@ files:
94
112
  - bin/templates/public/stylesheets/scaffold.css.template
95
113
  - bin/templates/Rakefile.template
96
114
  - lib/core_extensions/hash.rb
115
+ - lib/core_extensions/kernel.rb
97
116
  - lib/core_extensions/module.rb
98
117
  - lib/core_extensions/nil.rb
99
118
  - lib/core_extensions/object.rb
@@ -128,6 +147,7 @@ files:
128
147
  - lib/rendering/classes/public.rb
129
148
  - lib/rendering/classes/text.rb
130
149
  - lib/rendering/classes/url.rb
150
+ - lib/rendering/classes/xml.rb
131
151
  - lib/routing/route_map.rb
132
152
  - lib/routing/urls.rb
133
153
  - lib/sea_level/controller_base.rb
@@ -148,6 +168,8 @@ files:
148
168
  - lib/tasks/test_tasks.rake
149
169
  - lib/test_extensions/test_assertions.rb
150
170
  - lib/test_extensions/test_helpers.rb
171
+ - lib/utils/crypt/default_worker.rb
172
+ - lib/utils/crypt/keeper.rb
151
173
  - lib/utils/html.rb
152
174
  - lib/utils/inflections.rb
153
175
  - lib/utils/inflector.rb