mongodb_logger 0.4.2 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. data/.gitignore +2 -1
  2. data/.rvmrc +1 -1
  3. data/.travis.yml +5 -4
  4. data/Appraisals +9 -0
  5. data/CHANGELOG.md +20 -3
  6. data/README.md +58 -35
  7. data/Rakefile +33 -96
  8. data/app/assets/javascripts/analytics.js.coffee +5 -4
  9. data/app/assets/javascripts/logs.js.coffee +11 -11
  10. data/app/assets/javascripts/mongodb_logger.js +2 -1
  11. data/app/assets/javascripts/vendors/jquery-1.9.1.min.js +5 -0
  12. data/app/assets/javascripts/vendors/jquery.pjax.min.js +15 -13
  13. data/app/assets/javascripts/vendors/mustache.min.js +10 -0
  14. data/app/assets/stylesheets/layout.css +20 -15
  15. data/app/assets/stylesheets/mongodb_logger.css +0 -3
  16. data/bin/mongodb_logger_web +1 -2
  17. data/features/rails.feature +20 -8
  18. data/features/step_definitions/mongodb_logger_web_steps.rb +2 -3
  19. data/features/step_definitions/rails_application_steps.rb +84 -58
  20. data/features/step_definitions/rake_steps.rb +10 -0
  21. data/features/support/aruba.rb +5 -0
  22. data/features/support/env.rb +11 -5
  23. data/features/support/rails.rb +55 -67
  24. data/gemfiles/rails31.gemfile +8 -0
  25. data/gemfiles/rails32.gemfile +8 -0
  26. data/lib/mongodb_logger.rb +10 -3
  27. data/lib/mongodb_logger/adapters/base.rb +5 -1
  28. data/lib/mongodb_logger/adapters/mongo.rb +17 -13
  29. data/lib/mongodb_logger/adapters/moped.rb +17 -11
  30. data/lib/mongodb_logger/capistrano.rb +8 -0
  31. data/lib/mongodb_logger/logger.rb +13 -26
  32. data/lib/mongodb_logger/rack_middleware.rb +24 -0
  33. data/lib/mongodb_logger/railtie.rb +4 -4
  34. data/lib/mongodb_logger/server.rb +43 -68
  35. data/lib/mongodb_logger/server/helpers.rb +5 -0
  36. data/lib/mongodb_logger/server/{content_for.rb → helpers/content_for.rb} +0 -0
  37. data/lib/mongodb_logger/server/helpers/mustache_helpers.rb +66 -0
  38. data/lib/mongodb_logger/server/{partials.rb → helpers/partials.rb} +0 -0
  39. data/lib/mongodb_logger/server/{sprokets.rb → helpers/sprokets.rb} +4 -4
  40. data/lib/mongodb_logger/server/{view_helpers.rb → helpers/view_helpers.rb} +22 -38
  41. data/lib/mongodb_logger/server/model.rb +4 -0
  42. data/lib/mongodb_logger/server/model/additional_filter.rb +15 -23
  43. data/lib/mongodb_logger/server/model/analytic.rb +24 -32
  44. data/lib/mongodb_logger/server/model/base.rb +21 -0
  45. data/lib/mongodb_logger/server/model/filter.rb +12 -20
  46. data/lib/mongodb_logger/server/mustache/logs/info.rb +15 -0
  47. data/lib/mongodb_logger/server/templates/logs/info.mustache +25 -0
  48. data/lib/mongodb_logger/server/views/layout.erb +28 -26
  49. data/lib/mongodb_logger/server/views/shared/_log.erb +1 -1
  50. data/lib/mongodb_logger/server/views/shared/_tabs.erb +2 -2
  51. data/lib/mongodb_logger/server/views/shared/layout/_mustache.erb +6 -0
  52. data/lib/mongodb_logger/server/views/show_log.erb +2 -2
  53. data/lib/mongodb_logger/server_config.rb +4 -4
  54. data/lib/mongodb_logger/utils/migrate.rb +50 -0
  55. data/lib/mongodb_logger/utils/progressbar.rb +79 -0
  56. data/lib/mongodb_logger/version.rb +1 -1
  57. data/mongodb_logger.gemspec +15 -8
  58. data/{test/config/samples → spec/factories/config}/database.yml +0 -0
  59. data/{test/config/samples → spec/factories/config}/database_no_file_logging.yml +0 -0
  60. data/{test/config/samples → spec/factories/config}/database_replica_set.yml +0 -0
  61. data/{test/config/samples → spec/factories/config}/database_with_auth.yml +0 -0
  62. data/spec/factories/config/database_with_capsize.yml +9 -0
  63. data/{test/config/samples → spec/factories/config}/database_with_collection.yml +0 -0
  64. data/{test/config/samples → spec/factories/config}/database_with_url.yml +0 -0
  65. data/{test/config/samples → spec/factories/config}/mongodb_logger.yml +0 -0
  66. data/{test/config/samples → spec/factories/config}/mongoid.yml +0 -0
  67. data/{test/config/samples → spec/factories/config}/server_config.yml +0 -0
  68. data/spec/javascripts/support/jasmine.yml +1 -5
  69. data/spec/mongodb_logger_spec.rb +257 -0
  70. data/spec/rails_spec/controllers/tests_controller_spec_rails.rb +128 -0
  71. data/spec/rails_spec/spec_helper_rails.rb +13 -0
  72. data/spec/spec_helper.rb +17 -0
  73. data/{test/test_helper.rb → spec/support/mongodb_logger_helper.rb} +44 -63
  74. data/spec/support/mongodb_logger_macros.rb +22 -0
  75. data/spec/support/rails.rb +40 -0
  76. data/spec/utils/migrate_spec.rb +32 -0
  77. data/{lib/tasks → tasks}/mongodb_logger.rake +14 -6
  78. metadata +198 -78
  79. data/SUPPORTED_RAILS_VERSIONS +0 -16
  80. data/TESTING.md +0 -24
  81. data/app/assets/javascripts/vendors/jquery-1.8.3.min.js +0 -2
  82. data/features/support/terminal.rb +0 -95
  83. data/lib/mongodb_logger/server/views/shared/_log_info.erb +0 -27
  84. data/test/Gemfile_tests +0 -9
  85. data/test/active_record.rb +0 -13
  86. data/test/log/.gitkeep +0 -0
  87. data/test/rails.rb +0 -22
  88. data/test/rails/app/controllers/order_controller.rb +0 -23
  89. data/test/rails/test/functional/order_controller_test.rb +0 -116
  90. data/test/rails/test/test_helper.rb +0 -10
  91. data/test/shoulda_macros/log_macros.rb +0 -13
  92. data/test/test.sh +0 -7
  93. data/test/unit/mongodb_logger_replica_test.rb +0 -56
  94. data/test/unit/mongodb_logger_test.rb +0 -307
