diff --git a/config/environments/development.rb b/config/environments/development.rb index e9df74f..1316dc0 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -20,4 +20,7 @@ SITE_HOST = 'localhost:3000' -config.middleware.use "Rack::Bug" \ No newline at end of file +require 'rack/bug' +ActionController::Dispatcher.middleware.use ::Rack::Bug, + :ip_masks => [IPAddr.new("127.0.0.1")], + :secret_key => "secretkeeeeeeeeeyyyyyyyyyyyyyy" diff --git a/vendor/plugins/rack-bug/.gitignore b/vendor/plugins/rack-bug/.gitignore new file mode 100644 index 0000000..de8e10e --- /dev/null +++ b/vendor/plugins/rack-bug/.gitignore @@ -0,0 +1,3 @@ +coverage +pkg +TODO \ No newline at end of file diff --git a/vendor/plugins/rack-bug/History.txt b/vendor/plugins/rack-bug/History.txt new file mode 100644 index 0000000..e69de29 diff --git a/vendor/plugins/rack-bug/MIT-LICENSE.txt b/vendor/plugins/rack-bug/MIT-LICENSE.txt new file mode 100644 index 0000000..e2463e6 --- /dev/null +++ b/vendor/plugins/rack-bug/MIT-LICENSE.txt @@ -0,0 +1,19 @@ +Copyright (c) 2009 Bryan Helmkamp + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/plugins/rack-bug/README.rdoc b/vendor/plugins/rack-bug/README.rdoc new file mode 100644 index 0000000..516c1f7 --- /dev/null +++ b/vendor/plugins/rack-bug/README.rdoc @@ -0,0 +1,19 @@ +Usage: + + script/plugin install git://github.com/brynary/rack-bug.git + + # config/environments/development.rb + config.middleware.use "Rack::Bug" + + # add bookmarklet to browser + open http://RAILS_APP/__rack_bug__/bookmarklet.html + +Thanks to: + + Django debug toolbar + Rails footnotes + Rack's ShowException middleware + Oink + Rack::Cache + + diff --git a/vendor/plugins/rack-bug/Rakefile b/vendor/plugins/rack-bug/Rakefile new file mode 100644 index 0000000..6859c49 --- /dev/null +++ b/vendor/plugins/rack-bug/Rakefile @@ -0,0 +1,49 @@ +require "rubygems" +require "rake/gempackagetask" +require "rake/clean" +require "spec/rake/spectask" + +$LOAD_PATH.unshift File.dirname(__FILE__) + '/lib' + +require "rack/bug" + +Spec::Rake::SpecTask.new do |t| + t.spec_opts = ['--options', "\"#{File.dirname(__FILE__)}/spec/spec.opts\""] +end + +desc "Run the specs" +task :default => :spec + +desc "Run all specs in spec directory with RCov" +Spec::Rake::SpecTask.new(:rcov) do |t| + t.spec_opts = ['--options', "\"#{File.dirname(__FILE__)}/spec/spec.opts\""] + t.rcov = true + t.rcov_opts = lambda do + IO.readlines(File.dirname(__FILE__) + "/spec/rcov.opts").map {|l| l.chomp.split " "}.flatten + end +end + +spec = Gem::Specification.new do |s| + s.name = "rack-bug" + s.version = Rack::Bug::VERSION + s.author = "Bryan Helmkamp" + s.email = "bryan" + "@" + "brynary.com" + s.homepage = "http://github.com/brynary/rack-bug" + s.summary = "Debugging toolbar for Rack applications implemented as middleware" + s.description = s.summary + s.files = %w[History.txt Rakefile README.rdoc] + Dir["lib/**/*"] + + # rdoc + s.has_rdoc = true + s.extra_rdoc_files = %w(README.rdoc MIT-LICENSE.txt) +end + +Rake::GemPackageTask.new(spec) do |package| + package.gem_spec = spec +end + +desc 'Install the package as a gem.' +task :install => [:clean, :package] do + gem = Dir['pkg/*.gem'].first + sh "sudo gem install --no-rdoc --no-ri --local #{gem}" +end \ No newline at end of file diff --git a/vendor/plugins/rack-bug/lib/rack/bug.rb b/vendor/plugins/rack-bug/lib/rack/bug.rb new file mode 100644 index 0000000..ea36ebe --- /dev/null +++ b/vendor/plugins/rack-bug/lib/rack/bug.rb @@ -0,0 +1,26 @@ +require "rack" + +module Rack::Bug + require "rack/bug/toolbar" + + VERSION = "0.1.0" + + class SecurityError < StandardError + end + + def self.enable + Thread.current["rack-bug.enabled"] = true + end + + def self.disable + Thread.current["rack-bug.enabled"] = false + end + + def self.enabled? + Thread.current["rack-bug.enabled"] == true + end + + def self.new(*args, &block) + Toolbar.new(*args, &block) + end +end \ No newline at end of file diff --git a/vendor/plugins/rack-bug/lib/rack/bug/options.rb b/vendor/plugins/rack-bug/lib/rack/bug/options.rb new file mode 100644 index 0000000..8c12f40 --- /dev/null +++ b/vendor/plugins/rack-bug/lib/rack/bug/options.rb @@ -0,0 +1,90 @@ +module Rack::Bug + + module Options + class << self + private + def option_accessor(key) + define_method(key) { || read_option(key) } + define_method("#{key}=") { |value| write_option(key, value) } + define_method("#{key}?") { || !! read_option(key) } + end + end + + option_accessor :secret_key + option_accessor :ip_masks + option_accessor :password + option_accessor :panel_classes + option_accessor :intercept_redirects + + # The underlying options Hash. During initialization (or outside of a + # request), this is a default values Hash. During a request, this is the + # Rack environment Hash. The default values Hash is merged in underneath + # the Rack environment before each request is processed. + def options + @env || @default_options + end + + # Set multiple options. + def options=(hash={}) + hash.each { |key,value| write_option(key, value) } + end + + # Set an option. When +option+ is a Symbol, it is set in the Rack + # Environment as "rack-cache.option". When +option+ is a String, it + # exactly as specified. The +option+ argument may also be a Hash in + # which case each key/value pair is merged into the environment as if + # the #set method were called on each. + def set(option, value=self, &block) + if block_given? + write_option option, block + elsif value == self + self.options = option.to_hash + else + write_option option, value + end + end + + private + + def read_option(key) + options[option_name(key)] + end + + def write_option(key, value) + options[option_name(key)] = value + end + + def option_name(key) + case key + when Symbol ; "rack-bug.#{key}" + when String ; key + else raise ArgumentError + end + end + + def initialize_options(options={}) + @default_options = { + 'rack-bug.ip_masks' => [IPAddr.new("127.0.0.1")], + 'rack-bug.password' => nil, + 'rack-bug.verbose' => nil, + 'rack-bug.secret_key' => nil, + 'rack-bug.intercept_redirects' => false, + 'rack-bug.panels' => [], + 'rack-bug.panel_classes' => [ + RailsInfoPanel, + TimerPanel, + RequestVariablesPanel, + EnvPanel, + SQLPanel, + ActiveRecordPanel, + CachePanel, + TemplatesPanel, + LogPanel, + MemoryPanel + ] + } + self.options = options + end + + end +end diff --git a/vendor/plugins/rack-bug/lib/rack/bug/panel.rb b/vendor/plugins/rack-bug/lib/rack/bug/panel.rb new file mode 100644 index 0000000..c895b1b --- /dev/null +++ b/vendor/plugins/rack-bug/lib/rack/bug/panel.rb @@ -0,0 +1,50 @@ +require "erb" + +module Rack + module Bug + + # Panels are also Rack middleware + class Panel + include Render + include ERB::Util + + attr_reader :request + + def initialize(app) + if panel_app + @app = Rack::Cascade.new([panel_app, app]) + else + @app = app + end + end + + def call(env) + before(env) + status, headers, body = @app.call(env) + @request = Request.new(env) + after(env, status, headers, body) + env["rack-bug.panels"] << self + return [status, headers, body] + end + + def panel_app + nil + end + + def has_content? + true + end + + def before(env) + end + + def after(env, status, headers, body) + end + + def render(template) + end + + end + + end +end \ No newline at end of file diff --git a/vendor/plugins/rack-bug/lib/rack/bug/panel_app.rb b/vendor/plugins/rack-bug/lib/rack/bug/panel_app.rb new file mode 100644 index 0000000..18d731f --- /dev/null +++ b/vendor/plugins/rack-bug/lib/rack/bug/panel_app.rb @@ -0,0 +1,35 @@ +require "rack/bug/params_signature" + +module Rack + module Bug + + class PanelApp + include Rack::Bug::Render + + attr_reader :request + + def call(env) + @request = Rack::Request.new(env) + dispatch + end + + def render_template(*args) + Rack::Response.new([super]).to_a + end + + def params + @request.GET + end + + def not_found + [404, {}, []] + end + + def validate_params + ParamsSignature.new(request).validate! + end + + end + + end +end \ No newline at end of file diff --git a/vendor/plugins/rack-bug/lib/rack/bug/panels/active_record_panel.rb b/vendor/plugins/rack-bug/lib/rack/bug/panels/active_record_panel.rb new file mode 100644 index 0000000..425c3a4 --- /dev/null +++ b/vendor/plugins/rack-bug/lib/rack/bug/panels/active_record_panel.rb @@ -0,0 +1,46 @@ +require "rack/bug/panel" +require "rack/bug/panels/active_record_panel/activerecord_extensions" + +module Rack + module Bug + + class ActiveRecordPanel < Panel + + def self.record(class_name) + return unless Rack::Bug.enabled? + records[class_name] += 1 + end + + def self.reset + Thread.current["rack.bug.active_records"] = Hash.new { 0 } + end + + def self.records + Thread.current["rack.bug.active_records"] ||= Hash.new { 0 } + end + + def self.total + records.inject(0) do |memo, (key, value)| + memo + value + end + end + + def name + "active_record" + end + + def heading + "#{self.class.total} AR Objects" + end + + def content + records = self.class.records.to_a.sort_by { |key, value| value }.reverse + result = render_template "panels/active_record", :records => records + self.class.reset + result + end + + end + + end +end \ No newline at end of file diff --git a/vendor/plugins/rack-bug/lib/rack/bug/panels/active_record_panel/activerecord_extensions.rb b/vendor/plugins/rack-bug/lib/rack/bug/panels/active_record_panel/activerecord_extensions.rb new file mode 100644 index 0000000..6256a1c --- /dev/null +++ b/vendor/plugins/rack-bug/lib/rack/bug/panels/active_record_panel/activerecord_extensions.rb @@ -0,0 +1,18 @@ +if defined?(ActiveRecord) + ActiveRecord::Base.class_eval do + + if instance_methods.include?("after_initialize") + def after_initialize_with_rack_bug + Rack::Bug::ActiveRecordPanel.record(self.class.base_class.name) + after_initialize_without_rack_bug + end + + alias_method_chain :after_initialize, :rack_bug + else + def after_initialize + Rack::Bug::ActiveRecordPanel.record(self.class.base_class.name) + end + end + + end +end \ No newline at end of file diff --git a/vendor/plugins/rack-bug/lib/rack/bug/panels/cache_panel.rb b/vendor/plugins/rack-bug/lib/rack/bug/panels/cache_panel.rb new file mode 100644 index 0000000..fc96457 --- /dev/null +++ b/vendor/plugins/rack-bug/lib/rack/bug/panels/cache_panel.rb @@ -0,0 +1,51 @@ +require "rack/bug/panels/cache_panel/memcache_extension" + +module Rack + module Bug + + class CachePanel < Panel + + require "rack/bug/panels/cache_panel/stats" + require "rack/bug/panels/cache_panel/panel_app" + + def self.record(method, *keys, &block) + return block.call unless Rack::Bug.enabled? + + start_time = Time.now + result = block.call + total_time = Time.now - start_time + hit = result.nil? ? false : true + stats.record_call(method, total_time * 1_000, hit, *keys) + return result + end + + def self.reset + Thread.current["rack.bug.cache"] = Stats.new + end + + def self.stats + Thread.current["rack.bug.cache"] ||= Stats.new + end + + def panel_app + PanelApp.new + end + + def name + "cache" + end + + def heading + "Cache: %.2fms (#{self.class.stats.queries.size} calls)" % self.class.stats.time + end + + def content + result = render_template "panels/cache", :stats => self.class.stats + self.class.reset + return result + end + + end + + end +end \ No newline at end of file diff --git a/vendor/plugins/rack-bug/lib/rack/bug/panels/cache_panel/memcache_extension.rb b/vendor/plugins/rack-bug/lib/rack/bug/panels/cache_panel/memcache_extension.rb new file mode 100644 index 0000000..4a78377 --- /dev/null +++ b/vendor/plugins/rack-bug/lib/rack/bug/panels/cache_panel/memcache_extension.rb @@ -0,0 +1,129 @@ +if defined?(Memcached) + Memcached.class_eval do + + def set_with_rack_bug(key, value, timeout=0, marshal=true) + Rack::Bug::CachePanel.record(:set, key) do + set_without_rack_bug(key, value, timeout, marshal) + end + end + + def add_with_rack_bug(key, value, timeout=0, marshal=true) + Rack::Bug::CachePanel.record(:add, key) do + add_without_rack_bug(key, value, timeout, marshal) + end + end + + def increment_with_rack_bug(key, offset=1) + Rack::Bug::CachePanel.record(:incr, key) do + increment_without_rack_bug(key, offset) + end + end + + def decrement_with_rack_bug(key, offset=1) + Rack::Bug::CachePanel.record(:decr, key) do + decrement_without_rack_bug(key, offset) + end + end + + def replace_with_rack_bug(key, value, timeout=0, marshal=true) + Rack::Bug::CachePanel.record(:replace, key) do + replace_without_rack_bug(key, value, timeout, marshal) + end + end + + def append_with_rack_bug(key, value) + Rack::Bug::CachePanel.record(:append, key) do + append_without_rack_bug(key, value) + end + end + + def prepend_with_rack_bug(key, value) + Rack::Bug::CachePanel.record(:prepend, key) do + prepend_without_rack_bug(key, value) + end + end + + def delete_with_rack_bug(key) + Rack::Bug::CachePanel.record(:delete, key) do + delete_without_rack_bug(key) + end + end + + def get_with_rack_bug(keys, marshal=true) + if keys.is_a? Array + Rack::Bug::CachePanel.record(:get_multi, *keys) do + get_without_rack_bug(keys, marshal) + end + else + Rack::Bug::CachePanel.record(:get, keys) do + get_without_rack_bug(keys, marshal) + end + end + end + + alias_method_chain :decrement, :rack_bug + alias_method_chain :get, :rack_bug + alias_method_chain :increment, :rack_bug + alias_method_chain :set, :rack_bug + alias_method_chain :add, :rack_bug + alias_method_chain :replace, :rack_bug + alias_method_chain :delete, :rack_bug + alias_method_chain :prepend, :rack_bug + alias_method_chain :append, :rack_bug + end +end + +if defined?(MemCache) + MemCache.class_eval do + + def decr_with_rack_bug(key, amount = 1) + Rack::Bug::CachePanel.record(:decr, key) do + decr_without_rack_bug(key, amount) + end + end + + def get_with_rack_bug(key, raw = false) + Rack::Bug::CachePanel.record(:get, key) do + get_without_rack_bug(key, raw) + end + end + + def get_multi_with_rack_bug(*keys) + Rack::Bug::CachePanel.record(:get_multi, *keys) do + get_multi_without_rack_bug(*keys) + end + end + + def incr_with_rack_bug(key, amount = 1) + Rack::Bug::CachePanel.record(:incr, key) do + incr_without_rack_bug(key, amount) + end + end + + def set_with_rack_bug(key, value, expiry = 0, raw = false) + Rack::Bug::CachePanel.record(:set, key) do + set_without_rack_bug(key, value, expiry, raw) + end + end + + def add_with_rack_bug(key, value, expiry = 0, raw = false) + Rack::Bug::CachePanel.record(:add, key) do + add_without_rack_bug(key, value, expiry, raw) + end + end + + def delete_with_rack_bug(key, expiry = 0) + Rack::Bug::CachePanel.record(:delete, key) do + delete_without_rack_bug(key, expiry) + end + end + + alias_method_chain :decr, :rack_bug + alias_method_chain :get, :rack_bug + alias_method_chain :get_multi, :rack_bug + alias_method_chain :incr, :rack_bug + alias_method_chain :set, :rack_bug + alias_method_chain :add, :rack_bug + alias_method_chain :delete, :rack_bug + end +end \ No newline at end of file diff --git a/vendor/plugins/rack-bug/lib/rack/bug/panels/cache_panel/panel_app.rb b/vendor/plugins/rack-bug/lib/rack/bug/panels/cache_panel/panel_app.rb new file mode 100644 index 0000000..1f767fd --- /dev/null +++ b/vendor/plugins/rack-bug/lib/rack/bug/panels/cache_panel/panel_app.rb @@ -0,0 +1,50 @@ +require "rack/bug/panel_app" + +module Rack + module Bug + class CachePanel + + class PanelApp < ::Rack::Bug::PanelApp + + def dispatch + case request.path_info + when "/__rack_bug__/view_cache" then view_cache + when "/__rack_bug__/delete_cache" then delete_cache + when "/__rack_bug__/delete_cache_list" then delete_cache_list + else not_found + end + end + + def ok + Rack::Response.new(["OK"]).to_a + end + + def view_cache + validate_params + render_template "panels/view_cache", :key => params["key"], :value => Rails.cache.read(params["key"]) + end + + def delete_cache + validate_params + raise "Rails not found... can't delete key" unless defined?(Rails) + Rails.cache.delete(params["key"]) + ok + end + + def delete_cache_list + validate_params + raise "Rails not found... can't delete key" unless defined?(Rails) + + params.each do |key, value| + next unless key =~ /^keys_/ + Rails.cache.delete(value) + end + + ok + end + + end + + end + end +end \ No newline at end of file diff --git a/vendor/plugins/rack-bug/lib/rack/bug/panels/cache_panel/stats.rb b/vendor/plugins/rack-bug/lib/rack/bug/panels/cache_panel/stats.rb new file mode 100644 index 0000000..769f7d5 --- /dev/null +++ b/vendor/plugins/rack-bug/lib/rack/bug/panels/cache_panel/stats.rb @@ -0,0 +1,97 @@ +module Rack + module Bug + class CachePanel + + class Stats + class Query + attr_reader :method, :time, :hit, :keys + + def initialize(method, time, hit, keys) + @method = method + @time = time + @hit = hit + @keys = keys + end + + def display_time + "%.2fms" % time + end + + def display_keys + if keys.size == 1 + keys.first + else + keys.join(", ") + end + end + end + + attr_reader :calls + attr_reader :keys + attr_reader :queries + + def initialize + @queries = [] + @misses = + @calls = 0 + @time = 0.0 + @keys = [] + end + + def record_call(method, time, hit, *keys) + @queries << Query.new(method, time, hit, keys) + @calls += 1 + @time += time + @keys += keys + end + + def display_time + "%.2fms" % time + end + + def time + @queries.inject(0) do |memo, query| + memo + query.time + end + end + + def gets + count_queries(:get) + end + + def sets + count_queries(:set) + end + + def deletes + count_queries(:delete) + end + + def get_multis + count_queries(:get_multi) + end + + def hits + @queries.select { |q| [:get, :get_multi].include?(q.method) && q.hit }.size + end + + def misses + @queries.select { |q| [:get, :get_multi].include?(q.method) && !q.hit }.size + end + + def count_queries(method) + @queries.select { |q| q.method == method }.size + end + + def queries_to_param + params = {} + @queries.each_with_index do |query, index| + params["keys_#{index}"] = query.keys.first + end + params + end + end + + end + end +end \ No newline at end of file diff --git a/vendor/plugins/rack-bug/lib/rack/bug/panels/env_panel.rb b/vendor/plugins/rack-bug/lib/rack/bug/panels/env_panel.rb new file mode 100644 index 0000000..0945e44 --- /dev/null +++ b/vendor/plugins/rack-bug/lib/rack/bug/panels/env_panel.rb @@ -0,0 +1,25 @@ +module Rack + module Bug + + class EnvPanel < Panel + + def name + "env" + end + + def before(env) + @env = env + end + + def heading + "Rack Env" + end + + def content + render_template "panels/env", :env => @env + end + + end + + end +end \ No newline at end of file diff --git a/vendor/plugins/rack-bug/lib/rack/bug/panels/log_panel.rb b/vendor/plugins/rack-bug/lib/rack/bug/panels/log_panel.rb new file mode 100644 index 0000000..a143373 --- /dev/null +++ b/vendor/plugins/rack-bug/lib/rack/bug/panels/log_panel.rb @@ -0,0 +1,39 @@ +require "rack/bug/panels/log_panel/rails_extension" + +module Rack + module Bug + + class LogPanel < Panel + + def self.record(message) + return unless Rack::Bug.enabled? + return unless message + logs << message.to_s + end + + def self.reset + Thread.current["rack.bug.logs"] = [] + end + + def self.logs + Thread.current["rack.bug.logs"] ||= [] + end + + def name + "log" + end + + def heading + "Log" + end + + def content + result = render_template "panels/log", :logs => self.class.logs + self.class.reset + return result + end + + end + + end +end diff --git a/vendor/plugins/rack-bug/lib/rack/bug/panels/log_panel/rails_extension.rb b/vendor/plugins/rack-bug/lib/rack/bug/panels/log_panel/rails_extension.rb new file mode 100644 index 0000000..1f7c5a6 --- /dev/null +++ b/vendor/plugins/rack-bug/lib/rack/bug/panels/log_panel/rails_extension.rb @@ -0,0 +1,11 @@ +if defined?(Rails) && Rails.logger + module LoggingExtensions + def add(*args, &block) + logged_message = super + Rack::Bug::LogPanel.record(logged_message) + return logged_message + end + end + + Rails.logger.extend LoggingExtensions +end \ No newline at end of file diff --git a/vendor/plugins/rack-bug/lib/rack/bug/panels/memory_panel.rb b/vendor/plugins/rack-bug/lib/rack/bug/panels/memory_panel.rb new file mode 100644 index 0000000..2fa70f4 --- /dev/null +++ b/vendor/plugins/rack-bug/lib/rack/bug/panels/memory_panel.rb @@ -0,0 +1,27 @@ +# +module Rack + module Bug + + class MemoryPanel < Panel + + def before(env) + @original_memory = `ps -o rss= -p #{$$}`.to_i + end + + def after(env, status, headers, body) + @total_memory = `ps -o rss= -p #{$$}`.to_i + @memory_increase = @total_memory - @original_memory + end + + def heading + "#{@memory_increase} KB Δ, #{@total_memory} KB total" + end + + def has_content? + false + end + + end + + end +end \ No newline at end of file diff --git a/vendor/plugins/rack-bug/lib/rack/bug/panels/rails_info_panel.rb b/vendor/plugins/rack-bug/lib/rack/bug/panels/rails_info_panel.rb new file mode 100644 index 0000000..fb1eae7 --- /dev/null +++ b/vendor/plugins/rack-bug/lib/rack/bug/panels/rails_info_panel.rb @@ -0,0 +1,23 @@ +module Rack + module Bug + + class RailsInfoPanel < Panel + + def name + "rails_info" + end + + def heading + return unless defined?(Rails) + "Rails #{Rails.version}" + end + + def content + return unless defined?(Rails) + render_template "panels/rails_info" + end + + end + + end +end diff --git a/vendor/plugins/rack-bug/lib/rack/bug/panels/request_variables_panel.rb b/vendor/plugins/rack-bug/lib/rack/bug/panels/request_variables_panel.rb new file mode 100644 index 0000000..df3338e --- /dev/null +++ b/vendor/plugins/rack-bug/lib/rack/bug/panels/request_variables_panel.rb @@ -0,0 +1,25 @@ +module Rack + module Bug + + class RequestVariablesPanel < Panel + + def name + "request_variables" + end + + def before(env) + @env = env + end + + def heading + "Request Vars" + end + + def content + render_template "panels/request_variables", :request => @request + end + + end + + end +end \ No newline at end of file diff --git a/vendor/plugins/rack-bug/lib/rack/bug/panels/sql_panel.rb b/vendor/plugins/rack-bug/lib/rack/bug/panels/sql_panel.rb new file mode 100644 index 0000000..114a747 --- /dev/null +++ b/vendor/plugins/rack-bug/lib/rack/bug/panels/sql_panel.rb @@ -0,0 +1,55 @@ +require "digest" + +module Rack + module Bug + + class SQLPanel < Panel + + require "rack/bug/panels/sql_panel/sql_extension" + require "rack/bug/panels/sql_panel/query" + require "rack/bug/panels/sql_panel/panel_app" + + def panel_app + PanelApp.new + end + + def self.record(sql, backtrace = [], &block) + return block.call unless Rack::Bug.enabled? + + start_time = Time.now + result = block.call + queries << Query.new(sql, Time.now - start_time, backtrace) + + return result + end + + def self.reset + Thread.current["rack.test.queries"] = [] + end + + def self.queries + Thread.current["rack.test.queries"] ||= [] + end + + def self.total_time + (queries.inject(0) { |memo, query| memo + query.time}) * 1_000 + end + + def name + "sql" + end + + def heading + "#{self.class.queries.size} Queries (%.2fms)" % self.class.total_time + end + + def content + result = render_template "panels/sql", :queries => self.class.queries + self.class.reset + return result + end + + end + + end +end \ No newline at end of file diff --git a/vendor/plugins/rack-bug/lib/rack/bug/panels/sql_panel/panel_app.rb b/vendor/plugins/rack-bug/lib/rack/bug/panels/sql_panel/panel_app.rb new file mode 100644 index 0000000..019206d --- /dev/null +++ b/vendor/plugins/rack-bug/lib/rack/bug/panels/sql_panel/panel_app.rb @@ -0,0 +1,39 @@ +require "rack/bug/panel_app" + +module Rack + module Bug + class SQLPanel + + class PanelApp < ::Rack::Bug::PanelApp + + def dispatch + case request.path_info + when "/__rack_bug__/explain_sql" then explain_sql + when "/__rack_bug__/profile_sql" then profile_sql + when "/__rack_bug__/execute_sql" then execute_sql + else not_found + end + end + + def explain_sql + validate_params + query = Query.new(params["query"], params["time"].to_f) + render_template "panels/explain_sql", :result => query.explain, :query => query.sql, :time => query.time + end + + def profile_sql + validate_params + query = Query.new(params["query"], params["time"].to_f) + render_template "panels/profile_sql", :result => query.profile, :query => query.sql, :time => query.time + end + + def execute_sql + validate_params + query = Query.new(params["query"], params["time"].to_f) + render_template "panels/execute_sql", :result => query.execute, :query => query.sql, :time => query.time + end + + end + end + end +end \ No newline at end of file diff --git a/vendor/plugins/rack-bug/lib/rack/bug/panels/sql_panel/query.rb b/vendor/plugins/rack-bug/lib/rack/bug/panels/sql_panel/query.rb new file mode 100644 index 0000000..9648880 --- /dev/null +++ b/vendor/plugins/rack-bug/lib/rack/bug/panels/sql_panel/query.rb @@ -0,0 +1,95 @@ +module Rack + module Bug + class SQLPanel + + class Query + attr_reader :sql + attr_reader :time + attr_reader :backtrace + + def initialize(sql, time, backtrace = []) + @sql = sql + @time = time + @backtrace = backtrace + end + + def human_time + "%.2fms" % (@time * 1_000) + end + + def inspectable? + sql.strip =~ /^SELECT /i + end + + def with_profiling + self.class.execute("SET PROFILING=1") + result = yield + self.class.execute("SET PROFILING=0") + return result + end + + def explain + self.class.execute "EXPLAIN #{@sql}" + end + + def profile + with_profiling do + execute + self.class.execute <<-SQL + SELECT * + FROM information_schema.profiling + WHERE query_id = (SELECT query_id FROM information_schema.profiling ORDER BY query_id DESC LIMIT 1) + SQL + end + end + + def execute + self.class.execute(@sql) + end + + def valid_hash?(secret_key, possible_hash) + hash = Digest::SHA1.hexdigest [secret_key, @sql].join(":") + possible_hash == hash + end + + def self.execute(sql) + ActiveRecord::Base.connection.execute(sql) + end + + def self.adapter + klass = ActiveRecord::Base.connection.class.to_s + parts = klass.split '::' + if parts and parts.any? + adapter = parts.last.gsub('Adapter', '').downcase.to_sym + else + :unknown + end + end + + def adapter + self.class.adapter + end + + def self.mysql? + adapter == :mysql + end + + def mysql? + self.class.mysql? + end + + def has_backtrace? + filtered_backtrace.any? + end + + def filtered_backtrace + @filtered_backtrace ||= @backtrace.map { |l| l.to_s.strip }.select do |line| + line.starts_with?(Rails.root) && + !line.starts_with?(Rails.root.join("vendor")) + end + end + end + + end + end +end \ No newline at end of file diff --git a/vendor/plugins/rack-bug/lib/rack/bug/panels/sql_panel/sql_extension.rb b/vendor/plugins/rack-bug/lib/rack/bug/panels/sql_panel/sql_extension.rb new file mode 100644 index 0000000..387d080 --- /dev/null +++ b/vendor/plugins/rack-bug/lib/rack/bug/panels/sql_panel/sql_extension.rb @@ -0,0 +1,11 @@ +if defined?(ActiveRecord) + ActiveRecord::ConnectionAdapters::AbstractAdapter.class_eval do + def log_with_rack_bug(sql, name, &block) + Rack::Bug::SQLPanel.record(sql, Kernel.caller) do + log_without_rack_bug(sql, name, &block) + end + end + + alias_method_chain :log, :rack_bug + end +end \ No newline at end of file diff --git a/vendor/plugins/rack-bug/lib/rack/bug/panels/templates_panel.rb b/vendor/plugins/rack-bug/lib/rack/bug/panels/templates_panel.rb new file mode 100644 index 0000000..1bdd792 --- /dev/null +++ b/vendor/plugins/rack-bug/lib/rack/bug/panels/templates_panel.rb @@ -0,0 +1,44 @@ +module Rack + module Bug + + class TemplatesPanel < Panel + + require "rack/bug/panels/templates_panel/actionview_extension" + require "rack/bug/panels/templates_panel/trace" + require "rack/bug/panels/templates_panel/rendering" + + def self.record(template, &block) + return block.call unless Rack::Bug.enabled? + + template_trace.start(template) + result = block.call + template_trace.finished(template) + return result + end + + def self.reset + Thread.current["rack.bug.template_trace"] = Trace.new + end + + def self.template_trace + Thread.current["rack.bug.template_trace"] ||= Trace.new + end + + def name + "templates" + end + + def heading + "Templates: %.2fms" % (self.class.template_trace.total_time * 1_000) + end + + def content + result = render_template "panels/templates", :template_trace => self.class.template_trace + self.class.reset + return result + end + + end + + end +end \ No newline at end of file diff --git a/vendor/plugins/rack-bug/lib/rack/bug/panels/templates_panel/actionview_extension.rb b/vendor/plugins/rack-bug/lib/rack/bug/panels/templates_panel/actionview_extension.rb new file mode 100644 index 0000000..f2e1238 --- /dev/null +++ b/vendor/plugins/rack-bug/lib/rack/bug/panels/templates_panel/actionview_extension.rb @@ -0,0 +1,12 @@ +if defined?(ActionView) && defined?(ActionView::Template) + ActionView::Template.class_eval do + + def render_template_with_rack_bug(*args, &block) + Rack::Bug::TemplatesPanel.record(path_without_format_and_extension) do + render_template_without_rack_bug(*args, &block) + end + end + + alias_method_chain :render_template, :rack_bug + end +end \ No newline at end of file diff --git a/vendor/plugins/rack-bug/lib/rack/bug/panels/templates_panel/rendering.rb b/vendor/plugins/rack-bug/lib/rack/bug/panels/templates_panel/rendering.rb new file mode 100644 index 0000000..561c5e6 --- /dev/null +++ b/vendor/plugins/rack-bug/lib/rack/bug/panels/templates_panel/rendering.rb @@ -0,0 +1,67 @@ +module Rack + module Bug + class TemplatesPanel + + class Rendering + attr_accessor :name + attr_accessor :start_time + attr_accessor :end_time + attr_accessor :parent + attr_reader :children + + + def initialize(name) + @name = name + @children = [] + end + + def add(rendering) + @children << rendering + rendering.parent = self + end + + def time + @end_time - @start_time + end + + def exclusive_time + time - child_time + end + + def child_time + children.inject(0.0) { |memo, c| memo + c.time } + end + + def time_summary + if children.any? + "%.2fms, %.2f exclusive" % [time * 1_000, exclusive_time * 1_000] + else + "%.2fms" % (time * 1_000) + end + end + def html + <<-HTML +
  • +

    #{name} (#{time_summary})

    + + #{children_html} +
  • + HTML + end + + def children_html + return "" unless children.any? + + <<-HTML + + HTML + end + + def joined_children_html + children.map { |c| c.html }.join + end + end + + end + end +end \ No newline at end of file diff --git a/vendor/plugins/rack-bug/lib/rack/bug/panels/templates_panel/trace.rb b/vendor/plugins/rack-bug/lib/rack/bug/panels/templates_panel/trace.rb new file mode 100644 index 0000000..52740b9 --- /dev/null +++ b/vendor/plugins/rack-bug/lib/rack/bug/panels/templates_panel/trace.rb @@ -0,0 +1,34 @@ +module Rack + module Bug + class TemplatesPanel + + class Trace + + def start(template_name) + rendering = Rendering.new(template_name) + rendering.start_time = Time.now + @current.add(rendering) + @current = rendering + end + + def finished(template_name) + @current.end_time = Time.now + @current = @current.parent + end + + def initialize + @current = root + end + + def total_time + root.child_time + end + + def root + @root ||= Rendering.new("root") + end + end + + end + end +end \ No newline at end of file diff --git a/vendor/plugins/rack-bug/lib/rack/bug/panels/timer_panel.rb b/vendor/plugins/rack-bug/lib/rack/bug/panels/timer_panel.rb new file mode 100644 index 0000000..99a1918 --- /dev/null +++ b/vendor/plugins/rack-bug/lib/rack/bug/panels/timer_panel.rb @@ -0,0 +1,41 @@ +require "rack/bug/panel" +require "benchmark" + +module Rack + module Bug + + class TimerPanel < Panel + + def name + "timer" + end + + def call(env) + status, headers, body = nil + @times = Benchmark.measure do + status, headers, body = @app.call(env) + end + + @measurements = [ + ["User CPU time", "%.2fms" % (@times.utime * 1_000)], + ["System CPU time", "%.2fms" % (@times.stime * 1_000)], + ["Total CPU time", "%.2fms" % (@times.total * 1_000)], + ["Elapsed time", "%.2fms" % (@times.real * 1_000)] + ] + + env["rack-bug.panels"] << self + return [status, headers, body] + end + + def heading + "%.2fms" % (@times.real * 1_000) + end + + def content + render_template "panels/timer", :measurements => @measurements + end + + end + + end +end \ No newline at end of file diff --git a/vendor/plugins/rack-bug/lib/rack/bug/params_signature.rb b/vendor/plugins/rack-bug/lib/rack/bug/params_signature.rb new file mode 100644 index 0000000..89ad80c --- /dev/null +++ b/vendor/plugins/rack-bug/lib/rack/bug/params_signature.rb @@ -0,0 +1,65 @@ +require "digest" + +module Rack + module Bug + + class ParamsSignature + extend ERB::Util + + def self.sign(request, hash) + parts = [] + + hash.keys.sort.each do |key| + parts << "#{key}=#{u(hash[key])}" + end + + signature = new(request).signature(hash) + parts << "hash=#{u(signature)}" + + parts.join("&") + end + + attr_reader :request + + def initialize(request) + @request = request + end + + def secret_key + @request.env['rack-bug.secret_key'] + end + + def secret_key_blank? + secret_key.nil? || secret_key == "" + end + + def validate! + if secret_key_blank? + raise SecurityError.new("Missing secret key") + end + + if secret_key_blank? || request.params["hash"] != signature(request.params) + raise SecurityError.new("Invalid query hash.") + end + end + + def signature(params) + Digest::SHA1.hexdigest(signature_base(params)) + end + + def signature_base(params) + signature = [] + signature << secret_key + + params.keys.sort.each do |key| + next if key == "hash" + signature << params[key].to_s + end + + signature.join(":") + end + + end + + end +end \ No newline at end of file diff --git a/vendor/plugins/rack-bug/lib/rack/bug/public/__rack_bug__/bookmarklet.html b/vendor/plugins/rack-bug/lib/rack/bug/public/__rack_bug__/bookmarklet.html new file mode 100644 index 0000000..aca6ad3 --- /dev/null +++ b/vendor/plugins/rack-bug/lib/rack/bug/public/__rack_bug__/bookmarklet.html @@ -0,0 +1,10 @@ + + + + +


    + + Toggle Rack::Bug + + + \ No newline at end of file diff --git a/vendor/plugins/rack-bug/lib/rack/bug/public/__rack_bug__/bookmarklet.js b/vendor/plugins/rack-bug/lib/rack/bug/public/__rack_bug__/bookmarklet.js new file mode 100644 index 0000000..3f93392 --- /dev/null +++ b/vendor/plugins/rack-bug/lib/rack/bug/public/__rack_bug__/bookmarklet.js @@ -0,0 +1,215 @@ +/** +* +* Secure Hash Algorithm (SHA1) +* http://www.webtoolkit.info/ +* +**/ + +document.SHA1 = function(msg) { + function rotate_left(n,s) { + var t4 = ( n<>>(32-s)); + return t4; + }; + + function lsb_hex(val) { + var str=""; + var i; + var vh; + var vl; + + for( i=0; i<=6; i+=2 ) { + vh = (val>>>(i*4+4))&0x0f; + vl = (val>>>(i*4))&0x0f; + str += vh.toString(16) + vl.toString(16); + } + return str; + }; + + function cvt_hex(val) { + var str=""; + var i; + var v; + + for( i=7; i>=0; i-- ) { + v = (val>>>(i*4))&0x0f; + str += v.toString(16); + } + return str; + }; + + + function Utf8Encode(string) { + string = string.replace(/\r\n/g,"\n"); + var utftext = ""; + + for (var n = 0; n < string.length; n++) { + + var c = string.charCodeAt(n); + + if (c < 128) { + utftext += String.fromCharCode(c); + } + else if((c > 127) && (c < 2048)) { + utftext += String.fromCharCode((c >> 6) | 192); + utftext += String.fromCharCode((c & 63) | 128); + } + else { + utftext += String.fromCharCode((c >> 12) | 224); + utftext += String.fromCharCode(((c >> 6) & 63) | 128); + utftext += String.fromCharCode((c & 63) | 128); + } + + } + + return utftext; + }; + + var blockstart; + var i, j; + var W = new Array(80); + var H0 = 0x67452301; + var H1 = 0xEFCDAB89; + var H2 = 0x98BADCFE; + var H3 = 0x10325476; + var H4 = 0xC3D2E1F0; + var A, B, C, D, E; + var temp; + + msg = Utf8Encode(msg); + + var msg_len = msg.length; + + var word_array = new Array(); + for( i=0; i>>29 ); + word_array.push( (msg_len<<3)&0x0ffffffff ); + + + for ( blockstart=0; blockstart)[^>]*$|^#([\w-]+)$/, + // Is it a simple selector + isSimple = /^.[^:#\[\.,]*$/; + +jQuery.fn = jQuery.prototype = { + init: function( selector, context ) { + // Make sure that a selection was provided + selector = selector || document; + + // Handle $(DOMElement) + if ( selector.nodeType ) { + this[0] = selector; + this.length = 1; + this.context = selector; + return this; + } + // Handle HTML strings + if ( typeof selector === "string" ) { + // Are we dealing with HTML string or an ID? + var match = quickExpr.exec( selector ); + + // Verify a match, and that no context was specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) + selector = jQuery.clean( [ match[1] ], context ); + + // HANDLE: $("#id") + else { + var elem = document.getElementById( match[3] ); + + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem && elem.id != match[3] ) + return jQuery().find( selector ); + + // Otherwise, we inject the element directly into the jQuery object + var ret = jQuery( elem || [] ); + ret.context = document; + ret.selector = selector; + return ret; + } + + // HANDLE: $(expr, [context]) + // (which is just equivalent to: $(content).find(expr) + } else + return jQuery( context ).find( selector ); + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) + return jQuery( document ).ready( selector ); + + // Make sure that old selector state is passed along + if ( selector.selector && selector.context ) { + this.selector = selector.selector; + this.context = selector.context; + } + + return this.setArray(jQuery.isArray( selector ) ? + selector : + jQuery.makeArray(selector)); + }, + + // Start with an empty selector + selector: "", + + // The current version of jQuery being used + jquery: "1.3.2", + + // The number of elements contained in the matched element set + size: function() { + return this.length; + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num === undefined ? + + // Return a 'clean' array + Array.prototype.slice.call( this ) : + + // Return just the object + this[ num ]; + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems, name, selector ) { + // Build a new jQuery matched element set + var ret = jQuery( elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + ret.context = this.context; + + if ( name === "find" ) + ret.selector = this.selector + (this.selector ? " " : "") + selector; + else if ( name ) + ret.selector = this.selector + "." + name + "(" + selector + ")"; + + // Return the newly-formed element set + return ret; + }, + + // Force the current matched set of elements to become + // the specified array of elements (destroying the stack in the process) + // You should use pushStack() in order to do this, but maintain the stack + setArray: function( elems ) { + // Resetting the length to 0, then using the native Array push + // is a super-fast way to populate an object with array-like properties + this.length = 0; + Array.prototype.push.apply( this, elems ); + + return this; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem && elem.jquery ? elem[0] : elem + , this ); + }, + + attr: function( name, value, type ) { + var options = name; + + // Look for the case where we're accessing a style value + if ( typeof name === "string" ) + if ( value === undefined ) + return this[0] && jQuery[ type || "attr" ]( this[0], name ); + + else { + options = {}; + options[ name ] = value; + } + + // Check to see if we're setting style values + return this.each(function(i){ + // Set all the styles + for ( name in options ) + jQuery.attr( + type ? + this.style : + this, + name, jQuery.prop( this, options[ name ], type, i, name ) + ); + }); + }, + + css: function( key, value ) { + // ignore negative width and height values + if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 ) + value = undefined; + return this.attr( key, value, "curCSS" ); + }, + + text: function( text ) { + if ( typeof text !== "object" && text != null ) + return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) ); + + var ret = ""; + + jQuery.each( text || this, function(){ + jQuery.each( this.childNodes, function(){ + if ( this.nodeType != 8 ) + ret += this.nodeType != 1 ? + this.nodeValue : + jQuery.fn.text( [ this ] ); + }); + }); + + return ret; + }, + + wrapAll: function( html ) { + if ( this[0] ) { + // The elements to wrap the target around + var wrap = jQuery( html, this[0].ownerDocument ).clone(); + + if ( this[0].parentNode ) + wrap.insertBefore( this[0] ); + + wrap.map(function(){ + var elem = this; + + while ( elem.firstChild ) + elem = elem.firstChild; + + return elem; + }).append(this); + } + + return this; + }, + + wrapInner: function( html ) { + return this.each(function(){ + jQuery( this ).contents().wrapAll( html ); + }); + }, + + wrap: function( html ) { + return this.each(function(){ + jQuery( this ).wrapAll( html ); + }); + }, + + append: function() { + return this.domManip(arguments, true, function(elem){ + if (this.nodeType == 1) + this.appendChild( elem ); + }); + }, + + prepend: function() { + return this.domManip(arguments, true, function(elem){ + if (this.nodeType == 1) + this.insertBefore( elem, this.firstChild ); + }); + }, + + before: function() { + return this.domManip(arguments, false, function(elem){ + this.parentNode.insertBefore( elem, this ); + }); + }, + + after: function() { + return this.domManip(arguments, false, function(elem){ + this.parentNode.insertBefore( elem, this.nextSibling ); + }); + }, + + end: function() { + return this.prevObject || jQuery( [] ); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: [].push, + sort: [].sort, + splice: [].splice, + + find: function( selector ) { + if ( this.length === 1 ) { + var ret = this.pushStack( [], "find", selector ); + ret.length = 0; + jQuery.find( selector, this[0], ret ); + return ret; + } else { + return this.pushStack( jQuery.unique(jQuery.map(this, function(elem){ + return jQuery.find( selector, elem ); + })), "find", selector ); + } + }, + + clone: function( events ) { + // Do the clone + var ret = this.map(function(){ + if ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(this) ) { + // IE copies events bound via attachEvent when + // using cloneNode. Calling detachEvent on the + // clone will also remove the events from the orignal + // In order to get around this, we use innerHTML. + // Unfortunately, this means some modifications to + // attributes in IE that are actually only stored + // as properties will not be copied (such as the + // the name attribute on an input). + var html = this.outerHTML; + if ( !html ) { + var div = this.ownerDocument.createElement("div"); + div.appendChild( this.cloneNode(true) ); + html = div.innerHTML; + } + + return jQuery.clean([html.replace(/ jQuery\d+="(?:\d+|null)"/g, "").replace(/^\s*/, "")])[0]; + } else + return this.cloneNode(true); + }); + + // Copy the events from the original to the clone + if ( events === true ) { + var orig = this.find("*").andSelf(), i = 0; + + ret.find("*").andSelf().each(function(){ + if ( this.nodeName !== orig[i].nodeName ) + return; + + var events = jQuery.data( orig[i], "events" ); + + for ( var type in events ) { + for ( var handler in events[ type ] ) { + jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data ); + } + } + + i++; + }); + } + + // Return the cloned set + return ret; + }, + + filter: function( selector ) { + return this.pushStack( + jQuery.isFunction( selector ) && + jQuery.grep(this, function(elem, i){ + return selector.call( elem, i ); + }) || + + jQuery.multiFilter( selector, jQuery.grep(this, function(elem){ + return elem.nodeType === 1; + }) ), "filter", selector ); + }, + + closest: function( selector ) { + var pos = jQuery.expr.match.POS.test( selector ) ? jQuery(selector) : null, + closer = 0; + + return this.map(function(){ + var cur = this; + while ( cur && cur.ownerDocument ) { + if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selector) ) { + jQuery.data(cur, "closest", closer); + return cur; + } + cur = cur.parentNode; + closer++; + } + }); + }, + + not: function( selector ) { + if ( typeof selector === "string" ) + // test special case where just one selector is passed in + if ( isSimple.test( selector ) ) + return this.pushStack( jQuery.multiFilter( selector, this, true ), "not", selector ); + else + selector = jQuery.multiFilter( selector, this ); + + var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType; + return this.filter(function() { + return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector; + }); + }, + + add: function( selector ) { + return this.pushStack( jQuery.unique( jQuery.merge( + this.get(), + typeof selector === "string" ? + jQuery( selector ) : + jQuery.makeArray( selector ) + ))); + }, + + is: function( selector ) { + return !!selector && jQuery.multiFilter( selector, this ).length > 0; + }, + + hasClass: function( selector ) { + return !!selector && this.is( "." + selector ); + }, + + val: function( value ) { + if ( value === undefined ) { + var elem = this[0]; + + if ( elem ) { + if( jQuery.nodeName( elem, 'option' ) ) + return (elem.attributes.value || {}).specified ? elem.value : elem.text; + + // We need to handle select boxes special + if ( jQuery.nodeName( elem, "select" ) ) { + var index = elem.selectedIndex, + values = [], + options = elem.options, + one = elem.type == "select-one"; + + // Nothing was selected + if ( index < 0 ) + return null; + + // Loop through all the selected options + for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) { + var option = options[ i ]; + + if ( option.selected ) { + // Get the specifc value for the option + value = jQuery(option).val(); + + // We don't need an array for one selects + if ( one ) + return value; + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + } + + // Everything else, we just grab the value + return (elem.value || "").replace(/\r/g, ""); + + } + + return undefined; + } + + if ( typeof value === "number" ) + value += ''; + + return this.each(function(){ + if ( this.nodeType != 1 ) + return; + + if ( jQuery.isArray(value) && /radio|checkbox/.test( this.type ) ) + this.checked = (jQuery.inArray(this.value, value) >= 0 || + jQuery.inArray(this.name, value) >= 0); + + else if ( jQuery.nodeName( this, "select" ) ) { + var values = jQuery.makeArray(value); + + jQuery( "option", this ).each(function(){ + this.selected = (jQuery.inArray( this.value, values ) >= 0 || + jQuery.inArray( this.text, values ) >= 0); + }); + + if ( !values.length ) + this.selectedIndex = -1; + + } else + this.value = value; + }); + }, + + html: function( value ) { + return value === undefined ? + (this[0] ? + this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g, "") : + null) : + this.empty().append( value ); + }, + + replaceWith: function( value ) { + return this.after( value ).remove(); + }, + + eq: function( i ) { + return this.slice( i, +i + 1 ); + }, + + slice: function() { + return this.pushStack( Array.prototype.slice.apply( this, arguments ), + "slice", Array.prototype.slice.call(arguments).join(",") ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function(elem, i){ + return callback.call( elem, i, elem ); + })); + }, + + andSelf: function() { + return this.add( this.prevObject ); + }, + + domManip: function( args, table, callback ) { + if ( this[0] ) { + var fragment = (this[0].ownerDocument || this[0]).createDocumentFragment(), + scripts = jQuery.clean( args, (this[0].ownerDocument || this[0]), fragment ), + first = fragment.firstChild; + + if ( first ) + for ( var i = 0, l = this.length; i < l; i++ ) + callback.call( root(this[i], first), this.length > 1 || i > 0 ? + fragment.cloneNode(true) : fragment ); + + if ( scripts ) + jQuery.each( scripts, evalScript ); + } + + return this; + + function root( elem, cur ) { + return table && jQuery.nodeName(elem, "table") && jQuery.nodeName(cur, "tr") ? + (elem.getElementsByTagName("tbody")[0] || + elem.appendChild(elem.ownerDocument.createElement("tbody"))) : + elem; + } + } +}; + +// Give the init function the jQuery prototype for later instantiation +jQuery.fn.init.prototype = jQuery.fn; + +function evalScript( i, elem ) { + if ( elem.src ) + jQuery.ajax({ + url: elem.src, + async: false, + dataType: "script" + }); + + else + jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" ); + + if ( elem.parentNode ) + elem.parentNode.removeChild( elem ); +} + +function now(){ + return +new Date; +} + +jQuery.extend = jQuery.fn.extend = function() { + // copy reference to target object + var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) + target = {}; + + // extend jQuery itself if only one argument is passed + if ( length == i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) + // Extend the base object + for ( var name in options ) { + var src = target[ name ], copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) + continue; + + // Recurse if we're merging object values + if ( deep && copy && typeof copy === "object" && !copy.nodeType ) + target[ name ] = jQuery.extend( deep, + // Never move original objects, clone them + src || ( copy.length != null ? [ ] : { } ) + , copy ); + + // Don't bring in undefined values + else if ( copy !== undefined ) + target[ name ] = copy; + + } + + // Return the modified object + return target; +}; + +// exclude the following css properties to add px +var exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i, + // cache defaultView + defaultView = document.defaultView || {}, + toString = Object.prototype.toString; + +jQuery.extend({ + noConflict: function( deep ) { + window.$ = _$; + + if ( deep ) + window.jQuery = _jQuery; + + return jQuery; + }, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return toString.call(obj) === "[object Function]"; + }, + + isArray: function( obj ) { + return toString.call(obj) === "[object Array]"; + }, + + // check if an element is in a (or is an) XML document + isXMLDoc: function( elem ) { + return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" || + !!elem.ownerDocument && jQuery.isXMLDoc( elem.ownerDocument ); + }, + + // Evalulates a script in a global context + globalEval: function( data ) { + if ( data && /\S/.test(data) ) { + // Inspired by code by Andrea Giammarchi + // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html + var head = document.getElementsByTagName("head")[0] || document.documentElement, + script = document.createElement("script"); + + script.type = "text/javascript"; + if ( jQuery.support.scriptEval ) + script.appendChild( document.createTextNode( data ) ); + else + script.text = data; + + // Use insertBefore instead of appendChild to circumvent an IE6 bug. + // This arises when a base node is used (#2709). + head.insertBefore( script, head.firstChild ); + head.removeChild( script ); + } + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase(); + }, + + // args is for internal usage only + each: function( object, callback, args ) { + var name, i = 0, length = object.length; + + if ( args ) { + if ( length === undefined ) { + for ( name in object ) + if ( callback.apply( object[ name ], args ) === false ) + break; + } else + for ( ; i < length; ) + if ( callback.apply( object[ i++ ], args ) === false ) + break; + + // A special, fast, case for the most common use of each + } else { + if ( length === undefined ) { + for ( name in object ) + if ( callback.call( object[ name ], name, object[ name ] ) === false ) + break; + } else + for ( var value = object[0]; + i < length && callback.call( value, i, value ) !== false; value = object[++i] ){} + } + + return object; + }, + + prop: function( elem, value, type, i, name ) { + // Handle executable functions + if ( jQuery.isFunction( value ) ) + value = value.call( elem, i ); + + // Handle passing in a number to a CSS property + return typeof value === "number" && type == "curCSS" && !exclude.test( name ) ? + value + "px" : + value; + }, + + className: { + // internal only, use addClass("class") + add: function( elem, classNames ) { + jQuery.each((classNames || "").split(/\s+/), function(i, className){ + if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) ) + elem.className += (elem.className ? " " : "") + className; + }); + }, + + // internal only, use removeClass("class") + remove: function( elem, classNames ) { + if (elem.nodeType == 1) + elem.className = classNames !== undefined ? + jQuery.grep(elem.className.split(/\s+/), function(className){ + return !jQuery.className.has( classNames, className ); + }).join(" ") : + ""; + }, + + // internal only, use hasClass("class") + has: function( elem, className ) { + return elem && jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1; + } + }, + + // A method for quickly swapping in/out CSS properties to get correct calculations + swap: function( elem, options, callback ) { + var old = {}; + // Remember the old values, and insert the new ones + for ( var name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + callback.call( elem ); + + // Revert the old values + for ( var name in options ) + elem.style[ name ] = old[ name ]; + }, + + css: function( elem, name, force, extra ) { + if ( name == "width" || name == "height" ) { + var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ]; + + function getWH() { + val = name == "width" ? elem.offsetWidth : elem.offsetHeight; + + if ( extra === "border" ) + return; + + jQuery.each( which, function() { + if ( !extra ) + val -= parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0; + if ( extra === "margin" ) + val += parseFloat(jQuery.curCSS( elem, "margin" + this, true)) || 0; + else + val -= parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0; + }); + } + + if ( elem.offsetWidth !== 0 ) + getWH(); + else + jQuery.swap( elem, props, getWH ); + + return Math.max(0, Math.round(val)); + } + + return jQuery.curCSS( elem, name, force ); + }, + + curCSS: function( elem, name, force ) { + var ret, style = elem.style; + + // We need to handle opacity special in IE + if ( name == "opacity" && !jQuery.support.opacity ) { + ret = jQuery.attr( style, "opacity" ); + + return ret == "" ? + "1" : + ret; + } + + // Make sure we're using the right name for getting the float value + if ( name.match( /float/i ) ) + name = styleFloat; + + if ( !force && style && style[ name ] ) + ret = style[ name ]; + + else if ( defaultView.getComputedStyle ) { + + // Only "float" is needed here + if ( name.match( /float/i ) ) + name = "float"; + + name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase(); + + var computedStyle = defaultView.getComputedStyle( elem, null ); + + if ( computedStyle ) + ret = computedStyle.getPropertyValue( name ); + + // We should always get a number back from opacity + if ( name == "opacity" && ret == "" ) + ret = "1"; + + } else if ( elem.currentStyle ) { + var camelCase = name.replace(/\-(\w)/g, function(all, letter){ + return letter.toUpperCase(); + }); + + ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ]; + + // From the awesome hack by Dean Edwards + // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 + + // If we're not dealing with a regular pixel number + // but a number that has a weird ending, we need to convert it to pixels + if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) { + // Remember the original values + var left = style.left, rsLeft = elem.runtimeStyle.left; + + // Put in the new values to get a computed value out + elem.runtimeStyle.left = elem.currentStyle.left; + style.left = ret || 0; + ret = style.pixelLeft + "px"; + + // Revert the changed values + style.left = left; + elem.runtimeStyle.left = rsLeft; + } + } + + return ret; + }, + + clean: function( elems, context, fragment ) { + context = context || document; + + // !context.createElement fails in IE with an error but returns typeof 'object' + if ( typeof context.createElement === "undefined" ) + context = context.ownerDocument || context[0] && context[0].ownerDocument || document; + + // If a single string is passed in and it's a single tag + // just do a createElement and skip the rest + if ( !fragment && elems.length === 1 && typeof elems[0] === "string" ) { + var match = /^<(\w+)\s*\/?>$/.exec(elems[0]); + if ( match ) + return [ context.createElement( match[1] ) ]; + } + + var ret = [], scripts = [], div = context.createElement("div"); + + jQuery.each(elems, function(i, elem){ + if ( typeof elem === "number" ) + elem += ''; + + if ( !elem ) + return; + + // Convert html string into DOM nodes + if ( typeof elem === "string" ) { + // Fix "XHTML"-style tags in all browsers + elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){ + return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ? + all : + front + ">"; + }); + + // Trim whitespace, otherwise indexOf won't work as expected + var tags = elem.replace(/^\s+/, "").substring(0, 10).toLowerCase(); + + var wrap = + // option or optgroup + !tags.indexOf("", "" ] || + + !tags.indexOf("", "" ] || + + tags.match(/^<(thead|tbody|tfoot|colg|cap)/) && + [ 1, "", "
    " ] || + + !tags.indexOf("", "" ] || + + // matched above + (!tags.indexOf("", "" ] || + + !tags.indexOf("", "" ] || + + // IE can't serialize and + + + +
    +
    +

    There was an error within Rack::Bug!

    +
    +
    diff --git a/vendor/plugins/rack-bug/lib/rack/bug/views/panels/active_record.html.erb b/vendor/plugins/rack-bug/lib/rack/bug/views/panels/active_record.html.erb new file mode 100644 index 0000000..97eed4f --- /dev/null +++ b/vendor/plugins/rack-bug/lib/rack/bug/views/panels/active_record.html.erb @@ -0,0 +1,17 @@ +

    ActiveRecord Objects

    + + + + + + + + + <% records.each do |class_name, count| %> + + + + + <% end %> + +
    CountClass
    <%= count %><%= class_name %>
    \ No newline at end of file diff --git a/vendor/plugins/rack-bug/lib/rack/bug/views/panels/cache.html.erb b/vendor/plugins/rack-bug/lib/rack/bug/views/panels/cache.html.erb new file mode 100644 index 0000000..fd8888e --- /dev/null +++ b/vendor/plugins/rack-bug/lib/rack/bug/views/panels/cache.html.erb @@ -0,0 +1,93 @@ +

    Cache Usage

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Total Calls<%= stats.calls %>Total Time<%= stats.display_time %>Hits<%= stats.hits %>Misses<%= stats.misses %>
    gets<%= stats.gets %>sets<%= stats.sets %>deletes<%= stats.deletes %>get_multis<%= stats.get_multis %>
    + +<% if stats.queries.any? %> +

    Breakdown

    + + + + + + + + + + + + <% i = 1 %> + <% stats.queries.each do |query| %> + "> + + + + + + + <% i += 1 %> + <% end %> + +
    Time (ms)TypeParametersFunction + + Delete All + +
    <%= query.display_time %><%= query.method %><%= query.display_keys %> + query.keys.first) %>" class="remote_call">View | + query.keys.first) %>" class="rb_delete_cache">Delete +
    +<% end %> + + \ No newline at end of file diff --git a/vendor/plugins/rack-bug/lib/rack/bug/views/panels/env.html.erb b/vendor/plugins/rack-bug/lib/rack/bug/views/panels/env.html.erb new file mode 100644 index 0000000..8cba869 --- /dev/null +++ b/vendor/plugins/rack-bug/lib/rack/bug/views/panels/env.html.erb @@ -0,0 +1,19 @@ +

    Rack ENV

    + + + + + + + + + <% i = 1 %> + <% env.sort_by { |k, v| k.to_s }.each do |key, val| %> + "> + + + + <% i += 1 %> + <% end %> + +
    VariableValue
    <%=h key %>
    <%=h val %>
    \ No newline at end of file diff --git a/vendor/plugins/rack-bug/lib/rack/bug/views/panels/execute_sql.html.erb b/vendor/plugins/rack-bug/lib/rack/bug/views/panels/execute_sql.html.erb new file mode 100644 index 0000000..7a3d56a --- /dev/null +++ b/vendor/plugins/rack-bug/lib/rack/bug/views/panels/execute_sql.html.erb @@ -0,0 +1,32 @@ +« Back + +

    SQL Results

    + +
    +
    Executed SQL
    +
    <%=h query %>
    + +
    Time
    +
    <%=h "%.2f" % (time * 1_000) %>ms
    +
    + + + + + <% result.fetch_fields.each do |field| %> + + <% end %> + + + + <% i = 1 %> + <% result.each do |row| %> + "> + <% row.each do |value| %> + + <% end %> + + <% i += 1 %> + <% end %> + +
    <%= field.name.upcase %>
    <%= value %>
    diff --git a/vendor/plugins/rack-bug/lib/rack/bug/views/panels/explain_sql.html.erb b/vendor/plugins/rack-bug/lib/rack/bug/views/panels/explain_sql.html.erb new file mode 100644 index 0000000..d6f1d7c --- /dev/null +++ b/vendor/plugins/rack-bug/lib/rack/bug/views/panels/explain_sql.html.erb @@ -0,0 +1,32 @@ +« Back + +

    SQL Explained

    + +
    +
    Executed SQL
    +
    <%=h query %>
    + +
    Time
    +
    <%=h "%.2f" % (time * 1_000) %>ms
    +
    + + + + + <% result.fetch_fields.each do |field| %> + + <% end %> + + + + <% i = 1 %> + <% result.each do |row| %> + "> + <% row.each do |value| %> + + <% end %> + + <% i += 1 %> + <% end %> + +
    <%= field.name.upcase %>
    <%= value %>
    diff --git a/vendor/plugins/rack-bug/lib/rack/bug/views/panels/log.html.erb b/vendor/plugins/rack-bug/lib/rack/bug/views/panels/log.html.erb new file mode 100644 index 0000000..add0f5f --- /dev/null +++ b/vendor/plugins/rack-bug/lib/rack/bug/views/panels/log.html.erb @@ -0,0 +1,23 @@ +

    Log Messages

    + + + + + + + + + + + <% i = 1 %> + <% logs.each do |log| %> + "> + + + + + + <% i += 1 %> + <% end %> + +
    LevelTimeMessageLocation
    <%= log.to_s.gsub(/\e\[[;\d]+m/, "") %>
    \ No newline at end of file diff --git a/vendor/plugins/rack-bug/lib/rack/bug/views/panels/profile_sql.html.erb b/vendor/plugins/rack-bug/lib/rack/bug/views/panels/profile_sql.html.erb new file mode 100644 index 0000000..2135e04 --- /dev/null +++ b/vendor/plugins/rack-bug/lib/rack/bug/views/panels/profile_sql.html.erb @@ -0,0 +1,32 @@ +« Back + +

    SQL Profiled

    + +
    +
    Executed SQL
    +
    <%=h query %>
    + +
    Time
    +
    <%=h "%.2f" % (time * 1_000) %>ms
    +
    + + + + + <% result.fetch_fields.each do |field| %> + + <% end %> + + + + <% i = 1 %> + <% result.each do |row| %> + "> + <% row.each do |value| %> + + <% end %> + + <% i += 1 %> + <% end %> + +
    <%= field.name.upcase %>
    <%= value %>
    diff --git a/vendor/plugins/rack-bug/lib/rack/bug/views/panels/rails_info.html.erb b/vendor/plugins/rack-bug/lib/rack/bug/views/panels/rails_info.html.erb new file mode 100644 index 0000000..a54c313 --- /dev/null +++ b/vendor/plugins/rack-bug/lib/rack/bug/views/panels/rails_info.html.erb @@ -0,0 +1,19 @@ +

    Rails Environment

    + + + + + + + + + <% i = 1 %> + <% Rails::Info.properties.each do |key, val| %> + "> + + + + <% i += 1 %> + <% end %> + +
    VariableValue
    <%=h key %>
    <%=h val %>
    \ No newline at end of file diff --git a/vendor/plugins/rack-bug/lib/rack/bug/views/panels/request_variables.html.erb b/vendor/plugins/rack-bug/lib/rack/bug/views/panels/request_variables.html.erb new file mode 100644 index 0000000..865e2d9 --- /dev/null +++ b/vendor/plugins/rack-bug/lib/rack/bug/views/panels/request_variables.html.erb @@ -0,0 +1,87 @@ +<% if request.GET.any? %> +

    GET

    + + + + + + + + + <% i = 1 %> + <% request.GET.sort_by { |k, v| k.to_s }.each do |key, val| %> + "> + + + + <% i += 1 %> + <% end %> + +
    VariableValue
    <%=h key %>
    <%=h val %>
    +<% end %> + +<% if request.POST.any? %> +

    POST

    + + + + + + + + + <% i = 1 %> + <% request.POST.sort_by { |k, v| k.to_s }.each do |key, val| %> + "> + + + + <% i += 1 %> + <% end %> + +
    VariableValue
    <%=h key %>
    <%=h val %>
    +<% end %> + +<% if request.env["rack.session"] && request.env["rack.session"].any? %> +

    Session

    + + + + + + + + + <% i = 1 %> + <% request.env["rack.session"].sort_by { |k, v| k.to_s }.each do |key, val| %> + "> + + + + <% i += 1 %> + <% end %> + +
    VariableValue
    <%=h key %>
    <%=h val %>
    +<% end %> + +<% if request.env["rack.request.cookie_hash"] && request.env["rack.request.cookie_hash"].any? %> +

    Cookies

    + + + + + + + + + <% i = 1 %> + <% request.env["rack.request.cookie_hash"].sort_by { |k, v| k.to_s }.each do |key, val| %> + "> + + + + <% i += 1 %> + <% end %> + +
    VariableValue
    <%=h key %>
    <%=h val %>
    +<% end %> \ No newline at end of file diff --git a/vendor/plugins/rack-bug/lib/rack/bug/views/panels/sql.html.erb b/vendor/plugins/rack-bug/lib/rack/bug/views/panels/sql.html.erb new file mode 100644 index 0000000..a11e825 --- /dev/null +++ b/vendor/plugins/rack-bug/lib/rack/bug/views/panels/sql.html.erb @@ -0,0 +1,43 @@ +

    SQL Queries

    + + + + + + + + + + + <% i = 1 %> + <% queries.each do |query| %> + "> + + + + + + + + + + <% i += 1 %> + <% end %> + +
    Time (ms)Query
    <%= query.human_time %><%= query.sql %> + <% if query.has_backtrace? %> + Show Backtrace + <% end %> + + <% if query.inspectable? and query.mysql? %> + query.sql, "time" => query.time) %>" class="remote_call">SELECT | + query.sql, "time" => query.time) %>" class="remote_call">EXPLAIN | + query.sql, "time" => query.time) %>" class="remote_call">Profile + <% end %> +
    +
      + <% query.filtered_backtrace.each do |line| %> +
    • <%=h line %>
    • + <% end %> +
    +
    \ No newline at end of file diff --git a/vendor/plugins/rack-bug/lib/rack/bug/views/panels/templates.html.erb b/vendor/plugins/rack-bug/lib/rack/bug/views/panels/templates.html.erb new file mode 100644 index 0000000..724c11f --- /dev/null +++ b/vendor/plugins/rack-bug/lib/rack/bug/views/panels/templates.html.erb @@ -0,0 +1,7 @@ +

    Templates

    + +
      + <% template_trace.root.children.each do |child| %> + <%= child.html %> + <% end %> +
    diff --git a/vendor/plugins/rack-bug/lib/rack/bug/views/panels/timer.html.erb b/vendor/plugins/rack-bug/lib/rack/bug/views/panels/timer.html.erb new file mode 100644 index 0000000..6cf7420 --- /dev/null +++ b/vendor/plugins/rack-bug/lib/rack/bug/views/panels/timer.html.erb @@ -0,0 +1,19 @@ +

    Resource Usage

    + + + + + + + + + <% i = 1 %> + <% measurements.each do |key, val| %> + "> + + + + <% i += 1 %> + <% end %> + +
    KeyValue
    <%=h key %><%=h val %>
    \ No newline at end of file diff --git a/vendor/plugins/rack-bug/lib/rack/bug/views/panels/view_cache.html.erb b/vendor/plugins/rack-bug/lib/rack/bug/views/panels/view_cache.html.erb new file mode 100644 index 0000000..251700d --- /dev/null +++ b/vendor/plugins/rack-bug/lib/rack/bug/views/panels/view_cache.html.erb @@ -0,0 +1,19 @@ +« Back + +

    Cache Read

    + +
    +
    Key
    +
    <%=h key %>
    + +
    Time
    +
    <%=h "%.2f" % (0.0 * 1_000) %>ms
    +
    + +

    + <% if value.is_a?(String )%> + <%=h value %> + <% else %> + <%=h value.inspect %> + <% end %> +

    \ No newline at end of file diff --git a/vendor/plugins/rack-bug/lib/rack/bug/views/redirect.html.erb b/vendor/plugins/rack-bug/lib/rack/bug/views/redirect.html.erb new file mode 100644 index 0000000..de9add8 --- /dev/null +++ b/vendor/plugins/rack-bug/lib/rack/bug/views/redirect.html.erb @@ -0,0 +1,16 @@ + + + + +

    Redirect

    + +

    Location: <%= redirect_to %>

    + +

    + Rack::Bug has intercepted a redirect to the above URL for debug viewing + purposes. You can click the above link to continue with the redirect as + normal. If you'd like to disable this feature, set the Rack::Bug + internal_redirects option to false. +

    + + diff --git a/vendor/plugins/rack-bug/lib/rack/bug/views/toolbar.html.erb b/vendor/plugins/rack-bug/lib/rack/bug/views/toolbar.html.erb new file mode 100644 index 0000000..a8bfc3e --- /dev/null +++ b/vendor/plugins/rack-bug/lib/rack/bug/views/toolbar.html.erb @@ -0,0 +1,41 @@ + + + + +
    +
    +
      +
    • Rack::Bug
    • + + <% panels.each do |panel| %> +
    • + <% if panel.has_content? %> + + <%= panel.heading %> + + <% else %> + <%= panel.heading %> + <% end %> +
    • + <% end %> +
    +
    + + <% panels.each do |panel| %> + <% if panel.has_content? %> +
    + Close + <%= panel.content %> +
    + <% end %> + <% end %> + +
    +
    diff --git a/vendor/plugins/rack-bug/spec/fixtures/config.ru b/vendor/plugins/rack-bug/spec/fixtures/config.ru new file mode 100644 index 0000000..32118e6 --- /dev/null +++ b/vendor/plugins/rack-bug/spec/fixtures/config.ru @@ -0,0 +1,8 @@ +require "rubygems" +require "sample_app" + +$LOAD_PATH.unshift File.dirname(File.dirname(__FILE__)) + '/../../lib' +require "rack/bug" + +use Rack::Bug, :password => "secret" +run SampleApp \ No newline at end of file diff --git a/vendor/plugins/rack-bug/spec/fixtures/dummy_panel.rb b/vendor/plugins/rack-bug/spec/fixtures/dummy_panel.rb new file mode 100644 index 0000000..93e20d4 --- /dev/null +++ b/vendor/plugins/rack-bug/spec/fixtures/dummy_panel.rb @@ -0,0 +1,2 @@ +class DummyPanel < Rack::Bug::Panel +end diff --git a/vendor/plugins/rack-bug/spec/fixtures/sample_app.rb b/vendor/plugins/rack-bug/spec/fixtures/sample_app.rb new file mode 100644 index 0000000..3e1b068 --- /dev/null +++ b/vendor/plugins/rack-bug/spec/fixtures/sample_app.rb @@ -0,0 +1,29 @@ +require "sinatra/base" + +class SampleApp < Sinatra::Default + + get "/redirect" do + redirect "/" + end + + get "/error" do + raise "Error!" + end + + get "/" do + if params[:content_type] + headers["Content-Type"] = params[:content_type] + end + + <<-HTML + + + + +

    Hello

    + + + HTML + end + +end \ No newline at end of file diff --git a/vendor/plugins/rack-bug/spec/rack/bug/panels/active_record_panel_spec.rb b/vendor/plugins/rack-bug/spec/rack/bug/panels/active_record_panel_spec.rb new file mode 100644 index 0000000..5a58885 --- /dev/null +++ b/vendor/plugins/rack-bug/spec/rack/bug/panels/active_record_panel_spec.rb @@ -0,0 +1,30 @@ +require File.expand_path(File.dirname(__FILE__) + '/../../../spec_helper') + +module Rack::Bug + describe ActiveRecordPanel do + before do + ActiveRecordPanel.reset + header "rack-bug.panel_classes", [ActiveRecordPanel] + end + + describe "heading" do + it "displays the total number of instantiated AR objects" do + ActiveRecordPanel.record("User") + ActiveRecordPanel.record("Group") + response = get "/" + response.should have_heading("2 AR Objects") + end + end + + describe "content" do + it "displays the count of instantiated objects for each class" do + ActiveRecordPanel.record("User") + ActiveRecordPanel.record("User") + ActiveRecordPanel.record("Group") + response = get "/" + response.should have_row("#active_record", "User", "2") + response.should have_row("#active_record", "Group", "1") + end + end + end +end \ No newline at end of file diff --git a/vendor/plugins/rack-bug/spec/rack/bug/panels/cache_panel_spec.rb b/vendor/plugins/rack-bug/spec/rack/bug/panels/cache_panel_spec.rb new file mode 100644 index 0000000..7becf26 --- /dev/null +++ b/vendor/plugins/rack-bug/spec/rack/bug/panels/cache_panel_spec.rb @@ -0,0 +1,159 @@ +require File.expand_path(File.dirname(__FILE__) + '/../../../spec_helper') + +module Rack::Bug + describe CachePanel do + before do + CachePanel.reset + header "rack-bug.panel_classes", [CachePanel] + end + + describe "heading" do + it "displays the total memcache time" do + response = get "/" + response.should have_heading("Cache: 0.00ms") + end + end + + describe "content" do + describe "usage table" do + it "displays the total number of memcache calls" do + CachePanel.record(:get, "user:1") { } + response = get "/" + + # This causes a bus error: + # response.should have_selector("th:content('Total Calls') + td", :content => "1") + + response.should have_row("#cache_usage", "Total Calls", "1") + end + + it "displays the total memcache time" do + response = get "/" + response.should have_row("#cache_usage", "Total Time", "0.00ms") + end + + it "dispays the number of memcache hits" do + CachePanel.record(:get, "user:1") { } + response = get "/" + response.should have_row("#cache_usage", "Hits", "0") + end + + it "displays the number of memcache misses" do + CachePanel.record(:get, "user:1") { } + response = get "/" + response.should have_row("#cache_usage", "Misses", "1") + end + + it "displays the number of memcache gets" do + CachePanel.record(:get, "user:1") { } + response = get "/" + response.should have_row("#cache_usage", "gets", "1") + end + + it "displays the number of memcache sets" do + CachePanel.record(:set, "user:1") { } + response = get "/" + response.should have_row("#cache_usage", "sets", "1") + end + + it "displays the number of memcache deletes" do + CachePanel.record(:delete, "user:1") { } + response = get "/" + response.should have_row("#cache_usage", "deletes", "1") + end + + it "displays the number of memcache get_multis" do + CachePanel.record(:get_multi, "user:1", "user:2") { } + response = get "/" + response.should have_row("#cache_usage", "get_multis", "1") + end + end + + describe "breakdown" do + it "displays each memcache operation" do + CachePanel.record(:get, "user:1") { } + response = get "/" + response.should have_row("#cache_breakdown", "get") + end + + it "displays the time for each memcache call" do + CachePanel.record(:get, "user:1") { } + response = get "/" + response.should have_row("#cache_breakdown", "user:1", TIME_MS_REGEXP) + end + + it "displays the keys for each memcache call" do + CachePanel.record(:get, "user:1") { } + response = get "/" + response.should have_row("#cache_breakdown", "user:1", "get") + end + end + end + + describe "expire_all" do + before do + header "rack-bug.secret_key", 'abc' + end + + it "expires the cache keys" do + Rails.stub!(:cache => mock("cache")) + Rails.cache.should_receive(:delete).with("user:1") + Rails.cache.should_receive(:delete).with("user:2") + Rails.cache.should_receive(:delete).with("user:3") + Rails.cache.should_receive(:delete).with("user:4") + + get "/__rack_bug__/delete_cache_list", + :keys_1 => "user:1", :keys_2 => "user:2", :keys_3 => "user:3", :keys_4 => "user:4", + :hash => "c367b76e0199c308862a3afd8fba32b8715e7976" + end + + it "returns OK" do + Rails.stub!(:cache => mock("cache", :delete => nil)) + response = get "/__rack_bug__/delete_cache_list", + :keys_1 => "user:1", :keys_2 => "user:2", :keys_3 => "user:3", :keys_4 => "user:4", + :hash => "c367b76e0199c308862a3afd8fba32b8715e7976" + response.should contain("OK") + end + end + + describe "expire" do + before do + header "rack-bug.secret_key", 'abc' + end + + it "expires the cache key" do + Rails.stub!(:cache => mock("cache")) + Rails.cache.should_receive(:delete).with("user:1") + get "/__rack_bug__/delete_cache", :key => "user:1", + :hash => "f87215442d312d8e42cf51e6b66fc3eb3d59ac74" + end + + it "returns OK" do + Rails.stub!(:cache => mock("cache", :delete => nil)) + response = get "/__rack_bug__/delete_cache", :key => "user:1", + :hash => "f87215442d312d8e42cf51e6b66fc3eb3d59ac74" + response.should contain("OK") + end + end + + describe "view_cache" do + before do + header "rack-bug.secret_key", 'abc' + end + + it "renders the cache key" do + Rails.stub!(:cache => mock("cache", :read => "cache body")) + response = get "/__rack_bug__/view_cache", :key => "user:1", + :hash => "f87215442d312d8e42cf51e6b66fc3eb3d59ac74" + response.should contain("cache body") + end + + it "renders non-String cache values properly" do + Rails.stub!(:cache => mock("cache", :read => [1, 2])) + response = get "/__rack_bug__/view_cache", :key => "user:1", + :hash => "f87215442d312d8e42cf51e6b66fc3eb3d59ac74" + response.should contain("[1, 2]") + end + end + + end +end \ No newline at end of file diff --git a/vendor/plugins/rack-bug/spec/rack/bug/panels/env_panel_spec.rb b/vendor/plugins/rack-bug/spec/rack/bug/panels/env_panel_spec.rb new file mode 100644 index 0000000..93f97ee --- /dev/null +++ b/vendor/plugins/rack-bug/spec/rack/bug/panels/env_panel_spec.rb @@ -0,0 +1,24 @@ +require File.expand_path(File.dirname(__FILE__) + '/../../../spec_helper') + +module Rack::Bug + describe EnvPanel do + before do + header "rack-bug.panel_classes", [EnvPanel] + end + + describe "heading" do + it "displays 'Rack Env'" do + response = get "/" + response.should have_heading("Rack Env") + end + end + + describe "content" do + it "displays the Rack environment" do + response = get "/" + response.should have_row("#env", "PATH_INFO", "/") + response.should have_row("#env", "REMOTE_ADDR", "127.0.0.1") + end + end + end +end \ No newline at end of file diff --git a/vendor/plugins/rack-bug/spec/rack/bug/panels/log_panel_spec.rb b/vendor/plugins/rack-bug/spec/rack/bug/panels/log_panel_spec.rb new file mode 100644 index 0000000..dff2564 --- /dev/null +++ b/vendor/plugins/rack-bug/spec/rack/bug/panels/log_panel_spec.rb @@ -0,0 +1,25 @@ +require File.expand_path(File.dirname(__FILE__) + '/../../../spec_helper') + +module Rack::Bug + describe LogPanel do + before do + LogPanel.reset + header "rack-bug.panel_classes", [LogPanel] + end + + describe "heading" do + it "displays 'Log'" do + response = get "/" + response.should have_heading("Log") + end + end + + describe "content" do + it "displays recorded log lines" do + LogPanel.record("This is a logged message") + response = get "/" + response.should contain("This is a logged message") + end + end + end +end \ No newline at end of file diff --git a/vendor/plugins/rack-bug/spec/rack/bug/panels/memory_panel_spec.rb b/vendor/plugins/rack-bug/spec/rack/bug/panels/memory_panel_spec.rb new file mode 100644 index 0000000..65f57cc --- /dev/null +++ b/vendor/plugins/rack-bug/spec/rack/bug/panels/memory_panel_spec.rb @@ -0,0 +1,21 @@ +require File.expand_path(File.dirname(__FILE__) + '/../../../spec_helper') + +module Rack::Bug + describe MemoryPanel do + before do + header "rack-bug.panel_classes", [MemoryPanel] + end + + describe "heading" do + it "displays the total memory" do + response = get "/" + response.should have_heading(/\d+ KB total/) + end + + it "displays the memory change during the request" do + response = get "/" + response.should have_heading(/\d+ KB Δ/) + end + end + end +end \ No newline at end of file diff --git a/vendor/plugins/rack-bug/spec/rack/bug/panels/rails_info_panel_spec.rb b/vendor/plugins/rack-bug/spec/rack/bug/panels/rails_info_panel_spec.rb new file mode 100644 index 0000000..c66b36f --- /dev/null +++ b/vendor/plugins/rack-bug/spec/rack/bug/panels/rails_info_panel_spec.rb @@ -0,0 +1,25 @@ +require File.expand_path(File.dirname(__FILE__) + '/../../../spec_helper') + +module Rack::Bug + describe RailsInfoPanel do + before do + header "rack-bug.panel_classes", [RailsInfoPanel] + end + + describe "heading" do + it "displays the Rails version" do + Rails.stub!(:version => "v2.3.0") + response = get "/" + response.should have_heading("Rails v2.3.0") + end + end + + describe "content" do + it "displays the Rails::Info properties" do + Rails::Info.stub!(:properties => [["Name", "Value"]]) + response = get "/" + response.should have_row("#rails_info", "Name", "Value") + end + end + end +end \ No newline at end of file diff --git a/vendor/plugins/rack-bug/spec/rack/bug/panels/sql_panel_spec.rb b/vendor/plugins/rack-bug/spec/rack/bug/panels/sql_panel_spec.rb new file mode 100644 index 0000000..0ba3699 --- /dev/null +++ b/vendor/plugins/rack-bug/spec/rack/bug/panels/sql_panel_spec.rb @@ -0,0 +1,136 @@ +require File.expand_path(File.dirname(__FILE__) + '/../../../spec_helper') + +module Rack::Bug + describe SQLPanel do + before do + SQLPanel.reset + header "rack-bug.panel_classes", [SQLPanel] + end + + describe "heading" do + it "displays the total SQL query count" do + SQLPanel.record("SELECT NOW();") { } + response = get "/" + response.should have_heading("1 Queries") + end + + it "displays the total SQL time" do + SQLPanel.record("SELECT NOW();") { } + response = get "/" + response.should have_heading(/Queries \(\d+\.\d{2}ms\)/) + end + end + + describe "content" do + it "displays each executed SQL query" do + SQLPanel.record("SELECT NOW();") { } + response = get "/" + response.should have_row("#sql", "SELECT NOW();") + end + + it "displays the time of each executed SQL query" do + SQLPanel.record("SELECT NOW();") { } + response = get "/" + response.should have_row("#sql", "SELECT NOW();", TIME_MS_REGEXP) + end + end + + def stub_result(results = [[]]) + columns = results.first + fields = columns.map { |c| stub("field", :name => c) } + rows = results[1..-1] + + result = stub("result", :fetch_fields => fields) + result.stub!(:each).and_yield(*rows) + return result + end + + def expect_query(sql, results) + conn = stub("connection") + ActiveRecord::Base.stub!(:connection => conn) + conn.should_receive(:execute).with(sql).and_return(stub_result(results)) + end + + describe "execute_sql" do + it "displays the query results" do + header "rack-bug.secret_key", "abc" + expect_query "SELECT username FROM users", + [["username"], + ["bryan"]] + + response = get "/__rack_bug__/execute_sql", :query => "SELECT username FROM users", + :hash => "6f286f55b75716e5c91f16d77d09fa73b353ebc1" + response.should contain("SELECT username FROM users") + response.should be_ok + end + + it "is forbidden when the hash is missing or wrong" do + header "rack-bug.secret_key", 'abc' + + lambda { + get "/__rack_bug__/execute_sql", :query => "SELECT username FROM users", + :hash => "foobar" + }.should raise_error(SecurityError) + end + + it "is not available when the rack-bug.secret_key is nil" do + header "rack-bug.secret_key", nil + + lambda { + get "/__rack_bug__/execute_sql", :query => "SELECT username FROM users", + :hash => "6f286f55b75716e5c91f16d77d09fa73b353ebc1" + }.should raise_error(SecurityError) + end + + it "is not available when the rack-bug.secret_key is an empty string" do + header "rack-bug.secret_key", "" + + lambda { + get "/__rack_bug__/execute_sql", :query => "SELECT username FROM users", + :hash => "6f286f55b75716e5c91f16d77d09fa73b353ebc1" + }.should raise_error(SecurityError) + end + end + + describe "explain_sql" do + it "displays the query explain plan" do + header "rack-bug.secret_key", "abc" + expect_query "EXPLAIN SELECT username FROM users", + [["table"], + ["users"]] + + response = get "/__rack_bug__/explain_sql", :query => "SELECT username FROM users", + :hash => "6f286f55b75716e5c91f16d77d09fa73b353ebc1" + response.should contain("SELECT username FROM users") + response.should be_ok + end + + it "is forbidden when the hash is missing or wrong" do + header "rack-bug.secret_key", 'abc' + + lambda { + get "/__rack_bug__/explain_sql", :query => "SELECT username FROM users", + :hash => "foobar" + }.should raise_error(SecurityError) + end + + it "is not available when the rack-bug.secret_key is nil" do + header "rack-bug.secret_key", nil + + lambda { + get "/__rack_bug__/explain_sql", :query => "SELECT username FROM users", + :hash => "6f286f55b75716e5c91f16d77d09fa73b353ebc1" + }.should raise_error(SecurityError) + end + + it "is not available when the rack-bug.secret_key is an empty string" do + header "rack-bug.secret_key", "" + + lambda { + get "/__rack_bug__/explain_sql", :query => "SELECT username FROM users", + :hash => "6f286f55b75716e5c91f16d77d09fa73b353ebc1" + }.should raise_error(SecurityError) + end + end + end +end \ No newline at end of file diff --git a/vendor/plugins/rack-bug/spec/rack/bug/panels/templates_panel_spec.rb b/vendor/plugins/rack-bug/spec/rack/bug/panels/templates_panel_spec.rb new file mode 100644 index 0000000..916c196 --- /dev/null +++ b/vendor/plugins/rack-bug/spec/rack/bug/panels/templates_panel_spec.rb @@ -0,0 +1,71 @@ +require File.expand_path(File.dirname(__FILE__) + '/../../../spec_helper') + +module Rack::Bug + describe TemplatesPanel do + before do + TemplatesPanel.reset + header "rack-bug.panel_classes", [TemplatesPanel] + end + + describe "heading" do + it "displays the total rendering time" do + response = get "/" + response.should have_heading("Templates: 0.00ms") + end + end + + describe "content" do + it "displays the template paths" do + TemplatesPanel.record("users/show") { } + response = get "/" + response.should contain("users/show") + end + + it "displays the template children" do + TemplatesPanel.record("users/show") do + TemplatesPanel.record("users/toolbar") { } + end + + response = get "/" + response.should have_selector("li", :content => "users/show") do |li| + li.should contain("users/toolbar") + end + end + + context "for templates that rendered templates" do + it "displays the total time" do + TemplatesPanel.record("users/show") do + TemplatesPanel.record("users/toolbar") { } + end + + response = get "/" + response.should have_selector("li", :content => "users/show") do |li| + li.should contain(TIME_MS_REGEXP) + end + end + + it "displays the exclusive time" do + TemplatesPanel.record("users/show") do + TemplatesPanel.record("users/toolbar") { } + end + + response = get "/" + response.should have_selector("li", :content => "users/show") do |li| + li.should contain(/\d\.\d{2} exclusive/) + end + end + end + + context "for leaf templates" do + it "does not display the exclusive time" do + TemplatesPanel.record("users/show") { } + + response = get "/" + response.should contain("users/show") do |li| + li.should_not contain("exclusive") + end + end + end + end + end +end \ No newline at end of file diff --git a/vendor/plugins/rack-bug/spec/rack/bug/panels/timer_panel_spec.rb b/vendor/plugins/rack-bug/spec/rack/bug/panels/timer_panel_spec.rb new file mode 100644 index 0000000..014b243 --- /dev/null +++ b/vendor/plugins/rack-bug/spec/rack/bug/panels/timer_panel_spec.rb @@ -0,0 +1,38 @@ +require File.expand_path(File.dirname(__FILE__) + '/../../../spec_helper') + +module Rack::Bug + describe TimerPanel do + before do + header "rack-bug.panel_classes", [TimerPanel] + end + + describe "heading" do + it "displays the elapsed time" do + response = get "/" + response.should have_heading(TIME_MS_REGEXP) + end + end + + describe "content" do + it "displays the user CPU time" do + response = get "/" + response.should have_row("#timer", "User CPU time", TIME_MS_REGEXP) + end + + it "displays the system CPU time" do + response = get "/" + response.should have_row("#timer", "System CPU time", TIME_MS_REGEXP) + end + + it "displays the total CPU time" do + response = get "/" + response.should have_row("#timer", "Total CPU time", TIME_MS_REGEXP) + end + + it "displays the elapsed time" do + response = get "/" + response.should have_row("#timer", "Elapsed time", TIME_MS_REGEXP) + end + end + end +end \ No newline at end of file diff --git a/vendor/plugins/rack-bug/spec/rack/toolbar_spec.rb b/vendor/plugins/rack-bug/spec/rack/toolbar_spec.rb new file mode 100644 index 0000000..153258c --- /dev/null +++ b/vendor/plugins/rack-bug/spec/rack/toolbar_spec.rb @@ -0,0 +1,100 @@ +require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') + +describe Rack::Bug do + it "inserts the Rack::Bug toolbar" do + response = get "/" + response.should contain("Rack::Bug") + end + + it "updates the Content-Length" do + response = get "/" + response["Content-Length"].should == response.body.size.to_s + end + + it "serves the Rack::Bug assets under /__rack_bug__/" do + response = get "/__rack_bug__/bug.css" + response.should be_ok + end + + it "modifies HTML responses with a charset" do + response = get "/", :content_type => "application/xhtml+xml; charset=utf-8" + response.should contain("Rack::Bug") + end + + it "does not modify XMLHttpRequest responses" do + response = get "/", {}, { :xhr => true } + response.should_not contain("Rack::Bug") + end + + it "modifies XHTML responses" do + response = get "/", :content_type => "application/xhtml+xml" + response.should contain("Rack::Bug") + end + + it "does not modify non-HTML responses" do + response = get "/", :content_type => "text/csv" + response.should_not contain("Rack::Bug") + end + + it "does not modify redirects" do + response = get "/redirect" + response.body.should == "" + end + + it "does not modify server errors" do + response = get "/error" + response.should_not contain("Rack::Bug") + end + + context "configured to intercept redirects" do + it "inserts the Rack::Bug toolbar for redirects" do + response = get "/redirect", {}, "rack-bug.intercept_redirects" => true + response.should contain("Location: /") + end + end + + context "configured with an IP address restriction" do + before do + header "rack-bug.ip_masks", [IPAddr.new("127.0.0.1/255.255.255.0")] + end + + it "inserts the Rack::Bug toolbar when the IP matches" do + response = get "/", {}, "REMOTE_ADDR" => "127.0.0.2" + response.should contain("Rack::Bug") + end + + it "is disabled when the IP doesn't match" do + response = get "/", {}, "REMOTE_ADDR" => "128.0.0.1" + response.should_not contain("Rack::Bug") + end + + it "doesn't use any panels" do + DummyPanel.should_not_receive(:new) + header "rack-bug.panel_classes", [DummyPanel] + get "/", {}, "REMOTE_ADDR" => "128.0.0.1" + end + end + + context "configured with a password" do + before do + header "rack-bug.password", "secret" + end + + it "inserts the Rack::Bug toolbar when the password matches" do + sha = "545049d1c5e2a6e0dfefd37f9a9e0beb95241935" + response = get "/", {}, :cookie => ["rack_bug_enabled=1", "rack_bug_password=#{sha}"] + response.should contain("Rack::Bug") + end + + it "is disabled when the password doesn't match" do + response = get "/" + response.should_not contain("Rack::Bug") + end + + it "doesn't use any panels" do + DummyPanel.should_not_receive(:new) + header "rack-bug.panel_classes", [DummyPanel] + get "/" + end + end +end \ No newline at end of file diff --git a/vendor/plugins/rack-bug/spec/rcov.opts b/vendor/plugins/rack-bug/spec/rcov.opts new file mode 100644 index 0000000..5b0aa15 --- /dev/null +++ b/vendor/plugins/rack-bug/spec/rcov.opts @@ -0,0 +1 @@ +-x gems,spec\/ \ No newline at end of file diff --git a/vendor/plugins/rack-bug/spec/spec.opts b/vendor/plugins/rack-bug/spec/spec.opts new file mode 100644 index 0000000..4e1e0d2 --- /dev/null +++ b/vendor/plugins/rack-bug/spec/spec.opts @@ -0,0 +1 @@ +--color diff --git a/vendor/plugins/rack-bug/spec/spec_helper.rb b/vendor/plugins/rack-bug/spec/spec_helper.rb new file mode 100644 index 0000000..8b1caa3 --- /dev/null +++ b/vendor/plugins/rack-bug/spec/spec_helper.rb @@ -0,0 +1,70 @@ +require "rubygems" +require "spec" +require "webrat" +require "rack/test" + +$LOAD_PATH.unshift File.dirname(File.dirname(__FILE__)) + '/lib' +$LOAD_PATH.unshift File.dirname(File.dirname(__FILE__)) + +require "rack/bug" +require "spec/fixtures/sample_app" +require "spec/fixtures/dummy_panel" + +module Rails + def self.version + "" + end + + class Info + def self.properties + [] + end + end +end + +module ActiveRecord + class Base + end +end + +Spec::Runner.configure do |config| + TIME_MS_REGEXP = /\d+\.\d{2}ms/ + + config.include Rack::Test::Methods + config.include Webrat::Matchers + + config.before do + # This allows specs to record data outside the request + Rack::Bug.enable + + # Set the cookie that triggers Rack::Bug under normal conditions + header :cookie, "rack_bug_enabled=1" + end + + def app + Rack::Builder.new do + use Rack::Bug + run SampleApp.new + end + end + + def have_row(container, key, value = nil) + simple_matcher("contain row") do |response| + if value + response.should have_selector("#{container} tr", :content => key) do |row| + row.should contain(value) + end + else + response.should have_selector("#{container} tr", :content => key) + end + end + end + + def have_heading(text) + simple_matcher("have heading") do |response| + response.should have_selector("#rack_bug_toolbar li") do |heading| + heading.should contain(text) + end + end + end +end \ No newline at end of file