manveru-ramaze 2008.08 → 2008.09

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. data/Rakefile +1 -1
  2. data/bin/ramaze +1 -0
  3. data/doc/CHANGELOG +966 -0
  4. data/doc/tutorial/todolist.html +421 -313
  5. data/doc/tutorial/todolist.mkd +26 -9
  6. data/examples/helpers/paginate.rb +71 -0
  7. data/examples/misc/simple_auth.rb +20 -8
  8. data/lib/proto/controller/init.rb +10 -0
  9. data/lib/proto/controller/main.rb +1 -3
  10. data/lib/proto/model/init.rb +4 -0
  11. data/lib/proto/spec/main.rb +2 -1
  12. data/lib/proto/start.rb +3 -3
  13. data/lib/ramaze.rb +6 -1
  14. data/lib/ramaze/action.rb +2 -2
  15. data/lib/ramaze/adapter.rb +0 -5
  16. data/lib/ramaze/adapter/base.rb +24 -7
  17. data/lib/ramaze/contrib/gzip_filter.rb +22 -9
  18. data/lib/ramaze/contrib/maruku_uv.rb +59 -0
  19. data/lib/ramaze/contrib/profiling.rb +1 -1
  20. data/lib/ramaze/contrib/sequel/create_join.rb +25 -0
  21. data/lib/ramaze/contrib/sequel/form_field.rb +129 -0
  22. data/lib/ramaze/contrib/sequel/image.rb +198 -0
  23. data/lib/ramaze/contrib/sequel/relation.rb +82 -0
  24. data/lib/ramaze/controller/resolve.rb +1 -1
  25. data/lib/ramaze/current.rb +60 -20
  26. data/lib/ramaze/current/response.rb +15 -3
  27. data/lib/ramaze/dispatcher.rb +9 -3
  28. data/lib/ramaze/dispatcher/action.rb +2 -3
  29. data/lib/ramaze/dispatcher/directory.rb +1 -1
  30. data/lib/ramaze/dispatcher/error.rb +1 -1
  31. data/lib/ramaze/dispatcher/file.rb +1 -1
  32. data/lib/ramaze/helper/formatting.rb +33 -0
  33. data/lib/ramaze/helper/paginate.rb +234 -0
  34. data/lib/ramaze/option.rb +2 -2
  35. data/lib/ramaze/reloader.rb +2 -2
  36. data/lib/ramaze/snippets.rb +13 -0
  37. data/lib/ramaze/snippets/array/put_within.rb +31 -24
  38. data/lib/ramaze/snippets/binding/locals.rb +23 -11
  39. data/lib/ramaze/snippets/kernel/constant.rb +36 -21
  40. data/lib/ramaze/snippets/kernel/pretty_inspect.rb +12 -6
  41. data/lib/ramaze/snippets/numeric/filesize_format.rb +24 -17
  42. data/lib/ramaze/snippets/numeric/time.rb +63 -56
  43. data/lib/ramaze/snippets/object/__dir__.rb +29 -0
  44. data/lib/ramaze/snippets/object/acquire.rb +40 -0
  45. data/lib/ramaze/snippets/object/instance_variable_defined.rb +16 -5
  46. data/lib/ramaze/snippets/object/pretty.rb +14 -4
  47. data/lib/ramaze/snippets/object/scope.rb +14 -7
  48. data/lib/ramaze/snippets/ordered_set.rb +4 -0
  49. data/lib/ramaze/snippets/proc/locals.rb +17 -9
  50. data/lib/ramaze/snippets/ramaze/struct.rb +45 -0
  51. data/lib/ramaze/snippets/string/camel_case.rb +13 -8
  52. data/lib/ramaze/snippets/string/color.rb +24 -20
  53. data/lib/ramaze/snippets/string/each.rb +14 -3
  54. data/lib/ramaze/snippets/string/end_with.rb +17 -6
  55. data/lib/ramaze/snippets/string/esc.rb +26 -18
  56. data/lib/ramaze/snippets/string/ord.rb +12 -6
  57. data/lib/ramaze/snippets/string/snake_case.rb +13 -7
  58. data/lib/ramaze/snippets/string/start_with.rb +16 -6
  59. data/lib/ramaze/snippets/string/unindent.rb +23 -15
  60. data/lib/ramaze/snippets/thread/into.rb +3 -3
  61. data/lib/ramaze/spec/helper/snippets.rb +8 -0
  62. data/lib/ramaze/template/ezamar/textpow.syntax +34 -0
  63. data/lib/ramaze/tool/create.rb +27 -53
  64. data/lib/ramaze/tool/project_creator.rb +110 -0
  65. data/lib/ramaze/version.rb +1 -1
  66. data/rake_tasks/gem.rake +2 -1
  67. data/rake_tasks/maintenance.rake +38 -0
  68. data/rake_tasks/release.rake +6 -2
  69. data/rake_tasks/spec.rake +1 -2
  70. data/ramaze.gemspec +69 -78
  71. data/spec/examples/simple_auth.rb +2 -2
  72. data/spec/examples/templates/template_haml.rb +0 -2
  73. data/spec/ramaze/current/session.rb +1 -1
  74. data/spec/ramaze/dispatcher/file.rb +2 -2
  75. data/spec/ramaze/helper/formatting.rb +13 -0
  76. data/spec/ramaze/rewrite.rb +1 -1
  77. data/spec/ramaze/struct.rb +47 -0
  78. data/spec/ramaze/template/markaby.rb +1 -1
  79. data/spec/snippets/{kernel → object}/__dir__.rb +0 -0
  80. data/spec/snippets/{kernel → object}/acquire.rb +0 -0
  81. metadata +69 -78
  82. data/examples/app/rammit/spec/rammit.rb +0 -31
  83. data/examples/app/rammit/src/controller/main.rb +0 -3
  84. data/examples/app/rammit/src/controller/page.rb +0 -16
  85. data/examples/app/rammit/src/model.rb +0 -33
  86. data/examples/app/rammit/start.rb +0 -8
  87. data/examples/app/rammit/template/index.xhtml +0 -14
  88. data/examples/app/rammit/template/page/view.xhtml +0 -4
  89. data/lib/ramaze/snippets/kernel/__dir__.rb +0 -23
  90. data/lib/ramaze/snippets/kernel/acquire.rb +0 -34
  91. data/lib/ramaze/snippets/struct/fill.rb +0 -23
  92. data/lib/ramaze/snippets/struct/values_at.rb +0 -39
  93. data/lib/ramaze/snippets/symbol/to_proc.rb +0 -24
  94. data/lib/ramaze/sourcereload.rb +0 -183
  95. data/spec/snippets/struct/fill.rb +0 -26
  96. data/spec/snippets/struct/values_at.rb +0 -52
  97. data/spec/snippets/symbol/to_proc.rb +0 -13