@@ -15,7 +15,7 @@ module MongodbLogger
15
15
  # Looks for configuration files in this order
16
16
  CONFIGURATION_FILES = ["mongodb_logger.yml", "mongoid.yml", "database.yml"]
17
17
  LOG_LEVEL_SYM = [:debug, :info, :warn, :error, :fatal, :unknown]
18
-
18
+
19
19
  ADAPTERS = [
20
20
  ["mongo", Adapers::Mongo],
21
21
  ["moped", Adapers::Moped]
@@ -84,11 +84,11 @@ module MongodbLogger
84
84
  rescue
85
85
  begin
86
86
  # try to nice serialize record
87
- nice_serialize @mongo_record
87
+ record_serializer @mongo_record, true
88
88
  @insert_block.call
89
89
  rescue
90
- # do extra work to inpect (and flatten)
91
- force_serialize @mongo_record
90
+ # do extra work to inspect (and flatten)
91
+ record_serializer @mongo_record, false
92
92
  @insert_block.call rescue nil
93
93
  end
94
94
  end
@@ -137,7 +137,7 @@ module MongodbLogger
137
137
  end
138
138
  config
139
139
  end
140
-
140
+
141
141
  def find_adapter
142
142
  ADAPTERS.each do |(library, adapter)|
143
143
  begin
@@ -171,15 +171,12 @@ module MongodbLogger
171
171
  end
172
172
 
173
173
  # try to serialyze data by each key and found invalid object
174
- def nice_serialize(rec)
175
- if msgs = rec[:messages]
176
- msgs.each do |i, j|
177
- msgs[i] = nice_serialize_object(j)
178
- end
179
- end
180
- if pms = rec[:params]
181
- pms.each do |i, j|
182
- pms[i] = nice_serialize_object(j)
174
+ def record_serializer(rec, nice = true)
175
+ [:messages, :params].each do |key|
176
+ if msgs = rec[key]
177
+ msgs.each do |i, j|
178
+ msgs[i] = (true == nice ? nice_serialize_object(j) : j.inspect)
179
+ end
183
180
  end
184
181
  end
185
182
  end
@@ -190,10 +187,10 @@ module MongodbLogger
190
187
  data
191
188
  when Hash
192
189
  hvalues = Hash.new
193
- data.each{|k,v| hvalues[k] = nice_serialize_object(v) }
190
+ data.each{ |k,v| hvalues[k] = nice_serialize_object(v) }
194
191
  hvalues
195
192
  when Array
196
- data.map{|v| nice_serialize_object(v) }
193
+ data.map{ |v| nice_serialize_object(v) }
197
194
  when ActionDispatch::Http::UploadedFile, Rack::Test::UploadedFile # uploaded files
198
195
  hvalues = {
199
196
  original_filename: data.original_filename,
@@ -204,15 +201,5 @@ module MongodbLogger
204
201
  end
205
202
  end
206
203
 
207
- # force the data in the db by inspecting each top level array and hash element
208
- # this will flatten other hashes and arrays
209
- def force_serialize(rec)
210
- if msgs = rec[:messages]
211
- msgs.each { |i, j| msgs[i] = j.inspect }
212
- end
213
- if pms = rec[:params]
214
- pms.each { |i, j| pms[i] = j.inspect }
215
- end
216
- end
217
204
  end
218
205
  end
@@ -0,0 +1,24 @@
1
+ # Rack middleware for mounted rack app (e.g Grape)
2
+ module MongodbLogger
3
+ class RackMiddleware
4
+ def initialize(app)
5
+ @app = app
6
+ end
7
+
8
+ def call(env)
9
+ request = ::Rack::Request.new env
10
+ path = request.path.split('/')
11
+ log_attrs = {:method => request.request_method,
12
+ :action => path[2..-1].join('/'),
13
+ :controller => path[1],
14
+ :path => request.path,
15
+ :url => request.url,
16
+ :params => request.params,
17
+ :ip => env['REMOTE_ADDR'] }
18
+
19
+ Rails.logger.mongoize(log_attrs) do
20
+ return @app.call(env)
21
+ end
22
+ end
23
+ end
24
+ end
@@ -2,15 +2,15 @@ require 'mongodb_logger/initializer_mixin'
2
2
  module MongodbLogger
3
3
  class Railtie < Rails::Railtie
4
4
  include MongodbLogger::InitializerMixin
5
-
5
+
6
6
  initializer :initialize_mongodb_logger, :before => :initialize_logger do
7
7
  app_config = Rails.application.config
8
8
  Rails.logger = config.logger = create_logger(app_config)
9
9
  end
10
-
10
+
11
11
  rake_tasks do
12
- load "tasks/mongodb_logger.rake"
12
+ load File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "tasks", "mongodb_logger.rake"))
13
13
  end
14
-
14
+
15
15
  end
16
16
  end
@@ -1,69 +1,52 @@
1
1
  require 'sinatra/base'
2
2
  require 'erubis'
3
- require 'json'
3
+ require 'multi_json'
4
4
  require 'active_support'
5
+ require 'mustache/sinatra'
5
6
 
6
- require 'mongodb_logger/server/view_helpers'
7
- require 'mongodb_logger/server/partials'
8
- require 'mongodb_logger/server/content_for'
9
- require 'mongodb_logger/server/sprokets'
10
-
11
- require 'mongodb_logger/server/model/additional_filter'
12
- require 'mongodb_logger/server/model/filter'
13
- require 'mongodb_logger/server/model/analytic'
14
-
7
+ require 'mongodb_logger/server/helpers'
8
+ require 'mongodb_logger/server/model'
15
9
  require 'mongodb_logger/server_config'
16
10
 
17
- if defined? Encoding
18
- Encoding.default_external = Encoding::UTF_8
19
- end
11
+ Encoding.default_external = Encoding::UTF_8 if defined?(Encoding)
20
12
 
21
13
  module MongodbLogger
22
14
  class Server < Sinatra::Base
15
+ module Views; end
16
+
17
+ register Mustache::Sinatra
23
18
  helpers Sinatra::ViewHelpers