@@ -3,13 +3,22 @@
3
3
 
4
4
  # gzip_filter.rb
5
5
  #
6
- # Use this to compress "large" pages with gzip. All major browsers support gzipped pages.
7
- # This filter brought to you by your friends in #ramaze: Pistos, manveru, rikur and Kashia.
6
+ # Use this to compress "large" pages with gzip. All major browsers support
7
+ # gzipped pages.
8
+ # This filter brought to you by your friends in #ramaze:
9
+ # Pistos, manveru, rikur and Kashia.
8
10
  #
9
11
  # Usage, in start.rb:
10
12
  #
11
13
  # require 'ramaze/contrib/gzip_filter'
12
14
  # Ramaze::Dispatcher::Action::FILTER << Ramaze::Filter::Gzip
15
+ #
16
+ # Setting options (at any point in your code):
17
+ #
18
+ # Ramaze::Filter::Gzip.trait(
19
+ # :threshold => 1024,
20
+ # :content_type => /^text\/.+/
21
+ # )
13
22
 
14
23
  require 'zlib'
15
24
 
@@ -17,8 +26,9 @@ module Ramaze
17
26
  module Filter
18
27
  class Gzip
19
28
 
20
- trait :enabled => true
21
- trait :threshold => 32768 # bytes
29
+ trait :enabled => true,
30
+ :content_type => /^text\/.+/,
31
+ :threshold => 32768 # bytes
22
32
 