24
19
  helpers Sinatra::Partials
25
20
  helpers Sinatra::ContentFor
26
-
21
+
27
22
  dir = File.dirname(File.expand_path(__FILE__))
28
23
 
29
24
  set :views, "#{dir}/server/views"
30
25
  #set :environment, :production
31
26
  set :static, true
27
+ set :mustache, {
28
+ templates: "#{dir}/server/templates",
29
+ views: "#{dir}/server/mustache"
30
+ }
32
31
 
33
32
  helpers do
34
33
  include Rack::Utils
35
- alias_method :h, :escape_html
36
- # pipeline
37
34
  include AssetHelpers
38
-
39
- def current_page
40
- url_path request.path_info.sub('/','')
41
- end
42
-
43
- def class_if_current(path = '')
44
- 'class="active"' if current_page[0, path.size] == path
45
- end
46
-
47
- def url_path(*path_parts)
48
- [ path_prefix, path_parts ].join("/").squeeze('/')
49
- end
35
+ include MustacheHelpers
36
+ alias_method :h, :escape_html
50
37
  alias_method :u, :url_path
51
-
52
- def path_prefix
53
- request.env['SCRIPT_NAME']
54
- end
55
-
56
38
  end
57
-
39
+
58
40
  before do
59
41
  begin
42
+ @main_dir = dir
60
43
  @mongo_adapter = (ServerConfig.mongo_adapter ? ServerConfig.mongo_adapter : Rails.logger.mongo_adapter)
61
44
  @collection_stats = @mongo_adapter.collection_stats
62
45
  rescue => e
63
46
  erb :error, {:layout => false}, :error => "Can't connect to MongoDB!"
64
47
  return false
65
48
  end
66
-
49
+
67
50
  cache_control :private, :must_revalidate, :max_age => 0
68
51
  end
69
52
 
@@ -71,7 +54,7 @@ module MongodbLogger
71
54
  begin
72
55
  erb page.to_sym, {:layout => layout}
73
56
  rescue => e
74
- erb :error, {:layout => false}, :error => "Error in view. Debug: #{e.inspect}"
57
+ erb :error, { :layout => false }, :error => "Error in view. Debug: #{e.inspect}"
75
58
  end
76
59
  end
77
60
 
@@ -80,55 +63,47 @@ module MongodbLogger
80
63
  redirect url_path(:overview)
81
64
  end
82
65
 
83
- %w( overview ).each do |page|
84
- get "/#{page}/?" do
85
- @filter = ServerModel::Filter.new(params[:filter])
86
- @logs = @mongo_adapter.filter_by_conditions(@filter)
87
- show page, !request.xhr?
88
- end
66
+ get "/overview/?" do
67
+ @filter = ServerModel::Filter.new(params[:filter])
68
+ @logs = @mongo_adapter.filter_by_conditions(@filter)
69
+ show :overview, !request.xhr?
89
70
  end
90
-
71
+
72
+ # log info
73
+ get "/log/:id" do
74
+ @log = @mongo_adapter.find_by_id(params[:id])
75
+ show :show_log, !request.xhr?
76
+ end
77
+
91
78
  get "/tail_logs/?:log_last_id?" do
92
79
  @info = @mongo_adapter.tail_log_from_params(params)
93
80
  @info.merge!(
94
- :content => @info[:logs].map{|log| partial(:"shared/log", :object => log) }.join("\n"),
81
+ :content => @info[:logs].map{ |log| partial(:"shared/log", :object => log) }.join("\n"),
95
82
  :collection_stats => partial(:"shared/collection_stats", :object => @collection_stats)
96
83
  )
97
- content_type :json
98
- @info.to_json
84
+ content_type :json
85
+ MultiJson.dump(@info)
99
86
  end
100
-
87
+
101
88
  get "/changed_filter/:type" do
102
89
  type_id = ServerModel::AdditionalFilter.get_type_index params[:type]
103
90
  conditions = ServerModel::AdditionalFilter::VAR_TYPE_CONDITIONS[type_id]
104
91
  values = ServerModel::AdditionalFilter::VAR_TYPE_VALUES[type_id]
105
-
92
+
106
93
  content_type :json
107
- {
94
+ MultiJson.dump({
108
95
  :type_id => type_id,
109
96
  :conditions => conditions,
110
97
  :values => values
111
- }.to_json
98
+ })
112
99
  end
113
-
114
- # log info
115
- get "/log/:id" do
116
- @log = @mongo_adapter.find_by_id(params[:id])
117
- show :show_log, !request.xhr?
118
- end
119
-
120
- # log info right
121
- get "/log_info/:id" do
122
- @log = @mongo_adapter.find_by_id(params[:id])
123
- partial(:"shared/log_info", :object => @log)
124
- end
125
-
100
+
126
101
  get "/add_filter/?" do
127
102
  @filter = ServerModel::Filter.new(nil)
128
103
  @filter_more = ServerModel::AdditionalFilter.new(nil, @filter)
129
104
  partial(:"shared/dynamic_filter", :object => @filter_more)
130
105
  end
131
-
106
+
132
107
  # analytics
133
108
  %w( analytics ).each do |page|
134
109
  get "/#{page}/?" do
@@ -138,13 +113,13 @@ module MongodbLogger
138
113
  post "/#{page}/?" do
139
114
  @analytic = ServerModel::Analytic.new(@mongo_adapter, params[:analytic])
140
115
  content_type :json
141
- @analytic.get_data.to_json
116
+ MultiJson.dump(@analytic.get_data)
142
117
  end
143
118
  end
144
-
119
+
145
120
  error do
146
- erb :error, {:layout => false}, :error => 'Sorry there was a nasty error. Maybe no connection to MongoDB. Debug: ' + env['sinatra.error'].inspect + '<br />' + env.inspect
121
+ erb :error, { :layout => false }, :error => 'Sorry there was a nasty error. Maybe no connection to MongoDB. Debug: ' + env['sinatra.error'].inspect + '<br />' + env.inspect
147
122
  end
148
-
123
+
149
124
  end
150
125
  end