23
33
  class << self
24
34
 
@@ -27,21 +37,24 @@ module Ramaze
27
37
  # Enables being plugged into Dispatcher::Action::FILTER
28
38
 
29
39
  def call( response, options = {} )
30
- return response if not trait[ :enabled ]
31
- return response if response.body.nil?
32
- return response if response.body.respond_to?( :read )
40
+ return response unless trait[ :enabled ]
41
+ return response unless body = response.body
42
+ return response if body.respond_to?( :read )
33
43
 
34
44
  accepts = request.env[ 'HTTP_ACCEPT_ENCODING' ]
35
45
  return response if accepts.nil? || ( accepts !~ /(x-gzip|gzip)/ )
36
46
 
37
- if response.content_type == 'text/html' && response.body.size > trait[ :threshold ]
47
+ acceptable_size = body.size >= trait[ :threshold ]
48
+ acceptable_type = response.content_type =~ trait[:content_type]
49
+
50
+ if acceptable_type and acceptable_size
38
51
  output = StringIO.new
39
52
  def output.close
40
53
  # Zlib closes the file handle, so we want to circumvent this
41
54
  rewind
42
55
  end
43
56
  gz = Zlib::GzipWriter.new( output )
44
- gz.write( response.body )
57
+ gz.write( body )
45
58
  gz.close
46
59
 
47
60
  response.body = output.string
@@ -0,0 +1,59 @@
1
+ # A hack to make MaRuKu use UltraViolet for highlighting
2
+ # To specify the style to use use for example:
3
+ # uv_style: amy
4
+ # html_use_syntax: true
5
+ # code_lang: ruby
6
+ # In the document header area.
7
+
8
+ require 'maruku'
9
+
10
+ module MaRuKu
11
+ module Out
12
+ module HTML
13
+ def uv_highlight(source, lang, style)
14
+ require 'uv'
15
+
16
+ html = Uv.parse(source, 'xhtml', lang, lines = false, style)
17
+
18
+ # Prepare <code> containing <pre>
19
+ code = Document.new(html, :respect_whitespace => :all).root
20
+ code.name = 'code'
21
+ code.attributes['class'] = lang
22
+ code.attributes['lang'] = lang
23
+
24
+ # Prepare <pre>
25
+ pre = Element.new('pre')
26
+ pre << code
27
+ pre.attributes['class'] = style
28
+ pre
29
+ rescue => ex
30
+ puts ex
31
+ to_html_code_using_pre(source)
32
+ end
33
+
34
+ def to_html_code
35
+ source = self.raw_code
36
+ use_syntax = get_setting(:html_use_syntax)
37
+ uv_style = get_setting(:uv_style)
38
+
39
+ lang = self.attributes[:lang] || @doc.attributes[:code_lang]
40
+ lang ||= 'ruby' if attributes[:ruby]
41
+
42
+ # we always use syntax highlighting, this is a doc wiki
43
+ if lang and use_syntax
44
+ element = uv_highlight(source, lang, uv_style)
45
+ else
46
+ element = to_html_code_using_pre(source)
47
+ end
48
+
49
+ color = get_setting(:code_background_color)
50
+
51
+ if color != Globals[:code_background_color]
52
+ element.attributes['style'] = "background-color: #{color};"
53
+ end
54
+
55
+ add_ws element
56
+ end
57
+ end # HTML
58
+ end # Out
59
+ end # MaRuKu
@@ -1,7 +1,7 @@
1
1
  require "ruby-prof"