@@ -0,0 +1,5 @@
1
+ require 'mongodb_logger/server/helpers/view_helpers'
2
+ require 'mongodb_logger/server/helpers/partials'
3
+ require 'mongodb_logger/server/helpers/content_for'
4
+ require 'mongodb_logger/server/helpers/sprokets'
5
+ require 'mongodb_logger/server/helpers/mustache_helpers'
@@ -0,0 +1,66 @@
1
+ require 'multi_json'
2
+ module MongodbLogger
3
+ module MustacheHelpers
4
+ include Rack::Utils
5
+
6
+ def url_path(*path_parts)
7
+ [ path_prefix, path_parts ].join("/").squeeze('/')
8
+ end
9
+
10
+ def path_prefix
11
+ request.env['SCRIPT_NAME']
12
+ end
13
+
14
+ def current_page
15
+ url_path request.path_info.sub('/','')
16
+ end
17
+
18
+ def class_if_current(path = '')
19
+ 'class="active"' if current_page[0, path.size] == path
20
+ end
21
+
22
+ def string_from_log_message(message)
23
+ message.is_a?(Array) ? message.join("\n") : message.to_s
24
+ end
25
+
26
+ def pretty_hash(hash)
27
+ begin
28
+ Marshal::dump(hash)
29
+ h(hash.to_yaml).gsub(" ", "&nbsp; ")
30
+ rescue Exception => e # errors from Marshal or YAML
31
+ # Object couldn't be dumped, perhaps because of singleton methods -- this is the fallback
32
+ h(hash.inspect)
33
+ end
34
+ end
35
+
36
+ def log_data(log)
37
+ main_msg = "No message"
38
+ if log['messages'] && log['messages']['info']
39
+ main_msg = string_from_log_message(log['messages']['info']).truncate(300, :separator => ' ')
40
+ end
41
+ if log['is_exception'] && log['messages'] && log['messages']['error']
42
+ main_msg = string_from_log_message(log['messages']['error']).truncate(300, :separator => ' ')
43
+ end
44
+ # return value
45
+ {
46
+ '_id' => log['_id'].to_s,
47
+ 'web_url' => url_path("log/#{log['_id']}"),
48
+ 'main_msg' => main_msg,
49
+ 'is_exception_class' => (log['is_exception'] ? 'failure' : 'success'),
50
+ 'method' => log['method'],
51
+ 'url' => log['url'],
52
+ 'request_time' => log['request_time'],
53
+ 'ip' => log['ip'],
54
+ 'params' => pretty_hash(log['params'])
55
+ }
56
+ end
57
+
58
+ def log_data_json(log)
59
+ MultiJson.dump(log_data(log))
60
+ end
61
+ end
62
+
63
+ class MustacheHelpersObj
64
+ extend MustacheHelpers
65
+ end
66
+ end
@@ -3,7 +3,7 @@ require 'rack/utils'
3
3
  require 'sprockets'
4
4
 
5
5
  module MongodbLogger
6
-
6
+
7
7
  module AssetHelpers
8
8
  def asset_path(source)
9
9
  "#{request.env['SCRIPT_NAME']}/assets/#{Assets.instance.find_asset(source).digest_path}" unless Assets.instance.find_asset(source).nil?
@@ -16,11 +16,11 @@ module MongodbLogger
16
16
  end
17
17
  end
18
18
  end
19
-
19
+
20
20
  class Assets < Sprockets::Environment
21
21
  class << self
22
22
  def instance(root = nil)
23
- assets_path = File.expand_path('../../../../app/assets', __FILE__)
23
+ assets_path = File.expand_path('../../../../../app/assets', __FILE__)
24
24
  @instance ||= new(assets_path)
25
25
  end
26
26
  end
@@ -36,5 +36,5 @@ module MongodbLogger
36
36
  end
37
37
  end
38
38
  end
39
-
39
+
40
40
  end
@@ -1,24 +1,10 @@
1
1
  # view helpers
2
2
  module Sinatra::ViewHelpers
3
-
4
- def pretty_hash(hash)
5
- begin
6
- Marshal::dump(hash)
7
- h(hash.to_yaml).gsub(" ", "&nbsp; ")
8
- rescue Exception => e # errors from Marshal or YAML
9
- # Object couldn't be dumped, perhaps because of singleton methods -- this is the fallback
10
- h(object.inspect)
11
- end
12
- end
13
-
3
+
14
4
  def percent_of_userd_memory(collection_stats)
15
5
  ((collection_stats[:size] / collection_stats[:storageSize]) * 100).round
16
6
  end
17
-
18
- def string_from_log_message(message)
19
- message.is_a?(Array) ? message.join("\n") : message.to_s
20
- end
21
-
7
+
22
8
  def meta_informations(log)