2
2
 
3
3
  module Ramaze
4
- module Dispatcher
4
+ class Dispatcher
5
5
  class ActionProfiler < Action
6
6
  def self.call(path)
7
7
  if RubyProf.running?
@@ -0,0 +1,25 @@
1
+ require 'sequel'
2
+
3
+ module Sequel
4
+ class Model
5
+ # Force join table generation
6
+ #
7
+ # Usage:
8
+ # User.create_join(Article, 'articles_users')
9
+ # # or let the method figure out the correct join table using sequel
10
+ # # conventions.
11
+ # User.create_join(Article)
12
+ def self.create_join(to, name = nil)
13
+ from = self
14
+ name ||= [table_name.to_s, to.table_name.to_s].sort.join('_')
15
+ from_key = "#{from.table_name.to_s.singularize}_id"
16
+ to_key = "#{to.table_name.to_s.singularize}_id"
17
+
18
+ db.create_table! name do
19
+ primary_key :id
20
+ foreign_key from_key, :class => from
21
+ foreign_key to_key, :class => to
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,129 @@
1
+ require 'ramaze/gestalt'
2
+
3
+ # job = Job[4]
4
+ # puts CGI::pretty(FormField.new(job, :contract, show_errors = true, Job::CONTRACTS).to_s)
5
+
6
+ class FormField
7
+ attr_accessor :this, :field, :show_errors, :hint, :db_type, :id, :value
8
+
9
+ # show_errors may be a number indicating how many errors it should display at
10
+ # maximum, 0 displays none, -1 all
11
+
12
+ def initialize(this, field, show_errors = true, hint = nil)
13
+ @this, @field, @show_errors, @hint =
14
+ this, field.to_sym, show_errors, hint
15
+ @db_type = db_type
16
+ @id = "form_#{@field}"
17
+ @value = this.send(@field)
18
+ end
19
+
20
+ def db_type
21
+ if field_schema = this.class.db_schema[field]
22
+ field_schema[:db_type]
23
+ else
24
+ nil
25
+ end
26
+ end
27
+
28
+ def to_s
29
+ unless label = @this.class::FORM_LABEL[field]
30
+ raise("No FORM_LABEL for %p on %p" % [field, @this.class])
31
+ end
32
+
33
+ label += ':'
34
+ id = @id
35
+ _self = self
36
+
37
+ Ramaze::Gestalt.build{
38
+ div(:class => :pair){
39
+ label(:for => id){ label }
40
+ _self.build_tag(self)
41
+ _self.build_errors(self)
42
+ }
43
+ }
44
+ end
45
+
46
+ def password(gestalt)
47
+ gestalt.input(@args.merge :type => :password, :value => value)
48
+ end
49
+
50
+ def checkbox(gestalt)
51
+ @args[:checked] = :checked if value
52
+ gestalt.input(@args.merge :type => :checkbox)
53
+ end
54
+
55
+ def select(gestalt)
56
+ gestalt.select @args do
57
+ v = value.to_s
58
+ hint.each do |h|
59
+ h = h.to_s
60
+ if h == v
61
+ gestalt.option(:value => h, :selected => :selected){ h }
62
+ else
63
+ gestalt.option(:value => h){ h }
64
+ end
65
+ end
66
+ end
67
+ end
68
+
69
+ def input(gestalt)
70
+ gestalt.input(@args.merge :type => :text, :value => value)
71
+ end
72
+
73
+ def file(gestalt)
74
+ gestalt.input(@args.merge :type => :file)
75
+ end
76
+
77
+ def textarea(gestalt)
78
+ gestalt.textarea(@args){ value.to_s }
79
+ end
80
+
81
+ def build_tag(gestalt)
82
+ @args = {:id => id, :name => field}
83
+
84
+ case hint
85
+ when :password
86
+ password(gestalt)
87
+ when :boolean, :checkbox
88
+ checkbox(gestalt)
89
+ when :textarea
90
+ textarea(gestalt)
91
+ when :file
92
+ file(gestalt)
93
+ when Array, Range
94
+ select(gestalt)
95
+ else
96
+ case db_type
97
+ when 'varchar', 'integer'
98
+ input(gestalt)
99
+ when 'boolean'
100
+ checkbox(gestalt)
101
+ when 'string'
102
+ textarea(gestalt)
103
+ else
104
+ raise "Unsupported type: (#{db_type || hint} : #{field})"
105
+ end
106
+ end
107
+ end
108
+
109
+ def build_errors(gestalt)
110
+ each_error do |error|
111
+ gestalt.span(:class => :error){ error }
112
+ end
113
+ end
114
+
115
+ # TODO: suggest 'validated?' feature to sequel
116
+ def each_error(&block)
117
+ return unless show_errors
118
+
119
+ this.validate if this.errors.empty?
120
+ this.errors[field].first(show_errors).each(&block)
121
+ end
122
+
123
+ module Model
124
+ def form_field(field, hint = nil)
125
+ show_errors = Ramaze::Request.current.post? ? 1 : 0
126
+ FormField.new(self, field, show_errors, hint).to_s
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,198 @@
1
+ # Copyright (c) 2008 Michael Fellinger m.fellinger@gmail.com
2
+ # All files in this distribution are subject to the terms of the Ruby license.
3
+
4
+ # Scaffold image models utilizing thumbnailing and Ramaze integration.
5
+ # Resizing is done by ImageScience.
6
+ #
7
+ # Usage:
8
+ # class Avatar < Sequel::Model
9
+ # IMAGE = {
10
+ # # specifies belongs_to, will create relation and foreign key
11
+ #
12
+ # :owner => :User,
13
+ #
14
+ #
15
+ # # Remove original and thumbnails on Avatar#destroy
16
+ #
17
+ # :cleanup => true,
18
+ #
19
+ #
20
+ # # Algorithm to use in ImageScience
21
+ # #
22
+ # # * resize(width, height)
23
+ # # Resizes the image to +width+ and +height+ using a cubic-bspline
24
+ # # filter.
25
+ # #
26
+ # # * thumbnail(size)
27
+ # # Creates a proportional thumbnail of the image scaled so its
28
+ # # longest edge is resized to +size+.
29
+ # #
30
+ # # * cropped_thumbnail(size)
31
+ # # Creates a square thumbnail of the image cropping the longest edge
32
+ # # to match the shortest edge, resizes to +size+.
33
+ #
34
+ # :agorithm => :thumbnail,
35
+ #
36
+ #
37
+ # # Key specifies the filename and accessors, value are arguments to the
38
+ # # algorithm
39
+ #
40
+ # :sizes => {
41
+ # :small => 150,
42
+ # :medium => 300,
43
+ # :large => 600
44
+ # }
45
+ # }
46
+ #
47
+ # # Perform the scaffold
48
+ # include SequelImage
49
+ # end
50
+
51
+ module SequelImage
52
+ def self.included(model)
53
+ args = model::IMAGE
54
+ set_foreign_key = args[:foreign_key] || "#{args[:owner]}_id".downcase.to_sym
55
+ set_belongs_to = args[:belongs_to] || args[:owner].to_s.downcase.to_sym
56
+
57
+ # Define schema
58
+ model.set_schema do
59
+ primary_key :id
60
+
61
+ varchar :original # path to the original image
62
+ varchar :mime, :size => 22 # average of /etc/mime.types
63
+
64
+ time :created_at
65
+ time :updated_at
66
+
67
+ foreign_key set_foreign_key
68
+ end
69
+
70
+ # Define Relations
71
+ model.belongs_to set_belongs_to
72
+
73
+ # Define Hooks
74
+ model.send(:hooks).clear
75
+
76
+ model.before_create do
77
+ generate_thumbnails
78
+ self.created_at = Time.now
79
+ end
80
+
81
+ model.before_save do
82
+ self.updated_at = Time.now
83
+ end
84
+
85
+ model.before_destroy do
86
+ cleanup if conf[:cleanup]
87
+ end
88
+
89
+ # Define singleton methods
90
+ model.extend(SingletonMethods)
91
+
92
+ # Define instance methods
93
+ model.send(:include,
94
+ InstanceMethods,
95
+ Ramaze::Helper::CGI,
96
+ Ramaze::Helper::Link)
97
+
98
+ args[:sizes].each do |size, *args|
99
+ model.send(:define_method, size){ public_file(size) }
100
+ model.send(:define_method, "#{size}_url"){ file(size) }
101
+ end
102
+ end
103
+
104
+ module SingletonMethods
105
+ def store(file, uid, hash = {})
106
+ image = new(hash)
107
+
108
+ type = file[:type]
109
+ filename = file[:filename]
110
+ tempfile = file[:tempfile]
111
+ raise ArgumentError, 'Empty tempfile' if tempfile.size == 0
112
+
113
+ ext = Ramaze::Tool::MIME.ext_for(type)
114
+ image.mime = type
115
+ target_name = image.next_name(File.basename(filename, File.extname(filename)), ext)
116
+ target_path = File.join(image.public_root, image.path, target_name)
117
+
118
+ FileUtils.mkdir_p(File.dirname(target_path))
119
+ FileUtils.cp(tempfile.path, target_path)
120
+
121
+ image.original = target_path
122
+ image.save
123
+ end
124
+ end
125
+
126
+ module InstanceMethods
127
+ def file(size = nil)
128
+ File.join('/', path, filename(size))
129
+ end
130
+
131
+ def public_file(size)
132
+ File.join(public_path, filename(size))
133
+ end
134
+
135
+ def public_path
136
+ File.join(public_root, path)
137
+ end
138
+
139
+ def path
140
+ conf[:path] || conf[:owner].to_s.downcase
141
+ end
142
+
143
+ def next_name(uid, ext)
144
+ uid = uid.to_s.scan(%r![^\\/'".:?&;\s]+!).join('-')
145
+ "#{uid}#{ext}"
146
+ end
147
+
148
+ def basename
149
+ File.basename(original, File.extname(original))
150
+ end
151
+
152
+ def public_root
153
+ Ramaze::Global.public_root
154
+ end
155
+
156
+ def filename(size)
157
+ if size
158
+ "#{basename}_#{size}.png"
159
+ else
160
+ "#{basename}.png"
161
+ end
162
+ end
163
+
164
+ def conf
165
+ self.class::IMAGE
166
+ end
167
+
168
+ def cleanup
169
+ conf[:sizes].each do |name, args|
170
+ out = public_file(name)
171
+ Ramaze::Log.debug "Remove Thumbnail: #{out}"
172
+ FileUtils.rm_f(out)
173
+ end
174
+
175
+ Ramaze::Log.debug "Remove original: #{original}"
176
+ FileUtils.rm_f(original)
177
+ end
178
+
179
+ def generate_thumbnails
180
+ FileUtils.mkdir_p(public_path)
181
+
182
+ sizes, algorithm = conf.values_at(:sizes, :algorithm)
183
+
184
+ ImageScience.with_image(original) do |img|
185
+ Ramaze::Log.debug "Process original: #{original}"
186
+
187
+ sizes.each do |name, args|
188
+ out = public_file(name)
189
+ Ramaze::Log.debug "Generate Thumbnail: #{out}"
190
+
191
+ img.send(algorithm, *args) do |thumb|
192
+ thumb.save(out)
193
+ end
194
+ end
195
+ end
196
+ end
197
+ end
198
+ end