23
9
  meta_data = Hash.new
24
10
  log.each do |key, val|
@@ -28,32 +14,30 @@ module Sinatra::ViewHelpers
28
14
  end
29
15
  meta_data
30
16
  end
31
-
32
- # TODO: improve this
17
+
18
+ STORAGE_UNITS = [:byte, :kb, :mb, :gb, :tb].freeze
33
19
  def number_to_human_size(number, precision = 2)
34
20
  number = begin
35
21
  Float(number)
36
22
  rescue ArgumentError, TypeError
37
23
  return number
38
24
  end
39
- case
40
- when number.to_i == 1 then
41
- "1 Byte"
42
- when number < 1024 then
43
- "%d Bytes" % number
44
- when number < 1048576 then
45
- "%.#{precision}f KB" % (number / 1024)
46
- when number < 1073741824 then
47
- "%.#{precision}f MB" % (number / 1048576)
48
- when number < 1099511627776 then
49
- "%.#{precision}f GB" % (number / 1073741824)
50
- else
51
- "%.#{precision}f TB" % (number / 1099511627776)
52
- end.sub(/([0-9]\.\d*?)0+ /, '\1 ' ).sub(/\. /,' ')
25
+ number = begin
26
+ Float(number)
27
+ rescue ArgumentError, TypeError
28
+ return number
29
+ end
30
+ base = 1024
31
+ max_exp = STORAGE_UNITS.size - 1
32
+ exponent = (Math.log(number) / Math.log(base)).to_i # Convert to base
33
+ exponent = max_exp if exponent > max_exp # we need this to avoid overflow for the highest unit
34
+ number /= base ** exponent
35
+ unit_key = STORAGE_UNITS[exponent]
36
+ ("%.#{precision}f #{unit_key.to_s.upcase}" % number).sub(/([0-9]\.\d*?)0+ /, '\1 ' ).sub(/\. /,' ')
53
37
  rescue
54
38
  nil
55
39
  end
56
-
40
+
57
41
  def text_field_tag(object, name, options = {})
58
42
  value = ""
59
43
  value = options.delete(:value) if options[:value]
@@ -64,7 +48,7 @@ module Sinatra::ViewHelpers
64
48
  end
65
49
  "<input type='text' name='#{object.form_name}[#{name.to_s}]' value='#{value}' #{attr.join(" ")} />"
66
50
  end
67
-
51
+
68
52
  def submit_tag(name, value, options = {})
69
53
  attr = []
70
54
  options.each do |key, val|
@@ -72,7 +56,7 @@ module Sinatra::ViewHelpers
72
56
  end
73
57
  "<input type='submit' name='#{name.to_s}' value='#{value}' #{attr.join(" ")} />"
74
58
  end
75
-
59
+
76
60
  def check_box_tag(object, name, options = {})
77
61
  value = nil
78
62
  value = options.delete(:value) if options[:value]
@@ -83,7 +67,7 @@ module Sinatra::ViewHelpers
83
67
  end
84
68
  "<input id='#{object.form_name}_#{name.to_s}' type='checkbox' name='#{object.form_name}[#{name.to_s}]' #{'checked="checked"' if value} value='1' #{attr.join(" ")} />"
85
69
  end
86
-
70
+
87
71
  def label_tag(object, name, label, options = {})
88
72
  attr = []
89
73
  options.each do |key, val|
@@ -91,7 +75,7 @@ module Sinatra::ViewHelpers
91
75
  end
92
76
  "<label for='#{object.form_name}_#{name.to_s}' #{attr.join(" ")}>#{label}</label>"
93
77
  end
94
-
78
+
95
79
  def select_tag(object, name, options_array, options = {})
96
80
  value = nil
97
81
  value = options.delete(:value) if options[:value]
@@ -113,5 +97,5 @@ module Sinatra::ViewHelpers
113
97
  select_tag << "</select>"
114
98
  select_tag.join("\n")
115
99
  end
116
-
100
+
117
101
  end