diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bdcc719 --- /dev/null +++ b/.gitignore @@ -0,0 +1,19 @@ +.DS_Store +log/* +tmp/* +TAGS +*~ +.#* +schema/schema.rb +schema/*_structure.sql +schema/*.sqlite3 +schema/*.sqlite +schema/*.db +*.sqlite +*.sqlite3 +*.db +src/* +.hgignore +.hg/* +.svn/* +gems/gems \ No newline at end of file diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..a760c99 --- /dev/null +++ b/Rakefile @@ -0,0 +1,35 @@ +require 'rubygems' +require 'rake/rdoctask' + +require 'merb-core' +require 'merb-core/tasks/merb' + +include FileUtils + +# Load the basic runtime dependencies; this will include +# any plugins and therefore plugin rake tasks. +init_env = ENV['MERB_ENV'] || 'rake' +Merb.load_dependencies(:environment => init_env) + +# Get Merb plugins and dependencies +Merb::Plugins.rakefiles.each { |r| require r } + +# Load any app level custom rakefile extensions from lib/tasks +tasks_path = File.join(File.dirname(__FILE__), "lib", "tasks") +rake_files = Dir["#{tasks_path}/*.rake"] +rake_files.each{|rake_file| load rake_file } + +desc "Start runner environment" +task :merb_env do + Merb.start_environment(:environment => init_env, :adapter => 'runner') +end + +require 'spec/rake/spectask' +require 'merb-core/test/tasks/spectasks' +desc 'Default: run spec examples' +task :default => 'spec' + +############################################################################## +# ADD YOUR CUSTOM TASKS IN /lib/tasks +# NAME YOUR RAKE FILES file_name.rake +############################################################################## diff --git a/app/controllers/application.rb b/app/controllers/application.rb new file mode 100644 index 0000000..6d43c48 --- /dev/null +++ b/app/controllers/application.rb @@ -0,0 +1,5 @@ +require "ruby-debug" + +class Application < Merb::Controller + +end \ No newline at end of file diff --git a/app/controllers/exceptions.rb b/app/controllers/exceptions.rb new file mode 100644 index 0000000..4fdb566 --- /dev/null +++ b/app/controllers/exceptions.rb @@ -0,0 +1,13 @@ +class Exceptions < Merb::Controller + + # handle NotFound exceptions (404) + def not_found + render :format => :html + end + + # handle NotAcceptable exceptions (406) + def not_acceptable + render :format => :html + end + +end \ No newline at end of file diff --git a/app/controllers/klasses.rb b/app/controllers/klasses.rb new file mode 100644 index 0000000..548da39 --- /dev/null +++ b/app/controllers/klasses.rb @@ -0,0 +1,17 @@ +class Klasses < Application + cache :index, :show + + # ...and remember, everything returned from an action + # goes to the client... + def index + @klasses = Doc::Class.all(:types => ["Class"]) + display @klasses + end + + def show(name) + @klass = Doc::Class.get(name) + @methods = @klass.all_methods + display @klass + end + +end diff --git a/app/helpers/global_helpers.rb b/app/helpers/global_helpers.rb new file mode 100644 index 0000000..9c9e5aa --- /dev/null +++ b/app/helpers/global_helpers.rb @@ -0,0 +1,5 @@ +module Merb + module GlobalHelpers + # helpers defined here available to all views. + end +end diff --git a/app/helpers/klass_helper.rb b/app/helpers/klass_helper.rb new file mode 100644 index 0000000..9fb93c9 --- /dev/null +++ b/app/helpers/klass_helper.rb @@ -0,0 +1,5 @@ +module Merb + module KlassHelper + + end +end # Merb \ No newline at end of file diff --git a/app/models/doc/class.rb b/app/models/doc/class.rb new file mode 100644 index 0000000..da99a73 --- /dev/null +++ b/app/models/doc/class.rb @@ -0,0 +1,74 @@ +module Doc + class Class + include Describe + + def self.any?(opts = {}) + !!get_all(opts).first + end + + def self.all(opts = {}) + get_all(opts).map {|k| new(k, opts[:api] || "public")} + end + + private + def self.get_all(opts) + opts[:api] ||= "public" + opts[:types] ||= %w(Class Module) + search = opts[:name] ? "[name='#{opts[:name]}']" : "" + search << (opts[:api] ? ":contains(':api: #{opts[:api]}')" : "") + ret = DOC_XML.css(opts[:types].map {|name| "#{name}#{search}"}.join(", ")) + end + + public + def self.get(name, api = "public") + node = get_all(:name => name, :api => api).first + node && new(node, api) + end + + attr_reader :api, :included_modules, :name, :node, + :description, :superclass + + def initialize(node, api) + @node, @api, @name = node, api, node["name"] + desc = node.xpath("./description")[0] + @description = desc && tweak_links(desc.text) + + superclass = node.css("superclass a").first + @superclass = superclass && superclass.text + @superclass = nil if @name == @superclass + + @included_modules = + node.css("included-module-list included-module"). + map {|mod| mod.get_attribute("name")} + end + + def inspect + "#" + end + + def ancestors + @included_modules + (@superclass ? [@superclass] : []) + end + + def method_list + lists = @node.css("method-list") + search = @api ? "method:contains(':api: #{@api}')" : "method" + lists.inject({}) do |accum, list| + method_list = list.css(search).map {|meth| Doc::Method.new(meth, self.name) } + (accum[list.get_attribute("category")] ||= []).push *method_list + accum + end + end + + def all_methods + ancestors.inject(method_list) do |accum, mod| + result = Doc::Class.get(mod) + result && result.all_methods.each do |k,v| + accum[k].push *v + end + accum + end + end + + end +end diff --git a/app/models/doc/describe.rb b/app/models/doc/describe.rb new file mode 100644 index 0000000..a839d4f --- /dev/null +++ b/app/models/doc/describe.rb @@ -0,0 +1,19 @@ +module Doc + module Describe + def tweak_links(desc) + desc = Nokogiri::HTML(desc) + desc.css("a[href]").each do |node| + href = node["href"] + if href =~ /#(M\d{6})/ + node["href"] = "/klasses/#{Doc::Method.by_id($1).klass}##{$1}" + elsif href =~ /#(.*)/ && Doc::Class.any?(:name => $1) + node["href"] = "/klasses/#{$1}" + else + txt = Nokogiri::XML::Text.new(node.inner_html, desc) + node.replace(txt) + end + end + desc.css("body")[0].inner_html + end + end +end \ No newline at end of file diff --git a/app/models/doc/method.rb b/app/models/doc/method.rb new file mode 100644 index 0000000..8cd2e8c --- /dev/null +++ b/app/models/doc/method.rb @@ -0,0 +1,42 @@ +module Doc + class Method + include Describe + + attr_reader :name, :type, :category, :from, + :ident, :params, :description, :source_code + + def self.by_id(id) + new(DOC_XML.css("[id='#{id}']")[0]) + end + + def initialize(node, from = nil) + @node = node + @from = klass + attrs = @node.attributes + @name = attrs["name"] + @type = attrs["type"] + @category = attrs["category"] + @ident = attrs["id"] + @params = @node.css("parameters").first.text + @source_code = + @node.css("source-code-listing").first.to_s. + match(/(.*)<\/source-code-listing>/m)[1].strip + end + + def klass + @node.xpath("../../..")[0].attributes["name"] + end + + def inspect + "#<#{name.inspect} params=#{@params.inspect} from=#{@from.inspect}>" + end + + def description + @description ||= begin + desc = @node.css("description").text + tweak_links(desc) + end + end + + end +end \ No newline at end of file diff --git a/app/views/exceptions/not_acceptable.html.erb b/app/views/exceptions/not_acceptable.html.erb new file mode 100644 index 0000000..a7b7752 --- /dev/null +++ b/app/views/exceptions/not_acceptable.html.erb @@ -0,0 +1,63 @@ +
+
+ + +

pocket rocket web framework

+
+
+ +
+

Exception:

+

<%= request.exceptions.first.message %>

+
+ +
+

Why am I seeing this page?

+

Merb couldn't find an appropriate content_type to return, + based on what you said was available via provides() and + what the client requested.

+ +

How to add a mime-type

+

+      Merb.add_mime_type :pdf, :to_pdf, %w[application/pdf], "Content-Encoding" => "gzip"
+    
+

What this means is:

+
    +
  • Add a mime-type for :pdf
  • +
  • Register the method for converting objects to PDF as #to_pdf.
  • +
  • Register the incoming mime-type "Accept" header as application/pdf.
  • +
  • Specify a new header for PDF types so it will set Content-Encoding to gzip.
  • +
+ +

You can then do:

+

+      class Foo < Application
+        provides :pdf
+      end
+    
+ +

Where can I find help?

+

If you have any questions or if you can't figure something out, please take a + look at our project page, + feel free to come chat at irc.freenode.net, channel #merb, + or post to merb mailing list + on Google Groups.

+ +

What if I've found a bug?

+

If you want to file a bug or make your own contribution to Merb, + feel free to register and create a ticket at our + project development page + on Lighthouse.

+ +

How do I edit this page?

+

You can change what people see when this happens by editing app/views/exceptions/not_acceptable.html.erb.

+ +
+ + +
diff --git a/app/views/exceptions/not_found.html.erb b/app/views/exceptions/not_found.html.erb new file mode 100644 index 0000000..42b41a8 --- /dev/null +++ b/app/views/exceptions/not_found.html.erb @@ -0,0 +1,47 @@ +
+
+ + +

pocket rocket web framework

+
+
+ +
+

Exception:

+

<%= request.exceptions.first.message %>

+
+ +
+

Welcome to Merb!

+

Merb is a light-weight MVC framework written in Ruby. We hope you enjoy it.

+ +

Where can I find help?

+

If you have any questions or if you can't figure something out, please take a + look at our project page, + feel free to come chat at irc.freenode.net, channel #merb, + or post to merb mailing list + on Google Groups.

+ +

What if I've found a bug?

+

If you want to file a bug or make your own contribution to Merb, + feel free to register and create a ticket at our + project development page + on Lighthouse.

+ +

How do I edit this page?

+

You're seeing this page because you need to edit the following files: +

    +
  • config/router.rb (recommended)
  • +
  • app/views/exceptions/not_found.html.erb (recommended)
  • +
  • app/views/layout/application.html.erb (change this layout)
  • +
+

+
+ + +
diff --git a/app/views/klasses/index.html.haml b/app/views/klasses/index.html.haml new file mode 100644 index 0000000..504f1e4 --- /dev/null +++ b/app/views/klasses/index.html.haml @@ -0,0 +1,3 @@ +%ul + - @klasses.each do |klass| + %li= link_to(klass.name, resource(klass)) \ No newline at end of file diff --git a/app/views/klasses/show.html.haml b/app/views/klasses/show.html.haml new file mode 100644 index 0000000..c00c317 --- /dev/null +++ b/app/views/klasses/show.html.haml @@ -0,0 +1,28 @@ +.sidebar + - @methods.each do |type, list| + %h2= type + %ul.method-list + - list.sort_by {|i| i.name }.each do |meth| + %li{:class => meth.from != @klass.name ? "inherit" : nil} + = link_to meth.name, "##{meth.ident}" + +.main + %h1= @klass.name + - if @klass.description + %h2 + Class Documentation + .desc= @klass.description + + - @methods.each do |type, list| + - next if list.empty? + %h2== #{type} Methods + - list.sort_by {|i| i.name}.each do |meth| + %div.method-details{:id => meth.ident} + %p.from= link_to(meth.from, "/klasses/#{meth.from}") + %p{:class => meth.from != @klass.name ? "inherit" : nil} + == #{meth.name}#{meth.params} + + .desc + = meth.description + = link_to "Show source", "#", :class => "source" + %pre.source= meth.source_code \ No newline at end of file diff --git a/app/views/layout/application.html.erb b/app/views/layout/application.html.erb new file mode 100644 index 0000000..c080b2b --- /dev/null +++ b/app/views/layout/application.html.erb @@ -0,0 +1,13 @@ + + + + Fresh Merb App + + + <%= js_include_tag "jquery", "application" %> + + + <%#= message[:notice] %> + <%= catch_content :for_layout %> + + \ No newline at end of file diff --git a/autotest/discover.rb b/autotest/discover.rb new file mode 100644 index 0000000..8df3b0f --- /dev/null +++ b/autotest/discover.rb @@ -0,0 +1,2 @@ +Autotest.add_discovery { "merb" } +Autotest.add_discovery { "rspec" } \ No newline at end of file diff --git a/autotest/merb.rb b/autotest/merb.rb new file mode 100644 index 0000000..f78df15 --- /dev/null +++ b/autotest/merb.rb @@ -0,0 +1,152 @@ +# Adapted from Autotest::Rails +require 'autotest' + +class Autotest::Merb < Autotest + + # +model_tests_dir+:: the directory to find model-centric tests + # +controller_tests_dir+:: the directory to find controller-centric tests + # +view_tests_dir+:: the directory to find view-centric tests + # +fixtures_dir+:: the directory to find fixtures in + attr_accessor :model_tests_dir, :controller_tests_dir, :view_tests_dir, :fixtures_dir + + def initialize + super + + initialize_test_layout + + # Ignore any happenings in these directories + add_exception %r%^\./(?:doc|log|public|tmp|\.git|\.hg|\.svn|framework|gems|schema|\.DS_Store|autotest|bin|.*\.sqlite3)% + # Ignore SCM directories and custom Autotest mappings + %w[.svn .hg .git .autotest].each { |exception| add_exception(exception) } + + + # Ignore any mappings that Autotest may have already set up + clear_mappings + + # Any changes to a file in the root of the 'lib' directory will run any + # model test with a corresponding name. + add_mapping %r%^lib\/.*\.rb% do |filename, _| + files_matching Regexp.new(["^#{model_test_for(filename)}$"]) + end + + # Any changes to a fixture will run corresponding view, controller and + # model tests + add_mapping %r%^#{fixtures_dir}/(.*)s.yml% do |_, m| + [ + model_test_for(m[1]), + controller_test_for(m[1]), + view_test_for(m[1]) + ] + end + + # Any change to a test will cause it to be run + add_mapping %r%^test/(unit|models|integration|controllers|views|functional)/.*rb$% do |filename, _| + filename + end + + # Any change to a model will cause it's corresponding test to be run + add_mapping %r%^app/models/(.*)\.rb$% do |_, m| + model_test_for(m[1]) + end + + # Any change to the global helper will result in all view and controller + # tests being run + add_mapping %r%^app/helpers/global_helpers.rb% do + files_matching %r%^test/(views|functional|controllers)/.*_test\.rb$% + end + + # Any change to a helper will run it's corresponding view and controller + # tests, unless the helper is the global helper. Changes to the global + # helper run all view and controller tests. + add_mapping %r%^app/helpers/(.*)_helper(s)?.rb% do |_, m| + if m[1] == "global" then + files_matching %r%^test/(views|functional|controllers)/.*_test\.rb$% + else + [ + view_test_for(m[1]), + controller_test_for(m[1]) + ] + end + end + + # Changes to views result in their corresponding view and controller test + # being run + add_mapping %r%^app/views/(.*)/% do |_, m| + [ + view_test_for(m[1]), + controller_test_for(m[1]) + ] + end + + # Changes to a controller result in its corresponding test being run. If + # the controller is the exception or application controller, all + # controller tests are run. + add_mapping %r%^app/controllers/(.*)\.rb$% do |_, m| + if ["application", "exception"].include?(m[1]) + files_matching %r%^test/(controllers|views|functional)/.*_test\.rb$% + else + controller_test_for(m[1]) + end + end + + # If a change is made to the router, run all controller and view tests + add_mapping %r%^config/router.rb$% do # FIX + files_matching %r%^test/(controllers|views|functional)/.*_test\.rb$% + end + + # If any of the major files governing the environment are altered, run + # everything + add_mapping %r%^test/test_helper.rb|config/(init|rack|environments/test.rb|database.yml)% do # FIX + files_matching %r%^test/(unit|models|controllers|views|functional)/.*_test\.rb$% + end + end + +private + + # Determines the paths we can expect tests or specs to reside, as well as + # corresponding fixtures. + def initialize_test_layout + self.model_tests_dir = "test/unit" + self.controller_tests_dir = "test/functional" + self.view_tests_dir = "test/views" + self.fixtures_dir = "test/fixtures" + end + + # Given a filename and the test type, this method will return the + # corresponding test's or spec's name. + # + # ==== Arguments + # +filename+:: the file name of the model, view, or controller + # +kind_of_test+:: the type of test we that we should run + # + # ==== Returns + # String:: the name of the corresponding test or spec + # + # ==== Example + # + # > test_for("user", :model) + # => "user_test.rb" + # > test_for("login", :controller) + # => "login_controller_test.rb" + # > test_for("form", :view) + # => "form_view_spec.rb" # If you're running a RSpec-like suite + def test_for(filename, kind_of_test) + name = [filename] + name << kind_of_test.to_s if kind_of_test == :view + name << "test" + return name.join("_") + ".rb" + end + + def model_test_for(filename) + [model_tests_dir, test_for(filename, :model)].join("/") + end + + def controller_test_for(filename) + [controller_tests_dir, test_for(filename, :controller)].join("/") + end + + def view_test_for(filename) + [view_tests_dir, test_for(filename, :view)].join("/") + end + +end \ No newline at end of file diff --git a/autotest/merb_rspec.rb b/autotest/merb_rspec.rb new file mode 100644 index 0000000..536665d --- /dev/null +++ b/autotest/merb_rspec.rb @@ -0,0 +1,165 @@ +# Adapted from Autotest::Rails, RSpec's autotest class, as well as merb-core's. +require 'autotest' + +class RspecCommandError < StandardError; end + +# This class maps your application's structure so Autotest can understand what +# specs to run when files change. +# +# Fixtures are _not_ covered by this class. If you change a fixture file, you +# will have to run your spec suite manually, or, better yet, provide your own +# Autotest map explaining how your fixtures are set up. +class Autotest::MerbRspec < Autotest + def initialize + super + + # Ignore any happenings in these directories + add_exception %r%^\./(?:doc|log|public|tmp|\.git|\.hg|\.svn|framework|gems|schema|\.DS_Store|autotest|bin|.*\.sqlite3|.*\.thor)% + # Ignore SCM directories and custom Autotest mappings + %w[.svn .hg .git .autotest].each { |exception| add_exception(exception) } + + # Ignore any mappings that Autotest may have already set up + clear_mappings + + # Anything in /lib could have a spec anywhere, if at all. So, look for + # files with roughly the same name as the file in /lib + add_mapping %r%^lib\/(.*)\.rb% do |_, m| + files_matching %r%^spec\/#{m[1]}% + end + + add_mapping %r%^spec/(spec_helper|shared/.*)\.rb$% do + all_specs + end + + # Changing a spec will cause it to run itself + add_mapping %r%^spec/.*\.rb$% do |filename, _| + filename + end + + # Any change to a model will cause it's corresponding test to be run + add_mapping %r%^app/models/(.*)\.rb$% do |_, m| + spec_for(m[1], 'model') + end + + # Any change to global_helpers will result in all view and controller + # tests being run + add_mapping %r%^app/helpers/global_helpers\.rb% do + files_matching %r%^spec/(views|controllers|helpers|requests)/.*_spec\.rb$% + end + + # Any change to a helper will cause its spec to be run + add_mapping %r%^app/helpers/((.*)_helper(s)?)\.rb% do |_, m| + spec_for(m[1], 'helper') + end + + # Changes to a view cause its spec to be run + add_mapping %r%^app/views/(.*)/% do |_, m| + spec_for(m[1], 'view') + end + + # Changes to a controller result in its corresponding spec being run. If + # the controller is the exception or application controller, all + # controller specs are run. + add_mapping %r%^app/controllers/(.*)\.rb$% do |_, m| + if ["application", "exception"].include?(m[1]) + files_matching %r%^spec/controllers/.*_spec\.rb$% + else + spec_for(m[1], 'controller') + end + end + + # If a change is made to the router, run controller, view and helper specs + add_mapping %r%^config/router.rb$% do + files_matching %r%^spec/(controllers|views|helpers)/.*_spec\.rb$% + end + + # If any of the major files governing the environment are altered, run + # everything + add_mapping %r%^config/(init|rack|environments/test).*\.rb|database\.yml% do + all_specs + end + end + + def failed_results(results) + results.scan(/^\d+\)\n(?:\e\[\d*m)?(?:.*?Error in )?'([^\n]*)'(?: FAILED)?(?:\e\[\d*m)?\n(.*?)\n\n/m) + end + + def handle_results(results) + @failures = failed_results(results) + @files_to_test = consolidate_failures(@failures) + @files_to_test.empty? && !$TESTING ? hook(:green) : hook(:red) + @tainted = !@files_to_test.empty? + end + + def consolidate_failures(failed) + filters = Hash.new { |h,k| h[k] = [] } + failed.each do |spec, failed_trace| + if f = test_files_for(failed).find { |f| f =~ /spec\// } + filters[f] << spec + break + end + end + filters + end + + def make_test_cmd(specs_to_runs) + [ + ruby, + "-S", + spec_command, + add_options_if_present, + files_to_test.keys.flatten.join(' ') + ].join(' ') + end + + def add_options_if_present + File.exist?("spec/spec.opts") ? "-O spec/spec.opts " : "" + end + + # Finds the proper spec command to use. Precendence is set in the + # lazily-evaluated method spec_commands. Alias + Override that in + # ~/.autotest to provide a different spec command then the default + # paths provided. + def spec_command(separator=File::ALT_SEPARATOR) + unless defined?(@spec_command) + @spec_command = spec_commands.find { |cmd| File.exists?(cmd) } + + raise RspecCommandError, "No spec command could be found" unless @spec_command + + @spec_command.gsub!(File::SEPARATOR, separator) if separator + end + @spec_command + end + + # Autotest will look for spec commands in the following + # locations, in this order: + # + # * default spec bin/loader installed in Rubygems + # * any spec command found in PATH + def spec_commands + [File.join(Config::CONFIG['bindir'], 'spec'), 'spec'] + end + +private + + # Runs +files_matching+ for all specs + def all_specs + files_matching %r%^spec/.*_spec\.rb$% + end + + # Generates a path to some spec given its kind and the match from a mapping + # + # ==== Arguments + # match:: the match from a mapping + # kind:: the kind of spec that the match represents + # + # ==== Returns + # String + # + # ==== Example + # > spec_for('post', :view') + # => "spec/views/post_spec.rb" + def spec_for(match, kind) + File.join("spec", kind + 's', "#{match}_spec.rb") + end +end diff --git a/bin/autospec b/bin/autospec new file mode 100755 index 0000000..f7b3fbb --- /dev/null +++ b/bin/autospec @@ -0,0 +1,31 @@ +#!/usr/bin/env ruby +# +# This file was generated by Merb's GemManagement +# +# The application 'rspec' is installed as part of a gem, and +# this file is here to facilitate running it. + +begin + require 'minigems' +rescue LoadError + require 'rubygems' +end + +# use gems dir if ../gems exists - eg. only for ./bin/autospec +if File.directory?(gems_dir = File.join(File.dirname(__FILE__), '..', 'gems')) + $BUNDLE = true; Gem.clear_paths; Gem.path.replace([File.expand_path(gems_dir)]) + ENV["PATH"] = "#{File.dirname(__FILE__)}:#{gems_dir}/bin:#{ENV["PATH"]}" + if (local_gem = Dir[File.join(gems_dir, "specifications", "rspec-*.gemspec")].last) + version = File.basename(local_gem)[/-([\.\d]+)\.gemspec$/, 1] + end +end + +version ||= ">= 0" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'rspec', version +load 'autospec' diff --git a/bin/autotest b/bin/autotest new file mode 100755 index 0000000..7f84b23 --- /dev/null +++ b/bin/autotest @@ -0,0 +1,31 @@ +#!/usr/bin/env ruby +# +# This file was generated by Merb's GemManagement +# +# The application 'ZenTest' is installed as part of a gem, and +# this file is here to facilitate running it. + +begin + require 'minigems' +rescue LoadError + require 'rubygems' +end + +# use gems dir if ../gems exists - eg. only for ./bin/autotest +if File.directory?(gems_dir = File.join(File.dirname(__FILE__), '..', 'gems')) + $BUNDLE = true; Gem.clear_paths; Gem.path.replace([File.expand_path(gems_dir)]) + ENV["PATH"] = "#{File.dirname(__FILE__)}:#{gems_dir}/bin:#{ENV["PATH"]}" + if (local_gem = Dir[File.join(gems_dir, "specifications", "ZenTest-*.gemspec")].last) + version = File.basename(local_gem)[/-([\.\d]+)\.gemspec$/, 1] + end +end + +version ||= ">= 0" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'ZenTest', version +load 'autotest' diff --git a/bin/css2sass b/bin/css2sass new file mode 100755 index 0000000..cd70385 --- /dev/null +++ b/bin/css2sass @@ -0,0 +1,31 @@ +#!/usr/bin/env ruby +# +# This file was generated by Merb's GemManagement +# +# The application 'haml' is installed as part of a gem, and +# this file is here to facilitate running it. + +begin + require 'minigems' +rescue LoadError + require 'rubygems' +end + +# use gems dir if ../gems exists - eg. only for ./bin/css2sass +if File.directory?(gems_dir = File.join(File.dirname(__FILE__), '..', 'gems')) + $BUNDLE = true; Gem.clear_paths; Gem.path.replace([File.expand_path(gems_dir)]) + ENV["PATH"] = "#{File.dirname(__FILE__)}:#{gems_dir}/bin:#{ENV["PATH"]}" + if (local_gem = Dir[File.join(gems_dir, "specifications", "haml-*.gemspec")].last) + version = File.basename(local_gem)[/-([\.\d]+)\.gemspec$/, 1] + end +end + +version ||= ">= 0" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'haml', version +load 'css2sass' diff --git a/bin/edit_json.rb b/bin/edit_json.rb new file mode 100755 index 0000000..b6d3e9b --- /dev/null +++ b/bin/edit_json.rb @@ -0,0 +1,31 @@ +#!/usr/bin/env ruby +# +# This file was generated by Merb's GemManagement +# +# The application 'json_pure' is installed as part of a gem, and +# this file is here to facilitate running it. + +begin + require 'minigems' +rescue LoadError + require 'rubygems' +end + +# use gems dir if ../gems exists - eg. only for ./bin/edit_json.rb +if File.directory?(gems_dir = File.join(File.dirname(__FILE__), '..', 'gems')) + $BUNDLE = true; Gem.clear_paths; Gem.path.replace([File.expand_path(gems_dir)]) + ENV["PATH"] = "#{File.dirname(__FILE__)}:#{gems_dir}/bin:#{ENV["PATH"]}" + if (local_gem = Dir[File.join(gems_dir, "specifications", "json_pure-*.gemspec")].last) + version = File.basename(local_gem)[/-([\.\d]+)\.gemspec$/, 1] + end +end + +version ||= ">= 0" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'json_pure', version +load 'edit_json.rb' diff --git a/bin/erubis b/bin/erubis new file mode 100755 index 0000000..d42f026 --- /dev/null +++ b/bin/erubis @@ -0,0 +1,31 @@ +#!/usr/bin/env ruby +# +# This file was generated by Merb's GemManagement +# +# The application 'erubis' is installed as part of a gem, and +# this file is here to facilitate running it. + +begin + require 'minigems' +rescue LoadError + require 'rubygems' +end + +# use gems dir if ../gems exists - eg. only for ./bin/erubis +if File.directory?(gems_dir = File.join(File.dirname(__FILE__), '..', 'gems')) + $BUNDLE = true; Gem.clear_paths; Gem.path.replace([File.expand_path(gems_dir)]) + ENV["PATH"] = "#{File.dirname(__FILE__)}:#{gems_dir}/bin:#{ENV["PATH"]}" + if (local_gem = Dir[File.join(gems_dir, "specifications", "erubis-*.gemspec")].last) + version = File.basename(local_gem)[/-([\.\d]+)\.gemspec$/, 1] + end +end + +version ||= ">= 0" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'erubis', version +load 'erubis' diff --git a/bin/gpgen b/bin/gpgen new file mode 100755 index 0000000..3ebc7e9 --- /dev/null +++ b/bin/gpgen @@ -0,0 +1,31 @@ +#!/usr/bin/env ruby +# +# This file was generated by Merb's GemManagement +# +# The application 'gem_plugin' is installed as part of a gem, and +# this file is here to facilitate running it. + +begin + require 'minigems' +rescue LoadError + require 'rubygems' +end + +# use gems dir if ../gems exists - eg. only for ./bin/gpgen +if File.directory?(gems_dir = File.join(File.dirname(__FILE__), '..', 'gems')) + $BUNDLE = true; Gem.clear_paths; Gem.path.replace([File.expand_path(gems_dir)]) + ENV["PATH"] = "#{File.dirname(__FILE__)}:#{gems_dir}/bin:#{ENV["PATH"]}" + if (local_gem = Dir[File.join(gems_dir, "specifications", "gem_plugin-*.gemspec")].last) + version = File.basename(local_gem)[/-([\.\d]+)\.gemspec$/, 1] + end +end + +version ||= ">= 0" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'gem_plugin', version +load 'gpgen' diff --git a/bin/haml b/bin/haml new file mode 100755 index 0000000..0d26ad6 --- /dev/null +++ b/bin/haml @@ -0,0 +1,31 @@ +#!/usr/bin/env ruby +# +# This file was generated by Merb's GemManagement +# +# The application 'haml' is installed as part of a gem, and +# this file is here to facilitate running it. + +begin + require 'minigems' +rescue LoadError + require 'rubygems' +end + +# use gems dir if ../gems exists - eg. only for ./bin/haml +if File.directory?(gems_dir = File.join(File.dirname(__FILE__), '..', 'gems')) + $BUNDLE = true; Gem.clear_paths; Gem.path.replace([File.expand_path(gems_dir)]) + ENV["PATH"] = "#{File.dirname(__FILE__)}:#{gems_dir}/bin:#{ENV["PATH"]}" + if (local_gem = Dir[File.join(gems_dir, "specifications", "haml-*.gemspec")].last) + version = File.basename(local_gem)[/-([\.\d]+)\.gemspec$/, 1] + end +end + +version ||= ">= 0" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'haml', version +load 'haml' diff --git a/bin/html2haml b/bin/html2haml new file mode 100755 index 0000000..2b39daa --- /dev/null +++ b/bin/html2haml @@ -0,0 +1,31 @@ +#!/usr/bin/env ruby +# +# This file was generated by Merb's GemManagement +# +# The application 'haml' is installed as part of a gem, and +# this file is here to facilitate running it. + +begin + require 'minigems' +rescue LoadError + require 'rubygems' +end + +# use gems dir if ../gems exists - eg. only for ./bin/html2haml +if File.directory?(gems_dir = File.join(File.dirname(__FILE__), '..', 'gems')) + $BUNDLE = true; Gem.clear_paths; Gem.path.replace([File.expand_path(gems_dir)]) + ENV["PATH"] = "#{File.dirname(__FILE__)}:#{gems_dir}/bin:#{ENV["PATH"]}" + if (local_gem = Dir[File.join(gems_dir, "specifications", "haml-*.gemspec")].last) + version = File.basename(local_gem)[/-([\.\d]+)\.gemspec$/, 1] + end +end + +version ||= ">= 0" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'haml', version +load 'html2haml' diff --git a/bin/htmldiff b/bin/htmldiff new file mode 100755 index 0000000..aab07ed --- /dev/null +++ b/bin/htmldiff @@ -0,0 +1,31 @@ +#!/usr/bin/env ruby +# +# This file was generated by Merb's GemManagement +# +# The application 'diff-lcs' is installed as part of a gem, and +# this file is here to facilitate running it. + +begin + require 'minigems' +rescue LoadError + require 'rubygems' +end + +# use gems dir if ../gems exists - eg. only for ./bin/htmldiff +if File.directory?(gems_dir = File.join(File.dirname(__FILE__), '..', 'gems')) + $BUNDLE = true; Gem.clear_paths; Gem.path.replace([File.expand_path(gems_dir)]) + ENV["PATH"] = "#{File.dirname(__FILE__)}:#{gems_dir}/bin:#{ENV["PATH"]}" + if (local_gem = Dir[File.join(gems_dir, "specifications", "diff-lcs-*.gemspec")].last) + version = File.basename(local_gem)[/-([\.\d]+)\.gemspec$/, 1] + end +end + +version ||= ">= 0" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'diff-lcs', version +load 'htmldiff' diff --git a/bin/ldiff b/bin/ldiff new file mode 100755 index 0000000..5f3a239 --- /dev/null +++ b/bin/ldiff @@ -0,0 +1,31 @@ +#!/usr/bin/env ruby +# +# This file was generated by Merb's GemManagement +# +# The application 'diff-lcs' is installed as part of a gem, and +# this file is here to facilitate running it. + +begin + require 'minigems' +rescue LoadError + require 'rubygems' +end + +# use gems dir if ../gems exists - eg. only for ./bin/ldiff +if File.directory?(gems_dir = File.join(File.dirname(__FILE__), '..', 'gems')) + $BUNDLE = true; Gem.clear_paths; Gem.path.replace([File.expand_path(gems_dir)]) + ENV["PATH"] = "#{File.dirname(__FILE__)}:#{gems_dir}/bin:#{ENV["PATH"]}" + if (local_gem = Dir[File.join(gems_dir, "specifications", "diff-lcs-*.gemspec")].last) + version = File.basename(local_gem)[/-([\.\d]+)\.gemspec$/, 1] + end +end + +version ||= ">= 0" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'diff-lcs', version +load 'ldiff' diff --git a/bin/merb b/bin/merb new file mode 100755 index 0000000..3bbeae1 --- /dev/null +++ b/bin/merb @@ -0,0 +1,31 @@ +#!/usr/bin/env ruby +# +# This file was generated by Merb's GemManagement +# +# The application 'merb-core' is installed as part of a gem, and +# this file is here to facilitate running it. + +begin + require 'minigems' +rescue LoadError + require 'rubygems' +end + +# use gems dir if ../gems exists - eg. only for ./bin/merb +if File.directory?(gems_dir = File.join(File.dirname(__FILE__), '..', 'gems')) + $BUNDLE = true; Gem.clear_paths; Gem.path.replace([File.expand_path(gems_dir)]) + ENV["PATH"] = "#{File.dirname(__FILE__)}:#{gems_dir}/bin:#{ENV["PATH"]}" + if (local_gem = Dir[File.join(gems_dir, "specifications", "merb-core-*.gemspec")].last) + version = File.basename(local_gem)[/-([\.\d]+)\.gemspec$/, 1] + end +end + +version ||= ">= 0" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'merb-core', version +load 'merb' diff --git a/bin/merb-gen b/bin/merb-gen new file mode 100755 index 0000000..29b28fd --- /dev/null +++ b/bin/merb-gen @@ -0,0 +1,31 @@ +#!/usr/bin/env ruby +# +# This file was generated by Merb's GemManagement +# +# The application 'merb-gen' is installed as part of a gem, and +# this file is here to facilitate running it. + +begin + require 'minigems' +rescue LoadError + require 'rubygems' +end + +# use gems dir if ../gems exists - eg. only for ./bin/merb-gen +if File.directory?(gems_dir = File.join(File.dirname(__FILE__), '..', 'gems')) + $BUNDLE = true; Gem.clear_paths; Gem.path.replace([File.expand_path(gems_dir)]) + ENV["PATH"] = "#{File.dirname(__FILE__)}:#{gems_dir}/bin:#{ENV["PATH"]}" + if (local_gem = Dir[File.join(gems_dir, "specifications", "merb-gen-*.gemspec")].last) + version = File.basename(local_gem)[/-([\.\d]+)\.gemspec$/, 1] + end +end + +version ||= ">= 0" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'merb-gen', version +load 'merb-gen' diff --git a/bin/mongrel_rails b/bin/mongrel_rails new file mode 100755 index 0000000..4ec5fdd --- /dev/null +++ b/bin/mongrel_rails @@ -0,0 +1,31 @@ +#!/usr/bin/env ruby +# +# This file was generated by Merb's GemManagement +# +# The application 'mongrel' is installed as part of a gem, and +# this file is here to facilitate running it. + +begin + require 'minigems' +rescue LoadError + require 'rubygems' +end + +# use gems dir if ../gems exists - eg. only for ./bin/mongrel_rails +if File.directory?(gems_dir = File.join(File.dirname(__FILE__), '..', 'gems')) + $BUNDLE = true; Gem.clear_paths; Gem.path.replace([File.expand_path(gems_dir)]) + ENV["PATH"] = "#{File.dirname(__FILE__)}:#{gems_dir}/bin:#{ENV["PATH"]}" + if (local_gem = Dir[File.join(gems_dir, "specifications", "mongrel-*.gemspec")].last) + version = File.basename(local_gem)[/-([\.\d]+)\.gemspec$/, 1] + end +end + +version ||= ">= 0" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'mongrel', version +load 'mongrel_rails' diff --git a/bin/multiruby b/bin/multiruby new file mode 100755 index 0000000..b6b9991 --- /dev/null +++ b/bin/multiruby @@ -0,0 +1,31 @@ +#!/usr/bin/env ruby +# +# This file was generated by Merb's GemManagement +# +# The application 'ZenTest' is installed as part of a gem, and +# this file is here to facilitate running it. + +begin + require 'minigems' +rescue LoadError + require 'rubygems' +end + +# use gems dir if ../gems exists - eg. only for ./bin/multiruby +if File.directory?(gems_dir = File.join(File.dirname(__FILE__), '..', 'gems')) + $BUNDLE = true; Gem.clear_paths; Gem.path.replace([File.expand_path(gems_dir)]) + ENV["PATH"] = "#{File.dirname(__FILE__)}:#{gems_dir}/bin:#{ENV["PATH"]}" + if (local_gem = Dir[File.join(gems_dir, "specifications", "ZenTest-*.gemspec")].last) + version = File.basename(local_gem)[/-([\.\d]+)\.gemspec$/, 1] + end +end + +version ||= ">= 0" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'ZenTest', version +load 'multiruby' diff --git a/bin/multiruby_setup b/bin/multiruby_setup new file mode 100755 index 0000000..76b14e0 --- /dev/null +++ b/bin/multiruby_setup @@ -0,0 +1,31 @@ +#!/usr/bin/env ruby +# +# This file was generated by Merb's GemManagement +# +# The application 'ZenTest' is installed as part of a gem, and +# this file is here to facilitate running it. + +begin + require 'minigems' +rescue LoadError + require 'rubygems' +end + +# use gems dir if ../gems exists - eg. only for ./bin/multiruby_setup +if File.directory?(gems_dir = File.join(File.dirname(__FILE__), '..', 'gems')) + $BUNDLE = true; Gem.clear_paths; Gem.path.replace([File.expand_path(gems_dir)]) + ENV["PATH"] = "#{File.dirname(__FILE__)}:#{gems_dir}/bin:#{ENV["PATH"]}" + if (local_gem = Dir[File.join(gems_dir, "specifications", "ZenTest-*.gemspec")].last) + version = File.basename(local_gem)[/-([\.\d]+)\.gemspec$/, 1] + end +end + +version ||= ">= 0" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'ZenTest', version +load 'multiruby_setup' diff --git a/bin/parse_tree_abc b/bin/parse_tree_abc new file mode 100755 index 0000000..0209fde --- /dev/null +++ b/bin/parse_tree_abc @@ -0,0 +1,31 @@ +#!/usr/bin/env ruby +# +# This file was generated by Merb's GemManagement +# +# The application 'ParseTree' is installed as part of a gem, and +# this file is here to facilitate running it. + +begin + require 'minigems' +rescue LoadError + require 'rubygems' +end + +# use gems dir if ../gems exists - eg. only for ./bin/parse_tree_abc +if File.directory?(gems_dir = File.join(File.dirname(__FILE__), '..', 'gems')) + $BUNDLE = true; Gem.clear_paths; Gem.path.replace([File.expand_path(gems_dir)]) + ENV["PATH"] = "#{File.dirname(__FILE__)}:#{gems_dir}/bin:#{ENV["PATH"]}" + if (local_gem = Dir[File.join(gems_dir, "specifications", "ParseTree-*.gemspec")].last) + version = File.basename(local_gem)[/-([\.\d]+)\.gemspec$/, 1] + end +end + +version ||= ">= 0" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'ParseTree', version +load 'parse_tree_abc' diff --git a/bin/parse_tree_audit b/bin/parse_tree_audit new file mode 100755 index 0000000..992f23e --- /dev/null +++ b/bin/parse_tree_audit @@ -0,0 +1,31 @@ +#!/usr/bin/env ruby +# +# This file was generated by Merb's GemManagement +# +# The application 'ParseTree' is installed as part of a gem, and +# this file is here to facilitate running it. + +begin + require 'minigems' +rescue LoadError + require 'rubygems' +end + +# use gems dir if ../gems exists - eg. only for ./bin/parse_tree_audit +if File.directory?(gems_dir = File.join(File.dirname(__FILE__), '..', 'gems')) + $BUNDLE = true; Gem.clear_paths; Gem.path.replace([File.expand_path(gems_dir)]) + ENV["PATH"] = "#{File.dirname(__FILE__)}:#{gems_dir}/bin:#{ENV["PATH"]}" + if (local_gem = Dir[File.join(gems_dir, "specifications", "ParseTree-*.gemspec")].last) + version = File.basename(local_gem)[/-([\.\d]+)\.gemspec$/, 1] + end +end + +version ||= ">= 0" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'ParseTree', version +load 'parse_tree_audit' diff --git a/bin/parse_tree_deps b/bin/parse_tree_deps new file mode 100755 index 0000000..27ad719 --- /dev/null +++ b/bin/parse_tree_deps @@ -0,0 +1,31 @@ +#!/usr/bin/env ruby +# +# This file was generated by Merb's GemManagement +# +# The application 'ParseTree' is installed as part of a gem, and +# this file is here to facilitate running it. + +begin + require 'minigems' +rescue LoadError + require 'rubygems' +end + +# use gems dir if ../gems exists - eg. only for ./bin/parse_tree_deps +if File.directory?(gems_dir = File.join(File.dirname(__FILE__), '..', 'gems')) + $BUNDLE = true; Gem.clear_paths; Gem.path.replace([File.expand_path(gems_dir)]) + ENV["PATH"] = "#{File.dirname(__FILE__)}:#{gems_dir}/bin:#{ENV["PATH"]}" + if (local_gem = Dir[File.join(gems_dir, "specifications", "ParseTree-*.gemspec")].last) + version = File.basename(local_gem)[/-([\.\d]+)\.gemspec$/, 1] + end +end + +version ||= ">= 0" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'ParseTree', version +load 'parse_tree_deps' diff --git a/bin/parse_tree_show b/bin/parse_tree_show new file mode 100755 index 0000000..c32d5e1 --- /dev/null +++ b/bin/parse_tree_show @@ -0,0 +1,31 @@ +#!/usr/bin/env ruby +# +# This file was generated by Merb's GemManagement +# +# The application 'ParseTree' is installed as part of a gem, and +# this file is here to facilitate running it. + +begin + require 'minigems' +rescue LoadError + require 'rubygems' +end + +# use gems dir if ../gems exists - eg. only for ./bin/parse_tree_show +if File.directory?(gems_dir = File.join(File.dirname(__FILE__), '..', 'gems')) + $BUNDLE = true; Gem.clear_paths; Gem.path.replace([File.expand_path(gems_dir)]) + ENV["PATH"] = "#{File.dirname(__FILE__)}:#{gems_dir}/bin:#{ENV["PATH"]}" + if (local_gem = Dir[File.join(gems_dir, "specifications", "ParseTree-*.gemspec")].last) + version = File.basename(local_gem)[/-([\.\d]+)\.gemspec$/, 1] + end +end + +version ||= ">= 0" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'ParseTree', version +load 'parse_tree_show' diff --git a/bin/r2r_show b/bin/r2r_show new file mode 100755 index 0000000..6564d85 --- /dev/null +++ b/bin/r2r_show @@ -0,0 +1,31 @@ +#!/usr/bin/env ruby +# +# This file was generated by Merb's GemManagement +# +# The application 'ruby2ruby' is installed as part of a gem, and +# this file is here to facilitate running it. + +begin + require 'minigems' +rescue LoadError + require 'rubygems' +end + +# use gems dir if ../gems exists - eg. only for ./bin/r2r_show +if File.directory?(gems_dir = File.join(File.dirname(__FILE__), '..', 'gems')) + $BUNDLE = true; Gem.clear_paths; Gem.path.replace([File.expand_path(gems_dir)]) + ENV["PATH"] = "#{File.dirname(__FILE__)}:#{gems_dir}/bin:#{ENV["PATH"]}" + if (local_gem = Dir[File.join(gems_dir, "specifications", "ruby2ruby-*.gemspec")].last) + version = File.basename(local_gem)[/-([\.\d]+)\.gemspec$/, 1] + end +end + +version ||= ">= 0" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'ruby2ruby', version +load 'r2r_show' diff --git a/bin/rackup b/bin/rackup new file mode 100755 index 0000000..77f7556 --- /dev/null +++ b/bin/rackup @@ -0,0 +1,31 @@ +#!/usr/bin/env ruby +# +# This file was generated by Merb's GemManagement +# +# The application 'rack' is installed as part of a gem, and +# this file is here to facilitate running it. + +begin + require 'minigems' +rescue LoadError + require 'rubygems' +end + +# use gems dir if ../gems exists - eg. only for ./bin/rackup +if File.directory?(gems_dir = File.join(File.dirname(__FILE__), '..', 'gems')) + $BUNDLE = true; Gem.clear_paths; Gem.path.replace([File.expand_path(gems_dir)]) + ENV["PATH"] = "#{File.dirname(__FILE__)}:#{gems_dir}/bin:#{ENV["PATH"]}" + if (local_gem = Dir[File.join(gems_dir, "specifications", "rack-*.gemspec")].last) + version = File.basename(local_gem)[/-([\.\d]+)\.gemspec$/, 1] + end +end + +version ||= ">= 0" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'rack', version +load 'rackup' diff --git a/bin/rails_test_audit b/bin/rails_test_audit new file mode 100755 index 0000000..b17bd05 --- /dev/null +++ b/bin/rails_test_audit @@ -0,0 +1,31 @@ +#!/usr/bin/env ruby +# +# This file was generated by Merb's GemManagement +# +# The application 'ZenTest' is installed as part of a gem, and +# this file is here to facilitate running it. + +begin + require 'minigems' +rescue LoadError + require 'rubygems' +end + +# use gems dir if ../gems exists - eg. only for ./bin/rails_test_audit +if File.directory?(gems_dir = File.join(File.dirname(__FILE__), '..', 'gems')) + $BUNDLE = true; Gem.clear_paths; Gem.path.replace([File.expand_path(gems_dir)]) + ENV["PATH"] = "#{File.dirname(__FILE__)}:#{gems_dir}/bin:#{ENV["PATH"]}" + if (local_gem = Dir[File.join(gems_dir, "specifications", "ZenTest-*.gemspec")].last) + version = File.basename(local_gem)[/-([\.\d]+)\.gemspec$/, 1] + end +end + +version ||= ">= 0" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'ZenTest', version +load 'rails_test_audit' diff --git a/bin/rake b/bin/rake new file mode 100755 index 0000000..8257d5c --- /dev/null +++ b/bin/rake @@ -0,0 +1,31 @@ +#!/usr/bin/env ruby +# +# This file was generated by Merb's GemManagement +# +# The application 'rake' is installed as part of a gem, and +# this file is here to facilitate running it. + +begin + require 'minigems' +rescue LoadError + require 'rubygems' +end + +# use gems dir if ../gems exists - eg. only for ./bin/rake +if File.directory?(gems_dir = File.join(File.dirname(__FILE__), '..', 'gems')) + $BUNDLE = true; Gem.clear_paths; Gem.path.replace([File.expand_path(gems_dir)]) + ENV["PATH"] = "#{File.dirname(__FILE__)}:#{gems_dir}/bin:#{ENV["PATH"]}" + if (local_gem = Dir[File.join(gems_dir, "specifications", "rake-*.gemspec")].last) + version = File.basename(local_gem)[/-([\.\d]+)\.gemspec$/, 1] + end +end + +version ||= ">= 0" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'rake', version +load 'rake' diff --git a/bin/rake2thor b/bin/rake2thor new file mode 100755 index 0000000..913f7c5 --- /dev/null +++ b/bin/rake2thor @@ -0,0 +1,31 @@ +#!/usr/bin/env ruby +# +# This file was generated by Merb's GemManagement +# +# The application 'thor' is installed as part of a gem, and +# this file is here to facilitate running it. + +begin + require 'minigems' +rescue LoadError + require 'rubygems' +end + +# use gems dir if ../gems exists - eg. only for ./bin/rake2thor +if File.directory?(gems_dir = File.join(File.dirname(__FILE__), '..', 'gems')) + $BUNDLE = true; Gem.clear_paths; Gem.path.replace([File.expand_path(gems_dir)]) + ENV["PATH"] = "#{File.dirname(__FILE__)}:#{gems_dir}/bin:#{ENV["PATH"]}" + if (local_gem = Dir[File.join(gems_dir, "specifications", "thor-*.gemspec")].last) + version = File.basename(local_gem)[/-([\.\d]+)\.gemspec$/, 1] + end +end + +version ||= ">= 0" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'thor', version +load 'rake2thor' diff --git a/bin/sass b/bin/sass new file mode 100755 index 0000000..c1e4dd8 --- /dev/null +++ b/bin/sass @@ -0,0 +1,31 @@ +#!/usr/bin/env ruby +# +# This file was generated by Merb's GemManagement +# +# The application 'haml' is installed as part of a gem, and +# this file is here to facilitate running it. + +begin + require 'minigems' +rescue LoadError + require 'rubygems' +end + +# use gems dir if ../gems exists - eg. only for ./bin/sass +if File.directory?(gems_dir = File.join(File.dirname(__FILE__), '..', 'gems')) + $BUNDLE = true; Gem.clear_paths; Gem.path.replace([File.expand_path(gems_dir)]) + ENV["PATH"] = "#{File.dirname(__FILE__)}:#{gems_dir}/bin:#{ENV["PATH"]}" + if (local_gem = Dir[File.join(gems_dir, "specifications", "haml-*.gemspec")].last) + version = File.basename(local_gem)[/-([\.\d]+)\.gemspec$/, 1] + end +end + +version ||= ">= 0" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'haml', version +load 'sass' diff --git a/bin/slice b/bin/slice new file mode 100755 index 0000000..13bdcc7 --- /dev/null +++ b/bin/slice @@ -0,0 +1,31 @@ +#!/usr/bin/env ruby +# +# This file was generated by Merb's GemManagement +# +# The application 'merb-slices' is installed as part of a gem, and +# this file is here to facilitate running it. + +begin + require 'minigems' +rescue LoadError + require 'rubygems' +end + +# use gems dir if ../gems exists - eg. only for ./bin/slice +if File.directory?(gems_dir = File.join(File.dirname(__FILE__), '..', 'gems')) + $BUNDLE = true; Gem.clear_paths; Gem.path.replace([File.expand_path(gems_dir)]) + ENV["PATH"] = "#{File.dirname(__FILE__)}:#{gems_dir}/bin:#{ENV["PATH"]}" + if (local_gem = Dir[File.join(gems_dir, "specifications", "merb-slices-*.gemspec")].last) + version = File.basename(local_gem)[/-([\.\d]+)\.gemspec$/, 1] + end +end + +version ||= ">= 0" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'merb-slices', version +load 'slice' diff --git a/bin/spec b/bin/spec new file mode 100755 index 0000000..7575d37 --- /dev/null +++ b/bin/spec @@ -0,0 +1,31 @@ +#!/usr/bin/env ruby +# +# This file was generated by Merb's GemManagement +# +# The application 'rspec' is installed as part of a gem, and +# this file is here to facilitate running it. + +begin + require 'minigems' +rescue LoadError + require 'rubygems' +end + +# use gems dir if ../gems exists - eg. only for ./bin/spec +if File.directory?(gems_dir = File.join(File.dirname(__FILE__), '..', 'gems')) + $BUNDLE = true; Gem.clear_paths; Gem.path.replace([File.expand_path(gems_dir)]) + ENV["PATH"] = "#{File.dirname(__FILE__)}:#{gems_dir}/bin:#{ENV["PATH"]}" + if (local_gem = Dir[File.join(gems_dir, "specifications", "rspec-*.gemspec")].last) + version = File.basename(local_gem)[/-([\.\d]+)\.gemspec$/, 1] + end +end + +version ||= ">= 0" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'rspec', version +load 'spec' diff --git a/bin/thor b/bin/thor new file mode 100755 index 0000000..946f5de --- /dev/null +++ b/bin/thor @@ -0,0 +1,31 @@ +#!/usr/bin/env ruby +# +# This file was generated by Merb's GemManagement +# +# The application 'thor' is installed as part of a gem, and +# this file is here to facilitate running it. + +begin + require 'minigems' +rescue LoadError + require 'rubygems' +end + +# use gems dir if ../gems exists - eg. only for ./bin/thor +if File.directory?(gems_dir = File.join(File.dirname(__FILE__), '..', 'gems')) + $BUNDLE = true; Gem.clear_paths; Gem.path.replace([File.expand_path(gems_dir)]) + ENV["PATH"] = "#{File.dirname(__FILE__)}:#{gems_dir}/bin:#{ENV["PATH"]}" + if (local_gem = Dir[File.join(gems_dir, "specifications", "thor-*.gemspec")].last) + version = File.basename(local_gem)[/-([\.\d]+)\.gemspec$/, 1] + end +end + +version ||= ">= 0" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'thor', version +load 'thor' diff --git a/bin/unit_diff b/bin/unit_diff new file mode 100755 index 0000000..dce224c --- /dev/null +++ b/bin/unit_diff @@ -0,0 +1,31 @@ +#!/usr/bin/env ruby +# +# This file was generated by Merb's GemManagement +# +# The application 'ZenTest' is installed as part of a gem, and +# this file is here to facilitate running it. + +begin + require 'minigems' +rescue LoadError + require 'rubygems' +end + +# use gems dir if ../gems exists - eg. only for ./bin/unit_diff +if File.directory?(gems_dir = File.join(File.dirname(__FILE__), '..', 'gems')) + $BUNDLE = true; Gem.clear_paths; Gem.path.replace([File.expand_path(gems_dir)]) + ENV["PATH"] = "#{File.dirname(__FILE__)}:#{gems_dir}/bin:#{ENV["PATH"]}" + if (local_gem = Dir[File.join(gems_dir, "specifications", "ZenTest-*.gemspec")].last) + version = File.basename(local_gem)[/-([\.\d]+)\.gemspec$/, 1] + end +end + +version ||= ">= 0" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'ZenTest', version +load 'unit_diff' diff --git a/bin/zentest b/bin/zentest new file mode 100755 index 0000000..bc36569 --- /dev/null +++ b/bin/zentest @@ -0,0 +1,31 @@ +#!/usr/bin/env ruby +# +# This file was generated by Merb's GemManagement +# +# The application 'ZenTest' is installed as part of a gem, and +# this file is here to facilitate running it. + +begin + require 'minigems' +rescue LoadError + require 'rubygems' +end + +# use gems dir if ../gems exists - eg. only for ./bin/zentest +if File.directory?(gems_dir = File.join(File.dirname(__FILE__), '..', 'gems')) + $BUNDLE = true; Gem.clear_paths; Gem.path.replace([File.expand_path(gems_dir)]) + ENV["PATH"] = "#{File.dirname(__FILE__)}:#{gems_dir}/bin:#{ENV["PATH"]}" + if (local_gem = Dir[File.join(gems_dir, "specifications", "ZenTest-*.gemspec")].last) + version = File.basename(local_gem)[/-([\.\d]+)\.gemspec$/, 1] + end +end + +version ||= ">= 0" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'ZenTest', version +load 'zentest' diff --git a/config/database.yml b/config/database.yml new file mode 100644 index 0000000..ba3a4f8 --- /dev/null +++ b/config/database.yml @@ -0,0 +1,33 @@ +--- +# This is a sample database file for the DataMapper ORM +development: &defaults + # These are the settings for repository :default + adapter: sqlite3 + database: sample_development.db + + # Add more repositories + # repositories: + # repo1: + # adapter: sqlite3 + # database: sample_1_development.db + # repo2: + # ... + +test: + <<: *defaults + database: sample_test.db + + # repositories: + # repo1: + # database: sample_1_test.db + +production: + <<: *defaults + database: production.db + + # repositories: + # repo1: + # database: sample_production.db + +rake: + <<: *defaults \ No newline at end of file diff --git a/config/dependencies.rb b/config/dependencies.rb new file mode 100644 index 0000000..28eff27 --- /dev/null +++ b/config/dependencies.rb @@ -0,0 +1,18 @@ +# dependencies are generated using a strict version, don't forget to edit the dependency versions when upgrading. +merb_gems_version = "1.0" +dm_gems_version = "0.9.6" + +# For more information about each component, please read http://wiki.merbivore.com/faqs/merb_components +dependency "merb-action-args", merb_gems_version +dependency "merb-assets", merb_gems_version +dependency "merb-cache", merb_gems_version +dependency "merb-helpers", merb_gems_version +dependency "merb-mailer", merb_gems_version +dependency "merb-slices", merb_gems_version +# dependency "merb-auth-core", merb_gems_version +# dependency "merb-auth-more", merb_gems_version +# dependency "merb-auth-slice-password", merb_gems_version +dependency "merb-param-protection", merb_gems_version +dependency "merb-exceptions", merb_gems_version + +dependency "nokogiri" \ No newline at end of file diff --git a/config/doc.xml b/config/doc.xml new file mode 100644 index 0000000..2a90857 --- /dev/null +++ b/config/doc.xml @@ -0,0 +1,33412 @@ + + + + + + + lib/merb-core/autoload.rb + Fri Nov 07 11:00:19 -0800 2008 + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/bootloader.rb + Sat Nov 15 10:27:50 -0800 2008 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/config.rb + Sat Nov 15 10:27:50 -0800 2008 + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/constants.rb + Sat Nov 15 10:27:50 -0800 2008 + + + + + + + + + + + + + lib/merb-core/controller/abstract_controller.rb + Sat Nov 15 10:27:50 -0800 2008 + + + + + + + + + + + + + lib/merb-core/controller/exceptions.rb + Sat Nov 15 10:27:50 -0800 2008 + + + + + + + + + + + + + lib/merb-core/controller/merb_controller.rb + Sat Nov 15 10:27:50 -0800 2008 + + + + + + + + + + + + + lib/merb-core/controller/mime.rb + Sat Nov 15 10:27:50 -0800 2008 + + + + + + + + + + + + + lib/merb-core/controller/mixins/authentication.rb + Sat Nov 08 08:14:52 -0800 2008 + + + + + + + + + + + + + lib/merb-core/controller/mixins/conditional_get.rb + Sat Nov 08 08:14:52 -0800 2008 + + + + + + + + + + + + + lib/merb-core/controller/mixins/controller.rb + Sat Nov 15 10:27:50 -0800 2008 + + + + + + + + + + + + + lib/merb-core/controller/mixins/render.rb + Sat Nov 15 10:27:50 -0800 2008 + + + + + + + + + + + + + lib/merb-core/controller/mixins/responder.rb + Sat Nov 15 10:27:50 -0800 2008 + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/template.rb + Sat Nov 15 10:27:50 -0800 2008 + + + + + + + + + + + + + lib/merb-core/core_ext/hash.rb + Sat Nov 08 08:14:52 -0800 2008 + + + + + + + + + + + + + lib/merb-core/core_ext/kernel.rb + Sat Nov 15 10:27:50 -0800 2008 + + + + + + + + + + + + + + + + + + + + + lib/merb-core/core_ext.rb + Fri Nov 07 11:00:19 -0800 2008 + + + + + + + + + + + + + + + + + + + lib/merb-core/dispatch/cookies.rb + Sat Nov 15 10:27:50 -0800 2008 + + + + + + + + + + + + + lib/merb-core/dispatch/default_exception/default_exception.rb + Sat Nov 08 08:14:52 -0800 2008 + + + + + + + + + + + + + lib/merb-core/dispatch/default_exception/views/_css.html.erb + Fri Nov 07 11:00:19 -0800 2008 + + + + + + + + + + + + + lib/merb-core/dispatch/default_exception/views/_javascript.html.erb + Fri Nov 07 11:00:19 -0800 2008 + + + + + + + + + + + + + lib/merb-core/dispatch/default_exception/views/index.html.erb + Fri Nov 07 11:00:19 -0800 2008 + + + + + + + + + + + + + lib/merb-core/dispatch/dispatcher.rb + Sat Nov 08 08:14:52 -0800 2008 + + + + + + + + + + + + + lib/merb-core/dispatch/request.rb + Sat Nov 15 10:27:50 -0800 2008 + + + + + + + + + + + + + + + + + + + lib/merb-core/dispatch/request_parsers.rb + Sat Nov 08 08:14:52 -0800 2008 + + + + + + + + + + + + + lib/merb-core/dispatch/router/behavior.rb + Sat Nov 15 10:27:50 -0800 2008 + + + + + + + + + + + + + lib/merb-core/dispatch/router/cached_proc.rb + Sat Nov 08 08:14:52 -0800 2008 + + + + + + + + + + + + + lib/merb-core/dispatch/router/resources.rb + Sat Nov 15 10:27:50 -0800 2008 + + + + + + + + + + + + + lib/merb-core/dispatch/router/route.rb + Sat Nov 15 10:27:50 -0800 2008 + + + + + + + + + + + + + lib/merb-core/dispatch/router.rb + Sat Nov 15 10:27:50 -0800 2008 + + + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/dispatch/session/container.rb + Sat Nov 15 10:27:50 -0800 2008 + + + + + + + + + + + + + lib/merb-core/dispatch/session/cookie.rb + Sat Nov 15 10:27:50 -0800 2008 + + + + + + + + + + + + + + + + + + + + + lib/merb-core/dispatch/session/memcached.rb + Sat Nov 15 10:27:50 -0800 2008 + + + + + + + + + + + + + lib/merb-core/dispatch/session/memory.rb + Sat Nov 08 08:14:52 -0800 2008 + + + + + + + + + + + + + lib/merb-core/dispatch/session/store_container.rb + Sat Nov 15 10:27:50 -0800 2008 + + + + + + + + + + + + + lib/merb-core/dispatch/session.rb + Sat Nov 15 10:27:50 -0800 2008 + + + + + + + + + + + + + + + + + + + + + lib/merb-core/dispatch/worker.rb + Sat Nov 08 08:14:52 -0800 2008 + + + + + + + + + + + + + lib/merb-core/gem_ext/erubis.rb + Sat Nov 15 10:27:50 -0800 2008 + + + + + + + + + + + + + + + + + + + lib/merb-core/logger.rb + Sat Nov 15 10:27:50 -0800 2008 + + + + + + + + + + + + + lib/merb-core/plugins.rb + Sat Nov 08 08:14:52 -0800 2008 + + + + + + + + + + + + + + + + + + + lib/merb-core/rack/adapter/abstract.rb + Sat Nov 15 10:27:50 -0800 2008 + + + + + + + + + + + + + lib/merb-core/rack/adapter/ebb.rb + Sat Nov 08 08:14:52 -0800 2008 + + + + + + + + + + + + + + + + + + + lib/merb-core/rack/adapter/evented_mongrel.rb + Sat Nov 08 08:14:52 -0800 2008 + + + + + + + + + + + + + + + + + + + + + lib/merb-core/rack/adapter/fcgi.rb + Sat Nov 08 08:14:52 -0800 2008 + + + + + + + + + + + + + lib/merb-core/rack/adapter/irb.rb + Sat Nov 15 10:27:50 -0800 2008 + + + + + + + + + + + + + + + + + + + + + lib/merb-core/rack/adapter/mongrel.rb + Sat Nov 08 08:14:52 -0800 2008 + + + + + + + + + + + + + + + + + + + + + lib/merb-core/rack/adapter/runner.rb + Sat Nov 08 08:14:52 -0800 2008 + + + + + + + + + + + + + lib/merb-core/rack/adapter/swiftiplied_mongrel.rb + Sat Nov 08 08:14:52 -0800 2008 + + + + + + + + + + + + + + + + + + + + + lib/merb-core/rack/adapter/thin.rb + Sat Nov 08 08:14:52 -0800 2008 + + + + + + + + + + + + + + + + + + + lib/merb-core/rack/adapter/thin_turbo.rb + Sat Nov 08 08:14:52 -0800 2008 + + + + + + + + + + + + + + + + + + + lib/merb-core/rack/adapter/webrick.rb + Sat Nov 08 08:14:52 -0800 2008 + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/rack/adapter.rb + Sat Nov 15 10:27:50 -0800 2008 + + + + + + + + + + + + + lib/merb-core/rack/application.rb + Sat Nov 15 10:27:50 -0800 2008 + + + + + + + + + + + + + lib/merb-core/rack/handler/mongrel.rb + Sat Nov 08 08:14:52 -0800 2008 + + + + + + + + + + + + + + + + + + + lib/merb-core/rack/helpers.rb + Sat Nov 08 08:14:52 -0800 2008 + + + + + + + + + + + + + lib/merb-core/rack/middleware/conditional_get.rb + Sat Nov 08 08:14:52 -0800 2008 + + + + + + + + + + + + + lib/merb-core/rack/middleware/content_length.rb + Sat Nov 08 08:14:52 -0800 2008 + + + + + + + + + + + + + lib/merb-core/rack/middleware/path_prefix.rb + Sat Nov 08 08:14:52 -0800 2008 + + + + + + + + + + + + + lib/merb-core/rack/middleware/profiler.rb + Sat Nov 08 08:14:52 -0800 2008 + + + + + + + + + + + + + lib/merb-core/rack/middleware/static.rb + Sat Nov 08 08:14:53 -0800 2008 + + + + + + + + + + + + + lib/merb-core/rack/middleware/tracer.rb + Sat Nov 08 08:14:53 -0800 2008 + + + + + + + + + + + + + lib/merb-core/rack/middleware.rb + Sat Nov 08 08:14:52 -0800 2008 + + + + + + + + + + + + + lib/merb-core/rack/stream_wrapper.rb + Sat Nov 08 08:14:53 -0800 2008 + + + + + + + + + + + + + lib/merb-core/rack.rb + Sat Nov 08 08:14:52 -0800 2008 + + + + + + + + + + + + + + + + + + + lib/merb-core/server.rb + Sat Nov 15 10:27:50 -0800 2008 + + + + + + + + + + + + + + + + + + + + + lib/merb-core/tasks/audit.rake + Fri Nov 07 11:00:19 -0800 2008 + + + + + + + + + + + + + lib/merb-core/tasks/gem_management.rb + Sat Nov 08 08:14:53 -0800 2008 + + + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/tasks/merb.rb + Sat Nov 08 08:14:53 -0800 2008 + + + + + + + + + + + + + + + + + + + lib/merb-core/tasks/merb_rake_helper.rb + Sat Nov 08 08:14:53 -0800 2008 + + + + + + + + + + + + + lib/merb-core/tasks/stats.rake + Fri Nov 07 11:00:19 -0800 2008 + + + + + + + + + + + + + lib/merb-core/test/helpers/controller_helper.rb + Fri Nov 07 11:00:19 -0800 2008 + + + + + + + + + + + + + lib/merb-core/test/helpers/cookie_jar.rb + Sat Nov 08 08:14:53 -0800 2008 + + + + + + + + + + + + + + + + + + + lib/merb-core/test/helpers/mock_request_helper.rb + Sat Nov 08 08:14:53 -0800 2008 + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/test/helpers/multipart_request_helper.rb + Sat Nov 15 10:27:50 -0800 2008 + + + + + + + + + + + + + lib/merb-core/test/helpers/request_helper.rb + Sat Nov 08 08:14:53 -0800 2008 + + + + + + + + + + + + + + + + + + + lib/merb-core/test/helpers/route_helper.rb + Sat Nov 08 08:14:53 -0800 2008 + + + + + + + + + + + + + lib/merb-core/test/helpers.rb + Sat Nov 08 08:14:53 -0800 2008 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/test/matchers/controller_matchers.rb + Sat Nov 15 10:27:50 -0800 2008 + + + + + + + + + + + + + lib/merb-core/test/matchers/request_matchers.rb + Sat Nov 08 08:14:53 -0800 2008 + + + + + + + + + + + + + lib/merb-core/test/matchers/route_matchers.rb + Fri Nov 07 11:00:19 -0800 2008 + + + + + + + + + + + + + lib/merb-core/test/matchers.rb + Sat Nov 08 08:14:53 -0800 2008 + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/test/run_spec.rb + Sat Nov 08 08:14:53 -0800 2008 + + + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/test/run_specs.rb + Fri Nov 07 11:00:20 -0800 2008 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/test/tasks/spectasks.rb + Sat Nov 15 10:27:50 -0800 2008 + + + + + + + + + + + + + lib/merb-core/test/test_ext/hpricot.rb + Sat Nov 08 08:14:53 -0800 2008 + + + + + + + + + + + + + lib/merb-core/test/test_ext/object.rb + Fri Nov 07 11:00:20 -0800 2008 + + + + + + + + + + + + + lib/merb-core/test/test_ext/rspec.rb + Sat Nov 08 14:28:20 -0800 2008 + + + + + + + + + + + + + + + + + + + lib/merb-core/test/test_ext/string.rb + Sat Nov 08 08:14:53 -0800 2008 + + + + + + + + + + + + + lib/merb-core/test.rb + Sat Nov 08 08:14:53 -0800 2008 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/version.rb + Sat Nov 08 08:14:53 -0800 2008 + + + + + + + + + + + + + + + + + + + lib/merb-core/core_ext/hash.rb + + + + + Object + + + + + + + + + + + + + + + + (*args) + + +Returns the value of self for each argument and deletes those entries. +

+

Parameters

+ + +
*args:the keys whose values should be extracted and deleted. + +
+

Returns

+ + +
Array[Object]:The values of the provided arguments in corresponding order. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/core_ext/hash.rb, line 11 + def extract!(*args) + args.map do |arg| + self.delete(arg) + end + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/dispatch/session/memcached.rb + + + + + Object + + + + +For the memcached gem. +

+ + ]]>
+ + + + + + + + + + + + + + + + + + + +
+ + + + + + + lib/merb-core/dispatch/session/memcached.rb + + + + + Object + + + + +For the memcache-client gem. +

+ + ]]>
+ + + + + + + + + + + + + + + + + + + +
+ + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Object + + + + + + + + + + + + + + + + () + + +Returns the action_name that will be invoked on your +Exceptions controller when an instance is raised during a request. +

+

Returns

+ + +
String:The name of the action in the Exceptions controller which will get invoked + +
+
+  when an instance of this Exception sub/class is raised by an action.
+
+

+:api: public @overridable +

+ ]]>
+ + + +# File lib/merb-core/controller/exceptions.rb, line 33 + def self.action_name + if self == Exception + return nil unless Object.const_defined?(:Exceptions) && + Exceptions.method_defined?(:exception) + end + name = self.to_s.split('::').last.snake_case + Object.const_defined?(:Exceptions) && + Exceptions.method_defined?(name) ? name : superclass.action_name + end + + +
+ + + () + + +The status that will be sent in the response when an instance is raised +during a request. Override this to send a different status. +

+

Returns

+ + +
Integer:The status code to send in the response. Defaults to 500. + +
+

+:api: public @overridable +

+ ]]>
+ + + +# File lib/merb-core/controller/exceptions.rb, line 51 + def self.status + 500 + end + + +
+ + +
+ + + + + + () + + +Returns the action_name that will be invoked on your +Exceptions controller when this exception is raised. Override this method +to force a different action to be invoked. +

+

Returns

+ + +
String:The name of the action in the Exceptions controller which will get invoked + +
+
+  when this exception is raised during a request.
+
+

+:api: public @overridable +

+ ]]>
+ + + +# File lib/merb-core/controller/exceptions.rb, line 11 + def action_name() self.class.action_name end + + +
+ + + (other) + + Returns + + +
Boolean:Whether or not this exception is the same as another. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/exceptions.rb, line 18 + def same?(other) + self.class == other.class && + self.message == other.message && + self.backtrace == other.backtrace + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/test/test_ext/object.rb + + + + + Object + + + + + + + + + + + + + + + + (attr) + + Parameters + + +
attr<~to_s>:The name of the instance variable to get. + +
+

Returns

+ + +
Object:The instance variable @attr for this object. + +
+

Examples

+
+  # In a spec
+  @my_obj.assigns(:my_value).should == @my_value
+
+ ]]>
+ + + +# File lib/merb-core/test/test_ext/object.rb, line 11 + def assigns(attr) + self.instance_variable_get("@#{attr}") + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/test/test_ext/string.rb + + + + + Object + + + + + + + + + + + + + + + + (value) + + + +# File lib/merb-core/test/test_ext/string.rb, line 2 + def contain?(value) + self.include?(value) + end + + + + + + (value) + + +Alias for contain? +

+ ]]>
+ + +
+ + + (regex) + + + +# File lib/merb-core/test/test_ext/string.rb, line 8 + def match?(regex) + self.match(regex) + end + + + + + + (regex) + + +Alias for match? +

+ ]]>
+ + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/tasks/gem_management.rb + + + + + + + + + + + + + + + + + + + (source_dir) + + + +# File lib/merb-core/tasks/gem_management.rb, line 199 + def clobber(source_dir) + Dir.chdir(source_dir) do + system "#{Gem.ruby} -S rake -s clobber" unless File.exists?('Thorfile') + end + end + + + + + + (gem_dir, bin_dir, *gems) + + +Create a modified executable wrapper in the specified bin directory. +

+ ]]>
+ + + +# File lib/merb-core/tasks/gem_management.rb, line 280 + def ensure_bin_wrapper_for(gem_dir, bin_dir, *gems) + options = gems.last.is_a?(Hash) ? gems.last : {} + options[:no_minigems] ||= [] + if bin_dir && File.directory?(bin_dir) + gems.each do |gem| + if gemspec_path = Dir[File.join(gem_dir, 'specifications', "#{gem}-*.gemspec")].last + spec = Gem::Specification.load(gemspec_path) + enable_minigems = !options[:no_minigems].include?(spec.name) + spec.executables.each do |exec| + executable = File.join(bin_dir, exec) + message "Writing executable wrapper #{executable}" + File.open(executable, 'w', 0755) do |f| + f.write(executable_wrapper(spec, exec, enable_minigems)) + end + end + end + end + end + end + + +
+ + + (gemspecs, options) + + + +# File lib/merb-core/tasks/gem_management.rb, line 300 + def ensure_bin_wrapper_for_installed_gems(gemspecs, options) + if options[:install_dir] && options[:bin_dir] + gems = gemspecs.map { |spec| spec.name } + ensure_bin_wrapper_for(options[:install_dir], options[:bin_dir], *gems) + end + end + + + + + + (gem, options = {}) + + +Install a gem - looks remotely and local gem cache; won’t process +rdoc or ri options. +

+ ]]>
+ + + +# File lib/merb-core/tasks/gem_management.rb, line 46 + def install_gem(gem, options = {}) + refresh = options.delete(:refresh) || [] + from_cache = (options.key?(:cache) && options.delete(:cache)) + if from_cache + install_gem_from_cache(gem, options) + else + version = options.delete(:version) + Gem.configuration.update_sources = false + + # Limit source index to install dir + update_source_index(options[:install_dir]) if options[:install_dir] + + installer = Gem::DependencyInstaller.new(options.merge(:user_install => false)) + + # Force-refresh certain gems by excluding them from the current index + if !options[:ignore_dependencies] && refresh.respond_to?(:include?) && !refresh.empty? + source_index = installer.instance_variable_get(:@source_index) + source_index.gems.each do |name, spec| + source_index.gems.delete(name) if refresh.include?(spec.name) + end + end + + exception = nil + begin + installer.install gem, version + rescue Gem::InstallError => e + exception = e + rescue Gem::GemNotFoundException => e + if from_cache && gem_file = find_gem_in_cache(gem, version) + puts "Located #{gem} in gem cache..." + installer.install gem_file + else + exception = e + end + rescue => e + exception = e + end + if installer.installed_gems.empty? && exception + error "Failed to install gem '#{gem} (#{version || 'any version'})' (#{exception.message})" + end + ensure_bin_wrapper_for_installed_gems(installer.installed_gems, options) + installer.installed_gems.each do |spec| + success "Successfully installed #{spec.full_name}" + end + return !installer.installed_gems.empty? + end + end + + +
+ + + (gem, options = {}) + + +Install a gem - looks in the system’s gem cache instead of remotely; +won’t process rdoc or ri options. +

+ ]]>
+ + + +# File lib/merb-core/tasks/gem_management.rb, line 96 + def install_gem_from_cache(gem, options = {}) + version = options.delete(:version) + Gem.configuration.update_sources = false + installer = Gem::DependencyInstaller.new(options.merge(:user_install => false)) + exception = nil + begin + if gem_file = find_gem_in_cache(gem, version) + puts "Located #{gem} in gem cache..." + installer.install gem_file + else + raise Gem::InstallError, "Unknown gem #{gem}" + end + rescue Gem::InstallError => e + exception = e + end + if installer.installed_gems.empty? && exception + error "Failed to install gem '#{gem}' (#{e.message})" + end + ensure_bin_wrapper_for_installed_gems(installer.installed_gems, options) + installer.installed_gems.each do |spec| + success "Successfully installed #{spec.full_name}" + end + end + + +
+ + + (source_dir, *args) + + +Install a gem from source - builds and packages it first then installs. +

+

+Examples: install_gem_from_source(source_dir, +:install_dir => …) install_gem_from_source(source_dir, gem_name) install_gem_from_source(source_dir, :skip => +[…]) +

+ ]]>
+ + + +# File lib/merb-core/tasks/gem_management.rb, line 126 + def install_gem_from_source(source_dir, *args) + installed_gems = [] + opts = args.last.is_a?(Hash) ? args.pop : {} + Dir.chdir(source_dir) do + gem_name = args[0] || File.basename(source_dir) + gem_pkg_dir = File.join(source_dir, 'pkg') + gem_pkg_glob = File.join(gem_pkg_dir, "#{gem_name}-*.gem") + skip_gems = opts.delete(:skip) || [] + + # Cleanup what's already there + clobber(source_dir) + FileUtils.mkdir_p(gem_pkg_dir) unless File.directory?(gem_pkg_dir) + + # Recursively process all gem packages within the source dir + skip_gems << gem_name + packages = package_all(source_dir, skip_gems) + + if packages.length == 1 + # The are no subpackages for the main package + refresh = [gem_name] + else + # Gather all packages into the top-level pkg directory + packages.each do |pkg| + FileUtils.copy_entry(pkg, File.join(gem_pkg_dir, File.basename(pkg))) + end + + # Finally package the main gem - without clobbering the already copied pkgs + package(source_dir, false) + + # Gather subgems to refresh during installation of the main gem + refresh = packages.map do |pkg| + File.basename(pkg, '.gem')[/^(.*?)-([\d\.]+)$/, 1] rescue nil + end.compact + + # Install subgems explicitly even if ignore_dependencies is set + if opts[:ignore_dependencies] + refresh.each do |name| + gem_pkg = Dir[File.join(gem_pkg_dir, "#{name}-*.gem")][0] + install_pkg(gem_pkg, opts) + end + end + end + + ensure_bin_wrapper_for(opts[:install_dir], opts[:bin_dir], *installed_gems) + + # Finally install the main gem + if install_pkg(Dir[gem_pkg_glob][0], opts.merge(:refresh => refresh)) + installed_gems = refresh + else + installed_gems = [] + end + end + installed_gems + end + + +
+ + + (gem_pkg, opts = {}) + + + +# File lib/merb-core/tasks/gem_management.rb, line 181 + def install_pkg(gem_pkg, opts = {}) + if (gem_pkg && File.exists?(gem_pkg)) + # Needs to be executed from the directory that contains all packages + Dir.chdir(File.dirname(gem_pkg)) { install_gem(gem_pkg, opts) } + else + false + end + end + + + + + + (source_dir, clobber = true) + + + +# File lib/merb-core/tasks/gem_management.rb, line 205 + def package(source_dir, clobber = true) + Dir.chdir(source_dir) do + if File.exists?('Thorfile') + thor ":package" + elsif File.exists?('Rakefile') + rake "clobber" if clobber + rake "package" + end + end + Dir[File.join(source_dir, 'pkg/*.gem')] + end + + + + + + (source_dir, skip = [], packages = []) + + + +# File lib/merb-core/tasks/gem_management.rb, line 217 + def package_all(source_dir, skip = [], packages = []) + if Dir[File.join(source_dir, '{Rakefile,Thorfile}')][0] + name = File.basename(source_dir) + Dir[File.join(source_dir, '*', '{Rakefile,Thorfile}')].each do |taskfile| + package_all(File.dirname(taskfile), skip, packages) + end + packages.push(*package(source_dir)) unless skip.include?(name) + end + packages.uniq + end + + + + + + (dependencies, gem_dir) + + +Partition gems into system, local and missing gems +

+ ]]>
+ + + +# File lib/merb-core/tasks/gem_management.rb, line 248 + def partition_dependencies(dependencies, gem_dir) + system_specs, local_specs, missing_deps = [], [], [] + if gem_dir && File.directory?(gem_dir) + gem_dir = File.expand_path(gem_dir) + ::Gem.clear_paths; ::Gem.path.unshift(gem_dir) + ::Gem.source_index.refresh! + dependencies.each do |dep| + gemspecs = ::Gem.source_index.search(dep) + local = gemspecs.reverse.find { |s| s.loaded_from.index(gem_dir) == 0 } + if local + local_specs << local + elsif gemspecs.last + system_specs << gemspecs.last + else + missing_deps << dep + end + end + ::Gem.clear_paths + else + dependencies.each do |dep| + gemspecs = ::Gem.source_index.search(dep) + if gemspecs.last + system_specs << gemspecs.last + else + missing_deps << dep + end + end + end + [system_specs, local_specs, missing_deps] + end + + +
+ + + (cmd) + + + +# File lib/merb-core/tasks/gem_management.rb, line 228 + def rake(cmd) + cmd << " >/dev/null" if $SILENT && !Gem.win_platform? + system "#{Gem.ruby} -S #{which('rake')} -s #{cmd} >/dev/null" + end + + + + + + (cmd) + + + +# File lib/merb-core/tasks/gem_management.rb, line 233 + def thor(cmd) + cmd << " >/dev/null" if $SILENT && !Gem.win_platform? + system "#{Gem.ruby} -S #{which('thor')} #{cmd}" + end + + + + + + (gem, options = {}) + + +Uninstall a gem. +

+ ]]>
+ + + +# File lib/merb-core/tasks/gem_management.rb, line 191 + def uninstall_gem(gem, options = {}) + if options[:version] && !options[:version].is_a?(Gem::Requirement) + options[:version] = Gem::Requirement.new ["= #{options[:version]}"] + end + update_source_index(options[:install_dir]) if options[:install_dir] + Gem::Uninstaller.new(gem, options).uninstall rescue nil + end + + +
+ + + (executable) + + +Use the local bin/* executables if available. +

+ ]]>
+ + + +# File lib/merb-core/tasks/gem_management.rb, line 239 + def which(executable) + if File.executable?(exec = File.join(Dir.pwd, 'bin', executable)) + exec + else + executable + end + end + + +
+ + +
+ + + + + + + + + + + +
+ +
+ + + + + + + lib/merb-core/core_ext/kernel.rb + + + + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/core_ext/kernel.rb + + + + + Object + + + + + + + + + + + + + + RW + + + + + + + RW + + + + + + + + + + + + + + + + + + + + lib/merb-core/test/run_spec.rb + + lib/merb-core/test/test_ext/rspec.rb + + + + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/test/test_ext/rspec.rb + + + + + + + + + + + + + + + + + + + (*names, &block) + + + +# File lib/merb-core/test/test_ext/rspec.rb, line 81 + def self.create(*names, &block) + @guid ||= 0 + Merb::Test::Matchers.module_eval do + klass = Class.new(MatcherDSL) do + def initialize(expected_value) + @expected_value = expected_value + end + end + klass.class_eval(&block) + + names.each do |name| + define_method(name) do |*expected_value| + # Avoid a warning for the form should foo. + klass.new(expected_value && expected_value[0]) + end + end + end + end + + + + + + (expected_value) + + + +# File lib/merb-core/test/test_ext/rspec.rb, line 85 + def initialize(expected_value) + @expected_value = expected_value + end + + + + + + + + + + + + () + + + +# File lib/merb-core/test/test_ext/rspec.rb, line 19 + def fail + raise_error(Spec::Expectations::ExpectationNotMetError) + end + + + + + + (message) + + + +# File lib/merb-core/test/test_ext/rspec.rb, line 23 + def fail_with(message) + raise_error(Spec::Expectations::ExpectationNotMetError, message) + end + + + + + + + + + + + + + + + + + + + + + lib/merb-core/test/test_ext/rspec.rb + + + + + Object + + + + + + + + + + + + + + + + (&block) + + + +# File lib/merb-core/test/test_ext/rspec.rb, line 116 + def self.expected_value(&block) + define_method(:transform_expected, &block) + + define_method(:initialize) do |expected_value| + @expected_value = transform_expected(expected_value) || expected_value + end + end + + + + + + (&block) + + + +# File lib/merb-core/test/test_ext/rspec.rb, line 132 + def self.failure_message(&block) + define_method(:proxy_failure_message, &block) + + define_method(:failure_message) do + proxy_failure_message(@object, @expected_value) + end + end + + + + + + (&block) + + + +# File lib/merb-core/test/test_ext/rspec.rb, line 103 + def self.matches(&block) + define_method(:matches_proxy, &block) + + define_method(:matches?) do |object| + @object = object + if block.arity == 2 + matches_proxy(@object, @expected_value) + else + matches_proxy(@object) + end + end + end + + + + + + (&block) + + + +# File lib/merb-core/test/test_ext/rspec.rb, line 140 + def self.message(&block) + class_eval do + def failure_message + generic_message(@object, @expected_value, nil) + end + + def negative_failure_message + generic_message(@object, @expected_value, " not") + end + end + + define_method(:proxy_generic_message, &block) + + ar = block.arity + + define_method(:generic_message) do |object, expected, not_string| + if ar == 3 + proxy_generic_message(not_string, object, expected) + else + proxy_generic_message(not_string, object) + end + end + end + + + + + + (&block) + + + +# File lib/merb-core/test/test_ext/rspec.rb, line 124 + def self.negative_failure_message(&block) + define_method(:proxy_negative_failure_message, &block) + + define_method(:negative_failure_message) do + proxy_negative_failure_message(@object, @expected_value) + end + end + + + + + + + + + + + + () + + + +# File lib/merb-core/test/test_ext/rspec.rb, line 142 + def failure_message + generic_message(@object, @expected_value, nil) + end + + + + + + () + + + +# File lib/merb-core/test/test_ext/rspec.rb, line 146 + def negative_failure_message + generic_message(@object, @expected_value, " not") + end + + + + + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/test/run_spec.rb + + + + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/test/run_spec.rb + + + + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/test/run_spec.rb + + + + + Object + + + + + + + + + + + + + + + + (counter, failure) + + + +# File lib/merb-core/test/run_spec.rb, line 10 + def dump_failure(counter, failure) + output = @options.error_stream + output.puts + output.puts "#{counter.to_s})" + output.puts colourise("#{failure.header}\n#{failure.exception.message}", failure) + output.puts format_backtrace(failure.exception.backtrace) + output.flush + end + + + + + + + + + + + + + + + + + + + + + lib/merb-core/core_ext/kernel.rb + + lib/merb-core/test/test_ext/rspec.rb + + + + + + + + + + + + + + + + + + + (i = 1) + + Parameters + + +
i<Fixnum>:The caller number. Defaults to 1. + +
+

Returns

+ + +
<Array[Array]>:The file, line and method of the caller. + +
+

Example

+

+caller_info(1) +

+
+  # => ['/usr/lib/ruby/1.8/irb/workspace.rb', '52', 'irb_binding']
+
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/core_ext/kernel.rb, line 338 + def __caller_info__(i = 1) + file, line, meth = caller[i].scan(/(.*?):(\d+):in `(.*?)'/).first + end + + +
+ + + (file, line, size = 4) {|:error, "Template Error! Problem while rendering", false| ...} + + Parameters + + + +
file<String>:The file to read. + +
line<Fixnum>:The line number to look for. + +
+

+size<Fixnum> +

+
+  Number of lines to include above and below the the line to look for.
+  Defaults to 4.
+
+

Returns

+

+<Array[Array]> +

+
+  Triplets containing the line number, the line and whether this was the
+  searched line.
+
+

+@example +

+
+  __caller_lines__('/usr/lib/ruby/1.8/debug.rb', 122, 2) # =>
+    [
+      [ 120, "  def check_suspend",                               false ],
+      [ 121, "    return if Thread.critical",                     false ],
+      [ 122, "    while (Thread.critical = true; @suspend_next)", true  ],
+      [ 123, "      DEBUGGER__.waiting.push Thread.current",      false ],
+      [ 124, "      @suspend_next = false",                       false ]
+    ]
+
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/core_ext/kernel.rb, line 365 + def __caller_lines__(file, line, size = 4) + line = line.to_i + if file =~ /\(erubis\)/ + yield :error, "Template Error! Problem while rendering", false + elsif !File.file?(file) || !File.readable?(file) + yield :error, "File `#{file}' not available", false + else + lines = File.read(file).split("\n") + first_line = (f = line - size - 1) < 0 ? 0 : f + + if first_line.zero? + new_size = line - 1 + lines = lines[first_line, size + new_size + 1] + else + new_size = nil + lines = lines[first_line, size * 2 + 1] + end + + lines && lines.each_with_index do |str, index| + line_n = index + line + line_n = (new_size.nil?) ? line_n - size : line_n - new_size + yield line_n, str.chomp + end + end + end + + +
+ + + (name, min=1, iter=100) {|| ...} + + +Takes a block, profiles the results of running the block specified number +of times and generates HTML report. +

+

Parameters

+

+name<to_s> +

+
+  The file name. The result will be written out to
+  Merb.root/"log/#{name}.html".
+
+

+min<Fixnum> +

+
+  Minimum percentage of the total time a method must take for it to be
+  included in the result. Defaults to 1.
+
+

Returns

+ + +
<String>:The result of the profiling. + +
+

Note

+

+Requires ruby-prof (sudo gem install ruby-prof) +

+

Example

+

+profile("MyProfile", 5, 30) do +

+
+  rand(10)**rand(10)
+  puts "Profile run"
+
+

+end +

+

+Assuming that the total time taken for puts calls was less than 5% of the +total time to run, puts won’t appear in the profile report. The code +block will be run 30 times in the example above. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/core_ext/kernel.rb, line 419 + def __profile__(name, min=1, iter=100) + require 'ruby-prof' unless defined?(RubyProf) + return_result = '' + result = RubyProf.profile do + iter.times{return_result = yield} + end + printer = RubyProf::GraphHtmlPrinter.new(result) + path = File.join(Merb.root, 'log', "#{name}.html") + File.open(path, 'w') do |file| + printer.print(file, {:min_percent => min, + :print_file => true}) + end + return_result + end + + +
+ + + () + + +Defines debugger method so that code even works if debugger was not +requested. Drops a note to the logs that Debugger was not available. +

+ ]]>
+ + + +# File lib/merb-core/core_ext/kernel.rb, line 477 + def debugger + Merb.logger.info! "\n***** Debugger requested, but was not " + + "available: Start server with --debugger " + + "to enable *****\n" + end + + +
+ + + (*args) + + +Loads both gem and library dependencies that are passed in as arguments. +Execution is deferred to the Merb::BootLoader::Dependencies.run during bootup. +

+

Parameters

+

+*args<String, Hash, Array> +The dependencies to load. +

+

Returns

+ + +
Array[(Gem::Dependency, Array[Gem::Dependency])]:Gem::Dependencies for the + +
+
+  dependencies specified in args.
+
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/core_ext/kernel.rb, line 176 + def dependencies(*args) + args.map do |arg| + case arg + when String then dependency(arg) + when Hash then arg.map { |r,v| dependency(r, v) } + when Array then arg.map { |r| dependency(r) } + end + end + end + + +
+ + + (name, *ver, &blk) + + +Loads the given string as a gem. Execution is deferred until after the +logger has been instantiated and the framework directory structure is +defined. +

+

+If that has already happened, the gem will be activated immediately, but it +will still be registered. +

+

Parameters

+

+name<String> The name of the gem to load. *ver<Gem::Requirement, +Gem::Version, Array, to_str> +

+
+  Version requirements to be passed to Gem::Dependency.new.
+  If the last argument is a Hash, extract the :immediate option,
+  forcing a dependency to load immediately.
+
+

Options

+

+:immediate when true, gem is loaded immediately even if framework is not +yet ready. :require_as file name to require for this gem. +

+

+See examples below. +

+

Notes

+

+If block is given, it is called after require is called. If you use a block +to require multiple files, require first using :require_as option and the +rest in the block. +

+

Examples

+

+Usage scenario is typically one of the following: +

+
    +
  1. Gem name and loaded file names are the same (ex.: amqp +gem uses amqp.rb). In this case no extra options needed. + +
  2. +
+

+dependency "amqp" +

+
    +
  1. Gem name is different from the file needs to be required +(ex.: ParseTree gem uses parse_tree.rb as main file). + +
  2. +
+

+dependency "ParseTree", :require_as => "parse_tree" +

+
    +
  1. You need to require a number of files from the library explicitly (ex.: +cherry pick features from xmpp4r). Pass a n array to :require_as. + +
  2. +
+

+dependency "xmpp4r", :require_as => %w(xmpp4r/client +xmpp4r/sasl xmpp4r/vcard) +

+
    +
  1. You need to require a specific version of the gem. + +
  2. +
+

+dependency "RedCloth", "3.0.4" +

+
    +
  1. You want to load dependency as soon as the method is called. + +
  2. +
+

+dependency "syslog", :immediate => true +

+
    +
  1. You need to execute some arbitraty code after dependency is loaded: + +
  2. +
+

+dependency "ruby-growl" do +

+
+  g = Growl.new "localhost", "ruby-growl",
+             ["ruby-growl Notification"]
+  g.notify "ruby-growl Notification", "Ruby-Growl is set up",
+        "Ruby-Growl is set up"
+
+

+end +

+

Returns

+ + +
Gem::Dependency:The dependency information. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/core_ext/kernel.rb, line 107 + def dependency(name, *ver, &blk) + immediate = ver.last.delete(:immediate) if ver.last.is_a?(Hash) + if immediate || Merb::BootLoader.finished?(Merb::BootLoader::Dependencies) + load_dependency(name, *ver, &blk) + else + track_dependency(name, *ver, &blk) + end + end + + +
+ + + (opts = {}) + + +Checks that the given objects quack like the given conditions. +

+

Parameters

+

+opts<Hash> +

+
+  Conditions to enforce. Each key will receive a quacks_like? call with the
+  value (see Object#quacks_like? for details).
+
+

Raises

+ + +
<ArgumentError>:An object failed to quack like a condition. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/core_ext/kernel.rb, line 467 + def enforce!(opts = {}) + opts.each do |k,v| + raise ArgumentError, "#{k.inspect} doesn't quack like #{v.inspect}" unless k.quacks_like?(v) + end + end + + +
+ + + (args) + + +Extracts an options hash if it is the last item in the args array. Used +internally in methods that take *args. +

+

Parameters

+ + +
args<Array>:The arguments to extract the hash from. + +
+

Example

+

+def render(*args,&blk) +

+
+  opts = extract_options_from_args!(args) || {}
+  # [...]
+
+

+end +

+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/core_ext/kernel.rb, line 447 + def extract_options_from_args!(args) + last_arg = args.last + if last_arg.instance_of?(Hash) || last_arg.instance_of?(Mash) + args.pop + else + nil + end + end + + +
+ + + (*args, &example_group_block) + + + +# File lib/merb-core/test/test_ext/rspec.rb, line 3 + def given(*args, &example_group_block) + args << {} unless Hash === args.last + params = args.last + + params[:shared] = true + + describe(*args) do + prepend_before(:each) do + self.instance_eval(&example_group_block) + end + end + end + + + + + + (*args) + + +Loads both gem and library dependencies that are passed in as arguments. +

+

Parameters

+ + +
*args<String, Hash, Array>:The dependencies to load. + +
+

Notes

+

+Each argument can be: +

+
+  String:: Single dependency.
+  Hash::
+    Multiple dependencies where the keys are names and the values versions.
+  Array:: Multiple string dependencies.
+
+

Examples

+

+dependencies "RedCloth" # Loads the the RedCloth gem dependencies +"RedCloth", "merb_helpers" # Loads RedCloth and +merb_helpers dependencies "RedCloth" => "3.0" # +Loads RedCloth 3.0 +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/core_ext/kernel.rb, line 204 + def load_dependencies(*args) + args.map do |arg| + case arg + when String then load_dependency(arg) + when Hash then arg.map { |r,v| load_dependency(r, v) } + when Array then arg.map { |r| load_dependency(r) } + end + end + end + + +
+ + + (name, *ver, &blk) + + +Loads the given string as a gem. +

+

+This new version tries to load the file via ROOT/gems first before moving +off to the system gems (so if you have a lower version of a gem in +ROOT/gems, it’ll still get loaded). +

+

Parameters

+

+name<String> The name or dependency object of the gem to load. +*ver<Gem::Requirement, Gem::Version, Array, to_str> +

+
+  Version requirements to be passed to Gem.activate.
+
+

Notes

+

+If the gem cannot be found, the method will attempt to require the string +as a library. If block given, it is called instead of doing a require, so +that you can pass some arbitraty code do load the gem. +

+

Returns

+ + +
Gem::Dependency:The dependency information. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/core_ext/kernel.rb, line 138 + def load_dependency(name, *ver, &blk) + dep = name.is_a?(Gem::Dependency) ? name : track_dependency(name, *ver, &blk) + Merb.logger.verbose!("activating gem '#{dep.name}' ...") + gem(dep) + rescue Gem::LoadError => e + msg = "Could not activate gem #{name} using gem '#{dep.name}': #{e.message}.\nIt usually means gem has unsatisfied dependencies. Run Merb with --verbose option if you are not sure what the problem is." + Merb.fatal! msg, e + ensure + begin + Merb.logger.verbose!("loading gem '#{dep.name}' ...") + [dep.require_as].flatten.each do |req| + Merb.logger.verbose!("running require '#{req}' ...") + require req + end + rescue LoadError => e + msg = "Could not load gem #{name} (tried to require #{dep.require_as.inspect}): #{e.message}.\nIt may happen because you mispelled file to require or gem has unsatisfied dependencies. Run Merb with --verbose option if you are not sure what the problem is." + Merb.fatal! msg, e + end + + if block = dep.require_block + Merb.logger.verbose!("calling a block after loading of '#{dep.name}' ...") + block.call + end + + return dep # ensure needs explicit return + end + + +
+ + + (library, message = nil) + + +Does a basic require, and prints a message if an error occurs. +

+

Parameters

+ + + +
library<to_s>:The library to attempt to include. + +
message<String>:The error to add to the log upon failure. Defaults to nil. + +
+

+:api: private @deprecated +

+ ]]>
+ + + +# File lib/merb-core/core_ext/kernel.rb, line 222 + def rescue_require(library, message = nil) + Merb.logger.warn("Deprecation warning: rescue_require is deprecated") + sleep 2.0 + require library + rescue LoadError, RuntimeError + Merb.logger.error!(message) if message + end + + +
+ + + (name, *ver, &blk) + + +Keeps track of all required dependencies. +

+

Parameters

+ + +
name<String>:The name of the gem to load. + +
+

+*ver<Gem::Requirement, Gem::Version, Array, to_str> +

+
+  Version requirements to be passed to Gem::Dependency.new.
+
+

Returns

+ + +
Gem::Dependency:The dependency information. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/core_ext/kernel.rb, line 23 + def track_dependency(name, *ver, &blk) + options = ver.pop if ver.last.is_a?(Hash) + new_dep = Gem::Dependency.new(name, ver.empty? ? nil : ver) + new_dep.require_block = blk + new_dep.require_as = (options && options[:require_as]) || name + + deps = Merb::BootLoader::Dependencies.dependencies + + idx = deps.each_with_index {|d,i| break i if d.name == new_dep.name} + + idx = idx.is_a?(Array) ? deps.size + 1 : idx + deps.delete_at(idx) + deps.insert(idx - 1, new_dep) + + new_dep + end + + +
+ + + (orm, &blk) + + +Used in Merb.root/config/init.rb to tell Merb which ORM +(Object Relational Mapper) you wish to use. Currently +Merb has plugins to support ActiveRecord, DataMapper, +and Sequel. +

+

Parameters

+ + +
orm<Symbol>:The ORM to use. + +
+

Returns

+

+nil +

+

Example

+
+  use_orm :datamapper
+
+  # This will use the DataMapper generator for your ORM
+  $ merb-gen model ActivityEvent
+
+

Notes

+
+  If for some reason this is called more than once, latter
+  call takes over other.
+
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/core_ext/kernel.rb, line 251 + def use_orm(orm, &blk) + begin + Merb.orm = orm + orm_plugin = "merb_#{orm}" + Kernel.dependency(orm_plugin, &blk) + rescue LoadError => e + Merb.logger.warn!("The #{orm_plugin} gem was not found. You may need to install it.") + raise e + end + nil + end + + +
+ + + (template_engine, &blk) + + +Used in Merb.root/config/init.rb to tell Merb which +template engine to prefer. +

+

Parameters

+

+template_engine<Symbol> +

+
+  The template engine to use.
+
+

Returns

+

+nil +

+

Example

+
+  use_template_engine :haml
+
+  # This will now use haml templates in generators where available.
+  $ merb-gen resource_controller Project
+
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/core_ext/kernel.rb, line 308 + def use_template_engine(template_engine, &blk) + Merb.template_engine = template_engine + + if template_engine != :erb + if template_engine.in?(:haml, :builder) + template_engine_plugin = "merb-#{template_engine}" + else + template_engine_plugin = "merb_#{template_engine}" + end + Kernel.dependency(template_engine_plugin, &blk) + end + + nil + rescue LoadError => e + Merb.logger.warn!("The #{template_engine_plugin} gem was not found. You may need to install it.") + raise e + end + + +
+ + + (*args) + + + +# File lib/merb-core/core_ext/kernel.rb, line 287 + def use_test(*args) + use_testing_framework(*args) + end + + + + + + (test_framework, *test_dependencies) + + +Used in Merb.root/config/init.rb to tell Merb which +testing framework to use. Currently Merb has plugins to +support RSpec and Test::Unit. +

+

Parameters

+ + +
test_framework<Symbol>:The test framework to use. Currently only supports :rspec and :test_unit. + +
+

Returns

+

+nil +

+

Example

+
+  use_test :rspec
+
+  # This will now use the RSpec generator for tests
+  $ merb-gen model ActivityEvent
+
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/core_ext/kernel.rb, line 280 + def use_testing_framework(test_framework, *test_dependencies) + Merb.test_framework = test_framework + + Kernel.dependencies test_dependencies if Merb.env == "test" || Merb.env.nil? + nil + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/rack/handler/mongrel.rb + + + + + Object + + + + + + + + + + + + + "HTTP/1.1 %d %s\r\n".freeze + + + + + + + + + + + + + + (content_length=@body.length) + + +Sends the status to the client without closing the connection. +

+

Parameters

+ + +
content_length<Fixnum>:The length of the content. Defaults to body length. + +
+ ]]>
+ + + +# File lib/merb-core/rack/handler/mongrel.rb, line 9 + def send_status_no_connection_close(content_length=@body.length) + unless @status_sent + write(NO_CLOSE_STATUS_FORMAT % [@status, Mongrel::HTTP_STATUS_CODES[@status]]) + @status_sent = true + end + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/controller/template.rb + + lib/merb-core/gem_ext/erubis.rb + + + + + + + + + + + + + + + + + + + (file, binding = binding) + + +Loads a file, runs it through Erubis and parses it as +YAML. +

+

Parameters

+ + + +
file<String>:The name of the file to load. + +
binding<Binding>:The binding to use when evaluating the ERB tags. Defaults to the current +binding. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/gem_ext/erubis.rb, line 80 + def self.load_yaml_file(file, binding = binding) + YAML::load(Erubis::MEruby.new(IO.read(File.expand_path(file))).result(binding)) + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/gem_ext/erubis.rb + + + + + + + +This adds support for embedding the return value of a block call: +

+
+  <%= foo do %>...<% end =%>
+
+

+:api: private +

+ + ]]>
+ + + + + + + + + + + + + + (src, input) + + + +# File lib/merb-core/gem_ext/erubis.rb, line 8 + def convert_input(src, input) + pat = @pattern + regexp = pat.nil? || pat == '<% %>' ? DEFAULT_REGEXP : pattern_regexp(pat) + pos = 0 + is_bol = true # is beginning of line + input.scan(regexp) do |indicator, code, tailch, rspace| + match = Regexp.last_match() + len = match.begin(0) - pos + text = input[pos, len] + pos = match.end(0) + ch = indicator ? indicator[0] : nil + lspace = ch == ?= ? nil : detect_spaces_at_bol(text, is_bol) + is_bol = rspace ? true : false + add_text(src, text) if text && !text.empty? + ## * when '<%= %>', do nothing + ## * when '<% %>' or '<%# %>', delete spaces iff only spaces are around '<% %>' + if ch == ?= # <%= %> + rspace = nil if tailch && !tailch.empty? + add_text(src, lspace) if lspace + add_expr(src, code, indicator) + add_text(src, rspace) if rspace + elsif ch == ?\# # <%# %> + n = code.count("\n") + (rspace ? 1 : 0) + if @trim && lspace && rspace + add_stmt(src, "\n" * n) + else + add_text(src, lspace) if lspace + add_stmt(src, "\n" * n) + add_text(src, rspace) if rspace + end + elsif ch == ?% # <%% %> + s = "#{lspace}#{@prefix||='<%'}#{code}#{tailch}#{@postfix||='%>'}#{rspace}" + add_text(src, s) + else # <% %> + if @trim && lspace && rspace + if respond_to?(:add_stmt2) + add_stmt2(src, "#{lspace}#{code}#{rspace}", tailch) + else + add_stmt(src, "#{lspace}#{code}#{rspace}") + end + else + add_text(src, lspace) if lspace + if respond_to?(:add_stmt2) + add_stmt2(src, code, tailch) + else + add_stmt(src, code) + end + add_text(src, rspace) if rspace + end + end + end + #rest = $' || input # ruby1.8 + rest = pos == 0 ? input : input[pos..-1] # ruby1.9 + add_text(src, rest) + end + + + + + + + + + + + + + +
+ + + + + + + lib/merb-core/controller/template.rb + + + + + + + + + + + + + + + + + + + (src, code) + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/controller/template.rb, line 264 + def add_expr_escaped(src, code) + src << ' @_erb_buf.concat(' << escaped_expr(code) << ');' + end + + +
+ + + (src, code) + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/controller/template.rb, line 276 + def add_expr_literal(src, code) + if code =~ /(do|\{)(\s*\|[^|]*\|)?\s*\Z/ + src << ' @_erb_buf.concat( ' << code << "; " + else + src << ' @_erb_buf.concat((' << code << ').to_s);' + end + end + + +
+ + + (src) + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/controller/template.rb, line 253 + def add_postamble(src) + src << "\n" unless src[-1] == ?\n + src << "_ret = @_erb_buf; @_erb_buf = _old_buf; _ret.to_s;\n" + end + + +
+ + + (src) + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/controller/template.rb, line 247 + def add_preamble(src) + src << "_old_buf, @_erb_buf = @_erb_buf, ''; " + src << "@_engine = 'erb'; " + end + + +
+ + + (src, code, tailch) + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/controller/template.rb, line 269 + def add_stmt2(src, code, tailch) + src << code + src << " ).to_s; " if tailch == "=" + src << ';' unless code[-1] == ?\n + end + + +
+ + + (src, text) + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/controller/template.rb, line 259 + def add_text(src, text) + src << " @_erb_buf.concat('" << escape_text(text) << "'); " + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/gem_ext/erubis.rb + + + + + Erubis::Eruby + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/template.rb + + + + + Eruby + + + + + + + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/autoload.rb + + lib/merb-core/bootloader.rb + + lib/merb-core/config.rb + + lib/merb-core/constants.rb + + lib/merb-core/controller/exceptions.rb + + lib/merb-core/controller/mime.rb + + lib/merb-core/controller/mixins/controller.rb + + lib/merb-core/controller/mixins/responder.rb + + lib/merb-core/dispatch/cookies.rb + + lib/merb-core/dispatch/default_exception/default_exception.rb + + lib/merb-core/dispatch/dispatcher.rb + + lib/merb-core/dispatch/request.rb + + lib/merb-core/dispatch/request_parsers.rb + + lib/merb-core/dispatch/router/behavior.rb + + lib/merb-core/dispatch/router/cached_proc.rb + + lib/merb-core/dispatch/router/resources.rb + + lib/merb-core/dispatch/router/route.rb + + lib/merb-core/dispatch/router.rb + + lib/merb-core/dispatch/session/container.rb + + lib/merb-core/dispatch/session/cookie.rb + + lib/merb-core/dispatch/session/memcached.rb + + lib/merb-core/dispatch/session/memory.rb + + lib/merb-core/dispatch/session/store_container.rb + + lib/merb-core/dispatch/session.rb + + lib/merb-core/dispatch/worker.rb + + lib/merb-core/logger.rb + + lib/merb-core/plugins.rb + + lib/merb-core/rack/adapter/abstract.rb + + lib/merb-core/rack/adapter/ebb.rb + + lib/merb-core/rack/adapter/evented_mongrel.rb + + lib/merb-core/rack/adapter/fcgi.rb + + lib/merb-core/rack/adapter/irb.rb + + lib/merb-core/rack/adapter/mongrel.rb + + lib/merb-core/rack/adapter/runner.rb + + lib/merb-core/rack/adapter/swiftiplied_mongrel.rb + + lib/merb-core/rack/adapter/thin.rb + + lib/merb-core/rack/adapter/thin_turbo.rb + + lib/merb-core/rack/adapter/webrick.rb + + lib/merb-core/rack/adapter.rb + + lib/merb-core/rack/application.rb + + lib/merb-core/rack/handler/mongrel.rb + + lib/merb-core/rack/helpers.rb + + lib/merb-core/rack/middleware/conditional_get.rb + + lib/merb-core/rack/middleware/content_length.rb + + lib/merb-core/rack/middleware/path_prefix.rb + + lib/merb-core/rack/middleware/profiler.rb + + lib/merb-core/rack/middleware/static.rb + + lib/merb-core/rack/middleware/tracer.rb + + lib/merb-core/rack/middleware.rb + + lib/merb-core/rack/stream_wrapper.rb + + lib/merb-core/rack.rb + + lib/merb-core/server.rb + + lib/merb-core/tasks/merb_rake_helper.rb + + lib/merb-core/test/helpers/controller_helper.rb + + lib/merb-core/test/helpers/cookie_jar.rb + + lib/merb-core/test/helpers/mock_request_helper.rb + + lib/merb-core/test/helpers/request_helper.rb + + lib/merb-core/test/helpers/route_helper.rb + + lib/merb-core/test/run_specs.rb + + lib/merb-core/test/test_ext/rspec.rb + + lib/merb-core/test.rb + + lib/merb-core/version.rb + + + + + + + +Most of this list is simply constants frozen for efficiency and lowered +memory consumption. Every time Ruby VM comes across a string or a number or +a regexp literal, new object is created. +

+

+This means if you refer to the same string 6 times per request and your +application takes 100 requests per second, there are 600 objects for weak +MRI garbage collector to work on. +

+

+GC cycles take up to 80% (!) time of request processing in some cases. +Eventually Rubinius and maybe MRI 2.0 gonna improve this situation but at +the moment, all commonly used strings, regexp and numbers used as constants +so no extra objects created and VM just operates pointers. +

+

+require "time" # httpdate +

+

Public Merb Logger API

+

+To replace an existing logger with a new one: +

+
+ Merb::Logger.set_log(log{String, IO},level{Symbol, String})
+
+

+Available logging levels are +

+
+  Merb::Logger::{ Fatal, Error, Warn, Info, Debug }
+
+

+Logging via: +

+
+  Merb.logger.fatal(message<String>,&block)
+  Merb.logger.error(message<String>,&block)
+  Merb.logger.warn(message<String>,&block)
+  Merb.logger.info(message<String>,&block)
+  Merb.logger.debug(message<String>,&block)
+
+

+Logging with autoflush: +

+
+  Merb.logger.fatal!(message<String>,&block)
+  Merb.logger.error!(message<String>,&block)
+  Merb.logger.warn!(message<String>,&block)
+  Merb.logger.info!(message<String>,&block)
+  Merb.logger.debug!(message<String>,&block)
+
+

+Flush the buffer to +

+
+  Merb.logger.flush
+
+

+Remove the current log object +

+
+  Merb.logger.close
+
+

Private Merb Logger API

+

+To initialize the logger you create a new object, proxies to set_log. +

+
+  Merb::Logger.new(log{String, IO},level{Symbol, String})
+
+ + ]]>
+ + + + + + + + + + + '1.0' unless defined?(Merb::VERSION) + + + + + + + + + + + + + + (key, transform_method, mimes, new_response_headers = {}, default_quality = 1, &block) + + +Any specific outgoing headers should be included here. These are not the +content-type header but anything in addition to it. +transform_method should be set to a symbol of the method used to +transform a resource into this mime type. For example for the :xml mime +type an object might be transformed by calling :to_xml, or for the :js mime +type, :to_json. If there is no transform method, use nil. +

+

Autogenerated Methods

+

+Adding a mime-type adds a render_type method that sets the content type and +calls render. +

+

+By default this does: def render_all, def render_yaml, def render_text, def +render_html, def render_xml, def render_js, and def render_yaml +

+

Parameters

+ + + + + + +
key<Symbol>:The name of the mime-type. This is used by the provides API + +
transform_method<~to_s>:The associated method to call on objects to convert them to the appropriate +mime-type. For instance, :json would use :to_json as its transform_method. + +
mimes<Array[String]>:A list of possible values sent in the Accept header, such as text/html, +that should be associated with this content-type. + +
new_response_headers<Hash>:The response headers to set for the mime type. For example: +‘Content-Type’ => ‘application/json; +charset=utf-8’; As a shortcut for the common charset option, use +:charset => ‘utf-8’, which will be correctly appended to the +mimetype itself. + +
&block:a block which receives the current controller when the format + +
+
+  is set (in the controller's #content_type method)
+
+

Returns

+

+nil +

+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mime.rb, line 70 + def add_mime_type(key, transform_method, mimes, new_response_headers = {}, default_quality = 1, &block) + enforce!(key => Symbol, mimes => Array) + + content_type = new_response_headers["Content-Type"] || mimes.first + + if charset = new_response_headers.delete(:charset) + content_type += "; charset=#{charset}" + end + + ResponderMixin::TYPES.update(key => + {:accepts => mimes, + :transform_method => transform_method, + :content_type => content_type, + :response_headers => new_response_headers, + :default_quality => default_quality, + :response_block => block }) + + mimes.each do |mime| + ResponderMixin::MIMES.update(mime => key) + end + + Merb::RenderMixin.class_eval "def render_\#{key}(thing = nil, opts = {})\nself.content_type = :\#{key}\nrender thing, opts\nend\n", __FILE__, __LINE__ + + nil + end + + +
+ + + () + + Returns + + +
Hash{String => Symbol}:A hash mapping Content-Type values to the mime type key of the appropriate +entry in available_mime_types + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mime.rb, line 30 + def available_accepts + ResponderMixin::MIMES + end + + +
+ + + () + + +Returns a hash of the available mime types. +

+

Returns

+ + +
Hash{Symbol => Hash{Symbol => Object}}:The available mime types. + +
+

Notes

+

+Each entry corresponds to a call to add_mime_type, +having the mime type key (:html, :xml, :json, etc.) as the key and a hash +containing the following entries: +

+
+  :accepts           # the mime types that will be recognized by this entry
+  :transform_method  # the method called on an object to convert it to content of this type (such as to_json)
+  :content_type      # the value set to the "Content-Type" HTTP header when this mime is sent in a response
+  :response_headers  # sent in a response using this content type
+  :default_quality   # the scale factor used in describing content type preference
+  :response_block    # the block to be called with the controller when a request responds to this mime type
+
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mime.rb, line 21 + def available_mime_types + ResponderMixin::TYPES + end + + +
+ + + (e) + + +Required to show exceptions in the log file +

+

Parameters

+ + +
e<Exception>:The exception that a message is being generated for + +
+

+:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/controller/exceptions.rb, line 346 + def self.exception(e) + "#{ e.message } - (#{ e.class })\n" << + "#{(e.backtrace or []).join("\n")}" + end + + +
+ + + (key) + + Parameters + + +
key<Symbol>:The key that represents the mime-type. + +
+

Returns

+ + +
Symbol:The transform method for the mime type, e.g. :to_json. + +
+

Raises

+ + +
ArgumentError:The requested mime type is not valid. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/controller/mime.rb, line 130 + def mime_transform_method(key) + raise ArgumentError, ":#{key} is not a valid MIME-type" unless ResponderMixin::TYPES.key?(key) + ResponderMixin::TYPES[key][:transform_method] + end + + +
+ + + (key) + + +Removes a MIME-type from the mime-type list. +

+

Parameters

+ + +
key<Symbol>:The key that represents the mime-type to remove. + +
+

Returns

+ + +
(Boolean, Hash{Symbol => Object}):If it was present, the old specification of the MIME-type. Same structure + +
+
+  as a value in Merb.available_mime_types. False if the key was not present.
+
+

Notes

+

+:all is the key for /; It can’t be removed. +

+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mime.rb, line 115 + def remove_mime_type(key) + return false if key == :all + ResponderMixin::TYPES.delete(key) + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/plugins.rb + + + + + + + + + + + + + + + + + + + (*generators) + + Parameters + + +
*generators:Generator paths to add to the list of plugin generators. + +
+

Notes

+

+This is the recommended way to register your plugin’s generators in +Merb. +

+

+:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/plugins.rb, line 76 + def self.add_generators(*generators) + Merb.add_generators(*generators) + end + + +
+ + + (*rakefiles) + + Parameters + + +
*rakefiles:Rakefiles to add to the list of plugin Rakefiles. + +
+

Notes

+

+This is a recommended way to register your plugin’s Raketasks in Merb. +

+

Examples

+

+From merb_sequel plugin: +

+

+if defined(Merb::Plugins) +

+
+  Merb::Plugins.add_rakefiles "merb_sequel" / "merbtasks"
+
+

+end +

+

+:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/plugins.rb, line 63 + def self.add_rakefiles(*rakefiles) + Merb.add_rakefiles(*rakefiles) + end + + +
+ + + () + + +Returns the configuration settings hash for plugins. This is prepopulated +from Merb.root / "config/plugins.yml" if it is present. +

+

Returns

+ + +
Hash:The configuration loaded from Merb.root / "config/plugins.yml" +or, if the load fails, an empty hash whose default value is another Hash. + +
+

+:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/plugins.rb, line 14 + def self.config + @config ||= begin + # this is so you can do Merb.plugins.config[:helpers][:awesome] = "bar" + config_hash = Hash.new {|h,k| h[k] = {}} + file = Merb.root / "config" / "plugins.yml" + + if File.exists?(file) + require 'yaml' + to_merge = YAML.load_file(file) + else + to_merge = {} + end + + config_hash.merge(to_merge) + end + end + + +
+ + + () + + Returns + + +
Array(String):All Generator load paths Merb uses for plugins. + +
+

+:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/plugins.rb, line 43 + def self.generators + Merb.generators + end + + +
+ + + () + + Returns + + +
Array(String):All Rakefile load paths Merb uses for plugins. + +
+

+:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/plugins.rb, line 35 + def self.rakefiles + Merb.rakefiles + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/dispatch/session.rb + + + + + + + +This is mixed into Merb::Controller on +framework boot. +

+ + ]]>
+ + + + + + + + + + + + + + (base) + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/session.rb, line 53 + def self.included(base) + # Register a callback to finalize sessions - needs to run before the cookie + # callback extracts Set-Cookie headers from request.cookies. + base._after_dispatch_callbacks.unshift lambda { |c| c.request.finalize_session } + end + + +
+ + + () + + +Marks this session as needing a new cookie. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/session.rb, line 92 + def needs_new_cookie! + @_new_cookie = true + end + + +
+ + + () + + +Does session need new cookie? +

+

Returns

+ + +
Boolean:true if a new cookie is needed, false otherwise. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/session.rb, line 102 + def needs_new_cookie? + @_new_cookie + end + + +
+ + + () + + Returns + + +
String:A random 32 character string for use as a unique session ID. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/session.rb, line 76 + def rand_uuid + values = [ + rand(0x0010000), + rand(0x0010000), + rand(0x0010000), + rand(0x0010000), + rand(0x0010000), + rand(0x1000000), + rand(0x1000000), + ] + "%04x%04x%04x%04x%04x%06x%06x" % values + end + + +
+ + +
+ + + + + + (session_store = nil) + + Parameters + + +
session_store<String>:The type of session store to access. + +
+

Returns

+ + +
SessionContainer:The session that was extracted from the request object. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/session.rb, line 66 + def session(session_store = nil) + request.session(session_store) + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/dispatch/session.rb + + + + + + + + + + + + + + + + + + + (base) + + +Adds class methods to Merb::Request object. +Sets up repository of session store types. Sets the session ID key and +expiry values. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/session.rb, line 115 + def self.included(base) + base.extend ClassMethods + + # Keep track of all known session store types. + base.cattr_accessor :registered_session_types + base.registered_session_types = Dictionary.new + base.class_inheritable_accessor :_session_id_key, :_session_secret_key, + :_session_expiry + + base._session_id_key = Merb::Config[:session_id_key] || '_session_id' + base._session_expiry = Merb::Config[:session_expiry] || 0 + base._session_secret_key = Merb::Config[:session_secret_key] + end + + +
+ + +
+ + + + + + () + + +Assigns default cookie values +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/session.rb, line 231 + def default_cookies + defaults = {} + if route && route.allow_fixation? && params.key?(_session_id_key) + Merb.logger.info("Fixated session id: #{_session_id_key}") + defaults[_session_id_key] = params[_session_id_key] + end + defaults + end + + +
+ + + () + + +The default session store type. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/session.rb, line 148 + def default_session_store + Merb::Config[:session_store] && Merb::Config[:session_store].to_sym + end + + +
+ + + () + + +Destroy the session cookie. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/session.rb, line 266 + def destroy_session_cookie + cookies.delete(_session_id_key) + end + + +
+ + + () + + +Teardown and/or persist the current sessions. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/session.rb, line 223 + def finalize_session + session_stores.each { |name, store| store.finalize(self) } + end + + +
+ + + () + + +Alias for finalize_session +

+ ]]>
+ + +
+ + + (session_store = nil) + + +Returns session container. Merb is able to handle +multiple session stores, hence a parameter to pick it. +

+

Parameters

+ + +
session_store<String>:The type of session store to access, + +
+

+defaults to default_session_store. +

+

Notes

+

+If no suitable session store type is given, it defaults to cookie-based +sessions. +

+

Returns

+ + +
SessionContainer:an instance of a session store extending Merb::SessionContainer. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/session.rb, line 176 + def session(session_store = nil) + session_store ||= default_session_store + if class_name = self.class.registered_session_types[session_store] + session_stores[session_store] ||= Object.full_const_get(class_name).setup(self) + elsif fallback = self.class.registered_session_types.keys.first + Merb.logger.warn "Session store '#{session_store}' not found. Check your configuration in init file." + Merb.logger.warn "Falling back to #{fallback} session store." + session(fallback) + else + msg = "No session store set. Set it in init file like this: c[:session_store] = 'activerecord'" + Merb.logger.error!(msg) + raise NoSessionContainer, msg + end + end + + +
+ + + (new_session) + + Parameters + + +
new_session<Merb::SessionContainer>:A session store instance. + +
+

Notes

+

+The session is assigned internally by its session_store_type key. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/session.rb, line 198 + def session=(new_session) + if self.session?(new_session.class.session_store_type) + original_session_id = self.session(new_session.class.session_store_type).session_id + if new_session.session_id != original_session_id + set_session_id_cookie(new_session.session_id) + end + end + session_stores[new_session.class.session_store_type] = new_session + end + + +
+ + + (session_store = nil) + + +Whether a session has been setup +

+

Returns

+ + +
Boolean:true if the session is part of the session stores configured. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/session.rb, line 214 + def session?(session_store = nil) + (session_store ? [session_store] : session_stores).any? do |type, store| + store.is_a?(Merb::SessionContainer) + end + end + + +
+ + + () + + Returns + + +
String:The value of the session cookie; either the session id or the actual +encoded data. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/session.rb, line 258 + def session_cookie_value + cookies[_session_id_key] + end + + +
+ + + () + + +Alias for session_cookie_value +

+ ]]>
+ + +
+ + + () + + Returns + + +
Hash:All active session stores by type. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/session.rb, line 156 + def session_stores + @session_stores ||= {} + end + + +
+ + + (value, options = {}) + + +Sets session cookie value. +

+

Parameters

+ + + +
value<String>:The value of the session cookie; either the session id or the actual +encoded data. + +
options<Hash>:Cookie options like domain, path and expired. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/session.rb, line 247 + def set_session_cookie_value(value, options = {}) + defaults = {} + defaults[:expires] = Time.now + _session_expiry if _session_expiry > 0 + cookies.set_cookie(_session_id_key, value, defaults.merge(options)) + end + + +
+ + + (value, options = {}) + + +Alias for set_session_cookie_value +

+ ]]>
+ + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/dispatch/session.rb + + + + + + + + + + + + + + + + + + + (name, class_name) + + Parameters + + + +
name<~to_sym>:Name of the session type to register. + +
class_name<String>:The corresponding class name. + +
+

Notes

+

+This is automatically called when Merb::SessionContainer is subclassed. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/session.rb, line 139 + def register_session_type(name, class_name) + self.registered_session_types[name.to_sym] = class_name + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/dispatch/session.rb + + + + + StandardError + + + + +Raised when no suitable session store has been setup. +

+ + ]]>
+ + + + + + + + + + + + + +
+ + + + + + + lib/merb-core/dispatch/session.rb + + + + + StandardError + + + + +Raised when storing more data than the available space reserved. +

+ + ]]>
+ + + + + + + + + + + + + +
+ + + + + + + lib/merb-core/controller/mixins/render.rb + + + + + + + + + + + + + + + + + + + (base) + + Parameters + + +
base<Module>:Module that is including RenderMixin +(probably a controller) + +
+

+@api private +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/render.rb, line 9 + def self.included(base) + base.extend(ClassMethods) + base.class_eval do + class_inheritable_accessor :_default_render_options + end + end + + +
+ + +
+ + + + + + (layout = nil) + + +Gets the layout that should be used. The content-type will be appended to +the layout unless the layout already contains a "." in it. +

+

+If no layout was passed in, this method will look for one with the same +name as the controller, and finally one in +"application.#{content_type}". +

+

Parameters

+ + +
layout<~to_s>:A layout, relative to the layout root. Defaults to nil. + +
+

Returns

+ + +
String:The method name that corresponds to the found layout. + +
+

Raises

+ + +
TemplateNotFound:If a layout was specified (either via layout in the class or by passing one +in to this method), and not found. No error will be raised if no layout was +specified, and the default layouts were not found. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/render.rb, line 369 + def _get_layout(layout = nil) + return false if layout == false + + layout = layout.instance_of?(Symbol) && self.respond_to?(layout, true) ? send(layout) : layout + layout = layout.to_s if layout + + # If a layout was provided, throw an error if it's not found + if layout + template_method, template_location = + _template_for(layout, layout.index(".") ? nil : content_type, "layout") + + raise TemplateNotFound, "No layout found at #{template_location}" unless template_method + template_method + + # If a layout was not provided, try the default locations + else + template, location = _template_for(controller_name, content_type, "layout") + template, location = _template_for("application", content_type, "layout") unless template + template + end + end + + +
+ + + (opts) + + +Takes the options hash and handles it as appropriate. +

+

Parameters

+ + +
opts<Hash>:The options hash that was passed into render. + +
+

Options

+ + +
:status<~to_i>:The status of the response will be set to opts[:status].to_i + +
+

Returns

+ + +
Hash:The options hash that was passed in. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/render.rb, line 344 + def _handle_options!(opts) + self.status = opts.delete(:status).to_i if opts[:status] + headers["Location"] = opts.delete(:location) if opts[:location] + opts + end + + +
+ + + (context, content_type, controller=nil, template=nil, locals=[]) + + +Iterates over the template roots in reverse order, and returns the template +and template location of the first match. +

+

Parameters

+ + + + + +
context<Object>:The controller action or template (basename or absolute path). + +
content_type<~to_s>:The content type (like html or json). + +
controller<~to_s>:The name of the controller. Defaults to nil. + +
locals<Array[Symbol]>:A list of locals to assign from the args passed into the compiled template. + +
+

Options (opts)

+ + +
:template<String>:The location of the template to use. Defaults to whatever matches this +context, content_type and controller. + +
+

Returns

+ + +
Array[Symbol, String]:A pair consisting of the template method and location. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/render.rb, line 410 + def _template_for(context, content_type, controller=nil, template=nil, locals=[]) + template_method, template_location = nil, nil + + # absolute path to a template (:template => "/foo/bar") + if template.is_a?(String) && template =~ %r{^/} + template_location = self._absolute_template_location(template, content_type) + return [_template_method_for(template_location, locals), template_location] + end + + self.class._template_roots.reverse_each do |root, template_meth| + # :template => "foo/bar.html" where root / "foo/bar.html.*" exists + if template + template_location = root / self.send(template_meth, template, content_type, nil) + # :layout => "foo" where root / "layouts" / "#{controller}.html.*" exists + else + template_location = root / self.send(template_meth, context, content_type, controller) + end + + break if template_method = _template_method_for(template_location.to_s, locals) + end + + # template_location is a Pathname + [template_method, template_location.to_s] + end + + +
+ + + (template_location, locals) + + +Returns the template method for a location, and checks to make sure the +current controller actually responds to the method. +

+

Parameters

+ + + +
template_location<String>:The physical path of the template + +
locals<Array[Symbol]>:A list of locals to assign from the args passed into the compiled template. + +
+

Returns

+ + +
String:The method, if it exists. Otherwise return nil. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/render.rb, line 446 + def _template_method_for(template_location, locals) + meth = Merb::Template.template_for(template_location, [], locals) + meth && self.respond_to?(meth) ? meth : nil + end + + +
+ + + (obj, string = nil, &block) + + +Called in templates to append content for later use. Works like +throw_content. +

+

+@param [Object] obj +

+
+  Key used in the thrown_content hash.
+
+

+@param [String] string +

+
+  Textual content. Default to nil.
+
+

+@yield +

+
+  Evaluated with result concatenated to string.
+
+

+@raise [ArgumentError] +

+
+  Neither string nor block given
+
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/render.rb, line 512 + def append_content(obj, string = nil, &block) + unless string || block_given? + raise ArgumentError, "You must pass a block or a string into append_content" + end + @_caught_content[obj] = [] if @_caught_content[obj].nil? + @_caught_content[obj] << string.to_s << (block_given? ? capture(&block) : "") + end + + +
+ + + (obj = :for_layout) + + +Called in templates to get at content thrown in another template. The +results of rendering a template are automatically thrown into :for_layout, +so catch_content or catch_content(:for_layout) can be used inside layouts +to get the content rendered by the action template. +

+

Parameters

+ + +
obj<Object>:The key in the thrown_content hash. Defaults to :for_layout. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/render.rb, line 460 + def catch_content(obj = :for_layout) + @_caught_content[obj] || '' + end + + +
+ + + (obj = :for_layout) + + +Called when renderers need to be sure that existing thrown content is +cleared before throwing new content. This prevents double rendering of +content when multiple templates are rendered after each other. +

+

Parameters

+ + +
obj<Object>:The key in the thrown_content hash. Defaults to :for_layout. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/render.rb, line 528 + def clear_content(obj = :for_layout) + @_caught_content.delete(obj) unless @_caught_content[obj].nil? + end + + +
+ + + (object, thing = nil, opts = {}) + + +Renders an object using to registered transform method based on the +negotiated content-type, if a template does not exist. For instance, if the +content-type is :json, Merb will first look for +current_action.json.*. Failing that, it will run object.to_json. +

+

Parameter

+ + + + +
object<Object>:An object that responds_to? the transform method registered for the +negotiated mime-type. + +
thing<String, Symbol>:The thing to attempt to render via render before +calling the transform method on the object. Defaults to nil. + +
opts<Hash>:An options hash that will be used for rendering (passed on to render or serialization methods like to_json or to_xml) + +
+

Returns

+ + +
String:The rendered template or if no template is found, the transformed object. + +
+

Raises

+ + +
NotAcceptable:If there is no transform method for the specified mime-type or the object +does not respond to the transform method. + +
+

Alternatives

+

+A string in the second parameter will be interpreted as a template: +

+
+  display @object, "path/to/foo"
+  #=> display @object, nil, :template => "path/to/foo"
+
+

+A hash in the second parameters will be interpreted as opts: +

+
+  display @object, :layout => "zoo"
+  #=> display @object, nil, :layout => "zoo"
+
+

+If you need to pass extra parameters to serialization method, for instance, +to exclude some of attributes or serialize associations, just pass options +for it. For instance, +

+

+display @locations, :except => [:locatable_type, :locatable_id], +:include => [:locatable] +

+

+serializes object with polymorphic association, not raw locatable_* +attributes. +

+

Options

+

+:template a template to use for rendering :layout a layout to use for +rendering :status the status code to return (defaults to 200) :location the +value of the Location header +

+

+all other options options that will be pass to serialization method +

+
+                         like #to_json or #to_xml
+
+

Notes

+

+The transformed object will not be used in a layout unless a :layout is +explicitly passed in the opts. +

+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/render.rb, line 205 + def display(object, thing = nil, opts = {}) + template_opt = thing.is_a?(Hash) ? thing.delete(:template) : opts.delete(:template) + + case thing + # display @object, "path/to/foo" means display @object, nil, :template => "path/to/foo" + when String + template_opt, thing = thing, nil + # display @object, :template => "path/to/foo" means display @object, nil, :template => "path/to/foo" + when Hash + opts, thing = thing, nil + end + + # Try to render without the object + render(thing || action_name.to_sym, opts.merge(:template => template_opt)) + + # If the render fails (i.e. a template was not found) + rescue TemplateNotFound => e + # Merge with class level default render options + # @todo can we find a way to refactor this out so we don't have to do it everywhere? + opts = self.class.default_render_options.merge(opts) + + # Figure out what to transform and raise NotAcceptable unless there's a transform method assigned + transform = Merb.mime_transform_method(content_type) + if !transform + raise NotAcceptable, "#{e.message} and there was no transform method registered for #{content_type.inspect}" + elsif !object.respond_to?(transform) + raise NotAcceptable, "#{e.message} and your object does not respond to ##{transform}" + end + + layout_opt = opts.delete(:layout) + _handle_options!(opts) + throw_content(:for_layout, opts.empty? ? object.send(transform) : object.send(transform, opts)) + + meth, _ = _template_for(layout_opt, layout_opt.to_s.index(".") ? nil : content_type, "layout") if layout_opt + meth ? send(meth) : catch_content(:for_layout) + end + + +
+ + + (template, opts={}) + + +Renders a partial template. +

+

Parameters

+ + + +
template<~to_s>:The path to the template, relative to the current controller or the +template root; absolute path will work too. If the template contains a +"/", Merb will search for it relative to the +template root; otherwise, Merb will search for it +relative to the current controller. + +
opts<Hash>:A hash of options (see below) + +
+

Options (opts)

+ + + + + +
:with<Object, Array>:An object or an array of objects that will be passed into the partial. + +
:as<~to_sym>:The local name of the :with Object inside of the +partial. + +
:format<Symbol>:The mime format that you want the partial to be in (:js, :html, etc.) + +
others:A Hash object names and values that will be the local +names and values inside the partial. + +
+

Examples

+
+  partial :foo, :hello => @object
+
+

+The "_foo" partial will be called, relative to the current +controller, with a local variable of hello inside of it, assigned +to @object. +

+
+  partial :bar, :with => ['one', 'two', 'three']
+
+

+The "_bar" partial will be called once for each element of the +array specified by :with for a total of three iterations. Each element of +the array will be available in the partial via a local variable named +bar. Additionally, there will be two extra local variables: +collection_index and collection_size. +collection_index is the index of the object currently referenced +by bar in the collection passed to the partial. +collection_size is the total size of the collection. +

+

+By default, the object specified by :with will be available through a local +variable with the same name as the partial template. However, this can be +changed using the :as option. +

+
+  partial :bar, :with => "one", :as => :number
+
+

+In this case, "one" will be available in the partial through the +local variable named number. +

+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/render.rb, line 287 + def partial(template, opts={}) + + # partial :foo becomes "#{controller_name}/_foo" + # partial "foo/bar" becomes "foo/_bar" + template = template.to_s + if template =~ %r{^/} + template_path = File.dirname(template) / "_#{File.basename(template)}" + else + kontroller = (m = template.match(/.*(?=\/)/)) ? m[0] : controller_name + template = "_#{File.basename(template)}" + end + + # This handles no :with as well + with = [opts.delete(:with)].flatten + as = (opts.delete(:as) || template.match(%r[(?:.*/)?_([^\./]*)])[1]).to_sym + + # Ensure that as is in the locals hash even if it isn't passed in here + # so that it's included in the preamble. + locals = opts.merge(:collection_index => -1, :collection_size => with.size, as => opts[as]) + template_method, template_location = _template_for( + template, + opts.delete(:format) || content_type, + kontroller, + template_path, + locals.keys) + + # this handles an edge-case where the name of the partial is _foo.* and your opts + # have :foo as a key. + named_local = opts.key?(as) + + sent_template = with.map do |temp| + locals[as] = temp unless named_local + + if template_method && self.respond_to?(template_method) + locals[:collection_index] += 1 + send(template_method, locals) + else + raise TemplateNotFound, "Could not find template at #{template_location}.*" + end + end.join + + sent_template + end + + +
+ + + (thing = nil, opts = {}) + + +Renders the specified item, with the specified options. +

+

Parameters

+ + + +
thing<String, Symbol, nil>:The thing to render. This will default to the current action + +
opts<Hash>:An options hash (see below) + +
+

Options (opts)

+ + + + + +
:format<Symbol>:A registered mime-type format + +
:template<String>:The path to the template relative to the template root + +
:status<~to_i>:The status to send to the client. Typically, this would be an integer +(200), or a Merb status code (Accepted) + +
:layout<~to_s, FalseClass>:A layout to use instead of the default. This should be relative to the +layout root. By default, the layout will be either the controller_name or +application. If you want to use an alternative content-type than the one +that the base template was rendered as, you will need to do :layout => +"foo.#{content_type}" (i.e. "foo.json"). If you want to +render without layout, use :layout => false. This overrides layout set +by layout method. + +
+

Returns

+ + +
String:The rendered template, including layout, if appropriate. + +
+

Raises

+ + +
TemplateNotFound:There is no template for the specified location. + +
+

Alternatives

+

+If you pass a Hash as the first parameter, it will be +moved to opts and "thing" will be the current action +

+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/render.rb, line 100 + def render(thing = nil, opts = {}) + # render :format => :xml means render nil, :format => :xml + opts, thing = thing, nil if thing.is_a?(Hash) + + # Merge with class level default render options + opts = self.class.default_render_options.merge(opts) + + # If you don't specify a thing to render, assume they want to render the current action + thing ||= action_name.to_sym + + # Content negotiation + self.content_type = opts[:format] if opts[:format] + + # Handle options (:status) + _handle_options!(opts) + + # Do we have a template to try to render? + if thing.is_a?(Symbol) || opts[:template] + + template_method, template_location = + _template_for(thing, content_type, controller_name, opts[:template]) + + # Raise an error if there's no template + unless template_method && self.respond_to?(template_method) + template_files = Merb::Template.template_extensions.map { |ext| "#{template_location}.#{ext}" } + raise TemplateNotFound, "Oops! No template found. Merb was looking for #{template_files.join(', ')}" + + "for content type '#{content_type}'. You might have mispelled the template or file name. " + + "Registered template extensions: #{Merb::Template.template_extensions.join(', ')}. " + + "If you use Haml or some other template plugin, make sure you required Merb plugin dependency " + + "in your init file." + end + + # Call the method in question and throw the content for later consumption by the layout + throw_content(:for_layout, self.send(template_method)) + + # Do we have a string to render? + elsif thing.is_a?(String) + + # Throw it for later consumption by the layout + throw_content(:for_layout, thing) + end + + # If we find a layout, use it. Otherwise, just render the content thrown for layout. + (layout = _get_layout(opts[:layout])) ? send(layout) : catch_content(:for_layout) + end + + +
+ + + (obj, string = nil, &block) + + +Called in templates to store up content for later use. Takes a string +and/or a block. First, the string is evaluated, and then the block is +captured using the capture() helper provided by the template languages. The +two are concatenated together. +

+

Parameters

+ + + + +
obj<Object>:The key in the thrown_content hash. + +
string<String>:Textual content. Defaults to nil. + +
&block:A block to be evaluated and concatenated to string. + +
+

Raises

+ + +
ArgumentError:Neither string nor block given. + +
+

Example

+
+  throw_content(:foo, "Foo")
+  catch_content(:foo) #=> "Foo"
+
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/render.rb, line 492 + def throw_content(obj, string = nil, &block) + unless string || block_given? + raise ArgumentError, "You must pass a block or a string into throw_content" + end + @_caught_content[obj] = string.to_s << (block_given? ? capture(&block) : "") + end + + +
+ + + (obj = :for_layout) + + +Called in templates to test for the existence of previously thrown content. +

+

Parameters

+ + +
obj<Object>:The key in the thrown_content hash. Defaults to :for_layout. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/render.rb, line 470 + def thrown_content?(obj = :for_layout) + @_caught_content.key?(obj) + end + + +
+ + +
+ + + + + + + + + + + +
+ +
+ + + + + + + lib/merb-core/controller/mixins/render.rb + + + + + + + + + + + + + + + + + + + () + + +Enables the default layout logic - resets the layout option. +

+

Returns

+ + +
~to_s:The layout that was previously set. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/render.rb, line 61 + def default_layout + self.default_render_options.delete(:layout) + end + + +
+ + + () + + +Returns the default render options. +

+

Returns

+ + +
Hash:An options hash + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/render.rb, line 24 + def default_render_options + self._default_render_options ||= {} + end + + +
+ + + (layout) + + +Sets the default layout to use or nil/false to disable layout rendering. +This is a shortcut for render_options :layout => +false. +

+

Parameters

+ + +
layout<~to_s>:The layout that should be used for this class. + +
+

Notes

+

+You can override by passing :layout => true to render method. +

+

Returns

+ + +
Hash:The default render options. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/render.rb, line 51 + def layout(layout) + self.default_render_options.update(:layout => (layout || false)) + end + + +
+ + + (opts) + + +Sets default render options at the class level. +

+

Parameters

+ + +
opts<Hash>:An options hash + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/render.rb, line 34 + def render_options(opts) + self._default_render_options = opts + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/tasks/merb_rake_helper.rb + + + + + + + + + + + + + + + + + + + (name, options = {}) + + + +# File lib/merb-core/tasks/merb_rake_helper.rb, line 8 + def self.install(name, options = {}) + defaults = { :cache => false } + defaults[:install_dir] = ENV['GEM_DIR'] if ENV['GEM_DIR'] + opts = defaults.merge(options) + dir = if File.directory?(subdir = File.join(Dir.pwd, name)) + subdir + else + Dir.pwd + end + install_gem_from_source(dir, name, opts) + ensure_wrapper(opts[:install_dir] || Gem.default_dir, name) + end + + + + + + (pkg, options = {}) + + + +# File lib/merb-core/tasks/merb_rake_helper.rb, line 21 + def self.install_package(pkg, options = {}) + defaults = { :cache => false } + defaults[:install_dir] = ENV['GEM_DIR'] if ENV['GEM_DIR'] + opts = defaults.merge(options) + # Needs to be executed from the directory that contains all packages + Dir.chdir(File.dirname(pkg_file = File.expand_path(pkg))) do + install_gem(pkg_file, opts) + end + name = File.basename(pkg, '.gem')[/^(.*?)-([\d\.]+)$/, 1] + ensure_wrapper(opts[:install_dir] || Gem.default_dir, name) + end + + + + + + () + + + +# File lib/merb-core/tasks/merb_rake_helper.rb, line 39 + def self.sudo + ENV['MERB_SUDO'] ||= "sudo" + sudo = windows? ? "" : ENV['MERB_SUDO'] + end + + + + + + (name, options = {}) + + + +# File lib/merb-core/tasks/merb_rake_helper.rb, line 33 + def self.uninstall(name, options = {}) + defaults = { :ignore => true, :executables => true } + defaults[:install_dir] = ENV['GEM_DIR'] if ENV['GEM_DIR'] + uninstall_gem(name, defaults.merge(options)) + end + + + + + + () + + + +# File lib/merb-core/tasks/merb_rake_helper.rb, line 44 + def self.windows? + (PLATFORM =~ /win32|cygwin/) rescue nil + end + + + + + + + + + + + + (gemdir, name) + + + +# File lib/merb-core/tasks/merb_rake_helper.rb, line 50 + def self.ensure_wrapper(gemdir, name) + # See if there's a local bin dir - one directory up from ./gems + bindir = File.expand_path(File.join(gemdir, '..', 'bin')) + # Fall back to system wide bindir - usually needs sudo permissions + bindir = Gem.bindir unless File.directory?(bindir) + ensure_bin_wrapper_for(gemdir, bindir, name, :no_minigems => ['merb-gen']) + end + + + + + + + + + + + + + + + + + + + + + lib/merb-core/rack/adapter/abstract.rb + + lib/merb-core/rack/adapter/ebb.rb + + lib/merb-core/rack/adapter/evented_mongrel.rb + + lib/merb-core/rack/adapter/fcgi.rb + + lib/merb-core/rack/adapter/irb.rb + + lib/merb-core/rack/adapter/mongrel.rb + + lib/merb-core/rack/adapter/runner.rb + + lib/merb-core/rack/adapter/swiftiplied_mongrel.rb + + lib/merb-core/rack/adapter/thin.rb + + lib/merb-core/rack/adapter/thin_turbo.rb + + lib/merb-core/rack/adapter/webrick.rb + + lib/merb-core/rack/adapter.rb + + lib/merb-core/rack/application.rb + + lib/merb-core/rack/handler/mongrel.rb + + lib/merb-core/rack/helpers.rb + + lib/merb-core/rack/middleware/conditional_get.rb + + lib/merb-core/rack/middleware/content_length.rb + + lib/merb-core/rack/middleware/path_prefix.rb + + lib/merb-core/rack/middleware/profiler.rb + + lib/merb-core/rack/middleware/static.rb + + lib/merb-core/rack/middleware/tracer.rb + + lib/merb-core/rack/middleware.rb + + lib/merb-core/rack/stream_wrapper.rb + + lib/merb-core/rack.rb + + + + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/rack/helpers.rb + + + + + + + + + + + + + + + + + + + (url, options = {}) + + +A helper to build a rack response which implements a redirect. The status +will be set to the passed in status if passed. If you pass in permanent it +will be a 301, permanent redirect, otherwise it defaults to a temporary 302 +redirect. +

+

Parameters

+ + + +
url<~to_s>:The url to redirect to. + +
options<Hash>:A hash of options for the redirect + +
+
+  status: The status code to use for the redirect
+  permanent:  True if this is a permanent redirect (301)
+
+

Returns

+ + +
<Array>:A rack response to redirect to the specified url. + +
+

+:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/rack/helpers.rb, line 19 + def self.redirect(url, options = {}) + # Build the rack array + status = options.delete(:status) + status ||= options[:permanent] ? 301 : 302 + + Merb.logger.info("Dispatcher redirecting to: #{url} (#{status})") + Merb.logger.flush + + [status, { Merb::Const::LOCATION => url }, + Merb::Rack::StreamWrapper.new("<html><body>You are being <a href=\"#{url}\">redirected</a>.</body></html>")] + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/rack/handler/mongrel.rb + + + + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/rack/handler/mongrel.rb + + + + + ::Mongrel::HttpHandler + + + + + + + + + + + + + + + + (app) + + Parameters + + +
app<Merb::Rack::Application>:The app that Mongrel should +handle. + +
+

+:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/rack/handler/mongrel.rb, line 53 + def initialize(app) + @app = app + end + + +
+ + + (app, options={}) {|@server if block_given?| ...} + + +Runs the server and yields it to a block. +

+

Parameters

+ + + +
app<Merb::Rack::Application>:The app that Mongrel should +handle. + +
options<Hash>:Options to pass to Mongrel (see +below). + +
+

Block parameters

+ + +
server<Mongrel::HttpServer>:The server to run. + +
+

Options (options)

+ + + +
:Host<String>:The hostname on which the app should run. Defaults to "0.0.0.0" + +
:Port<Fixnum>:The port for the app. Defaults to 8080. + +
+

+:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/rack/handler/mongrel.rb, line 36 + def self.run(app, options={}) + @server = ::Mongrel::HttpServer.new(options[:Host] || '0.0.0.0', + options[:Port] || 8080) + @server.register('/', ::Merb::Rack::Handler::Mongrel.new(app)) + yield @server if block_given? + @server.run.join + end + + +
+ + + (block = true) + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/rack/handler/mongrel.rb, line 45 + def self.stop(block = true) + @server.stop + end + + +
+ + +
+ + + + + + (request, response) + + Parameters + + + +
request<Merb::Request>:The HTTP request to handle. + +
response<HTTPResponse>:The response object to write response to. + +
+

+:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/rack/handler/mongrel.rb, line 62 + def process(request, response) + env = {}.replace(request.params) + env.delete Merb::Const::HTTP_CONTENT_TYPE + env.delete Merb::Const::HTTP_CONTENT_LENGTH + + env[Merb::Const::SCRIPT_NAME] = Merb::Const::EMPTY_STRING if env[Merb::Const::SCRIPT_NAME] == Merb::Const::SLASH + + env.update({"rack.version" => [0,1], + "rack.input" => request.body || StringIO.new(""), + "rack.errors" => STDERR, + + "rack.multithread" => true, + "rack.multiprocess" => false, # ??? + "rack.run_once" => false, + + "rack.url_scheme" => "http" + }) + env[Merb::Const::QUERY_STRING] ||= "" + env.delete Merb::Const::PATH_INFO if env[Merb::Const::PATH_INFO] == Merb::Const::EMPTY_STRING + + status, headers, body = @app.call(env) + + begin + response.status = status.to_i + headers.each { |k, vs| + vs.each { |v| + response.header[k] = v + } + } + + body.each { |part| + response.body << part + } + response.finished + ensure + body.close if body.respond_to? :close + end + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/rack/middleware/path_prefix.rb + + + + + Merb::Rack::Middleware + + + + + + + + + + + + + + + + (app, path_prefix = nil) + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/rack/middleware/path_prefix.rb, line 6 + def initialize(app, path_prefix = nil) + super(app) + @path_prefix = /^#{Regexp.escape(path_prefix)}/ + end + + +
+ + +
+ + + + + + (env) + + +:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/rack/middleware/path_prefix.rb, line 18 + def call(env) + strip_path_prefix(env) + @app.call(env) + end + + +
+ + + (env) + + +:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/rack/middleware/path_prefix.rb, line 12 + def deferred?(env) + strip_path_prefix(env) + @app.deferred?(env) + end + + +
+ + + (env) + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/rack/middleware/path_prefix.rb, line 24 + def strip_path_prefix(env) + ['PATH_INFO', 'REQUEST_URI'].each do |path_key| + if env[path_key] =~ @path_prefix + env[path_key].sub!(@path_prefix, Merb::Const::EMPTY_STRING) + env[path_key] = Merb::Const::SLASH if env[path_key].empty? + end + end + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/rack/middleware/tracer.rb + + + + + Merb::Rack::Middleware + + + + + + + + + + + + + + + + (env) + + +:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/rack/middleware/tracer.rb, line 6 + def call(env) + + Merb.logger.debug!("Rack environment:\n" + env.inspect + "\n\n") + + status, headers, body = @app.call(env) + + Merb.logger.debug!("Status: #{status.inspect}") + Merb.logger.debug!("Headers: #{headers.inspect}") + Merb.logger.debug!("Body: #{body.inspect}") + + [status, headers, body] + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/rack/middleware/content_length.rb + + + + + Merb::Rack::Middleware + + + + + + + + + + + + + + + + (env) + + +:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/rack/middleware/content_length.rb, line 7 + def call(env) + status, headers, body = @app.call(env) + + # to_s is because Rack spec expects header + # values to be iterable and yield strings + header = 'Content-Length'.freeze + headers[header] = body.size.to_s unless headers.has_key?(header) + + [status, headers, body] + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/rack/adapter/fcgi.rb + + + + + Object + + + + + + + + + + + + + + + + (opts={}) + + Parameters + + +
opts<Hash>:Options for FastCGI (see below). + +
+

Options (opts)

+ + +
:app<String>>:The application name. + +
+

+:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/rack/adapter/fcgi.rb, line 12 + def self.start(opts={}) + Merb.logger.warn!("Using FastCGI adapter") + Merb::Server.change_privilege + ::Rack::Handler::FastCGI.run(opts[:app], opts) + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/rack/adapter/thin.rb + + + + + Merb::Rack::AbstractAdapter + + + + + + + + + + + + + + + + (port) + + +:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/rack/adapter/thin.rb, line 11 + def self.new_server(port) + Merb::Dispatcher.use_mutex = false + + if (@opts[:socket] || @opts[:socket_file]) + socket = port.to_s + socket_file = @opts[:socket_file] || "#{Merb.log_path}/#{Merb::Config[:name]}.#{socket}.sock" + Merb.logger.warn!("Using Thin adapter with socket file #{socket_file}.") + @server = ::Thin::Server.new(socket_file, @opts[:app], @opts) + else + Merb.logger.warn!("Using Thin adapter on host #{@opts[:host]} and port #{port}.") + @opts[:host] = "#{@opts[:host]}-#{port}" if @opts[:host].include?('/') + @server = ::Thin::Server.new(@opts[:host], port, @opts[:app], @opts) + end + end + + +
+ + + () + + +:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/rack/adapter/thin.rb, line 27 + def self.start_server + ::Thin::Logging.silent = true + @server.start + end + + +
+ + + (status = 0) + + +:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/rack/adapter/thin.rb, line 33 + def self.stop(status = 0) + if @server + @server.stop + true + end + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/rack/adapter/irb.rb + + + + + Object + + + + + + + + + + + + + + + + (opts={}) + + Parameters +

+opts<Hash>: +

+
+  Options for IRB. Currently this is not used by the IRB adapter.
+
+

Notes

+

+If the .irbrc file exists, it will be loaded into the IRBRC +environment variable. +

+

+:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/rack/adapter/irb.rb, line 149 + def self.start(opts={}) + m = Merb::Rack::Console.new + m.extend Merb::Test::RequestHelper + Object.send(:define_method, :merb) { m } + ARGV.clear # Avoid passing args to IRB + m.open_sandbox! if sandboxed? + require 'irb' + require 'irb/completion' + if File.exists? ".irbrc" + ENV['IRBRC'] = ".irbrc" + end + IRB.start + at_exit do merb.close_sandbox! if sandboxed? end + exit + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/rack/adapter.rb + + + + + Object + + + + + + + + + + + + + + + + (id) + + +Gets a rack adapter by id. +

+

Parameters

+ + +
id<String>:The identifier of the Rack adapter class to +retrieve. + +
+

Returns.

+ + +
Class:The adapter class. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/rack/adapter.rb, line 17 + def get(id) + if @adapters[id.to_s] + Object.full_const_get(@adapters[id.to_s]) + else + Merb.fatal! "The adapter #{id} did not exist" + end + end + + +
+ + + (ids, adapter_class) + + +Registers a new Rack adapter. +

+

Parameters

+ + + +
ids<Array>:Identifiers by which this adapter is recognized by. + +
adapter_class<Class>:The Rack adapter class. + +
+

+:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/rack/adapter.rb, line 32 + def register(ids, adapter_class) + @adapters ||= Hash.new + ids.each { |id| @adapters[id] = "Merb::Rack::#{adapter_class}" } + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/rack/application.rb + + + + + Object + + + + + + + + + + + + + + + + (env) + + +The main rack application call method. This is the entry point from rack +(and the webserver) to your application. +

+

Parameters

+ + +
env<Hash>:A rack request of parameters. + +
+

Returns

+ + +
<Array>:A rack response of [status<Integer>, headers<Hash>, body<String, Stream>] + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/rack/application.rb, line 15 + def call(env) + begin + rack_response = ::Merb::Dispatcher.handle(Merb::Request.new(env)) + rescue Object => e + return [500, {Merb::Const::CONTENT_TYPE => Merb::Const::TEXT_SLASH_HTML}, e.message + Merb::Const::BREAK_TAG + e.backtrace.join(Merb::Const::BREAK_TAG)] + end + Merb.logger.info Merb::Const::DOUBLE_NEWLINE + Merb.logger.flush + + # unless controller.headers[Merb::Const::DATE] + # require "time" + # controller.headers[Merb::Const::DATE] = Time.now.rfc2822.to_s + # end + rack_response + end + + +
+ + + (env) + + +Determines whether this request is a "deferred_action", usually a +long request. Rack uses this method to determine +whether to use an evented request or a deferred request in evented rack +handlers. +

+

Parameters

+ + +
env<Hash>:The rack request + +
+

Returns

+ + +
Boolean:True if the request should be deferred. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/rack/application.rb, line 43 + def deferred?(env) + path = env[Merb::Const::PATH_INFO] ? env[Merb::Const::PATH_INFO].chomp(Merb::Const::SLASH) : Merb::Const::EMPTY_STRING + if path =~ Merb.deferred_actions + Merb.logger.info! "Deferring Request: #{path}" + true + else + false + end + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/rack/adapter/runner.rb + + + + + Object + + + + + + + + + + + + + + + + (opts={}) + + Parameters + + +
opts<Hash>:Options for the runner (see below). + +
+

Options (opts)

+ + +
:runner_code<String>:The code to run. + +
+

Notes

+

+If opts[:runner_code] matches a filename, that file will be read and the +contents executed. Otherwise the code will be executed directly. +

+

+:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/rack/adapter/runner.rb, line 17 + def self.start(opts={}) + Merb::Server.change_privilege + if opts[:runner_code] + if File.exists?(opts[:runner_code]) + eval(File.read(opts[:runner_code]), TOPLEVEL_BINDING, __FILE__, __LINE__) + else + eval(opts[:runner_code], TOPLEVEL_BINDING, __FILE__, __LINE__) + end + exit + end + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/rack/adapter/irb.rb + + + + + Object + + + + + + + + + + + + + + + + () + + +Ends a sandboxed session (delegates to any Merb::Orms::* modules). +

+

+An ORM should implement Merb::Orms::MyOrm#close_sandbox! to support this. +Usually this involves rolling back a transaction. :api: public +

+ ]]>
+ + + +# File lib/merb-core/rack/adapter/irb.rb, line 113 + def close_sandbox! + orm_modules.each { |orm| orm.close_sandbox! if orm.respond_to?(:close_sandbox!) } + puts "Modifications have been rolled back" + end + + +
+ + + () + + +Starts a sandboxed session (delegates to any Merb::Orms::* modules). +

+

+An ORM should implement Merb::Orms::MyOrm#open_sandbox! to support this. +Usually this involves starting a transaction. :api: public +

+ ]]>
+ + + +# File lib/merb-core/rack/adapter/irb.rb, line 102 + def open_sandbox! + puts "Loading #{Merb.environment} environment in sandbox (Merb #{Merb::VERSION})" + puts "Any modifications you make will be rolled back on exit" + orm_modules.each { |orm| orm.open_sandbox! if orm.respond_to?(:open_sandbox!) } + end + + +
+ + + () + + +Reloads classes using Merb::BootLoader::ReloadClasses. +:api: public +

+ ]]>
+ + + +# File lib/merb-core/rack/adapter/irb.rb, line 65 + def reload! + Merb::BootLoader::ReloadClasses.reload + end + + +
+ + + () + + +Prints all routes for the application. :api: public +

+ ]]>
+ + + +# File lib/merb-core/rack/adapter/irb.rb, line 71 + def show_routes + seen = [] + unless Merb::Router.named_routes.empty? + puts "==== Named routes" + Merb::Router.named_routes.each do |name,route| + # something weird happens when you combine sprintf and irb + puts "Helper : #{name}" + meth = $1.upcase if route.conditions[:method].to_s =~ /(get|post|put|delete)/ + puts "HTTP method: #{meth || 'GET'}" + puts "Route : #{route}" + puts "Params : #{route.params.inspect}" + puts + seen << route + end + end + puts "==== Anonymous routes" + (Merb::Router.routes - seen).each do |route| + meth = $1.upcase if route.conditions[:method].to_s =~ /(get|post|put|delete)/ + puts "HTTP method: #{meth || 'GET'}" + puts "Route : #{route}" + puts "Params : #{route.params.inspect}" + puts + end + nil + end + + +
+ + + () + + +Explictly show logger output during IRB session :api: public +

+ ]]>
+ + + +# File lib/merb-core/rack/adapter/irb.rb, line 120 + def trace_log! + Merb.logger.auto_flush = true + end + + +
+ + + (name, *args) + + +There are three possible ways to use this method. First, if you have a +named route, you can specify the route as the first parameter as a symbol +and any parameters in a hash. Second, you can generate the default route by +just passing the params hash, just passing the params hash. Finally, you +can use the anonymous parameters. This allows you to specify the parameters +to a named route in the order they appear in the router. +

+

Parameters(Named Route)

+ + + +
name<Symbol>:The name of the route. + +
args<Hash>:Parameters for the route generation. + +
+

Parameters(Default Route)

+ + +
args<Hash>:Parameters for the route generation. This route will use the default route. + +
+

Parameters(Anonymous Parameters)

+ + + +
name<Symbol>:The name of the route. + +
args<Array>:An array of anonymous parameters to generate the route with. These +parameters are assigned to the route parameters in the order that they are +passed. + +
+

Returns

+ + +
String:The generated URL. + +
+

Examples

+

+Named Route +

+

+Merb::Router.prepare do +

+
+  match("/articles/:title").to(:controller => :articles, :action => :show).name("articles")
+
+

+end +

+

+url(:articles, :title => "new_article") +

+

+Default Route +

+

+Merb::Router.prepare do +

+
+  default_routes
+
+

+end +

+

+url(:controller => "articles", :action => "new") +

+

+Anonymous Parameters +

+

+Merb::Router.prepare do +

+
+  match("/articles/:year/:month/:title").to(:controller => :articles, :action => :show).name("articles")
+
+

+end +

+

+url(:articles, 2008, 10, "test_article") +

+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/rack/adapter/irb.rb, line 58 + def url(name, *args) + args << {} + Merb::Router.url(name, *args) + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/rack/adapter/ebb.rb + + + + + Merb::Rack::AbstractAdapter + + + + + + + + + + + + + + + + (port) + + +start an Ebb server on given host and port. +:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/rack/adapter/ebb.rb, line 9 + def self.new_server(port) + Merb::Dispatcher.use_mutex = false + opts = @opts.merge(:port => port) + @th = Thread.new { Thread.current[:server] = ::Ebb.start_server(opts[:app], opts) } + end + + +
+ + + () + + +:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/rack/adapter/ebb.rb, line 16 + def self.start_server + @th.join + end + + +
+ + + (status = 0) + + +:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/rack/adapter/ebb.rb, line 21 + def self.stop(status = 0) + ::Ebb.stop_server + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/rack/adapter/abstract.rb + + + + + Object + + + + + + + + + + + + + + + + (status = 0) + + +Exit the process with the specified status. +

+

Parameters

+ + +
status<Integer>:The exit code of the process. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/rack/adapter/abstract.rb, line 244 + def self.exit_process(status = 0) + exit(status) + end + + +
+ + + (port) + + +This method is designed to be overridden in a rack adapter. It will be +called to create a new instance of the server for the adapter to start. The +adapter should attempt to bind to a port at this point. This is called from +the AbstractAdapter start +method. +

+

Parameters

+ + +
port<Integer>:The port the server should listen on + +
+

+:api: plugin @overridable +

+ ]]>
+ + + +# File lib/merb-core/rack/adapter/abstract.rb, line 25 + def self.new_server(port) + raise NotImplemented + end + + +
+ + + (whoami, port) + + +Sets the process title. +

+

Parameters

+ + +
whoami<Symbol>:Either :spawner for the master process or :worker for any of the worker + +
+
+  processes.
+
+ + +
port<Integer>:The base port that the app is running on. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/rack/adapter/abstract.rb, line 256 + def self.process_title(whoami, port) + name = Merb::Config[:name] + app = "merb#{" : #{name}" if (name && name != "merb")}" + max_port = Merb::Config[:cluster] ? (Merb::Config[:cluster] - 1) : 0 + numbers = ((whoami != :worker) && (max_port > 0)) ? "#{port}..#{port + max_port}" : port + file = Merb::Config[:socket_file] % port if Merb::Config[:socket_file] + + listening_on = if Merb::Config[:socket] + "socket#{'s' if max_port > 0 && whoami != :worker} #{numbers} "\ + "#{file ? file : "#{Merb.log_path}/#{name}.#{port}.sock"}" + else + "port#{'s' if max_port > 0 && whoami != :worker} #{port}" + end + "#{app} : #{whoami} (#{listening_on})" + end + + +
+ + + (port) + + +Spawns a new worker process at a port. +

+

Parameters

+ + +
port<Integer>:The port to start the worker process on. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/rack/adapter/abstract.rb, line 50 + def self.spawn_worker(port) + worker_pid = Kernel.fork + start_at_port(port, @opts) unless worker_pid + + # If we have a worker_pid, we're in the parent. + throw(:new_worker) unless worker_pid + + @pids[port] = worker_pid + $WORKERS = @pids.values + end + + +
+ + + (opts={}) + + +The main start method for bootloaders that support forking. This method +launches the adapters which inherit using the new_server and start_server +methods. This method should not be overridden in adapters which want to +fork. +

+

Parameters

+ + +
opts<Hash>:A hash of options + +
+
+  socket: the socket to bind to
+  port: the port to bind to
+  cluster: the number
+
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/rack/adapter/abstract.rb, line 73 + def self.start(opts={}) + @opts = opts + $WORKERS ||= [] + parent = nil + + @pids = {} + port = (opts[:socket] || opts[:port]).to_i + max_port = Merb::Config[:cluster] ? Merb::Config[:cluster] - 1 : 0 + + # If we only have a single merb, just start it up and dispense with + # the spawner/worker setup. + if max_port == 0 + start_at_port(port) + return + end + + $0 = process_title(:spawner, port) + + # For each port, spawn a new worker. The parent will continue in + # the loop, while the worker will throw :new_worker and be booted + # out of the loop. + catch(:new_worker) do + 0.upto(max_port) do |i| + parent = spawn_worker(port + i) + end + end + + # If we're in a worker, we're done. Otherwise, we've completed + # setting up workers and now need to watch them. + return unless parent + + # For each worker, set up a thread in the spawner to watch it + 0.upto(max_port) do |i| + Thread.new do + catch(:new_worker) do + loop do + pid = @pids[port + i] + begin + # Watch for the pid to exit. + _, status = Process.wait2(pid) + + # If the pid doesn't exist, we want to silently exit instead of + # raising here. + rescue SystemCallError => e + ensure + # If there was no worker with that PID, the status was non-0 + # (we send back a status of 128 when ABRT is called on a + # worker, and Merb.fatal! exits with a status of 1), or if + # Merb is in the process of exiting, *then* don't respawn. + # Note that processes killed with kill -9 will return no + # exitstatus, and we respawn them. + if !status || + (status.exitstatus && status.exitstatus != 0) || + Merb.exiting then + Thread.exit + end + end + + # Otherwise, respawn the worker, and watch it again. + spawn_worker(port + i) + end + end + end + end + + # The spawner process will make it here, and when it does, it should just + # sleep so it can pick up ctrl-c if it's in console mode. + sleep + + end + + +
+ + + (port, opts = @opts) + + +Forks a server on the specified port and start the app. +

+

Parameters

+ + + +
port<Integer>:The port to start the server on + +
opts<Hash>:The hash of options, defaults to the @opts + +
+
+  instance variable.
+
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/rack/adapter/abstract.rb, line 152 + def self.start_at_port(port, opts = @opts) + at_exit do + Merb::Server.remove_pid(port) + end + + Merb::Worker.start unless Merb.testing? + + # If Merb is daemonized, trap INT. If it's not daemonized, + # we let the master process' ctrl-c control the cluster + # of workers. + if Merb::Config[:daemonize] + Merb.trap('INT') do + Merb.exiting = true + stop + Merb.logger.warn! "Exiting port #{port}\n" + exit_process + end + # If it was not fork_for_class_load, we already set up + # ctrl-c handlers in the master thread. + elsif Merb::Config[:fork_for_class_load] + if Merb::Config[:console_trap] + Merb::Server.add_irb_trap + end + end + + # In daemonized mode or not, support HUPing the process to + # restart it. + Merb.trap('HUP') do + Merb.exiting = true + stop + Merb.logger.warn! "Exiting port #{port} on #{Process.pid}\n" + exit_process + end + + # ABRTing the process will kill it, and it will not be respawned. + Merb.trap('ABRT') do + Merb.exiting = true + stopped = stop(128) + Merb.logger.warn! "Exiting port #{port}\n" if stopped + exit_process(128) + end + + # Each worker gets its own `ps' name. + $0 = process_title(:worker, port) + + # Store the PID for this worker + Merb::Server.store_pid(port) + + Merb::Config[:log_delimiter] = "#{process_title(:worker, port)} ~ " + + Merb.reset_logger! + Merb.logger.warn!("Starting #{self.name.split("::").last} at port #{port}") + + # If we can't connect to the port, keep trying until we can. Print + # a warning about this once. Try every 0.25s. + printed_warning = false + loop do + begin + # Call the adapter's new_server method, which should attempt + # to bind to a port. + new_server(port) + rescue Errno::EADDRINUSE => e + if Merb::Config[:bind_fail_fatal] + Merb.fatal! "Could not bind to #{port}. It was already in use", e + end + + unless printed_warning + Merb.logger.warn! "Port #{port} is in use, " \ + "Waiting for it to become available." + printed_warning = true + end + + sleep 0.25 + next + end + break + end + + Merb.logger.warn! "Successfully bound to port #{port}" + + Merb::Server.change_privilege + + # Call the adapter's start_server method. + start_server + end + + +
+ + + () + + +This method is designed to be overridden in a rack adapter. It will be +called to start a server created with the new_server +method. This is called from the AbstractAdapter start method. +

+

+:api: plugin @overridable +

+ ]]>
+ + + +# File lib/merb-core/rack/adapter/abstract.rb, line 11 + def self.start_server + raise NotImplemented + end + + +
+ + + (status) + + +This method is designed to be overridden in a rack adapter. It will be +called to stop the adapter server. +

+

Parameters

+ + +
status<Integer>:The exit status the adapter should exit with. + +
+

Returns

+ + +
Boolean:True if the server was properly stopped. + +
+

+:api: plugin @overridable +

+ ]]>
+ + + +# File lib/merb-core/rack/adapter/abstract.rb, line 40 + def self.stop(status) + raise NotImplemented + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/rack/middleware.rb + + + + + Object + + + + + + + + + + + + + + + + (app) + + +@overridable :api: plugin +

+ ]]>
+ + + +# File lib/merb-core/rack/middleware.rb, line 7 + def initialize(app) + @app = app + end + + +
+ + +
+ + + + + + (env) + + +@overridable :api: plugin +

+ ]]>
+ + + +# File lib/merb-core/rack/middleware.rb, line 19 + def call(env) + @app.call(env) + end + + +
+ + + (env) + + +@overridable :api: plugin +

+ ]]>
+ + + +# File lib/merb-core/rack/middleware.rb, line 13 + def deferred?(env) + @app.deferred?(env) + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/rack/middleware/static.rb + + + + + Merb::Rack::Middleware + + + + + + + + + + + + + + + + (app,directory) + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/rack/middleware/static.rb, line 6 + def initialize(app,directory) + super(app) + @static_server = ::Rack::File.new(directory) + end + + +
+ + +
+ + + + + + (env) + + +:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/rack/middleware/static.rb, line 12 + def call(env) + path = if env[Merb::Const::PATH_INFO] + env[Merb::Const::PATH_INFO].chomp(Merb::Const::SLASH) + else + Merb::Const::EMPTY_STRING + end + cached_path = (path.empty? ? 'index' : path) + '.html' + + if file_exist?(path) && env[Merb::Const::REQUEST_METHOD] =~ /GET|HEAD/ # Serve the file if it's there and the request method is GET or HEAD + serve_static(env) + elsif file_exist?(cached_path) && env[Merb::Const::REQUEST_METHOD] =~ /GET|HEAD/ # Serve the page cache if it's there and the request method is GET or HEAD + env[Merb::Const::PATH_INFO] = cached_path + serve_static(env) + elsif path =~ /favicon\.ico/ + return [404, { Merb::Const::CONTENT_TYPE => Merb::Const::TEXT_SLASH_HTML }, "404 Not Found."] + else + @app.call(env) + end + end + + +
+ + + (path) + + Parameters + + +
path<String>:The path to the file relative to the server root. + +
+

Returns

+ + +
Boolean:True if file exists under the server root and is readable. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/rack/middleware/static.rb, line 39 + def file_exist?(path) + full_path = ::File.join(@static_server.root, ::Merb::Parse.unescape(path)) + ::File.file?(full_path) && ::File.readable?(full_path) + end + + +
+ + + (env) + + Parameters + + +
env<Hash>:Environment variables to pass on to the server. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/rack/middleware/static.rb, line 48 + def serve_static(env) + env[Merb::Const::PATH_INFO] = ::Merb::Parse.unescape(env[Merb::Const::PATH_INFO]) + @static_server.call(env) + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/rack/stream_wrapper.rb + + + + + Object + + + + + + + + + + + + + + + + (body) + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/rack/stream_wrapper.rb, line 6 + def initialize(body) + @body = body + end + + +
+ + +
+ + + + + + (other) + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/rack/stream_wrapper.rb, line 34 + def ==(other) + @body == other + end + + +
+ + + (&callback) + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/rack/stream_wrapper.rb, line 11 + def each(&callback) + if Proc === @body + @writer = lambda { |x| callback.call(x) } + @body.call(self) + elsif @body.is_a?(String) + @body.each_line(&callback) + else + @body.each(&callback) + end + end + + +
+ + + (sym, *args, &blk) + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/rack/stream_wrapper.rb, line 39 + def method_missing(sym, *args, &blk) + @body.send(sym, *args, &blk) + end + + +
+ + + () + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/rack/stream_wrapper.rb, line 29 + def to_s + @body.to_s + end + + +
+ + + (str) + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/rack/stream_wrapper.rb, line 23 + def write(str) + @writer.call str.to_s + str + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/rack/adapter/webrick.rb + + + + + Merb::Rack::AbstractAdapter + + + + + + + + + + + + + + RW + + + + + + + + + + + + + (port) + + +:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/rack/adapter/webrick.rb, line 15 + def self.new_server(port) + options = { + :Port => port, + :BindAddress => @opts[:host], + :Logger => Merb.logger, + :AccessLog => [ + [Merb.logger, ::WEBrick::AccessLog::COMMON_LOG_FORMAT], + [Merb.logger, ::WEBrick::AccessLog::REFERER_LOG_FORMAT] + ] + } + + sockets = ::WEBrick::Utils.create_listeners nil, port + @server = ::WEBrick::HTTPServer.new(options.merge(:DoNotListen => true)) + @server.listeners.replace sockets + end + + +
+ + + () + + +:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/rack/adapter/webrick.rb, line 32 + def self.start_server + @server.mount("/", ::Rack::Handler::WEBrick, @opts[:app]) + @server.start + exit(@status) + end + + +
+ + + (status = 0) + + +:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/rack/adapter/webrick.rb, line 39 + def self.stop(status = 0) + @status = status + @server.shutdown + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/rack/adapter/swiftiplied_mongrel.rb + + + + + Merb::Rack::Mongrel + + + + + + + + + + + + + + + + (port) + + +:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/rack/adapter/swiftiplied_mongrel.rb, line 8 + def self.new_server(port) + Merb::Dispatcher.use_mutex = false + super + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/rack/adapter/mongrel.rb + + + + + Merb::Rack::AbstractAdapter + + + + + + + + + + + + + + + + (port) + + +:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/rack/adapter/mongrel.rb, line 31 + def self.new_server(port) + @server = ::Mongrel::HttpServer.new(@opts[:host], port) + end + + +
+ + + () + + +:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/rack/adapter/mongrel.rb, line 36 + def self.start_server + @server.register('/', ::Merb::Rack::Handler::Mongrel.new(@opts[:app])) + @server.run.join + end + + +
+ + + (status = 0) + + +:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/rack/adapter/mongrel.rb, line 18 + def self.stop(status = 0) + if @server + begin + @server.stop(true) + rescue Mongrel::TimeoutError + Merb.logger.fatal! "Your process took too long to shut " \ + "down, so mongrel killed it." + end + true + end + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/rack/middleware/profiler.rb + + + + + Merb::Rack::Middleware + + + + + + + + + + + + + + + + (app, min=1, iter=1) + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/rack/middleware/profiler.rb, line 6 + def initialize(app, min=1, iter=1) + super(app) + @min, @iter = min, iter + end + + +
+ + +
+ + + + + + (env) + + +:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/rack/middleware/profiler.rb, line 12 + def call(env) + __profile__("profile_output", @min, @iter) do + @app.call(env) + end + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/rack/middleware/conditional_get.rb + + + + + Merb::Rack::Middleware + + + + + + + + + + + + + + + + (env) + + +:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/rack/middleware/conditional_get.rb, line 7 + def call(env) + status, headers, body = @app.call(env) + + if document_not_modified?(env, headers) + status = 304 + body = Merb::Const::EMPTY_STRING + # set Date header using RFC1123 date format as specified by HTTP + # RFC2616 section 3.3.1. + end + + [status, headers, body] + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/rack/adapter/thin_turbo.rb + + + + + Merb::Rack::Thin + + + + + + + + + + + + + + + + (port) + + +:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/rack/adapter/thin_turbo.rb, line 11 + def self.new_server(port) + @opts.merge!(:backend => ::Thin::Backends::Turbo) + super + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/rack/adapter/evented_mongrel.rb + + + + + Merb::Rack::Mongrel + + + + + + + + + + + + + + + + (port) + + +:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/rack/adapter/evented_mongrel.rb, line 8 + def self.new_server(port) + Merb::Dispatcher.use_mutex = false + super + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/controller/mixins/responder.rb + + + + + + + +The ResponderMixin adds methods that +help you manage what formats your controllers have available, determine +what format(s) the client requested and is capable of handling, and perform +content negotiation to pick the proper content format to deliver. +

+

+If you hear someone say "Use provides" they’re talking +about the Responder. If you hear someone ask +"What happened to respond_to?" it was replaced by provides and +the other Responder methods. +

+

A simple example

+

+The best way to understand how all of these pieces fit together is with an +example. Here’s a simple web-service ready resource that provides a +list of all the widgets we know about. The widget list is available in 3 +formats: :html (the default), plus :xml and :text. +

+
+    class Widgets < Application
+      provides :html   # This is the default, but you can
+                       # be explicit if you like.
+      provides :xml, :text
+
+      def index
+        @widgets = Widget.fetch
+        render @widgets
+      end
+    end
+
+

+Let’s look at some example requests for this list of widgets. +We’ll assume they’re all GET requests, but that’s only to +make the examples easier; this works for the full set of RESTful methods. +

+
    +
  1. The simplest case, /widgets.html Since the request includes a specific +format (.html) we know what format to return. Since :html is in our list of +provided formats, that’s what we’ll return. render +will look for an index.html.erb (or another template format like +index.html.mab; see the documentation on Template engines) + +
  2. +
  3. Almost as simple, /widgets.xml This is very similar. They want :xml, we +have :xml, so that’s what they get. If render doesn’t +find an index.xml.builder or similar template, it will call to_xml +on @widgets. This may or may not do something useful, but you can see how +it works. + +
  4. +
  5. A browser request for /widgets This time the URL doesn’t say what +format is being requested, so we’ll look to the HTTP Accept: header. +If it’s ‘/’ (anything), we’ll use the first +format on our list, :html by default. + +

    +If it parses to a list of accepted formats, we’ll look through them, +in order, until we find one we have available. If we find one, we’ll +use that. Otherwise, we can’t fulfill the request: they asked for a +format we don’t have. So we raise 406: Not Acceptable. +

    +
  6. +
+

A more complex example

+

+Sometimes you don’t have the same code to handle each available +format. Sometimes you need to load different data to serve /widgets.xml +versus /widgets.txt. In that case, you can use content_type to determine what format will be +delivered. +

+
+    class Widgets < Application
+      def action1
+        if content_type == :text
+          Widget.load_text_formatted(params[:id])
+        else
+          render
+        end
+      end
+
+      def action2
+        case content_type
+        when :html
+          handle_html()
+        when :xml
+          handle_xml()
+        when :text
+          handle_text()
+        else
+          render
+        end
+      end
+    end
+
+

+You can do any standard Ruby flow control using content_type. If you don’t call it yourself, +it will be called (triggering content negotiation) by render. +

+

+Once content_type has been called, the +output format is frozen, and none of the provides methods can be used. +

+ + ]]>
+ + + + + + + + + + + Dictionary.new + + + + + + + {} + + + + + + + + + + + + + + (base) + + Parameters + + +
base<Module>:The module that ResponderMixin was +mixed into + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/responder.rb, line 109 + def self.included(base) + base.extend(ClassMethods) + base.class_eval do + class_inheritable_accessor :class_provided_formats + self.class_provided_formats = [] + end + base.reset_provides + end + + +
+ + +
+ + + + + + () + + +Do the content negotiation: +

+
    +
  1. if params[:format] is there, and provided, use it + +
  2. +
  3. Parse the Accept header + +
  4. +
  5. If it’s /, use the first provided format + +
  6. +
  7. Look for one that is provided, in order of request + +
  8. +
  9. Raise 406 if none found + +
  10. +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/responder.rb, line 268 + def _perform_content_negotiation + if (fmt = params[:format]) && !fmt.empty? + accepts = [fmt.to_sym] + elsif request.accept =~ %r{^(text/html|\*/\*)} && _provided_formats.first == :html + # Handle the common case of text/html and :html provided after checking :format + return :html + else + accepts = Responder.parse(request.accept).map {|t| t.to_sym}.compact + end + + # no need to make a bunch of method calls to _provided_formats + provided_formats = _provided_formats + + specifics = accepts & provided_formats + return specifics.first unless specifics.length == 0 + return provided_formats.first if accepts.include?(:all) && !provided_formats.empty? + + message = "A format (%s) that isn't provided (%s) has been requested. " + message += "Make sure the action provides the format, and be " + message += "careful of before filters which won't recognize " + message += "formats provided within actions." + raise Merb::ControllerExceptions::NotAcceptable, + (message % [accepts.join(', '), provided_formats.join(', ')]) + end + + +
+ + + () + + Returns + + +
Array[Symbol]:The current list of formats provided for this instance of the controller. +It starts with what has been set in the controller (or :html by default) +but can be modified on a per-action basis. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/responder.rb, line 199 + def _provided_formats + @_provided_formats ||= class_provided_formats.dup + end + + +
+ + + (fmt = nil) + + +Returns the output format for this request, based on the provided formats, +params[:format] and the client’s HTTP Accept header. +

+

+The first time this is called, it triggers content negotiation and caches +the value. Once you call content_type you +can not set or change the list of provided formats. +

+

+Called automatically by render, so you should only call it if you +need the value, not to trigger content negotiation. +

+

Parameters

+ + +
fmt<String>:An optional format to use instead of performing content negotiation. This +can be used to pass in the values of opts[:format] from the render function +to short-circuit content-negotiation when it’s not necessary. This +optional parameter should not be considered part of the public API. + +
+

Returns

+ + +
Symbol:The content-type that will be used for this controller. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/responder.rb, line 316 + def content_type(fmt = nil) + self.content_type = (fmt || _perform_content_negotiation) unless @_content_type + @_content_type + end + + +
+ + + (type) + + +Sets the content type of the current response to a value based on a passed +in key. The Content-Type header will be set to the first registered header +for the mime-type. +

+

Parameters

+ + +
type<Symbol>:The content type. + +
+

Raises

+ + +
ArgumentError:type is not in the list of registered mime-types. + +
+

Returns

+ + +
Symbol:The content-type that was passed in. + +
+

+:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/responder.rb, line 335 + def content_type=(type) + unless Merb.available_mime_types.has_key?(type) + raise Merb::ControllerExceptions::NotAcceptable.new("Unknown content_type for response: #{type}") + end + + @_content_type = type + + mime = Merb.available_mime_types[type] + + headers["Content-Type"] = mime[:content_type] + + # merge any format specific response headers + mime[:response_headers].each { |k,v| headers[k] ||= v } + + # if given, use a block to finetune any runtime headers + mime[:response_block].call(self) if mime[:response_block] + + @_content_type + end + + +
+ + + (*formats) + + +Removes formats from the list of provided formats for this particular +request. Usually used to remove formats from a single action. See also the +controller-level does_not_provide that affects all +actions in a controller. +

+

Parameters

+ + +
*formats<Symbol>:Registered mime-type + +
+

Returns

+ + +
Array[Symbol]:List of formats that remain after removing the ones not to provide. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/responder.rb, line 256 + def does_not_provide(*formats) + @_provided_formats -= formats.flatten + end + + +
+ + + (*formats) + + +Sets list of provided formats for this particular request. Usually used to +limit formats to a single action. See also the controller-level only_provides that affects all actions in a controller. +

+

Parameters

+ + +
*formats<Symbol>:A list of formats to use as the per-action list of provided formats. + +
+

Returns

+ + +
Array[Symbol]:List of formats passed in. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/responder.rb, line 238 + def only_provides(*formats) + @_provided_formats = [] + provides(*formats) + end + + +
+ + + (*formats) + + +Adds formats to the list of provided formats for this particular request. +Usually used to add formats to a single action. See also the +controller-level provides that affects all actions in a controller. +

+

Parameters

+ + +
*formats<Symbol>:A list of formats to add to the per-action list of provided formats. + +
+

Raises

+ + +
Merb::ResponderMixin::ContentTypeAlreadySet:Content negotiation already occurred, and the content_type is set. + +
+

Returns

+ + +
Array[Symbol]:List of formats passed in. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/responder.rb, line 219 + def provides(*formats) + if @_content_type + raise ContentTypeAlreadySet, "Cannot modify provided_formats because content_type has already been set" + end + @_provided_formats = self._provided_formats | formats # merges with class_provided_formats if not already + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/controller/mixins/responder.rb + + + + + + + + + + + + + + + + + + + () + + +Clear the list of provides. +

+

Returns

+ + +
Array:An empty Array. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/responder.rb, line 177 + def clear_provides + self.class_provided_formats.clear + end + + +
+ + + (*formats) + + +This class should not provide any of this list of formats, despite any. +other definitions previously or in superclasses. +

+

Parameters

+ + +
*formats<Symbol>:Registered mime-types. + +
+

Returns

+ + +
Array[Symbol]:List of formats that remain after removing the ones not to provide. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/responder.rb, line 167 + def does_not_provide(*formats) + self.class_provided_formats -= formats + end + + +
+ + + (*formats) + + +This class should only provide the formats listed here, despite any other +definitions previously or in superclasses. +

+

Parameters

+ + +
*formats<Symbol>:Registered mime-types. + +
+

Returns

+ + +
Array[Symbol]:List of formats passed in. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/responder.rb, line 151 + def only_provides(*formats) + clear_provides + provides(*formats) + end + + +
+ + + (*formats) + + +Adds symbols representing formats to the controller’s default list of +provided_formats. These will apply to every action in the controller, +unless modified in the action. If the last argument is a Hash or an Array, these are regarded as arguments to pass +to the to_<mime_type> method as needed. +

+

Parameters

+ + +
*formats<Symbol>:A list of mime-types that the controller should provide. + +
+

Returns

+ + +
Array[Symbol]:List of formats passed in. + +
+

Examples

+
+  provides :html, :xml
+
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/responder.rb, line 137 + def provides(*formats) + self.class_provided_formats |= formats + end + + +
+ + + () + + +Reset the list of provides to include only :html. +

+

Returns

+ + +
Array[Symbol]:[:html]. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/responder.rb, line 187 + def reset_provides + only_provides(:html) + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/controller/mixins/responder.rb + + + + + StandardError + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/mixins/authentication.rb + + + + + + + + + + + + + + + + + + + (realm = "Application", &authenticator) + + +Attempts to authenticate the user via HTTP Basic authentication. Takes a +block with the username and password, if the block yields false the +authentication is not accepted and :halt is thrown. +

+

+If no block is passed, basic_authentication, the request and +authenticate methods can be chained. These can be used to +independently request authentication or confirm it, if more control is +desired. +

+

Parameters

+ + + +
realm<~to_s>:The realm to authenticate against. Defaults to ‘Application’. + +
&authenticator:A block to check if the authentication is valid. + +
+

Returns

+

+Merb::AuthenticationMixin::BasicAuthentication +

+

Examples

+
+    class Application < Merb::Controller
+
+      before :authenticate
+
+      protected
+
+      def authenticate
+        basic_authentication("My App") do |username, password|
+          password == "secret"
+        end
+      end
+
+    end
+
+    class Application < Merb::Controller
+
+      before :authenticate
+
+      def authenticate
+        user = basic_authentication.authenticate do |username, password|
+          User.authenticate(username, password)
+        end
+
+        if user
+          @current_user = user
+        else
+          basic_authentication.request
+        end
+      end
+
+    end
+
+

+If you need to request basic authentication inside an action you need to +use the request! method. +

+

Example

+
+   class Sessions < Application
+
+     def new
+       case content_type
+       when :html
+         render
+
+       else
+        user = basic_authentication.authenticate do |username, password|
+          User.authenticate(username, password)
+        end
+
+        if user
+          display(user)
+        else
+          basic_authentication.request
+        end
+       end
+     end
+
+   end
+
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/authentication.rb, line 79 + def basic_authentication(realm = "Application", &authenticator) + @_basic_authentication ||= BasicAuthentication.new(self, realm, &authenticator) + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/controller/mixins/authentication.rb + + + + + Object + + + + + + + + + + + + + + + + (controller, realm = "Application", &authenticator) + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/authentication.rb, line 88 + def initialize(controller, realm = "Application", &authenticator) + @controller = controller + @realm = realm + @auth = Rack::Auth::Basic::Request.new(@controller.request.env) + authenticate_or_request(&authenticator) if authenticator + end + + +
+ + +
+ + + + + + (&authenticator) + + +Determines whether or not the user is authenticated using the criteria in +the provided authenticator block. +

+

Parameters

+ + +
&authenticator:A block that decides whether the provided username and password + +
+
+  are valid.
+
+

Returns

+ + +
Object:False if basic auth is not provided, otherwise the return value of the +authenticator block. + +
+

+@overridable :api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/authentication.rb, line 107 + def authenticate(&authenticator) + if @auth.provided? and @auth.basic? + authenticator.call(*@auth.credentials) + else + false + end + end + + +
+ + + () + + Returns + + +
String:The password provided in the request. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/authentication.rb, line 158 + def password + provided? ? @auth.credentials.last : nil + end + + +
+ + + () + + Returns + + +
Boolean:Whether there has been any basic authentication credentials provided + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/authentication.rb, line 142 + def provided? + @auth.provided? + end + + +
+ + + () + + +Request basic authentication and halt the +filter chain. This is for use in a before filter. +

+

Throws

+

+:halt with an "HTTP Basic: Access denied." message with no +layout, and sets the status to Unauthorized. +

+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/authentication.rb, line 121 + def request + request! + throw :halt, @controller.render("HTTP Basic: Access denied.\n", :status => Unauthorized.status, :layout => false) + end + + +
+ + + () + + +Sets headers to request basic auth. +

+

Returns

+ + +
String:Returns the empty string to provide a response body. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/authentication.rb, line 132 + def request! + @controller.status = Unauthorized.status + @controller.headers['WWW-Authenticate'] = 'Basic realm="%s"' % @realm + "" + end + + +
+ + + () + + Returns + + +
String:The username provided in the request. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/authentication.rb, line 150 + def username + provided? ? @auth.credentials.first : nil + end + + +
+ + +
+ + + + + + (&authenticator) + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/authentication.rb, line 165 + def authenticate_or_request(&authenticator) + authenticate(&authenticator) || request + end + + +
+ + +
+ + + + + + + + + + + +
+ +
+ + + + + + + lib/merb-core/constants.rb + + + + + + + + + + + + + + + + { :type => 'application/octet-stream'.freeze, :disposition => 'attachment'.freeze }.freeze + + + + + + + 'rack.input'.freeze + + + + + + + 'binary'.freeze + + + + + + + " %s=%s; path=/; expires=%s".freeze + + + + + + + "%a, %d-%b-%Y %H:%M:%S GMT".freeze + + + + + + + /[;,] */n.freeze + + + + + + + /\s*(.+)=(.*)\s*/.freeze + + + + + + + Time.at(0).freeze + + + + + + + 60 * 60 + + + + + + + HOUR * 24 + + + + + + + DAY * 7 + + + + + + + /\Amultipart\/form-data.*boundary=\"?([^\";,]+)/n.freeze + + + + + + + 'HTTP_COOKIE'.freeze + + + + + + + 'QUERY_STRING'.freeze + + + + + + + %r{^application/json|^text/x-json}.freeze + + + + + + + %r{^application/xml|^text/xml}.freeze + + + + + + + %r{^application/x-www-form-urlencoded}.freeze + + + + + + + /^unknown$|^(127|10|172\.16|192\.168)\./i.freeze + + + + + + + /XMLHttpRequest/i.freeze + + + + + + + 'CONTENT_TYPE'.freeze + + + + + + + "Content-Type".freeze + + + + + + + 'Date'.freeze + + + + + + + 'HTTPS'.freeze + + + + + + + 'https'.freeze + + + + + + + 'http'.freeze + + + + + + + 'ETag'.freeze + + + + + + + "Last-Modified".freeze + + + + + + + "GET".freeze + + + + + + + "POST".freeze + + + + + + + "HEAD".freeze + + + + + + + "CONTENT_LENGTH".freeze + + + + + + + 'Content-Disposition'.freeze + + + + + + + "Content-Transfer-Encoding".freeze + + + + + + + "HTTP_CLIENT_IP".freeze + + + + + + + "HTTP_X_REQUESTED_WITH".freeze + + + + + + + "HTTP_X_FORWARDED_FOR".freeze + + + + + + + "HTTP_X_FORWARDED_PROTO".freeze + + + + + + + "HTTP_X_FORWARDED_HOST".freeze + + + + + + + "HTTP_IF_MODIFIED_SINCE".freeze + + + + + + + "HTTP_IF_NONE_MATCH".freeze + + + + + + + "HTTP_CONTENT_TYPE".freeze + + + + + + + "HTTP_CONTENT_LENGTH".freeze + + + + + + + "HTTP_REFERER".freeze + + + + + + + "HTTP_USER_AGENT".freeze + + + + + + + "HTTP_HOST".freeze + + + + + + + "HTTP_CONNECTION".freeze + + + + + + + "HTTP_KEEP_ALIVE".freeze + + + + + + + "HTTP_ACCEPT".freeze + + + + + + + "HTTP_ACCEPT_ENCODING".freeze + + + + + + + "HTTP_ACCEPT_LANGUAGE".freeze + + + + + + + "HTTP_ACCEPT_CHARSET".freeze + + + + + + + "HTTP_CACHE_CONTROL".freeze + + + + + + + "upload_id".freeze + + + + + + + "PATH_INFO".freeze + + + + + + + "HTTP_VERSION".freeze + + + + + + + "GATEWAY_INTERFACE".freeze + + + + + + + "SCRIPT_NAME".freeze + + + + + + + "SERVER_NAME".freeze + + + + + + + "SERVER_SOFTWARE".freeze + + + + + + + "SERVER_PROTOCOL".freeze + + + + + + + "SERVER_PORT".freeze + + + + + + + "REQUEST_URI".freeze + + + + + + + "REQUEST_PATH".freeze + + + + + + + "REQUEST_METHOD".freeze + + + + + + + "REMOTE_ADDR".freeze + + + + + + + "<br/>".freeze + + + + + + + "".freeze + + + + + + + " ".freeze + + + + + + + "\n".freeze + + + + + + + "/".freeze + + + + + + + ".".freeze + + + + + + + "?".freeze + + + + + + + "\n\n".freeze + + + + + + + "Location".freeze + + + + + + + "text/html".freeze + + + + + + + 'X-Accel-Redirect'.freeze + + + + + + + /(:?mswin|mingw|cygwin)/.freeze + + + + + + + /java/.freeze + + + + + + + + + + + + + + + + + + + + + lib/merb-core/dispatch/session.rb + + + + + + + +The Merb::Session module gets mixed into Merb::SessionContainer to allow +app-level functionality (usually found in ./merb/session/session.rb) for +session. +

+

+You can use this module to implement additional methods to simplify +building wizard-like application components, authentication frameworks, +etc. +

+

+Session configuration options: +

+

+:session_id_key The key by which a session value/id is +

+
+                          retrieved; defaults to _session_id
+
+

+:session_expiry When to expire the session cookie; +

+
+                          by defaults session expires when browser quits.
+
+

+:session_secret_key A secret string which is used to sign/validate +

+
+                          session data; min. 16 chars
+
+

+:default_cookie_domain The default domain to write cookies for. +

+ + ]]>
+ + + + + + + + + + + + + +
+ + + + + + + lib/merb-core/controller/exceptions.rb + + + + + + + + def admin_access_required + render + end + end + +

+In app/views/exceptions/admin_access_required.rhtml +

+
+  <h1>You're not an administrator!</h1>
+  <p>You tried to access <%= @tried_to_access %> but that URL is
+  restricted to administrators.</p>
+
+ + ]]>
+ + + + + + + + + + + {} + + + + + + + + + + + + + +
+ + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Merb::ControllerExceptions::ServerError + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Merb::ControllerExceptions::ClientError + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Merb::ControllerExceptions::ClientError + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Merb::ControllerExceptions::ClientError + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Merb::ControllerExceptions::Base + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Merb::ControllerExceptions::Successful + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Merb::ControllerExceptions::ServerError + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Merb::ControllerExceptions::ClientError + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Merb::ControllerExceptions::Successful + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Merb::ControllerExceptions::Successful + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Merb::ControllerExceptions::Informational + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Merb::ControllerExceptions::ClientError + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Merb::ControllerExceptions::NotFound + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Merb::ControllerExceptions::Successful + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Merb::ControllerExceptions::Successful + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Merb::ControllerExceptions::ServerError + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Merb::ControllerExceptions::ClientError + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Merb::ControllerExceptions::Base + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Merb::ControllerExceptions::ServerError + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Merb::ControllerExceptions::Base + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Merb::ControllerExceptions::NotFound + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Merb::ControllerExceptions::ClientError + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Merb::ControllerExceptions::BadRequest + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Merb::ControllerExceptions::Redirection + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Merb::ControllerExceptions::Base + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Merb::ControllerExceptions::Base + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Merb::ControllerExceptions::Redirection + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Merb::ControllerExceptions::Redirection + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Merb::ControllerExceptions::Successful + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/exceptions.rb + + + + + StandardError + + + + + + + + + + + + + + + + (subclass) + + +Registers any subclasses with status codes for easy lookup by set_status in +Merb::Controller. +

+

+Inheritance ensures this method gets inherited by any subclasses, so it +goes all the way down the chain of inheritance. +

+

Parameters

+ + +
subclass<Merb::ControllerExceptions::Base>:The Exception class that is inheriting from Merb::ControllerExceptions::Base + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/exceptions.rb, line 219 + def inherited(subclass) + # don't set the constant yet - any class methods will be called after self.inherited + # unless self.status = ... is set explicitly, the status code will be inherited + register_status_code(subclass, self.status) if self.status? + end + + +
+ + + () + + +Gets the actual status-code for an Exception +class. +

+

+As usual, this can come from a constant upwards in the inheritance chain. +

+

Returns

+ + +
Fixnum:The status code of this exception. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/exceptions.rb, line 174 + def status + const_get(:STATUS) rescue 0 + end + + +
+ + + (num) + + +Sets the actual status-code for an Exception +class. +

+

+If possible, set the STATUS constant, and update any previously registered +(inherited) status-code. +

+

Parameters

+ + +
num<~to_i>:The status code + +
+

Returns

+ + +
(Integer, nil):The status set on this exception, or nil if a status was already set. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/controller/exceptions.rb, line 191 + def status=(num) + unless self.status? + register_status_code(self, num) + self.const_set(:STATUS, num.to_i) + end + end + + +
+ + + () + + +See if a status-code has been defined (on self explicitly). +

+

Returns

+ + +
Boolean:Whether a status code has been set + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/controller/exceptions.rb, line 204 + def status? + self.const_defined?(:STATUS) + end + + +
+ + +
+ + + + + + () + + Returns + + +
Integer:The status-code of the error. + +
+

+@overridable :api: plugin +

+ ]]>
+ + + +# File lib/merb-core/controller/exceptions.rb, line 160 + def status; self.class.status; end + + +
+ + + () + + +Alias for status +

+ ]]>
+ + +
+ + + () + + +Alias for status +

+ ]]>
+ + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Merb::ControllerExceptions::ServerError + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Merb::ControllerExceptions::ClientError + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Merb::ControllerExceptions::ClientError + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Merb::ControllerExceptions::Redirection + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Merb::ControllerExceptions::Redirection + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Merb::ControllerExceptions::Successful + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Merb::ControllerExceptions::Informational + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Merb::ControllerExceptions::ServerError + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Merb::ControllerExceptions::ClientError + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Merb::ControllerExceptions::ClientError + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Merb::ControllerExceptions::Redirection + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Merb::ControllerExceptions::ClientError + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Merb::ControllerExceptions::ClientError + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Merb::ControllerExceptions::ClientError + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Merb::ControllerExceptions::NotFound + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Merb::ControllerExceptions::ClientError + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Merb::ControllerExceptions::ClientError + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Merb::ControllerExceptions::ClientError + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Merb::ControllerExceptions::ClientError + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/exceptions.rb + + + + + Merb::ControllerExceptions::Redirection + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/autoload.rb + + lib/merb-core/controller/template.rb + + + + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/controller/mixins/controller.rb + + + + + + + +Module that is mixed in to all implemented controllers. +

+ + ]]>
+ + + + + + + + + + + + + + (name) + + +Marks a cookie as deleted and gives it an expires stamp in the past. This +method is used primarily internally in Merb. +

+

+Use the cookies hash to manipulate cookies instead. +

+

Parameters

+ + +
name<~to_s>:A name for the cookie to delete. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/controller.rb, line 322 + def delete_cookie(name) + set_cookie(name, nil, Merb::Const::COOKIE_EXPIRED_TIME) + end + + +
+ + + (obj) + + +Alias for escape_xml +

+ ]]>
+ + +
+ + + (obj) + + +Escapes the string representation of obj and escapes it for use in +XML. +

+

Parameter

+ + +
obj<~to_s>:The object to escape for use in XML. + +
+

Returns

+ + +
String:The escaped object. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/controller.rb, line 335 + def escape_xml(obj) + Erubis::XmlHelper.escape_xml(obj.to_s) + end + + +
+ + + (obj) + + +Alias for escape_xml +

+ ]]>
+ + +
+ + + () + + +Retrieves the redirect message either locally or from the request. +

+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/controller.rb, line 148 + def message + @_message = defined?(@_message) ? @_message : request.message + end + + +
+ + + (message) + + +Sets the redirect message for the current request, like flash.now in Rails. +

+

+@api public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/controller.rb, line 155 + def message=(message) + @_message = message + end + + +
+ + + (path, content_type = Merb::Const::EMPTY_STRING) + + +Uses the nginx specific X-Accel-Redirect header to send a file +directly from nginx. +

+

Notes

+

+Unless Content-Disposition is set before calling this method, it is set to +attachment with streamed file name. +

+

+For more information, see the nginx wiki: wiki.codemongers.com/NginxXSendfile +

+

+and the following sample gist: gist.github.com/11225 +

+

+there’s also example application up on GitHub: +

+

+github.com/michaelklishin/nginx-x-accel-redirect-example-application/tree/master +

+

Parameters

+ + + +
path<String>:Path to file to send to the client. + +
content_type<String>:content type header value. By default is set to empty string to let Nginx +detect it. + +
+

Return

+ + +
String:precisely a single space. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/controller.rb, line 288 + def nginx_send_file(path, content_type = Merb::Const::EMPTY_STRING) + # Let Nginx detect content type unless it is explicitly set + headers[Merb::Const::CONTENT_TYPE] = content_type + headers[Merb::Const::CONTENT_DISPOSITION] ||= "attachment; filename=#{File.basename(path)}" + # X-Accel-Redirect + headers[Merb::Const::X_ACCEL_REDIRECT] = path + + return Merb::Const::SPACE + end + + +
+ + + (url, opts = {}) + + Parameters + + + +
url<String>:URL to redirect to. It can be either a relative or fully-qualified URL. + +
opts<Hash>:An options hash (see below) + +
+

Options (opts)

+ + + +
:message<Hash>:Messages to pass in url query string as value for "_message" + +
:permanent<Boolean>:When true, return status 301 Moved Permanently + +
+

Returns

+ + +
String:Explanation of redirect. + +
+

Examples

+
+  redirect("/posts/34")
+  redirect("/posts/34", :message => { :notice => 'Post updated successfully!' })
+  redirect("http://www.merbivore.com/")
+  redirect("http://www.merbivore.com/", :permanent => true)
+
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/controller.rb, line 132 + def redirect(url, opts = {}) + default_redirect_options = { :message => nil, :permanent => false } + opts = default_redirect_options.merge(opts) + if opts[:message] + notice = Merb::Parse.escape([Marshal.dump(opts[:message])].pack("m")) + url = url =~ /\?/ ? "#{url}&_message=#{notice}" : "#{url}?_message=#{notice}" + end + self.status = opts[:permanent] ? 301 : 302 + Merb.logger.info("Redirecting to: #{url} (#{self.status})") + headers['Location'] = url + "<html><body>You are being <a href=\"#{url}\">redirected</a>.</body></html>" + end + + +
+ + + (&blk) + + +Renders the block given as a parameter using chunked encoding. +

+

Parameters

+ + +
&blk:A block that, when called, will use send_chunks to send chunks of data down +to the server. The chunking will terminate once the block returns. + +
+

Examples

+
+  def stream
+    prefix = '<p>'
+    suffix = "</p>\r\n"
+    render_chunked do
+      IO.popen("cat /tmp/test.log") do |io|
+        done = false
+        until done
+          sleep 0.3
+          line = io.gets.chomp
+
+          if line == 'EOF'
+            done = true
+          else
+            send_chunk(prefix + line + suffix)
+          end
+        end
+      end
+    end
+  end
+
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/controller.rb, line 50 + def render_chunked(&blk) + must_support_streaming! + headers['Transfer-Encoding'] = 'chunked' + Proc.new { |response| + @response = response + response.send_status_no_connection_close('') + response.send_header + blk.call + response.write("0\r\n\r\n") + } + end + + +
+ + + (&blk) + + Parameters + + +
&blk:A proc that should get called outside the mutex, and which will return the +value to render. + +
+

Returns

+ + +
Proc:A block that the server can call later, allowing Merb +to release the thread lock and render another request. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/controller.rb, line 86 + def render_deferred(&blk) + Proc.new do |response| + response.write(blk.call) + end + end + + +
+ + + (str, &blk) + + +Renders the passed in string, then calls the block outside the mutex and +after the string has been returned to the client. +

+

Parameters

+ + + +
str<String>:A String to return to the client. + +
&blk:A block that should get called once the string has been returned. + +
+

Returns

+ + +
Proc:A block that Mongrel can call after returning the +string to the user. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/controller.rb, line 104 + def render_then_call(str, &blk) + Proc.new do |response| + response.write(str) + blk.call + end + end + + +
+ + + (&blk) + + +Enqueues a block to run in a background thread outside of the request +response dispatch. +

+

Parameters

+ + +
&blk:proc to run later + +
+

Example

+

+run_later do +

+
+  SomeBackgroundTask.run
+
+

+end +

+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/controller.rb, line 17 + def run_later(&blk) + Merb::Dispatcher.work_queue << blk + end + + +
+ + + (data) + + +Writes a chunk from render_chunked to the +response that is sent back to the client. This should only be called within +a render_chunked block. +

+

Parameters

+ + +
data<String>:a chunk of data to return. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/controller.rb, line 69 + def send_chunk(data) + only_runs_on_mongrel! + @response.write('%x' % data.size + "\r\n") + @response.write(data + "\r\n") + end + + +
+ + + (data, opts={}) + + +Sends binary data over HTTP to the user as a file download. May set content +type, apparent file name, and specify whether to show data inline or +download as an attachment. +

+

Parameters

+ + + +
data<String>:Path to file to send to the client. + +
opts<Hash>:Options for sending the data (see below). + +
+

Options (opts)

+ + + + +
:disposition<String>:The disposition of the file send. Defaults to "attachment". + +
:filename<String>:The name to use for the file. Defaults to the filename of file. + +
:type<String>:The content type. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/controller.rb, line 210 + def send_data(data, opts={}) + opts.update(Merb::Const::DEFAULT_SEND_FILE_OPTIONS.merge(opts)) + disposition = opts[:disposition].dup || DEFAULT_SEND_FILE_OPTIONS[:disposition] + disposition << %(; filename="#{opts[:filename]}") if opts[:filename] + headers.update( + Merb::Const::CONTENT_TYPE => opts[:type].strip, # fixes a problem with extra '\r' with some browsers + Merb::Const::CONTENT_DISPOSITION => disposition, + Merb::Const::CONTENT_TRANSFER_ENCODING => Merb::Const::BINARY + ) + data + end + + +
+ + + (file, opts={}) + + +Sends a file over HTTP. When given a path to a file, it will set the right +headers so that the static file is served directly. +

+

Parameters

+ + + +
file<String>:Path to file to send to the client. + +
opts<Hash>:Options for sending the file (see below). + +
+

Options (opts)

+ + + + +
:disposition<String>:The disposition of the file send. Defaults to "attachment". + +
:filename<String>:The name to use for the file. Defaults to the filename of file. + +
:type<String>:The content type. + +
+

Returns

+ + +
IO:An I/O stream for the file. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/controller.rb, line 177 + def send_file(file, opts={}) + opts.update(Merb::Const::DEFAULT_SEND_FILE_OPTIONS.merge(opts)) + disposition = opts[:disposition].dup || DEFAULT_SEND_FILE_OPTIONS[:disposition] + disposition << %(; filename="#{opts[:filename] ? opts[:filename] : File.basename(file)}") + headers.update( + Merb::Const::CONTENT_TYPE => opts[:type].strip, # fixes a problem with extra '\r' with some browsers + Merb::Const::CONTENT_DISPOSITION => disposition, + Merb::Const::CONTENT_TRANSFER_ENCODING => Merb::Const::BINARY + ) + Proc.new do |response| + file = File.open(file, 'rb') + while chunk = file.read(16384) + response.write chunk + end + file.close + end + end + + +
+ + + (name, value, expires) + + +Sets a cookie to be included in the response. +

+

+If you need to set a cookie, then use the cookies hash. +

+

Parameters

+ + + + +
name<~to_s>:A name for the cookie. + +
value<~to_s>:A value for the cookie. + +
expires<~gmtime:~strftime, Hash>:An expiration time for the cookie, or a hash of cookie options. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/controller.rb, line 308 + def set_cookie(name, value, expires) + options = expires.is_a?(Hash) ? expires : {:expires => expires} + cookies.set_cookie(name, value, options) + end + + +
+ + + (opts={}, &stream) + + +Streams a file over HTTP. +

+

Parameters

+ + + +
opts<Hash>:Options for the file streaming (see below). + +
&stream:A block that, when called, will return an object that responds to +get_lines for streaming. + +
+

Options

+ + + + + +
:disposition<String>:The disposition of the file send. Defaults to "attachment". + +
:type<String>:The content type. + +
:content_length<Numeric>:The length of the content to send. + +
:filename<String>:The name to use for the streamed file. + +
+

Examples

+
+  stream_file({ :filename => file_name, :type => content_type,
+    :content_length => content_length }) do |response|
+    AWS::S3::S3Object.stream(user.folder_name + "-" + user_file.unique_id, bucket_name) do |chunk|
+      response.write chunk
+    end
+  end
+
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/controller.rb, line 246 + def stream_file(opts={}, &stream) + opts.update(Merb::Const::DEFAULT_SEND_FILE_OPTIONS.merge(opts)) + disposition = opts[:disposition].dup || DEFAULT_SEND_FILE_OPTIONS[:disposition] + disposition << %(; filename="#{opts[:filename]}") + headers.update( + Merb::Const::CONTENT_TYPE => opts[:type].strip, # fixes a problem with extra '\r' with some browsers + Merb::Const::CONTENT_DISPOSITION => disposition, + Merb::Const::CONTENT_TRANSFER_ENCODING => Merb::Const::BINARY, + # Rack specification requires header values to respond to :each + Merb::Const::CONTENT_LENGTH => opts[:content_length].to_s + ) + Proc.new do |response| + stream.call(response) + end + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/controller/mixins/conditional_get.rb + + + + + + + +Provides conditional get support in Merb core. +Conditional get support is intentionally simple and does not do fancy stuff +like making ETag value from Ruby objects for you. +

+

+The most interesting method for end user is request_fresh? that is +used after setting of last modification time or ETag: +

+

Example

+

+def show +

+
+  self.etag = Digest::SHA1.hexdigest(calculate_cache_key(params))
+
+  if request_fresh?
+    self.status = 304
+    return ''
+  else
+    @product = Product.get(params[:id])
+    display @product
+  end
+
+

+end +

+ + ]]>
+ + + + + + + + + + + + + + () + + Returns + + +
<String>:Value of ETag response header or nil if it’s not set. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/conditional_get.rb, line 43 + def etag + headers[Merb::Const::ETAG] + end + + +
+ + + (tag) + + +Sets ETag response header by calling to_s on the argument. +

+

Parameters

+ + +
tag<~to_s>:value of ETag header enclosed in double quotes as required by the RFC + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/conditional_get.rb, line 34 + def etag=(tag) + headers[Merb::Const::ETAG] = %("#{tag}") + end + + +
+ + + (tag = self.etag) + + Returns +

+<Boolean>:: true if ETag response header equals If-None-Match request +header, false otherwise +

+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/conditional_get.rb, line 53 + def etag_matches?(tag = self.etag) + tag == self.request.if_none_match + end + + +
+ + + () + + Returns + + +
<String>:Value of Last-Modified response header or nil if it’s not set. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/conditional_get.rb, line 74 + def last_modified + Time.rfc2822(headers[Merb::Const::LAST_MODIFIED]) + end + + +
+ + + (time) + + +Sets Last-Modified response header. +

+

Parameters

+

+tag<Time>:: resource modification timestamp converted into format +required by the RFC +

+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/conditional_get.rb, line 65 + def last_modified=(time) + headers[Merb::Const::LAST_MODIFIED] = time.httpdate + end + + +
+ + + (time = self.last_modified) + + Returns +

+<Boolean>:: true if Last-Modified response header is < than +If-Modified-Since request header value, false otherwise. +

+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/conditional_get.rb, line 84 + def not_modified?(time = self.last_modified) + request.if_modified_since && time && time <= request.if_modified_since + end + + +
+ + + () + + Returns +

+<Boolean>:: true if either ETag matches or entity is not modified, so +request is fresh; false otherwise +

+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/conditional_get.rb, line 94 + def request_fresh? + etag_matches?(self.etag) || not_modified?(self.last_modified) + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/test/helpers/controller_helper.rb + + lib/merb-core/test/helpers/cookie_jar.rb + + lib/merb-core/test/helpers/mock_request_helper.rb + + lib/merb-core/test/helpers/request_helper.rb + + lib/merb-core/test/helpers/route_helper.rb + + lib/merb-core/test/test_ext/rspec.rb + + lib/merb-core/test.rb + + + + + + + + + + + + + + + + + + + (&block) + + + +# File lib/merb-core/test/test_ext/rspec.rb, line 31 + def self.add_helpers(&block) + if Merb.test_framework == :rspec + ExampleGroup.class_eval(&block) + else + raise NotImplementedError + end + end + + + + + + + + + + + + + + + + + + + + + lib/merb-core/test/matchers.rb + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/test/helpers/request_helper.rb + + + + + + + + + + + + + + + + + + + (uri, env = {}) + + + +# File lib/merb-core/test/helpers/request_helper.rb, line 7 + def request(uri, env = {}) + uri = url(uri) if uri.is_a?(Symbol) + uri = URI(uri) + uri.scheme ||= "http" + uri.host ||= "example.org" + + if (env[:method] == "POST" || env["REQUEST_METHOD"] == "POST") + params = env.delete(:body_params) if env.key?(:body_params) + params = env.delete(:params) if env.key?(:params) && !env.key?(:input) + + unless env.key?(:input) + env[:input] = Merb::Parse.params_to_query_string(params) + env["CONTENT_TYPE"] = "application/x-www-form-urlencoded" + end + end + + if env[:params] + uri.query = [ + uri.query, Merb::Parse.params_to_query_string(env.delete(:params)) + ].compact.join("&") + end + + ignore_cookies = env.has_key?(:jar) && env[:jar].nil? + + unless ignore_cookies + # Setup a default cookie jar container + @__cookie_jar__ ||= Merb::Test::CookieJar.new + # Grab the cookie group name + jar = env.delete(:jar) || :default + # Set the cookie header with the cookies + env["HTTP_COOKIE"] = @__cookie_jar__.for(jar, uri) + end + + app = Merb::Rack::Application.new + rack = app.call(::Rack::MockRequest.env_for(uri.to_s, env)) + + rack = Struct.new(:status, :headers, :body, :url, :original_env). + new(rack[0], rack[1], rack[2], uri.to_s, env) + + @__cookie_jar__.update(jar, uri, rack.headers["Set-Cookie"]) unless ignore_cookies + + Merb::Dispatcher.work_queue.size.times do + Merb::Dispatcher.work_queue.pop.call + end + + rack + end + + + + + + + + + + + + + + + + + + + + + lib/merb-core/test/helpers/controller_helper.rb + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/test/test_ext/rspec.rb + + + + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/test/helpers.rb + + + + + + + +This is a place holder to allow plugins etc a place to include testing +helpers +

+ + ]]>
+ + + + + + + + + + + + + +
+ + + + + + + lib/merb-core/test/helpers/route_helper.rb + + + + + + + + + + + + + + + + + + + (path, method = :get, env = {}) + + Parameters + + + + +
path<~to_string>:The URL of the request. + +
method<~to_sym>:HTTP request method. + +
env<Hash>:Additional parameters for the request. + +
+

Returns

+ + +
Hash:A hash containing the controller and action along with any parameters + +
+ ]]>
+ + + +# File lib/merb-core/test/helpers/route_helper.rb, line 85 + def request_to(path, method = :get, env = {}) + env[:request_method] ||= method.to_s.upcase + env[:request_uri] = path + + check_request_for_route(build_request({}, env)) + end + + +
+ + + (*args) + + +Mimics the resource method available to controllers +

+

Paramaters

+ + + +
resources<Object>:The resources to generate URLs from + +
params<Hash>:Any extra parameters that are required. + +
+

Returns

+ + +
String:The generated URL. + +
+ ]]>
+ + + +# File lib/merb-core/test/helpers/route_helper.rb, line 73 + def resource(*args) + args << @request_params || {} + Merb::Router.resource(*args) + end + + +
+ + + (*args) + + +There are three possible ways to use this method. First, if you have a +named route, you can specify the route as the first parameter as a symbol +and any paramters in a hash. Second, you can generate the default route by +just passing the params hash, just passing the params hash. Finally, you +can use the anonymous parameters. This allows you to specify the parameters +to a named route in the order they appear in the router. +

+

Parameters(Named Route)

+ + + +
name<Symbol>:The name of the route. + +
args<Hash>:Parameters for the route generation. + +
+

Parameters(Default Route)

+ + +
args<Hash>:Parameters for the route generation. This route will use the default route. + +
+

Parameters(Anonymous Parameters)

+ + + +
name<Symbol>:The name of the route. + +
args<Array>:An array of anonymous parameters to generate the route with. These +parameters are assigned to the route parameters in the order that they are +passed. + +
+

Returns

+ + +
String:The generated URL. + +
+

Examples

+

+Named Route +

+

+Merb::Router.prepare do +

+
+  match("/articles/:title").to(:controller => :articles, :action => :show).name("articles")
+
+

+end +

+

+url(:articles, :title => "new_article") +

+

+Default Route +

+

+Merb::Router.prepare do +

+
+  default_routes
+
+

+end +

+

+url(:controller => "articles", :action => "new") +

+

+Anonymous Paramters +

+

+Merb::Router.prepare do +

+
+  match("/articles/:year/:month/:title").to(:controller => :articles, :action => :show).name("articles")
+
+

+end +

+

+url(:articles, 2008, 10, "test_article") +

+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/test/helpers/route_helper.rb, line 60 + def url(*args) + args << (@request_params || {}) + Merb::Router.url(*args) + end + + +
+ + +
+ + + + + + + + + + + +
+ +
+ + + + + + + lib/merb-core/test/matchers.rb + + + + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/test/matchers/controller_matchers.rb + + + + + + + + + + + + + + + + + + + (expected) + + + +# File lib/merb-core/test/matchers/controller_matchers.rb, line 55 + def be_error(expected) + BeError.new(expected) + end + + + + + + ( expected ) + + +Passes if the controller actually provides the target format +

+

Parameters

+ + +
expected<Symbol>:A format to check + +
+

Examples

+
+  ControllerClass.should provide( :html )
+  controller_instance.should provide( :xml )
+
+ ]]>
+ + + +# File lib/merb-core/test/matchers/controller_matchers.rb, line 105 + def provide( expected ) + Provide.new( expected ) + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/test/matchers/controller_matchers.rb + + + + + Object + + + + + + + + + + + + + + + + (expected) + + Parameters + + +
expected<Symbol>:A format to check + +
+ ]]>
+ + + +# File lib/merb-core/test/matchers/controller_matchers.rb, line 63 + def initialize(expected) + @expected = expected + end + + +
+ + +
+ + + + + + () + + Returns + + +
String:The failure message. + +
+ ]]>
+ + + +# File lib/merb-core/test/matchers/controller_matchers.rb, line 80 + def failure_message + "expected #{@target.name} to provide #{@expected}, but it doesn't" + end + + +
+ + + (target) + + Parameters + + +
target<Symbol>:A ControllerClass or controller_instance + +
+

Returns

+ + +
Boolean:True if the formats provided by the target controller/class include the +expected + +
+ ]]>
+ + + +# File lib/merb-core/test/matchers/controller_matchers.rb, line 73 + def matches?(target) + @target = target + provided_formats.include?( @expected ) + end + + +
+ + + () + + Returns + + +
String:The failure message to be displayed in negative matches. + +
+ ]]>
+ + + +# File lib/merb-core/test/matchers/controller_matchers.rb, line 86 + def negative_failure_message + "expected #{@target.name} not to provide #{@expected}, but it does" + end + + +
+ + + () + + Returns + + +
Array[Symbol]:The formats the expected provides + +
+ ]]>
+ + + +# File lib/merb-core/test/matchers/controller_matchers.rb, line 92 + def provided_formats + @target.class_provided_formats + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/test/matchers/controller_matchers.rb + + + + + Object + + + + + + + + + + + + + + + + (expected) + + + +# File lib/merb-core/test/matchers/controller_matchers.rb, line 35 + def initialize(expected) + @expected = expected + end + + + + + + + + + + + + () + + + +# File lib/merb-core/test/matchers/controller_matchers.rb, line 45 + def failure_message + "expected #{@target} to be a #{@expected} error, but it was " << + @target.request.exceptions.first.inspect + end + + + + + + (target) + + + +# File lib/merb-core/test/matchers/controller_matchers.rb, line 39 + def matches?(target) + @target = target + @target.request.exceptions && + @target.request.exceptions.first.is_a?(@expected) + end + + + + + + () + + + +# File lib/merb-core/test/matchers/controller_matchers.rb, line 50 + def negative_failure_message + "expected #{@target} not to be a #{@expected} error, but it was" + end + + + + + + + + + + + + + + + + + + + + + lib/merb-core/test/matchers/controller_matchers.rb + + + + + Object + + + + + + + + + + + + + + + + () + + Returns + + +
String:The failure message. + +
+ ]]>
+ + + +# File lib/merb-core/test/matchers/controller_matchers.rb, line 17 + def failure_message + "expected#{inspect_target} to redirect" + end + + +
+ + + () + + Returns + + +
String:The controller and action name. + +
+ ]]>
+ + + +# File lib/merb-core/test/matchers/controller_matchers.rb, line 29 + def inspect_target + " #{@target.controller_name}##{@target.action_name}" if @target.respond_to?(:controller_name) && @target.respond_to?(:action_name) + end + + +
+ + + (target) + + Parameters + + +
target<Fixnum, ~status>:Either the status code or a controller with a status code. + +
+

Returns

+ + +
Boolean:True if the status code is in the range 300..305 or 307. + +
+ ]]>
+ + + +# File lib/merb-core/test/matchers/controller_matchers.rb, line 10 + def matches?(target) + @target = target + [307, *(300..305)].include?(target.respond_to?(:status) ? target.status : target) + end + + +
+ + + () + + Returns + + +
String:The failure message to be displayed in negative matches. + +
+ ]]>
+ + + +# File lib/merb-core/test/matchers/controller_matchers.rb, line 23 + def negative_failure_message + "expected#{inspect_target} not to redirect" + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/test/matchers/route_matchers.rb + + + + + + + + + + + + + + + + + + + (klass_or_name, action) + + +Passes when the actual route parameters match the expected controller class +and controller action. Exposes a with method for specifying +parameters. +

+

Parameters

+ + + +
klass_or_name<Class, String>:The controller class or class name to match routes for. + +
action<~to_s>:The name of the action to match routes for. + +
+

Example

+
+  # Passes if a GET request to "/" is routed to the Widgets controller's
+  # index action.
+  request_to("/", :get).should route_to(Widgets, :index)
+
+  # Use the 'with' method for parameter checks
+  request_to("/123").should route_to(widgets, :show).with(:id => "123")
+
+ ]]>
+ + + +# File lib/merb-core/test/matchers/route_matchers.rb, line 134 + def route_to(klass_or_name, action) + RouteToMatcher.new(klass_or_name, action) + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/test/matchers/route_matchers.rb + + + + + Object + + + + + + + + + + + + + + + + (klass_or_name, action) + + Parameters + + + +
klass_or_name<Class, String>:The controller class or class name to match routes for. + +
action<~to_s>:The name of the action to match routes for. + +
+ ]]>
+ + + +# File lib/merb-core/test/matchers/route_matchers.rb, line 9 + def initialize(klass_or_name, action) + @expected_controller = Class === klass_or_name ? klass_or_name.name : klass_or_name + @expected_action = action.to_s + end + + +
+ + +
+ + + + + + () + + + +# File lib/merb-core/test/matchers/route_matchers.rb, line 72 + def actual_parameters_message + " with #{(@parameter_matcher.actual || {}).inspect}" if @parameter_matcher + end + + + + + + () + + + +# File lib/merb-core/test/matchers/route_matchers.rb, line 68 + def expected_parameters_message + " with #{@parameter_matcher.expected.inspect}" if @parameter_matcher + end + + + + + + () + + Returns + + +
String:The failure message. + +
+ ]]>
+ + + +# File lib/merb-core/test/matchers/route_matchers.rb, line 58 + def failure_message + "expected the request to route to #{@expected_controller.to_const_string}##{@expected_action}#{expected_parameters_message}, but was #{@target_controller.to_const_string}##{@target_action}#{actual_parameters_message}" + end + + +
+ + + (target) + + Parameters + + +
target<Hash>:The route parameters to match. + +
+

Returns

+ + +
Boolean:True if the parameter matcher created with with +matches or if no parameter matcher exists. + +
+ ]]>
+ + + +# File lib/merb-core/test/matchers/route_matchers.rb, line 35 + def match_parameters(target) + @parameter_matcher.nil? ? true : @parameter_matcher.matches?(target) + end + + +
+ + + (target) + + Parameters + + +
target<Hash>:The route parameters to match. + +
+

Returns

+ + +
Boolean:True if the controller action and parameters match. + +
+ ]]>
+ + + +# File lib/merb-core/test/matchers/route_matchers.rb, line 19 + def matches?(target) + @target_env = target.dup + @target_controller, @target_action = @target_env.delete(:controller).to_s, @target_env.delete(:action).to_s + + @target_controller = "#{target.delete(:namespace)}::#{@target_controller}" if target.has_key?(:namespace) + + @expected_controller.snake_case == @target_controller.snake_case && @expected_action == @target_action && match_parameters(@target_env) + end + + +
+ + + () + + Returns + + +
String:The failure message to be displayed in negative matches. + +
+ ]]>
+ + + +# File lib/merb-core/test/matchers/route_matchers.rb, line 64 + def negative_failure_message + "expected the request not to route to #{@expected_controller.camel_case}##{@expected_action}#{expected_parameters_message}, but it did" + end + + +
+ + + (parameters) + + +Creates a new paramter matcher. +

+

Parameters

+ + +
parameters<Hash, ~to_param>:The parameters to match. + +
+

Returns

+ + +
RouteToMatcher:This matcher. + +
+

Alternatives

+

+If parameters is an object, then a new expected hash will be constructed +with the key :id set to parameters.to_param. +

+ ]]>
+ + + +# File lib/merb-core/test/matchers/route_matchers.rb, line 50 + def with(parameters) + @parameter_matcher = ParameterMatcher.new(parameters) + + self + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/test/matchers/route_matchers.rb + + + + + Object + + + + + + + + + + + + + + RW + + + + + + + RW + + + + + + + + + + + + + (hash_or_object) + + Parameters + + +
hash_or_object<Hash, ~to_param>:The parameters to match. + +
+

Alternatives

+

+If hash_or_object is an object, then a new expected hash will be +constructed with the key :id set to hash_or_object.to_param. +

+ ]]>
+ + + +# File lib/merb-core/test/matchers/route_matchers.rb, line 86 + def initialize(hash_or_object) + @expected = {} + case hash_or_object + when Hash then @expected = hash_or_object + else @expected[:id] = hash_or_object.to_param + end + end + + +
+ + +
+ + + + + + () + + Returns + + +
String:The failure message. + +
+ ]]>
+ + + +# File lib/merb-core/test/matchers/route_matchers.rb, line 108 + def failure_message + "expected the route to contain parameters #{@expected.inspect}, but instead contained #{@actual.inspect}" + end + + +
+ + + (parameter_hash) + + Parameters + + +
parameter_hash<Hash>:The route parameters to match. + +
+

Returns

+ + +
Boolean:True if the route parameters match the expected ones. + +
+ ]]>
+ + + +# File lib/merb-core/test/matchers/route_matchers.rb, line 99 + def matches?(parameter_hash) + @actual = parameter_hash.dup.except(:controller, :action) + + return @actual.empty? if @expected.empty? + @expected.all? {|(k, v)| @actual.has_key?(k) && @actual[k] == v} + end + + +
+ + + () + + Returns + + +
String:The failure message to be displayed in negative matches. + +
+ ]]>
+ + + +# File lib/merb-core/test/matchers/route_matchers.rb, line 114 + def negative_failure_message + "expected the route not to contain parameters #{@expected.inspect}, but it did" + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/test/helpers/mock_request_helper.rb + + lib/merb-core/test/helpers/request_helper.rb + + + + + + + + + + + + + + + + + + + (params = {}, env = {}) + + +Prepares and returns a request suitable for dispatching with +dispatch_request. If you don’t need to modify the request object +before dispatching (e.g. to add cookies), you probably want to use dispatch_to instead. +

+

Parameters

+ + + +
params<Hash>:An optional hash that will end up as params in the controller instance. + +
env<Hash>:An optional hash that is passed to the fake request. Any request options +should go here (see fake_request), +including :req or :post_body for setting the request body itself. + +
+

Example

+
+  req = build_request(:id => 1)
+  req.cookies['app_cookie'] = "testing"
+  dispatch_request(req, MyController, :edit)
+
+

Notes

+

+Does not use routes. +

+

+:api: public @deprecated +

+ ]]>
+ + + +# File lib/merb-core/test/helpers/mock_request_helper.rb, line 212 + def build_request(params = {}, env = {}) + params = Merb::Parse.params_to_query_string(params) + + query_string = env[:query_string] || env['QUERY_STRING'] + env[:query_string] = query_string ? "#{query_string}&#{params}" : params + + post_body = env[:post_body] || env['POST_BODY'] + fake_request(env, { :post_body => post_body, :req => env[:req] }) + end + + +
+ + + (request) + + +Checks to see that a request is routable. +

+

Parameters

+ + +
request<Merb::Test::RequestHelper::FakeRequest, Merb::Request>:The request object to inspect. + +
+

Raises

+ + +
Merb::ControllerExceptions::BadRequest:No matching route was found. + +
+

Returns

+ + +
Hash:The parameters built based on the matching route. + +
+

+:api: plugin @deprecated +

+ ]]>
+ + + +# File lib/merb-core/test/helpers/mock_request_helper.rb, line 390 + def check_request_for_route(request) + match = ::Merb::Router.match(request) + if match[0].nil? && match[1].empty? + raise ::Merb::ControllerExceptions::BadRequest, "No routes match the request. Request uri: #{request.uri}" + else + match[1] + end + end + + +
+ + + (path, params = {}, env = {}, &block) + + +An HTTP DELETE request that operates through the router +

+

Parameters

+ + + + + +
path<String>:The path that should go to the router as the request uri. + +
params<Hash>:An optional hash that will end up as params in the controller instance. + +
env<Hash>:An optional hash that is passed to the fake request. Any request options +should go here (see fake_request). + +
&blk:The controller is yielded to the block provided for actions prior to +the action being dispatched. + +
+

+:api: public @deprecated +

+ ]]>
+ + + +# File lib/merb-core/test/helpers/mock_request_helper.rb, line 296 + def delete(path, params = {}, env = {}, &block) + env[:request_method] = "DELETE" + mock_request(path, params, env, &block) + end + + +
+ + + (input) + + + +# File lib/merb-core/test/helpers/request_helper.rb, line 63 + def describe_input(input) + if input.respond_to?(:controller_name) + "#{input.controller_name}##{input.action_name}" + elsif input.respond_to?(:original_env) + describe_request(input) + else + input + end + end + + + + + + (rack) + + + +# File lib/merb-core/test/helpers/request_helper.rb, line 59 + def describe_request(rack) + "a #{rack.original_env[:method] || rack.original_env["REQUEST_METHOD"] || "GET"} to '#{rack.url}'" + end + + + + + + (request, controller_klass, action) {|controller if block_given?| ...} + + +The workhorse for the dispatch*to helpers. +

+

Parameters

+ + + + + +
request<Merb::Test::RequestHelper::FakeRequest, Merb::Request>:A request object that has been setup for testing. + +
controller_klass<Merb::Controller>:The class object off the controller to dispatch the action to. + +
action<Symbol>:The action to dispatch the request to. + +
&blk:The controller is yielded to the block provided for actions prior to +the action being dispatched. + +
+

Returns

+

+An instance of controller_klass based on the parameters. +

+

Notes

+

+Does not use routes. +

+

+:api: public @deprecated +

+ ]]>
+ + + +# File lib/merb-core/test/helpers/mock_request_helper.rb, line 364 + def dispatch_request(request, controller_klass, action, &blk) + controller = controller_klass.new(request) + yield controller if block_given? + controller._dispatch(action) + + Merb.logger.info controller._benchmarks.inspect + Merb.logger.flush + + controller + end + + +
+ + + (controller_klass, action, params = {}, env = {}, &blk) + + +Dispatches an action to the given class. This bypasses the router and is +suitable for unit testing of controllers. +

+

Parameters

+ + + + + + +
controller_klass<Controller>:The controller class object that the action should be dispatched to. + +
action<Symbol>:The action name, as a symbol. + +
params<Hash>:An optional hash that will end up as params in the controller instance. + +
env<Hash>:An optional hash that is passed to the fake request. Any request options +should go here (see fake_request), +including :req or :post_body for setting the request body itself. + +
&blk:The controller is yielded to the block provided for actions prior to +the action being dispatched. + +
+

Example

+
+  dispatch_to(MyController, :create, :name => 'Homer' ) do |controller|
+    controller.stub!(:current_user).and_return(@user)
+  end
+
+

Notes

+

+Does not use routes. +

+

+:api: public @deprecated +

+ ]]>
+ + + +# File lib/merb-core/test/helpers/mock_request_helper.rb, line 116 + def dispatch_to(controller_klass, action, params = {}, env = {}, &blk) + params = merge_controller_and_action(controller_klass, action, params) + dispatch_request(build_request(params, env), controller_klass, action.to_s, &blk) + end + + +
+ + + (controller_klass, action, username, password, params = {}, env = {}, &blk) + + +Dispatches an action to the given class and using HTTP Basic Authentication +This bypasses the router and is suitable for unit testing of controllers. +

+

Parameters

+ + + + + + + + +
controller_klass<Controller>:The controller class object that the action should be dispatched to. + +
action<Symbol>:The action name, as a symbol. + +
username<String>:The username. + +
password<String>:The password. + +
params<Hash>:An optional hash that will end up as params in the controller instance. + +
env<Hash>:An optional hash that is passed to the fake request. Any request options +should go here (see fake_request), +including :req or :post_body for setting the request body itself. + +
&blk:The controller is yielded to the block provided for actions prior to +the action being dispatched. + +
+

Example

+
+  dispatch_with_basic_authentication_to(MyController, :create, 'Fred', 'secret', :name => 'Homer' ) do |controller|
+    controller.stub!(:current_user).and_return(@user)
+  end
+
+

Notes

+

+Does not use routes. +

+

+:api: public @deprecated +

+ ]]>
+ + + +# File lib/merb-core/test/helpers/mock_request_helper.rb, line 174 + def dispatch_with_basic_authentication_to(controller_klass, action, username, password, params = {}, env = {}, &blk) + env["X_HTTP_AUTHORIZATION"] = "Basic #{Base64.encode64("#{username}:#{password}")}" + + params = merge_controller_and_action(controller_klass, action, params) + dispatch_request(build_request(params, env), controller_klass, action.to_s, &blk) + end + + +
+ + + (env = {}, opt = {}) + + Parameters + + + +
env<Hash>:A hash of environment keys to be merged into the default list. + +
opt<Hash>:A hash of options (see below). + +
+

Options (opt)

+ + + +
:post_body<String>:The post body for the request. + +
:req<String>:The request string. This will only be used if :post_body is left out. + +
+

Returns

+ + +
FakeRequest:A Request object that is built based on the +parameters. + +
+

Notes

+

+If you pass a post body, the content-type will be set to URL-encoded. +

+

+:api: public @deprecated +

+ ]]>
+ + + +# File lib/merb-core/test/helpers/mock_request_helper.rb, line 79 + def fake_request(env = {}, opt = {}) + if opt[:post_body] + req = opt[:post_body] + env[:content_type] ||= "application/x-www-form-urlencoded" + else + req = opt[:req] + end + FakeRequest.new(env, StringIO.new(req || '')) + end + + +
+ + + (path, params = {}, env = {}, &block) + + +An HTTP GET request that operates through the router. +

+

Parameters

+ + + + + +
path<String>:The path that should go to the router as the request uri. + +
params<Hash>:An optional hash that will end up as params in the controller instance. + +
env<Hash>:An optional hash that is passed to the fake request. Any request options +should go here (see fake_request). + +
&blk:The controller is yielded to the block provided for actions prior to +the action being dispatched. + +
+

+:api: public @deprecated +

+ ]]>
+ + + +# File lib/merb-core/test/helpers/mock_request_helper.rb, line 237 + def get(path, params = {}, env = {}, &block) + env[:request_method] = "GET" + mock_request(path, params, env, &block) + end + + +
+ + + (controller_klass, action, params) + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/test/helpers/mock_request_helper.rb, line 182 + def merge_controller_and_action(controller_klass, action, params) + params[:controller] = controller_klass.name.to_const_path + params[:action] = action.to_s + + params + end + + +
+ + + (path, params = {}, env= {}, &block) + + +A generic request that checks the router for the controller and action. +This request goes through the Merb::Router and +finishes at the controller. +

+

Parameters

+ + + + + +
path<String>:The path that should go to the router as the request uri. + +
params<Hash>:An optional hash that will end up as params in the controller instance. + +
env<Hash>:An optional hash that is passed to the fake request. Any request options +should go here (see fake_request). + +
&blk:The controller is yielded to the block provided for actions prior to +the action being dispatched. + +
+

Example

+
+  request(path, { :name => 'Homer' }, { :request_method => "PUT" }) do |controller|
+    controller.stub!(:current_user).and_return(@user)
+  end
+
+

Notes

+

+Uses Routes. +

+

+:api: plugin @deprecated +

+ ]]>
+ + + +# File lib/merb-core/test/helpers/mock_request_helper.rb, line 325 + def mock_request(path, params = {}, env= {}, &block) + env[:request_method] ||= "GET" + env[:request_uri], env[:query_string] = path.split('?') + + multipart = env.delete(:test_with_multipart) + + request = build_request(params, env) + + opts = check_request_for_route(request) # Check that the request will be routed correctly + controller_name = (opts[:namespace] ? opts.delete(:namespace) + '/' : '') + opts.delete(:controller) + klass = Object.full_const_get(controller_name.snake_case.to_const_string) + + action = opts.delete(:action).to_s + params.merge!(opts) + + multipart.nil? ? dispatch_to(klass, action, params, env, &block) : dispatch_multipart_to(klass, action, params, env, &block) + end + + +
+ + + (path, params = {}, env = {}, &block) + + +An HTTP POST request that operates through the router. +

+

Parameters

+ + + + + +
path<String>:The path that should go to the router as the request uri. + +
params<Hash>:An optional hash that will end up as params in the controller instance. + +
env<Hash>:An optional hash that is passed to the fake request. Any request options +should go here (see fake_request). + +
&blk:The controller is yielded to the block provided for actions prior to +the action being dispatched. + +
+

+:api: public @deprecated +

+ ]]>
+ + + +# File lib/merb-core/test/helpers/mock_request_helper.rb, line 257 + def post(path, params = {}, env = {}, &block) + env[:request_method] = "POST" + mock_request(path, params, env, &block) + end + + +
+ + + (path, params = {}, env = {}, &block) + + +An HTTP PUT request that operates through the router. +

+

Parameters

+ + + + + +
path<String>:The path that should go to the router as the request uri. + +
params<Hash>:An optional hash that will end up as params in the controller instance. + +
env<Hash>:An optional hash that is passed to the fake request. Any request options +should go here (see fake_request). + +
&blk:The controller is yielded to the block provided for actions prior to +the action being dispatched. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/test/helpers/mock_request_helper.rb, line 276 + def put(path, params = {}, env = {}, &block) + env[:request_method] = "PUT" + mock_request(path, params, env, &block) + end + + +
+ + + (*args) + + + +# File lib/merb-core/test/helpers/request_helper.rb, line 77 + def requesting(*args) request(*args) end + + + + + + (*args) + + + +# File lib/merb-core/test/helpers/request_helper.rb, line 78 + def response_for(*args) request(*args) end + + + + + + (input) + + + +# File lib/merb-core/test/helpers/request_helper.rb, line 73 + def status_code(input) + input.respond_to?(:status) ? input.status : input + end + + + + + + (*controller_classes, &blk) + + +Keep track of cookie values in CookieJar within the +context of the block; you need to set this up for secific controllers. +

+

Parameters

+ + + +
*controller_classes:Controller classes to operate on in the +context of the block. + +
&blk:The context to operate on; optionally accepts the cookie jar as an +argument. + +
+

+:api: public @deprecated +

+ ]]>
+ + + +# File lib/merb-core/test/helpers/mock_request_helper.rb, line 130 + def with_cookies(*controller_classes, &blk) + cookie_jar = CookieJar.new + before_cb = lambda { |c| c.cookies.update(cookie_jar) } + after_cb = lambda { |c| cookie_jar.update_from_request(c.request) } + controller_classes.each do |klass| + klass._before_dispatch_callbacks << before_cb + klass._after_dispatch_callbacks << after_cb + end + blk.arity == 1 ? blk.call(cookie_jar) : blk.call + controller_classes.each do |klass| + klass._before_dispatch_callbacks.delete before_cb + klass._after_dispatch_callbacks.delete after_cb + end + end + + +
+ + +
+ + + + + + + + + + + +
+ +
+ + + + + + + lib/merb-core/test/helpers/mock_request_helper.rb + + + + + Mash + + + + +CookieJar keeps track +of cookies in a simple Mash. +

+ + ]]>
+ + + + + + + + + + + + + + (request) + + Parameters + + +
request<Merb::Request, Merb::FakeRequest>:The controller request. + +
+ ]]>
+ + + +# File lib/merb-core/test/helpers/mock_request_helper.rb, line 50 + def update_from_request(request) + request.cookies.each do |key, value| + if value.blank? + self.delete(key) + else + self[key] = Merb::Parse.unescape(value) + end + end + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/test/helpers/mock_request_helper.rb + + + + + Merb::Request + + + + +FakeRequest sets up a +default enviroment which can be overridden either by passing and env into +initialize or using request[‘HTTP_VAR’] = ‘foo’ +

+ + ]]>
+ + + + + + + + + + + Mash.new({ 'SERVER_NAME' => 'localhost', 'PATH_INFO' => '/', 'HTTP_ACCEPT_ENCODING' => 'gzip,deflate', 'HTTP_USER_AGENT' => 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8.0.1) Gecko/20060214 Camino/1.0', 'SCRIPT_NAME' => '/', 'SERVER_PROTOCOL' => 'HTTP/1.1', 'HTTP_CACHE_CONTROL' => 'max-age=0', 'HTTP_ACCEPT_LANGUAGE' => 'en,ja;q=0.9,fr;q=0.9,de;q=0.8,es;q=0.7,it;q=0.7,nl;q=0.6,sv;q=0.5,nb;q=0.5,da;q=0.4,fi;q=0.3,pt;q=0.3,zh-Hans;q=0.2,zh-Hant;q=0.1,ko;q=0.1', 'HTTP_HOST' => 'localhost', 'REMOTE_ADDR' => '127.0.0.1', 'SERVER_SOFTWARE' => 'Mongrel 1.1', 'HTTP_KEEP_ALIVE' => '300', 'HTTP_REFERER' => 'http://localhost/', 'HTTP_ACCEPT_CHARSET' => 'ISO-8859-1,utf-8;q=0.7,*;q=0.7', 'HTTP_VERSION' => 'HTTP/1.1', 'REQUEST_URI' => '/', 'SERVER_PORT' => '80', 'GATEWAY_INTERFACE' => 'CGI/1.2', 'HTTP_ACCEPT' => 'text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5', 'HTTP_CONNECTION' => 'keep-alive', 'REQUEST_METHOD' => 'GET' }) unless defined?(DEFAULT_ENV) + + + + + + + + + + + + + + (env = {}, req = StringIO.new) + + Parameters + + + +
env<Hash>:Environment options that override the defaults. + +
req<StringIO>:The request to set as input for Rack. + +
+ ]]>
+ + + +# File lib/merb-core/test/helpers/mock_request_helper.rb, line 13 + def initialize(env = {}, req = StringIO.new) + env.environmentize_keys! + env['rack.input'] = req + super(DEFAULT_ENV.merge(env)) + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/test/helpers/multipart_request_helper.rb + + + + + + + + + + + + + + + + + + + (controller_klass, action, params = {}, env = {}, &blk) + + + Similar to dispatch_to but allows for sending files inside params. + + ==== Paramters + controller_klass<Controller>:: + The controller class object that the action should be dispatched to. + action<Symbol>:: The action name, as a symbol. + params<Hash>:: + An optional hash that will end up as params in the controller instance. + env<Hash>:: + An optional hash that is passed to the fake request. Any request options + should go here (see +fake_request+). + &blk:: The block is executed in the context of the controller. + + ==== Example + dispatch_multipart_to(MyController, :create, :my_file => @a_file ) do |controller| + controller.stub!(:current_user).and_return(@user) + end + + ==== Notes + Set your option to contain a file object to simulate file uploads. + + Does not use routes. + +
+ @api public
+
+ ]]>
+ + + +# File lib/merb-core/test/helpers/multipart_request_helper.rb, line 111 + def dispatch_multipart_to(controller_klass, action, params = {}, env = {}, &blk) + request = multipart_fake_request(env, params) + dispatch_request(request, controller_klass, action, &blk) + end + + +
+ + + (env = {}, params = {}) + + Parameters + + + +
env<Hash>:An optional hash that is passed to the fake request. Any request options +should go here (see fake_request). + +
params<Hash>:An optional hash that will end up as params in the controller instance. + +
+

Returns

+ + +
FakeRequest:A multipart Request object that is built based +on the parameters. + +
+ ]]>
+ + + +# File lib/merb-core/test/helpers/multipart_request_helper.rb, line 166 + def multipart_fake_request(env = {}, params = {}) + if params.empty? + fake_request(env) + else + m = Post.new(params) + body, head = m.to_multipart + fake_request(env.merge( :content_type => head, + :content_length => body.length), :post_body => body) + end + end + + +
+ + + (path, params = {}, env = {}, &block) + + +An HTTP POST request that operates through the router and uses multipart +parameters. +

+

Parameters

+ + + + + +
path<String>:The path that should go to the router as the request uri. + +
params<Hash>:An optional hash that will end up as params in the controller instance. + +
env<Hash>:An optional hash that is passed to the fake request. Any request options +should go here (see fake_request). + +
block<Proc>:The block is executed in the context of the controller. + +
+

Notes

+

+To include an uploaded file, put a file object as a value in params. +

+ ]]>
+ + + +# File lib/merb-core/test/helpers/multipart_request_helper.rb, line 130 + def multipart_post(path, params = {}, env = {}, &block) + env[:request_method] = "POST" + env[:test_with_multipart] = true + mock_request(path, params, env, &block) + end + + +
+ + + (path, params = {}, env = {}, &block) + + +An HTTP PUT request that operates through the router and uses multipart +parameters. +

+

Parameters

+ + + + + +
path<String>:The path that should go to the router as the request uri. + +
params<Hash>:An optional hash that will end up as params in the controller instance. + +
env<Hash>:An optional hash that is passed to the fake request. Any request options +should go here (see fake_request). + +
block<Proc>:The block is executed in the context of the controller. + +
+

Notes

+

+To include an uplaoded file, put a file object as a value in params. +

+ ]]>
+ + + +# File lib/merb-core/test/helpers/multipart_request_helper.rb, line 150 + def multipart_put(path, params = {}, env = {}, &block) + env[:request_method] = "PUT" + env[:test_with_multipart] = true + mock_request(path, params, env, &block) + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/test/helpers/multipart_request_helper.rb + + + + + Object + + + + + + + + + + + + + + RW + + + + + + + RW + + + + + + + + + + + + + (key, value) + + Parameters + + + +
key<~to_s>:The parameter key. + +
value<~to_s>:The parameter value. + +
+ ]]>
+ + + +# File lib/merb-core/test/helpers/multipart_request_helper.rb, line 12 + def initialize(key, value) + @key = key + @value = value + end + + +
+ + +
+ + + + + + () + + Returns + + +
String:The parameter in a form suitable for a multipart request. + +
+ ]]>
+ + + +# File lib/merb-core/test/helpers/multipart_request_helper.rb, line 19 + def to_multipart + return %(Content-Disposition: form-data; name="#{key}"\r\n\r\n#{value}\r\n) + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/test/helpers/multipart_request_helper.rb + + + + + Object + + + + + + + + + + + + + '----------0xKhTmLbOuNdArY' + + + + + + + "multipart/form-data, boundary=" + BOUNDARY + + + + + + + + + + + + + + (params = {}) + + Parameters + + +
params<Hash>:Optional params for the controller. + +
+ ]]>
+ + + +# File lib/merb-core/test/helpers/multipart_request_helper.rb, line 51 + def initialize(params = {}) + @multipart_params = [] + push_params(params) + end + + +
+ + +
+ + + + + + (params, prefix = nil) + + +Saves the params in an array of multipart params as Param and FileParam +objects. +

+

Parameters

+ + + +
params<Hash>:The params to add to the multipart params. + +
prefix<~to_s>:An optional prefix for the request string keys. + +
+ ]]>
+ + + +# File lib/merb-core/test/helpers/multipart_request_helper.rb, line 62 + def push_params(params, prefix = nil) + params.sort_by {|k| k.to_s}.each do |key, value| + param_key = prefix.nil? ? key : "#{prefix}[#{key}]" + if value.respond_to?(:read) + @multipart_params << FileParam.new(param_key, value.path, value.read) + else + if value.is_a?(Hash) || value.is_a?(Mash) + value.keys.each do |k| + push_params(value, param_key) + end + else + @multipart_params << Param.new(param_key, value) + end + end + end + end + + +
+ + + () + + Returns + + +
Array[String, String]:The query and the content type. + +
+ ]]>
+ + + +# File lib/merb-core/test/helpers/multipart_request_helper.rb, line 81 + def to_multipart + query = @multipart_params.collect { |param| "--" + BOUNDARY + "\r\n" + param.to_multipart }.join("") + "--" + BOUNDARY + "--" + return query, CONTENT_TYPE + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/test/helpers/multipart_request_helper.rb + + + + + Object + + + + + + + + + + + + + + RW + + + + + + + RW + + + + + + + RW + + + + + + + + + + + + + (key, filename, content) + + Parameters + + + + +
key<~to_s>:The parameter key. + +
filename<~to_s>:Name of the file for this parameter. + +
content<~to_s>:Content of the file for this parameter. + +
+ ]]>
+ + + +# File lib/merb-core/test/helpers/multipart_request_helper.rb, line 31 + def initialize(key, filename, content) + @key = key + @filename = filename + @content = content + end + + +
+ + +
+ + + + + + () + + Returns + + +
String:The file parameter in a form suitable for a multipart request. + +
+ ]]>
+ + + +# File lib/merb-core/test/helpers/multipart_request_helper.rb, line 40 + def to_multipart + return %(Content-Disposition: form-data; name="#{key}"; filename="#{filename}"\r\n) + "Content-Type: #{MIME::Types.type_for(@filename)}\r\n\r\n" + content + "\r\n" + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/test/helpers/cookie_jar.rb + + + + + Object + + + + + + + + + + + + + + + + () + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/test/helpers/cookie_jar.rb, line 75 + def initialize + @jars = {} + end + + +
+ + +
+ + + + + + (jar, uri) + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/test/helpers/cookie_jar.rb, line 102 + def for(jar, uri) + cookies = {} + + @jars[jar] ||= [] + # The cookies are sorted by most specific first. So, we loop through + # all the cookies in order and add it to a hash by cookie name if + # the cookie can be sent to the current URI. It's added to the hash + # so that when we are done, the cookies will be unique by name and + # we'll have grabbed the most specific to the URI. + @jars[jar].each do |cookie| + cookies[cookie.name] = cookie.raw if cookie.matches?(uri) + end + + cookies.values.join + end + + +
+ + + (jar, uri, raw_cookies) + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/test/helpers/cookie_jar.rb, line 80 + def update(jar, uri, raw_cookies) + return unless raw_cookies + # Initialize all the the received cookies + cookies = [] + raw_cookies.each do |raw| + c = Cookie.new(raw, uri.host) + cookies << c if c.valid?(uri) + end + + @jars[jar] ||= [] + + # Remove all the cookies that will be updated + @jars[jar].delete_if do |existing| + cookies.find { |c| [c.name, c.domain, c.path] == [existing.name, existing.domain, existing.path] } + end + + @jars[jar].concat cookies + + @jars[jar].sort! + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/test/test_ext/rspec.rb + + + + + Spec::Example::ExampleGroup + + + + + + + + + + + + + + + + (*args, &example_group_block) + + +This is a copy of the method in rspec, so we can have describe +"…", :when => "logged in", and the like +

+ ]]>
+ + + +# File lib/merb-core/test/test_ext/rspec.rb, line 51 + def describe(*args, &example_group_block) + params = args.last.is_a?(Hash) ? args.last : {} + if example_group_block + ret = super(params[:given]) do + it_should_behave_like params[:given] if params[:given] + super(*args, &example_group_block) + end + params[:given] = params[:when] || params[:given] + end + end + + +
+ + + (*args, &example_group_block) + + + +# File lib/merb-core/test/test_ext/rspec.rb, line 63 + def given(*args, &example_group_block) + args << {} unless Hash === args.last + params = args.last + + params[:shared] = true + + describe(*args, &example_group_block) + end + + + + + +
+ + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + lib/merb-core/test/helpers/cookie_jar.rb + + + + + Object + + + + + + + + + + + + + + R + + + + + + + R + + + + + + + + + + + + + (raw, default_host) + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/test/helpers/cookie_jar.rb, line 11 + def initialize(raw, default_host) + # separate the name / value pair from the cookie options + @name_value_raw, options = raw.split(/[;,] */n, 2) + + @name, @value = Merb::Parse.query(@name_value_raw, ';').to_a.first + @options = Merb::Parse.query(options, ';') + + @options.delete_if { |k, v| !v || v.empty? } + + @options["domain"] ||= default_host + end + + +
+ + +
+ + + + + + (other) + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/test/helpers/cookie_jar.rb, line 65 + def <=>(other) + # Orders the cookies from least specific to most + [name, path, domain.reverse] <=> [other.name, other.path, other.domain.reverse] + end + + +
+ + + () + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/test/helpers/cookie_jar.rb, line 34 + def domain + @options["domain"] + end + + +
+ + + () + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/test/helpers/cookie_jar.rb, line 29 + def empty? + @value.nil? || @value.empty? + end + + +
+ + + () + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/test/helpers/cookie_jar.rb, line 49 + def expired? + expires && expires < Time.now + end + + +
+ + + () + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/test/helpers/cookie_jar.rb, line 44 + def expires + Time.parse(@options["expires"]) if @options["expires"] + end + + +
+ + + (uri) + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/test/helpers/cookie_jar.rb, line 60 + def matches?(uri) + ! expired? && valid?(uri) + end + + +
+ + + () + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/test/helpers/cookie_jar.rb, line 39 + def path + @options["path"] || "/" + end + + +
+ + + () + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/test/helpers/cookie_jar.rb, line 24 + def raw + @name_value_raw + end + + +
+ + + (uri) + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/test/helpers/cookie_jar.rb, line 54 + def valid?(uri) + uri.host =~ Regexp.new("#{Regexp.escape(domain)}$") && + uri.path =~ Regexp.new("^#{Regexp.escape(path)}") + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/dispatch/cookies.rb + + + + + + + + + + + + + + + + + + + (base) + + + +# File lib/merb-core/dispatch/cookies.rb, line 93 + def self.included(base) + # Allow per-controller default cookie domains (see callback below) + base.class_inheritable_accessor :_default_cookie_domain + base._default_cookie_domain = Merb::Config[:default_cookie_domain] + + # Add a callback to enable Set-Cookie headers + base._after_dispatch_callbacks << lambda do |c| + headers = c.request.cookies.extract_headers("domain" => c._default_cookie_domain) + c.headers.update(headers) + end + end + + + + + + + + + + + + () + + Returns + + +
Merb::Cookies:A new Merb::Cookies instance representing the +cookies that came in from the request object + +
+

Notes

+

+Headers are passed into the cookie object so that you can do: +

+
+  cookies[:foo] = "bar"
+
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/cookies.rb, line 115 + def cookies + request.cookies + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/dispatch/cookies.rb + + + + + + + + + + + + + + + + + + + () + + Returns + + +
Hash:The cookies for this request. + +
+

Notes

+

+If a method default_cookies is defined it will be called. This can be used +for session fixation purposes for example. The method returns a Hash of key => value pairs. +

+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/cookies.rb, line 130 + def cookies + @cookies ||= begin + values = Merb::Parse.query(@env[Merb::Const::HTTP_COOKIE], ';,') + cookies = Merb::Cookies.new(values) + cookies.update(default_cookies) if respond_to?(:default_cookies) + cookies + end + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/dispatch/request_parsers.rb + + + + + + + + + + + + + + + + /Content-Disposition:.* name="?([^\";]*)"?/ni.freeze + + + + + + + /Content-Type: (.*)\r\n/ni.freeze + + + + + + + /Content-Disposition:.* filename="?([^\";]*)"?/ni.freeze + + + + + + + "\r\n".freeze + + + + + + + CRLF + + + + + + + + + + + + + + (s) + + Parameters + + +
s<String>:String to URL escape. + +
+

returns

+ + +
String:The escaped string. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/request_parsers.rb, line 178 + def self.escape(s) + s.to_s.gsub(/([^ a-zA-Z0-9_.-]+)/n) { + '%'+$1.unpack('H2'*$1.size).join('%').upcase + }.tr(' ', '+') + end + + +
+ + + (request, boundary, content_length) + + Parameters + + + + +
request<IO>:The raw request. + +
boundary<String>:The boundary string. + +
content_length<Fixnum>:The length of the content. + +
+

Raises

+ + +
ControllerExceptions::MultiPartParseError:Failed to parse request. + +
+

Returns

+ + +
Hash:The parsed request. + +
+

+:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/dispatch/request_parsers.rb, line 49 + def self.multipart(request, boundary, content_length) + boundary = "--#{boundary}" + paramhsh = {} + buf = "" + input = request + input.binmode if defined? input.binmode + boundary_size = boundary.size + EOL.size + bufsize = 16384 + content_length -= boundary_size + # status is boundary delimiter line + status = input.read(boundary_size) + return {} if status == nil || status.empty? + raise ControllerExceptions::MultiPartParseError, "bad content body:\n'#{status}' should == '#{boundary + EOL}'" unless status == boundary + EOL + # second argument to Regexp.quote is for KCODE + rx = /(?:#{EOL})?#{Regexp.quote(boundary,'n')}(#{EOL}|--)/ + loop { + head = nil + body = '' + filename = content_type = name = nil + read_size = 0 + until head && buf =~ rx + i = buf.index("\r\n\r\n") + if( i == nil && read_size == 0 && content_length == 0 ) + content_length = -1 + break + end + if !head && i + head = buf.slice!(0, i+2) # First \r\n + buf.slice!(0, 2) # Second \r\n + + # String#[] with 2nd arg here is returning + # a group from match data + filename = head[FILENAME_REGEX, 1] + content_type = head[CONTENT_TYPE_REGEX, 1] + name = head[NAME_REGEX, 1] + + if filename && !filename.empty? + body = Tempfile.new(:Merb) + body.binmode if defined? body.binmode + end + next + end + + # Save the read body part. + if head && (boundary_size+4 < buf.size) + body << buf.slice!(0, buf.size - (boundary_size+4)) + end + + read_size = bufsize < content_length ? bufsize : content_length + if( read_size > 0 ) + c = input.read(read_size) + raise ControllerExceptions::MultiPartParseError, "bad content body" if c.nil? || c.empty? + buf << c + content_length -= c.size + end + end + + # Save the rest. + if i = buf.index(rx) + # correct value of i for some edge cases + if (i > 2) && (j = buf.index(rx, i-2)) && (j < i) + i = j + end + body << buf.slice!(0, i) + buf.slice!(0, boundary_size+2) + + content_length = -1 if $1 == "--" + end + + if filename && !filename.empty? + body.rewind + data = { + :filename => File.basename(filename), + :content_type => content_type, + :tempfile => body, + :size => File.size(body.path) + } + else + data = body + end + paramhsh = normalize_params(paramhsh,name,data) + break if buf.empty? || content_length == -1 + } + paramhsh + end + + +
+ + + (value, prefix = nil) + + Parameters + + + +
value<Array, Hash, Dictionary ~to_s>:The value for the query string. + +
prefix<~to_s>:The prefix to add to the query string keys. + +
+

Returns

+ + +
String:The query string. + +
+

Alternatives

+

+If the value is a string, the prefix will be used as the key. +

+

Examples

+
+  params_to_query_string(10, "page")
+    # => "page=10"
+  params_to_query_string({ :page => 10, :word => "ruby" })
+    # => "page=10&word=ruby"
+  params_to_query_string({ :page => 10, :word => "ruby" }, "search")
+    # => "search[page]=10&search[word]=ruby"
+  params_to_query_string([ "ice-cream", "cake" ], "shopping_list")
+    # => "shopping_list[]=ice-cream&shopping_list[]=cake"
+
+

+:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/dispatch/request_parsers.rb, line 156 + def self.params_to_query_string(value, prefix = nil) + case value + when Array + value.map { |v| + params_to_query_string(v, "#{prefix}[]") + } * "&" + when Hash, Dictionary + value.map { |k, v| + params_to_query_string(v, prefix ? "#{prefix}[#{escape(k)}]" : escape(k)) + } * "&" + else + "#{prefix}=#{escape(value)}" + end + end + + +
+ + + (query_string, delimiter = '&;', preserve_order = false) + + Parameters + + + + +
query_string<String>:The query string. + +
delimiter<String>:The query string divider. Defaults to "&". + +
preserve_order<Boolean>:Preserve order of args. Defaults to false. + +
+

Returns

+ + +
Mash:The parsed query string (Dictionary if preserve_order is set). + +
+

Examples

+
+  Merb::Parse.query("bar=nik&post[body]=heya")
+    # => { :bar => "nik", :post => { :body => "heya" } }
+
+

+:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/dispatch/request_parsers.rb, line 17 + def self.query(query_string, delimiter = '&;', preserve_order = false) + query = preserve_order ? Dictionary.new : {} + for pair in (query_string || '').split(/[#{delimiter}] */n) + key, value = unescape(pair).split('=',2) + next if key.nil? + if key.include?('[') + normalize_params(query, key, value) + else + query[key] = value + end + end + preserve_order ? query : query.to_mash + end + + +
+ + + (s) + + Parameter + + +
s<String>:String to URL unescape. + +
+

returns

+ + +
String:The unescaped string. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/request_parsers.rb, line 191 + def self.unescape(s) + s.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/n){ + [$1.delete('%')].pack('H*') + } + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/controller/template.rb + + + + + + + + + + + + + + + + {} unless defined?(EXTENSIONS) + + + + + + + {} unless defined?(METHOD_LIST) + + + + + + + Hash.new([].freeze) unless defined?(SUPPORTED_LOCALS_LIST) + + + + + + + {} unless defined?(MTIMES) + + + + + + + + + + + + + + (path) + + +Finds the engine for a particular path. +

+

Parameters

+ + +
path<String>:The path of the file to find an engine for. + +
+

Returns

+ + +
Class:The engine. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/controller/template.rb, line 148 + def engine_for(path) + path = File.expand_path(path) + EXTENSIONS[path.match(/\.([^\.]*)$/)[1]] + end + + +
+ + + (io, locals=[], mod = Merb::InlineTemplates) + + +Takes a template at a particular path and inlines it into a module and adds +it to the METHOD_LIST table to speed lookup later. +

+

Parameters

+ + + + +
io<path>:An IO that responds to path (File or VirtualFile) + +
locals<Array[Symbol]>:A list of local names that should be assigned in the template method from +the arguments hash. Defaults to []. + +
mod<Module>:The module to put the compiled method into. Defaults to Merb::InlineTemplates + +
+

Returns

+ + +
Symbol:The name of the method that the template was compiled into. + +
+

Notes

+

+Even though this method supports inlining into any module, the method must +be available to instances of AbstractController that will use it. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/controller/template.rb, line 127 + def inline_template(io, locals=[], mod = Merb::InlineTemplates) + full_file_path = File.expand_path(io.path) + engine_neutral_path = full_file_path.gsub(/\.[^\.]*$/, "") + + SUPPORTED_LOCALS_LIST[engine_neutral_path] |= locals unless locals.empty? + ret = METHOD_LIST[engine_neutral_path] = + engine_for(full_file_path).compile_template(io, template_name(full_file_path), locals, mod) + + io.close + ret + end + + +
+ + + (path) + + +For a given path, gets an IO object that responds to path. +

+

+This is so that plugins can override this if they provide mechanisms for +specifying templates that are not just simple files. The plugin is +responsible for ensuring that the fake path provided will work with template_for, and thus the RenderMixin in general. +

+

Parameters

+ + +
path<String>:A full path to find a template for. This is the + +
+
+  path that the RenderMixin assumes it should find the template
+  in.
+
+

Returns

+ + +
IO#path:An IO object that responds to path (File or VirtualFile). + +
+

+:api: plugin @overridable +

+ ]]>
+ + + +# File lib/merb-core/controller/template.rb, line 52 + def load_template_io(path) + File.open(path, "r") + end + + +
+ + + (path, locals) + + +Decides if a template needs to be re/compiled. +

+

Parameters

+ + + +
path<String>:The full path of the template to check support for. + +
locals<Array[Symbol]>:The list of locals that need to be supported + +
+

Returns

+ + +
Boolean:Whether or not the template for the provided path needs to be recompiled + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/controller/template.rb, line 88 + def needs_compilation?(path, locals) + return true if Merb::Config[:reload_templates] || !METHOD_LIST[path] + + current_locals = SUPPORTED_LOCALS_LIST[path] + current_locals != locals && + !(locals - current_locals).empty? + end + + +
+ + + (engine, extensions) + + +Registers the extensions that will trigger a particular templating engine. +

+

Parameters

+ + + +
engine<Class>:The class of the engine that is being registered + +
extensions<Array[String]>:The list of extensions that will be registered with this templating +language + +
+

Raises

+ + +
ArgumentError:engine does not have a compile_template method. + +
+

Returns

+

+nil +

+

Example

+
+  Merb::Template.register_extensions(Merb::Template::Erubis, ["erb"])
+
+

+:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/controller/template.rb, line 172 + def register_extensions(engine, extensions) + raise ArgumentError, "The class you are registering does not have a compile_template method" unless + engine.respond_to?(:compile_template) + extensions.each{|ext| EXTENSIONS[ext] = engine } + Merb::AbstractController.class_eval "include \#{engine}::Mixin\n" + end + + +
+ + + () + + +Gets all known template extensions +

+

Returns

+
+  Array:: Extension strings.
+
+

+:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/controller/template.rb, line 102 + def template_extensions + EXTENSIONS.keys + end + + +
+ + + (path, template_stack = [], locals=[]) + + +Gets the name of the template method for a particular path. +

+

Parameters

+ + + + +
path<String>:A full path to find a template method for. + +
template_stack<Array>:The template stack. Not used. + +
locals<Array[Symbol]>:The names of local variables + +
+

Returns

+ + +
<String>:name of the method that inlines the template. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/controller/template.rb, line 67 + def template_for(path, template_stack = [], locals=[]) + path = File.expand_path(path) + + if needs_compilation?(path, locals) + file = Dir["#{path}.{#{template_extensions.join(',')}}"].first + METHOD_LIST[path] = file ? inline_template(load_template_io(file), locals) : nil + end + + METHOD_LIST[path] + end + + +
+ + + (path) + + +Gets the template’s method name from a full path. This replaces +non-alphanumeric characters with __ and "." with "_" +

+

+Collisions are potentially possible with something like: ~foo.bar and +__foo.bar or !foo.bar. +

+

Parameters

+ + +
path<String>:A full path to convert to a valid Ruby method name + +
+

Returns

+ + +
String:The template name. + +
+

+We might want to replace this with something that varies the character +replaced based on the non-alphanumeric character to avoid edge-case +collisions. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/controller/template.rb, line 29 + def template_name(path) + path = File.expand_path(path) + path.gsub(/[^\.a-zA-Z0-9]/, "__").gsub(/\./, "_") + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/controller/template.rb + + + + + Object + + + + + + + + + + + + + + + + (io, name, locals, mod) + + Parameters + + + + + +
io<path>:An IO containing the full path of the template. + +
name<String>:The name of the method that will be created. + +
locals<Array[Symbol]>:A list of locals to assign from the args passed into the compiled template. + +
mod<Module>:The module that the compiled method will be placed into. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/controller/template.rb, line 193 + def self.compile_template(io, name, locals, mod) + template = ::Erubis::BlockAwareEruby.new(io.read) + _old_verbose, $VERBOSE = $VERBOSE, nil + assigns = locals.inject([]) do |assigns, local| + assigns << "#{local} = _locals[#{local.inspect}]" + end.join(";") + + code = "def #{name}(_locals={}); #{assigns}; #{template.src}; end" + mod.module_eval code, File.expand_path(io.path) + $VERBOSE = _old_verbose + + name + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/controller/template.rb + + + + + + + + + + + + + + + + + + + (*args, &block) + + Parameters + + + +
*args:Arguments to pass to the block. + +
&block:The template block to call. + +
+

Returns

+ + +
String:The output of the block. + +
+

Examples

+

+Capture being used in a .html.erb page: +

+
+  <% @foo = capture do %>
+    <p>Some Foo content!</p>
+  <% end %>
+
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/controller/template.rb, line 224 + def capture_erb(*args, &block) + _old_buf, @_erb_buf = @_erb_buf, "" + block.call(*args) + ret = @_erb_buf + @_erb_buf = _old_buf + ret + end + + +
+ + + (string, binding) + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/controller/template.rb, line 233 + def concat_erb(string, binding) + @_erb_buf << string + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/dispatch/session/memcached.rb + + + + + + + + + + + + + + + + + + + (session_id) + + Parameters + + +
session_id<String>:ID of the session to delete. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/session/memcached.rb, line 58 + def delete_session(session_id) + delete("session:#{session_id}") + end + + +
+ + + (session_id) + + Parameters + + +
session_id<String>:ID of the session to retrieve. + +
+

Returns

+ + +
ContainerSession:The session corresponding to the ID. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/session/memcached.rb, line 41 + def retrieve_session(session_id) + get("session:#{session_id}") + end + + +
+ + + (session_id, data) + + Parameters + + + +
session_id<String>:ID of the session to set. + +
data<ContainerSession>:The session to set. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/session/memcached.rb, line 50 + def store_session(session_id, data) + set("session:#{session_id}", data) + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/dispatch/session/cookie.rb + + + + + Merb::SessionContainer + + + + +If you have more than 4K of session data or don’t want your data to +be visible to the user, pick another session store. +

+

+CookieOverflow is raised +if you attempt to store more than 4K of data. TamperedWithCookie is +raised if the data integrity check fails. +

+

+A message digest is included with the cookie to ensure data integrity: a +user cannot alter session data without knowing the secret key included in +the hash. +

+

+To use Cookie Sessions, set in config/merb.yml +

+
+ :session_secret_key - your secret digest key
+ :session_store - cookie
+
+ + ]]>
+ + + + + + + + + + + 4096 + + + + + + + OpenSSL::Digest::Digest.new('SHA1') + + + + + + + + + + + + RW + + + + + + + + + + + + + () + + +Generates a new session ID and creates a new session. +

+

Returns

+ + +
SessionContainer:The new session. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/session/cookie.rb, line 46 + def generate + self.new(Merb::SessionMixin.rand_uuid, "", Merb::Request._session_secret_key) + end + + +
+ + + (session_id, cookie, secret) + + Parameters + + + + +
session_id<String>:A unique identifier for this session. + +
cookie<String>:The raw cookie data. + +
secret<String>:A session secret. + +
+

Raises

+ + +
ArgumentError:blank or insufficiently long secret. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/session/cookie.rb, line 78 + def initialize(session_id, cookie, secret) + super session_id + if secret.blank? || secret.length < 16 + msg = "You must specify a session_secret_key in your init file, and it must be at least 16 characters" + Merb.logger.warn(msg) + raise ArgumentError, msg + end + @secret = secret + self.update(unmarshal(cookie)) + end + + +
+ + + (request) + + +Sets up a new session on request: make it available on request instance. +

+

Parameters

+ + +
request<Merb::Request>:The Merb::Request that came in from Rack. + +
+

Returns

+ + +
SessionContainer:a SessionContainer. If no sessions +were found, + +
+

+a new SessionContainer will be +generated. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/session/cookie.rb, line 60 + def setup(request) + session = self.new(Merb::SessionMixin.rand_uuid, + request.session_cookie_value, request._session_secret_key) + session._original_session_data = session.to_cookie + request.session = session + end + + +
+ + +
+ + + + + + (request) + + +Teardown and/or persist the current session. +

+

+If @_destroy is true, clear out the session completely, including removal +of the session cookie itself. +

+

Parameters

+ + +
request<Merb::Request>:request object created from Rack environment. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/session/cookie.rb, line 98 + def finalize(request) + if @_destroy + request.destroy_session_cookie + elsif _original_session_data != (new_session_data = self.to_cookie) + request.set_session_cookie_value(new_session_data) + end + end + + +
+ + + () + + +Regenerates the session_id. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/session/cookie.rb, line 109 + def regenerate + self.session_id = Merb::SessionMixin.rand_uuid + end + + +
+ + + () + + +Creates the raw cookie string; includes an HMAC keyed message digest. +

+

Returns

+ + +
String:Cookie value. + +
+

Raises

+ + +
CookieOverflow:More than 4K of data put into session. + +
+

Notes

+

+Session data is converted to a Hash first, since a container might choose to marshal it, +which would make it persist attributes like ‘needs_new_cookie’, +which it shouldn’t. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/session/cookie.rb, line 127 + def to_cookie + unless self.empty? + data = self.serialize + value = Merb::Parse.escape "#{data}--#{generate_digest(data)}" + if value.size > MAX + msg = "Cookies have limit of 4K. Session contents: #{data.inspect}" + Merb.logger.error!(msg) + raise CookieOverflow, msg + end + value + end + end + + +
+ + +
+ + + + + + () + + +Serializes current session data as a Hash. Uses Base64 +encoding for integrity. +

+

Returns

+ + +
String:Base64 encoded dump of the session hash. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/session/cookie.rb, line 189 + def serialize + Base64.encode64(Marshal.dump(self.to_hash)).chop + end + + +
+ + + (data) + + +Unserializes the raw cookie data to a Hash +

+

Returns

+ + +
Hash:the session hash Base64 decoded from the data dump. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/session/cookie.rb, line 199 + def unserialize(data) + Marshal.load(Base64.decode64(data)) rescue {} + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/dispatch/session/cookie.rb + + + + + StandardError + + + + +Raised when storing more than 4K of session data. +

+ + ]]>
+ + + + + + + + + + + + + +
+ + + + + + + lib/merb-core/dispatch/session/cookie.rb + + + + + StandardError + + + + +Raised when the cookie fails its integrity check. +

+ + ]]>
+ + + + + + + + + + + + + +
+ + + + + + + lib/merb-core/dispatch/session/container.rb + + + + + Mash + + + + + + + + + + + + + + RW + + + + + + + R + + + + + + + + + + + + + () + + +Generates a new session ID and creates a new session. +

+

Returns

+ + +
SessionContainer:The new session. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/session/container.rb, line 27 + def generate + end + + +
+ + + (klass) + + +Registers the subclass as an available session store type. +

+ ]]>
+ + + +# File lib/merb-core/dispatch/session/container.rb, line 16 + def inherited(klass) + self.subclasses << klass.to_s + super + end + + +
+ + + (session_id) + + Parameters + + +
session_id<String>:A unique identifier for this session. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/session/container.rb, line 49 + def initialize(session_id) + @_destroy = false + self.session_id = session_id + end + + +
+ + + (request) + + Parameters + + +
request<Merb::Request>:The Merb::Request that came in from Rack. + +
+

Notes

+

+If no sessions were found, a new SessionContainer will be generated. +

+

Returns

+ + +
SessionContainer:a SessionContainer. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/session/container.rb, line 40 + def setup(request) + end + + +
+ + +
+ + + + + + () + + +Destroy the current session - clears data and removes session cookie. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/session/container.rb, line 80 + def clear! + @_destroy = true + self.clear + end + + +
+ + + (request) + + +Teardown and/or persist the current session. +

+

+If @_destroy is true, clear out the session completely, including removal +of the session cookie itself. +

+

Parameters

+ + +
request<Merb::Request>:The Merb::Request that came in from Rack. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/session/container.rb, line 74 + def finalize(request) + end + + +
+ + + () + + +Regenerate the session_id. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/session/container.rb, line 88 + def regenerate + end + + +
+ + + (sid) + + +Assigns a new session_id. +

+

+Recreates the cookie with the default expiration time. Useful during log in +for pushing back the expiration date. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/session/container.rb, line 60 + def session_id=(sid) + self.needs_new_cookie = (@session_id && @session_id != sid) + @session_id = sid + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/dispatch/worker.rb + + + + + Object + + + + + + + + + + + + + + RW + + + + + + + + + + + + + () + + +Creates a new worker thread that loops over the work queue. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/worker.rb, line 29 + def initialize + @thread = Thread.new do + loop do + process_queue + break if Merb::Dispatcher.work_queue.empty? && Merb.exiting + end + end + end + + +
+ + + () + + Returns + + +
Merb::Worker:instance of a worker. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/worker.rb, line 12 + def start + @worker ||= new + Merb.at_exit do + if Merb::Dispatcher.work_queue.empty? + @worker.thread.abort_on_exception = false + @worker.thread.raise + else + @worker.thread.join + end + end + @worker + end + + +
+ + +
+ + + + + + () + + +Processes tasks in the Merb::Dispatcher.work_queue. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/worker.rb, line 41 + def process_queue + begin + while blk = Merb::Dispatcher.work_queue.pop + # we've been blocking on the queue waiting for an item sleeping. + # when someone pushes an item it wakes up this thread so we + # immediately pass execution to the scheduler so we don't + # accidentally run this block before the action finishes + # it's own processing + Thread.pass + blk.call + break if Merb::Dispatcher.work_queue.empty? && Merb.exiting + end + rescue Exception => e + Merb.logger.warn! %Q!Worker Thread Crashed with Exception:\n#{Merb.exception(e)}\nRestarting Worker Thread! + retry + end + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/dispatch/session/memory.rb + + + + + Object + + + + +Used for handling multiple sessions stored in memory. +

+ + ]]>
+ + + + + + + + + + + + + + (ttl=nil) + + Parameters + + +
ttl<Fixnum>:Session validity time in seconds. Defaults to +1 hour. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/session/memory.rb, line 44 + def initialize(ttl=nil) + @sessions = Hash.new + @timestamps = Hash.new + @mutex = Mutex.new + @session_ttl = ttl || Merb::Const::HOUR # defaults 1 hour + start_timer + end + + +
+ + +
+ + + + + + (session_id) + + Parameters + + +
session_id<String>:ID of the session to delete. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/session/memory.rb, line 82 + def delete_session(session_id) + @mutex.synchronize { + @timestamps.delete(session_id) + @sessions.delete(session_id) + } + end + + +
+ + + () + + +Deletes any sessions that have reached their maximum validity. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/session/memory.rb, line 92 + def reap_expired_sessions + @timestamps.each do |session_id,stamp| + delete_session(session_id) if (stamp + @session_ttl) < Time.now + end + GC.start + end + + +
+ + + (session_id) + + Parameters + + +
session_id<String>:ID of the session to retrieve. + +
+

Returns

+ + +
ContainerSession:The session corresponding to the ID. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/session/memory.rb, line 59 + def retrieve_session(session_id) + @mutex.synchronize { + @timestamps[session_id] = Time.now + @sessions[session_id] + } + end + + +
+ + + () + + +Starts the timer that will eventually reap outdated sessions. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/session/memory.rb, line 102 + def start_timer + Thread.new do + loop { + sleep @session_ttl + reap_expired_sessions + } + end + end + + +
+ + + (session_id, data) + + Parameters + + + +
session_id<String>:ID of the session to set. + +
data<ContainerSession>:The session to set. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/session/memory.rb, line 71 + def store_session(session_id, data) + @mutex.synchronize { + @timestamps[session_id] = Time.now + @sessions[session_id] = data + } + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/dispatch/session/memcached.rb + + + + + Merb::SessionStoreContainer + + + + +Sessions stored in memcached. +

+

+Requires setup in your init.rb. +

+

+This for the ‘memcache-client’ gem: +

+
+  Merb::BootLoader.after_app_loads do
+    require 'memcache'
+    Merb::MemcacheSession.store =
+       MemCache.new('127.0.0.1:11211', :namespace => 'my_app')
+  end
+
+

+Or this for the ‘memcached’ gem: +

+
+  Merb::BootLoader.after_app_loads do
+    require 'memcache'
+    Merb::MemcacheSession.store =
+       Memcached.new('127.0.0.1:11211', :namespace => 'my_app')
+  end
+
+ + ]]>
+ + + + + + + + + + + + + +
+ + + + + + + lib/merb-core/controller/mixins/responder.rb + + + + + Object + + + + + + + + + + + + + + R + + + + + + + R + + + + + + + R + + + + + + + R + + + + + + + R + + + + + + + + + + + + + (entry,index) + + Parameters + + + +
entry<String>:The accept type pattern + +
index<Fixnum>:The index used for sorting accept types. A lower value indicates higher +priority. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/responder.rb, line 388 + def initialize(entry,index) + @index = index + + entry =~ /\s*([^;\s]*)\s*(;\s*q=\s*(.*))?/ + @media_range, quality = $1, $3 + + @type, @sub_type = @media_range.split(%r{/}) + (quality ||= 0.0) if @media_range == "*/*" + @quality = quality ? (quality.to_f * 100).to_i : 100 + @quality *= (mime && mime[:default_quality] || 1) + end + + +
+ + +
+ + + + + + (entry) + + +Compares two accept types for sorting purposes. +

+

Parameters

+ + +
entry<AcceptType>:The accept type to compare. + +
+

Returns

+ + +
Fixnum:-1, 0 or 1, depending on whether entry has a lower, equal or higher +priority than the accept type being compared. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/responder.rb, line 411 + def <=>(entry) + if entry.quality == quality + @index <=> entry.index + else + entry.quality <=> @quality + end + end + + +
+ + + (entry) + + +An alias for eql?. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/responder.rb, line 436 + def ==(entry); eql?(entry); end + + +
+ + + (entry) + + Parameters + + +
entry<AcceptType>:The accept type to compare. + +
+

Returns

+ + +
Boolean:True if the accept types are equal, i.e. if the synonyms for this accept +type includes the entry media range. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/responder.rb, line 429 + def eql?(entry) + synonyms.include?(entry.media_range) + end + + +
+ + + () + + Returns + + +
Fixnum:A hash based on the super range. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/responder.rb, line 442 + def hash; super_range.hash; end + + +
+ + + () + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/responder.rb, line 459 + def mime + @mime ||= Merb.available_mime_types[Merb::ResponderMixin::MIMES[@media_range]] + end + + +
+ + + () + + Returns + + +
String:The primary media range for this accept type, i.e. either the first synonym +or, if none exist, the media range. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/responder.rb, line 469 + def super_range + synonyms.first || @media_range + end + + +
+ + + () + + Returns + + +
Array[String]:All Accept header values, such as "text/html", that match this +type. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/responder.rb, line 449 + def synonyms + return @syns if @syns + if _mime = mime + @syns = _mime[:accepts] + else + @syns = [] + end + end + + +
+ + + () + + Returns + + +
String:The accept type as a string, i.e. the media range. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/responder.rb, line 486 + def to_s + @media_range + end + + +
+ + + () + + Returns +

+Symbol: The type as a symbol, e.g. :html. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/responder.rb, line 477 + def to_sym + Merb.available_mime_types.select{|k,v| + v[:accepts] == synonyms || v[:accepts][0] == synonyms[0]}.flatten.first + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/controller/mixins/responder.rb + + + + + Object + + + + + + + + + + + + + + + + (accept_header) + + +Parses the raw accept header into an array of sorted AcceptType objects. +

+

Parameters

+ + +
accept_header<~to_s>:The raw accept header. + +
+

Returns

+ + +
Array[AcceptType]:The accepted types. + +
+

+@api private +

+ ]]>
+ + + +# File lib/merb-core/controller/mixins/responder.rb, line 367 + def self.parse(accept_header) + headers = accept_header.split(/,/) + idx, list = 0, [] + while idx < headers.size + list << AcceptType.new(headers[idx], idx) + idx += 1 + end + list.sort + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/config.rb + + lib/merb-core/dispatch/session.rb + + + + + Object + + + + + + + + + + + + + + RW + + + + + + + + + + + + + (key) + + +Retrieve the value of a config entry. +

+

Parameters

+ + +
key<Object>:The key to retrieve the parameter for. + +
+

Returns

+ + +
Object:The value of the configuration parameter. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/config.rb, line 79 + def [](key) + (@configuration ||= setup)[key] + end + + +
+ + + (key, val) + + +Set the value of a config entry. +

+

Parameters

+ + + +
key<Object>:The key to set the parameter for. + +
val<Object>:The value of the parameter. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/config.rb, line 90 + def []=(key, val) + (@configuration ||= setup)[key] = val + end + + +
+ + + (&block) + + +Set configuration parameters from a code block, where each method evaluates +to a config parameter. +

+

Parameters

+ + +
&block:Configuration parameter block. + +
+

Examples

+
+  # Set environment and log level.
+  Merb::Config.configure do
+    environment "development"
+    log_level   "debug"
+    log_file    Merb.root / "log" / "special.log"
+  end
+
+

Returns

+

+nil +

+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/config.rb, line 428 + def configure(&block) + ConfigBlock.new(self, &block) if block_given? + nil + end + + +
+ + + () + + +Returns the hash of default config values for Merb. +

+

Returns

+ + +
Hash:The defaults for the config. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/config.rb, line 15 + def defaults + @defaults ||= { + :host => "0.0.0.0", + :port => "4000", + :adapter => "runner", + :reload_classes => true, + :fork_for_class_load => Merb.forking_environment?, + :environment => "development", + :merb_root => Dir.pwd, + :use_mutex => true, + :log_delimiter => " ~ ", + :log_auto_flush => false, + :log_level => :info, + :log_stream => STDOUT, + :disabled_components => Merb.on_windows? ? [:signals] : [], + :deferred_actions => [], + :verbose => false, + :name => "merb" + } + end + + +
+ + + (key) + + +Removes the value of a config entry. +

+

Parameters

+ + +
key<Object>:The key of the parameter to delete. + +
+

Returns

+ + +
Object:The value of the removed entry. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/config.rb, line 103 + def delete(key) + @configuration.delete(key) + end + + +
+ + + (key, default) + + +Retrieves the value of a config entry, returning the provided default if +the key is not present +

+

Parameters

+ + + +
key<Object>:The key to retrieve the parameter for. + +
default<Object>:The default value to return if the parameter is not set. + +
+

Returns

+ + +
Object:The value of the configuration parameter or the default. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/config.rb, line 118 + def fetch(key, default) + @configuration.fetch(key, default) + end + + +
+ + + (key) + + +Detects whether the provided key is in the config. +

+

Parameters

+ + +
key<Object>:The key to check. + +
+

Returns

+ + +
Boolean:True if the key exists in the config. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/config.rb, line 66 + def key?(key) + @configuration.key?(key) + end + + +
+ + + (method, *args) + + +Allows retrieval of single key config values via Merb.config.<key> +Allows single key assignment via Merb.config.<key> = … +

+

Parameters

+ + + +
method<~to_s>:Method name as hash key value. + +
*args:Value to set the configuration parameter to. + +
+

Returns

+

+The value of the entry fetched or assigned to. +

+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/config.rb, line 444 + def method_missing(method, *args) + if method.to_s[-1,1] == '=' + @configuration[method.to_s.tr('=','').to_sym] = *args + else + @configuration[method] + end + end + + +
+ + + (argv = ARGV) + + +Parses the command line arguments and stores them in the config. +

+

Parameters

+ + +
argv<String>:The command line arguments. Defaults to ARGV. + +
+

Returns

+

+The configuration as a hash. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/config.rb, line 181 + def parse_args(argv = ARGV) + @configuration ||= {} + # Our primary configuration hash for the length of this method + options = {} + + # Environment variables always win + options[:environment] = ENV["MERB_ENV"] if ENV["MERB_ENV"] + + # Build a parser for the command line arguments + opts = OptionParser.new do |opts| + opts.version = Merb::VERSION + + opts.banner = "Usage: merb [uGdcIpPhmailLerkKX] [argument]" + opts.define_head "Merb. Pocket rocket web framework" + opts.separator '*' * 80 + opts.separator "If no flags are given, Merb starts in the " \ + "foreground on port 4000." + opts.separator '*' * 80 + + opts.on("-u", "--user USER", "This flag is for having merb run " \ + "as a user other than the one currently logged in. Note: " \ + "if you set this you must also provide a --group option " \ + "for it to take effect.") do |user| + options[:user] = user + end + + opts.on("-G", "--group GROUP", "This flag is for having merb run " \ + "as a group other than the one currently logged in. Note: " \ + "if you set this you must also provide a --user option " \ + "for it to take effect.") do |group| + options[:group] = group + end + + opts.on("-d", "--daemonize", "This will run a single merb in the " \ + "background.") do |daemon| + options[:daemonize] = true + end + + opts.on("-N", "--no-daemonize", "This will allow you to run a " \ + "cluster in console mode") do |no_daemon| + options[:daemonize] = false + end + + opts.on("-c", "--cluster-nodes NUM_MERBS", Integer, + "Number of merb daemons to run.") do |nodes| + options[:daemonize] = true unless options.key?(:daemonize) + options[:cluster] = nodes + end + + opts.on("-I", "--init-file FILE", "File to use for initialization " \ + "on load, defaults to config/init.rb") do |init_file| + options[:init_file] = init_file + end + + opts.on("-p", "--port PORTNUM", Integer, "Port to run merb on, " \ + "defaults to 4000.") do |port| + options[:port] = port + end + + opts.on("-o", "--socket-file FILE", "Socket file to run merb on, " \ + "defaults to [Merb.root]/log/merb.sock. This is for " \ + "web servers, like thin, that use sockets." \ + "Specify this *only* if you *must*.") do |port| + options[:socket_file] = port + end + + opts.on("-s", "--socket SOCKNUM", Integer, "Socket number to run " \ + "merb on, defaults to 0.") do |port| + options[:socket] = port + end + + opts.on("-n", "--name NAME", String, "Set the name of the application. "\ + "This is used in the process title and log file names.") do |name| + options[:name] = name + end + + opts.on("-P", "--pid PIDFILE", "PID file, defaults to " \ + "[Merb.root]/log/merb.main.pid for the master process and" \ + "[Merb.root]/log/merb.[port number].pid for worker " \ + "processes. For clusters, use %s to specify where " \ + "in the file merb should place the port number. For " \ + "instance: -P myapp.%s.pid") do |pid_file| + options[:pid_file] = pid_file + end + + opts.on("-h", "--host HOSTNAME", "Host to bind to " \ + "(default is 0.0.0.0).") do |host| + options[:host] = host + end + + opts.on("-m", "--merb-root /path/to/approot", "The path to the " \ + "Merb.root for the app you want to run " \ + "(default is current working directory).") do |root| + options[:merb_root] = File.expand_path(root) + end + + adapters = [:mongrel, :emongrel, :thin, :ebb, :fastcgi, :webrick] + + opts.on("-a", "--adapter ADAPTER", + "The rack adapter to use to run merb (default is mongrel)" \ + "[#{adapters.join(', ')}]") do |adapter| + options[:adapter] ||= adapter + end + + opts.on("-R", "--rackup FILE", "Load an alternate Rack config " \ + "file (default is config/rack.rb)") do |rackup| + options[:rackup] = rackup + end + + opts.on("-i", "--irb-console", "This flag will start merb in " \ + "irb console mode. All your models and other classes will " \ + "be available for you in an irb session.") do |console| + options[:adapter] = 'irb' + end + + opts.on("-S", "--sandbox", "This flag will enable a sandboxed irb " \ + "console. If your ORM supports transactions, all edits will " \ + "be rolled back on exit.") do |sandbox| + options[:sandbox] = true + end + + opts.on("-l", "--log-level LEVEL", "Log levels can be set to any of " \ + "these options: debug < info < warn < error < " \ + "fatal (default is info)") do |log_level| + options[:log_level] = log_level.to_sym + options[:force_logging] = true + end + + opts.on("-L", "--log LOGFILE", "A string representing the logfile to " \ + "use. Defaults to [Merb.root]/log/merb.[main].log for the " \ + "master process and [Merb.root]/log/merb[port number].log" \ + "for worker processes") do |log_file| + options[:log_file] = log_file + options[:force_logging] = true + end + + opts.on("-e", "--environment STRING", "Environment to run Merb " \ + "under [development, production, testing] " \ + "(default is development)") do |env| + options[:environment] = env + end + + opts.on("-r", "--script-runner ['RUBY CODE'| FULL_SCRIPT_PATH]", + "Command-line option to run scripts and/or code in the " \ + "merb app.") do |code_or_file| + options[:runner_code] = code_or_file + options[:adapter] = 'runner' + end + + opts.on("-K", "--graceful PORT or all", "Gracefully kill one " \ + "merb proceses by port number. Use merb -K all to " \ + "gracefully kill all merbs.") do |ports| + options[:action] = :kill + ports = "main" if ports == "all" + options[:port] = ports + end + + opts.on("-k", "--kill PORT", "Force kill one merb worker " \ + "by port number. This will cause the worker to" \ + "be respawned.") do |port| + options[:action] = :kill_9 + port = "main" if port == "all" + options[:port] = port + end + + opts.on("--fast-deploy", "Reload the code, but not your" \ + "init.rb or gems") do + options[:action] = :fast_deploy + end + + # @todo Do we really need this flag? It seems unlikely to want to + # change the mutex from the command-line. + opts.on("-X", "--mutex on/off", "This flag is for turning the " \ + "mutex lock on and off.") do |mutex| + if mutex == "off" + options[:use_mutex] = false + else + options[:use_mutex] = true + end + end + + opts.on("-D", "--debugger", "Run merb using rDebug.") do + begin + require "ruby-debug" + Debugger.start + + # Load up any .rdebugrc files we find + [".", ENV["HOME"], ENV["HOMEPATH"]].each do |script_dir| + script_file = "#{script_dir}/.rdebugrc" + Debugger.run_script script_file, StringIO.new if File.exists?(script_file) + end + + if Debugger.respond_to?(:settings) + Debugger.settings[:autoeval] = true + end + puts "Debugger enabled" + rescue LoadError + puts "You need to install ruby-debug to run the server in " \ + "debugging mode. With gems, use `gem install ruby-debug'" + exit + end + end + + opts.on("-V", "--verbose", "Print extra information") do + options[:verbose] = true + end + + opts.on("-C", "--console-trap", "Enter an irb console on ^C") do + options[:console_trap] = true + end + + opts.on("-?", "-H", "--help", "Show this help message") do + puts opts + exit + end + end + + # Parse what we have on the command line + begin + opts.parse!(argv) + rescue OptionParser::InvalidOption => e + Merb.fatal! e.message, e + end + Merb::Config.setup(options) + end + + +
+ + + () + + +Returns stores list constructed from configured session stores (:session_stores config option) or default one +(:session_store config option). +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/session.rb, line 11 + def self.session_stores + @session_stores ||= begin + config_stores = Array( + Merb::Config[:session_stores] || Merb::Config[:session_store] + ) + config_stores.map { |name| name.to_sym } + end + end + + +
+ + + (settings = {}) + + +Sets up the configuration by storing the given settings. +

+

Parameters

+ + +
settings<Hash>:Configuration settings to use. These are merged with the defaults. + +
+

Returns

+

+The configuration as a hash. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/config.rb, line 153 + def setup(settings = {}) + config = defaults.merge(settings) + + unless config[:reload_classes] + config[:fork_for_class_load] = false + end + + dev_mode = config[:environment] == "development" + unless config.key?(:reap_workers_quickly) + config[:reap_workers_quickly] = dev_mode & !config[:cluster] + end + + unless config.key?(:bind_fail_fatal) + config[:bind_fail_fatal] = dev_mode + end + + @configuration = config + end + + +
+ + + () + + +Returns the configuration as a hash. +

+

Returns

+ + +
Hash:The config as a hash. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/config.rb, line 128 + def to_hash + @configuration + end + + +
+ + + () + + +Returns the config as YAML. +

+

Returns

+ + +
String:The config as YAML. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/config.rb, line 138 + def to_yaml + require "yaml" + @configuration.to_yaml + end + + +
+ + + () {|@configuration| ...} + + +Yields the configuration. +

+

Block parameters

+ + +
c<Hash>:The configuration parameters. + +
+

Examples

+
+  Merb::Config.use do |config|
+    config[:exception_details] = false
+    config[:log_stream]        = STDOUT
+  end
+
+

Returns

+

+nil +

+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/config.rb, line 51 + def use + @configuration ||= {} + yield @configuration + nil + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/config.rb + + + + + Object + + + + + + + + + + + + + + + + (klass, &block) + + +Evaluates the provided block, where any call to a method causes #[]= to be +called on klass with the method name as the key and the arguments as the +value. +

+

Parameters

+ + + +
klass<Object~[]=>:The object on which to assign values. + +
&block:The block which specifies the config values to set. + +
+

Returns

+

+nil +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/config.rb, line 468 + def initialize(klass, &block) + @klass = klass + instance_eval(&block) + end + + +
+ + +
+ + + + + + (method, *args) + + +Assign args as the value of the entry keyed by method. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/config.rb, line 476 + def method_missing(method, *args) + @klass[method] = *args + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/dispatch/session/store_container.rb + + + + + Merb::SessionContainer + + + + + + + + + + + + + + RW + + + + + + + + + + + + + () + + +Generates a new session ID and creates a new session. +

+

Returns

+ + +
SessionStoreContainer:The new session. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/session/store_container.rb, line 56 + def generate + session = new(Merb::SessionMixin.rand_uuid) + session.needs_new_cookie = true + session + end + + +
+ + + (request) + + +Setups a new session or retrieves an existing session. +

+

Parameters

+ + +
request<Merb::Request>:The Merb::Request that came in from Rack. + +
+

Notes

+

+If no sessions were found, a new SessionContainer will be generated. +

+

Returns

+ + +
SessionContainer:a SessionContainer. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/session/store_container.rb, line 74 + def setup(request) + session = retrieve(request.session_id) + request.session = session + # TODO Marshal.dump is slow - needs optimization + session._fingerprint = Marshal.dump(request.session.to_hash).hash + session + end + + +
+ + +
+ + + + + + (request) + + +Teardown and/or persist the current session. +

+

+If @_destroy is true, clear out the session completely, including removal +of the session cookie itself. +

+

Parameters

+ + +
request<Merb::Request>:The Merb::Request that came in from Rack. + +
+

Notes

+

+The data (self) is converted to a Hash first, since a +container might choose to do a full Marshal on the data, which would make +it persist attributes like ‘needs_new_cookie’, which it +shouldn’t. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/session/store_container.rb, line 135 + def finalize(request) + if @_destroy + store.delete_session(self.session_id) + request.destroy_session_cookie + else + if _fingerprint != Marshal.dump(data = self.to_hash).hash + begin + store.store_session(request.session(self.class.session_store_type).session_id, data) + rescue => err + Merb.logger.warn!("Could not persist session to #{self.class.name}: #{err.message}") + end + end + if needs_new_cookie || Merb::SessionMixin.needs_new_cookie? + request.set_session_id_cookie(self.session_id) + end + end + end + + +
+ + + () + + +Regenerate the session ID. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/session/store_container.rb, line 156 + def regenerate + store.delete_session(self.session_id) + self.session_id = Merb::SessionMixin.rand_uuid + store.store_session(self.session_id, self) + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/controller/merb_controller.rb + + + + + Merb::AbstractController + + + + + + + + + + + + + + R + + + + + + + R + + + + + + + + + + + + + () + + +All methods that are callable as actions. +

+

Returns

+ + +
Array:A list of method names that are also actions + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/controller/merb_controller.rb, line 107 + def self._callable_methods + callables = [] + klass = self + begin + callables << (klass.public_instance_methods(false) + klass._shown_actions) - klass._hidden_actions + klass = klass.superclass + end until klass == Merb::AbstractController || klass == Object + callables.flatten.reject{|action| action =~ /^_.*/} + end + + +
+ + + (params) + + +This is a stub method so plugins can implement param filtering if they +want. +

+

Parameters

+ + +
params<Hash{Symbol => String}>:A list of params + +
+

Returns

+ + +
Hash{Symbol => String}:A new list of params, filtered as desired + +
+

+:api: plugin @overridable +

+ ]]>
+ + + +# File lib/merb-core/controller/merb_controller.rb, line 97 + def self._filter_params(params) + params + end + + +
+ + + () + + +Sets a controller to be "abstract" This controller will not be +able to be routed to and is used for super classing only +

+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/merb_controller.rb, line 359 + def self.abstract! + @_abstract = true + end + + +
+ + + () + + +Asks a controller if it is abstract +

+

Returns

+

+Boolean +

+
+ true if the controller has been set as abstract
+
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/merb_controller.rb, line 370 + def self.abstract? + !!@_abstract + end + + +
+ + + () + + +The list of actions that are callable, after taking defaults, +_hidden_actions and _shown_actions into consideration. It is calculated +once, the first time an action is dispatched for this controller. +

+

Returns

+ + +
SimpleSet[String]:A set of actions that should be callable. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/merb_controller.rb, line 83 + def self.callable_actions + @callable_actions ||= Extlib::SimpleSet.new(_callable_methods) + end + + +
+ + + (*names) + + +Hides each of the given methods from being callable as actions. +

+

Parameters

+ + +
*names<~to-s>:Actions that should be added to the list. + +
+

Returns

+ + +
Array[String]:An array of actions that should not be possible to dispatch to. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/merb_controller.rb, line 40 + def self.hide_action(*names) + self._hidden_actions = self._hidden_actions | names.map { |n| n.to_s } + end + + +
+ + + (klass) + + Parameters + + +
klass<Merb::Controller>:The Merb::Controller inheriting from the +base class. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/controller/merb_controller.rb, line 24 + def self.inherited(klass) + _subclasses << klass.to_s + super + klass._template_root = Merb.dir_for(:view) unless self._template_root + end + + +
+ + + (request, status=200, headers={'Content-Type' => 'text/html; charset=utf-8'}) + + +Builds a new controller. +

+

+Sets the variables that came in through the dispatch as available to the +controller. +

+

Parameters

+ + + + +
request<Merb::Request>:The Merb::Request that came in from Rack. + +
status<Integer>:An integer code for the status. Defaults to 200. + +
headers<Hash{header => value}>:A hash of headers to start the controller with. These headers can be +overridden later by the headers method. + +
+

+:api: plugin @overridable +

+ ]]>
+ + + +# File lib/merb-core/controller/merb_controller.rb, line 170 + def initialize(request, status=200, headers={'Content-Type' => 'text/html; charset=utf-8'}) + super() + @request, @_status, @headers = request, status, headers + end + + +
+ + + (*names) + + +Makes each of the given methods being callable as actions. You can use this +to make methods included from modules callable as actions. +

+

Parameters

+ + +
*names<~to-s>:Actions that should be added to the list. + +
+

Returns

+ + +
Array[String]:An array of actions that should be dispatched to even if they would not +otherwise be. + +
+

Example

+
+  module Foo
+    def self.included(base)
+      base.show_action(:foo)
+    end
+
+    def foo
+      # some actiony stuff
+    end
+
+    def foo_helper
+      # this should not be an action
+    end
+  end
+
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/merb_controller.rb, line 71 + def self.show_action(*names) + self._shown_actions = self._shown_actions | names.map {|n| n.to_s} + end + + +
+ + + () + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/controller/merb_controller.rb, line 12 + def self.subclasses_list() _subclasses end + + +
+ + +
+ + + + + + (template, type) + + +The location to look for a template and mime-type. This is overridden from +AbstractController, which defines a +version of this that does not involve mime-types. +

+

Parameters

+ + + +
template<String>:The absolute path to a template - without mime and template extension. The +mime-type extension is optional - it will be appended from the current +content type if it hasn’t been added already. + +
type<~to_s>:The mime-type of the template that will be rendered. Defaults to nil. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/merb_controller.rb, line 152 + def _absolute_template_location(template, type) + _conditionally_append_extension(template, type) + end + + +
+ + + (action=:index) + + +Dispatch the action. +

+

Parameters

+ + +
action<~to_s>:An action to dispatch to. Defaults to :index. + +
+

Returns

+ + +
String:The string sent to the logger for time spent. + +
+

Raises

+ + +
ActionNotFound:The requested action was not found in class. + +
+

+:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/controller/merb_controller.rb, line 187 + def _dispatch(action=:index) + Merb.logger.info("Params: #{self.class._filter_params(request.params).inspect}") + start = Time.now + if self.class.callable_actions.include?(action.to_s) + super(action) + else + raise ActionNotFound, "Action '#{action}' was not found in #{self.class}" + end + @_benchmarks[:action_time] = Time.now - start + self + end + + +
+ + + (context, type, controller) + + +The location to look for a template for a particular controller, context, +and mime-type. This is overridden from AbstractController, which defines a +version of this that does not involve mime-types. +

+

Parameters

+ + + + +
context<~to_s>:The name of the action or template basename that will be rendered. + +
type<~to_s>:The mime-type of the template that will be rendered. Defaults to nil. + +
controller<~to_s>:The name of the controller that will be rendered. Defaults to +controller_name. This will be "layout" for rendering a layout. + +
+

Notes

+

+By default, this renders ":controller/:action.:type". To change +this, override it in your application class or in individual controllers. +

+

+:api: public @overridable +

+ ]]>
+ + + +# File lib/merb-core/controller/merb_controller.rb, line 135 + def _template_location(context, type, controller) + _conditionally_append_extension(controller ? "#{controller}/#{context}" : "#{context}", type) + end + + +
+ + + (*args) + + +Returns the absolute url including the passed protocol and host. +

+

+This uses the same arguments as the url method, with added requirements of +protocol and host options. +

+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/merb_controller.rb, line 335 + def absolute_url(*args) + options = extract_options_from_args!(args) || {} + options[:protocol] ||= request.protocol + options[:host] ||= request.host + args << options + super(*args) + end + + +
+ + + () + + Returns + + +
Hash:The parameters from the request object + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/merb_controller.rb, line 230 + def params() request.params end + + +
+ + + () + + +The results of the controller’s render, to be returned to Rack. +

+

Returns

+ + +
Array[Integer, Hash, String]:The controller’s status code, headers, and body + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/controller/merb_controller.rb, line 350 + def rack_response + [status, headers, Merb::Rack::StreamWrapper.new(body)] + end + + +
+ + + (name, *args) + + +Alias for url +

+ ]]>
+ + +
+ + + (*args) + + +Generates a URL for a single or nested resource. +

+

Parameters

+ + +
resources<Symbol,Object>:The resources for which the URL + +
+
+  should be generated. These resources should be specified
+  in the router.rb file using #resources and #resource.
+
+ + +
options<Hash>:Any extra parameters that are needed to + +
+
+  generate the URL.
+
+

Returns

+ + +
String:The generated URL. + +
+

Examples

+

+Merb::Router.prepare do +

+
+  resources :users do
+    resources :comments
+  end
+
+

+end +

+

+resource(:users) # => /users resource(@user) # => /users/10 +resource(@user, :comments) # => /users/10/comments resource(@user, +@comment) # => /users/10/comments/15 resource(:users, :new) # => +/users/new resource(:@user, :edit) # => /users/10/edit +

+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/merb_controller.rb, line 321 + def resource(*args) + args << params + Merb::Router.resource(*args) + end + + +
+ + + () + + Returns + + +
Fixnum:The response status code + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/merb_controller.rb, line 206 + def status + @_status + end + + +
+ + + (s) + + +Sets the response status code. +

+

Parameters

+ + +
s<Fixnum, Symbol>:A status-code or named http-status + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/merb_controller.rb, line 216 + def status=(s) + if s.is_a?(Symbol) && STATUS_CODES.key?(s) + @_status = STATUS_CODES[s] + elsif s.is_a?(Fixnum) + @_status = s + else + raise ArgumentError, "Status should be of type Fixnum or Symbol, was #{s.class}" + end + end + + +
+ + + (name, *args) + + +There are three possible ways to use this method. First, if you have a +named route, you can specify the route as the first parameter as a symbol +and any parameters in a hash. Second, you can generate the default route by +just passing the params hash, just passing the params hash. Finally, you +can use the anonymous parameters. This allows you to specify the parameters +to a named route in the order they appear in the router. +

+

Parameters(Named Route)

+ + + +
name<Symbol>:The name of the route. + +
args<Hash>:Parameters for the route generation. + +
+

Parameters(Default Route)

+ + +
args<Hash>:Parameters for the route generation. This route will use the default route. + +
+

Parameters(Anonymous Parameters)

+ + + +
name<Symbol>:The name of the route. + +
args<Array>:An array of anonymous parameters to generate the route with. These +parameters are assigned to the route parameters in the order that they are +passed. + +
+

Returns

+ + +
String:The generated URL. + +
+

Examples

+

+Named Route +

+

+Merb::Router.prepare do +

+
+  match("/articles/:title").to(:controller => :articles, :action => :show).name("articles")
+
+

+end +

+

+url(:articles, :title => "new_article") +

+

+Default Route +

+

+Merb::Router.prepare do +

+
+  default_routes
+
+

+end +

+

+url(:controller => "articles", :action => "new") +

+

+Anonymous Parameters +

+

+Merb::Router.prepare do +

+
+  match("/articles/:year/:month/:title").to(:controller => :articles, :action => :show).name("articles")
+
+

+end +

+

+url(:articles, 2008, 10, "test_article") +

+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/merb_controller.rb, line 286 + def url(name, *args) + args << params + name = request.route if name == :this + Merb::Router.url(name, *args) + end + + +
+ + +
+ + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + lib/merb-core/server.rb + + + + + Object + + + + +Server encapsulates the management of Merb daemons. +

+ + ]]>
+ + + + + + + + + + + + + + (user, group=user) + + +Changes privileges of the process to the specified user and group. +

+

Parameters

+ + + +
user<String>:The user to change the process to. + +
group<String>:The group to change the process to. + +
+

Alternatives

+

+If group is left out, the user will be used as the group. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/server.rb, line 324 + def _change_privilege(user, group=user) + Merb.logger.warn! "Changing privileges to #{user}:#{group}" + + uid, gid = Process.euid, Process.egid + + begin + target_uid = Etc.getpwnam(user).uid + rescue ArgumentError => e + Merb.fatal!("Failed to change to user #{user}, does the user exist?", e) + return false + end + + begin + target_gid = Etc.getgrnam(group).gid + rescue ArgumentError => e + Merb.fatal!("Failed to change to group #{group}, does the group exist?", e) + return false + end + + if (uid != target_uid) || (gid != target_gid) + # Change process ownership + Process.initgroups(user, target_gid) + Process::GID.change_privilege(target_gid) + Process::UID.change_privilege(target_uid) + end + true + rescue Errno::EPERM => e + Merb.fatal! "Permission denied for changing user:group to #{user}:#{group}.", e + false + end + + +
+ + + () + + +Add trap to enter IRB on SIGINT. Process exit if second SIGINT is received. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/server.rb, line 358 + def add_irb_trap + Merb.trap("INT") do + if @interrupted + Merb.logger.warn! "Interrupt received a second time, exiting!\n" + exit + end + + @interrupted = true + Merb.logger.warn! "Interrupt a second time to quit." + Kernel.sleep 1.5 + ARGV.clear # Avoid passing args to IRB + + if @irb.nil? + require "irb" + IRB.setup(nil) + @irb = IRB::Irb.new(nil) + IRB.conf[:MAIN_CONTEXT] = @irb.context + end + + Merb.trap(:INT) { @irb.signal_handle } + catch(:IRB_EXIT) { @irb.eval_input } + + Merb.logger.warn! "Exiting from IRB mode back into server mode." + @interrupted = false + add_irb_trap + end + end + + +
+ + + (port) + + Parameters + + +
port<~to_s>:The port to check for Merb instances on. + +
+

Returns

+ + +
Boolean:True if Merb is running on the specified port. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/server.rb, line 54 + def alive?(port) + pidfile = pid_file(port) + pid = pid_in_file(pidfile) + Process.kill(0, pid) + true + rescue Errno::ESRCH, Errno::ENOENT + false + rescue Errno::EACCES => e + Merb.fatal!("You don't have access to the PID file at #{pidfile}: #{e.message}") + end + + +
+ + + () + + +Starts up Merb by running the bootloader and starting +the adapter. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/server.rb, line 168 + def bootup + Merb.trap("TERM") { shutdown } + + Merb.logger.warn! "Running bootloaders..." if Merb::Config[:verbose] + BootLoader.run + Merb.logger.warn! "Starting Rack adapter..." if Merb::Config[:verbose] + Merb.adapter.start(Merb::Config.to_hash) + end + + +
+ + + () + + +Changes process user/group to those specified in Merb::Config. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/server.rb, line 190 + def change_privilege + if Merb::Config[:user] && Merb::Config[:group] + Merb.logger.verbose! "About to change privilege to group " \ + "#{Merb::Config[:group]} and user #{Merb::Config[:user]}" + _change_privilege(Merb::Config[:user], Merb::Config[:group]) + elsif Merb::Config[:user] + Merb.logger.verbose! "About to change privilege to user " \ + "#{Merb::Config[:user]}" + _change_privilege(Merb::Config[:user]) + else + return true + end + end + + +
+ + + (port) + + Parameters + + +
port<~to_s>:The port of the Merb process to daemonize. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/server.rb, line 141 + def daemonize(port) + Merb.logger.warn! "About to fork..." if Merb::Config[:verbose] + fork do + Process.setsid + exit if fork + Merb.logger.warn! "In #{Process.pid}" if Merb.logger + File.umask 0000 + STDIN.reopen "/dev/null" + STDOUT.reopen "/dev/null", "a" + STDERR.reopen STDOUT + begin + Dir.chdir Merb::Config[:merb_root] + rescue Errno::EACCES => e + Merb.fatal! "You specified Merb root as #{Merb::Config[:merb_root]}, " \ + "yet the current user does not have access to it. ", e + end + at_exit { remove_pid_file(port) } + Merb::Config[:port] = port + bootup + end + rescue NotImplementedError => e + Merb.fatal! "Daemonized mode is not supported on your platform. ", e + end + + +
+ + + (port, sig = "INT") + + Parameters + + + +
port<~to_s>:The port of the Merb process to kill. + +
sig<~to_s>:The signal to send to the process, the default is 9 - SIGKILL. + +
+

+No Name Default Action Description 1 SIGHUP terminate process terminal line +hangup 2 SIGINT terminate process interrupt program 3 SIGQUIT create core +image quit program 4 SIGILL create core image illegal instruction 9 SIGKILL +terminate process kill program 15 SIGTERM terminate process software +termination signal 30 SIGUSR1 terminate process User defined signal 1 31 +SIGUSR2 terminate process User defined signal 2 +

+

Alternatives

+

+If you pass "all" as the port, the signal will be sent to all Merb processes. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/server.rb, line 88 + def kill(port, sig = "INT") + if sig.is_a?(Integer) + sig = Signal.list.invert[sig] + end + + Merb::BootLoader::BuildFramework.run + + # If we kill the master, then the workers should be reaped also. + if %w(main master all).include?(port) + # If a graceful exit is requested then send INT to the master process. + # + # Otherwise read pids from pid files and try to kill each process in turn. + kill_pid(sig, pid_file("main")) if sig == "INT" + else + kill_pid(sig, pid_file(port)) + end + end + + +
+ + + (sig, file) + + +Sends the provided signal to the process pointed at by the provided pid +file. :api: private +

+ ]]>
+ + + +# File lib/merb-core/server.rb, line 108 + def kill_pid(sig, file) + begin + pid = pid_in_file(file) + Merb.logger.fatal! "Killing pid #{pid} with #{sig}" + Process.kill(sig, pid) + FileUtils.rm(file) if File.exist?(file) + rescue Errno::EINVAL + Merb.logger.fatal! "Failed to kill PID #{pid} with #{sig}: '#{sig}' is an invalid " \ + "or unsupported signal number." + rescue Errno::EPERM + Merb.logger.fatal! "Failed to kill PID #{pid} with #{sig}: Insufficient permissions." + rescue Errno::ESRCH + FileUtils.rm file + Merb.logger.fatal! "Failed to kill PID #{pid} with #{sig}: Process is " \ + "deceased or zombie." + rescue Errno::EACCES => e + Merb.logger.fatal! e.message + rescue Errno::ENOENT => e + # This should not cause abnormal exit, which is why + # we do not use Merb.fatal but instead just log with max level. + Merb.logger.fatal! "Could not find a PID file at #{file}. " \ + "Most likely the process is no longer running and the pid file was not cleaned up." + rescue Exception => e + if !e.is_a?(SystemExit) + Merb.logger.fatal! "Failed to kill PID #{pid.inspect} with #{sig.inspect}: #{e.message}" + end + end + end + + +
+ + + (port) + + +Gets the pid file for the specified port/socket. +

+

Parameters

+ + +
port<~to_s>:The port/socket of the Merb process to whom the PID +file belongs to. + +
+

Returns

+ + +
String:Location of pid file for specified port. If clustered and pid_file option is specified, it adds the port/socket +value to the path. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/server.rb, line 290 + def pid_file(port) + pidfile = Merb::Config[:pid_file] || (Merb.log_path / "merb.%s.pid") + pidfile % port + end + + +
+ + + () + + +Gets a list of the pid files. +

+

Returns

+ + +
Array:List of pid file paths. If not running clustered, the array contains a +single path. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/server.rb, line 302 + def pid_files + if Merb::Config[:pid_file] + if Merb::Config[:cluster] + Dir[Merb::Config[:pid_file] % "*"] + else + [ Merb::Config[:pid_file] ] + end + else + Dir[Merb.log_path / "merb.*.pid"] + end + end + + +
+ + + (pidfile) + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/server.rb, line 66 + def pid_in_file(pidfile) + File.read(pidfile).chomp.to_i + end + + +
+ + + (port) + + +Deletes the pidfile for the specified port/socket. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/server.rb, line 245 + def remove_pid(port) + FileUtils.rm(pid_file(port)) if File.file?(pid_file(port)) + end + + +
+ + + (port) + + +Removes a PID file used by the server from the filesystem. This uses :pid_file options from configuration when provided or +merb.<port/socket>.pid in log directory by default. +

+

Parameters

+ + +
port<~to_s>:The port of the Merb process to whom the the PID file +belongs to. + +
+

Alternatives

+

+If Merb::Config[:pid_file] has been specified, that +will be used instead of the port/socket based PID file. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/server.rb, line 217 + def remove_pid_file(port) + pidfile = pid_file(port) + if File.exist?(pidfile) + Merb.logger.warn! "Removing pid file #{pidfile} (port/socket: #{port})..." + FileUtils.rm(pidfile) + end + end + + +
+ + + (status = 0) + + +Shut down Merb, reap any workers if necessary. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/server.rb, line 180 + def shutdown(status = 0) + # reap_workers does exit but may not be called... + Merb::BootLoader::LoadClasses.reap_workers(status) if Merb::Config[:fork_for_class_load] + # which is why we exit explicitly here + exit(status) + end + + +
+ + + (port, cluster=nil) + + +Starts a Merb server, in either foreground, daemonized +or cluster mode. +

+

Parameters

+ + + +
port<~to_i>:The port to which the first server instance should bind to. Subsequent +server instances bind to the immediately following ports. + +
cluster<~to_i>:Number of servers to run in a cluster. + +
+

Alternatives

+

+If cluster is left out, then one process will be started. This process will +be daemonized if Merb::Config[:daemonize] is true. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/server.rb, line 23 + def start(port, cluster=nil) + + @port = port + @cluster = cluster + + if Merb::Config[:daemonize] + pidfile = pid_file(port) + pid = File.read(pidfile).chomp.to_i if File.exist?(pidfile) + + unless alive?(@port) + remove_pid_file(@port) + Merb.logger.warn! "Daemonizing..." if Merb::Config[:verbose] + daemonize(@port) + else + Merb.fatal! "Merb is already running on port #{port}.\n" \ + "\e[0m \e[1;31;47mpid file: \e[34;47m#{pidfile}" \ + "\e[1;31;47m, process id is \e[34;47m#{pid}." + end + else + bootup + end + end + + +
+ + + (port = nil) + + +Stores a PID file on the filesystem. This uses :pid_file options from configuration when provided or +merb.<port/socket>.pid in log directory by default. +

+

Parameters

+ + +
port<~to_s>:The port of the Merb process to whom the PID file +belongs to. + +
+

Alternatives

+

+If Merb::Config[:pid_file] has been specified, that +will be used instead of the port/socket based PID file. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/server.rb, line 262 + def store_details(port = nil) + file = pid_file(port) + begin + FileUtils.mkdir_p(File.dirname(file)) + rescue Errno::EACCES => e + Merb.fatal! "Failed to store Merb logs in #{File.dirname(file)}, " \ + "permission denied. ", e + end + Merb.logger.warn! "Storing pid #{Process.pid} file to #{file}..." if Merb::Config[:verbose] + begin + File.open(file, 'w'){ |f| f.write(Process.pid.to_s) } + rescue Errno::EACCES => e + Merb.fatal! "Failed to access #{file}, permission denied.", e + end + end + + +
+ + + (port) + + +Stores a PID file on the filesystem. This uses :pid_file options from configuration when provided or +merb.<port>.pid in log directory by default. +

+

Parameters

+ + +
port<~to_s>:The port of the Merb process to whom the the PID file +belongs to. + +
+

Alternatives

+

+If Merb::Config[:pid_file] has been specified, that +will be used instead of the port/socket based PID file. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/server.rb, line 238 + def store_pid(port) + store_details(port) + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/dispatch/default_exception/default_exception.rb + + lib/merb-core/dispatch/dispatcher.rb + + + + + Object + + + + + + + + + + + + + + RW + + + + + + + + + + + + + (request) + + +Dispatch the rack environment. ControllerExceptions are rescued +here and redispatched. +

+

Parameters

+ + +
rack_env<Rack::Environment>:The rack environment, which is used to instantiate a Merb::Request + +
+

Returns

+ + +
Merb::Controller:The Merb::Controller that was dispatched to + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/dispatcher.rb, line 35 + def handle(request) + request.handle + end + + +
+ + + () + + Returns + + +
Queue:the current queue of dispatch jobs. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/dispatcher.rb, line 17 + def work_queue + @@work_queue + end + + +
+ + +
+ + + + + + + + + + + +
+ +
+ + + + + + + lib/merb-core/dispatch/default_exception/default_exception.rb + + + + + + + +:api: private +

+ + ]]>
+ + + + + + + + + + + + + + (exception) + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/default_exception/default_exception.rb, line 12 + def error_codes(exception) + if @show_details + message, message_details = exception.message.split("\n", 2) + "<h2>#{escape_html(message)}</h2><p>#{escape_html(message_details)}</p>" + else + "<h2>Sorry about that...</h2>" + end + end + + +
+ + + (line) + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/default_exception/default_exception.rb, line 22 + def frame_details(line) + filename, lineno, location = line.split(":") + if filename.index(Merb.framework_root) + type = "framework" + shortname = Pathname.new(filename).relative_path_from(Pathname.new(Merb.framework_root)) + elsif filename.index(Merb.root) + type = "app" + shortname = Pathname.new(filename).relative_path_from(Pathname.new(Merb.root)) + elsif path = Gem.path.find {|p| filename.index(p)} + type = "gem" + shortname = Pathname.new(filename).relative_path_from(Pathname.new(path)) + else + type = "other" + shortname = filename + end + [type, shortname, filename, lineno, location] + end + + +
+ + + (e) + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/default_exception/default_exception.rb, line 7 + def humanize_exception(e) + e.class.name.split("::").last.gsub(/([a-z])([A-Z])/, '\1 \2') + end + + +
+ + + (key, value, arr) + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/default_exception/default_exception.rb, line 41 + def listing(key, value, arr) + ret = [] + ret << "<table class=\"listing\" style=\"display: none\">" + ret << " <thead>" + ret << " <tr><th width='25%'>#{key}</th><th width='75%'>#{value}</th></tr>" + ret << " </thead>" + ret << " <tbody>" + (arr || []).each_with_index do |(key, val), i| + klass = i % 2 == 0 ? "even" : "odd" + ret << " <tr class=\"#{klass}\"><td>#{key}</td><td>#{val.inspect}</td></tr>" + end + if arr.blank? + ret << " <tr class='odd'><td colspan='2'>None</td></tr>" + end + ret << " </tbody>" + ret << "</table>" + ret.join("\n") + end + + +
+ + + (filename, line) + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/default_exception/default_exception.rb, line 66 + def render_source(filename, line) + line = line.to_i + ret = [] + ret << "<tr class='source'>" + ret << " <td class='collapse'></td>" + str = " <td class='code' colspan='2'><div>" + + __caller_lines__(filename, line, 5) do |lline, lcode| + str << "<a href='txmt://open?url=file://#{filename}&amp;line=#{lline}'>#{lline}</a>" + str << "<em>" if line == lline + str << Erubis::XmlHelper.escape_xml(lcode) + str << "</em>" if line == lline + str << "\n" + end + str << "</div></td>" + ret << str + ret << "</tr>" + ret.join("\n") + end + + +
+ + + (filename, line) + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/default_exception/default_exception.rb, line 61 + def textmate_url(filename, line) + "<a href='txmt://open?url=file://#{filename}&amp;line=#{line}'>#{line}</a>" + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/dispatch/default_exception/default_exception.rb + + + + + Merb::Controller + + + + +:api: private +

+ + ]]>
+ + + + + + + + + + + + + + (context, type = nil, controller = controller_name) + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/default_exception/default_exception.rb, line 92 + def _template_location(context, type = nil, controller = controller_name) + "#{context}.#{type}" + end + + +
+ + + () + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/default_exception/default_exception.rb, line 97 + def index + @exceptions = request.exceptions + @show_details = Merb::Config[:exception_details] + render :format => :html + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/dispatch/dispatcher.rb + + lib/merb-core/dispatch/request.rb + + + + + Object + + + + + + + + + + + + + %w{get post put delete head options} + + + + + + + + + + + + RW + + + + + + + RW + + + + + + + RW + + + + + + + R + + + + + + + + + + + + + (rack_env) + + +Initializes the request object. +

+

Parameters

+ + +
http_request<~params:~[], ~body:IO>:An object like an HTTP Request. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/request.rb, line 38 + def initialize(rack_env) + @env = rack_env + @body = rack_env[Merb::Const::RACK_INPUT] + @route_params = {} + end + + +
+ + +
+ + + + + + (retval) + + Notes +

+Processes the return value of a deferred router block and returns the +current route params for the current request evaluation +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/request.rb, line 126 + def _process_block_return(retval) + # If the return value is an array, then it is a redirect + # so we must set the request as a redirect and extract + # the redirect params and return it as a hash so that the + # dispatcher can handle it + matched! if retval.is_a?(Array) + retval + end + + +
+ + + () + + Returns + + +
String:The accepted response types. Defaults to "/". + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/request.rb, line 491 + def accept + @env[Merb::Const::HTTP_ACCEPT].blank? ? "*/*" : @env[Merb::Const::HTTP_ACCEPT] + end + + +
+ + + () + + Returns + + +
String:The accepted character sets. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/request.rb, line 467 + def accept_charset + @env[Merb::Const::HTTP_ACCEPT_CHARSET] + end + + +
+ + + () + + Returns + + +
String:The accepted encodings. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/request.rb, line 419 + def accept_encoding + @env[Merb::Const::HTTP_ACCEPT_ENCODING] + end + + +
+ + + () + + Returns + + +
String:The accepted language. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/request.rb, line 443 + def accept_language + @env[Merb::Const::HTTP_ACCEPT_LANGUAGE] + end + + +
+ + + () + + +Alias for xml_http_request? +

+ ]]>
+ + +
+ + + () + + Returns + + +
String:HTTP cache control. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/request.rb, line 435 + def cache_control + @env[Merb::Const::HTTP_CACHE_CONTROL] + end + + +
+ + + () + + Returns + + +
String:The HTTP connection. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/request.rb, line 499 + def connection + @env[Merb::Const::HTTP_CONNECTION] + end + + +
+ + + () + + Returns + + +
Fixnum:The request content length. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/request.rb, line 523 + def content_length + @content_length ||= @env[Merb::Const::CONTENT_LENGTH].to_i + end + + +
+ + + () + + Returns + + +
String:The request content type. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/request.rb, line 515 + def content_type + @env[Merb::Const::UPCASE_CONTENT_TYPE] + end + + +
+ + + () + + +Returns the controller object for initialization and dispatching the +request. +

+

Returns

+ + +
Class:The controller class matching the routed request, + +
+
+  e.g. Posts.
+
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/request.rb, line 52 + def controller + unless params[:controller] + raise ControllerExceptions::NotFound, + "Route matched, but route did not specify a controller.\n" + + "Did you forgot to add :controller => \"people\" or :controller " + + "segment to route definition?\nHere is what's specified:\n" + + route.inspect + end + path = [params[:namespace], params[:controller]].compact.join(Merb::Const::SLASH) + controller = path.snake_case.to_const_string + + begin + Object.full_const_get(controller) + rescue NameError => e + msg = "Controller class not found for controller `#{path}'" + Merb.logger.warn!(msg) + raise ControllerExceptions::NotFound, msg + end + end + + +
+ + + (tld_length = 1) + + Parameters + + +
tld_length<Fixnum>:Number of domains levels to include in the top level domain. Defaults to 1. + +
+

Returns

+ + +
String:The full domain name without the port number. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/request.rb, line 589 + def domain(tld_length = 1) + host.split(Merb::Const::DOT).last(1 + tld_length).join(Merb::Const::DOT).sub(/:\d+$/,'') + end + + +
+ + + () + + Notes +

+Finds route using requested URI and merges route parameters (:action, +:controller and named segments) into request params hash. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/request.rb, line 115 + def find_route! + @route, @route_params = Merb::Router.route_for(self) + params.merge! @route_params if @route_params.is_a?(Hash) + end + + +
+ + + () + + Returns + + +
String:The full URI, including protocol and host + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/request.rb, line 387 + def full_uri + protocol + "://" + host + uri + end + + +
+ + + () + + Returns + + +
String:The gateway. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/request.rb, line 483 + def gateway + @env[Merb::Const::GATEWAY_INTERFACE] + end + + +
+ + + () + + +Handles request routing and action dispatch. +

+

Returns

+ + +
Merb::Controller:the controller that handled the action dispatch. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/dispatcher.rb, line 52 + def handle + start = Time.now + Merb.logger.info "Started request handling: #{start.to_s}" + + find_route! + return rack_response if handled? + + klass = controller + Merb.logger.debug("Routed to: #{params.inspect}") + + unless klass < Controller + raise NotFound, + "Controller '#{klass}' not found.\n" \ + "If Merb tries to find a controller for static files, " \ + "you may need to check your Rackup file, see the Problems " \ + "section at: http://wiki.merbivore.com/pages/rack-middleware" + end + + if klass.abstract? + raise NotFound, "The '#{klass}' controller has no public actions" + end + + controller = dispatch_action(klass, params[:action]) + controller._benchmarks[:dispatch_time] = Time.now - start + Merb.logger.info controller._benchmarks.inspect + Merb.logger.flush + controller.rack_response + rescue Object => exception + dispatch_exception(exception).rack_response + end + + +
+ + + () + + +If @route_params is an Array, then it will be the rack response. In this +case, the request is considered handled. +

+

Returns

+ + +
Boolean:true if @route_params is an Array, false otherwise. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/request.rb, line 170 + def handled? + @route_params.is_a?(Array) + end + + +
+ + + () + + Returns + + +
String:The full hostname including the port. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/request.rb, line 561 + def host + @env[Merb::Const::HTTP_X_FORWARDED_HOST] || @env[Merb::Const::HTTP_HOST] || + @env[Merb::Const::SERVER_NAME] + end + + +
+ + + () + + Returns +

+Value of If-Modified-Since request header. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/request.rb, line 605 + def if_modified_since + if time = @env[Merb::Const::HTTP_IF_MODIFIED_SINCE] + Time.rfc2822(time) + end + end + + +
+ + + () + + Returns +

+Value of If-None-Match request header. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/request.rb, line 597 + def if_none_match + @env[Merb::Const::HTTP_IF_NONE_MATCH] + end + + +
+ + + () + + Returns + + +
String:Value of HTTP_KEEP_ALIVE. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/request.rb, line 459 + def keep_alive + @env[Merb::Const::HTTP_KEEP_ALIVE] + end + + +
+ + + () + + +Sets the request as matched. This will abort evaluating any further +deferred procs. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/request.rb, line 139 + def matched! + @matched = true + end + + +
+ + + () + + +Checks whether or not the request has been matched to a route. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/request.rb, line 146 + def matched? + @matched + end + + +
+ + + () + + Returns + + +
String:Returns the redirect message Base64 unencoded. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/request.rb, line 303 + def message + return {} unless params[:_message] + begin + Marshal.load(Merb::Parse.unescape(params[:_message]).unpack("m").first) + rescue ArgumentError, TypeError + {} + end + end + + +
+ + + () + + Returns + + +
Symbol:The name of the request method, e.g. :get. + +
+

Notes

+

+If the method is post, then the blocks specified in http_method_overrides +will be checked for the masquerading method. The block will get the +controller yielded to it. The first matching workaround wins. To disable +this behavior, set http_method_overrides = [] +

+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/request.rb, line 84 + def method + @method ||= begin + request_method = @env[Merb::Const::REQUEST_METHOD].downcase.to_sym + case request_method + when :get, :head, :put, :delete, :options + request_method + when :post + m = nil + self.class.http_method_overrides.each do |o| + m ||= o.call(self); break if m + end + m.downcase! if m + METHODS.include?(m) ? m.to_sym : :post + else + raise "Unknown REQUEST_METHOD: #{@env[Merb::Const::REQUEST_METHOD]}" + end + end + end + + +
+ + + () + + Returns + + +
Mash:All request parameters. + +
+

Notes

+

+The order of precedence for the params is XML, JSON, multipart, body and +request string. +

+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/request.rb, line 289 + def params + @params ||= begin + h = body_and_query_params.merge(route_params) + h.merge!(multipart_params) if self.class.parse_multipart_params && multipart_params + h.merge!(json_params) if self.class.parse_json_params && json_params + h.merge!(xml_params) if self.class.parse_xml_params && xml_params + h + end + end + + +
+ + + () + + Returns + + +
String:The URI without the query string. Strips trailing "/" and reduces +duplicate "/" to a single "/". + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/request.rb, line 533 + def path + # Merb::Const::SLASH is / + # Merb::Const::QUESTION_MARK is ? + path = (uri.empty? ? Merb::Const::SLASH : uri.split(Merb::Const::QUESTION_MARK).first).squeeze(Merb::Const::SLASH) + path = path[0..-2] if (path[-1] == ?/) && path.size > 1 + path + end + + +
+ + + () + + Returns + + +
String:The path info. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/request.rb, line 545 + def path_info + @path_info ||= Merb::Parse.unescape(@env[Merb::Const::PATH_INFO]) + end + + +
+ + + () + + Returns + + +
Fixnum:The server port. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/request.rb, line 553 + def port + @env[Merb::Const::SERVER_PORT].to_i + end + + +
+ + + () + + Returns + + +
String:The protocol, i.e. either "https" or "http" depending +on the HTTPS header. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/request.rb, line 363 + def protocol + ssl? ? Merb::Const::HTTPS : Merb::Const::HTTP + end + + +
+ + + () + + Returns + + +
String:The query string. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/request.rb, line 507 + def query_string + @env[Merb::Const::QUERY_STRING] + end + + +
+ + + () + + Returns + + +
(Array, Hash):the route params for the matched route. + +
+

Notes

+

+If the response is an Array then it is considered a direct Rack response to be sent back as a response. +Otherwise, the route_params is a Hash with routing data +(controller, action, et al). +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/request.rb, line 159 + def rack_response + @route_params + end + + +
+ + + () + + Returns + + +
String:The raw post. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/request.rb, line 324 + def raw_post + @body.rewind if @body.respond_to?(:rewind) + @raw_post ||= @body.read + end + + +
+ + + () + + Returns + + +
String:The HTTP referer. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/request.rb, line 379 + def referer + @env[Merb::Const::HTTP_REFERER] + end + + +
+ + + () + + Returns + + +
String:The remote IP address. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/request.rb, line 343 + def remote_ip + return @env[Merb::Const::HTTP_CLIENT_IP] if @env.include?(Merb::Const::HTTP_CLIENT_IP) + + if @env.include?(Merb::Const::HTTP_X_FORWARDED_FOR) then + remote_ips = @env[Merb::Const::HTTP_X_FORWARDED_FOR].split(',').reject do |ip| + ip =~ Merb::Const::LOCAL_IP_REGEXP + end + + return remote_ips.first.strip unless remote_ips.empty? + end + + return @env[Merb::Const::REMOTE_ADDR] + end + + +
+ + + () + + Notes +

+Resets the params to a nil value. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/request.rb, line 316 + def reset_params! + @params = nil + end + + +
+ + + () + + Returns + + +
String:The script name. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/request.rb, line 427 + def script_name + @env[Merb::Const::SCRIPT_NAME] + end + + +
+ + + () + + Returns + + +
String:The server name. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/request.rb, line 411 + def server_name + @env[Merb::Const::SERVER_NAME] + end + + +
+ + + () + + Returns + + +
String:The server software. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/request.rb, line 451 + def server_software + @env[Merb::Const::SERVER_SOFTWARE] + end + + +
+ + + () + + Returns + + +
Boolean::True if the request is an SSL request. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/request.rb, line 371 + def ssl? + @env[Merb::Const::UPCASE_HTTPS] == 'on' || @env[Merb::Const::HTTP_X_FORWARDED_PROTO] == Merb::Const::HTTPS + end + + +
+ + + (tld_length = 1) + + Parameters + + +
tld_length<Fixnum>:Number of domains levels to include in the top level domain. Defaults to 1. + +
+

Returns

+ + +
Array:All the subdomain parts of the host. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/request.rb, line 575 + def subdomains(tld_length = 1) + parts = host.split(Merb::Const::DOT) + parts[0..-(tld_length+2)] + end + + +
+ + + () + + Returns + + +
String:The request URI. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/request.rb, line 395 + def uri + @env[Merb::Const::REQUEST_PATH] || @env[Merb::Const::REQUEST_URI] || path_info + end + + +
+ + + () + + Returns + + +
String:The HTTP user agent. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/request.rb, line 403 + def user_agent + @env[Merb::Const::HTTP_USER_AGENT] + end + + +
+ + + () + + Returns + + +
String:The HTTP version + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/request.rb, line 475 + def version + @env[Merb::Const::HTTP_VERSION] + end + + +
+ + + () + + +Alias for xml_http_request? +

+ ]]>
+ + +
+ + + () + + Returns + + +
Boolean:If the request is an XML HTTP request. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/request.rb, line 333 + def xml_http_request? + not Merb::Const::XML_HTTP_REQUEST_REGEXP.match(@env[Merb::Const::HTTP_X_REQUESTED_WITH]).nil? + end + + +
+ + +
+ + + + + + + + + + + +
+ +
+ + + + + + + lib/merb-core/dispatch/cookies.rb + + + + + Mash + + + + + + + + + + + + + + + + (constructor = {}) + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/cookies.rb, line 6 + def initialize(constructor = {}) + @_options_lookup = Mash.new + @_cookie_defaults = { "domain" => Merb::Controller._default_cookie_domain, "path" => '/' } + super constructor + end + + +
+ + +
+ + + + + + (key, value) + + +Implicit assignment of cookie key and value. +

+

Parameters

+ + + +
name<~to_s>:Name of the cookie. + +
value<~to_s>:Value of the cookie. + +
+

Notes

+

+By using this method, a cookie key is marked for being included in the +Set-Cookie response header. +

+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/cookies.rb, line 23 + def []=(key, value) + @_options_lookup[key] ||= {} + super + end + + +
+ + + (name, options = {}) + + +Removes the cookie on the client machine by setting the value to an empty +string and setting its expiration date into the past. +

+

Parameters

+ + + +
name<~to_s>:Name of the cookie to delete. + +
options<Hash>:Additional options to pass to set_cookie. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/cookies.rb, line 59 + def delete(name, options = {}) + set_cookie(name, "", options.merge("expires" => Time.at(0))) + end + + +
+ + + (controller_defaults = {}) + + +Generates any necessary headers. +

+

Returns

+ + +
Hash:The headers to set, or an empty array if no cookies are set. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/cookies.rb, line 69 + def extract_headers(controller_defaults = {}) + defaults = @_cookie_defaults.merge(controller_defaults) + cookies = [] + self.each do |name, value| + # Only set cookies that marked for inclusion in the response header. + next unless @_options_lookup[name] + options = defaults.merge(@_options_lookup[name]) + if (expiry = options["expires"]).respond_to?(:gmtime) + options["expires"] = expiry.gmtime.strftime(Merb::Const::COOKIE_EXPIRATION_FORMAT) + end + secure = options.delete("secure") + kookie = "#{name}=#{Merb::Parse.escape(value)}; " + # WebKit in particular doesn't like empty cookie options - skip them. + options.each { |k, v| kookie << "#{k}=#{v}; " unless v.blank? } + kookie << 'secure' if secure + cookies << kookie.rstrip + end + cookies.empty? ? {} : { 'Set-Cookie' => cookies } + end + + +
+ + + (name, value, options = {}) + + +Explicit assignment of cookie key, value and options +

+

Parameters

+ + + + +
name<~to_s>:Name of the cookie. + +
value<~to_s>:Value of the cookie. + +
options<Hash>:Additional options for the cookie (see below). + +
+

Options (options)

+ + + + + +
:path<String>:The path for which this cookie applies. Defaults to "/". + +
:expires<Time>:Cookie expiry date. + +
:domain<String>:The domain for which this cookie applies. + +
:secure<Boolean>:Security flag. + +
+

Notes

+

+By using this method, a cookie key is marked for being included in the +Set-Cookie response header. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/cookies.rb, line 46 + def set_cookie(name, value, options = {}) + @_options_lookup[name] = options + self[name] = value + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/controller/abstract_controller.rb + + + + + Object + + + + Why do we use Underscores? +

+In Merb, views are actually methods on controllers. +This provides not-insignificant speed benefits, as well as preventing us +from needing to copy over instance variables, which we think is proof that +everything belongs in one class to begin with. +

+

+Unfortunately, this means that view helpers need to be included into the +<strong>Controller</strong> class. To avoid causing confusion +when your helpers potentially conflict with our instance methods, we use an +_ to disambiguate. As long as you don’t begin your helper methods +with _, you only need to worry about conflicts with Merb methods that are part of the public API. +

+

Filters

+

+before is a class method that allows you to specify +before filters in your controllers. Filters can either be a symbol or +string that corresponds to a method name to call, or a proc object. if it +is a method name that method will be called and if it is a proc it will be +called with an argument of self where self is the current controller +object. When you use a proc as a filter it needs to take one parameter. +

+

+after is identical, but the filters are run after +the action is invoked. +

+
Examples
+
+  before :some_filter
+  before :authenticate, :exclude => [:login, :signup]
+  before :has_role, :with => ["Admin"], :exclude => [:index, :show]
+  before Proc.new { some_method }, :only => :foo
+  before :authorize, :unless => :logged_in?
+
+

+You can use either :only => :actionname or :exclude => +[:this, :that] but not both at once. :only will only run +before the listed actions and :exclude will run for every action +that is not listed. +

+

+Merb’s before filter chain is very flexible. To halt the filter chain +you use throw :halt. If throw is called with only one +argument of :halt the return value of the method +filters_halted will be what is rendered to the view. You can +override filters_halted in your own controllers to control what it +outputs. But the throw construct is much more powerful than just +that. +

+

+throw :halt can also take a second argument. Here is what that +second argument can be and the behavior each type can have: +

+
    +
  • String: when the second argument is a string then that string will +be what is rendered to the browser. Since merb’s render +method returns a string you can render a template or just use a plain +string: + +
    +  throw :halt, "You don't have permissions to do that!"
    +  throw :halt, render(:action => :access_denied)
    +
    +
  • +
  • Symbol: If the second arg is a symbol, then the method named after +that symbol will be called + +
    +  throw :halt, :must_click_disclaimer
    +
    +
  • +
  • Proc: If the second arg is a Proc, it will be called and its +return value will be what is rendered to the browser: + +
    +  throw :halt, proc { access_denied }
    +  throw :halt, proc { Tidy.new(c.index) }
    +
    +
  • +
+
Filter Options (.before, .after, .add_filter, .if, .unless)
+ + + + + + +
:only<Symbol, Array[Symbol]>:A list of actions that this filter should apply to + +
:exclude<Symbol, Array[Symbol]:A list of actions that this filter should not apply to + +
:if<Symbol, Proc>:Only apply the filter if the method named after the symbol or calling the +proc evaluates to true + +
:unless<Symbol, Proc>:Only apply the filter if the method named after the symbol or calling the +proc evaluates to false + +
:with<Array[Object]>:Arguments to be passed to the filter. Since we are talking method/proc +calls, filter method or Proc should to have the same arity as number of +elements in Array you pass to this option. + +
+
Types (shortcuts for use in this file)
+ + +
Filter:<Array[Symbol, (Symbol, String, Proc)]> + +
+

params[:action] and params[:controller] deprecated

+

+params[:action] and params[:controller] have been +deprecated as of the 0.9.0 release. They are no longer set during dispatch, +and have been replaced by action_name and controller_name respectively. +

+ + ]]>
+ + + + + + + + + + + [:only, :exclude, :if, :unless, :with] + + + + + + + + + + + + RW + + + + + + + RW + + + + + + + RW + + + + + + + RW + + + + + + + RW + + RenderMixin doesn’t throw errors :api: +private + +]]> + + + + + + + + + + + () + + +Resets the template root based on the @_template_root ivar. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/controller/abstract_controller.rb, line 201 + def self._reset_template_roots + self.template_roots = [[self._template_root, :_template_location]] + end + + +
+ + + (root) + + +Resets the template roots to the template root passed in. +

+

Parameters

+ + +
root<~to_s>:The new path to set the template root to. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/abstract_controller.rb, line 193 + def self._template_root=(root) + @_template_root = root + _reset_template_roots + end + + +
+ + + () + + Returns + + +
roots<Array[Array]>:Template roots as pairs of template root path +and template location method. + +
+

+:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/controller/abstract_controller.rb, line 211 + def self._template_roots + self.template_roots || _reset_template_roots + end + + +
+ + + (roots) + + Parameters + + +
roots<Array[Array]>:Template roots as pairs of template root path +and template location method. + +
+

+:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/controller/abstract_controller.rb, line 221 + def self._template_roots=(roots) + self.template_roots = roots + end + + +
+ + + (filter = nil, opts = {}, &block) + + +Adds a filter to the after filter chain +

+

Parameters

+ + + + +
filter<Symbol, Proc>:The filter to add. Defaults to nil. + +
opts<Hash>:Filter options (see class documentation under Filter Options). + +
&block:A block to use as a filter if filter is nil. + +
+

Notes

+

+If the filter already exists, its options will be replaced with opts.; +

+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/abstract_controller.rb, line 441 + def self.after(filter = nil, opts = {}, &block) + add_filter(self._after_filters, filter || block, opts) + end + + +
+ + + (filter = nil, opts = {}, &block) + + +Adds a filter to the before filter chain. +

+

Parameters

+ + + + +
filter<Symbol, Proc>:The filter to add. Defaults to nil. + +
opts<Hash>:Filter options (see class documentation under Filter Options). + +
&block:A block to use as a filter if filter is nil. + +
+

Notes

+

+If the filter already exists, its options will be replaced with opts. +

+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/abstract_controller.rb, line 457 + def self.before(filter = nil, opts = {}, &block) + add_filter(self._before_filters, filter || block, opts) + end + + +
+ + + () + + Returns + + +
String:The controller name in path form, e.g. "admin/items". + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/abstract_controller.rb, line 128 + def self.controller_name() @controller_name ||= self.name.to_const_path end + + +
+ + + (klass) + + Parameters + + +
klass<Merb::AbstractController>:The controller that is being inherited from Merb::AbstractController + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/controller/abstract_controller.rb, line 239 + def self.inherited(klass) + _abstract_subclasses << klass.to_s + helper_module_name = klass.to_s =~ /^(#|Merb::)/ ? "#{klass}Helper" : "Merb::#{klass}Helper" + Object.make_module helper_module_name + klass.class_eval "include Object.full_const_get(\"\#{helper_module_name}\") rescue nil\n" + super + end + + +
+ + + (*args) + + +This will initialize the controller, it is designed to be overridden in +subclasses (like MerbController) +

+

Parameters

+ + +
*args:The args are ignored in this class, but we need this so that subclassed +initializes can have parameters + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/controller/abstract_controller.rb, line 256 + def initialize(*args) + @_benchmarks = {} + @_caught_content = {} + end + + +
+ + + (filter) + + +Removes a filter from the after filter chain. This removes the filter from +the filter chain for the whole controller and does not take any options. +

+

Parameters

+ + +
filter<Symbol, String>:A filter name to skip. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/abstract_controller.rb, line 469 + def self.skip_after(filter) + skip_filter(self._after_filters, filter) + end + + +
+ + + (filter) + + +Removes a filter from the before filter chain. This removes the filter from +the filter chain for the whole controller and does not take any options. +

+

Parameters

+ + +
filter<Symbol, String>:A filter name to skip. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/abstract_controller.rb, line 481 + def self.skip_before(filter) + skip_filter(self._before_filters , filter) + end + + +
+ + + () + + +Returns the list of classes that have specifically subclassed AbstractController. Does not include +all descendants. +

+

Returns

+ + +
Set:The subclasses. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/controller/abstract_controller.rb, line 232 + def self.subclasses_list() _abstract_subclasses end + + +
+ + +
+ + + + + + (template, type) + + Returns + + +
String:The location to look for a template - override this method for particular +behaviour. + +
+

Parameters

+ + + +
template<String>:The absolute path to a template - without template extension. + +
type<~to_s>:The mime-type of the template that will be rendered. Defaults to being +called with nil. + +
+

+:api: public @overridable +

+ ]]>
+ + + +# File lib/merb-core/controller/abstract_controller.rb, line 182 + def _absolute_template_location(template, type) + template + end + + +
+ + + (action) + + +This method exists to provide an overridable hook for ActionArgs. It uses +send to call the action method. +

+

Parameters

+ + +
action<~to_s>:the action method to dispatch to + +
+

+:api: plugin @overridable +

+ ]]>
+ + + +# File lib/merb-core/controller/abstract_controller.rb, line 314 + def _call_action(action) + send(action) + end + + +
+ + + (rule, action_name) + + +Determines whether the filter should be called for the current action using +:only and :exclude. +

+

Parameters

+ + + +
rule<Hash>:Rules for the filter (see below). + +
action_name<~to_s>:The name of the action to be called. + +
+

Options (rule)

+ + + +
:only<Array>:Optional list of actions to fire. If given, action_name must be a part of +it for this function to return true. + +
:exclude<Array>:Optional list of actions not to fire. If given, action_name must not be a +part of it for this function to return true. + +
+

Returns

+ + +
Boolean:True if the action should be called. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/controller/abstract_controller.rb, line 373 + def _call_filter_for_action?(rule, action_name) + # Both: + # * no :only or the current action is in the :only list + # * no :exclude or the current action is not in the :exclude list + (!rule.key?(:only) || rule[:only].include?(action_name)) && + (!rule.key?(:exclude) || !rule[:exclude].include?(action_name)) + end + + +
+ + + (filter_set) + + +Calls a filter chain. +

+

Parameters

+ + +
filter_set<Array[Filter]>:A set of filters in the form [[:filter, rule], [:filter, rule]] + +
+

Returns

+ + +
Symbol::filter_chain_completed. + +
+

Notes

+

+Filter rules can be Symbols, Strings, or Procs. +

+ + + +
Symbols or Strings:Call the method represented by the Symbol or String. + +
Procs:Execute the Proc, in the context of the controller (self will be +the controller) + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/controller/abstract_controller.rb, line 337 + def _call_filters(filter_set) + (filter_set || []).each do |filter, rule| + if _call_filter_for_action?(rule, action_name) && _filter_condition_met?(rule) + case filter + when Symbol, String + if rule.key?(:with) + args = rule[:with] + send(filter, *args) + else + send(filter) + end + when Proc then self.instance_eval(&filter) + end + end + end + return :filter_chain_completed + end + + +
+ + + (action) + + +This will dispatch the request, calling internal before/after dispatch +callbacks. If the return value of _call_filters is +not :filter_chain_completed the action is not called, and the return from +the filters is used instead. +

+

Parameters

+ + +
action<~to_s>:The action to dispatch to. This will be send‘ed in _call_action. +Defaults to :to_s. + +
+

Returns

+ + +
<~to_s>:Returns the string that was returned from the action. + +
+

Raises

+ + +
ArgumentError:Invalid result caught from before filters. + +
+

+:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/controller/abstract_controller.rb, line 277 + def _dispatch(action) + self.action_name = action + self._before_dispatch_callbacks.each { |cb| cb.call(self) } + + caught = catch(:halt) do + start = Time.now + result = _call_filters(_before_filters) + @_benchmarks[:before_filters_time] = Time.now - start if _before_filters + result + end + + @body = case caught + when :filter_chain_completed then _call_action(action_name) + when String then caught + # return *something* if you throw halt with nothing + when nil then "<html><body><h1>Filter Chain Halted!</h1></body></html>" + when Symbol then __send__(caught) + when Proc then self.instance_eval(&caught) + else + raise ArgumentError, "Threw :halt, #{caught}. Expected String, nil, Symbol, Proc." + end + start = Time.now + _call_filters(_after_filters) + @_benchmarks[:after_filters_time] = Time.now - start if _after_filters + + self._after_dispatch_callbacks.each { |cb| cb.call(self) } + + @body + end + + +
+ + + (condition) + + +Evaluates a filter condition (:if or :unless) +

+

Parameters

+ + +
condition<Symbol, Proc>:The condition to evaluate. + +
+

Raises

+ + +
ArgumentError:condition not a Symbol or Proc. + +
+

Returns

+ + +
Boolean:True if the condition is met. + +
+

Alternatives

+

+If condition is a symbol, it will be send’ed. If it is a Proc it will +be called directly with self as an argument. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/controller/abstract_controller.rb, line 419 + def _evaluate_condition(condition) + case condition + when Symbol : self.send(condition) + when Proc : self.instance_eval(&condition) + else + raise ArgumentError, + 'Filter condtions need to be either a Symbol or a Proc' + end + end + + +
+ + + (rule) + + +Determines whether the filter should be run based on the conditions passed +(:if and :unless) +

+

Parameters

+ + +
rule<Hash>:Rules for the filter (see below). + +
+

Options (rule)

+ + + +
:if<Array>:Optional conditions that must be met for the filter to fire. + +
:unless<Array>:Optional conditions that must not be met for the filter to fire. + +
+

Returns

+ + +
Boolean:True if the conditions are met. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/controller/abstract_controller.rb, line 395 + def _filter_condition_met?(rule) + # Both: + # * no :if or the if condition evaluates to true + # * no :unless or the unless condition evaluates to false + (!rule.key?(:if) || _evaluate_condition(rule[:if])) && + (!rule.key?(:unless) || ! _evaluate_condition(rule[:unless])) + end + + +
+ + + (context, type, controller) + + +This is called after the controller is instantiated to figure out where to +look for templates under the _template_root. Override this to define a new +structure for your app. +

+

Parameters

+ + + + +
context<~to_s>:The controller context (the action or template name). + +
type<~to_s>:The content type. Could be nil. + +
controller<~to_s>:The name of the controller. Defaults to being called with the +controller_name. Set t + +
+

Returns

+ + +
String:Indicating where to look for the template for the current controller, +context, and content-type. + +
+

Notes

+

+The type is irrelevant for controller-types that don’t support +content-type negotiation, so we default to not include it in the +superclass. +

+

Examples

+
+  def _template_location
+    "#{params[:controller]}.#{params[:action]}.#{content_type}"
+  end
+
+

+This would look for templates at controller.action.mime.type instead of +controller/action.mime.type +

+

+:api: public @overridable +

+ ]]>
+ + + +# File lib/merb-core/controller/abstract_controller.rb, line 167 + def _template_location(context, type, controller) + controller ? "#{controller}/#{context}" : context + end + + +
+ + + (*args) + + +Returns the absolute url including the passed protocol and host. +

+

+This uses the same arguments as the url method, with added requirements of +protocol and host options. +

+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/abstract_controller.rb, line 552 + def absolute_url(*args) + options = extract_options_from_args!(args) || {} + protocol = options.delete(:protocol) + host = options.delete(:host) + + raise ArgumentError, "The :protocol option must be specified" unless protocol + raise ArgumentError, "The :host option must be specified" unless host + + args << options + + protocol + "://" + host + url(*args) + end + + +
+ + + (*args) {|*args| ...} + + +Calls the capture method for the selected template engine. +

+

Parameters

+ + + +
*args:Arguments to pass to the block. + +
&block:The block to call. + +
+

Returns

+ + +
String:The output of a template block or the return value of a non-template block +converted to a string. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/abstract_controller.rb, line 609 + def capture(*args, &block) + ret = nil + + captured = send("capture_#{@_engine}", *args) do |*args| + ret = yield *args + end + + # return captured value only if it is not empty + captured.empty? ? ret.to_s : captured + end + + +
+ + + (str, binding) + + +Calls the concatenate method for the selected template engine. +

+

Parameters

+ + + +
str<String>:The string to concatenate to the buffer. + +
binding<Binding>:The binding to use for the buffer. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/abstract_controller.rb, line 627 + def concat(str, binding) + send("concat_#{@_engine}", str, binding) + end + + +
+ + + () + + Returns + + +
String:The controller name in path form, e.g. "admin/items". + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/abstract_controller.rb, line 134 + def controller_name() self.class.controller_name end + + +
+ + + (name, *args) + + +Alias for url +

+ ]]>
+ + +
+ + + (*args) + + +Generates a URL for a single or nested resource. +

+

Parameters

+ + +
resources<Symbol,Object>:The resources for which the URL + +
+
+  should be generated. These resources should be specified
+  in the router.rb file using #resources and #resource.
+
+ + +
options<Hash>:Any extra parameters that are needed to + +
+
+  generate the URL.
+
+

Returns

+ + +
String:The generated URL. + +
+

Examples

+

+Merb::Router.prepare do +

+
+  resources :users do
+    resources :comments
+  end
+
+

+end +

+

+resource(:users) # => /users resource(@user) # => /users/10 +resource(@user, :comments) # => /users/10/comments resource(@user, +@comment) # => /users/10/comments/15 resource(:users, :new) # => +/users/new resource(:@user, :edit) # => /users/10/edit +

+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/abstract_controller.rb, line 594 + def resource(*args) + args << {} + Merb::Router.resource(*args) + end + + +
+ + + (name, *args) + + +There are three possible ways to use this method. First, if you have a +named route, you can specify the route as the first parameter as a symbol +and any paramters in a hash. Second, you can generate the default route by +just passing the params hash, just passing the params hash. Finally, you +can use the anonymous parameters. This allows you to specify the parameters +to a named route in the order they appear in the router. +

+

Parameters(Named Route)

+ + + +
name<Symbol>:The name of the route. + +
args<Hash>:Parameters for the route generation. + +
+

Parameters(Default Route)

+ + +
args<Hash>:Parameters for the route generation. This route will use the default route. + +
+

Parameters(Anonymous Parameters)

+ + + +
name<Symbol>:The name of the route. + +
args<Array>:An array of anonymous parameters to generate the route with. These +parameters are assigned to the route parameters in the order that they are +passed. + +
+

Returns

+ + +
String:The generated URL. + +
+

Examples

+

+Named Route +

+

+Merb::Router.prepare do +

+
+  match("/articles/:title").to(:controller => :articles, :action => :show).name("articles")
+
+

+end +

+

+url(:articles, :title => "new_article") +

+

+Default Route +

+

+Merb::Router.prepare do +

+
+  default_routes
+
+

+end +

+

+url(:controller => "articles", :action => "new") +

+

+Anonymous Parameters +

+

+Merb::Router.prepare do +

+
+  match("/articles/:year/:month/:title").to(:controller => :articles, :action => :show).name("articles")
+
+

+end +

+

+url(:articles, 2008, 10, "test_article") +

+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/controller/abstract_controller.rb, line 539 + def url(name, *args) + args << {} + Merb::Router.url(name, *args) + end + + +
+ + +
+ + + + + + + + + + + + + +
+ +
+ + + + + + + lib/merb-core/logger.rb + + + + + Extlib::Logger + + + + +Merb::Logger = Extlib::Logger +

+ + ]]>
+ + + + + + + + + + + Mash.new({ :fatal => 7, :error => 6, :warn => 4, :info => 3, :debug => 0 }) unless const_defined?(:Levels) + + + + + + + + + + + + RW + + + + + + + R + + + + + + + RW + + + + + + + R + + + + + + + RW + + + + + + + R + + + + + + + + + + + + + (*args) + + +To initialize the logger you create a new object, proxies to set_log. +

+

Parameters

+ + +
*args:Arguments to create the log from. See set_logs for specifics. + +
+ ]]>
+ + + +# File lib/merb-core/logger.rb, line 83 + def initialize(*args) + set_log(*args) + end + + +
+ + +
+ + + + + + (string = nil) + + +Appends a message to the log. The methods yield to an optional block and +the output of this block will be appended to the message. +

+

Parameters

+ + +
string<String>:The message to be logged. Defaults to nil. + +
+

Returns

+ + +
String:The resulting message added to the log file. + +
+ ]]>
+ + + +# File lib/merb-core/logger.rb, line 142 + def <<(string = nil) + message = "" + message << delimiter + message << string if string + message << "\n" unless message[-1] == ?\n + @buffer << message + flush if @auto_flush + + message + end + + +
+ + + () + + +Closes and removes the current log object. +

+ ]]>
+ + + +# File lib/merb-core/logger.rb, line 128 + def close + flush + @log.close if @log.respond_to?(:close) && !@log.tty? + @log = nil + end + + +
+ + + () + + +Flush the entire buffer to the log object. +

+ ]]>
+ + + +# File lib/merb-core/logger.rb, line 120 + def flush + return unless @buffer.size > 0 + @mutex.synchronize do + @log.write(@buffer.slice!(0..-1).to_s) + end + end + + +
+ + + (string = nil) + + +Alias for #<< +

+ ]]>
+ + +
+ + + (stream = Merb::Config[:log_stream], log_level = Merb::Config[:log_level], delimiter = Merb::Config[:log_delimiter], auto_flush = Merb::Config[:log_auto_flush]) + + +Replaces an existing logger with a new one. +

+

Parameters

+ + + + + +
log<IO, String>:Either an IO object or a name of a logfile. + +
log_level<~to_sym>:The log level from, e.g. :fatal or :info. Defaults to :error in the +production environment and :debug otherwise. + +
delimiter<String>:Delimiter to use between message sections. Defaults to " ~ ". + +
auto_flush<Boolean>:Whether the log should automatically flush after new messages are added. +Defaults to false. + +
+ ]]>
+ + + +# File lib/merb-core/logger.rb, line 99 + def set_log(stream = Merb::Config[:log_stream], + log_level = Merb::Config[:log_level], + delimiter = Merb::Config[:log_delimiter], + auto_flush = Merb::Config[:log_auto_flush]) + + @buffer = [] + @delimiter = delimiter + @auto_flush = auto_flush + + if Levels[log_level] + @level = Levels[log_level] + else + @level = log_level + end + + @log = stream + @log.sync = true + @mutex = (@@mutex[@log] ||= Mutex.new) + end + + +
+ + + (message, level = :warn) + + +:api: public +

+ ]]>
+ + + +# File lib/merb-core/logger.rb, line 10 + def verbose(message, level = :warn) + send(level, message) if Merb::Config[:verbose] + end + + +
+ + + (message, level = :warn) + + +:api: public +

+ ]]>
+ + + +# File lib/merb-core/logger.rb, line 5 + def verbose!(message, level = :warn) + send("#{level}!", message) if Merb::Config[:verbose] + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/dispatch/router/behavior.rb + + lib/merb-core/dispatch/router/cached_proc.rb + + lib/merb-core/dispatch/router/resources.rb + + lib/merb-core/dispatch/router/route.rb + + lib/merb-core/dispatch/router.rb + + + + + Object + + + + +Router stores route definitions and finds the +first route that matches the incoming request URL. +

+

+Then information from route is used by dispatcher to call action on the +controller. +

+

Routes compilation.

+

+The most interesting method of Router (and +heart of route matching machinery) is match method generated on the fly +from routes definitions. It is called routes compilation. Generated match +method body contains one if/elsif statement that picks the first matching +route definition and sets values to named parameters of the route. +

+

+Compilation is synchronized by mutex. +

+ + ]]>
+ + + + + + + + + + + + RW + +

+:api: plugin +

+]]>
+
+ + + + RW + +

+:api: private +

+]]>
+
+ + + + RW + + +resources :users do +

+
+  resources :comments
+
+

+end +

+

+The show comment route will have a key of ["User", +"Comment"] +

+

+:api: private +

+]]>
+
+ + + + RW + + Merb::Router.prepare block will defined in context of +this behavior. + +

Examples

+

+Merb::Router.root_behavior = +Merb::Router.root_behavior.match("/hello") +

+

+In the previous example, all routes will have the path prefix /hello. It is +important to note that this attribute must be set before any routes are +defined in order for the behavior to be applied to the routes. +

+

+:api: plugin +

+]]>
+
+ + + + RW + +

+:api: private +

+]]>
+
+ +
+ + + + + + + + (&block) + + +Adds functionality to the router. This can be in the form of including a +new module or directly defining new methods. +

+

Parameters

+ + +
&block<Block>:A block of code used to extend the route builder with. This can be +including a module or directly defining some new methods that should be +available to building routes. + +
+

Returns

+

+nil +

+

Example

+

+Merb::Router.extensions do +

+
+  def domain(name, domain, options={}, &block)
+    match(:domain => domain).namespace(name, :path => nil, &block)
+  end
+
+

+end +

+

+In this case, a method ‘domain’ will be available to the route +builder which will create namespaces around domains instead of path +prefixes. +

+

+This can then be used as follows. +

+

+Merb::Router.prepare do +

+
+  domain(:admin, "my-admin.com") do
+    # ... routes come here ...
+  end
+
+

+end +

+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/router.rb, line 310 + def extensions(&block) + Router::Behavior.class_eval(&block) + end + + +
+ + + (first = [], last = [], &block) + + +Creates a route building context and evaluates the block in it. A copy of +root_behavior (and instance of Behavior) is copied as the context. +

+

Parameters

+ + + +
first<Array>:An array containing routes that should be prepended to the routes defined +in the block. + +
last<Array>:An array containing routes that should be appended to the routes defined in +the block. + +
+

Returns

+ + +
Merb::Router:Returns self to allow chaining of methods. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/router.rb, line 103 + def prepare(first = [], last = [], &block) + @routes = [] + root_behavior._with_proxy(&block) + @routes = first + @routes + last + compile + self + end + + +
+ + + () + + +Clears the routing table. Route generation and request matching won’t +work anymore until a new routing table is built. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/router.rb, line 115 + def reset! + class << self + alias_method :match, :match_before_compilation + end + self.routes, self.named_routes, self.resource_routes = [], {}, {} + end + + +
+ + + (*args) + + +Generates a URL from the resource(s) +

+

Parameters

+ + + +
resources<Symbol,Object>:The identifiers for the resource route to generate. These can either be +symbols or objects. Symbols denote resource collection routes and objects +denote the members. + +
params<Hash>:Any extra parameters needed to generate the route. + +
+

Returns

+ + +
String:The generated URL + +
+

+:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/dispatch/router.rb, line 255 + def resource(*args) + defaults = args.pop + options = extract_options_from_args!(args) || {} + key = [] + params = [] + + args.each do |arg| + if arg.is_a?(Symbol) || arg.is_a?(String) + key << arg.to_s + else + key << arg.class.to_s + params << arg + end + end + + unless route = Merb::Router.resource_routes[key] + raise Merb::Router::GenerationError, "Resource route not found: #{args.inspect}" + end + + params << options + + route.generate(params, defaults, true) + end + + +
+ + + (request) + + +Finds route matching URI of the request and returns a tuple of [route +index, route params]. This method is called by the dispatcher and +isn’t as useful in applications. +

+

Parameters

+ + +
request<Merb::Request>:request to match. + +
+

Returns

+ + +
Array[Integer, Hash]:Two-tuple: route index and route parameters. Route parameters are +:controller, :action and all the named segments of the route. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/router.rb, line 135 + def route_for(request) + index, params = if @around_match + send(@around_match, request) { match(request) } + else + match(request) + end + route = routes[index] if index + if !route + raise ControllerExceptions::NotFound, + "No routes match the request: #{request.uri}" + end + [route, params] + end + + +
+ + + (name, *args) + + +There are three possible ways to use this method. First, if you have a +named route, you can specify the route as the first parameter as a symbol +and any parameters in a hash. Second, you can generate the default route by +just passing the params hash, just passing the params hash. Finally, you +can use the anonymous parameters. This allows you to specify the parameters +to a named route in the order they appear in the router. +

+

Parameters(Named Route)

+ + + +
name<Symbol>:The name of the route. + +
args<Hash>:Parameters for the route generation. + +
+

Parameters(Default Route)

+ + +
args<Hash>:Parameters for the route generation. This route will use the default route. + +
+

Parameters(Anonymous Parameters)

+ + + +
name<Symbol>:The name of the route. + +
args<Array>:An array of anonymous parameters to generate the route with. These +parameters are assigned to the route parameters in the order that they are +passed. + +
+

Returns

+ + +
String:The generated URL. + +
+

Examples

+

+Named Route +

+

+Merb::Router.prepare do +

+
+  match("/articles/:title").to(:controller => :articles, :action => :show).name("articles")
+
+

+end +

+

+url(:articles, :title => "new_article") +

+

+Default Route +

+

+Merb::Router.prepare do +

+
+  default_routes
+
+

+end +

+

+url(:controller => "articles", :action => "new") +

+

+Anonymous Parameters +

+

+Merb::Router.prepare do +

+
+  match("/articles/:year/:month/:title").to(:controller => :articles, :action => :show).name("articles")
+
+

+end +

+

+url(:articles, 2008, 10, "test_article") +

+

+:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/dispatch/router.rb, line 221 + def url(name, *args) + if name.is_a?(Route) + route = name + else + unless name.is_a?(Symbol) + args.unshift(name) + name = :default + end + + unless route = Merb::Router.named_routes[name] + raise Merb::Router::GenerationError, "Named route not found: #{name}" + end + end + + defaults = args.pop + + route.generate(args, defaults) + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/dispatch/router/resources.rb + + + + + + + + + + + + + + + + + + + (name, *args, &block) + + +Behavior#resource is a route helper for defining a singular +RESTful resource. It yields to a block for child routes. +

+

Parameters

+ + + +
name<String, Symbol>:The name of the resource. + +
options<Hash>:Overrides and parameters to be associated with the route. + +
+

Options (options)

+

+:namespace<~to_s>: The namespace for this route. +:name_prefix<~to_s>: +

+
+  A prefix for the named routes. If a namespace is passed and there
+  isn't a name prefix, the namespace will become the prefix.
+
+

+:controller<~to_s>: The controller for this route +

+

Block parameters

+ + +
next_level<Behavior>:The child behavior. + +
+

Returns

+ + +
Array:Routes which define a RESTful single resource. + +
+

Examples

+
+ r.resource :account # will result in the typical RESTful CRUD
+   # shows new resource form
+   # GET     /account/new                :action => "new"
+
+   # creates resource
+   # POST    /account/?(\.:format)?,     :action => "create"
+
+   # shows resource
+   # GET     /account/(\.:format)?       :action => "show"
+
+   # shows edit form
+   # GET     /account//edit           :action => "edit"
+
+   # updates resource
+   # PUT     /account/(\.:format)?       :action => "update"
+
+   # shows deletion confirmation page
+   # GET     /account//delete         :action => "delete"
+
+   # destroys resources
+   # DELETE  /account/(\.:format)?       :action => "destroy"
+
+

+You can optionally pass :namespace and :controller to refine the routing or +pass a block to nest resources. +

+
+  r.resource :account, :namespace => "admin" do |account|
+    account.resources :preferences, :controller => "settings"
+  end
+
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/router/resources.rb, line 227 + def resource(name, *args, &block) + name = name.to_s + options = extract_options_from_args!(args) || {} + params = { :controller => options.delete(:controller) || name.pluralize } + member = { :new => :get, :edit => :get, :delete => :get }.merge(options.delete(:member) || {}) + + options[:name_prefix] ||= nil # Don't use a name_prefix if not needed + options[:resource_prefix] ||= nil # Don't use a resource_prefix if not needed + options[:controller_prefix] ||= options.delete(:namespace) + + self.namespace(name, options).to(params) do |resource| + # => show + + resource.match("(.:format)", :method => :get).to(:action => "show"). + name(name).register_resource(name) + + # => create + resource.match("(.:format)", :method => :post).to(:action => "create") + + # => update + resource.match("(.:format)", :method => :put).to(:action => "update") + + # => destroy + resource.match("(.:format)", :method => :delete).to(:action => "destroy") + + member.each_pair do |action, method| + action = action.to_s + resource.match("/#{action}(.:format)", :method => method).to(:action => action). + name(action, name).register_resource(name, action) + end + + if block_given? + builders = {} + + builders[:member] = lambda do |action, to, method| + resource.match("/#{action}(.:format)", :method => method).to(:action => to). + name(action, name).register_resource(name, action) + end + + resource.options(:name_prefix => name, :resource_prefix => name). + resource_block(builders, &block) + end + end + end + + +
+ + + (name, *args, &block) + + +Behavior#resources is a route helper for defining a collection of +RESTful resources. It yields to a block for child routes. +

+

Parameters

+ + + +
name<String, Symbol>:The name of the resources + +
options<Hash>:Overrides and parameters to be associated with the route + +
+

Options (options)

+

+:namespace<~to_s>: The namespace for this route. +:name_prefix<~to_s>: +

+
+  A prefix for the named routes. If a namespace is passed and there
+  isn't a name prefix, the namespace will become the prefix.
+
+

+:controller<~to_s>: The controller for this route +:collection<~to_s>: Special settings for the collections routes +:member<Hash>: +

+
+  Special settings and resources related to a specific member of this
+  resource.
+
+

+:identify<Symbol|Array>: The method(s) that should be called on the +object +

+
+  before inserting it into an URL.
+
+

+:keys<Array>: +

+
+  A list of the keys to be used instead of :id with the resource in the order of the url.
+
+

+:singular<Symbol> +

+

Block parameters

+ + +
next_level<Behavior>:The child behavior. + +
+

Returns

+ + +
Array:Routes which will define the specified RESTful collection of resources + +
+

Examples

+
+ r.resources :posts # will result in the typical RESTful CRUD
+   # lists resources
+   # GET     /posts/?(\.:format)?      :action => "index"
+   # GET     /posts/index(\.:format)?  :action => "index"
+
+   # shows new resource form
+   # GET     /posts/new                :action => "new"
+
+   # creates resource
+   # POST    /posts/?(\.:format)?,     :action => "create"
+
+   # shows resource
+   # GET     /posts/:id(\.:format)?    :action => "show"
+
+   # shows edit form
+   # GET     /posts/:id/edit        :action => "edit"
+
+   # updates resource
+   # PUT     /posts/:id(\.:format)?    :action => "update"
+
+   # shows deletion confirmation page
+   # GET     /posts/:id/delete      :action => "delete"
+
+   # destroys resources
+   # DELETE  /posts/:id(\.:format)?    :action => "destroy"
+
+ # Nesting resources
+ r.resources :posts do |posts|
+   posts.resources :comments
+ end
+
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/router/resources.rb, line 70 + def resources(name, *args, &block) + name = name.to_s + options = extract_options_from_args!(args) || {} + match_opts = options.except(*resource_options) + options = options.only(*resource_options) + singular = options[:singular] ? options[:singular].to_s : Extlib::Inflection.singularize(name) + klass_name = args.first ? args.first.to_s : singular.to_const_string + keys = options.delete(:keys) || options.delete(:key) + params = { :controller => options.delete(:controller) || name } + collection = options.delete(:collection) || {} + member = { :edit => :get, :delete => :get }.merge(options.delete(:member) || {}) + + # Use the identifier for the class as a default + begin + if klass = Object.full_const_get(klass_name) + keys ||= options[:identify] + keys ||= @identifiers[klass] + elsif options[:identify] + raise Error, "The constant #{klass_name} does not exist, please specify the constant for this resource" + end + rescue NameError => e + Merb.logger.debug!("Could not find resource model #{klass_name}") + end + + keys = [ keys || :id ].flatten + + + # Try pulling :namespace out of options for backwards compatibility + options[:name_prefix] ||= nil # Don't use a name_prefix if not needed + options[:resource_prefix] ||= nil # Don't use a resource_prefix if not needed + options[:controller_prefix] ||= options.delete(:namespace) + + context = options[:identify] + context = klass && options[:identify] ? identify(klass => options.delete(:identify)) : self + context.namespace(name, options).to(params) do |resource| + root_keys = keys.map { |k| ":#{k}" }.join("/") + + # => index + resource.match("(/index)(.:format)", :method => :get).to(:action => "index"). + name(name).register_resource(name) + + # => create + resource.match("(.:format)", :method => :post).to(:action => "create") + + # => new + resource.match("/new(.:format)", :method => :get).to(:action => "new"). + name("new", singular).register_resource(name, "new") + + # => user defined collection routes + collection.each_pair do |action, method| + action = action.to_s + resource.match("/#{action}(.:format)", :method => method).to(:action => "#{action}"). + name(action, name).register_resource(name, action) + end + + # => show + resource.match("/#{root_keys}(.:format)", match_opts.merge(:method => :get)).to(:action => "show"). + name(singular).register_resource(klass_name, :identifiers => keys) + + # => user defined member routes + member.each_pair do |action, method| + action = action.to_s + resource.match("/#{root_keys}/#{action}(.:format)", match_opts.merge(:method => method)). + to(:action => "#{action}").name(action, singular).register_resource(klass_name, action, :identifiers => keys) + end + + # => update + resource.match("/#{root_keys}(.:format)", match_opts.merge(:method => :put)). + to(:action => "update") + + # => destroy + resource.match("/#{root_keys}(.:format)", match_opts.merge(:method => :delete)). + to(:action => "destroy") + + if block_given? + parent_keys = keys.map do |k| + k == :id ? "#{singular}_id".to_sym : k + end + + nested_keys = parent_keys.map { |k| ":#{k}" }.join("/") + + nested_match_opts = match_opts.except(:id) + nested_match_opts["#{singular}_id".to_sym] = match_opts[:id] if match_opts[:id] + + # Procs for building the extra collection/member resource routes + placeholder = Router.resource_routes[ [@options[:resource_prefix], klass_name].flatten.compact ] + builders = {} + + builders[:collection] = lambda do |action, to, method| + resource.before(placeholder).match("/#{action}(.:format)", match_opts.merge(:method => method)). + to(:action => to).name(action, name).register_resource(name, action) + end + + builders[:member] = lambda do |action, to, method| + resource.match("/#{root_keys}/#{action}(.:format)", match_opts.merge(:method => method)). + to(:action => to).name(action, singular).register_resource(klass_name, action, :identifiers => keys) + end + + resource.options(:name_prefix => singular, :resource_prefix => klass_name, :parent_keys => parent_keys). + match("/#{nested_keys}", nested_match_opts).resource_block(builders, &block) + end + end # namespace + end + + +
+ + +
+ + + + + + (*key) + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/router/resources.rb, line 275 + def register_resource(*key) + options = extract_options_from_args!(key) || {} + key = [ @options[:resource_prefix], key ].flatten.compact + identifiers = [ @options[:parent_keys], options[:identifiers] ] + @route.resource = key + @route.resource_identifiers = identifiers.flatten.compact.map { |id| id.to_sym } + self + end + + +
+ + + (builders, &block) + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/router/resources.rb, line 285 + def resource_block(builders, &block) + behavior = ResourceBehavior.new(builders, @proxy, @conditions, @params, @defaults, @identifiers, @options, @blocks) + with_behavior_context(behavior, &block) + end + + +
+ + + () + + + +# File lib/merb-core/dispatch/router/resources.rb, line 290 + def resource_options + [:singular, :keys, :key, :controller, :member, :collection, :identify, + :name_prefix, :resource_prefix, :controller_prefix, :namespace, :path] + end + + + + + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/dispatch/router/behavior.rb + + lib/merb-core/dispatch/router/resources.rb + + + + + Object + + + + + + + + + + + + + + + + (&block) + + +Proxies routes with the default behaviors. +

+

Parameters

+ + +
&block:defines routes within the provided context. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/router/behavior.rb, line 664 + def _with_proxy(&block) + proxy = Proxy.new + proxy.push Behavior.new(proxy, @conditions, @params, @defaults, @identifiers, @options, @blocks) + proxy.instance_eval(&block) + proxy + end + + +
+ + + (&block) + + +Captures any new routes that have been added within the block. +

+

+This utility method lets you track routes that have been added; it +doesn’t affect how/which routes are added. +

+

Parameters

+ + +
&block:A context in which routes are generated. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/router/behavior.rb, line 642 + def capture(&block) + captured_routes = {} + name_prefix = [@options[:name_prefix]].flatten.compact.map { |p| "#{p}_"} + current_names = Merb::Router.named_routes.keys + + behavior = Behavior.new(@proxy, @conditions, @params, @defaults, @identifiers, @options, @blocks) + with_behavior_context(behavior, &block) + + Merb::Router.named_routes.reject { |k,v| current_names.include?(k) }.each do |name, route| + name = route.name.to_s.sub("#{name_prefix}", '').to_sym unless name_prefix.empty? + captured_routes[name] = route + end + + captured_routes + end + + +
+ + + (defaults = {}, &block) + + +Sets default values for route parameters. If no value for the key can be +extracted from the request, then the value provided here will be used. +

+

Parameters

+ + + +
defaults<Hash>:The default values for named segments. + +
&block:All routes defined in the block will be scoped to the defaults defined by +the default method. + +
+

Block parameters

+ + +
r<Behavior>:optional - The defaults behavior object. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/router/behavior.rb, line 365 + def default(defaults = {}, &block) + behavior = Behavior.new(@proxy, @conditions, @params, @defaults.merge(defaults), @identifiers, @options, @blocks) + with_behavior_context(behavior, &block) + end + + +
+ + + (params = {}, &block) + + +Creates the most common routes /:controller/:action/:id.format when called +with no arguments. You can pass a hash or a block to add parameters or +override the default behavior. +

+

Parameters

+ + + +
params<Hash>:This optional hash can be used to augment the default settings + +
&block:When passing a block a new behavior is yielded and more refinement is +possible. + +
+

Returns

+ + +
Route:the default route + +
+

Examples

+
+  # Passing an extra parameter "mode" to all matches
+  r.default_routes :mode => "default"
+
+  # specifying exceptions within a block
+  r.default_routes do |nr|
+    nr.defer_to do |request, params|
+      nr.match(:protocol => "http://").to(:controller => "login",
+        :action => "new") if request.env["REQUEST_URI"] =~ /\/private\//
+    end
+  end
+
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/router/behavior.rb, line 515 + def default_routes(params = {}, &block) + match("/:controller(/:action(/:id))(.:format)").to(params, &block).name(:default) + end + + +
+ + + (defaults = {}, &block) + + +Alias for default +

+ ]]>
+ + +
+ + + (deferred_block, &block) + + +Takes a Proc as a parameter and applies it as a deferred proc for all the +routes defined in the block. This is mostly interesting for plugin +developers. +

+

Examples

+
+  defered_block = proc do |r, p|
+    p.merge :controller => 'api/comments' if request.xhr?
+  end
+  defer(defered_block) do
+    resources :comments
+  end
+
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/router/behavior.rb, line 555 + def defer(deferred_block, &block) + blocks = @blocks + [CachedProc.new(deferred_block)] + behavior = Behavior.new(@proxy, @conditions, @params, @defaults, @identifiers, @options, blocks) + with_behavior_context(behavior, &block) + end + + +
+ + + (params = {}, &block) + + +Takes a block and stores it for deferred conditional routes. The block +takes the request object and the params hash as +parameters. +

+

Parameters

+ + + +
params<Hash>:Parameters and conditions associated with this behavior. + +
&conditional_block:A block with the conditions to be met for the behavior to take effect. + +
+

Returns

+ + +
Route :The default route. + +
+

Examples

+
+  defer_to do |request, params|
+    params.merge :controller => 'here',
+      :action => 'there' if request.xhr?
+  end
+
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/router/behavior.rb, line 538 + def defer_to(params = {}, &block) + defer(block).to(params) + end + + +
+ + + (enable = true) + + +Specifies that a route can be fixatable. +

+

Parameters

+ + +
enabled<Boolean>:True enables fixation on the route. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/router/behavior.rb, line 605 + def fixatable(enable = true) + @route.fixation = enable + self + end + + +
+ + + (name) + + +Names this route in Router. Name must be a +Symbol. The current name_prefix is ignored. +

+

Parameters

+ + +
symbol<Symbol>:The name of the route. + +
+

Raises

+ + +
ArgumentError:symbol is not a Symbol. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/router/behavior.rb, line 588 + def full_name(name) + raise Error, ":this is reserved. Please pick another name." if name == :this + + if @route + @route.name = name + self + else + register.full_name(name) + end + end + + +
+ + + (identifiers = {}, &block) + + +Sets a method for instances of specified Classes to be called before +insertion into a route. This is useful when using models and want a +specific method to be called on it (For example, for ActiveRecord::Base it +would be to_param). +

+

+The default method called on objects is to_s. +

+

Paramters

+ + + +
identifiers<Hash>:The keys are Classes and the values are the method that instances of the +specified class should have called on. + +
&block:All routes defined in the block will be call the specified methods during +generation. + +
+

Block parameters

+ + +
r<Behavior>:The identify behavior object. This is optional + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/router/behavior.rb, line 475 + def identify(identifiers = {}, &block) + identifiers = if Hash === identifiers + @identifiers.merge(identifiers) + else + { Object => identifiers } + end + + behavior = Behavior.new(@proxy, @conditions, @params, @defaults, identifiers.freeze, @options, @blocks) + with_behavior_context(behavior, &block) + end + + +
+ + + (path = {}, conditions = {}, &block) + + +Defines the conditions that are required to match a Request. Each condition is applied to a +method of the Request object. Conditions can +also be applied to segments of the path. +

+

+If match is passed a block, it will create a new +route scope with the conditions passed to it and yield to the block such +that all routes that are defined in the block have the conditions applied +to them. +

+

Parameters

+ + + + +
path<String, Regexp>:The pattern against which Merb::Request path +is matched. + +

+When path is a String, any substring that is +wrapped in parenthesis is considered optional and any segment that begins +with a colon, ex.: ":login", defines both a capture and a named +param. Extra conditions can then be applied each named param individually. +

+

+When path is a Regexp, the pattern is left untouched and the Merb::Request path is matched against it as is. +

+

+path is optional. +

+
conditions<Hash>:Additional conditions that the request must meet in order to match. The +keys must be the names of previously defined path segments or be methods +that the Merb::Request instance will respond +to. The value is the string or regexp that matched the returned value. +Conditions are inherited by child routes. + +
&block:All routes defined in the block will be scoped to the conditions defined by +the match method. + +
+

Block parameters

+ + +
r<Behavior>:optional - The match behavior object. + +
+

Returns

+ + +
Behavior:A new instance of Behavior with the +specified path and conditions. + +
+

+Tip: When nesting always make sure the most inner sub-match +registers a Route and doesn’t just return new Behaviors. +

+

Examples

+
+  # registers /foo/bar to controller => "foo", :action => "bar"
+  # and /foo/baz to controller => "foo", :action => "baz"
+  match("/foo") do
+    match("/bar").to(:controller => "foo", :action => "bar")
+    match("/baz").to(:controller => "foo", :action => "caz")
+  end
+
+  # Checks the format of the segments against the specified Regexp
+  match("/:string/:number", :string => /[a-z]+/, :number => /\d+/).
+    to(:controller => "string_or_numbers")
+
+  # Equivalent to the default_route
+  match("/:controller(/:action(:id))(.:format)").register
+
+  #match only if the browser string contains MSIE or Gecko
+  match("/foo", :user_agent => /(MSIE|Gecko)/ )
+       .to(:controller => 'foo', :action => 'popular')
+
+  # Route GET and POST requests to different actions (see also #resources)
+  r.match('/foo', :method => :get).to(:action => 'show')
+  r.match('/foo', :method => :post).to(:action => 'create')
+
+  # match also takes regular expressions
+
+  r.match(%r[/account/([a-z]{4,6})]).to(:controller => "account",
+     :action => "show", :id => "[1]")
+
+  r.match(%r{/?(en|es|fr|be|nl)?}).to(:language => "[1]") do
+    match("/guides/:action/:id").to(:controller => "tour_guides")
+  end
+
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/router/behavior.rb, line 280 + def match(path = {}, conditions = {}, &block) + path, conditions = path[:path], path if path.is_a?(Hash) + + raise Error, "The route has already been committed. Further conditions cannot be specified" if @route + + conditions.delete_if { |k, v| v.nil? } + conditions[:path] = merge_paths(path) + + behavior = Behavior.new(@proxy, @conditions.merge(conditions), @params, @defaults, @identifiers, @options, @blocks) + with_behavior_context(behavior, &block) + end + + +
+ + + (prefix, name = nil) + + +Registers the route as a named route with the name given. +

+

Parameters

+ + +
symbol<Symbol>:the name of the route. + +
+

Raises

+ + +
ArgumentError:symbol is not a Symbol. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/router/behavior.rb, line 570 + def name(prefix, name = nil) + unless name + name, prefix = prefix, nil + end + + full_name([prefix, @options[:name_prefix], name].flatten.compact.join('_')) + end + + +
+ + + (name_or_path, opts = {}, &block) + + +Creates a namespace for a route. This way you can have logical separation +to your routes. +

+

Parameters

+ + + + +
name_or_path<String, Symbol>:The name or path of the namespace. + +
options<Hash>:Optional hash (see below) + +
&block:All routes defined in the block will be scoped to the namespace defined by +the namespace method. + +
+

Options (opts)

+ + +
:path<String>:match against this url + +
+

Block parameters

+ + +
r<Behavior>:The namespace behavior object. This is optional + +
+

Examples

+
+  namespace :admin do
+    resources :accounts
+    resource :email
+  end
+
+  # /super_admin/accounts
+  namespace(:admin, :path=>"super_admin") do
+    resources :accounts
+  end
+
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/router/behavior.rb, line 439 + def namespace(name_or_path, opts = {}, &block) + name = name_or_path.to_s # We don't want this modified ever + path = opts.has_key?(:path) ? opts[:path] : name + + raise Error, "The route has already been committed. Further options cannot be specified" if @route + + # option keys could be nil + opts[:controller_prefix] = name unless opts.has_key?(:controller_prefix) + opts[:name_prefix] = name unless opts.has_key?(:name_prefix) + opts[:resource_prefix] = opts[:name_prefix] unless opts.has_key?(:resource_prefix) + + behavior = self + behavior = behavior.match("/#{path}") unless path.nil? || path.empty? + behavior.options(opts, &block) + end + + +
+ + + (opts = {}, &block) + + +Alias for options +

+ ]]>
+ + +
+ + + (opts = {}, &block) + + +Allows the fine tuning of certain router options. +

+

Parameters

+ + + +
options<Hash>:The options to set for all routes defined in the scope. The currently +supported options are: + +
    +
  • :controller_prefix - The module that the controller is included in. + +
  • +
  • :name_prefix - The prefix added to all routes named with name + +
  • +
+
&block:All routes defined in the block will be scoped to the options defined by +the options method. + +
+

Block parameters

+ + +
r<Behavior>:The options behavior object. This is optional + +
+

Examples

+
+  # If :group is not matched in the path, it will be "registered" instead
+  # of nil.
+  match("/users(/:group)").default(:group => "registered")
+
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/router/behavior.rb, line 394 + def options(opts = {}, &block) + options = @options.dup + + opts.each_pair do |key, value| + options[key] = (options[key] || []) + [value.freeze] if value + end + + behavior = Behavior.new(@proxy, @conditions, @params, @defaults, @identifiers, options, @blocks) + with_behavior_context(behavior, &block) + end + + +
+ + + (url, opts = {}) + + +Redirects the current route. +

+

Parameters

+ + + +
path<String>:The path to redirect to. + +
options<Hash>:Options (see below) + +
+

Options (opts)

+ + +
:permanent<Boolean>:Whether or not the redirect should be permanent. The default value is +false. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/router/behavior.rb, line 624 + def redirect(url, opts = {}) + raise Error, "The route has already been committed." if @route + + status = opts[:permanent] ? 301 : 302 + @route = Route.new(@conditions, {:url => url.freeze, :status => status.freeze}, @blocks, :redirects => true) + @route.register + self + end + + +
+ + + (params = {}, &block) + + +Alias for to +

+ ]]>
+ + +
+ + + (params = {}, &block) + + +Creates a Route from one or more Behavior objects, unless a +block is passed in. +

+

Parameters

+ + + +
params<Hash>:The parameters the route maps to. + +
&block:All routes defined in the block will be scoped to the params defined by the +to method. + +
+

Block parameters

+ + +
r<Behavior>:optional - The to behavior object. + +
+

Returns

+ + +
Route:It registers a new route and returns it. + +
+

Examples

+
+  match('/:controller/:id).to(:action => 'show')
+
+  to(:controller => 'simple') do
+    match('/test').to(:action => 'index')
+    match('/other').to(:action => 'other')
+  end
+
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/router/behavior.rb, line 317 + def to(params = {}, &block) + raise Error, "The route has already been committed. Further params cannot be specified" if @route + + behavior = Behavior.new(@proxy, @conditions, @params.merge(params), @defaults, @identifiers, @options, @blocks) + + if block_given? + with_behavior_context(behavior, &block) + else + behavior.to_route + end + end + + +
+ + + (params = {}, &block) + + +Alias for to +

+ ]]>
+ + +
+ + +
+ + + + + + () + + +Returns the current route. +

+

Returns

+ + +
Route:the route. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/router/behavior.rb, line 679 + def _route + @route + end + + +
+ + + (route, &block) + + +Allows to insert the route at a certain spot in the list of routes instead +of appending to the list. +

+

Parameters

+ + + +
route<Route>:the route to insert before. + +
&block:the route definition to insert. + +
+

+:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/dispatch/router/behavior.rb, line 728 + def before(route, &block) + options(:before => route, &block) + end + + +
+ + + () + + +Turns a route definition into a Route object. +

+

Returns

+ + +
Route:the route generated. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/router/behavior.rb, line 689 + def to_route + raise Error, "The route has already been committed." if @route + + controller = @params[:controller] + + if prefixes = @options[:controller_prefix] + controller ||= ":controller" + + prefixes.reverse_each do |prefix| + break if controller =~ %r{^/(.*)} && controller = $1 + controller = "#{prefix}/#{controller}" + end + end + + @params.merge!(:controller => controller.to_s.gsub(%r{^/}, '')) if controller + + # Sorts the identifiers so that modules that are at the bottom of the + # inheritance chain come first (more specific modules first). Object + # should always be last. + identifiers = @identifiers.sort { |(first,_),(sec,_)| first <=> sec || 1 } + + @route = Route.new(@conditions.dup,@params, @blocks, :defaults => @defaults.dup, :identifiers => identifiers) + + if before = @options[:before] && @options[:before].last + @route.register_at(Router.routes.index(before)) + else + @route.register + end + self + end + + +
+ + +
+ + + + + + + + + + + +
+ +
+ + + + + + + lib/merb-core/dispatch/router/behavior.rb + + + + + Object + + + + +Proxy catches any methods and +proxies them to the current behavior. This allows building routes without +constantly having to catching the yielded behavior object +

+

+:api: private +

+ + ]]>
+ + + + + + + + + + + + + + () + + +:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/router/behavior.rb, line 21 + def initialize + @behaviors = [] + end + + +
+ + +
+ + + + + + () + + +Removes the top-most behavior. +

+

Notes

+

+This occurs at the end of a nested scope (namespace, etc). +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/router/behavior.rb, line 41 + def pop + @behaviors.pop + end + + +
+ + + (behavior) + + +Puts a behavior on the bottom of the stack. +

+

Notes

+

+The behaviors keep track of nested scopes. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/router/behavior.rb, line 31 + def push(behavior) + @behaviors.push(behavior) + end + + +
+ + + (url, opts = {}) + + +Generates a Rack redirection response. +

+

Notes

+

+Refer to Merb::Rack::Helpers.redirect for +documentation. +

+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/router/behavior.rb, line 139 + def redirect(url, opts = {}) + Merb::Rack::Helpers.redirect(url, opts) + end + + +
+ + + (*args) + + +Tests whether the top-most behavior responds to the arguments. +

+

Notes

+

+Behaviors contain the actual functionality of the proxy. +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/router/behavior.rb, line 51 + def respond_to?(*args) + super || @behaviors.last.respond_to?(*args) + end + + +
+ + + (name, *args) + + +There are three possible ways to use this method. First, if you have a +named route, you can specify the route as the first parameter as a symbol +and any parameters in a hash. Second, you can generate the default route by +just passing the params hash, just passing the params hash. Finally, you +can use the anonymous parameters. This allows you to specify the parameters +to a named route in the order they appear in the router. +

+

Parameters(Named Route)

+ + + +
name<Symbol>:The name of the route. + +
args<Hash>:Parameters for the route generation. + +
+

Parameters(Default Route)

+ + +
args<Hash>:Parameters for the route generation. This route will use the default route. + +
+

Parameters(Anonymous Parameters)

+ + + +
name<Symbol>:The name of the route. + +
args<Array>:An array of anonymous parameters to generate the route with. These +parameters are assigned to the route parameters in the order that they are +passed. + +
+

Returns

+ + +
String:The generated URL. + +
+

Examples

+

+Named Route +

+

+Merb::Router.prepare do +

+
+  match("/articles/:title").to(:controller => :articles, :action => :show).name("articles")
+
+

+end +

+

+url(:articles, :title => "new_article") +

+

+Default Route +

+

+Merb::Router.prepare do +

+
+  default_routes
+
+

+end +

+

+url(:controller => "articles", :action => "new") +

+

+Anonymous Parameters +

+

+Merb::Router.prepare do +

+
+  match("/articles/:year/:month/:title").to(:controller => :articles, :action => :show).name("articles")
+
+

+end +

+

+url(:articles, 2008, 10, "test_article") +

+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/dispatch/router/behavior.rb, line 128 + def url(name, *args) + args << {} + Merb::Router.url(name, *args) + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/dispatch/router/behavior.rb + + + + + StandardError + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/dispatch/router.rb + + + + + StandardError + + + + +Raised when route lookup fails. +

+ + ]]>
+ + + + + + + + + + + + + +
+ + + + + + + lib/merb-core/dispatch/router.rb + + + + + StandardError + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/dispatch/router/resources.rb + + + + + Merb::Router::Behavior + + + + +Adding the collection and member methods to behavior +

+ + ]]>
+ + + + + + + + + + + + + +
+ + + + + + + lib/merb-core/dispatch/router/cached_proc.rb + + + + + Object + + + + +Cache procs for future reference in eval statement :api: private +

+ + ]]>
+ + + + + + + + + + + + RW + + + + + + + RW + + + + + + + + + + + + + (index) + + Parameters + + +
index<Fixnum>:The index of the cached code to retrieve. + +
+

Returns

+ + +
CachedProc:The cached code at index. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/router/cached_proc.rb, line 60 + def [](index) @@list[index] end + + +
+ + + (index, code) + + +Sets the cached code for a specific index. +

+

Parameters

+ + + +
index<Fixnum>:The index of the cached code to set. + +
code<CachedProc>:The cached code to set. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/router/cached_proc.rb, line 51 + def []=(index, code) @@list[index] = code end + + +
+ + + (cache) + + Parameters + + +
cache<Proc>:The block of code to cache. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/router/cached_proc.rb, line 17 + def initialize(cache) + @cache, @index = cache, CachedProc.register(self) + end + + +
+ + + (cached_code) + + Parameters + + +
cached_code<CachedProc>:The cached code to register. + +
+

Returns

+ + +
Fixnum:The index of the newly registered CachedProc. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/router/cached_proc.rb, line 38 + def register(cached_code) + CachedProc[@@index] = cached_code + @@index += 1 + @@index - 1 + end + + +
+ + +
+ + + + + + () + + Returns + + +
String:The CachedProc object in a format +embeddable within a string. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/router/cached_proc.rb, line 25 + def to_s + "CachedProc[#{@index}].cache" + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/dispatch/router.rb + + + + + StandardError + + + + +Raised when parameters given to generation method do not match route +parameters. +

+ + ]]>
+ + + + + + + + + + + + + +
+ + + + + + + lib/merb-core/dispatch/router/route.rb + + + + + Object + + + + +This entire class is private and should never be accessed outside of Merb::Router and Behavior +

+ + ]]>
+ + + + + + + + + + + + + +
+ + + + + + + lib/merb-core/dispatch/router/route.rb + + + + + Object + + + + +The Generator class handles compiling the route down to a lambda that can +generate the URL from a params hash and a default params hash. +

+ + ]]>
+ + + + + + + + + + + + + +
+ + + + + + + lib/merb-core/bootloader.rb + + + + + Object + + + + + + + + + + + + + + + + (klass) + + +Execute this boot loader after the specified boot loader. +

+

Parameters

+ + +
klass<~to_s>:The boot loader class after which this boot loader should be run. + +
+

Returns

+

+nil +

+

+:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/bootloader.rb, line 42 + def after(klass) + move_klass(klass, 1) + nil + end + + +
+ + + (&block) + + +Execute a block of code after the app loads. +

+

Parameters

+ + +
&block:A block to be added to the callbacks that will be executed after the app +loads. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/bootloader.rb, line 157 + def after_app_loads(&block) + after_load_callbacks << block + end + + +
+ + + (klass) + + +Execute this boot loader before the specified boot loader. +

+

Parameters

+ + +
klass<~to_s>:The boot loader class before which this boot loader should be run. + +
+

Returns

+

+nil +

+

+:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/bootloader.rb, line 57 + def before(klass) + move_klass(klass, 0) + nil + end + + +
+ + + (&block) + + +Execute a block of code before the app loads but after dependencies load. +

+

Parameters

+ + +
&block:A block to be added to the callbacks that will be executed before the app +loads. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/bootloader.rb, line 169 + def before_app_loads(&block) + before_load_callbacks << block + end + + +
+ + + (&block) + + +Execute a block of code before master process is shut down. Only makes +sense on platforms where Merb server can use forking. +

+

Parameters

+ + +
&block:A block to be added to the callbacks that will be executed before master +process is shut down. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/bootloader.rb, line 182 + def before_master_shutdown(&block) + before_master_shutdown_callbacks << block + end + + +
+ + + (&block) + + +Execute a block of code before worker process is shut down. Only makes +sense on platforms where Merb server can use forking. +

+

Parameters

+ + +
&block:A block to be added to the callbacks that will be executed before worker +process is shut down. + +
+

+:api: public +

+ ]]>
+ + + +# File lib/merb-core/bootloader.rb, line 195 + def before_worker_shutdown(&block) + before_worker_shutdown_callbacks << block + end + + +
+ + + () + + +Set up the default framework +

+

Returns

+

+nil +

+

+:api: plugin @overridable +

+ ]]>
+ + + +# File lib/merb-core/bootloader.rb, line 129 + def default_framework + %w[view model helper controller mailer part].each do |component| + Merb.push_path(component.to_sym, Merb.root_path("app/#{component}s")) + end + Merb.push_path(:application, Merb.root_path("app" / "controllers" / "application.rb")) + Merb.push_path(:config, Merb.root_path("config"), nil) + Merb.push_path(:router, Merb.dir_for(:config), (Merb::Config[:router_file] || "router.rb")) + # IMPORTANT! Enabling autoload here for lib breaks most of Rake tasks + # in Merb repository. If you want to enable autoload by default, + # do it in the generated init.rb file: Merb.push_path(Merb.root_path("lib"), "*/*.rb") + Merb.push_path(:lib, Merb.root_path("lib"), nil) + Merb.push_path(:merb_session, Merb.root_path("merb" / "session")) + Merb.push_path(:log, Merb.log_path, nil) + Merb.push_path(:public, Merb.root_path("public"), nil) + Merb.push_path(:stylesheet, Merb.dir_for(:public) / "stylesheets", nil) + Merb.push_path(:javascript, Merb.dir_for(:public) / "javascripts", nil) + Merb.push_path(:image, Merb.dir_for(:public) / "images", nil) + nil + end + + +
+ + + (bootloader) + + +Determines whether or not a specific bootloader has finished yet. +

+

Parameters

+ + +
bootloader<String, Class>:The name of the bootloader to check. + +
+

Returns

+ + +
Boolean:Whether or not the bootloader has finished. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/bootloader.rb, line 118 + def finished?(bootloader) + self.finished.include?(bootloader.to_s) + end + + +
+ + + (klass) + + +Adds the inheriting class to the list of subclasses in a position specified +by the before and after methods. +

+

Parameters

+ + +
klass<Class>:The class inheriting from Merb::BootLoader. + +
+

Returns

+

+nil +

+

+:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/bootloader.rb, line 27 + def inherited(klass) + subclasses << klass.to_s + super + end + + +
+ + + (klass, where) + + +Move a class that is inside the bootloader to some place in the Array, +relative to another class. +

+

Parameters

+ + + +
klass<~to_s>:The klass to move the bootloader relative to + +
where<Integer>:0 means insert it before; 1 means insert it after + +
+

Returns

+

+nil +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/bootloader.rb, line 75 + def move_klass(klass, where) + index = Merb::BootLoader.subclasses.index(klass.to_s) + if index + Merb::BootLoader.subclasses.delete(self.to_s) + Merb::BootLoader.subclasses.insert(index + where, self.to_s) + end + nil + end + + +
+ + + () + + +Runs all boot loader classes by calling their run methods. +

+

Returns

+

+nil +

+

+:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/bootloader.rb, line 90 + def run + Merb.started = true + subklasses = subclasses.dup + until subclasses.empty? + time = Time.now.to_i + bootloader = subclasses.shift + if (ENV['DEBUG'] || $DEBUG || Merb::Config[:verbose]) && Merb.logger + Merb.logger.debug!("Loading: #{bootloader}") + end + Object.full_const_get(bootloader).run + if (ENV['DEBUG'] || $DEBUG || Merb::Config[:verbose]) && Merb.logger + Merb.logger.debug!("It took: #{Time.now.to_i - time}") + end + self.finished << bootloader + end + self.subclasses = subklasses + nil + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/bootloader.rb + + + + + Merb::BootLoader + + + + +Load all classes inside the load paths. +

+

+This is used in conjunction with Merb::BootLoader::ReloadClasses +to track files that need to be reloaded, and which constants need to be +removed in order to reload a file. +

+

+This also adds the model, controller, and lib directories to the load path, +so they can be required in order to avoid load-order issues. +

+ + ]]>
+ + + + + + + + + + + {} + + + + + + + {} + + + + + + + + + + + + + + () + + +Wait for any children to exit, remove the "main" PID, and exit. +

+

Returns

+

+(Does not return.) +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/bootloader.rb, line 655 + def exit_gracefully + # wait all workers to exit + Process.waitall + # remove master process pid + Merb::Server.remove_pid("main") + # terminate, workers remove their own pids + # in on exit hook + + Merb::BootLoader.before_master_shutdown_callbacks.each do |cb| + begin + cb.call + rescue Exception => e + Merb.logger.fatal "before_master_shutdown callback crashed: #{e.message}" + end + end + exit + end + + +
+ + + (*paths) + + +Loads classes from given paths - using path/glob pattern. +

+

Parameters

+ + +
*paths<Array>:Array of paths to load classes from - may contain glob pattern + +
+

Returns

+

+nil +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/bootloader.rb, line 872 + def load_classes(*paths) + orphaned_classes = [] + paths.flatten.each do |path| + Dir[path].each do |file| + begin + load_file file + rescue NameError => ne + orphaned_classes.unshift(file) + end + end + end + load_classes_with_requirements(orphaned_classes) + end + + +
+ + + (file) + + +Loads a file, tracking its modified time and, if necessary, the classes it +declared. +

+

Parameters

+ + +
file<String>:The file to load. + +
+

Returns

+

+nil +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/bootloader.rb, line 836 + def load_file(file) + # Don't do this expensive operation unless we need to + unless Merb::Config[:fork_for_class_load] + klasses = ObjectSpace.classes.dup + end + + # Ignore the file for syntax errors. The next time + # the file is changed, it'll be reloaded again + begin + require file + rescue SyntaxError => e + Merb.logger.error "Cannot load #{file} because of syntax error: #{e.message}" + ensure + if Merb::Config[:reload_classes] + MTIMES[file] = File.mtime(file) + end + end + + # Don't do this expensive operation unless we need to + unless Merb::Config[:fork_for_class_load] + LOADED_CLASSES[file] = ObjectSpace.classes - klasses + end + + nil + end + + +
+ + + (status = 0, sig = reap_workers_signal) + + +Reap any workers of the spawner process and exit with an appropriate status +code. +

+

+Note that exiting the spawner process with a status code of 128 when a +master process exists will cause the spawner process to be recreated, and +the app code reloaded. +

+

Parameters

+ + + +
status<Integer>:The status code to exit with. Defaults to 0. + +
sig<String>:The signal to send to workers + +
+

Returns

+

+(Does not return.) +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/bootloader.rb, line 794 + def reap_workers(status = 0, sig = reap_workers_signal) + Merb.logger.info "Executed all before worker shutdown callbacks..." + Merb::BootLoader.before_worker_shutdown_callbacks.each do |cb| + begin + cb.call + rescue Exception => e + Merb.logger.fatal "before worker shutdown callback crashed: #{e.message}" + end + + end + + Merb.exiting = true unless status == 128 + + begin + @writer.puts(status.to_s) if @writer + rescue SystemCallError + end + + threads = [] + + ($WORKERS || []).each do |p| + threads << Thread.new do + begin + Process.kill(sig, p) + Process.wait2(p) + rescue SystemCallError + end + end + end + threads.each {|t| t.join } + exit(status) + end + + +
+ + + () + + + +# File lib/merb-core/bootloader.rb, line 775 + def reap_workers_signal + Merb::Config[:reap_workers_quickly] ? "KILL" : "ABRT" + end + + + + + + (file) + + +Reloads the classes in the specified file. If fork-based loading is used, +this causes the current processes to be killed and all classes to be +reloaded. If class-based loading is not in use, the classes declared in +that file are removed and the file is reloaded. +

+

Parameters

+ + +
file<String>:The file to reload. + +
+

Returns

+

+When fork-based loading is used: +

+
+  (Does not return.)
+
+

+When fork-based loading is not in use: +

+
+  nil
+
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/bootloader.rb, line 901 + def reload(file) + if Merb::Config[:fork_for_class_load] + reap_workers(128) + else + remove_classes_in_file(file) { |f| load_file(f) } + end + end + + +
+ + + (file) {|file if block_given?| ...} + + +Removes all classes declared in the specified file. Any hashes which use +classes as keys will be protected provided they have been added to +Merb.klass_hashes. These hashes have their keys substituted with +placeholders before the file’s classes are unloaded. If a block is +provided, it is called before the substituted keys are reconstituted. +

+

Parameters

+ + + +
file<String>:The file to remove classes for. + +
&block:A block to call with the file that has been removed before klass_hashes are +updated + +
+

+to use the current values of the constants they used as keys. +

+

Returns

+

+nil +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/bootloader.rb, line 923 + def remove_classes_in_file(file, &block) + Merb.klass_hashes.each { |x| x.protect_keys! } + if klasses = LOADED_CLASSES.delete(file) + klasses.each { |klass| remove_constant(klass) unless klass.to_s =~ /Router/ } + end + yield file if block_given? + Merb.klass_hashes.each {|x| x.unprotect_keys!} + nil + end + + +
+ + + (const) + + +Removes the specified class. +

+

+Additionally, removes the specified class from the subclass list of every +superclass that tracks it’s subclasses in an array returned by +_subclasses_list. Classes that wish to use this functionality are required +to alias the reader for their list of subclasses to _subclasses_list. Plugins for ORMs and other libraries should keep +this in mind. +

+

Parameters

+ + +
const<Class>:The class to remove. + +
+

Returns

+

+nil +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/bootloader.rb, line 947 + def remove_constant(const) + # This is to support superclasses (like AbstractController) that track + # their subclasses in a class variable. + superklass = const + until (superklass = superklass.superclass).nil? + if superklass.respond_to?(:_subclasses_list) + superklass.send(:_subclasses_list).delete(klass) + superklass.send(:_subclasses_list).delete(klass.to_s) + end + end + + parts = const.to_s.split("::") + base = parts.size == 1 ? Object : Object.full_const_get(parts[0..-2].join("::")) + object = parts[-1].to_s + begin + base.send(:remove_const, object) + Merb.logger.debug("Removed constant #{object} from #{base}") + rescue NameError + Merb.logger.debug("Failed to remove constant #{object} from #{base}") + end + nil + end + + +
+ + + () + + +Load all classes from Merb’s native load paths. +

+

+If fork-based loading is used, every time classes are loaded this will +return in a new spawner process and boot loading will continue from this +point in the boot loading process. +

+

+If fork-based loading is not in use, this only returns once and does not +fork a new process. +

+

Returns

+

+Returns at least once: +

+
+  nil
+
+

+:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/bootloader.rb, line 615 + def run + # process name you see in ps output + $0 = "merb#{" : " + Merb::Config[:name] if Merb::Config[:name]} : master" + + # Log the process configuration user defined signal 1 (SIGUSR1) is received. + Merb.trap("USR1") do + require "yaml" + Merb.logger.fatal! "Configuration:\n#{Merb::Config.to_hash.merge(:pid => $$).to_yaml}\n\n" + end + + if Merb::Config[:fork_for_class_load] && !Merb.testing? + start_transaction + else + Merb.trap('INT') do + Merb.logger.warn! "Reaping Workers" + reap_workers + end + end + + # Load application file if it exists - for flat applications + load_file Merb.dir_for(:application) if File.file?(Merb.dir_for(:application)) + + # Load classes and their requirements + Merb.load_paths.each do |component, path| + next if path.last.blank? || component == :application || component == :router + load_classes(path.first / path.last) + end + + Merb::Controller.send :include, Merb::GlobalHelpers + + nil + end + + +
+ + + () + + +Set up the BEGIN point for fork-based loading and sets up any signals in +the parent and child. This is done by forking the app. The child process +continues on to run the app. The parent process waits for the child process +to finish and either forks again +

+

Returns

+

+Parent Process: +

+
+  (Does not return.)
+
+

+Child Process returns at least once: +

+
+  nil
+
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/bootloader.rb, line 686 + def start_transaction + Merb.logger.warn! "Parent pid: #{Process.pid}" + reader, writer = nil, nil + + if GC.respond_to?(:copy_on_write_friendly=) + GC.copy_on_write_friendly = true + end + + loop do + # create two connected endpoints + # we use them for master/workers communication + reader, @writer = IO.pipe + pid = Kernel.fork + + # pid means we're in the parent; only stay in the loop if that is case + break unless pid + # writer must be closed so reader can generate EOF condition + @writer.close + + # master process stores pid to merb.main.pid + Merb::Server.store_pid("main") + + if Merb::Config[:console_trap] + Merb.trap("INT") {} + else + # send ABRT to worker on INT + Merb.trap("INT") do + Merb.logger.warn! "Reaping Workers" + begin + Process.kill(reap_workers_signal, pid) + rescue SystemCallError + end + exit_gracefully + end + end + + Merb.trap("HUP") do + Merb.logger.warn! "Doing a fast deploy\n" + Process.kill("HUP", pid) + end + + reader_ary = [reader] + loop do + # wait for worker to exit and capture exit status + # + # + # WNOHANG specifies that wait2 exists without waiting + # if no worker processes are ready to be noticed. + if exit_status = Process.wait2(pid, Process::WNOHANG) + # wait2 returns a 2-tuple of process id and exit + # status. + # + # We do not care about specific pid here. + exit_status[1] && exit_status[1].exitstatus == 128 ? break : exit + end + # wait for data to become available, timeout in 0.25 of a second + if select(reader_ary, nil, nil, 0.25) + begin + # no open writers + next if reader.eof? + msg = reader.readline + if msg =~ /128/ + Process.detach(pid) + break + else + exit_gracefully + end + rescue SystemCallError + exit_gracefully + end + end + end + end + + reader.close + + # add traps to the worker + if Merb::Config[:console_trap] + Merb::Server.add_irb_trap + at_exit { reap_workers } + else + Merb.trap('INT') do + Merb::BootLoader.before_worker_shutdown_callbacks.each { |cb| cb.call } + end + Merb.trap('ABRT') { reap_workers } + Merb.trap('HUP') { reap_workers(128, "ABRT") } + end + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/bootloader.rb + + + + + Merb::BootLoader + + + + +Setup some useful defaults +

+ + ]]>
+ + + + + + + + + + + + + + () + + +Sets up the defaults +

+

Returns

+

+nil +

+

+:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/bootloader.rb, line 275 + def self.run + Merb::Request.http_method_overrides.concat([ + proc { |c| c.params[:_method] }, + proc { |c| c.env['HTTP_X_HTTP_METHOD_OVERRIDE'] } + ]) + nil + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/bootloader.rb + + + + + Merb::BootLoader + + + + + + + + + + + + + + + + () + + +Call any after_app_loads hooks that were registered via after_app_loads in +init.rb. +

+

Returns

+

+nil +

+

+:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/bootloader.rb, line 1235 + def self.run + Merb::BootLoader.after_load_callbacks.each {|x| x.call } + nil + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/bootloader.rb + + + + + Merb::BootLoader + + + + + + + + + + + + + + + + () + + +Loads json or json_pure and requires it. +

+

Returns

+

+nil +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/bootloader.rb, line 418 + def self.enable_json_gem + gem "json" + require "json/ext" + rescue LoadError + gem "json_pure" + require "json/pure" + end + + +
+ + + () + + +Load each dependency that has been declared so far. +

+

Returns

+

+nil +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/bootloader.rb, line 407 + def self.load_dependencies + dependencies.each { |dependency| Kernel.load_dependency(dependency) } + nil + end + + +
+ + + () + + +Load the init_file specified in Merb::Config or +if not specified, the init.rb file from the Merb +configuration directory, and any environment files, which register the list +of necessary dependencies and any after_app_loads hooks. +

+

+Dependencies can hook into +the bootloader process itself by using before or after insertion methods. +Since these are loaded from this bootloader (Dependencies), they can only +adapt the bootloaders that haven’t been loaded up until this point. +

+

Returns

+

+nil +

+

+:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/bootloader.rb, line 385 + def self.run + set_encoding + # this is crucial: load init file with all the preferences + # then environment init file, then start enabling specific + # components, load dependencies and update logger. + unless Merb::disabled?(:initfile) + load_initfile + load_env_config + end + expand_ruby_path + enable_json_gem unless Merb::disabled?(:json) + load_dependencies + update_logger + nil + end + + +
+ + + () + + +Default encoding to UTF8 if it has not already been set to something else. +

+

Returns

+

+nil +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/bootloader.rb, line 455 + def self.set_encoding + $KCODE = 'UTF8' if $KCODE == 'NONE' || $KCODE.blank? + nil + end + + +
+ + + () + + +Resets the logger and sets the log_stream to Merb::Config[:log_file] if one +is specified, falling back to STDOUT. +

+

Returns

+

+nil +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/bootloader.rb, line 433 + def self.update_logger + Merb.reset_logger! + + # If log file is given, use it and not log stream we have. + if Merb::Config[:log_file] + raise "log file should be a string, got: #{Merb::Config[:log_file].inspect}" unless Merb::Config[:log_file].is_a?(String) + STDOUT.puts "Logging to file at #{Merb::Config[:log_file]}" unless Merb.testing? + Merb::Config[:log_stream] = File.open(Merb::Config[:log_file], "w+") + # but if it's not given, fallback to log stream or stdout + else + Merb::Config[:log_stream] ||= STDOUT + end + + nil + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/bootloader.rb + + + + + Merb::BootLoader + + + + +Precompiles all non-partial templates. +

+ + ]]>
+ + + + + + + + + + + + + + () + + +Loads all non-partial templates into the Merb::InlineTemplates module. +

+

Returns

+ + +
Array[String]:The list of template files which were loaded. + +
+

+:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/bootloader.rb, line 1072 + def run + template_paths.each do |path| + Merb::Template.inline_template(File.open(path)) + end + end + + +
+ + + () + + +Finds a list of templates to load. +

+

Returns

+ + +
Array[String]:All found template files whose basename does not begin with "_". + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/bootloader.rb, line 1084 + def template_paths + extension_glob = "{#{Merb::Template.template_extensions.join(',')}}" + + # This gets all templates set in the controllers template roots + # We separate the two maps because most of controllers will have + # the same _template_root, so it's silly to be globbing the same + # path over and over. + controller_view_paths = [] + Merb::AbstractController._abstract_subclasses.each do |klass| + next if (const = Object.full_const_get(klass))._template_root.blank? + controller_view_paths += const._template_roots.map { |pair| pair.first } + end + template_paths = controller_view_paths.uniq.compact.map { |path| Dir["#{path}/**/*.#{extension_glob}"] } + + # This gets the templates that might be created outside controllers + # template roots. eg app/views/shared/* + template_paths << Dir["#{Merb.dir_for(:view)}/**/*.#{extension_glob}"] if Merb.dir_for(:view) + + # This ignores templates for partials, which need to be compiled at use time to generate + # a preamble that assigns local variables + template_paths.flatten.compact.uniq.grep(%r{^.*/[^_][^/]*$}) + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/bootloader.rb + + + + + Merb::BootLoader + + + + + + + + + + + + + + + + () + + +Mixin the session functionality; this is done before BeforeAppLoads so that SessionContainer and SessionStoreContainer can be +subclassed by plugin session stores for example - these need to be loaded +in a before_app_loads block or a BootLoader +that runs after MixinSession. +

+

+Note: access to Merb::Config is needed, so it +needs to run after Merb::BootLoader::Dependencies +is done. +

+

Returns

+

+nil +

+

+:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/bootloader.rb, line 565 + def self.run + require 'merb-core/dispatch/session' + Merb::Controller.send(:include, ::Merb::SessionMixin) + Merb::Request.send(:include, ::Merb::SessionMixin::RequestMixin) + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/bootloader.rb + + + + + Merb::BootLoader + + + + + + + + + + + + + + + + () + + +Call any before_app_loads hooks that were registered via before_app_loads +in any plugins. +

+

Returns

+

+nil +

+

+:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/bootloader.rb, line 582 + def self.run + Merb::BootLoader.before_load_callbacks.each { |x| x.call } + nil + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/bootloader.rb + + + + + Merb::BootLoader + + + + + + + + + + + + + + + + (paths) + + +Reloads all files which have been modified since they were last loaded. +

+

Returns

+

+nil +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/bootloader.rb, line 1350 + def self.reload(paths) + paths.each do |file| + next if LoadClasses::MTIMES[file] && + LoadClasses::MTIMES[file] == File.mtime(file) + + LoadClasses.reload(file) + end + + nil + end + + +
+ + + () + + +Set up the class reloader if class reloading is enabled. This checks +periodically for modifications to files loaded by the LoadClasses BootLoader and reloads them when they are +modified. +

+

Returns

+

+nil +

+

+:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/bootloader.rb, line 1320 + def self.run + return unless Merb::Config[:reload_classes] + + paths = [] + Merb.load_paths.each do |path_name, file_info| + path, glob = file_info + next unless glob + paths << Dir[path / glob] + end + + if Merb.dir_for(:application) && File.file?(Merb.dir_for(:application)) + paths << Merb.dir_for(:application) + end + + paths.flatten! + + TimedExecutor.every(Merb::Config[:reload_time] || 0.5) do + GC.start + reload(paths) + end + + nil + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/bootloader.rb + + + + + Object + + + + + + + + + + + + + + + + (seconds) {|| ...} + + +Executes the associated block every @seconds@ seconds in a separate thread. +

+

Parameters

+ + + +
seconds<Integer>:Number of seconds to sleep in between runs of &block. + +
&block:The block to execute periodically. + +
+

Returns

+ + +
Thread:The thread executing the block periodically. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/bootloader.rb, line 1301 + def self.every(seconds, &block) + Thread.new do + loop do + sleep( seconds ) + yield + end + Thread.exit + end + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/bootloader.rb + + + + + Merb::BootLoader + + + + + + + + + + + + + + + + () + + +Choose the Rack adapter/server to use and set +Merb.adapter. +

+

Returns

+

+nil +

+

+:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/bootloader.rb, line 1249 + def self.run + Merb.adapter = Merb::Rack::Adapter.get(Merb::Config[:adapter]) + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/bootloader.rb + + + + + Merb::BootLoader + + + + +Stores pid file. +

+

+Only run if daemonization or clustering options specified on start. Port is +taken from Merb::Config and must be already set +at this point. +

+ + ]]>
+ + + + + + + + + + + + + + () + + +Stores a PID file if Merb is running daemonized or +clustered. +

+

Returns

+

+nil +

+

+:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/bootloader.rb, line 260 + def run + Merb::Server.store_pid("main") #if Merb::Config[:daemonize] || Merb::Config[:cluster] + nil + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/bootloader.rb + + + + + Merb::BootLoader + + + + + + + + + + + + + + + + () + + +Enable the configured session container(s); any class that inherits from SessionContainer will be considered by +its session_store_type attribute. +

+

Returns

+

+nil +

+

+:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/bootloader.rb, line 1166 + def self.run + # Require all standard session containers. + Dir[Merb.framework_root / "merb-core" / "dispatch" / "session" / "*.rb"].each do |file| + base_name = File.basename(file, ".rb") + require file unless base_name == "container" || base_name == "store_container" + end + + # Set some defaults. + Merb::Config[:session_id_key] ||= "_session_id" + + # List of all session_stores from :session_stores and :session_store config options. + config_stores = Merb::Config.session_stores + + # Register all configured session stores - any loaded session container class + # (subclassed from Merb::SessionContainer) will be available for registration. + Merb::SessionContainer.subclasses.each do |class_name| + if(store = Object.full_const_get(class_name)) && + config_stores.include?(store.session_store_type) + Merb::Request.register_session_type(store.session_store_type, class_name) + end + end + + # Mixin the Merb::Session module to add app-level functionality to sessions + overrides = (Merb::Session.instance_methods & Merb::SessionContainer.instance_methods) + overrides.each do |m| + Merb.logger.warn!("Warning: Merb::Session##{m} overrides existing " \ + "Merb::SessionContainer##{m}") + end + Merb::SessionContainer.send(:include, Merb::Session) + nil + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/bootloader.rb + + + + + Merb::BootLoader + + + + + + + + + + + + + + + + () + + +Setup the Merb Rack App or +read a rackup file located at Merb::Config[:rackup] with the same syntax as +the rackup tool that comes with rack. Automatically evals the file in the +context of a Rack::Builder.new { } block. Allows for mounting additional +apps or middleware. +

+

Returns

+

+nil +

+

+:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/bootloader.rb, line 1265 + def self.run + require 'rack' + if File.exists?(Merb.dir_for(:config) / "rack.rb") + Merb::Config[:rackup] ||= Merb.dir_for(:config) / "rack.rb" + end + + if Merb::Config[:rackup] + rackup_code = File.read(Merb::Config[:rackup]) + Merb::Config[:app] = eval("::Rack::Builder.new {( #{rackup_code}\n )}.to_app", TOPLEVEL_BINDING, Merb::Config[:rackup]) + else + Merb::Config[:app] = ::Rack::Builder.new { + if prefix = ::Merb::Config[:path_prefix] + use Merb::Rack::PathPrefix, prefix + end + use Merb::Rack::Static, Merb.dir_for(:public) + run Merb::Rack::Application.new + }.to_app + end + + nil + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/bootloader.rb + + + + + Merb::BootLoader + + + + +Set up cookies support in Merb::Controller +and Merb::Request +

+ + ]]>
+ + + + + + + + + + + + + + () + + +Set up cookies support in Merb::Controller +and Merb::Request +

+

Returns

+

+nil +

+

+:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/bootloader.rb, line 1148 + def self.run + require 'merb-core/dispatch/cookies' + Merb::Controller.send(:include, Merb::CookiesMixin) + Merb::Request.send(:include, Merb::CookiesMixin::RequestMixin) + nil + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/bootloader.rb + + + + + Merb::BootLoader + + + + +In case someone’s running a sparse app, the default exceptions +require the Exceptions class. This must run prior to the AfterAppLoads BootLoader so that plugins may have ensured +access in the after_app_loads block +

+ + ]]>
+ + + + + + + + + + + + + + () + + +Declares empty Application and Exception +controllers. +

+

Returns

+

+nil +

+

+:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/bootloader.rb, line 1210 + def self.run + unless defined?(Exceptions) + Object.class_eval "class Application < Merb::Controller\nabstract!\nend\n\nclass Exceptions < Merb::Controller\nend\n" + end + nil + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/bootloader.rb + + + + + Merb::BootLoader + + + + +Registers the default MIME types: +

+

+By default, the mime-types include: +

+ + + + + + + + +
:all:no transform, / + +
:yaml:to_yaml, application/x-yaml or text/yaml + +
:text:to_text, text/plain + +
:html:to_html, text/html or application/xhtml+xml or application/html + +
:xml:to_xml, application/xml or text/xml or application/x-xml + +
:js:to_json, text/javascript ot application/javascript or +application/x-javascript + +
:json:to_json, application/json or text/x-json + +
+ + ]]>
+ + + + + + + + + + + + + + () + + +Registers the default MIME types. +

+

Returns

+

+nil +

+

+:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/bootloader.rb, line 1127 + def self.run + Merb.add_mime_type(:all, nil, %w[*/*]) + Merb.add_mime_type(:yaml, :to_yaml, %w[application/x-yaml text/yaml], :charset => "utf-8") + Merb.add_mime_type(:text, :to_text, %w[text/plain], :charset => "utf-8") + Merb.add_mime_type(:html, :to_html, %w[text/html application/xhtml+xml application/html], :charset => "utf-8") + Merb.add_mime_type(:xml, :to_xml, %w[application/xml text/xml application/x-xml], {:charset => "utf-8"}, 0.9998) + Merb.add_mime_type(:js, :to_json, %w[text/javascript application/javascript application/x-javascript], :charset => "utf-8") + Merb.add_mime_type(:json, :to_json, %w[application/json text/x-json], :charset => "utf-8") + nil + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/bootloader.rb + + + + + Merb::BootLoader + + + + +Loads the router file. This needs to happen after everything else is loaded +while merb is starting up to ensure the router has everything it needs to +run. +

+ + ]]>
+ + + + + + + + + + + + + + () + + +Tries to find the router file. +

+

Returns

+ + +
String:The path to the router file if it exists, nil otherwise. + +
+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/bootloader.rb, line 1051 + def router_file + @router_file ||= begin + if File.file?(router = Merb.dir_for(:router) / Merb.glob_for(:router)) + router + end + end + end + + +
+ + + () + + +load the router file +

+

Returns

+

+nil +

+

+:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/bootloader.rb, line 1039 + def run + Merb::BootLoader::LoadClasses.load_file(router_file) if router_file + + nil + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/bootloader.rb + + + + + Merb::BootLoader + + + + +Build the framework paths. +

+

+By default, the following paths will be used: +

+ + + + + + + + + + + +
application:Merb.root/app/controller/application.rb + +
config:Merb.root/config + +
lib:Merb.root/lib + +
log:Merb.root/log + +
view:Merb.root/app/views + +
model:Merb.root/app/models + +
controller:Merb.root/app/controllers + +
helper:Merb.root/app/helpers + +
mailer:Merb.root/app/mailers + +
part:Merb.root/app/parts + +
+

+To override the default, set Merb::Config[:framework] in your +initialization file. Merb::Config[:framework] takes a Hash whose key is the name of the path, and whose values +can be passed into Merb.push_path (see Merb.push_path for full details). +

+

Notes

+

+All paths will default to Merb.root, so you can get a flat-file structure +by doing Merb::Config[:framework] = {}. +

+

Example

+
+  Merb::Config[:framework] = {
+    :view   => Merb.root / "views",
+    :model  => Merb.root / "models",
+    :lib    => Merb.root / "lib",
+    :public => [Merb.root / "public", nil]
+    :router => [Merb.root / "config", "router.rb"]
+  }
+
+

+That will set up a flat directory structure with the config files and +controller files under Merb.root, but with models, views, and lib with +their own folders off of Merb.root. +

+ + ]]>
+ + + + + + + + + + + + + + () + + +Sets up merb paths to support the app’s file layout. First, +config/framework.rb is checked, next we look for Merb.root/framework.rb, +finally we use the default merb layout (Merb::BootLoader.default_framework) +

+

+This method can be overridden to support other application layouts. +

+

Returns

+

+nil +

+

+:api: plugin @overridable +

+ ]]>
+ + + +# File lib/merb-core/bootloader.rb, line 345 + def build_framework + if File.exists?(Merb.root / "config" / "framework.rb") + require Merb.root / "config" / "framework" + elsif File.exists?(Merb.root / "framework.rb") + require Merb.root / "framework" + else + Merb::BootLoader.default_framework + end + (Merb::Config[:framework] || {}).each do |name, path| + path = Array(path) + Merb.push_path(name, path.first, path.length == 2 ? path[1] : "**/*.rb") + end + nil + end + + +
+ + + () + + +Builds the framework directory structure. +

+

Returns

+

+nil +

+

+:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/bootloader.rb, line 329 + def run + $:.push Merb.root unless Merb.root == File.expand_path(Dir.pwd) + build_framework + nil + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/bootloader.rb + + + + + Merb::BootLoader + + + + +Set up the logger. +

+

+Place the logger inside of the Merb log directory (set +up in Merb::BootLoader::BuildFramework) +

+ + ]]>
+ + + + + + + + + + + + + + () + + +Print a warning if the installed version of rubygems is not supported +

+

Returns

+

+nil +

+

+:api: private +

+ ]]>
+ + + +# File lib/merb-core/bootloader.rb, line 239 + def self.print_warnings + if Gem::Version.new(Gem::RubyGemsVersion) < Gem::Version.new("1.1") + Merb.fatal! "Merb requires Rubygems 1.1 and later. " \ + "Please upgrade RubyGems with gem update --system." + end + end + + +
+ + + () + + +Sets Merb.logger to a new logger created based on the config settings. +

+

Returns

+

+nil +

+

+:api: plugin +

+ ]]>
+ + + +# File lib/merb-core/bootloader.rb, line 216 + def self.run + Merb::Config[:log_level] ||= begin + if Merb.environment == "production" + Merb::Logger::Levels[:warn] + else + Merb::Logger::Levels[:debug] + end + end + + Merb::Config[:log_stream] = + Merb::Config[:original_log_stream] || Merb.log_stream + + print_warnings + + nil + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/test/run_specs.rb + + + + + Object + + + + + + + + + + + + + + RW + + + + + + + + + + + + + () + + + +# File lib/merb-core/test/run_specs.rb, line 29 + def initialize + @examples, @failures, @errors, @pending, @total_time = 0, 0, 0, 0, 0 + @err = "" + @mutex = Mutex.new + end + + + + + + + + + + + + (spec, out, err) + + + +# File lib/merb-core/test/run_specs.rb, line 39 + def add(spec, out, err) + @mutex.synchronize do + puts + puts "Running #{spec}." + STDOUT.puts out + STDOUT.flush + match = out.match(/(\d+) examples?, (\d+) failures?(?:, (\d+) errors?)?(?:, (\d+) pending?)?/m) + time = out.match(/Finished in (\d+\.\d+) seconds/) + @total_time += time[1].to_f if time + if match + e, f, errors, pending = match[1..-1] + @examples += e.to_i + @failures += f.to_i + @errors += errors.to_i + @pending += pending.to_i + end + unless err.chomp.empty? + @err << err.chomp << "\n" + end + end + end + + + + + + () + + + +# File lib/merb-core/test/run_specs.rb, line 35 + def failed? + @failures > 0 + end + + + + + + () + + + +# File lib/merb-core/test/run_specs.rb, line 61 + def report + i = 0 + @err.gsub!(/^\d*\)\s*/) do + "#{i += 1})\n" + end + + puts @err + puts + if @failures != 0 || @errors != 0 + print "\e[31m" # Red + elsif @pending != 0 + print "\e[33m" # Yellow + else + print "\e[32m" # Green + end + puts "#{@examples} examples, #{@failures} failures, #{@errors} errors, #{@pending} pending, #{sprintf("suite run in %3.3f seconds", @time.real)}" + # TODO: we need to report pending examples all together + puts "\e[0m" + end + + + + + + + + + + + + + + + + + + + + + lib/merb-core/dispatch/session/memory.rb + + + + + Merb::SessionStoreContainer + + + + +Sessions stored in memory. +

+

+Set it up by adding the following to your init file: +

+
+ Merb::Config.use do |c|
+   c[:session_store]      = :memory
+   c[:memory_session_ttl] = 3600 # in seconds, one hour
+ end
+
+

+Sessions will remain in memory until the server is stopped or the time as +set in :memory_session_ttl expires. Expired sessions are cleaned up in the +background by a separate thread. Every time reaper cleans up expired +sessions, garbage collection is scheduled start. +

+

+Memory session is accessed in a thread safe manner. +

+ + ]]>
+ + + + + + + + + + + + + + () + + +Lazy load/setup of MemorySessionStore. :api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/session/memory.rb, line 31 + def self.store + @_store ||= MemorySessionStore.new(Merb::Config[:memory_session_ttl]) + end + + +
+ + +
+ + + + + + () + + +Bypass normal implicit class attribute reader - see below. :api: private +

+ ]]>
+ + + +# File lib/merb-core/dispatch/session/memory.rb, line 25 + def store + self.class.store + end + + +
+ + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + lib/merb-core/test/test_ext/hpricot.rb + + + + + Object + + + + +yehudakatz.com/2007/01/27/a-better-assert_select-assert_elements/ +based on assert_elements Author: Yehuda Katz Email: wycats @nospam@ +gmail.com Web: www.yehudakatz.com +

+

+which was based on HpricotTestHelper Author: Luke Redpath Email: contact +@nospam@ lukeredpath.co.uk Web: www.lukeredpath.co.uk / +opensource.agileevolved.com +

+ + ]]>
+ + + + + + + + + + + + + + (value) + + + +# File lib/merb-core/test/test_ext/hpricot.rb, line 13 + def contain?(value) + self.inner_text.include?(value) + end + + + + + + (value) + + +Alias for contain? +

+ ]]>
+ + +
+ + + () + + +courtesy of ‘thomas’ from the comments of _whys blog - get in +touch if you want a better credit! +

+ ]]>
+ + + +# File lib/merb-core/test/test_ext/hpricot.rb, line 27 + def inner_text + self.children.collect do |child| + child.is_a?(Hpricot::Text) ? child.content : ((child.respond_to?("inner_text") && child.inner_text) || "") + end.join.strip + end + + +
+ + + (regex) + + + +# File lib/merb-core/test/test_ext/hpricot.rb, line 19 + def match?(regex) + self.inner_text.match(regex) + end + + + + + + (regex) + + +Alias for match? +

+ ]]>
+ + +
+ + +
+ + + + + +
+ +
+ + + + + + + lib/merb-core/tasks/gem_management.rb + + + + + + + + + + + + + + + + + + + (*messages) + + +red +

+ ]]>
+ + + +# File lib/merb-core/tasks/gem_management.rb, line 6 + def error(*messages) + puts messages.map { |msg| "\033[1;31m#{msg}\033[0m" } + end + + +
+ + + (*messages) + + +blue +

+ ]]>
+ + + +# File lib/merb-core/tasks/gem_management.rb, line 28 + def info(*messages) + puts messages.map { |msg| "\033[1;34m#{msg}\033[0m" } + end + + +
+ + + (*messages) + + +Alias for success +

+ ]]>
+ + +
+ + + (*messages) + + +magenta +

+ ]]>
+ + + +# File lib/merb-core/tasks/gem_management.rb, line 23 + def note(*messages) + puts messages.map { |msg| "\033[1;35m#{msg}\033[0m" } + end + + +
+ + + (*messages) + + +green +

+ ]]>
+ + + +# File lib/merb-core/tasks/gem_management.rb, line 16 + def success(*messages) + puts messages.map { |msg| "\033[1;32m#{msg}\033[0m" } + end + + +
+ + + (*messages) + + +yellow +

+ ]]>
+ + + +# File lib/merb-core/tasks/gem_management.rb, line 11 + def warning(*messages) + puts messages.map { |msg| "\033[1;33m#{msg}\033[0m" } + end + + +
+ + +
+ + + + + +
+ +
+ +
+
\ No newline at end of file diff --git a/config/environments/development.rb b/config/environments/development.rb new file mode 100644 index 0000000..d6d4ab3 --- /dev/null +++ b/config/environments/development.rb @@ -0,0 +1,15 @@ +Merb.logger.info("Loaded DEVELOPMENT Environment...") +Merb::Config.use { |c| + c[:exception_details] = true + c[:reload_templates] = true + c[:reload_classes] = true + c[:reload_time] = 0.5 + c[:ignore_tampered_cookies] = true + c[:log_auto_flush ] = true + c[:log_level] = :debug + + c[:log_stream] = STDOUT + c[:log_file] = nil + # Or redirect logging into a file: + # c[:log_file] = Merb.root / "log" / "development.log" +} diff --git a/config/environments/production.rb b/config/environments/production.rb new file mode 100644 index 0000000..17a2d4b --- /dev/null +++ b/config/environments/production.rb @@ -0,0 +1,10 @@ +Merb.logger.info("Loaded PRODUCTION Environment...") +Merb::Config.use { |c| + c[:exception_details] = false + c[:reload_classes] = false + c[:log_level] = :error + + c[:log_file] = Merb.root / "log" / "production.log" + # or redirect logger using IO handle + # c[:log_stream] = STDOUT +} diff --git a/config/environments/rake.rb b/config/environments/rake.rb new file mode 100644 index 0000000..5e4b9a7 --- /dev/null +++ b/config/environments/rake.rb @@ -0,0 +1,11 @@ +Merb.logger.info("Loaded RAKE Environment...") +Merb::Config.use { |c| + c[:exception_details] = true + c[:reload_classes] = false + c[:log_auto_flush ] = true + + c[:log_stream] = STDOUT + c[:log_file] = nil + # Or redirect logging into a file: + # c[:log_file] = Merb.root / "log" / "development.log" +} diff --git a/config/environments/staging.rb b/config/environments/staging.rb new file mode 100644 index 0000000..f5b5058 --- /dev/null +++ b/config/environments/staging.rb @@ -0,0 +1,10 @@ +Merb.logger.info("Loaded STAGING Environment...") +Merb::Config.use { |c| + c[:exception_details] = false + c[:reload_classes] = false + c[:log_level] = :error + + c[:log_file] = Merb.root / "log" / "staging.log" + # or redirect logger using IO handle + # c[:log_stream] = STDOUT +} diff --git a/config/environments/test.rb b/config/environments/test.rb new file mode 100644 index 0000000..671ec76 --- /dev/null +++ b/config/environments/test.rb @@ -0,0 +1,12 @@ +Merb.logger.info("Loaded TEST Environment...") +Merb::Config.use { |c| + c[:testing] = true + c[:exception_details] = true + c[:log_auto_flush ] = true + # log less in testing environment + c[:log_level] = :error + + #c[:log_file] = Merb.root / "log" / "test.log" + # or redirect logger using IO handle + c[:log_stream] = STDOUT +} diff --git a/config/init.rb b/config/init.rb new file mode 100644 index 0000000..aa09acf --- /dev/null +++ b/config/init.rb @@ -0,0 +1,27 @@ +# Go to http://wiki.merbivore.com/pages/init-rb + +require 'config/dependencies.rb' + +use_test :rspec +use_template_engine :haml + +Merb::Config.use do |c| + c[:use_mutex] = false + c[:session_store] = 'cookie' # can also be 'memory', 'memcache', 'container', 'datamapper + + # cookie session store configuration + c[:session_secret_key] = 'f23e88da6bff058f03dfd6f3a863c33d67007f68' # required for cookie session store + # c[:session_id_key] = '_session_id' # cookie session id key, defaults to "_session_id" +end + +Merb::BootLoader.before_app_loads do + DOC_XML = Nokogiri::XML.parse(File.read(Merb.root / "config" / "doc.xml", nil, 0)) + # This will get executed after dependencies have been loaded but before your app's classes have loaded. +end + +Merb::BootLoader.after_app_loads do + Merb::Cache.setup do + register(:default, Merb::Cache::PageStore[Merb::Cache::FileStore], :dir => Merb.root / :public / "cache") + end + # This will get executed after your app's classes have been loaded. +end diff --git a/config/rack.rb b/config/rack.rb new file mode 100644 index 0000000..a9008cb --- /dev/null +++ b/config/rack.rb @@ -0,0 +1,12 @@ +# use PathPrefix Middleware if :path_prefix is set in Merb::Config +if prefix = ::Merb::Config[:path_prefix] + use Merb::Rack::PathPrefix, prefix +end + +# comment this out if you are running merb behind a load balancer +# that serves static files +use Merb::Rack::Static, Merb.dir_for(:public) +use Merb::Rack::Static, Merb.dir_for(:public) / "cache" + +# this is our main merb application +run Merb::Rack::Application.new \ No newline at end of file diff --git a/config/router.rb b/config/router.rb new file mode 100644 index 0000000..c58980e --- /dev/null +++ b/config/router.rb @@ -0,0 +1,45 @@ +# Merb::Router is the request routing mapper for the merb framework. +# +# You can route a specific URL to a controller / action pair: +# +# match("/contact"). +# to(:controller => "info", :action => "contact") +# +# You can define placeholder parts of the url with the :symbol notation. These +# placeholders will be available in the params hash of your controllers. For example: +# +# match("/books/:book_id/:action"). +# to(:controller => "books") +# +# Or, use placeholders in the "to" results for more complicated routing, e.g.: +# +# match("/admin/:module/:controller/:action/:id"). +# to(:controller => ":module/:controller") +# +# You can specify conditions on the placeholder by passing a hash as the second +# argument of "match" +# +# match("/registration/:course_name", :course_name => /^[a-z]{3,5}-\d{5}$/). +# to(:controller => "registration") +# +# You can also use regular expressions, deferred routes, and many other options. +# See merb/specs/merb/router.rb for a fairly complete usage sample. + +Merb.logger.info("Compiling routes...") +Merb::Router.prepare do + # RESTful routes + # resources :posts + resources :klasses, :identify => :name, :singular => "doc/class" + + # Adds the required routes for merb-auth using the password slice + # slice(:merb_auth_slice_password, :name_prefix => nil, :path_prefix => "") + + # This is the default route for /:controller/:action/:id + # This is fine for most cases. If you're heavily using resource-based + # routes, you may want to comment/remove this line to prevent + # clients from calling your create or destroy actions with a GET + default_routes + + # Change this for your home page to be available at / + # match('/').to(:controller => 'whatever', :action =>'index') +end \ No newline at end of file diff --git a/doc/rdoc/generators/merb_generator.rb b/doc/rdoc/generators/merb_generator.rb new file mode 100644 index 0000000..544c273 --- /dev/null +++ b/doc/rdoc/generators/merb_generator.rb @@ -0,0 +1,1362 @@ + +# # We're responsible for generating all the HTML files +# from the object tree defined in code_objects.rb. We +# generate: +# +# [files] an html file for each input file given. These +# input files appear as objects of class +# TopLevel +# +# [classes] an html file for each class or module encountered. +# These classes are not grouped by file: if a file +# contains four classes, we'll generate an html +# file for the file itself, and four html files +# for the individual classes. +# +# Method descriptions appear in whatever entity (file, class, +# or module) that contains them. +# +# We generate files in a structure below a specified subdirectory, +# normally +doc+. +# +# opdir +# | +# |___ files +# | |__ per file summaries +# | +# |___ classes +# |__ per class/module descriptions +# +# HTML is generated using the Template class. +# + +require 'ftools' + +require 'rdoc/options' +require 'rdoc/template' +require 'rdoc/markup/simple_markup' +require 'rdoc/markup/simple_markup/to_html' +require 'cgi' + +module Generators + + # Name of sub-direcories that hold file and class/module descriptions + + FILE_DIR = "files" + CLASS_DIR = "classes" + CSS_NAME = "stylesheet.css" + + + ## + # Build a hash of all items that can be cross-referenced. + # This is used when we output required and included names: + # if the names appear in this hash, we can generate + # an html cross reference to the appropriate description. + # We also use this when parsing comment blocks: any decorated + # words matching an entry in this list are hyperlinked. + + class AllReferences + @@refs = {} + + def AllReferences::reset + @@refs = {} + end + + def AllReferences.add(name, html_class) + @@refs[name] = html_class + end + + def AllReferences.[](name) + @@refs[name] + end + + def AllReferences.keys + @@refs.keys + end + end + + + ## + # Subclass of the SM::ToHtml class that supports looking + # up words in the AllReferences list. Those that are + # found (like AllReferences in this comment) will + # be hyperlinked + + class HyperlinkHtml < SM::ToHtml + # We need to record the html path of our caller so we can generate + # correct relative paths for any hyperlinks that we find + def initialize(from_path, context) + super() + @from_path = from_path + + @parent_name = context.parent_name + @parent_name += "::" if @parent_name + @context = context + end + + # We're invoked when any text matches the CROSSREF pattern + # (defined in MarkUp). If we fine the corresponding reference, + # generate a hyperlink. If the name we're looking for contains + # no punctuation, we look for it up the module/class chain. For + # example, HyperlinkHtml is found, even without the Generators:: + # prefix, because we look for it in module Generators first. + + def handle_special_CROSSREF(special) + name = special.text + if name[0,1] == '#' + lookup = name[1..-1] + name = lookup unless Options.instance.show_hash + else + lookup = name + end + + if /([A-Z].*)[.\#](.*)/ =~ lookup + container = $1 + method = $2 + ref = @context.find_symbol(container, method) + else + ref = @context.find_symbol(lookup) + end + + if ref and ref.document_self + "#{name}" + else + name #it does not need to be a link + end + end + + + # Generate a hyperlink for url, labeled with text. Handle the + # special cases for img: and link: described under handle_special_HYPEDLINK + def gen_url(url, text) + if url =~ /([A-Za-z]+):(.*)/ + type = $1 + path = $2 + else + type = "http" + path = url + url = "http://#{url}" + end + + if type == "link" + url = path + end + + if (type == "http" || type == "link") && url =~ /\.(gif|png|jpg|jpeg|bmp)$/ + "" + elsif (type == "http" || type == "link") + "#{text}" + else + "#{text.sub(%r{^#{type}:/*}, '')}" + + end + end + + # And we're invoked with a potential external hyperlink mailto: + # just gets inserted. http: links are checked to see if they + # reference an image. If so, that image gets inserted using an + # tag. Otherwise a conventional is used. We also + # support a special type of hyperlink, link:, which is a reference + # to a local file whose path is relative to the --op directory. + + def handle_special_HYPERLINK(special) + url = special.text + gen_url(url, url) + end + + # HEre's a hypedlink where the label is different to the URL + #

/, '') + res.sub!(/<\/p>$/, '') + end + res + end + + + def style_url(path, css_name=nil) + css_name ||= CSS_NAME + end + + # Build a webcvs URL with the given 'url' argument. URLs with a '%s' in them + # get the file's path sprintfed into them; otherwise they're just catenated + # together. + + def cvs_url(url, full_path) + if /%s/ =~ url + return sprintf( url, full_path ) + else + return url + full_path + end + end + end + + + ##################################################################### + # + # A Context is built by the parser to represent a container: contexts + # hold classes, modules, methods, require lists and include lists. + # ClassModule and TopLevel are the context objects we process here + # + class ContextUser + + include MarkUp + + attr_reader :context + + def initialize(context, options) + @context = context + @options = options + + end + + # convenience method to build a hyperlink # Where's the DRY in this?? Put this in the template where it belongs + def href(link, cls, name) + %{"#{name}"} + end + + # Create a list of HtmlMethod objects for each method + # in the corresponding context object. If the @options.show_all + # variable is set (corresponding to the --all option, + # we include all methods, otherwise just the public ones. + + def collect_methods + list = @context.method_list + unless @options.show_all + list = list.find_all {|m| m.visibility == :public || m.visibility == :protected || m.force_documentation } + end + @methods = list.collect {|m| HtmlMethod.new(m, self, @options) } + end + + # Build a summary list of all the methods in this context + def build_method_summary_list(path_prefix="") + collect_methods unless @methods + meths = @methods.sort + res = [] + meths.each do |meth| + res << { + "name" => CGI.escapeHTML(meth.name), + "aref" => meth.aref, + "href" => meth.path + } + end + res + end + + + # Build a list of aliases for which we couldn't find a + # corresponding method + def build_alias_summary_list(section) + values = [] + @context.aliases.each do |al| + next unless al.section == section + res = { + 'old_name' => al.old_name, + 'new_name' => al.new_name, + } + if al.comment && !al.comment.empty? + res['desc'] = markup(al.comment, true) + end + values << res + end + values + end + + # Build a list of constants + def build_constants_summary_list(section) + values = [] + @context.constants.each do |co| + next unless co.section == section + res = { + 'name' => co.name, + 'value' => CGI.escapeHTML(co.value) + } + res['desc'] = markup(co.comment, true) if co.comment && !co.comment.empty? + values << res + end + values + end + + def build_requires_list(context) + potentially_referenced_list(context.requires) {|fn| [fn + ".rb"] } + end + + def build_include_list(context) + potentially_referenced_list(context.includes) + end + + # Build a list from an array of Htmlxxx items. Look up each + # in the AllReferences hash: if we find a corresponding entry, + # we generate a hyperlink to it, otherwise just output the name. + # However, some names potentially need massaging. For example, + # you may require a Ruby file without the .rb extension, + # but the file names we know about may have it. To deal with + # this, we pass in a block which performs the massaging, + # returning an array of alternative names to match + + def potentially_referenced_list(array) + res = [] + array.each do |i| + ref = AllReferences[i.name] + # if !ref + # container = @context.parent + # while !ref && container + # name = container.name + "::" + i.name + # ref = AllReferences[name] + # container = container.parent + # end + # end + + ref = @context.find_symbol(i.name) + ref = ref.viewer if ref + + if !ref && block_given? + possibles = yield(i.name) + while !ref and !possibles.empty? + ref = AllReferences[possibles.shift] + end + end + h_name = CGI.escapeHTML(i.name) + if ref and ref.document_self + path = ref.path + res << { "name" => h_name, "href" => path } + else + res << { "name" => h_name, "href" => "" } + end + end + res + end + + # Build an array of arrays of method details. The outer array has up + # to six entries, public, private, and protected for both class + # methods, the other for instance methods. The inner arrays contain + # a hash for each method + + def build_method_detail_list(section) + outer = [] + + methods = @methods.sort + for singleton in [true, false] + for vis in [ :public, :protected, :private ] + res = [] + methods.each do |m| + if m.section == section and + m.document_self and + m.visibility == vis and + m.singleton == singleton + row = {} + if m.call_seq + row["callseq"] = m.call_seq.gsub(/->/, '→') + else + row["name"] = CGI.escapeHTML(m.name) + row["params"] = m.params + end + desc = m.description.strip + row["m_desc"] = desc unless desc.empty? + row["aref"] = m.aref + row["href"] = m.path + row["m_seq"] = m.seq + row["visibility"] = m.visibility.to_s + + alias_names = [] + m.aliases.each do |other| + if other.viewer # won't be if the alias is private + alias_names << { + 'name' => other.name, + 'href' => other.viewer.path, + 'aref' => other.viewer.aref + } + end + end + unless alias_names.empty? + row["aka"] = alias_names + end + + #if @options.inline_source + code = m.source_code + row["sourcecode"] = code if code + #else + # code = m.src_url + #if code + # row["codeurl"] = code + # row["imgurl"] = m.img_url + #end + #end + res << row + end + end + if res.size > 0 + outer << { + "type" => vis.to_s.capitalize, + "category" => singleton ? "Class" : "Instance", + "methods" => res + } + end + end + end + outer + end + + # Build the structured list of classes and modules contained + # in this context. + + def build_class_list(level, from, section, infile=nil) + res = "" + prefix = "  ::" * level; + + from.modules.sort.each do |mod| + next unless mod.section == section + next if infile && !mod.defined_in?(infile) + if mod.document_self + res << + prefix << + "Module " << + href(mod.viewer.path, "link", mod.full_name) << + "
\n" << + build_class_list(level + 1, mod, section, infile) + end + end + + from.classes.sort.each do |cls| + next unless cls.section == section + next if infile && !cls.defined_in?(infile) + if cls.document_self + res << + prefix << + "Class " << + href(cls.viewer.path, "link", cls.full_name) << + "
\n" << + build_class_list(level + 1, cls, section, infile) + end + end + + res + end + + def document_self + @context.document_self + end + + def diagram_reference(diagram) + res = diagram.gsub(/((?:src|href)=")(.*?)"/) { + $1 + $2 + '"' + } + res + end + + + # Find a symbol in ourselves or our parent + def find_symbol(symbol, method=nil) + res = @context.find_symbol(symbol, method) + if res + res = res.viewer + end + res + end + + # create table of contents if we contain sections + + def add_table_of_sections + toc = [] + @context.sections.each do |section| + if section.title + toc << { + 'secname' => section.title, + 'href' => section.sequence + } + end + end + + @values['toc'] = toc unless toc.empty? + end + + + end + + ##################################################################### + # + # Wrap a ClassModule context + + class HtmlClass < ContextUser + + @@c_seq = "C00000000" + + attr_reader :path + + def initialize(context, html_file, prefix, options) + super(context, options) + @@c_seq = @@c_seq.succ + @c_seq = @@c_seq + @html_file = html_file + @is_module = context.is_module? + @values = {} + + context.viewer = self + + @path = http_url(context.full_name, prefix) + + collect_methods + + AllReferences.add(name, self) + end + + # return the relative file name to store this class in, + # which is also its url + def http_url(full_name, prefix) + path = full_name.dup + if path['<<'] + path.gsub!(/<<\s*(\w*)/) { "from-#$1" } + end + File.join(prefix, path.split("::")) + ".html" + end + + def seq + @c_seq + end + + def aref + @c_seq + end + + def scope + a = @context.full_name.split("::") + if a.length > 1 + a.pop + a.join("::") + else + "" + end + end + + def name + @context.full_name.gsub("#{scope}::", '') + end + + def full_name + @context.full_name + end + + def parent_name + @context.parent.full_name + end + + def write_on(f) + value_hash + template = TemplatePage.new(RDoc::Page::BODY, + RDoc::Page::CLASS_PAGE, + RDoc::Page::METHOD_LIST) + template.write_html_on(f, @values) + end + + def value_hash + class_attribute_values + add_table_of_sections + + @values["charset"] = @options.charset + @values["style_url"] = style_url(path, @options.css) + + # Convert README to html + unless File.exist?('files/README.html') + File.open('files/README.html', 'w') do |file| + file << markup(File.read(File.expand_path(@options.main_page))) + end + end + + d = markup(@context.comment) + @values["description"] = d unless d.empty? + + ml = build_method_summary_list + @values["methods"] = ml unless ml.empty? + + il = build_include_list(@context) + @values["includes"] = il unless il.empty? + + @values["sections"] = @context.sections.map do |section| + + secdata = { + "sectitle" => section.title, + "secsequence" => section.sequence, + "seccomment" => markup(section.comment) + } + + al = build_alias_summary_list(section) + secdata["aliases"] = al unless al.empty? + + co = build_constants_summary_list(section) + secdata["constants"] = co unless co.empty? + + al = build_attribute_list(section) + secdata["attributes"] = al unless al.empty? + + cl = build_class_list(0, @context, section) + secdata["classlist"] = cl unless cl.empty? + + mdl = build_method_detail_list(section) + secdata["method_list"] = mdl unless mdl.empty? + + secdata + end + + @values + end + + def build_attribute_list(section) + atts = @context.attributes.sort + res = [] + atts.each do |att| + next unless att.section == section + if att.visibility == :public || att.visibility == :protected || @options.show_all + entry = { + "name" => CGI.escapeHTML(att.name), + "rw" => att.rw, + "a_desc" => markup(att.comment, true) + } + unless att.visibility == :public || att.visibility == :protected + entry["rw"] << "-" + end + res << entry + end + end + res + end + + def class_attribute_values + h_name = CGI.escapeHTML(name) + + @values["classmod"] = @is_module ? "Module" : "Class" + @values["title"] = "#{@values['classmod']}: #{h_name}" + + c = @context + c = c.parent while c and !c.diagram + if c && c.diagram + @values["diagram"] = diagram_reference(c.diagram) + end + + @values["full_name"] = h_name + @values["class_seq"] = seq + parent_class = @context.superclass + + if parent_class + @values["parent"] = CGI.escapeHTML(parent_class) + + if parent_name + lookup = parent_name + "::" + parent_class + else + lookup = parent_class + end + + parent_url = AllReferences[lookup] || AllReferences[parent_class] + + if parent_url and parent_url.document_self + @values["par_url"] = parent_url.path + end + end + + files = [] + @context.in_files.each do |f| + res = {} + full_path = CGI.escapeHTML(f.file_absolute_name) + + res["full_path"] = full_path + res["full_path_url"] = f.viewer.path if f.document_self + + if @options.webcvs + res["cvsurl"] = cvs_url( @options.webcvs, full_path ) + end + + files << res + end + + @values['infiles'] = files + end + + def <=>(other) + self.name <=> other.name + end + + end + + ##################################################################### + # + # Handles the mapping of a file's information to HTML. In reality, + # a file corresponds to a +TopLevel+ object, containing modules, + # classes, and top-level methods. In theory it _could_ contain + # attributes and aliases, but we ignore these for now. + + class HtmlFile < ContextUser + + @@f_seq = "F00000000" + + attr_reader :path + attr_reader :name + + def initialize(context, options, file_dir) + super(context, options) + @@f_seq = @@f_seq.succ + @f_seq = @@f_seq + @values = {} + + @path = http_url(file_dir) + @source_file_path = File.expand_path(@context.file_relative_name).gsub("\/doc\/", "/") + @name = @context.file_relative_name + + collect_methods + AllReferences.add(name, self) + context.viewer = self + end + + def http_url(file_dir) + File.join(file_dir, @context.file_relative_name.tr('.', '_')) + ".html" + end + + def filename_to_label + @context.file_relative_name.gsub(/%|\/|\?|\#/) {|s| '%' + ("%x" % s[0]) } + end + + def seq + @f_seq + end + + def aref + @f_seq + end + + def name + full_path = @context.file_absolute_name + short_name = File.basename(full_path) + end + + def full_name + @context.file_absolute_name + end + + def scope + @context.file_relative_name.gsub(/\/#{name}$/, '') + end + + def parent_name + nil + end + + def full_file_source + ret_str = "" + File.open(@source_file_path, 'r') do |f| + while(!f.eof?) do + ret_str += f.readline() + end + end + ret_str + rescue + "file not found -#{@source_file_path}-" + #@source_file_path + end + + def value_hash + file_attribute_values + add_table_of_sections + + @values["charset"] = @options.charset + @values["href"] = path + @values["style_url"] = style_url(path, @options.css) + @values["file_seq"] = seq + + #pulling in the source for this file + #@values["source_code"] = @context.token_stream + + @values["file_source_code"] = CGI.escapeHTML(full_file_source) + + if @context.comment + d = markup(@context.comment) + @values["description"] = d if d.size > 0 + end + + ml = build_method_summary_list + @values["methods"] = ml unless ml.empty? + + il = build_include_list(@context) + @values["includes"] = il unless il.empty? + + rl = build_requires_list(@context) + @values["requires"] = rl unless rl.empty? + + + file_context = @context + + @values["sections"] = @context.sections.map do |section| + + secdata = { + "sectitle" => section.title, + "secsequence" => section.sequence, + "seccomment" => markup(section.comment) + } + + cl = build_class_list(0, @context, section, file_context) + @values["classlist"] = cl unless cl.empty? + + mdl = build_method_detail_list(section) + secdata["method_list"] = mdl unless mdl.empty? + + al = build_alias_summary_list(section) + secdata["aliases"] = al unless al.empty? + + co = build_constants_summary_list(section) + @values["constants"] = co unless co.empty? + + secdata + end + + @values + end + + def write_on(f) + value_hash + template = TemplatePage.new(RDoc::Page::SRC_BODY,RDoc::Page::FILE_PAGE, RDoc::Page::METHOD_LIST) + template.write_html_on(f, @values) + end + + def file_attribute_values + full_path = @context.file_absolute_name + short_name = File.basename(full_path) + + @values["title"] = CGI.escapeHTML("File: #{short_name}") + + if @context.diagram + @values["diagram"] = diagram_reference(@context.diagram) + end + + @values["short_name"] = CGI.escapeHTML(short_name) + @values["full_path"] = CGI.escapeHTML(full_path) + @values["dtm_modified"] = @context.file_stat.mtime.to_s + + if @options.webcvs + @values["cvsurl"] = cvs_url( @options.webcvs, @values["full_path"] ) + end + end + + def <=>(other) + self.name <=> other.name + end + end + + ##################################################################### + + class HtmlMethod + include MarkUp + + attr_reader :context + attr_reader :src_url + attr_reader :img_url + attr_reader :source_code + + @@m_seq = "M000000" + + @@all_methods = [] + + def HtmlMethod::reset + @@all_methods = [] + end + + def initialize(context, html_class, options) + @context = context + @html_class = html_class + @options = options + @@m_seq = @@m_seq.succ + @m_seq = @@m_seq + @@all_methods << self + + context.viewer = self + + if (ts = @context.token_stream) + @source_code = markup_code(ts) + #unless @options.inline_source + # @src_url = create_source_code_file(@source_code) + # @img_url = MERBGenerator.gen_url(path, 'source.png') + #end + end + AllReferences.add(name, self) + end + + def seq + @m_seq + end + + def aref + @m_seq + end + + def scope + @html_class.full_name + end + + # return a reference to outselves to be used as an href= + # the form depends on whether we're all in one file + # or in multiple files + + def name + @context.name + end + + def section + @context.section + end + + def parent_name + if @context.parent.parent + @context.parent.parent.full_name + else + nil + end + end + + def path + @html_class.path + end + + def description + markup(@context.comment) + end + + def visibility + @context.visibility + end + + def singleton + @context.singleton + end + + def call_seq + cs = @context.call_seq + if cs + cs.gsub(/\n/, "
\n") + else + nil + end + end + + def params + # params coming from a call-seq in 'C' will start with the + # method name + p = @context.params + if p !~ /^\w/ + p = @context.params.gsub(/\s*\#.*/, '') + p = p.tr("\n", " ").squeeze(" ") + p = "(" + p + ")" unless p[0] == ?( + + if (block = @context.block_params) + # If this method has explicit block parameters, remove any + # explicit &block + + p.sub!(/,?\s*&\w+/, '') + + block.gsub!(/\s*\#.*/, '') + block = block.tr("\n", " ").squeeze(" ") + if block[0] == ?( + block.sub!(/^\(/, '').sub!(/\)/, '') + end + p << " {|#{block.strip}| ...}" + end + end + CGI.escapeHTML(p) + end + + def create_source_code_file(code_body) + meth_path = @html_class.path.sub(/\.html$/, '.src') + File.makedirs(meth_path) + file_path = File.join(meth_path, seq) + ".html" + + template = TemplatePage.new(RDoc::Page::SRC_PAGE) + File.open(file_path, "w") do |f| + values = { + 'title' => CGI.escapeHTML(name), + 'code' => code_body, + 'style_url' => style_url(file_path, @options.css), + 'charset' => @options.charset + } + template.write_html_on(f, values) + end + file_path + end + + def HtmlMethod.all_methods + @@all_methods + end + + def <=>(other) + @context <=> other.context + end + + ## + # Given a sequence of source tokens, mark up the source code + # to make it look purty. + + + def markup_code(tokens) + src = "" + tokens.each do |t| + next unless t + # p t.class + # style = STYLE_MAP[t.class] + style = case t + when RubyToken::TkCONSTANT then "ruby-constant" + when RubyToken::TkKW then "ruby-keyword kw" + when RubyToken::TkIVAR then "ruby-ivar" + when RubyToken::TkOp then "ruby-operator" + when RubyToken::TkId then "ruby-identifier" + when RubyToken::TkNode then "ruby-node" + when RubyToken::TkCOMMENT then "ruby-comment cmt" + when RubyToken::TkREGEXP then "ruby-regexp re" + when RubyToken::TkSTRING then "ruby-value str" + when RubyToken::TkVal then "ruby-value" + else + nil + end + + text = CGI.escapeHTML(t.text) + + if style + src << "#{text}" + else + src << text + end + end + + add_line_numbers(src) + src + end + + # we rely on the fact that the first line of a source code + # listing has + # # File xxxxx, line dddd + + def add_line_numbers(src) + if src =~ /\A.*, line (\d+)/ + first = $1.to_i - 1 + last = first + src.count("\n") + size = last.to_s.length + real_fmt = "%#{size}d: " + fmt = " " * (size+2) + src.gsub!(/^/) do + res = sprintf(fmt, first) + first += 1 + fmt = real_fmt + res + end + end + end + + def document_self + @context.document_self + end + + def aliases + @context.aliases + end + + def find_symbol(symbol, method=nil) + res = @context.parent.find_symbol(symbol, method) + if res + res = res.viewer + end + res + end + end + + ##################################################################### + + class MERBGenerator + + include MarkUp + + # Generators may need to return specific subclasses depending + # on the options they are passed. Because of this + # we create them using a factory + + def MERBGenerator.for(options) + AllReferences::reset + HtmlMethod::reset + + MERBGenerator.new(options) + + end + + class < "helvetica"} #this is not used anywhere but the template function demands a hash of values + template.write_html_on(f, values) + end + end + + def write_javascript + #Argh... I couldn't figure out how to copy these from the template dir so they were copied into + # the template file "ajax.rb" and processed similarlly to the style sheets. Not exactly a good thing to do with + # external library code. Not very DRY. + + File.open("api_grease.js", "w") do |f| + f << RDoc::Page::API_GREASE_JS + end + + File.open("prototype.js", "w") do |f| + f << RDoc::Page::PROTOTYPE_JS + end + + rescue LoadError + $stderr.puts "Could not find AJAX template" + exit 99 + end + + ## + # See the comments at the top for a description of the + # directory structure + + def gen_sub_directories + File.makedirs(FILE_DIR, CLASS_DIR) + rescue + $stderr.puts $!.message + exit 1 + end + + ## + # Generate: + # + # * a list of HtmlFile objects for each TopLevel object. + # * a list of HtmlClass objects for each first level + # class or module in the TopLevel objects + # * a complete list of all hyperlinkable terms (file, + # class, module, and method names) + + def build_indices + + @toplevels.each do |toplevel| + @files << HtmlFile.new(toplevel, @options, FILE_DIR) + end + + RDoc::TopLevel.all_classes_and_modules.each do |cls| + build_class_list(cls, @files[0], CLASS_DIR) + end + end + + def build_class_list(from, html_file, class_dir) + @classes << HtmlClass.new(from, html_file, class_dir, @options) + from.each_classmodule do |mod| + build_class_list(mod, html_file, class_dir) + end + end + + ## + # Generate all the HTML + # + def generate_html + # the individual descriptions for files and classes + gen_into(@files) + gen_into(@classes) + # and the index files + gen_file_index + gen_class_index + gen_method_index + gen_main_index + + # this method is defined in the template file + write_extra_pages if defined? write_extra_pages + end + + def gen_into(list) + list.each do |item| + if item.document_self + op_file = item.path + File.makedirs(File.dirname(op_file)) + File.open(op_file, "w") { |file| item.write_on(file) } + end + end + + end + + def gen_file_index + gen_an_index(@files, 'Files', + RDoc::Page::FILE_INDEX, + "fr_file_index.html") + end + + def gen_class_index + gen_an_index(@classes, 'Classes', + RDoc::Page::CLASS_INDEX, + "fr_class_index.html") + end + + def gen_method_index + gen_an_index(HtmlMethod.all_methods, 'Methods', + RDoc::Page::METHOD_INDEX, + "fr_method_index.html") + end + + + def gen_an_index(collection, title, template, filename) + template = TemplatePage.new(RDoc::Page::FR_INDEX_BODY, template) + res = [] + collection.sort.each do |f| + if f.document_self + res << { "href" => f.path, "name" => f.name, "scope" => f.scope, "seq_id" => f.seq } + end + end + + values = { + "entries" => res, + 'list_title' => CGI.escapeHTML(title), + 'index_url' => main_url, + 'charset' => @options.charset, + 'style_url' => style_url('', @options.css), + } + + File.open(filename, "w") do |f| + template.write_html_on(f, values) + end + end + + # The main index page is mostly a template frameset, but includes + # the initial page. If the --main option was given, + # we use this as our main page, otherwise we use the + # first file specified on the command line. + + def gen_main_index + template = TemplatePage.new(RDoc::Page::INDEX) + File.open("index.html", "w") do |f| + tStr = "" + #File.open(main_url, 'r') do |g| + # tStr = markup(g) + #end + values = { + "initial_page" => tStr, + 'title' => CGI.escapeHTML(@options.title), + 'charset' => @options.charset, + 'content' => File.read('files/README.html') + } + + values['inline_source'] = true + template.write_html_on(f, values) + end + end + + # return the url of the main page + def main_url + "files/README.html" + end + + + end + +end diff --git a/doc/rdoc/generators/template/merb/api_grease.js b/doc/rdoc/generators/template/merb/api_grease.js new file mode 100644 index 0000000..3df710e --- /dev/null +++ b/doc/rdoc/generators/template/merb/api_grease.js @@ -0,0 +1,640 @@ + +function setupPage(){ + hookUpActiveSearch(); + hookUpTabs(); + suppressPostbacks(); + var url_params = getUrlParams(); + if (url_params != null){ + loadUrlParams(url_params); + }else{ + loadDefaults(); + } + resizeDivs(); + window.onresize = function(){ resizeDivs(); }; +} + +function getUrlParams(){ + var window_location = window.location.href + var param_pos = window_location.search(/\?/) + if (param_pos > 0){ + return(window_location.slice(param_pos, window_location.length)); + }else{ + return(null); + } +} + +function loadUrlParams(url_param){ + //get the tabs + var t = getTabs(); + // now find our variables + var s_params = /(\?)(a=.+?)(&)(name=.*)/; + var results = url_param.match(s_params); + url_anchor = results[2].replace(/a=/,''); + + if (url_anchor.match(/M.+/)){//load the methods tab and scroller content + setActiveTabAndLoadContent(t[0]); + }else{ + if(url_anchor.match(/C.+/)){ //load the classes tab and scroller content + setActiveTabAndLoadContent(t[1]); + }else{ + if (url_anchor.match(/F.+/)){//load the files tab + setActiveTabAndLoadContent(t[2]); + }else{ + // default to loading the methods + setActiveTabAndLoadContent(t[0]); + } + } + } + paramLoadOfContentAnchor(url_anchor + "_link"); +} + +function updateUrlParams(anchor_id, name){ + //Also setting the page title + //window.document.title = name + " method - MerbBrain.com "; + + //updating the window location + var current_href = window.location.href; + //var m_name = name.replace("?","?"); + var rep_str = ".html?a=" + anchor_id + "&name=" + name; + var new_href = current_href.replace(/\.html.*/, rep_str); + if (new_href != current_href){ + window.location.href = new_href; + } +} + +//does as it says... +function hookUpActiveSearch(){ + + var s_field = $('searchForm').getInputs('text')[0]; + //var s_field = document.forms[0].searchText; + Event.observe(s_field, 'keydown', function(event) { + var el = Event.element(event); + var key = event.which || event.keyCode; + + switch (key) { + case Event.KEY_RETURN: + forceLoadOfContentAnchor(getCurrentAnchor()); + Event.stop(event); + break; + + case Event.KEY_UP: + scrollListToElementOffset(getCurrentAnchor(),-1); + break; + + case Event.KEY_DOWN: + scrollListToElementOffset(getCurrentAnchor(),1); + break; + + default: + break; + } + + }); + + Event.observe(s_field, 'keyup', function(event) { + var el = Event.element(event); + var key = event.which || event.keyCode; + switch (key) { + case Event.KEY_RETURN: + Event.stop(event); + break; + + case Event.KEY_UP: + break; + + case Event.KEY_DOWN: + break; + + default: + scrollToName(el.value); + setSavedSearch(getCurrentTab(), el.value); + break; + } + + }); + + Event.observe(s_field, 'keypress', function(event){ + var el = Event.element(event); + var key = event.which || event.keyCode; + switch (key) { + case Event.KEY_RETURN: + Event.stop(event); + break; + + default: + break; + } + + }); + + //Event.observe(document, 'keypress', function(event){ + // var key = event.which || event.keyCode; + // if (key == Event.KEY_TAB){ + // cycleNextTab(); + // Event.stop(event); + // } + //}); +} + +function hookUpTabs(){ + + var tabs = getTabs(); + for(x=0; x < tabs.length; x++) + { + Event.observe(tabs[x], 'click', function(event){ + var el = Event.element(event); + setActiveTabAndLoadContent(el); + }); + //tabs[x].onclick = function (){ return setActiveTabAndLoadContent(this);}; //the prototype guys say this is bad.. + } + +} + +function suppressPostbacks(){ + Event.observe('searchForm', 'submit', function(event){ + Event.stop(event); + }); +} + +function loadDefaults(){ + var t = getTabs(); + setActiveTabAndLoadContent(t[0]); //default loading of the first tab +} + +function resizeDivs(){ + var inner_height = 700; + if (window.innerHeight){ + inner_height = window.innerHeight; //all browsers except IE use this to determine the space available inside a window. Thank you Microsoft!! + }else{ + if(document.documentElement.clientHeight > 0){ //IE uses this in 'strict' mode + inner_height = document.documentElement.clientHeight; + }else{ + inner_height = document.body.clientHeight; //IE uses this in 'quirks' mode + } + } + $('rdocContent').style.height = (inner_height - 92) + "px";//Thankfully all browsers can agree on how to set the height of a div + $('listScroller').style.height = (inner_height - 88) + "px"; +} + +//The main function for handling clicks on the tabs +function setActiveTabAndLoadContent(current_tab){ + changeLoadingStatus("on"); + var tab_string = String(current_tab.innerHTML).strip(); //thank you ProtoType! + switch (tab_string){ + case "classes": + setCurrentTab("classes"); + loadScrollerContent('fr_class_index.html'); + setSearchFieldValue(getSavedSearch("classes")); + scrollToName(getSavedSearch("classes")); + setSearchFocus(); + break; + + case "files": + setCurrentTab("files"); + loadScrollerContent('fr_file_index.html'); + setSearchFieldValue(getSavedSearch("files")); + scrollToName(getSavedSearch("files")); + setSearchFocus(); + break; + + case "methods": + setCurrentTab("methods"); + loadScrollerContent('fr_method_index.html'); + setSearchFieldValue(getSavedSearch("methods")); + scrollToName(getSavedSearch("methods")); + setSearchFocus(); + break; + + default: + break; + } + changeLoadingStatus("off"); +} + +function cycleNextTab(){ + var currentT = getCurrentTab(); + var tabs = getTabs(); + if (currentT == "methods"){ + setActiveTabAndLoadContent(tabs[1]); + setSearchFocus(); + }else{ + if (currentT == "classes"){ + setActiveTabAndLoadContent(tabs[2]); + setSearchFocus(); + }else{ + if (currentT == "files"){ + setActiveTabAndLoadContent(tabs[0]); + setSearchFocus(); + } + } + } +} + +function getTabs(){ + return($('groupType').getElementsByTagName('li')); +} + +var Active_Tab = ""; +function getCurrentTab(){ + return Active_Tab; +} + +function setCurrentTab(tab_name){ + var tabs = getTabs(); + for(x=0; x < tabs.length; x++) + { + if(tabs[x].innerHTML.strip() == tab_name) //W00t!!! String.prototype.strip! + { + tabs[x].className = "activeLi"; + Active_Tab = tab_name; + } + else + { + tabs[x].className = ""; + } + } +} + +//These globals should not be used globally (hence the getters and setters) +var File_Search = ""; +var Method_Search = ""; +var Class_Search = ""; +function setSavedSearch(tab_name, s_val){ + switch(tab_name){ + case "methods": + Method_Search = s_val; + break; + case "files": + File_Search = s_val; + break; + case "classes": + Class_Search = s_val; + break; + } +} + +function getSavedSearch(tab_name){ + switch(tab_name){ + case "methods": + return (Method_Search); + break; + case "files": + return (File_Search); + break; + case "classes": + return (Class_Search); + break; + } +} + +//These globals handle the history stack + + +function setListScrollerContent(s){ + + $('listScroller').innerHTML = s; +} + +function setMainContent(s){ + + $('rdocContent').innerHTML = s; +} + +function setSearchFieldValue(s){ + + document.forms[0].searchText.value = s; +} + +function getSearchFieldValue(){ + + return Form.Element.getValue('searchText'); +} + +function setSearchFocus(){ + + document.forms[0].searchText.focus(); +} + +var Anchor_ID_Of_Current = null; // holds the last highlighted anchor tag in the scroll lsit +function getCurrentAnchor(){ + return(Anchor_ID_Of_Current); +} + +function setCurrentAnchor(a_id){ + Anchor_ID_Of_Current = a_id; +} + +//var Index_Of_Current = 0; //holds the last highlighted index +//function getCurrentIndex(){ +// return (Index_Of_Current); +//} + +//function setCurrentIndex(new_i){ +// Index_Of_Current = new_i; +//} + +function loadScrollerContent(url){ + + var scrollerHtml = new Ajax.Request(url, { + asynchronous: false, + method: 'get', + onComplete: function(method_data) { + setListScrollerContent(method_data.responseText); + } + }); + +} + +//called primarily from the links inside the scroller list +//loads the main page div then jumps to the anchor/element with id +function loadContent(url, anchor_id){ + + var mainHtml = new Ajax.Request(url, { + method: 'get', + onLoading: changeLoadingStatus("on"), + onSuccess: function(method_data) { + setMainContent(method_data.responseText);}, + onComplete: function(request) { + changeLoadingStatus("off"); + new jumpToAnchor(anchor_id); + } + }); +} + +//An alternative function that also will stuff the index history for methods, files, classes +function loadIndexContent(url, anchor_id, name, scope) +{ + if (From_URL_Param == true){ + var mainHtml = new Ajax.Request(url, { + method: 'get', + onLoading: changeLoadingStatus("on"), + onSuccess: function(method_data) { + setMainContent(method_data.responseText);}, + onComplete: function(request) { + changeLoadingStatus("off"); + updateBrowserBar(name, anchor_id, scope); + new jumpToAnchor(anchor_id);} + }); + From_URL_Param = false; + }else{ + updateUrlParams(anchor_id, name); + } + +} + +function updateBrowserBar(name, anchor_id, scope){ + if (getCurrentTab() == "methods"){ + $('browserBarInfo').update("class/module: " + scope + "  method: " + name + " "); + }else{ if(getCurrentTab() == "classes"){ + $('browserBarInfo').update("class/module: " + scope + "::" + name + " "); + }else{ + $('browserBarInfo').update("file: " + scope + "/" + name + " "); + } + } +} + + +// Force loads the contents of the index of the current scroller list. It does this by +// pulling the onclick method out and executing it manually. +function forceLoadOfContent(index_to_load){ + var scroller = $('listScroller'); + var a_array = scroller.getElementsByTagName('a'); + if ((index_to_load >= 0) && (index_to_load < a_array.length)){ + var load_element = a_array[index_to_load]; + var el_text = load_element.innerHTML.strip(); + setSearchFieldValue(el_text); + setSavedSearch(getCurrentTab(), el_text); + eval("new " + load_element.onclick); + } +} + +function forceLoadOfContentAnchor(anchor_id){ + + var load_element = $(anchor_id); + if (load_element != null){ + var el_text = load_element.innerHTML.strip(); + setSearchFieldValue(el_text); + scrollToAnchor(anchor_id); + setSavedSearch(getCurrentTab(), el_text); + eval("new " + load_element.onclick); + } +} + +var From_URL_Param = false; +function paramLoadOfContentAnchor(anchor_id){ + From_URL_Param = true; + forceLoadOfContentAnchor(anchor_id); +} + +//this handles the up/down keystrokes to move the selection of items in the list +function scrollListToElementOffset(anchor_id, offset){ + var scroller = $('listScroller'); + var a_array = scroller.getElementsByTagName('a'); + var current_index = findIndexOfAnchor(a_array, anchor_id); + if ((current_index >= 0) && (current_index < a_array.length)){ + scrollListToAnchor(a_array[current_index + offset].id); + setListActiveAnchor(a_array[current_index + offset].id); + } +} + +function findIndexOfAnchor(a_array, anchor_id){ + var found=false; + var counter = 0; + while(!found && counter < a_array.length){ + if (a_array[counter].id == anchor_id){ + found = true; + }else{ + counter +=1; + } + } + return(counter); +} + +function scrollToName(searcher_name){ + + var scroller = $('listScroller'); + var a_array = scroller.getElementsByTagName('a'); + + if (!searcher_name.match(new RegExp(/\s+/))){ //if searcher name is blank + + var searcher_pattern = new RegExp("^"+searcher_name, "i"); //the "i" is for case INsensitive + var found_index = -1; + + var found = false; + var x = 0; + while(!found && x < a_array.length){ + if(a_array[x].innerHTML.match(searcher_pattern)){ + found = true; + found_index = x; + } + else{ + x++; + } + } + + // // an attempt at binary searching... have not given up on this yet... + //found_index = binSearcher(searcher_pattern, a_array, 0, a_array.length); + + if ((found_index >= 0) && (found_index < a_array.length)){ + + scrollListToAnchor(a_array[found_index].id);//scroll to the item + setListActiveAnchor(a_array[found_index].id);//highlight the item + } + }else{ //since searcher name is blank + //scrollListToIndex(a_array, 0);//scroll to the item + //setListActiveItem(a_array, 0);//highlight the item + } +} + +function scrollToAnchor(anchor_id){ + var scroller = $('listScroller'); + if ($(anchor_id) != null){ + scrollListToAnchor(anchor_id); + setListActiveAnchor(anchor_id); + } +} + +function getY(element){ + + var y = 0; + for( var e = element; e; e = e.offsetParent)//iterate the offset Parents + { + y += e.offsetTop; //add up the offsetTop values + } + //for( e = element.parentNode; e && e != document.body; e = e.parentNode) + // if (e.scrollTop) y -= e.scrollTop; //subtract scrollbar values + return y; +} + +//function setListActiveItem(item_array, active_index){ +// +// item_array[getCurrentIndex()].className = ""; +// setCurrentIndex(active_index); +// item_array[getCurrentIndex()].className = "activeA"; //setting the active class name +//} + +function setListActiveAnchor(active_anchor){ + if ((getCurrentAnchor() != null) && ($(getCurrentAnchor()) != null)){ + $(getCurrentAnchor()).className = ""; + } + setCurrentAnchor(active_anchor); + $(getCurrentAnchor()).className = "activeA"; + +} + +//handles the scrolling of the list and setting of the current index +//function scrollListToIndex(a_array, scroll_index){ +// if (scroll_index > 0){ +// var scroller = $('listScroller'); +// scroller.scrollTop = getY(a_array[scroll_index]) - 120; //the -120 is what keeps it from going to the top... +// } +//} + +function scrollListToAnchor(scroll2_anchor){ + var scroller = $('listScroller'); + scroller.scrollTop = getY($(scroll2_anchor)) - 120; +} + +function jumpToAnchor(anchor_id){ + + var contentScroller = $('rdocContent'); + var a_div = $(anchor_id); + contentScroller.scrollTop = getY(a_div) - 80; //80 is the offset to adjust scroll point + var a_title = $(anchor_id + "_title"); + a_title.style.backgroundColor = "#222"; + a_title.style.color = "#FFF"; + a_title.style.padding = "3px"; + // a_title.style.borderBottom = "2px solid #ccc"; + + //other attempts + //a_div.className = "activeMethod"; //setting the active class name + //a_div.style.backgroundColor = "#ffc"; + //var titles = a_div.getElementsByClassName("title"); + //titles[0].className = "activeTitle"; + +} + +function jumpToTop(){ + $('rdocContent').scrollTop = 0; +} + +function changeLoadingStatus(status){ + if (status == "on"){ + $('loadingStatus').show(); + } + else{ + $('loadingStatus').hide(); + } +} + +//************* Misc functions (mostly from the old rdocs) *********************** +//snagged code from the old templating system +function toggleSource( id ){ + + var elem + var link + + if( document.getElementById ) + { + elem = document.getElementById( id ) + link = document.getElementById( "l_" + id ) + } + else if ( document.all ) + { + elem = eval( "document.all." + id ) + link = eval( "document.all.l_" + id ) + } + else + return false; + + if( elem.style.display == "block" ) + { + elem.style.display = "none" + link.innerHTML = "show source" + } + else + { + elem.style.display = "block" + link.innerHTML = "hide source" + } +} + +function openCode( url ){ + window.open( url, "SOURCE_CODE", "width=400,height=400,scrollbars=yes" ) +} + +//this function handles the ajax calling and afterits loaded the jumping to the anchor... +function jsHref(url){ + //alert(url); + var mainHtml = new Ajax.Request(url, { + method: 'get', + onSuccess: function(method_data) { + setMainContent(method_data.responseText);} + }); +} + +//function comparePatterns(string, regexp){ +// var direction = 0; +// +// +// return (direction) +//} + +////returns the index of the element +//function binSearcher(regexp_pattern, list, start_index, stop_index){ +// //divide the list in half +// var split_point = 0; +// split_point = parseInt((stop_index - start_index)/2); +// direction = comparePatterns(list[split_point].innerHTML, regexp_pattern); +// if(direction < 0) +// return (binSearcher(regexp_pattern, list, start_index, split_point)); +// else +// if(direction > 0) +// return (binSearcher(regexp_pattern, list, split_point, stop_index)); +// else +// return(split_point); +// +//} + + + diff --git a/doc/rdoc/generators/template/merb/index.html.erb b/doc/rdoc/generators/template/merb/index.html.erb new file mode 100644 index 0000000..5c8e798 --- /dev/null +++ b/doc/rdoc/generators/template/merb/index.html.erb @@ -0,0 +1,37 @@ + + + + Documentation + + + + + + + + +

+ + +
+ + diff --git a/doc/rdoc/generators/template/merb/merb.css b/doc/rdoc/generators/template/merb/merb.css new file mode 100644 index 0000000..e4f5531 --- /dev/null +++ b/doc/rdoc/generators/template/merb/merb.css @@ -0,0 +1,252 @@ +html, body, div, span, applet, object, iframe,h1, h2, h3, h4, h5, h6, p, blockquote, pre,a, abbr, acronym, address, big, cite, code,del, dfn, em, font, img, ins, kbd, q, s, samp,small, strike, strong, sub, sup, tt, var,dl, dt, dd, ol, ul, li,fieldset, form, label, legend,table, caption, tbody, tfoot, thead, tr, th, td { + margin: 0; + padding: 0; + border: 0; + font-weight: inherit; + font-style: inherit; + font-size: 100%; + font-family: inherit; + vertical-align: baseline; } + +/* GENERAL RULES */ + +body { + background: #000 url(../img/body.gif) repeat-x bottom center; + color: #000; + font: normal 12px "Lucida Grande", "Arial", sans-serif; + line-height: 1; +} +ul {list-style-type: none;} +#content_full ul.revisions{list-style-type: disc;} +#content_full ul.revisions li{margin-left: 15px;padding: 3px 0;} +li a {display: block;} +#content_full ul.revisions li a{display: inline;} +strong {font-weight: bold;} +table {border-collapse: separate;border-spacing: 0; } +caption, th, td {text-align: left;font-weight: normal; } +.invisible {display: none;} +.full_width {width:100%;} + +/* LAYOUT */ + +.wrap_to_center, #foot { + margin: 0 auto; + display: block; + width: 800px; +} + +#content {width: 100%;} + +#content_top { + background: #fff url(../img/content_top.gif) no-repeat top center; + float:left; + margin:25px 0px; + width:100%; +} +#content_bottom { + background: url(../img/content_bottom.gif) no-repeat bottom center; + width:100%; + float:left; +} +#content_main { + float:left; + margin: 10px 20px 20px 20px; + width:506px; +} +#content p { + line-height:17px; +} +#content_full {margin: 10px 20px 20px 20px;} + +/* HEADER & NAVIGATION */ + +#header { + background: #1db900 url(../img/header_waves.gif) repeat-x top center; + height:74px; + width: 100%; +} +#waves { + background: url(../img/header_waves.gif)no-repeat top left; + height:74px; + width:980px; +} +#header img {margin-top:8px; float:left;} +#header a {color:#fff; text-decoration:none;} +#header a:hover {color:#000;} +ul#nav {float:right;display:block;width:43.3em;margin-top:25px;} +ul#nav li {display:block;float:left;} +ul#nav li a {display:block;float:left;margin:0px 5px;padding:6px 9px 31px 9px;} +ul#nav li a:hover {background:url(../img/header_hover.gif) repeat-x bottom center;} +ul#nav li a#active {background:url(../img/header_arrow.gif)no-repeat bottom center;} +ul#nav li.last a {margin-right:0;} + +/* TEXT FORMATTING */ + +h1 { + border-bottom:2px solid #ccc; + color:#000; + font:bold 28px "Arial" sans-serif; + letter-spacing:1px; + margin:20px 0px; + text-align:left; + width:100%; +} +h1.home { + border:0; + color:#fff; + font-size:36px; + margin:20px 0px; + text-align:center; +} +h2 { + color:#7aad00; + font:bold 22px "Lucida Grande" sans-serif; + margin:10px 0px; +} +h3 { + font:bold 16px "Lucida Grande"; + margin:10px 0px; +} +#content a {color:#d7ff00;} +#content a:hover {background:#d7ff00;color:#000;} +#content_main ul {margin:10px 0px;} +#content_main ul li { + background: url(../img/li.gif) no-repeat left center; + padding: 4px 4px 4px 16px; + font-weight:bold; +} +p {margin-bottom:12px;} +#content_main a,#content_full a {color:#11b716;font-weight:bold;} +#content_main a:hover,#content_full a:hover {background:#22d716;} +pre { + background:#222; + color:#fff; + font:12px "Courier" serif; + line-height:18px; + padding: 12px; + margin-bottom: 10px; +} +code { + font:bold 12px "Courier" serif; +} +pre code {font-weight:normal;} + +/* SIDEBAR FOR CONTENT */ + +#content_sidebar { + float: left; + margin: 20px 20px 15px 10px; + width: 224px; +} +.sidebar_top { + background:#868686 url(../img/sidebar_top.gif) no-repeat top center; + margin-bottom:12px; + width:224px; +} +dl.sidebar_bottom { + background: url(../img/sidebar_bottom.gif) no-repeat bottom center; + padding:12px; +} +dl.sidebar_bottom dt { + color:#fff; + font:bold 14px "Lucida Grande" sans-serif; + margin-bottom:6px; +} +dl.sidebar_bottom dd {padding:3px 0px;} +#content_sidebar p {padding:10px 0px;} +p#rss a { + background: url(../img/rss.gif) no-repeat left center; + color:#000; + font:bold 14px "Lucida Grande"; + padding: 8px 6px 8px 34px; + text-decoration:none; +} +p#rss a:hover { + background: url(../img/rss.gif) no-repeat left center; + background-color:#fff; + text-decoration:underline; +} + +/* FOOTER */ + +#footer {background:#444; clear:both;} +#footer p {padding:12px; color:#999; margin:0; text-align:center;} + +/* FEATURES PAGE */ +.feature { + background-repeat:no-repeat; + background-position:top left; + border-bottom:2px solid #ccc; + padding-left:150px; +} +div#speed {background-image: url(../img/feature_speed.gif);} +div#light {background-image: url(../img/feature_light.gif);} +div#power {background-image: url(../img/feature_power.gif);} + +.quicklinks_top { + background:#868686 url(../img/quicklinks_top.gif) no-repeat top center; + float:right; + margin-bottom:12px; + width:169px; +} +ul.quicklinks_bottom { + background: url(../img/quicklinks_bottom.gif) no-repeat bottom center; + padding:12px; +} +ul.quicklinks_bottom li { + display:block; + padding:3px 0px; +} +#content_full ul.quicklinks_bottom li a{ + color:#d7ff00; + display:inline; +} +#content_full ul.quicklinks_bottom li a:hover { + background:#d7ff00; + color:#000; +} + +/* DOCUMENTATION PAGE */ +.sub-framework { + border-bottom:2px solid #ccc; + margin-bottom: 20px; + padding-bottom: 10px; +} + + +/* ICONS FOR HOMEPAGE */ + +#icons_top { + background: url(../img/icons_top.gif) no-repeat top center; + float:left; + width:800px; +} +#icons_bottom { + background: url(../img/icons_bottom.gif) no-repeat bottom center; + float:left; + width:800px; +} +#icons_top dl { + color:#fff; + float:left; + width: 224px; + padding: 15px 20px; +} +#icons_top dt { + background-repeat:no-repeat; + background-position:center 2.5em; + color:#35d726; + font:bold 18px 'Lucida Grande' sans-serif; + padding: 6px 6px 150px 6px; + text-align:center; +} +#icons_top dd { + font: 11px "Lucida Grande"; + line-height:18px; + text-align:center; +} +dl#speed, dl#light {border-right:1px solid #444;} +dl#light, dl#power {border-left:1px solid #000;} +dl#speed dt {background-image: url(../img/icon_speed.gif);} +dl#light dt {background-image: url(../img/icon_light.gif);} +dl#power dt {background-image: url(../img/icon_power.gif);} \ No newline at end of file diff --git a/doc/rdoc/generators/template/merb/merb.rb b/doc/rdoc/generators/template/merb/merb.rb new file mode 100644 index 0000000..36a77ed --- /dev/null +++ b/doc/rdoc/generators/template/merb/merb.rb @@ -0,0 +1,351 @@ +module RDoc +module Page + +STYLE = File.read(File.join(File.dirname(__FILE__), 'merb_doc_styles.css')) +FONTS = "" + +################################################################### + +CLASS_PAGE = < + +HTML + +################################################################### + +METHOD_LIST = < +IF:diagram +
+ %diagram% +
+ENDIF:diagram + +IF:description +
%description%
+ENDIF:description + +IF:requires +
Required Files
+
    +START:requires +
  • %name%
  • +END:requires +
+ENDIF:requires + +IF:toc +
Contents
+ +ENDIF:toc + +IF:methods +
Methods
+
    +START:methods +
  • %name%
  • +END:methods +
+ENDIF:methods + +IF:includes +
Included Modules
+
    +START:includes +
  • %name%
  • +END:includes +
+ENDIF:includes + +START:sections +IF:sectitle + +IF:seccomment +
+%seccomment% +
+ENDIF:seccomment +ENDIF:sectitle + +IF:classlist +
Classes and Modules
+ %classlist% +ENDIF:classlist + +IF:constants +
Constants
+ +START:constants + + + + + +IF:desc + + + + +ENDIF:desc +END:constants +
%name%=%value%
 %desc%
+ENDIF:constants + +IF:attributes +
Attributes
+ +START:attributes + + + + + +END:attributes +
+IF:rw +[%rw%] +ENDIF:rw + %name%%a_desc%
+ENDIF:attributes + +IF:method_list +START:method_list +IF:methods +
%type% %category% methods
+START:methods +
+
+IF:callseq + %callseq% +ENDIF:callseq +IFNOT:callseq + %name%%params% +ENDIF:callseq +IF:codeurl +[ source ] +ENDIF:codeurl +
+IF:m_desc +
+ %m_desc% +
+ENDIF:m_desc +IF:aka +
+ This method is also aliased as +START:aka + %name% +END:aka +
+ENDIF:aka +IF:sourcecode +
+ +
+
+%sourcecode%
+
+
+
+ENDIF:sourcecode +
+END:methods +ENDIF:methods +END:method_list +ENDIF:method_list +END:sections + +HTML + + + + +BODY = < + +
+ #{METHOD_LIST} +
+ +ENDBODY + + + +SRC_BODY = < + +
+

Source Code

+
%file_source_code%
+
+ENDSRCBODY + + +###################### File Page ########################## +FILE_PAGE = < +

%short_name%

+ + + + + + + + + +
Path:%full_path% +IF:cvsurl +  (CVS) +ENDIF:cvsurl +
Last Update:%dtm_modified%
+ +HTML + + +#### This is not used but kept for historical purposes +########################## Source code ########################## +# Separate page onlye + +SRC_PAGE = < +%title% + + + + +
%code%
+ + +HTML + +########################### source page body ################### + +SCR_CODE_BODY = < + %source_code% + + +HTML + +########################## Index ################################ + +FR_INDEX_BODY = < +START:entries +
  • %name%%scope%
  • +END:entries + +HTML + +CLASS_INDEX = FILE_INDEX +METHOD_INDEX = FILE_INDEX + +INDEX = < + + + + + + + + Merb | %title% API Documentation + + + + + +
      +
    • methods
    • +
    • classes
    • +
    • files
    • + +
    +
    +
    +
    + +
    +
    +
    + Loading via ajax... this could take a sec. +
    +
    +
    +    %title% README +
    +
    + %content% +
    +
    +Documentation for %title% usage tips + + + + + + +HTML + +API_GREASE_JS = File.read(File.join(File.dirname(__FILE__), 'api_grease.js')) + +PROTOTYPE_JS = File.read(File.join(File.dirname(__FILE__), 'prototype.js')) +end +end + diff --git a/doc/rdoc/generators/template/merb/merb_doc_styles.css b/doc/rdoc/generators/template/merb/merb_doc_styles.css new file mode 100644 index 0000000..cb01bb7 --- /dev/null +++ b/doc/rdoc/generators/template/merb/merb_doc_styles.css @@ -0,0 +1,492 @@ +html, body { + padding:10px 0px 0px 5px; + margin: 0px; + font-family: "Lucida Grande", "Lucida Sans Unicode", sans-serif; + font-size: 14px; +} + +body { + background: #000000 url(http://merbivore.com/img/header_waves.gif) repeat-x scroll center top; +} + +td, p { + background: #FFF; + color: #000; + margin: 0px; + font-size: small; + line-height: 17px; + margin-bottom 12px; +} + +#floater { + position: absolute; + top: 5px; + right: 5px; +} + +#floater strong { + color: white; +} + +#floater a { + color: black; +} + +#floater a:hover { + background-color: transparent; +} + + +/*holds the whole searching/drill down stuff */ +#listFrame{ + float:left; + padding: 2px; + width: 350px; + background-color: #868686; + border: 1px solid #999; + border-right: none; +} + +#browserBar{ + height: 25px; + padding:11px 0px 0px 0px; + margin:0px; + background-color: #868686; + border-top: 1px solid #999; + color: white; +} + +#browserBar a{ + text-decoration: none; +} + +.button{ + text-decoration: none; + padding:3px 8px 3px 8px; + border: 1px solid #66a; + background-color: #ccf; + color: #66a; +} + +.buttonInactive{ + text-decoration: none; + padding:3px 8px 3px 8px; + border: 1px solid #999; + background-color: #ccc; + color: #999; +} + +.miniButton{ + text-decoration: none; + padding:3px 2px 3px 2px; + border: 1px solid #66a; + background-color: #ccf; + color: #66a; +} + +.miniButtonInactive{ + text-decoration: none; + padding:3px 2px 3px 2px; + border: 1px solid #999; + background-color: #ccc; + color: #999; +} + +#blowOutListBox{ + position: absolute; + top: 63px; + left: 399px; + border: 1px solid #999; + padding: 0px; + margin: 0px; + z-index: 1000; + background-color: #ccf; + color: #66a; +} + +#blowOutListBox ul{ + list-style-type:none; + padding: 0px; + margin: 0px; +} + +#blowOutListBox ul li{ + padding: 3px; + margin: 0px; + line-height: 1.1em; + +} + +#blowOutListBox ul li a{ + text-decoration: none; + padding: 3px; +} +#blowOutListBox ul li a:hover{ + background-color: #ddf; +} + +/*holds the content for browsing etc... also is the target of method/class/file name clicks */ +#rdocContent{ + height: 600px; + background-color: #fff; + border: 1px solid #999; + border-left: 0px; + padding:5px; + overflow: auto; +} + +/*the grouping for methods,files,class,all... i.e. the tabs */ +ul#groupType{ + list-style-type: none; + padding: 0px; + padding-left: 5px; + margin: 0px; +} + +ul#groupType li{ + color: white; + display:inline; + padding: 5px 5px 0px 5px; + cursor: pointer; +} + +ul#groupType li#loadingStatus{ + margin: 3px; + border: 0px; + padding: 3px 3px 6px 3px; + color: #666; +} + +ul#groupType li.activeLi{ + border: 1px solid #999; + border-bottom: 0px; + background-color: #868686; + font-weight: bold; + padding-bottom: 1px; +} + +#listSearch{ + height: 25px; + padding: 3px; +} + +#listSearch input[type=text]{ + width: 340px; + font-size: 1.2em; +} + +#listScroller{ + width: 342px; + height: 700px; + margin: 3px; + background-color: #fcfcfc; + border: 1px solid #999; + overflow: auto; +} + +#listScroller ul{ + width: 500px; + padding:0px; + margin:0px; + list-style: none; +} + +#listScroller li{ + padding: 0px; + margin: 0px; + display: block; + line-height: 1.1em; +} + +a, h1 a, h2 a, .sectiontitle a, #listScroller a{ + color: #11B716; + font-weight: bold; + text-decoration: none; + padding: 0px 1px 1px 1px; + margin: 3px; + font-weight: bold; +} + +a:hover, h1 a:hover, h2 a:hover, .sectiontitle a:hover, #listScroller a:hover{ + background-color: #22D716; + color: black; +} + +#browserBar a, .banner a { + color: #D7FF00; +} + +#browserBar a:hover, .banner a:hover { + background-color: #D7FF00; + color: #000; +} + +#listScroller a.activeA { + background-color: #22D716; + color: black ; + border: 1px solid #ccc; + padding: 0px 1px 1px 1px; +} + +#listScroller small{ + color: #999; +} + +.activeTitle{ + font-family: monospace; + font-size: large; + border-bottom: 1px dashed black; + margin-bottom: 0.3em; + padding-bottom: 0.1em; + background-color: #ffc; +} + +.activeMethod{ + margin-left: 1em; + margin-right: 1em; + margin-bottom: 1em; +} + + +.activeMethod .title { + font-family: monospace; + font-size: large; + border-bottom: 1px dashed black; + margin-bottom: 0.3em; + padding-bottom: 0.1em; + background-color: #ffa; +} + +.activeMethod .description, .activeMethod .sourcecode { + margin-left: 1em; +} + +.activeMethod .sourcecode p.source-link { + text-indent: 0em; + margin-top: 0.5em; +} + +.activeMethod .aka { + margin-top: 0.3em; + margin-left: 1em; + font-style: italic; + text-indent: 2em; +} + +#content { + margin: 0.5em; +} + +#description p { + margin-bottom: 0.5em; +} + +.sectiontitle { + color: black; + font-size: 28px; + margin: 20px 0px; + border-bottom: 2px solid #CCCCCC; + +/* margin-top: 1em; + margin-bottom: 1em; + padding: 0.5em; + padding-left: 2em; + background: #005; + color: #FFF; + font-weight: bold; + border: 1px dotted black;*/ +} + +.attr-rw { + padding-left: 1em; + padding-right: 1em; + text-align: center; + color: #7AAD00; +} + +.attr-name { + font-weight: bold; +} + +.attr-desc { +} + +.attr-value { + font-family: monospace; +} + +.file-title-prefix { + font-size: large; +} + +.file-title { + font-size: large; + font-weight: bold; + background: #005; + color: #FFF; +} + +.banner { + background: #888; + color: #FFF; +/* border: 1px solid black;*/ + padding: 1em; +} + +.banner td { + background: transparent; + color: #FFF; +} + +.dyn-source { + display: none; + color: #000; + border: 0px; + border-left: 1px dotted #CCC; + border-top: 1px dotted #CCC; + margin: 0em; + padding: 0em; +} + +.dyn-source .cmt { + color: #7AAD00; + font-style: italic; +} + +.dyn-source .kw { + color: #11B716; + font-weight: bold; +} + +.method { + margin-left: 1em; + margin-right: 1em; + margin-bottom: 2em; +} + +.description pre, .description td { + font-family:"Courier",serif; +} +pre, .description pre { + font-size: 12px; + line-height: 18px; + color: white; + padding: 12px; + background: #222; + overflow: auto; +} + +h2.title, .method .title { + color: #7AAD00; + font-size: 22px; + margin: 10px 0px; + +/* font-size: large; + border-bottom: 1px dashed black; + margin: 0.3em; + padding: 0.2em; +*/} + +.method .description, .method .sourcecode { + margin-left: 1em; +} + +.description p, .sourcecode p { + margin-bottom: 0.5em; +} + +.method .sourcecode p.source-link { + text-indent: 0em; + margin-top: 0.5em; +} + +.method .aka { + margin-top: 0.3em; + margin-left: 1em; + font-style: italic; + text-indent: 2em; +} + +h1 { + padding: 1em; + font-size: x-large; +} + +h2 { + padding: 0.5em 1em 0.5em 1em; + font-size: large; +} + + +h1, h2, h3, h4, h5, h6 { + color: white; + background-color: #868686; +} + +h3, h4, h5, h6 { + padding: 0.2em 1em 0.2em 1em; + font-weight: bold; +} + +h4 { + margin-bottom: 2px; +} + +.sourcecode > pre { + padding: 0px; + margin: 0px; + border: 1px dotted black; + background: #FFE; +} + +/* ============= */ +/* = home page = */ +/* ============= */ + +body#home { + margin: 0; + padding: 0; +} + +#content { + margin: 0 auto; + width: 800px; +} + +#content h1.home { + background-color: transparent; + border:0pt none; + color:#FFFFFF; + font-size:36px; + margin:20px 0px; + padding: 0; + text-align:center; +} + +#content #documentation-links h2.title { + background-color: transparent; +} + +#documentation-links { + background-color : white; + margin-bottom: 20px; + padding-bottom: 10px; +} + +#documentation-links p { + margin: 22px; +} + +body#home #footer { + background:#444444 none repeat scroll 0%; + clear:both; +} + +#footer p { + background-color: transparent; + color:#999999; + margin:0 auto; + padding:12px; + text-align:center; + width: 800px; +} \ No newline at end of file diff --git a/doc/rdoc/generators/template/merb/prototype.js b/doc/rdoc/generators/template/merb/prototype.js new file mode 100644 index 0000000..5058221 --- /dev/null +++ b/doc/rdoc/generators/template/merb/prototype.js @@ -0,0 +1,2515 @@ +/* Prototype JavaScript framework, version 1.5.0 + * (c) 2005-2007 Sam Stephenson + * + * Prototype is freely distributable under the terms of an MIT-style license. + * For details, see the Prototype web site: http://prototype.conio.net/ + * +/*--------------------------------------------------------------------------*/ + +var Prototype = { + Version: '1.5.0', + BrowserFeatures: { + XPath: !!document.evaluate + }, + + ScriptFragment: '(?:)((\n|\r|.)*?)(?:<\/script>)', + emptyFunction: function() {}, + K: function(x) { return x } +} + +var Class = { + create: function() { + return function() { + this.initialize.apply(this, arguments); + } + } +} + +var Abstract = new Object(); + +Object.extend = function(destination, source) { + for (var property in source) { + destination[property] = source[property]; + } + return destination; +} + +Object.extend(Object, { + inspect: function(object) { + try { + if (object === undefined) return 'undefined'; + if (object === null) return 'null'; + return object.inspect ? object.inspect() : object.toString(); + } catch (e) { + if (e instanceof RangeError) return '...'; + throw e; + } + }, + + keys: function(object) { + var keys = []; + for (var property in object) + keys.push(property); + return keys; + }, + + values: function(object) { + var values = []; + for (var property in object) + values.push(object[property]); + return values; + }, + + clone: function(object) { + return Object.extend({}, object); + } +}); + +Function.prototype.bind = function() { + var __method = this, args = $A(arguments), object = args.shift(); + return function() { + return __method.apply(object, args.concat($A(arguments))); + } +} + +Function.prototype.bindAsEventListener = function(object) { + var __method = this, args = $A(arguments), object = args.shift(); + return function(event) { + return __method.apply(object, [( event || window.event)].concat(args).concat($A(arguments))); + } +} + +Object.extend(Number.prototype, { + toColorPart: function() { + var digits = this.toString(16); + if (this < 16) return '0' + digits; + return digits; + }, + + succ: function() { + return this + 1; + }, + + times: function(iterator) { + $R(0, this, true).each(iterator); + return this; + } +}); + +var Try = { + these: function() { + var returnValue; + + for (var i = 0, length = arguments.length; i < length; i++) { + var lambda = arguments[i]; + try { + returnValue = lambda(); + break; + } catch (e) {} + } + + return returnValue; + } +} + +/*--------------------------------------------------------------------------*/ + +var PeriodicalExecuter = Class.create(); +PeriodicalExecuter.prototype = { + initialize: function(callback, frequency) { + this.callback = callback; + this.frequency = frequency; + this.currentlyExecuting = false; + + this.registerCallback(); + }, + + registerCallback: function() { + this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + stop: function() { + if (!this.timer) return; + clearInterval(this.timer); + this.timer = null; + }, + + onTimerEvent: function() { + if (!this.currentlyExecuting) { + try { + this.currentlyExecuting = true; + this.callback(this); + } finally { + this.currentlyExecuting = false; + } + } + } +} +String.interpret = function(value){ + return value == null ? '' : String(value); +} + +Object.extend(String.prototype, { + gsub: function(pattern, replacement) { + var result = '', source = this, match; + replacement = arguments.callee.prepareReplacement(replacement); + + while (source.length > 0) { + if (match = source.match(pattern)) { + result += source.slice(0, match.index); + result += String.interpret(replacement(match)); + source = source.slice(match.index + match[0].length); + } else { + result += source, source = ''; + } + } + return result; + }, + + sub: function(pattern, replacement, count) { + replacement = this.gsub.prepareReplacement(replacement); + count = count === undefined ? 1 : count; + + return this.gsub(pattern, function(match) { + if (--count < 0) return match[0]; + return replacement(match); + }); + }, + + scan: function(pattern, iterator) { + this.gsub(pattern, iterator); + return this; + }, + + truncate: function(length, truncation) { + length = length || 30; + truncation = truncation === undefined ? '...' : truncation; + return this.length > length ? + this.slice(0, length - truncation.length) + truncation : this; + }, + + strip: function() { + return this.replace(/^\s+/, '').replace(/\s+$/, ''); + }, + + stripTags: function() { + return this.replace(/<\/?[^>]+>/gi, ''); + }, + + stripScripts: function() { + return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); + }, + + extractScripts: function() { + var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); + var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); + return (this.match(matchAll) || []).map(function(scriptTag) { + return (scriptTag.match(matchOne) || ['', ''])[1]; + }); + }, + + evalScripts: function() { + return this.extractScripts().map(function(script) { return eval(script) }); + }, + + escapeHTML: function() { + var div = document.createElement('div'); + var text = document.createTextNode(this); + div.appendChild(text); + return div.innerHTML; + }, + + unescapeHTML: function() { + var div = document.createElement('div'); + div.innerHTML = this.stripTags(); + return div.childNodes[0] ? (div.childNodes.length > 1 ? + $A(div.childNodes).inject('',function(memo,node){ return memo+node.nodeValue }) : + div.childNodes[0].nodeValue) : ''; + }, + + toQueryParams: function(separator) { + var match = this.strip().match(/([^?#]*)(#.*)?$/); + if (!match) return {}; + + return match[1].split(separator || '&').inject({}, function(hash, pair) { + if ((pair = pair.split('='))[0]) { + var name = decodeURIComponent(pair[0]); + var value = pair[1] ? decodeURIComponent(pair[1]) : undefined; + + if (hash[name] !== undefined) { + if (hash[name].constructor != Array) + hash[name] = [hash[name]]; + if (value) hash[name].push(value); + } + else hash[name] = value; + } + return hash; + }); + }, + + toArray: function() { + return this.split(''); + }, + + succ: function() { + return this.slice(0, this.length - 1) + + String.fromCharCode(this.charCodeAt(this.length - 1) + 1); + }, + + camelize: function() { + var parts = this.split('-'), len = parts.length; + if (len == 1) return parts[0]; + + var camelized = this.charAt(0) == '-' + ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1) + : parts[0]; + + for (var i = 1; i < len; i++) + camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1); + + return camelized; + }, + + capitalize: function(){ + return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); + }, + + underscore: function() { + return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase(); + }, + + dasherize: function() { + return this.gsub(/_/,'-'); + }, + + inspect: function(useDoubleQuotes) { + var escapedString = this.replace(/\\/g, '\\\\'); + if (useDoubleQuotes) + return '"' + escapedString.replace(/"/g, '\\"') + '"'; + else + return "'" + escapedString.replace(/'/g, '\\\'') + "'"; + } +}); + +String.prototype.gsub.prepareReplacement = function(replacement) { + if (typeof replacement == 'function') return replacement; + var template = new Template(replacement); + return function(match) { return template.evaluate(match) }; +} + +String.prototype.parseQuery = String.prototype.toQueryParams; + +var Template = Class.create(); +Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; +Template.prototype = { + initialize: function(template, pattern) { + this.template = template.toString(); + this.pattern = pattern || Template.Pattern; + }, + + evaluate: function(object) { + return this.template.gsub(this.pattern, function(match) { + var before = match[1]; + if (before == '\\') return match[2]; + return before + String.interpret(object[match[3]]); + }); + } +} + +var $break = new Object(); +var $continue = new Object(); + +var Enumerable = { + each: function(iterator) { + var index = 0; + try { + this._each(function(value) { + try { + iterator(value, index++); + } catch (e) { + if (e != $continue) throw e; + } + }); + } catch (e) { + if (e != $break) throw e; + } + return this; + }, + + eachSlice: function(number, iterator) { + var index = -number, slices = [], array = this.toArray(); + while ((index += number) < array.length) + slices.push(array.slice(index, index+number)); + return slices.map(iterator); + }, + + all: function(iterator) { + var result = true; + this.each(function(value, index) { + result = result && !!(iterator || Prototype.K)(value, index); + if (!result) throw $break; + }); + return result; + }, + + any: function(iterator) { + var result = false; + this.each(function(value, index) { + if (result = !!(iterator || Prototype.K)(value, index)) + throw $break; + }); + return result; + }, + + collect: function(iterator) { + var results = []; + this.each(function(value, index) { + results.push((iterator || Prototype.K)(value, index)); + }); + return results; + }, + + detect: function(iterator) { + var result; + this.each(function(value, index) { + if (iterator(value, index)) { + result = value; + throw $break; + } + }); + return result; + }, + + findAll: function(iterator) { + var results = []; + this.each(function(value, index) { + if (iterator(value, index)) + results.push(value); + }); + return results; + }, + + grep: function(pattern, iterator) { + var results = []; + this.each(function(value, index) { + var stringValue = value.toString(); + if (stringValue.match(pattern)) + results.push((iterator || Prototype.K)(value, index)); + }) + return results; + }, + + include: function(object) { + var found = false; + this.each(function(value) { + if (value == object) { + found = true; + throw $break; + } + }); + return found; + }, + + inGroupsOf: function(number, fillWith) { + fillWith = fillWith === undefined ? null : fillWith; + return this.eachSlice(number, function(slice) { + while(slice.length < number) slice.push(fillWith); + return slice; + }); + }, + + inject: function(memo, iterator) { + this.each(function(value, index) { + memo = iterator(memo, value, index); + }); + return memo; + }, + + invoke: function(method) { + var args = $A(arguments).slice(1); + return this.map(function(value) { + return value[method].apply(value, args); + }); + }, + + max: function(iterator) { + var result; + this.each(function(value, index) { + value = (iterator || Prototype.K)(value, index); + if (result == undefined || value >= result) + result = value; + }); + return result; + }, + + min: function(iterator) { + var result; + this.each(function(value, index) { + value = (iterator || Prototype.K)(value, index); + if (result == undefined || value < result) + result = value; + }); + return result; + }, + + partition: function(iterator) { + var trues = [], falses = []; + this.each(function(value, index) { + ((iterator || Prototype.K)(value, index) ? + trues : falses).push(value); + }); + return [trues, falses]; + }, + + pluck: function(property) { + var results = []; + this.each(function(value, index) { + results.push(value[property]); + }); + return results; + }, + + reject: function(iterator) { + var results = []; + this.each(function(value, index) { + if (!iterator(value, index)) + results.push(value); + }); + return results; + }, + + sortBy: function(iterator) { + return this.map(function(value, index) { + return {value: value, criteria: iterator(value, index)}; + }).sort(function(left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }).pluck('value'); + }, + + toArray: function() { + return this.map(); + }, + + zip: function() { + var iterator = Prototype.K, args = $A(arguments); + if (typeof args.last() == 'function') + iterator = args.pop(); + + var collections = [this].concat(args).map($A); + return this.map(function(value, index) { + return iterator(collections.pluck(index)); + }); + }, + + size: function() { + return this.toArray().length; + }, + + inspect: function() { + return '#'; + } +} + +Object.extend(Enumerable, { + map: Enumerable.collect, + find: Enumerable.detect, + select: Enumerable.findAll, + member: Enumerable.include, + entries: Enumerable.toArray +}); +var $A = Array.from = function(iterable) { + if (!iterable) return []; + if (iterable.toArray) { + return iterable.toArray(); + } else { + var results = []; + for (var i = 0, length = iterable.length; i < length; i++) + results.push(iterable[i]); + return results; + } +} + +Object.extend(Array.prototype, Enumerable); + +if (!Array.prototype._reverse) + Array.prototype._reverse = Array.prototype.reverse; + +Object.extend(Array.prototype, { + _each: function(iterator) { + for (var i = 0, length = this.length; i < length; i++) + iterator(this[i]); + }, + + clear: function() { + this.length = 0; + return this; + }, + + first: function() { + return this[0]; + }, + + last: function() { + return this[this.length - 1]; + }, + + compact: function() { + return this.select(function(value) { + return value != null; + }); + }, + + flatten: function() { + return this.inject([], function(array, value) { + return array.concat(value && value.constructor == Array ? + value.flatten() : [value]); + }); + }, + + without: function() { + var values = $A(arguments); + return this.select(function(value) { + return !values.include(value); + }); + }, + + indexOf: function(object) { + for (var i = 0, length = this.length; i < length; i++) + if (this[i] == object) return i; + return -1; + }, + + reverse: function(inline) { + return (inline !== false ? this : this.toArray())._reverse(); + }, + + reduce: function() { + return this.length > 1 ? this : this[0]; + }, + + uniq: function() { + return this.inject([], function(array, value) { + return array.include(value) ? array : array.concat([value]); + }); + }, + + clone: function() { + return [].concat(this); + }, + + size: function() { + return this.length; + }, + + inspect: function() { + return '[' + this.map(Object.inspect).join(', ') + ']'; + } +}); + +Array.prototype.toArray = Array.prototype.clone; + +function $w(string){ + string = string.strip(); + return string ? string.split(/\s+/) : []; +} + +if(window.opera){ + Array.prototype.concat = function(){ + var array = []; + for(var i = 0, length = this.length; i < length; i++) array.push(this[i]); + for(var i = 0, length = arguments.length; i < length; i++) { + if(arguments[i].constructor == Array) { + for(var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++) + array.push(arguments[i][j]); + } else { + array.push(arguments[i]); + } + } + return array; + } +} +var Hash = function(obj) { + Object.extend(this, obj || {}); +}; + +Object.extend(Hash, { + toQueryString: function(obj) { + var parts = []; + + this.prototype._each.call(obj, function(pair) { + if (!pair.key) return; + + if (pair.value && pair.value.constructor == Array) { + var values = pair.value.compact(); + if (values.length < 2) pair.value = values.reduce(); + else { + key = encodeURIComponent(pair.key); + values.each(function(value) { + value = value != undefined ? encodeURIComponent(value) : ''; + parts.push(key + '=' + encodeURIComponent(value)); + }); + return; + } + } + if (pair.value == undefined) pair[1] = ''; + parts.push(pair.map(encodeURIComponent).join('=')); + }); + + return parts.join('&'); + } +}); + +Object.extend(Hash.prototype, Enumerable); +Object.extend(Hash.prototype, { + _each: function(iterator) { + for (var key in this) { + var value = this[key]; + if (value && value == Hash.prototype[key]) continue; + + var pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } + }, + + keys: function() { + return this.pluck('key'); + }, + + values: function() { + return this.pluck('value'); + }, + + merge: function(hash) { + return $H(hash).inject(this, function(mergedHash, pair) { + mergedHash[pair.key] = pair.value; + return mergedHash; + }); + }, + + remove: function() { + var result; + for(var i = 0, length = arguments.length; i < length; i++) { + var value = this[arguments[i]]; + if (value !== undefined){ + if (result === undefined) result = value; + else { + if (result.constructor != Array) result = [result]; + result.push(value) + } + } + delete this[arguments[i]]; + } + return result; + }, + + toQueryString: function() { + return Hash.toQueryString(this); + }, + + inspect: function() { + return '#'; + } +}); + +function $H(object) { + if (object && object.constructor == Hash) return object; + return new Hash(object); +}; +ObjectRange = Class.create(); +Object.extend(ObjectRange.prototype, Enumerable); +Object.extend(ObjectRange.prototype, { + initialize: function(start, end, exclusive) { + this.start = start; + this.end = end; + this.exclusive = exclusive; + }, + + _each: function(iterator) { + var value = this.start; + while (this.include(value)) { + iterator(value); + value = value.succ(); + } + }, + + include: function(value) { + if (value < this.start) + return false; + if (this.exclusive) + return value < this.end; + return value <= this.end; + } +}); + +var $R = function(start, end, exclusive) { + return new ObjectRange(start, end, exclusive); +} + +var Ajax = { + getTransport: function() { + return Try.these( + function() {return new XMLHttpRequest()}, + function() {return new ActiveXObject('Msxml2.XMLHTTP')}, + function() {return new ActiveXObject('Microsoft.XMLHTTP')} + ) || false; + }, + + activeRequestCount: 0 +} + +Ajax.Responders = { + responders: [], + + _each: function(iterator) { + this.responders._each(iterator); + }, + + register: function(responder) { + if (!this.include(responder)) + this.responders.push(responder); + }, + + unregister: function(responder) { + this.responders = this.responders.without(responder); + }, + + dispatch: function(callback, request, transport, json) { + this.each(function(responder) { + if (typeof responder[callback] == 'function') { + try { + responder[callback].apply(responder, [request, transport, json]); + } catch (e) {} + } + }); + } +}; + +Object.extend(Ajax.Responders, Enumerable); + +Ajax.Responders.register({ + onCreate: function() { + Ajax.activeRequestCount++; + }, + onComplete: function() { + Ajax.activeRequestCount--; + } +}); + +Ajax.Base = function() {}; +Ajax.Base.prototype = { + setOptions: function(options) { + this.options = { + method: 'post', + asynchronous: true, + contentType: 'application/x-www-form-urlencoded', + encoding: 'UTF-8', + parameters: '' + } + Object.extend(this.options, options || {}); + + this.options.method = this.options.method.toLowerCase(); + if (typeof this.options.parameters == 'string') + this.options.parameters = this.options.parameters.toQueryParams(); + } +} + +Ajax.Request = Class.create(); +Ajax.Request.Events = + ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; + +Ajax.Request.prototype = Object.extend(new Ajax.Base(), { + _complete: false, + + initialize: function(url, options) { + this.transport = Ajax.getTransport(); + this.setOptions(options); + this.request(url); + }, + + request: function(url) { + this.url = url; + this.method = this.options.method; + var params = this.options.parameters; + + if (!['get', 'post'].include(this.method)) { + // simulate other verbs over post + params['_method'] = this.method; + this.method = 'post'; + } + + params = Hash.toQueryString(params); + if (params && /Konqueror|Safari|KHTML/.test(navigator.userAgent)) params += '&_=' + + // when GET, append parameters to URL + if (this.method == 'get' && params) + this.url += (this.url.indexOf('?') > -1 ? '&' : '?') + params; + + try { + Ajax.Responders.dispatch('onCreate', this, this.transport); + + this.transport.open(this.method.toUpperCase(), this.url, + this.options.asynchronous); + + if (this.options.asynchronous) + setTimeout(function() { this.respondToReadyState(1) }.bind(this), 10); + + this.transport.onreadystatechange = this.onStateChange.bind(this); + this.setRequestHeaders(); + + var body = this.method == 'post' ? (this.options.postBody || params) : null; + + this.transport.send(body); + + /* Force Firefox to handle ready state 4 for synchronous requests */ + if (!this.options.asynchronous && this.transport.overrideMimeType) + this.onStateChange(); + + } + catch (e) { + this.dispatchException(e); + } + }, + + onStateChange: function() { + var readyState = this.transport.readyState; + if (readyState > 1 && !((readyState == 4) && this._complete)) + this.respondToReadyState(this.transport.readyState); + }, + + setRequestHeaders: function() { + var headers = { + 'X-Requested-With': 'XMLHttpRequest', + 'X-Prototype-Version': Prototype.Version, + 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' + }; + + if (this.method == 'post') { + headers['Content-type'] = this.options.contentType + + (this.options.encoding ? '; charset=' + this.options.encoding : ''); + + /* Force "Connection: close" for older Mozilla browsers to work + * around a bug where XMLHttpRequest sends an incorrect + * Content-length header. See Mozilla Bugzilla #246651. + */ + if (this.transport.overrideMimeType && + (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005) + headers['Connection'] = 'close'; + } + + // user-defined headers + if (typeof this.options.requestHeaders == 'object') { + var extras = this.options.requestHeaders; + + if (typeof extras.push == 'function') + for (var i = 0, length = extras.length; i < length; i += 2) + headers[extras[i]] = extras[i+1]; + else + $H(extras).each(function(pair) { headers[pair.key] = pair.value }); + } + + for (var name in headers) + this.transport.setRequestHeader(name, headers[name]); + }, + + success: function() { + return !this.transport.status + || (this.transport.status >= 200 && this.transport.status < 300); + }, + + respondToReadyState: function(readyState) { + var state = Ajax.Request.Events[readyState]; + var transport = this.transport, json = this.evalJSON(); + + if (state == 'Complete') { + try { + this._complete = true; + (this.options['on' + this.transport.status] + || this.options['on' + (this.success() ? 'Success' : 'Failure')] + || Prototype.emptyFunction)(transport, json); + } catch (e) { + this.dispatchException(e); + } + + if ((this.getHeader('Content-type') || 'text/javascript').strip(). + match(/^(text|application)\/(x-)?(java|ecma)script(;.*)?$/i)) + this.evalResponse(); + } + + try { + (this.options['on' + state] || Prototype.emptyFunction)(transport, json); + Ajax.Responders.dispatch('on' + state, this, transport, json); + } catch (e) { + this.dispatchException(e); + } + + if (state == 'Complete') { + // avoid memory leak in MSIE: clean up + this.transport.onreadystatechange = Prototype.emptyFunction; + } + }, + + getHeader: function(name) { + try { + return this.transport.getResponseHeader(name); + } catch (e) { return null } + }, + + evalJSON: function() { + try { + var json = this.getHeader('X-JSON'); + return json ? eval('(' + json + ')') : null; + } catch (e) { return null } + }, + + evalResponse: function() { + try { + return eval(this.transport.responseText); + } catch (e) { + this.dispatchException(e); + } + }, + + dispatchException: function(exception) { + (this.options.onException || Prototype.emptyFunction)(this, exception); + Ajax.Responders.dispatch('onException', this, exception); + } +}); + +Ajax.Updater = Class.create(); + +Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), { + initialize: function(container, url, options) { + this.container = { + success: (container.success || container), + failure: (container.failure || (container.success ? null : container)) + } + + this.transport = Ajax.getTransport(); + this.setOptions(options); + + var onComplete = this.options.onComplete || Prototype.emptyFunction; + this.options.onComplete = (function(transport, param) { + this.updateContent(); + onComplete(transport, param); + }).bind(this); + + this.request(url); + }, + + updateContent: function() { + var receiver = this.container[this.success() ? 'success' : 'failure']; + var response = this.transport.responseText; + + if (!this.options.evalScripts) response = response.stripScripts(); + + if (receiver = $(receiver)) { + if (this.options.insertion) + new this.options.insertion(receiver, response); + else + receiver.update(response); + } + + if (this.success()) { + if (this.onComplete) + setTimeout(this.onComplete.bind(this), 10); + } + } +}); + +Ajax.PeriodicalUpdater = Class.create(); +Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), { + initialize: function(container, url, options) { + this.setOptions(options); + this.onComplete = this.options.onComplete; + + this.frequency = (this.options.frequency || 2); + this.decay = (this.options.decay || 1); + + this.updater = {}; + this.container = container; + this.url = url; + + this.start(); + }, + + start: function() { + this.options.onComplete = this.updateComplete.bind(this); + this.onTimerEvent(); + }, + + stop: function() { + this.updater.options.onComplete = undefined; + clearTimeout(this.timer); + (this.onComplete || Prototype.emptyFunction).apply(this, arguments); + }, + + updateComplete: function(request) { + if (this.options.decay) { + this.decay = (request.responseText == this.lastText ? + this.decay * this.options.decay : 1); + + this.lastText = request.responseText; + } + this.timer = setTimeout(this.onTimerEvent.bind(this), + this.decay * this.frequency * 1000); + }, + + onTimerEvent: function() { + this.updater = new Ajax.Updater(this.container, this.url, this.options); + } +}); +function $(element) { + if (arguments.length > 1) { + for (var i = 0, elements = [], length = arguments.length; i < length; i++) + elements.push($(arguments[i])); + return elements; + } + if (typeof element == 'string') + element = document.getElementById(element); + return Element.extend(element); +} + +if (Prototype.BrowserFeatures.XPath) { + document._getElementsByXPath = function(expression, parentElement) { + var results = []; + var query = document.evaluate(expression, $(parentElement) || document, + null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); + for (var i = 0, length = query.snapshotLength; i < length; i++) + results.push(query.snapshotItem(i)); + return results; + }; +} + +document.getElementsByClassName = function(className, parentElement) { + if (Prototype.BrowserFeatures.XPath) { + var q = ".//*[contains(concat(' ', @class, ' '), ' " + className + " ')]"; + return document._getElementsByXPath(q, parentElement); + } else { + var children = ($(parentElement) || document.body).getElementsByTagName('*'); + var elements = [], child; + for (var i = 0, length = children.length; i < length; i++) { + child = children[i]; + if (Element.hasClassName(child, className)) + elements.push(Element.extend(child)); + } + return elements; + } +}; + +/*--------------------------------------------------------------------------*/ + +if (!window.Element) + var Element = new Object(); + +Element.extend = function(element) { + if (!element || _nativeExtensions || element.nodeType == 3) return element; + + if (!element._extended && element.tagName && element != window) { + var methods = Object.clone(Element.Methods), cache = Element.extend.cache; + + if (element.tagName == 'FORM') + Object.extend(methods, Form.Methods); + if (['INPUT', 'TEXTAREA', 'SELECT'].include(element.tagName)) + Object.extend(methods, Form.Element.Methods); + + Object.extend(methods, Element.Methods.Simulated); + + for (var property in methods) { + var value = methods[property]; + if (typeof value == 'function' && !(property in element)) + element[property] = cache.findOrStore(value); + } + } + + element._extended = true; + return element; +}; + +Element.extend.cache = { + findOrStore: function(value) { + return this[value] = this[value] || function() { + return value.apply(null, [this].concat($A(arguments))); + } + } +}; + +Element.Methods = { + visible: function(element) { + return $(element).style.display != 'none'; + }, + + toggle: function(element) { + element = $(element); + Element[Element.visible(element) ? 'hide' : 'show'](element); + return element; + }, + + hide: function(element) { + $(element).style.display = 'none'; + return element; + }, + + show: function(element) { + $(element).style.display = ''; + return element; + }, + + remove: function(element) { + element = $(element); + element.parentNode.removeChild(element); + return element; + }, + + update: function(element, html) { + html = typeof html == 'undefined' ? '' : html.toString(); + $(element).innerHTML = html.stripScripts(); + setTimeout(function() {html.evalScripts()}, 10); + return element; + }, + + replace: function(element, html) { + element = $(element); + html = typeof html == 'undefined' ? '' : html.toString(); + if (element.outerHTML) { + element.outerHTML = html.stripScripts(); + } else { + var range = element.ownerDocument.createRange(); + range.selectNodeContents(element); + element.parentNode.replaceChild( + range.createContextualFragment(html.stripScripts()), element); + } + setTimeout(function() {html.evalScripts()}, 10); + return element; + }, + + inspect: function(element) { + element = $(element); + var result = '<' + element.tagName.toLowerCase(); + $H({'id': 'id', 'className': 'class'}).each(function(pair) { + var property = pair.first(), attribute = pair.last(); + var value = (element[property] || '').toString(); + if (value) result += ' ' + attribute + '=' + value.inspect(true); + }); + return result + '>'; + }, + + recursivelyCollect: function(element, property) { + element = $(element); + var elements = []; + while (element = element[property]) + if (element.nodeType == 1) + elements.push(Element.extend(element)); + return elements; + }, + + ancestors: function(element) { + return $(element).recursivelyCollect('parentNode'); + }, + + descendants: function(element) { + return $A($(element).getElementsByTagName('*')); + }, + + immediateDescendants: function(element) { + if (!(element = $(element).firstChild)) return []; + while (element && element.nodeType != 1) element = element.nextSibling; + if (element) return [element].concat($(element).nextSiblings()); + return []; + }, + + previousSiblings: function(element) { + return $(element).recursivelyCollect('previousSibling'); + }, + + nextSiblings: function(element) { + return $(element).recursivelyCollect('nextSibling'); + }, + + siblings: function(element) { + element = $(element); + return element.previousSiblings().reverse().concat(element.nextSiblings()); + }, + + match: function(element, selector) { + if (typeof selector == 'string') + selector = new Selector(selector); + return selector.match($(element)); + }, + + up: function(element, expression, index) { + return Selector.findElement($(element).ancestors(), expression, index); + }, + + down: function(element, expression, index) { + return Selector.findElement($(element).descendants(), expression, index); + }, + + previous: function(element, expression, index) { + return Selector.findElement($(element).previousSiblings(), expression, index); + }, + + next: function(element, expression, index) { + return Selector.findElement($(element).nextSiblings(), expression, index); + }, + + getElementsBySelector: function() { + var args = $A(arguments), element = $(args.shift()); + return Selector.findChildElements(element, args); + }, + + getElementsByClassName: function(element, className) { + return document.getElementsByClassName(className, element); + }, + + readAttribute: function(element, name) { + element = $(element); + if (document.all && !window.opera) { + var t = Element._attributeTranslations; + if (t.values[name]) return t.values[name](element, name); + if (t.names[name]) name = t.names[name]; + var attribute = element.attributes[name]; + if(attribute) return attribute.nodeValue; + } + return element.getAttribute(name); + }, + + getHeight: function(element) { + return $(element).getDimensions().height; + }, + + getWidth: function(element) { + return $(element).getDimensions().width; + }, + + classNames: function(element) { + return new Element.ClassNames(element); + }, + + hasClassName: function(element, className) { + if (!(element = $(element))) return; + var elementClassName = element.className; + if (elementClassName.length == 0) return false; + if (elementClassName == className || + elementClassName.match(new RegExp("(^|\\s)" + className + "(\\s|$)"))) + return true; + return false; + }, + + addClassName: function(element, className) { + if (!(element = $(element))) return; + Element.classNames(element).add(className); + return element; + }, + + removeClassName: function(element, className) { + if (!(element = $(element))) return; + Element.classNames(element).remove(className); + return element; + }, + + toggleClassName: function(element, className) { + if (!(element = $(element))) return; + Element.classNames(element)[element.hasClassName(className) ? 'remove' : 'add'](className); + return element; + }, + + observe: function() { + Event.observe.apply(Event, arguments); + return $A(arguments).first(); + }, + + stopObserving: function() { + Event.stopObserving.apply(Event, arguments); + return $A(arguments).first(); + }, + + // removes whitespace-only text node children + cleanWhitespace: function(element) { + element = $(element); + var node = element.firstChild; + while (node) { + var nextNode = node.nextSibling; + if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) + element.removeChild(node); + node = nextNode; + } + return element; + }, + + empty: function(element) { + return $(element).innerHTML.match(/^\s*$/); + }, + + descendantOf: function(element, ancestor) { + element = $(element), ancestor = $(ancestor); + while (element = element.parentNode) + if (element == ancestor) return true; + return false; + }, + + scrollTo: function(element) { + element = $(element); + var pos = Position.cumulativeOffset(element); + window.scrollTo(pos[0], pos[1]); + return element; + }, + + getStyle: function(element, style) { + element = $(element); + if (['float','cssFloat'].include(style)) + style = (typeof element.style.styleFloat != 'undefined' ? 'styleFloat' : 'cssFloat'); + style = style.camelize(); + var value = element.style[style]; + if (!value) { + if (document.defaultView && document.defaultView.getComputedStyle) { + var css = document.defaultView.getComputedStyle(element, null); + value = css ? css[style] : null; + } else if (element.currentStyle) { + value = element.currentStyle[style]; + } + } + + if((value == 'auto') && ['width','height'].include(style) && (element.getStyle('display') != 'none')) + value = element['offset'+style.capitalize()] + 'px'; + + if (window.opera && ['left', 'top', 'right', 'bottom'].include(style)) + if (Element.getStyle(element, 'position') == 'static') value = 'auto'; + if(style == 'opacity') { + if(value) return parseFloat(value); + if(value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/)) + if(value[1]) return parseFloat(value[1]) / 100; + return 1.0; + } + return value == 'auto' ? null : value; + }, + + setStyle: function(element, style) { + element = $(element); + for (var name in style) { + var value = style[name]; + if(name == 'opacity') { + if (value == 1) { + value = (/Gecko/.test(navigator.userAgent) && + !/Konqueror|Safari|KHTML/.test(navigator.userAgent)) ? 0.999999 : 1.0; + if(/MSIE/.test(navigator.userAgent) && !window.opera) + element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,''); + } else if(value == '') { + if(/MSIE/.test(navigator.userAgent) && !window.opera) + element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,''); + } else { + if(value < 0.00001) value = 0; + if(/MSIE/.test(navigator.userAgent) && !window.opera) + element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'') + + 'alpha(opacity='+value*100+')'; + } + } else if(['float','cssFloat'].include(name)) name = (typeof element.style.styleFloat != 'undefined') ? 'styleFloat' : 'cssFloat'; + element.style[name.camelize()] = value; + } + return element; + }, + + getDimensions: function(element) { + element = $(element); + var display = $(element).getStyle('display'); + if (display != 'none' && display != null) // Safari bug + return {width: element.offsetWidth, height: element.offsetHeight}; + + // All *Width and *Height properties give 0 on elements with display none, + // so enable the element temporarily + var els = element.style; + var originalVisibility = els.visibility; + var originalPosition = els.position; + var originalDisplay = els.display; + els.visibility = 'hidden'; + els.position = 'absolute'; + els.display = 'block'; + var originalWidth = element.clientWidth; + var originalHeight = element.clientHeight; + els.display = originalDisplay; + els.position = originalPosition; + els.visibility = originalVisibility; + return {width: originalWidth, height: originalHeight}; + }, + + makePositioned: function(element) { + element = $(element); + var pos = Element.getStyle(element, 'position'); + if (pos == 'static' || !pos) { + element._madePositioned = true; + element.style.position = 'relative'; + // Opera returns the offset relative to the positioning context, when an + // element is position relative but top and left have not been defined + if (window.opera) { + element.style.top = 0; + element.style.left = 0; + } + } + return element; + }, + + undoPositioned: function(element) { + element = $(element); + if (element._madePositioned) { + element._madePositioned = undefined; + element.style.position = + element.style.top = + element.style.left = + element.style.bottom = + element.style.right = ''; + } + return element; + }, + + makeClipping: function(element) { + element = $(element); + if (element._overflow) return element; + element._overflow = element.style.overflow || 'auto'; + if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden') + element.style.overflow = 'hidden'; + return element; + }, + + undoClipping: function(element) { + element = $(element); + if (!element._overflow) return element; + element.style.overflow = element._overflow == 'auto' ? '' : element._overflow; + element._overflow = null; + return element; + } +}; + +Object.extend(Element.Methods, {childOf: Element.Methods.descendantOf}); + +Element._attributeTranslations = {}; + +Element._attributeTranslations.names = { + colspan: "colSpan", + rowspan: "rowSpan", + valign: "vAlign", + datetime: "dateTime", + accesskey: "accessKey", + tabindex: "tabIndex", + enctype: "encType", + maxlength: "maxLength", + readonly: "readOnly", + longdesc: "longDesc" +}; + +Element._attributeTranslations.values = { + _getAttr: function(element, attribute) { + return element.getAttribute(attribute, 2); + }, + + _flag: function(element, attribute) { + return $(element).hasAttribute(attribute) ? attribute : null; + }, + + style: function(element) { + return element.style.cssText.toLowerCase(); + }, + + title: function(element) { + var node = element.getAttributeNode('title'); + return node.specified ? node.nodeValue : null; + } +}; + +Object.extend(Element._attributeTranslations.values, { + href: Element._attributeTranslations.values._getAttr, + src: Element._attributeTranslations.values._getAttr, + disabled: Element._attributeTranslations.values._flag, + checked: Element._attributeTranslations.values._flag, + readonly: Element._attributeTranslations.values._flag, + multiple: Element._attributeTranslations.values._flag +}); + +Element.Methods.Simulated = { + hasAttribute: function(element, attribute) { + var t = Element._attributeTranslations; + attribute = t.names[attribute] || attribute; + return $(element).getAttributeNode(attribute).specified; + } +}; + +// IE is missing .innerHTML support for TABLE-related elements +if (document.all && !window.opera){ + Element.Methods.update = function(element, html) { + element = $(element); + html = typeof html == 'undefined' ? '' : html.toString(); + var tagName = element.tagName.toUpperCase(); + if (['THEAD','TBODY','TR','TD'].include(tagName)) { + var div = document.createElement('div'); + switch (tagName) { + case 'THEAD': + case 'TBODY': + div.innerHTML = '' + html.stripScripts() + '
    '; + depth = 2; + break; + case 'TR': + div.innerHTML = '' + html.stripScripts() + '
    '; + depth = 3; + break; + case 'TD': + div.innerHTML = '
    ' + html.stripScripts() + '
    '; + depth = 4; + } + $A(element.childNodes).each(function(node){ + element.removeChild(node) + }); + depth.times(function(){ div = div.firstChild }); + + $A(div.childNodes).each( + function(node){ element.appendChild(node) }); + } else { + element.innerHTML = html.stripScripts(); + } + setTimeout(function() {html.evalScripts()}, 10); + return element; + } +}; + +Object.extend(Element, Element.Methods); + +var _nativeExtensions = false; + +if(/Konqueror|Safari|KHTML/.test(navigator.userAgent)) + ['', 'Form', 'Input', 'TextArea', 'Select'].each(function(tag) { + var className = 'HTML' + tag + 'Element'; + if(window[className]) return; + var klass = window[className] = {}; + klass.prototype = document.createElement(tag ? tag.toLowerCase() : 'div').__proto__; + }); + +Element.addMethods = function(methods) { + Object.extend(Element.Methods, methods || {}); + + function copy(methods, destination, onlyIfAbsent) { + onlyIfAbsent = onlyIfAbsent || false; + var cache = Element.extend.cache; + for (var property in methods) { + var value = methods[property]; + if (!onlyIfAbsent || !(property in destination)) + destination[property] = cache.findOrStore(value); + } + } + + if (typeof HTMLElement != 'undefined') { + copy(Element.Methods, HTMLElement.prototype); + copy(Element.Methods.Simulated, HTMLElement.prototype, true); + copy(Form.Methods, HTMLFormElement.prototype); + [HTMLInputElement, HTMLTextAreaElement, HTMLSelectElement].each(function(klass) { + copy(Form.Element.Methods, klass.prototype); + }); + _nativeExtensions = true; + } +} + +var Toggle = new Object(); +Toggle.display = Element.toggle; + +/*--------------------------------------------------------------------------*/ + +Abstract.Insertion = function(adjacency) { + this.adjacency = adjacency; +} + +Abstract.Insertion.prototype = { + initialize: function(element, content) { + this.element = $(element); + this.content = content.stripScripts(); + + if (this.adjacency && this.element.insertAdjacentHTML) { + try { + this.element.insertAdjacentHTML(this.adjacency, this.content); + } catch (e) { + var tagName = this.element.tagName.toUpperCase(); + if (['TBODY', 'TR'].include(tagName)) { + this.insertContent(this.contentFromAnonymousTable()); + } else { + throw e; + } + } + } else { + this.range = this.element.ownerDocument.createRange(); + if (this.initializeRange) this.initializeRange(); + this.insertContent([this.range.createContextualFragment(this.content)]); + } + + setTimeout(function() {content.evalScripts()}, 10); + }, + + contentFromAnonymousTable: function() { + var div = document.createElement('div'); + div.innerHTML = '' + this.content + '
    '; + return $A(div.childNodes[0].childNodes[0].childNodes); + } +} + +var Insertion = new Object(); + +Insertion.Before = Class.create(); +Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), { + initializeRange: function() { + this.range.setStartBefore(this.element); + }, + + insertContent: function(fragments) { + fragments.each((function(fragment) { + this.element.parentNode.insertBefore(fragment, this.element); + }).bind(this)); + } +}); + +Insertion.Top = Class.create(); +Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), { + initializeRange: function() { + this.range.selectNodeContents(this.element); + this.range.collapse(true); + }, + + insertContent: function(fragments) { + fragments.reverse(false).each((function(fragment) { + this.element.insertBefore(fragment, this.element.firstChild); + }).bind(this)); + } +}); + +Insertion.Bottom = Class.create(); +Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), { + initializeRange: function() { + this.range.selectNodeContents(this.element); + this.range.collapse(this.element); + }, + + insertContent: function(fragments) { + fragments.each((function(fragment) { + this.element.appendChild(fragment); + }).bind(this)); + } +}); + +Insertion.After = Class.create(); +Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), { + initializeRange: function() { + this.range.setStartAfter(this.element); + }, + + insertContent: function(fragments) { + fragments.each((function(fragment) { + this.element.parentNode.insertBefore(fragment, + this.element.nextSibling); + }).bind(this)); + } +}); + +/*--------------------------------------------------------------------------*/ + +Element.ClassNames = Class.create(); +Element.ClassNames.prototype = { + initialize: function(element) { + this.element = $(element); + }, + + _each: function(iterator) { + this.element.className.split(/\s+/).select(function(name) { + return name.length > 0; + })._each(iterator); + }, + + set: function(className) { + this.element.className = className; + }, + + add: function(classNameToAdd) { + if (this.include(classNameToAdd)) return; + this.set($A(this).concat(classNameToAdd).join(' ')); + }, + + remove: function(classNameToRemove) { + if (!this.include(classNameToRemove)) return; + this.set($A(this).without(classNameToRemove).join(' ')); + }, + + toString: function() { + return $A(this).join(' '); + } +}; + +Object.extend(Element.ClassNames.prototype, Enumerable); +var Selector = Class.create(); +Selector.prototype = { + initialize: function(expression) { + this.params = {classNames: []}; + this.expression = expression.toString().strip(); + this.parseExpression(); + this.compileMatcher(); + }, + + parseExpression: function() { + function abort(message) { throw 'Parse error in selector: ' + message; } + + if (this.expression == '') abort('empty expression'); + + var params = this.params, expr = this.expression, match, modifier, clause, rest; + while (match = expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i)) { + params.attributes = params.attributes || []; + params.attributes.push({name: match[2], operator: match[3], value: match[4] || match[5] || ''}); + expr = match[1]; + } + + if (expr == '*') return this.params.wildcard = true; + + while (match = expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+)(.*)/i)) { + modifier = match[1], clause = match[2], rest = match[3]; + switch (modifier) { + case '#': params.id = clause; break; + case '.': params.classNames.push(clause); break; + case '': + case undefined: params.tagName = clause.toUpperCase(); break; + default: abort(expr.inspect()); + } + expr = rest; + } + + if (expr.length > 0) abort(expr.inspect()); + }, + + buildMatchExpression: function() { + var params = this.params, conditions = [], clause; + + if (params.wildcard) + conditions.push('true'); + if (clause = params.id) + conditions.push('element.readAttribute("id") == ' + clause.inspect()); + if (clause = params.tagName) + conditions.push('element.tagName.toUpperCase() == ' + clause.inspect()); + if ((clause = params.classNames).length > 0) + for (var i = 0, length = clause.length; i < length; i++) + conditions.push('element.hasClassName(' + clause[i].inspect() + ')'); + if (clause = params.attributes) { + clause.each(function(attribute) { + var value = 'element.readAttribute(' + attribute.name.inspect() + ')'; + var splitValueBy = function(delimiter) { + return value + ' && ' + value + '.split(' + delimiter.inspect() + ')'; + } + + switch (attribute.operator) { + case '=': conditions.push(value + ' == ' + attribute.value.inspect()); break; + case '~=': conditions.push(splitValueBy(' ') + '.include(' + attribute.value.inspect() + ')'); break; + case '|=': conditions.push( + splitValueBy('-') + '.first().toUpperCase() == ' + attribute.value.toUpperCase().inspect() + ); break; + case '!=': conditions.push(value + ' != ' + attribute.value.inspect()); break; + case '': + case undefined: conditions.push('element.hasAttribute(' + attribute.name.inspect() + ')'); break; + default: throw 'Unknown operator ' + attribute.operator + ' in selector'; + } + }); + } + + return conditions.join(' && '); + }, + + compileMatcher: function() { + this.match = new Function('element', 'if (!element.tagName) return false; \ + element = $(element); \ + return ' + this.buildMatchExpression()); + }, + + findElements: function(scope) { + var element; + + if (element = $(this.params.id)) + if (this.match(element)) + if (!scope || Element.childOf(element, scope)) + return [element]; + + scope = (scope || document).getElementsByTagName(this.params.tagName || '*'); + + var results = []; + for (var i = 0, length = scope.length; i < length; i++) + if (this.match(element = scope[i])) + results.push(Element.extend(element)); + + return results; + }, + + toString: function() { + return this.expression; + } +} + +Object.extend(Selector, { + matchElements: function(elements, expression) { + var selector = new Selector(expression); + return elements.select(selector.match.bind(selector)).map(Element.extend); + }, + + findElement: function(elements, expression, index) { + if (typeof expression == 'number') index = expression, expression = false; + return Selector.matchElements(elements, expression || '*')[index || 0]; + }, + + findChildElements: function(element, expressions) { + return expressions.map(function(expression) { + return expression.match(/[^\s"]+(?:"[^"]*"[^\s"]+)*/g).inject([null], function(results, expr) { + var selector = new Selector(expr); + return results.inject([], function(elements, result) { + return elements.concat(selector.findElements(result || element)); + }); + }); + }).flatten(); + } +}); + +function $$() { + return Selector.findChildElements(document, $A(arguments)); +} +var Form = { + reset: function(form) { + $(form).reset(); + return form; + }, + + serializeElements: function(elements, getHash) { + var data = elements.inject({}, function(result, element) { + if (!element.disabled && element.name) { + var key = element.name, value = $(element).getValue(); + if (value != undefined) { + if (result[key]) { + if (result[key].constructor != Array) result[key] = [result[key]]; + result[key].push(value); + } + else result[key] = value; + } + } + return result; + }); + + return getHash ? data : Hash.toQueryString(data); + } +}; + +Form.Methods = { + serialize: function(form, getHash) { + return Form.serializeElements(Form.getElements(form), getHash); + }, + + getElements: function(form) { + return $A($(form).getElementsByTagName('*')).inject([], + function(elements, child) { + if (Form.Element.Serializers[child.tagName.toLowerCase()]) + elements.push(Element.extend(child)); + return elements; + } + ); + }, + + getInputs: function(form, typeName, name) { + form = $(form); + var inputs = form.getElementsByTagName('input'); + + if (!typeName && !name) return $A(inputs).map(Element.extend); + + for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) { + var input = inputs[i]; + if ((typeName && input.type != typeName) || (name && input.name != name)) + continue; + matchingInputs.push(Element.extend(input)); + } + + return matchingInputs; + }, + + disable: function(form) { + form = $(form); + form.getElements().each(function(element) { + element.blur(); + element.disabled = 'true'; + }); + return form; + }, + + enable: function(form) { + form = $(form); + form.getElements().each(function(element) { + element.disabled = ''; + }); + return form; + }, + + findFirstElement: function(form) { + return $(form).getElements().find(function(element) { + return element.type != 'hidden' && !element.disabled && + ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); + }); + }, + + focusFirstElement: function(form) { + form = $(form); + form.findFirstElement().activate(); + return form; + } +} + +Object.extend(Form, Form.Methods); + +/*--------------------------------------------------------------------------*/ + +Form.Element = { + focus: function(element) { + $(element).focus(); + return element; + }, + + select: function(element) { + $(element).select(); + return element; + } +} + +Form.Element.Methods = { + serialize: function(element) { + element = $(element); + if (!element.disabled && element.name) { + var value = element.getValue(); + if (value != undefined) { + var pair = {}; + pair[element.name] = value; + return Hash.toQueryString(pair); + } + } + return ''; + }, + + getValue: function(element) { + element = $(element); + var method = element.tagName.toLowerCase(); + return Form.Element.Serializers[method](element); + }, + + clear: function(element) { + $(element).value = ''; + return element; + }, + + present: function(element) { + return $(element).value != ''; + }, + + activate: function(element) { + element = $(element); + element.focus(); + if (element.select && ( element.tagName.toLowerCase() != 'input' || + !['button', 'reset', 'submit'].include(element.type) ) ) + element.select(); + return element; + }, + + disable: function(element) { + element = $(element); + element.disabled = true; + return element; + }, + + enable: function(element) { + element = $(element); + element.blur(); + element.disabled = false; + return element; + } +} + +Object.extend(Form.Element, Form.Element.Methods); +var Field = Form.Element; +var $F = Form.Element.getValue; + +/*--------------------------------------------------------------------------*/ + +Form.Element.Serializers = { + input: function(element) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + return Form.Element.Serializers.inputSelector(element); + default: + return Form.Element.Serializers.textarea(element); + } + }, + + inputSelector: function(element) { + return element.checked ? element.value : null; + }, + + textarea: function(element) { + return element.value; + }, + + select: function(element) { + return this[element.type == 'select-one' ? + 'selectOne' : 'selectMany'](element); + }, + + selectOne: function(element) { + var index = element.selectedIndex; + return index >= 0 ? this.optionValue(element.options[index]) : null; + }, + + selectMany: function(element) { + var values, length = element.length; + if (!length) return null; + + for (var i = 0, values = []; i < length; i++) { + var opt = element.options[i]; + if (opt.selected) values.push(this.optionValue(opt)); + } + return values; + }, + + optionValue: function(opt) { + // extend element because hasAttribute may not be native + return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text; + } +} + +/*--------------------------------------------------------------------------*/ + +Abstract.TimedObserver = function() {} +Abstract.TimedObserver.prototype = { + initialize: function(element, frequency, callback) { + this.frequency = frequency; + this.element = $(element); + this.callback = callback; + + this.lastValue = this.getValue(); + this.registerCallback(); + }, + + registerCallback: function() { + setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + onTimerEvent: function() { + var value = this.getValue(); + var changed = ('string' == typeof this.lastValue && 'string' == typeof value + ? this.lastValue != value : String(this.lastValue) != String(value)); + if (changed) { + this.callback(this.element, value); + this.lastValue = value; + } + } +} + +Form.Element.Observer = Class.create(); +Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.Observer = Class.create(); +Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { + getValue: function() { + return Form.serialize(this.element); + } +}); + +/*--------------------------------------------------------------------------*/ + +Abstract.EventObserver = function() {} +Abstract.EventObserver.prototype = { + initialize: function(element, callback) { + this.element = $(element); + this.callback = callback; + + this.lastValue = this.getValue(); + if (this.element.tagName.toLowerCase() == 'form') + this.registerFormCallbacks(); + else + this.registerCallback(this.element); + }, + + onElementEvent: function() { + var value = this.getValue(); + if (this.lastValue != value) { + this.callback(this.element, value); + this.lastValue = value; + } + }, + + registerFormCallbacks: function() { + Form.getElements(this.element).each(this.registerCallback.bind(this)); + }, + + registerCallback: function(element) { + if (element.type) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + Event.observe(element, 'click', this.onElementEvent.bind(this)); + break; + default: + Event.observe(element, 'change', this.onElementEvent.bind(this)); + break; + } + } + } +} + +Form.Element.EventObserver = Class.create(); +Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.EventObserver = Class.create(); +Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { + getValue: function() { + return Form.serialize(this.element); + } +}); +if (!window.Event) { + var Event = new Object(); +} + +Object.extend(Event, { + KEY_BACKSPACE: 8, + KEY_TAB: 9, + KEY_RETURN: 13, + KEY_ESC: 27, + KEY_LEFT: 37, + KEY_UP: 38, + KEY_RIGHT: 39, + KEY_DOWN: 40, + KEY_DELETE: 46, + KEY_HOME: 36, + KEY_END: 35, + KEY_PAGEUP: 33, + KEY_PAGEDOWN: 34, + + element: function(event) { + return event.target || event.srcElement; + }, + + isLeftClick: function(event) { + return (((event.which) && (event.which == 1)) || + ((event.button) && (event.button == 1))); + }, + + pointerX: function(event) { + return event.pageX || (event.clientX + + (document.documentElement.scrollLeft || document.body.scrollLeft)); + }, + + pointerY: function(event) { + return event.pageY || (event.clientY + + (document.documentElement.scrollTop || document.body.scrollTop)); + }, + + stop: function(event) { + if (event.preventDefault) { + event.preventDefault(); + event.stopPropagation(); + } else { + event.returnValue = false; + event.cancelBubble = true; + } + }, + + // find the first node with the given tagName, starting from the + // node the event was triggered on; traverses the DOM upwards + findElement: function(event, tagName) { + var element = Event.element(event); + while (element.parentNode && (!element.tagName || + (element.tagName.toUpperCase() != tagName.toUpperCase()))) + element = element.parentNode; + return element; + }, + + observers: false, + + _observeAndCache: function(element, name, observer, useCapture) { + if (!this.observers) this.observers = []; + if (element.addEventListener) { + this.observers.push([element, name, observer, useCapture]); + element.addEventListener(name, observer, useCapture); + } else if (element.attachEvent) { + this.observers.push([element, name, observer, useCapture]); + element.attachEvent('on' + name, observer); + } + }, + + unloadCache: function() { + if (!Event.observers) return; + for (var i = 0, length = Event.observers.length; i < length; i++) { + Event.stopObserving.apply(this, Event.observers[i]); + Event.observers[i][0] = null; + } + Event.observers = false; + }, + + observe: function(element, name, observer, useCapture) { + element = $(element); + useCapture = useCapture || false; + + if (name == 'keypress' && + (navigator.appVersion.match(/Konqueror|Safari|KHTML/) + || element.attachEvent)) + name = 'keydown'; + + Event._observeAndCache(element, name, observer, useCapture); + }, + + stopObserving: function(element, name, observer, useCapture) { + element = $(element); + useCapture = useCapture || false; + + if (name == 'keypress' && + (navigator.appVersion.match(/Konqueror|Safari|KHTML/) + || element.detachEvent)) + name = 'keydown'; + + if (element.removeEventListener) { + element.removeEventListener(name, observer, useCapture); + } else if (element.detachEvent) { + try { + element.detachEvent('on' + name, observer); + } catch (e) {} + } + } +}); + +/* prevent memory leaks in IE */ +if (navigator.appVersion.match(/\bMSIE\b/)) + Event.observe(window, 'unload', Event.unloadCache, false); +var Position = { + // set to true if needed, warning: firefox performance problems + // NOT neeeded for page scrolling, only if draggable contained in + // scrollable elements + includeScrollOffsets: false, + + // must be called before calling withinIncludingScrolloffset, every time the + // page is scrolled + prepare: function() { + this.deltaX = window.pageXOffset + || document.documentElement.scrollLeft + || document.body.scrollLeft + || 0; + this.deltaY = window.pageYOffset + || document.documentElement.scrollTop + || document.body.scrollTop + || 0; + }, + + realOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.scrollTop || 0; + valueL += element.scrollLeft || 0; + element = element.parentNode; + } while (element); + return [valueL, valueT]; + }, + + cumulativeOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + } while (element); + return [valueL, valueT]; + }, + + positionedOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + if (element) { + if(element.tagName=='BODY') break; + var p = Element.getStyle(element, 'position'); + if (p == 'relative' || p == 'absolute') break; + } + } while (element); + return [valueL, valueT]; + }, + + offsetParent: function(element) { + if (element.offsetParent) return element.offsetParent; + if (element == document.body) return element; + + while ((element = element.parentNode) && element != document.body) + if (Element.getStyle(element, 'position') != 'static') + return element; + + return document.body; + }, + + // caches x/y coordinate pair to use with overlap + within: function(element, x, y) { + if (this.includeScrollOffsets) + return this.withinIncludingScrolloffsets(element, x, y); + this.xcomp = x; + this.ycomp = y; + this.offset = this.cumulativeOffset(element); + + return (y >= this.offset[1] && + y < this.offset[1] + element.offsetHeight && + x >= this.offset[0] && + x < this.offset[0] + element.offsetWidth); + }, + + withinIncludingScrolloffsets: function(element, x, y) { + var offsetcache = this.realOffset(element); + + this.xcomp = x + offsetcache[0] - this.deltaX; + this.ycomp = y + offsetcache[1] - this.deltaY; + this.offset = this.cumulativeOffset(element); + + return (this.ycomp >= this.offset[1] && + this.ycomp < this.offset[1] + element.offsetHeight && + this.xcomp >= this.offset[0] && + this.xcomp < this.offset[0] + element.offsetWidth); + }, + + // within must be called directly before + overlap: function(mode, element) { + if (!mode) return 0; + if (mode == 'vertical') + return ((this.offset[1] + element.offsetHeight) - this.ycomp) / + element.offsetHeight; + if (mode == 'horizontal') + return ((this.offset[0] + element.offsetWidth) - this.xcomp) / + element.offsetWidth; + }, + + page: function(forElement) { + var valueT = 0, valueL = 0; + + var element = forElement; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + + // Safari fix + if (element.offsetParent==document.body) + if (Element.getStyle(element,'position')=='absolute') break; + + } while (element = element.offsetParent); + + element = forElement; + do { + if (!window.opera || element.tagName=='BODY') { + valueT -= element.scrollTop || 0; + valueL -= element.scrollLeft || 0; + } + } while (element = element.parentNode); + + return [valueL, valueT]; + }, + + clone: function(source, target) { + var options = Object.extend({ + setLeft: true, + setTop: true, + setWidth: true, + setHeight: true, + offsetTop: 0, + offsetLeft: 0 + }, arguments[2] || {}) + + // find page position of source + source = $(source); + var p = Position.page(source); + + // find coordinate system to use + target = $(target); + var delta = [0, 0]; + var parent = null; + // delta [0,0] will do fine with position: fixed elements, + // position:absolute needs offsetParent deltas + if (Element.getStyle(target,'position') == 'absolute') { + parent = Position.offsetParent(target); + delta = Position.page(parent); + } + + // correct by body offsets (fixes Safari) + if (parent == document.body) { + delta[0] -= document.body.offsetLeft; + delta[1] -= document.body.offsetTop; + } + + // set position + if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; + if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; + if(options.setWidth) target.style.width = source.offsetWidth + 'px'; + if(options.setHeight) target.style.height = source.offsetHeight + 'px'; + }, + + absolutize: function(element) { + element = $(element); + if (element.style.position == 'absolute') return; + Position.prepare(); + + var offsets = Position.positionedOffset(element); + var top = offsets[1]; + var left = offsets[0]; + var width = element.clientWidth; + var height = element.clientHeight; + + element._originalLeft = left - parseFloat(element.style.left || 0); + element._originalTop = top - parseFloat(element.style.top || 0); + element._originalWidth = element.style.width; + element._originalHeight = element.style.height; + + element.style.position = 'absolute'; + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.width = width + 'px'; + element.style.height = height + 'px'; + }, + + relativize: function(element) { + element = $(element); + if (element.style.position == 'relative') return; + Position.prepare(); + + element.style.position = 'relative'; + var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); + var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); + + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.height = element._originalHeight; + element.style.width = element._originalWidth; + } +} + +// Safari returns margins on body which is incorrect if the child is absolutely +// positioned. For performance reasons, redefine Position.cumulativeOffset for +// KHTML/WebKit only. +if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) { + Position.cumulativeOffset = function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + if (element.offsetParent == document.body) + if (Element.getStyle(element, 'position') == 'absolute') break; + + element = element.offsetParent; + } while (element); + + return [valueL, valueT]; + } +} + +Element.addMethods(); \ No newline at end of file diff --git a/gems/bin/rdebug b/gems/bin/rdebug new file mode 100755 index 0000000..0be0987 --- /dev/null +++ b/gems/bin/rdebug @@ -0,0 +1,19 @@ +#!/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby +# +# This file was generated by RubyGems. +# +# The application 'ruby-debug' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'rubygems' + +version = ">= 0" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem 'ruby-debug', version +load 'rdebug' diff --git a/gems/cache/ParseTree-3.0.2.gem b/gems/cache/ParseTree-3.0.2.gem new file mode 100644 index 0000000..4cac6d0 Binary files /dev/null and b/gems/cache/ParseTree-3.0.2.gem differ diff --git a/gems/cache/RubyInline-3.8.1.gem b/gems/cache/RubyInline-3.8.1.gem new file mode 100644 index 0000000..c4bdef0 Binary files /dev/null and b/gems/cache/RubyInline-3.8.1.gem differ diff --git a/gems/cache/ZenTest-3.11.0.gem b/gems/cache/ZenTest-3.11.0.gem new file mode 100644 index 0000000..a1a99e9 Binary files /dev/null and b/gems/cache/ZenTest-3.11.0.gem differ diff --git a/gems/cache/abstract-1.0.0.gem b/gems/cache/abstract-1.0.0.gem new file mode 100644 index 0000000..a9be232 Binary files /dev/null and b/gems/cache/abstract-1.0.0.gem differ diff --git a/gems/cache/addressable-1.0.4.gem b/gems/cache/addressable-1.0.4.gem new file mode 100644 index 0000000..fd1db0c Binary files /dev/null and b/gems/cache/addressable-1.0.4.gem differ diff --git a/gems/cache/cgi_multipart_eof_fix-2.5.0.gem b/gems/cache/cgi_multipart_eof_fix-2.5.0.gem new file mode 100644 index 0000000..5111044 Binary files /dev/null and b/gems/cache/cgi_multipart_eof_fix-2.5.0.gem differ diff --git a/gems/cache/columnize-0.1.gem b/gems/cache/columnize-0.1.gem new file mode 100644 index 0000000..b28a838 Binary files /dev/null and b/gems/cache/columnize-0.1.gem differ diff --git a/gems/cache/daemons-1.0.10.gem b/gems/cache/daemons-1.0.10.gem new file mode 100644 index 0000000..248c950 Binary files /dev/null and b/gems/cache/daemons-1.0.10.gem differ diff --git a/gems/cache/data_objects-0.9.6.gem b/gems/cache/data_objects-0.9.6.gem new file mode 100644 index 0000000..a670a59 Binary files /dev/null and b/gems/cache/data_objects-0.9.6.gem differ diff --git a/gems/cache/diff-lcs-1.1.2.gem b/gems/cache/diff-lcs-1.1.2.gem new file mode 100644 index 0000000..aa0be73 Binary files /dev/null and b/gems/cache/diff-lcs-1.1.2.gem differ diff --git a/gems/cache/dm-aggregates-0.9.6.gem b/gems/cache/dm-aggregates-0.9.6.gem new file mode 100644 index 0000000..df6ef03 Binary files /dev/null and b/gems/cache/dm-aggregates-0.9.6.gem differ diff --git a/gems/cache/dm-core-0.9.6.gem b/gems/cache/dm-core-0.9.6.gem new file mode 100644 index 0000000..a1e1aa9 Binary files /dev/null and b/gems/cache/dm-core-0.9.6.gem differ diff --git a/gems/cache/dm-migrations-0.9.6.gem b/gems/cache/dm-migrations-0.9.6.gem new file mode 100644 index 0000000..508819a Binary files /dev/null and b/gems/cache/dm-migrations-0.9.6.gem differ diff --git a/gems/cache/dm-sweatshop-0.9.6.gem b/gems/cache/dm-sweatshop-0.9.6.gem new file mode 100644 index 0000000..64128f5 Binary files /dev/null and b/gems/cache/dm-sweatshop-0.9.6.gem differ diff --git a/gems/cache/dm-timestamps-0.9.6.gem b/gems/cache/dm-timestamps-0.9.6.gem new file mode 100644 index 0000000..48f94cb Binary files /dev/null and b/gems/cache/dm-timestamps-0.9.6.gem differ diff --git a/gems/cache/dm-types-0.9.6.gem b/gems/cache/dm-types-0.9.6.gem new file mode 100644 index 0000000..c24c86e Binary files /dev/null and b/gems/cache/dm-types-0.9.6.gem differ diff --git a/gems/cache/dm-validations-0.9.6.gem b/gems/cache/dm-validations-0.9.6.gem new file mode 100644 index 0000000..347aeb7 Binary files /dev/null and b/gems/cache/dm-validations-0.9.6.gem differ diff --git a/gems/cache/do_sqlite3-0.9.6.gem b/gems/cache/do_sqlite3-0.9.6.gem new file mode 100644 index 0000000..e26de55 Binary files /dev/null and b/gems/cache/do_sqlite3-0.9.6.gem differ diff --git a/gems/cache/erubis-2.6.2.gem b/gems/cache/erubis-2.6.2.gem new file mode 100644 index 0000000..a3a48f7 Binary files /dev/null and b/gems/cache/erubis-2.6.2.gem differ diff --git a/gems/cache/extlib-0.9.8.gem b/gems/cache/extlib-0.9.8.gem new file mode 100644 index 0000000..f23ccf0 Binary files /dev/null and b/gems/cache/extlib-0.9.8.gem differ diff --git a/gems/cache/fastthread-1.0.1.gem b/gems/cache/fastthread-1.0.1.gem new file mode 100644 index 0000000..98ca380 Binary files /dev/null and b/gems/cache/fastthread-1.0.1.gem differ diff --git a/gems/cache/gem_plugin-0.2.3.gem b/gems/cache/gem_plugin-0.2.3.gem new file mode 100644 index 0000000..4c8af3f Binary files /dev/null and b/gems/cache/gem_plugin-0.2.3.gem differ diff --git a/gems/cache/haml-2.0.4.gem b/gems/cache/haml-2.0.4.gem new file mode 100644 index 0000000..35edc89 Binary files /dev/null and b/gems/cache/haml-2.0.4.gem differ diff --git a/gems/cache/highline-1.5.0.gem b/gems/cache/highline-1.5.0.gem new file mode 100644 index 0000000..c3b41fd Binary files /dev/null and b/gems/cache/highline-1.5.0.gem differ diff --git a/gems/cache/json_pure-1.1.3.gem b/gems/cache/json_pure-1.1.3.gem new file mode 100644 index 0000000..4a398e5 Binary files /dev/null and b/gems/cache/json_pure-1.1.3.gem differ diff --git a/gems/cache/linecache-0.43.gem b/gems/cache/linecache-0.43.gem new file mode 100644 index 0000000..244ae46 Binary files /dev/null and b/gems/cache/linecache-0.43.gem differ diff --git a/gems/cache/mailfactory-1.4.0.gem b/gems/cache/mailfactory-1.4.0.gem new file mode 100644 index 0000000..5d3f536 Binary files /dev/null and b/gems/cache/mailfactory-1.4.0.gem differ diff --git a/gems/cache/merb-1.0.gem b/gems/cache/merb-1.0.gem new file mode 100644 index 0000000..95960ae Binary files /dev/null and b/gems/cache/merb-1.0.gem differ diff --git a/gems/cache/merb-action-args-1.0.gem b/gems/cache/merb-action-args-1.0.gem new file mode 100644 index 0000000..ff90d5a Binary files /dev/null and b/gems/cache/merb-action-args-1.0.gem differ diff --git a/gems/cache/merb-assets-1.0.gem b/gems/cache/merb-assets-1.0.gem new file mode 100644 index 0000000..40db7b4 Binary files /dev/null and b/gems/cache/merb-assets-1.0.gem differ diff --git a/gems/cache/merb-auth-1.0.gem b/gems/cache/merb-auth-1.0.gem new file mode 100644 index 0000000..3b62c9e Binary files /dev/null and b/gems/cache/merb-auth-1.0.gem differ diff --git a/gems/cache/merb-auth-core-1.0.gem b/gems/cache/merb-auth-core-1.0.gem new file mode 100644 index 0000000..e14bec2 Binary files /dev/null and b/gems/cache/merb-auth-core-1.0.gem differ diff --git a/gems/cache/merb-auth-more-1.0.gem b/gems/cache/merb-auth-more-1.0.gem new file mode 100644 index 0000000..fb2fbd6 Binary files /dev/null and b/gems/cache/merb-auth-more-1.0.gem differ diff --git a/gems/cache/merb-auth-slice-password-1.0.gem b/gems/cache/merb-auth-slice-password-1.0.gem new file mode 100644 index 0000000..a4dd0f7 Binary files /dev/null and b/gems/cache/merb-auth-slice-password-1.0.gem differ diff --git a/gems/cache/merb-cache-1.0.gem b/gems/cache/merb-cache-1.0.gem new file mode 100644 index 0000000..4cb7af5 Binary files /dev/null and b/gems/cache/merb-cache-1.0.gem differ diff --git a/gems/cache/merb-core-1.0.gem b/gems/cache/merb-core-1.0.gem new file mode 100644 index 0000000..411af23 Binary files /dev/null and b/gems/cache/merb-core-1.0.gem differ diff --git a/gems/cache/merb-exceptions-1.0.gem b/gems/cache/merb-exceptions-1.0.gem new file mode 100644 index 0000000..0f912c8 Binary files /dev/null and b/gems/cache/merb-exceptions-1.0.gem differ diff --git a/gems/cache/merb-gen-1.0.gem b/gems/cache/merb-gen-1.0.gem new file mode 100644 index 0000000..8d27e32 Binary files /dev/null and b/gems/cache/merb-gen-1.0.gem differ diff --git a/gems/cache/merb-haml-1.0.gem b/gems/cache/merb-haml-1.0.gem new file mode 100644 index 0000000..2509bc0 Binary files /dev/null and b/gems/cache/merb-haml-1.0.gem differ diff --git a/gems/cache/merb-helpers-1.0.gem b/gems/cache/merb-helpers-1.0.gem new file mode 100644 index 0000000..9c940ca Binary files /dev/null and b/gems/cache/merb-helpers-1.0.gem differ diff --git a/gems/cache/merb-mailer-1.0.gem b/gems/cache/merb-mailer-1.0.gem new file mode 100644 index 0000000..0e6486c Binary files /dev/null and b/gems/cache/merb-mailer-1.0.gem differ diff --git a/gems/cache/merb-more-1.0.gem b/gems/cache/merb-more-1.0.gem new file mode 100644 index 0000000..9a39578 Binary files /dev/null and b/gems/cache/merb-more-1.0.gem differ diff --git a/gems/cache/merb-param-protection-1.0.gem b/gems/cache/merb-param-protection-1.0.gem new file mode 100644 index 0000000..40307e9 Binary files /dev/null and b/gems/cache/merb-param-protection-1.0.gem differ diff --git a/gems/cache/merb-slices-1.0.gem b/gems/cache/merb-slices-1.0.gem new file mode 100644 index 0000000..460e1e2 Binary files /dev/null and b/gems/cache/merb-slices-1.0.gem differ diff --git a/gems/cache/merb_datamapper-1.0.gem b/gems/cache/merb_datamapper-1.0.gem new file mode 100644 index 0000000..8385ace Binary files /dev/null and b/gems/cache/merb_datamapper-1.0.gem differ diff --git a/gems/cache/mime-types-1.15.gem b/gems/cache/mime-types-1.15.gem new file mode 100644 index 0000000..a94304a Binary files /dev/null and b/gems/cache/mime-types-1.15.gem differ diff --git a/gems/cache/mongrel-1.1.5.gem b/gems/cache/mongrel-1.1.5.gem new file mode 100644 index 0000000..1db3a00 Binary files /dev/null and b/gems/cache/mongrel-1.1.5.gem differ diff --git a/gems/cache/nokogiri-1.0.6.gem b/gems/cache/nokogiri-1.0.6.gem new file mode 100644 index 0000000..9e4636d Binary files /dev/null and b/gems/cache/nokogiri-1.0.6.gem differ diff --git a/gems/cache/rack-0.4.0.gem b/gems/cache/rack-0.4.0.gem new file mode 100644 index 0000000..f81a322 Binary files /dev/null and b/gems/cache/rack-0.4.0.gem differ diff --git a/gems/cache/rake-0.8.3.gem b/gems/cache/rake-0.8.3.gem new file mode 100644 index 0000000..15b02ac Binary files /dev/null and b/gems/cache/rake-0.8.3.gem differ diff --git a/gems/cache/randexp-0.1.4.gem b/gems/cache/randexp-0.1.4.gem new file mode 100644 index 0000000..636d396 Binary files /dev/null and b/gems/cache/randexp-0.1.4.gem differ diff --git a/gems/cache/rspec-1.1.11.gem b/gems/cache/rspec-1.1.11.gem new file mode 100644 index 0000000..cc9c66f Binary files /dev/null and b/gems/cache/rspec-1.1.11.gem differ diff --git a/gems/cache/ruby-debug-0.10.2.gem b/gems/cache/ruby-debug-0.10.2.gem new file mode 100644 index 0000000..3637cc2 Binary files /dev/null and b/gems/cache/ruby-debug-0.10.2.gem differ diff --git a/gems/cache/ruby-debug-base-0.10.2.gem b/gems/cache/ruby-debug-base-0.10.2.gem new file mode 100644 index 0000000..3e3e576 Binary files /dev/null and b/gems/cache/ruby-debug-base-0.10.2.gem differ diff --git a/gems/cache/ruby2ruby-1.2.1.gem b/gems/cache/ruby2ruby-1.2.1.gem new file mode 100644 index 0000000..18566c7 Binary files /dev/null and b/gems/cache/ruby2ruby-1.2.1.gem differ diff --git a/gems/cache/sexp_processor-3.0.0.gem b/gems/cache/sexp_processor-3.0.0.gem new file mode 100644 index 0000000..9773da9 Binary files /dev/null and b/gems/cache/sexp_processor-3.0.0.gem differ diff --git a/gems/cache/templater-0.4.0.gem b/gems/cache/templater-0.4.0.gem new file mode 100644 index 0000000..265076f Binary files /dev/null and b/gems/cache/templater-0.4.0.gem differ diff --git a/gems/cache/thor-0.9.8.gem b/gems/cache/thor-0.9.8.gem new file mode 100644 index 0000000..70e4ed7 Binary files /dev/null and b/gems/cache/thor-0.9.8.gem differ diff --git a/gems/cache/uuidtools-1.0.4.gem b/gems/cache/uuidtools-1.0.4.gem new file mode 100644 index 0000000..b1c7bbc Binary files /dev/null and b/gems/cache/uuidtools-1.0.4.gem differ diff --git a/gems/cache/webrat-0.3.1.gem b/gems/cache/webrat-0.3.1.gem new file mode 100644 index 0000000..79221e6 Binary files /dev/null and b/gems/cache/webrat-0.3.1.gem differ diff --git a/gems/specifications/ParseTree-3.0.2.gemspec b/gems/specifications/ParseTree-3.0.2.gemspec new file mode 100644 index 0000000..3c736ec --- /dev/null +++ b/gems/specifications/ParseTree-3.0.2.gemspec @@ -0,0 +1,42 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{ParseTree} + s.version = "3.0.2" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Ryan Davis"] + s.date = %q{2008-11-04} + s.description = %q{ParseTree is a C extension (using RubyInline) that extracts the parse tree for an entire class or a specific method and returns it as a s-expression (aka sexp) using ruby's arrays, strings, symbols, and integers. As an example: def conditional1(arg1) if arg1 == 0 then return 1 end return 0 end becomes: [:defn, :conditional1, [:scope, [:block, [:args, :arg1], [:if, [:call, [:lvar, :arg1], :==, [:array, [:lit, 0]]], [:return, [:lit, 1]], nil], [:return, [:lit, 0]]]]]} + s.email = ["ryand-ruby@zenspider.com"] + s.executables = ["parse_tree_abc", "parse_tree_audit", "parse_tree_deps", "parse_tree_show"] + s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.txt"] + s.files = [".autotest", "History.txt", "Manifest.txt", "README.txt", "Rakefile", "bin/parse_tree_abc", "bin/parse_tree_audit", "bin/parse_tree_deps", "bin/parse_tree_show", "demo/printer.rb", "lib/parse_tree.rb", "lib/parse_tree_extensions.rb", "lib/unified_ruby.rb", "lib/unique.rb", "test/pt_testcase.rb", "test/something.rb", "test/test_all.rb", "test/test_parse_tree.rb", "test/test_parse_tree_extensions.rb", "test/test_unified_ruby.rb", "validate.sh"] + s.has_rdoc = true + s.homepage = %q{http://rubyforge.org/projects/parsetree/} + s.rdoc_options = ["--main", "README.txt"] + s.require_paths = ["lib", "test"] + s.rubyforge_project = %q{parsetree} + s.rubygems_version = %q{1.3.1} + s.summary = %q{ParseTree is a C extension (using RubyInline) that extracts the parse tree for an entire class or a specific method and returns it as a s-expression (aka sexp) using ruby's arrays, strings, symbols, and integers} + s.test_files = ["test/test_all.rb"] + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, [">= 3.7.0"]) + s.add_runtime_dependency(%q, [">= 3.0.0"]) + s.add_development_dependency(%q, [">= 1.8.0"]) + else + s.add_dependency(%q, [">= 3.7.0"]) + s.add_dependency(%q, [">= 3.0.0"]) + s.add_dependency(%q, [">= 1.8.0"]) + end + else + s.add_dependency(%q, [">= 3.7.0"]) + s.add_dependency(%q, [">= 3.0.0"]) + s.add_dependency(%q, [">= 1.8.0"]) + end +end diff --git a/gems/specifications/RubyInline-3.8.1.gemspec b/gems/specifications/RubyInline-3.8.1.gemspec new file mode 100644 index 0000000..200eb45 --- /dev/null +++ b/gems/specifications/RubyInline-3.8.1.gemspec @@ -0,0 +1,39 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{RubyInline} + s.version = "3.8.1" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Ryan Davis"] + s.date = %q{2008-10-24} + s.description = %q{Inline allows you to write foreign code within your ruby code. It automatically determines if the code in question has changed and builds it only when necessary. The extensions are then automatically loaded into the class/module that defines it. You can even write extra builders that will allow you to write inlined code in any language. Use Inline::C as a template and look at Module#inline for the required API.} + s.email = ["ryand-ruby@zenspider.com"] + s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.txt"] + s.files = ["History.txt", "Manifest.txt", "README.txt", "Rakefile", "demo/fastmath.rb", "demo/hello.rb", "example.rb", "example2.rb", "lib/inline.rb", "test/test_inline.rb", "tutorial/example1.rb", "tutorial/example2.rb"] + s.has_rdoc = true + s.homepage = %q{http://rubyforge.org/projects/rubyinline/} + s.rdoc_options = ["--main", "README.txt"] + s.require_paths = ["lib"] + s.requirements = ["A POSIX environment and a compiler for your language."] + s.rubyforge_project = %q{rubyinline} + s.rubygems_version = %q{1.3.1} + s.summary = %q{Inline allows you to write foreign code within your ruby code} + s.test_files = ["test/test_inline.rb"] + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, [">= 0"]) + s.add_development_dependency(%q, [">= 1.8.0"]) + else + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 1.8.0"]) + end + else + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 1.8.0"]) + end +end diff --git a/gems/specifications/ZenTest-3.11.0.gemspec b/gems/specifications/ZenTest-3.11.0.gemspec new file mode 100644 index 0000000..fbccfe4 --- /dev/null +++ b/gems/specifications/ZenTest-3.11.0.gemspec @@ -0,0 +1,36 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{ZenTest} + s.version = "3.11.0" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Ryan Davis", "Eric Hodel"] + s.date = %q{2008-10-21} + s.description = %q{ZenTest provides 4 different tools and 1 library: zentest, unit_diff, autotest, multiruby, and Test::Rails. ZenTest scans your target and unit-test code and writes your missing code based on simple naming rules, enabling XP at a much quicker pace. ZenTest only works with Ruby and Test::Unit. unit_diff is a command-line filter to diff expected results from actual results and allow you to quickly see exactly what is wrong. autotest is a continous testing facility meant to be used during development. As soon as you save a file, autotest will run the corresponding dependent tests. multiruby runs anything you want on multiple versions of ruby. Great for compatibility checking! Use multiruby_setup to manage your installed versions. Test::Rails helps you build industrial-strength Rails code.} + s.email = ["ryand-ruby@zenspider.com", "drbrain@segment7.net"] + s.executables = ["autotest", "multiruby", "multiruby_setup", "rails_test_audit", "unit_diff", "zentest"] + s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.txt", "articles/how_to_use_zentest.txt", "example.txt"] + s.files = ["History.txt", "Manifest.txt", "README.txt", "Rakefile", "articles/Article.css", "articles/getting_started_with_autotest.html", "articles/how_to_use_zentest.txt", "bin/autotest", "bin/multiruby", "bin/multiruby_setup", "bin/rails_test_audit", "bin/unit_diff", "bin/zentest", "example.txt", "example1.rb", "example2.rb", "example_dot_autotest.rb", "lib/autotest.rb", "lib/autotest/autoupdate.rb", "lib/autotest/camping.rb", "lib/autotest/cctray.rb", "lib/autotest/discover.rb", "lib/autotest/emacs.rb", "lib/autotest/email_notify.rb", "lib/autotest/fixtures.rb", "lib/autotest/growl.rb", "lib/autotest/heckle.rb", "lib/autotest/html_report.rb", "lib/autotest/jabber_notify.rb", "lib/autotest/kdenotify.rb", "lib/autotest/menu.rb", "lib/autotest/migrate.rb", "lib/autotest/notify.rb", "lib/autotest/once.rb", "lib/autotest/pretty.rb", "lib/autotest/rails.rb", "lib/autotest/rcov.rb", "lib/autotest/redgreen.rb", "lib/autotest/restart.rb", "lib/autotest/screen.rb", "lib/autotest/shame.rb", "lib/autotest/snarl.rb", "lib/autotest/timestamp.rb", "lib/functional_test_matrix.rb", "lib/multiruby.rb", "lib/test/rails.rb", "lib/test/rails/controller_test_case.rb", "lib/test/rails/functional_test_case.rb", "lib/test/rails/helper_test_case.rb", "lib/test/rails/ivar_proxy.rb", "lib/test/rails/pp_html_document.rb", "lib/test/rails/rake_tasks.rb", "lib/test/rails/render_tree.rb", "lib/test/rails/test_case.rb", "lib/test/rails/view_test_case.rb", "lib/test/zentest_assertions.rb", "lib/unit_diff.rb", "lib/zentest.rb", "lib/zentest_mapping.rb", "test/test_autotest.rb", "test/test_help.rb", "test/test_rails_autotest.rb", "test/test_rails_controller_test_case.rb", "test/test_rails_helper_test_case.rb", "test/test_rails_view_test_case.rb", "test/test_unit_diff.rb", "test/test_zentest.rb", "test/test_zentest_assertions.rb", "test/test_zentest_mapping.rb"] + s.has_rdoc = true + s.homepage = %q{http://www.zenspider.com/ZSS/Products/ZenTest/} + s.rdoc_options = ["--main", "README.txt"] + s.require_paths = ["lib"] + s.rubyforge_project = %q{zentest} + s.rubygems_version = %q{1.3.1} + s.summary = %q{ZenTest provides 4 different tools and 1 library: zentest, unit_diff, autotest, multiruby, and Test::Rails} + s.test_files = ["test/test_autotest.rb", "test/test_help.rb", "test/test_rails_autotest.rb", "test/test_rails_controller_test_case.rb", "test/test_rails_helper_test_case.rb", "test/test_rails_view_test_case.rb", "test/test_unit_diff.rb", "test/test_zentest.rb", "test/test_zentest_assertions.rb", "test/test_zentest_mapping.rb"] + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_development_dependency(%q, [">= 1.8.0"]) + else + s.add_dependency(%q, [">= 1.8.0"]) + end + else + s.add_dependency(%q, [">= 1.8.0"]) + end +end diff --git a/gems/specifications/abstract-1.0.0.gemspec b/gems/specifications/abstract-1.0.0.gemspec new file mode 100644 index 0000000..b4d6fca --- /dev/null +++ b/gems/specifications/abstract-1.0.0.gemspec @@ -0,0 +1,29 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{abstract} + s.version = "1.0.0" + + s.required_rubygems_version = nil if s.respond_to? :required_rubygems_version= + s.authors = ["makoto kuwata"] + s.cert_chain = nil + s.date = %q{2006-03-12} + s.description = %q{'abstract.rb' is a library which enable you to define abstract method in Ruby.} + s.files = ["lib/abstract.rb", "test/test.rb", "README.txt", "ChangeLog", "setup.rb", "abstract.gemspec"] + s.homepage = %q{http://rubyforge.org/projects/abstract} + s.require_paths = ["lib"] + s.required_ruby_version = Gem::Requirement.new("> 0.0.0") + s.rubygems_version = %q{1.3.1} + s.summary = %q{a library which enable you to define abstract method in Ruby} + s.test_files = ["test/test.rb"] + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 1 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + else + end + else + end +end diff --git a/gems/specifications/addressable-1.0.4.gemspec b/gems/specifications/addressable-1.0.4.gemspec new file mode 100644 index 0000000..c731417 --- /dev/null +++ b/gems/specifications/addressable-1.0.4.gemspec @@ -0,0 +1,37 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{addressable} + s.version = "1.0.4" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Bob Aman"] + s.date = %q{2008-05-02} + s.description = %q{Addressable is a replacement for the URI implementation that is part of Ruby's standard library. It more closely conforms to the relevant RFCs and adds support for IRIs and URI templates.} + s.email = %q{bob@sporkmonger.com} + s.extra_rdoc_files = ["README"] + s.files = ["lib/addressable", "lib/addressable/uri.rb", "lib/addressable/version.rb", "spec/addressable", "spec/addressable/uri_spec.rb", "spec/data", "spec/data/rfc3986.txt", "coverage/-Library-Ruby-Gems-1_8-gems-rcov-0_8_1_2_0-lib-rcov_rb.html", "coverage/-Library-Ruby-Gems-1_8-gems-rspec-1_1_3-bin-spec.html", "coverage/-Library-Ruby-Gems-1_8-gems-rspec-1_1_3-lib-spec_rb.html", "coverage/-Library-Ruby-Gems-1_8-gems-rspec-1_1_3-plugins-mock_frameworks-rspec_rb.html", "coverage/index.html", "coverage/lib-addressable-uri_rb.html", "coverage/lib-addressable-version_rb.html", "CHANGELOG", "LICENSE", "README", "rakefile"] + s.has_rdoc = true + s.homepage = %q{http://sporkmonger.com/} + s.rdoc_options = ["--main", "README"] + s.require_paths = ["lib"] + s.rubyforge_project = %q{addressable} + s.rubygems_version = %q{1.3.1} + s.summary = %q{URI Implementation} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, [">= 0.7.3"]) + s.add_runtime_dependency(%q, [">= 1.0.8"]) + else + s.add_dependency(%q, [">= 0.7.3"]) + s.add_dependency(%q, [">= 1.0.8"]) + end + else + s.add_dependency(%q, [">= 0.7.3"]) + s.add_dependency(%q, [">= 1.0.8"]) + end +end diff --git a/gems/specifications/cgi_multipart_eof_fix-2.5.0.gemspec b/gems/specifications/cgi_multipart_eof_fix-2.5.0.gemspec new file mode 100644 index 0000000..38f5fdd --- /dev/null +++ b/gems/specifications/cgi_multipart_eof_fix-2.5.0.gemspec @@ -0,0 +1,31 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{cgi_multipart_eof_fix} + s.version = "2.5.0" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Evan Weaver"] + s.cert_chain = ["-----BEGIN CERTIFICATE-----\nMIIDUDCCAjigAwIBAgIBADANBgkqhkiG9w0BAQUFADBOMRwwGgYDVQQDDBNtb25n\ncmVsLWRldmVsb3BtZW50MRkwFwYKCZImiZPyLGQBGRYJcnVieWZvcmdlMRMwEQYK\nCZImiZPyLGQBGRYDb3JnMB4XDTA3MDkxNjEwMzI0OVoXDTA4MDkxNTEwMzI0OVow\nTjEcMBoGA1UEAwwTbW9uZ3JlbC1kZXZlbG9wbWVudDEZMBcGCgmSJomT8ixkARkW\nCXJ1Ynlmb3JnZTETMBEGCgmSJomT8ixkARkWA29yZzCCASIwDQYJKoZIhvcNAQEB\nBQADggEPADCCAQoCggEBAMb9v3B01eOHk3FyypbQgKXzJplUE5P6dXoG+xpPm0Lv\nP7BQmeMncOwqQ7zXpVQU+lTpXtQFTsOE3vL7KnhQFJKGvUAkbh24VFyopu1I0yqF\nmGu4nRqNXGXVj8TvLSj4S1WpSRLAa0acLPNyKhGmoV9+crqQypSjM6XKjBeppifo\n4eBmWGjiJEYMIJBvJZPJ4rAVDDA8C6CM1m3gMBGNh8ELDhU8HI9AP3dMIkTI2Wx9\n9xkJwHdroAaS0IFFtYChrwee4FbCF1FHDgoTosMwa47DrLHg4hZ6ojaKwK5QVWEV\nXGb6ju5UqpktnSWF2W+Lvl/K0tI42OH2CAhebT1gEVUCAwEAAaM5MDcwCQYDVR0T\nBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0OBBYEFGHChyMSZ16u9WOzKhgJSQ9lqDc5\nMA0GCSqGSIb3DQEBBQUAA4IBAQA/lfeN2WdB1xN+82tT7vNS4HOjRQw6MUh5yktu\nGQjaGqm0UB+aX0Z9y0B0qpfv9rj7nmIvEGiwBmDepNWYCGuW15JyqpN7QVVnG2xS\nMrame7VqgjM7A+VGDD5In5LtWbM/CHAATvvFlQ5Ph13YE1EdnVbZ65c+KQv+5sFY\nQ+zEop74d878uaC/SAHHXS46TiXneocaLSYw1CEZs/MAIy+9c4Q5ESbGpgnfg1Ad\n6lwl7k3hsNHO/+tZzx4HJtOXDI1yAl3+q6T9J0yI3z97EinwvAKhS1eyOI2Y5eeT\ntbQaNYkU127B3l/VNpd8fQm3Jkl/PqCCmDBQjUszFrJEODug\n-----END CERTIFICATE-----\n", "-----BEGIN CERTIFICATE-----\nMIIDPzCCAiegAwIBAgIBADANBgkqhkiG9w0BAQUFADBOMRwwGgYDVQQDDBNtb25n\ncmVsLWRldmVsb3BtZW50MRkwFwYKCZImiZPyLGQBGRYJcnVieWZvcmdlMRMwEQYK\nCZImiZPyLGQBGRYDb3JnMB4XDTA3MDkxNjEwMzMwMFoXDTA4MDkxNTEwMzMwMFow\nPTENMAsGA1UEAwwEZXZhbjEYMBYGCgmSJomT8ixkARkWCGNsb3VkYnVyMRIwEAYK\nCZImiZPyLGQBGRYCc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDk\nLQijz2fICmev4+9s0WB71WzJFYCUYFQQxqGlenbxWut9dlPSsBbskGjg+UITeOXi\ncTh3MTqAB0i1LJyNOiyvDsAivn7GjKXhVvflp2/npMhBBe83P4HOWqeQBjkk3QJI\nFFNBvqbFLeEXIP+HiqAOiyNHZEVXMepLEJLzGrg3Ly7M7A6L5fK7jDrt8jkm+c+8\nzGquVHV5ohAebGd/vpHMLjpA7lCG5+MBgYZd33rRfNtCxDJMNRgnOu9PsB05+LJn\nMpDKQq3x0SkOf5A+MVOcadNCaAkFflYk3SUcXaXWxu/eCHgqfW1m76RNSp5djpKE\nCgNPK9lGIWpB3CHzDaVNAgMBAAGjOTA3MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSw\nMB0GA1UdDgQWBBT5aonPfFBdJ5rWFG+8dZwgyB54LjANBgkqhkiG9w0BAQUFAAOC\nAQEAiKbzWgMcvZs/TPwJxr8tJ+7mSGz7+zDkWcbBl8FpQq1DtRcATh1oyTkQT7t+\nrFEBYMmb0FxbbUnojQp8hIFgFkUwFpStwWBL/okLSehntzI2iwjuEtfj4ac9Q3Y2\nuSdbmZqsQTuu+lEUc5C4qLK7YKwToaul+cx7vWxyk1YendcVwRlFLIBqA5cPrwo3\nyyGLTHlRYn2c9PSbM1B63Yg+LqSSAa4QSU3Wv9pNdffVpvwHPVEQpO7ZDo5slQFL\nGf6+gbD/eZAvhpvmn8JlXb+LxKaFVMs2Yvrk1xOuT76SsPjEGWxkr7jZCIpsYfgQ\nALN3mi/9z0Mf1YroliUgF0v5Yw==\n-----END CERTIFICATE-----\n"] + s.date = %q{2007-10-25} + s.description = %q{Fix an exploitable bug in CGI multipart parsing.} + s.email = %q{} + s.files = ["CHANGELOG", "lib/cgi_multipart_eof_fix.rb", "LICENSE", "Manifest", "README", "test/test_cgi_multipart_eof_fix.rb", "cgi_multipart_eof_fix.gemspec"] + s.has_rdoc = true + s.homepage = %q{http://blog.evanweaver.com/pages/code#cgi_multipart_eof_fix} + s.require_paths = ["lib"] + s.rubyforge_project = %q{mongrel} + s.rubygems_version = %q{1.3.1} + s.summary = %q{Fix an exploitable bug in CGI multipart parsing.} + s.test_files = ["test/test_cgi_multipart_eof_fix.rb"] + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + else + end + else + end +end diff --git a/gems/specifications/columnize-0.1.gemspec b/gems/specifications/columnize-0.1.gemspec new file mode 100644 index 0000000..255f4c9 --- /dev/null +++ b/gems/specifications/columnize-0.1.gemspec @@ -0,0 +1,32 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{columnize} + s.version = "0.1" + + s.required_rubygems_version = nil if s.respond_to? :required_rubygems_version= + s.authors = ["R. Bernstein"] + s.cert_chain = nil + s.date = %q{2007-12-08} + s.description = %q{Columnize is a module for reading and caching lines. This may be useful for example in a debugger where the same lines are shown many times.} + s.email = %q{rockyb@rubyforge.net} + s.extra_rdoc_files = ["README", "lib/columnize.rb"] + s.files = ["AUTHORS", "COPYING", "ChangeLog", "NEWS", "README", "Rakefile", "VERSION", "lib/columnize.rb", "test/test-columnize.rb"] + s.has_rdoc = true + s.homepage = %q{http://rubyforge.org/projects/rocky-hacks/columnize} + s.require_paths = ["lib"] + s.required_ruby_version = Gem::Requirement.new(">= 1.8.2") + s.rubyforge_project = %q{rocky-hacks} + s.rubygems_version = %q{1.3.1} + s.summary = %q{Read file with caching} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 1 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + else + end + else + end +end diff --git a/gems/specifications/daemons-1.0.10.gemspec b/gems/specifications/daemons-1.0.10.gemspec new file mode 100644 index 0000000..3cb3a31 --- /dev/null +++ b/gems/specifications/daemons-1.0.10.gemspec @@ -0,0 +1,31 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{daemons} + s.version = "1.0.10" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Thomas Uehlinger"] + s.autorequire = %q{daemons} + s.date = %q{2008-03-20} + s.description = %q{Daemons provides an easy way to wrap existing ruby scripts (for example a self-written server) to be run as a daemon and to be controlled by simple start/stop/restart commands. You can also call blocks as daemons and control them from the parent or just daemonize the current process. Besides this basic functionality, daemons offers many advanced features like exception backtracing and logging (in case your ruby script crashes) and monitoring and automatic restarting of your processes if they crash.} + s.email = %q{th.uehlinger@gmx.ch} + s.extra_rdoc_files = ["README", "Releases", "TODO"] + s.files = ["Rakefile", "Releases", "TODO", "README", "LICENSE", "setup.rb", "lib/daemons/application.rb", "lib/daemons/application_group.rb", "lib/daemons/cmdline.rb", "lib/daemons/controller.rb", "lib/daemons/daemonize.rb", "lib/daemons/exceptions.rb", "lib/daemons/monitor.rb", "lib/daemons/pid.rb", "lib/daemons/pidfile.rb", "lib/daemons/pidmem.rb", "lib/daemons.rb", "examples/call", "examples/call/call.rb", "examples/call/call_monitor.rb", "examples/daemonize", "examples/daemonize/daemonize.rb", "examples/run", "examples/run/ctrl_crash.rb", "examples/run/ctrl_exec.rb", "examples/run/ctrl_exit.rb", "examples/run/ctrl_keep_pid_files.rb", "examples/run/ctrl_monitor.rb", "examples/run/ctrl_multiple.rb", "examples/run/ctrl_normal.rb", "examples/run/ctrl_ontop.rb", "examples/run/ctrl_optionparser.rb", "examples/run/ctrl_proc.rb", "examples/run/ctrl_proc.rb.output", "examples/run/ctrl_proc_multiple.rb", "examples/run/ctrl_proc_multiple.rb.output", "examples/run/ctrl_proc_simple.rb", "examples/run/myserver.rb", "examples/run/myserver_crashing.rb", "examples/run/myserver_crashing.rb.output", "examples/run/myserver_exiting.rb"] + s.has_rdoc = true + s.homepage = %q{http://daemons.rubyforge.org} + s.require_paths = ["lib"] + s.rubyforge_project = %q{daemons} + s.rubygems_version = %q{1.3.1} + s.summary = %q{A toolkit to create and control daemons in different ways} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + else + end + else + end +end diff --git a/gems/specifications/data_objects-0.9.6.gemspec b/gems/specifications/data_objects-0.9.6.gemspec new file mode 100644 index 0000000..ab98a2e --- /dev/null +++ b/gems/specifications/data_objects-0.9.6.gemspec @@ -0,0 +1,40 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{data_objects} + s.version = "0.9.6" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Yehuda Katz"] + s.date = %q{2008-10-11} + s.description = %q{The Core DataObjects class} + s.email = ["wycats@gmail.com"] + s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.txt"] + s.files = ["History.txt", "LICENSE", "Manifest.txt", "README.txt", "Rakefile", "TODO", "lib/data_objects.rb", "lib/data_objects/command.rb", "lib/data_objects/connection.rb", "lib/data_objects/field.rb", "lib/data_objects/logger.rb", "lib/data_objects/quoting.rb", "lib/data_objects/reader.rb", "lib/data_objects/result.rb", "lib/data_objects/support/pooling.rb", "lib/data_objects/transaction.rb", "lib/data_objects/uri.rb", "lib/data_objects/version.rb", "spec/command_spec.rb", "spec/connection_spec.rb", "spec/dataobjects_spec.rb", "spec/do_mock.rb", "spec/reader_spec.rb", "spec/result_spec.rb", "spec/spec.opts", "spec/spec_helper.rb", "spec/support/pooling_spec.rb", "spec/transaction_spec.rb"] + s.has_rdoc = true + s.homepage = %q{http://rubyforge.org/projects/dorb} + s.rdoc_options = ["--main", "README.txt"] + s.require_paths = ["lib"] + s.rubyforge_project = %q{dorb} + s.rubygems_version = %q{1.3.1} + s.summary = %q{The Core DataObjects class} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, [">= 1.0.3"]) + s.add_runtime_dependency(%q, [">= 0.9.5"]) + s.add_development_dependency(%q, [">= 1.7.0"]) + else + s.add_dependency(%q, [">= 1.0.3"]) + s.add_dependency(%q, [">= 0.9.5"]) + s.add_dependency(%q, [">= 1.7.0"]) + end + else + s.add_dependency(%q, [">= 1.0.3"]) + s.add_dependency(%q, [">= 0.9.5"]) + s.add_dependency(%q, [">= 1.7.0"]) + end +end diff --git a/gems/specifications/diff-lcs-1.1.2.gemspec b/gems/specifications/diff-lcs-1.1.2.gemspec new file mode 100644 index 0000000..30af541 --- /dev/null +++ b/gems/specifications/diff-lcs-1.1.2.gemspec @@ -0,0 +1,35 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{diff-lcs} + s.version = "1.1.2" + + s.required_rubygems_version = nil if s.respond_to? :required_rubygems_version= + s.autorequire = %q{diff/lcs} + s.cert_chain = nil + s.date = %q{2004-10-20} + s.description = %q{Diff::LCS is a port of Algorithm::Diff that uses the McIlroy-Hunt longest common subsequence (LCS) algorithm to compute intelligent differences between two sequenced enumerable containers. The implementation is based on Mario I. Wolczko's Smalltalk version (1.2, 1993) and Ned Konz's Perl version (Algorithm::Diff).} + s.email = %q{diff-lcs@halostatue.ca} + s.executables = ["ldiff", "htmldiff"] + s.extra_rdoc_files = ["README", "ChangeLog", "Install"] + s.files = ["bin", "ChangeLog", "Install", "lib", "Rakefile", "README", "tests", "bin/htmldiff", "bin/ldiff", "lib/diff", "lib/diff/lcs", "lib/diff/lcs.rb", "lib/diff/lcs/array.rb", "lib/diff/lcs/block.rb", "lib/diff/lcs/callbacks.rb", "lib/diff/lcs/change.rb", "lib/diff/lcs/hunk.rb", "lib/diff/lcs/ldiff.rb", "lib/diff/lcs/string.rb", "tests/00test.rb"] + s.has_rdoc = true + s.homepage = %q{http://rubyforge.org/projects/ruwiki/} + s.rdoc_options = ["--title", "Diff::LCS -- A Diff Algorithm", "--main", "README", "--line-numbers"] + s.require_paths = ["lib"] + s.required_ruby_version = Gem::Requirement.new(">= 1.8.1") + s.rubyforge_project = %q{ruwiki} + s.rubygems_version = %q{1.3.1} + s.summary = %q{Provides a list of changes that represent the difference between two sequenced collections.} + s.test_files = ["tests/00test.rb"] + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 1 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + else + end + else + end +end diff --git a/gems/specifications/dm-aggregates-0.9.6.gemspec b/gems/specifications/dm-aggregates-0.9.6.gemspec new file mode 100644 index 0000000..40af83e --- /dev/null +++ b/gems/specifications/dm-aggregates-0.9.6.gemspec @@ -0,0 +1,37 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{dm-aggregates} + s.version = "0.9.6" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Foy Savas"] + s.date = %q{2008-10-11} + s.description = %q{DataMapper plugin providing support for aggregates, functions on collections and datasets} + s.email = ["foysavas@gmail.com"] + s.extra_rdoc_files = ["README.txt", "LICENSE", "TODO"] + s.files = ["History.txt", "LICENSE", "Manifest.txt", "README.txt", "Rakefile", "TODO", "lib/dm-aggregates.rb", "lib/dm-aggregates/adapters/data_objects_adapter.rb", "lib/dm-aggregates/aggregate_functions.rb", "lib/dm-aggregates/collection.rb", "lib/dm-aggregates/model.rb", "lib/dm-aggregates/repository.rb", "lib/dm-aggregates/support/symbol.rb", "lib/dm-aggregates/version.rb", "spec/integration/aggregates_spec.rb", "spec/spec.opts", "spec/spec_helper.rb"] + s.has_rdoc = true + s.homepage = %q{http://github.com/sam/dm-more/tree/master/dm-aggregates} + s.rdoc_options = ["--main", "README.txt"] + s.require_paths = ["lib"] + s.rubyforge_project = %q{datamapper} + s.rubygems_version = %q{1.3.1} + s.summary = %q{DataMapper plugin providing support for aggregates, functions on collections and datasets} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, ["= 0.9.6"]) + s.add_development_dependency(%q, [">= 1.7.0"]) + else + s.add_dependency(%q, ["= 0.9.6"]) + s.add_dependency(%q, [">= 1.7.0"]) + end + else + s.add_dependency(%q, ["= 0.9.6"]) + s.add_dependency(%q, [">= 1.7.0"]) + end +end diff --git a/gems/specifications/dm-core-0.9.6.gemspec b/gems/specifications/dm-core-0.9.6.gemspec new file mode 100644 index 0000000..5b7f032 --- /dev/null +++ b/gems/specifications/dm-core-0.9.6.gemspec @@ -0,0 +1,43 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{dm-core} + s.version = "0.9.6" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Sam Smoot"] + s.date = %q{2008-10-11} + s.description = %q{Faster, Better, Simpler.} + s.email = ["ssmoot@gmail.com"] + s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.txt"] + s.files = [".autotest", "CONTRIBUTING", "FAQ", "History.txt", "MIT-LICENSE", "Manifest.txt", "QUICKLINKS", "README.txt", "Rakefile", "SPECS", "TODO", "lib/dm-core.rb", "lib/dm-core/adapters.rb", "lib/dm-core/adapters/abstract_adapter.rb", "lib/dm-core/adapters/data_objects_adapter.rb", "lib/dm-core/adapters/in_memory_adapter.rb", "lib/dm-core/adapters/mysql_adapter.rb", "lib/dm-core/adapters/postgres_adapter.rb", "lib/dm-core/adapters/sqlite3_adapter.rb", "lib/dm-core/associations.rb", "lib/dm-core/associations/many_to_many.rb", "lib/dm-core/associations/many_to_one.rb", "lib/dm-core/associations/one_to_many.rb", "lib/dm-core/associations/one_to_one.rb", "lib/dm-core/associations/relationship.rb", "lib/dm-core/associations/relationship_chain.rb", "lib/dm-core/auto_migrations.rb", "lib/dm-core/collection.rb", "lib/dm-core/dependency_queue.rb", "lib/dm-core/hook.rb", "lib/dm-core/identity_map.rb", "lib/dm-core/is.rb", "lib/dm-core/logger.rb", "lib/dm-core/migrations/destructive_migrations.rb", "lib/dm-core/migrator.rb", "lib/dm-core/model.rb", "lib/dm-core/naming_conventions.rb", "lib/dm-core/property.rb", "lib/dm-core/property_set.rb", "lib/dm-core/query.rb", "lib/dm-core/repository.rb", "lib/dm-core/resource.rb", "lib/dm-core/scope.rb", "lib/dm-core/support.rb", "lib/dm-core/support/array.rb", "lib/dm-core/support/assertions.rb", "lib/dm-core/support/errors.rb", "lib/dm-core/support/kernel.rb", "lib/dm-core/support/symbol.rb", "lib/dm-core/transaction.rb", "lib/dm-core/type.rb", "lib/dm-core/type_map.rb", "lib/dm-core/types.rb", "lib/dm-core/types/boolean.rb", "lib/dm-core/types/discriminator.rb", "lib/dm-core/types/object.rb", "lib/dm-core/types/paranoid_boolean.rb", "lib/dm-core/types/paranoid_datetime.rb", "lib/dm-core/types/serial.rb", "lib/dm-core/types/text.rb", "lib/dm-core/version.rb", "script/all", "script/performance.rb", "script/profile.rb", "spec/integration/association_spec.rb", "spec/integration/association_through_spec.rb", "spec/integration/associations/many_to_many_spec.rb", "spec/integration/associations/many_to_one_spec.rb", "spec/integration/associations/one_to_many_spec.rb", "spec/integration/auto_migrations_spec.rb", "spec/integration/collection_spec.rb", "spec/integration/data_objects_adapter_spec.rb", "spec/integration/dependency_queue_spec.rb", "spec/integration/model_spec.rb", "spec/integration/mysql_adapter_spec.rb", "spec/integration/postgres_adapter_spec.rb", "spec/integration/property_spec.rb", "spec/integration/query_spec.rb", "spec/integration/repository_spec.rb", "spec/integration/resource_spec.rb", "spec/integration/sqlite3_adapter_spec.rb", "spec/integration/sti_spec.rb", "spec/integration/strategic_eager_loading_spec.rb", "spec/integration/transaction_spec.rb", "spec/integration/type_spec.rb", "spec/lib/logging_helper.rb", "spec/lib/mock_adapter.rb", "spec/lib/model_loader.rb", "spec/lib/publicize_methods.rb", "spec/models/content.rb", "spec/models/vehicles.rb", "spec/models/zoo.rb", "spec/spec.opts", "spec/spec_helper.rb", "spec/unit/adapters/abstract_adapter_spec.rb", "spec/unit/adapters/adapter_shared_spec.rb", "spec/unit/adapters/data_objects_adapter_spec.rb", "spec/unit/adapters/in_memory_adapter_spec.rb", "spec/unit/adapters/postgres_adapter_spec.rb", "spec/unit/associations/many_to_many_spec.rb", "spec/unit/associations/many_to_one_spec.rb", "spec/unit/associations/one_to_many_spec.rb", "spec/unit/associations/one_to_one_spec.rb", "spec/unit/associations/relationship_spec.rb", "spec/unit/associations_spec.rb", "spec/unit/auto_migrations_spec.rb", "spec/unit/collection_spec.rb", "spec/unit/data_mapper_spec.rb", "spec/unit/identity_map_spec.rb", "spec/unit/is_spec.rb", "spec/unit/migrator_spec.rb", "spec/unit/model_spec.rb", "spec/unit/naming_conventions_spec.rb", "spec/unit/property_set_spec.rb", "spec/unit/property_spec.rb", "spec/unit/query_spec.rb", "spec/unit/repository_spec.rb", "spec/unit/resource_spec.rb", "spec/unit/scope_spec.rb", "spec/unit/transaction_spec.rb", "spec/unit/type_map_spec.rb", "spec/unit/type_spec.rb", "tasks/ci.rb", "tasks/dm.rb", "tasks/doc.rb", "tasks/gemspec.rb", "tasks/hoe.rb", "tasks/install.rb"] + s.has_rdoc = true + s.homepage = %q{http://datamapper.org} + s.rdoc_options = ["--main", "README.txt"] + s.require_paths = ["lib"] + s.rubyforge_project = %q{datamapper} + s.rubygems_version = %q{1.3.1} + s.summary = %q{An Object/Relational Mapper for Ruby} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, [">= 0.9.5"]) + s.add_runtime_dependency(%q, [">= 0.9.5"]) + s.add_runtime_dependency(%q, [">= 1.1.3"]) + s.add_runtime_dependency(%q, [">= 1.0.4"]) + else + s.add_dependency(%q, [">= 0.9.5"]) + s.add_dependency(%q, [">= 0.9.5"]) + s.add_dependency(%q, [">= 1.1.3"]) + s.add_dependency(%q, [">= 1.0.4"]) + end + else + s.add_dependency(%q, [">= 0.9.5"]) + s.add_dependency(%q, [">= 0.9.5"]) + s.add_dependency(%q, [">= 1.1.3"]) + s.add_dependency(%q, [">= 1.0.4"]) + end +end diff --git a/gems/specifications/dm-migrations-0.9.6.gemspec b/gems/specifications/dm-migrations-0.9.6.gemspec new file mode 100644 index 0000000..c8564db --- /dev/null +++ b/gems/specifications/dm-migrations-0.9.6.gemspec @@ -0,0 +1,37 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{dm-migrations} + s.version = "0.9.6" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Paul Sadauskas"] + s.date = %q{2008-10-11} + s.description = %q{DataMapper plugin for writing and speccing migrations} + s.email = ["psadauskas@gmail.com"] + s.extra_rdoc_files = ["README.txt", "LICENSE", "TODO"] + s.files = ["History.txt", "LICENSE", "Manifest.txt", "README.txt", "Rakefile", "TODO", "db/migrations/1_create_people_table.rb", "db/migrations/2_add_dob_to_people.rb", "db/migrations/config.rb", "examples/sample_migration.rb", "examples/sample_migration_spec.rb", "lib/dm-migrations.rb", "lib/dm-migrations/version.rb", "lib/migration.rb", "lib/migration_runner.rb", "lib/spec/example/migration_example_group.rb", "lib/spec/matchers/migration_matchers.rb", "lib/sql.rb", "lib/sql/column.rb", "lib/sql/mysql.rb", "lib/sql/postgresql.rb", "lib/sql/sqlite3.rb", "lib/sql/table.rb", "lib/sql/table_creator.rb", "lib/sql/table_modifier.rb", "spec/integration/migration_runner_spec.rb", "spec/integration/migration_spec.rb", "spec/integration/sql_spec.rb", "spec/spec.opts", "spec/spec_helper.rb", "spec/unit/migration_spec.rb", "spec/unit/sql/column_spec.rb", "spec/unit/sql/postgresql_spec.rb", "spec/unit/sql/sqlite3_extensions_spec.rb", "spec/unit/sql/table_creator_spec.rb", "spec/unit/sql/table_modifier_spec.rb", "spec/unit/sql/table_spec.rb", "spec/unit/sql_spec.rb"] + s.has_rdoc = true + s.homepage = %q{http://github.com/sam/dm-more/tree/master/dm-migrations} + s.rdoc_options = ["--main", "README.txt"] + s.require_paths = ["lib"] + s.rubyforge_project = %q{datamapper} + s.rubygems_version = %q{1.3.1} + s.summary = %q{DataMapper plugin for writing and speccing migrations} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, ["> 0.9.5"]) + s.add_development_dependency(%q, [">= 1.7.0"]) + else + s.add_dependency(%q, ["> 0.9.5"]) + s.add_dependency(%q, [">= 1.7.0"]) + end + else + s.add_dependency(%q, ["> 0.9.5"]) + s.add_dependency(%q, [">= 1.7.0"]) + end +end diff --git a/gems/specifications/dm-sweatshop-0.9.6.gemspec b/gems/specifications/dm-sweatshop-0.9.6.gemspec new file mode 100644 index 0000000..c462949 --- /dev/null +++ b/gems/specifications/dm-sweatshop-0.9.6.gemspec @@ -0,0 +1,40 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{dm-sweatshop} + s.version = "0.9.6" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Ben Burkert"] + s.date = %q{2008-10-11} + s.description = %q{DataMapper plugin for building pseudo random models} + s.email = ["ben@benburkert.com"] + s.extra_rdoc_files = ["README.textile", "LICENSE", "TODO"] + s.files = ["History.txt", "LICENSE", "Manifest.txt", "README.textile", "Rakefile", "TODO", "lib/dm-sweatshop.rb", "lib/dm-sweatshop/sweatshop.rb", "lib/dm-sweatshop/model.rb", "lib/dm-sweatshop/version.rb", "spec/dm-sweatshop/model_spec.rb", "spec/dm-sweatshop/sweatshop_spec.rb", "spec/spec.opts", "spec/spec_helper.rb"] + s.has_rdoc = true + s.homepage = %q{http://github.com/sam/dm-more/tree/master/dm-Sweatshop} + s.rdoc_options = ["--main", "README.txt"] + s.require_paths = ["lib"] + s.rubyforge_project = %q{datamapper} + s.rubygems_version = %q{1.3.1} + s.summary = %q{DataMapper plugin for building pseudo random models} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, ["= 0.9.6"]) + s.add_runtime_dependency(%q, [">= 0"]) + s.add_development_dependency(%q, [">= 1.7.0"]) + else + s.add_dependency(%q, ["= 0.9.6"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 1.7.0"]) + end + else + s.add_dependency(%q, ["= 0.9.6"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 1.7.0"]) + end +end diff --git a/gems/specifications/dm-timestamps-0.9.6.gemspec b/gems/specifications/dm-timestamps-0.9.6.gemspec new file mode 100644 index 0000000..0287251 --- /dev/null +++ b/gems/specifications/dm-timestamps-0.9.6.gemspec @@ -0,0 +1,37 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{dm-timestamps} + s.version = "0.9.6" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Foy Savas"] + s.date = %q{2008-10-11} + s.description = %q{DataMapper plugin for magical timestamps} + s.email = ["foysavas@gmail.com"] + s.extra_rdoc_files = ["README.txt", "LICENSE", "TODO"] + s.files = ["History.txt", "LICENSE", "Manifest.txt", "README.txt", "Rakefile", "TODO", "lib/dm-timestamps.rb", "lib/dm-timestamps/version.rb", "spec/integration/timestamps_spec.rb", "spec/spec.opts", "spec/spec_helper.rb"] + s.has_rdoc = true + s.homepage = %q{http://github.com/sam/dm-more/tree/master/dm-timestamps} + s.rdoc_options = ["--main", "README.txt"] + s.require_paths = ["lib"] + s.rubyforge_project = %q{datamapper} + s.rubygems_version = %q{1.3.1} + s.summary = %q{DataMapper plugin for magical timestamps} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, ["= 0.9.6"]) + s.add_development_dependency(%q, [">= 1.7.0"]) + else + s.add_dependency(%q, ["= 0.9.6"]) + s.add_dependency(%q, [">= 1.7.0"]) + end + else + s.add_dependency(%q, ["= 0.9.6"]) + s.add_dependency(%q, [">= 1.7.0"]) + end +end diff --git a/gems/specifications/dm-types-0.9.6.gemspec b/gems/specifications/dm-types-0.9.6.gemspec new file mode 100644 index 0000000..73a9b10 --- /dev/null +++ b/gems/specifications/dm-types-0.9.6.gemspec @@ -0,0 +1,40 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{dm-types} + s.version = "0.9.6" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Sam Smoot"] + s.date = %q{2008-10-11} + s.description = %q{DataMapper plugin providing extra data types} + s.email = ["ssmoot@gmail.com"] + s.extra_rdoc_files = ["README.txt", "LICENSE", "TODO"] + s.files = ["History.txt", "LICENSE", "Manifest.txt", "README.txt", "Rakefile", "TODO", "lib/dm-types.rb", "lib/dm-types/bcrypt_hash.rb", "lib/dm-types/csv.rb", "lib/dm-types/enum.rb", "lib/dm-types/epoch_time.rb", "lib/dm-types/file_path.rb", "lib/dm-types/flag.rb", "lib/dm-types/ip_address.rb", "lib/dm-types/json.rb", "lib/dm-types/slug.rb", "lib/dm-types/regexp.rb", "lib/dm-types/serial.rb", "lib/dm-types/uri.rb", "lib/dm-types/uuid.rb", "lib/dm-types/version.rb", "lib/dm-types/yaml.rb", "spec/integration/bcrypt_hash_spec.rb", "spec/integration/enum_spec.rb", "spec/integration/file_path_spec.rb", "spec/integration/flag_spec.rb", "spec/integration/ip_address_spec.rb", "spec/integration/json_spec.rb", "spec/integration/slug_spec.rb", "spec/integration/uri_spec.rb", "spec/integration/yaml_spec.rb", "spec/spec.opts", "spec/spec_helper.rb", "spec/unit/bcrypt_hash_spec.rb", "spec/unit/csv_spec.rb", "spec/unit/enum_spec.rb", "spec/unit/epoch_time_spec.rb", "spec/unit/file_path_spec.rb", "spec/unit/flag_spec.rb", "spec/unit/ip_address_spec.rb", "spec/unit/json_spec.rb", "spec/unit/regexp_spec.rb", "spec/unit/uri_spec.rb", "spec/unit/yaml_spec.rb"] + s.has_rdoc = true + s.homepage = %q{http://github.com/sam/dm-more/tree/master/dm-types} + s.rdoc_options = ["--main", "README.txt"] + s.require_paths = ["lib"] + s.rubyforge_project = %q{datamapper} + s.rubygems_version = %q{1.3.1} + s.summary = %q{DataMapper plugin providing extra data types} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, ["= 0.9.6"]) + s.add_runtime_dependency(%q, [">= 0"]) + s.add_development_dependency(%q, [">= 1.7.0"]) + else + s.add_dependency(%q, ["= 0.9.6"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 1.7.0"]) + end + else + s.add_dependency(%q, ["= 0.9.6"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 1.7.0"]) + end +end diff --git a/gems/specifications/dm-validations-0.9.6.gemspec b/gems/specifications/dm-validations-0.9.6.gemspec new file mode 100644 index 0000000..c802d1c --- /dev/null +++ b/gems/specifications/dm-validations-0.9.6.gemspec @@ -0,0 +1,37 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{dm-validations} + s.version = "0.9.6" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Guy van den Berg"] + s.date = %q{2008-10-11} + s.description = %q{DataMapper plugin for performing validations on data models} + s.email = ["vandenberg.guy@gmail.com"] + s.extra_rdoc_files = ["README.txt", "LICENSE", "TODO"] + s.files = ["History.txt", "LICENSE", "Manifest.txt", "README.txt", "Rakefile", "TODO", "lib/dm-validations.rb", "lib/dm-validations/absent_field_validator.rb", "lib/dm-validations/acceptance_validator.rb", "lib/dm-validations/auto_validate.rb", "lib/dm-validations/block_validator.rb", "lib/dm-validations/confirmation_validator.rb", "lib/dm-validations/contextual_validators.rb", "lib/dm-validations/custom_validator.rb", "lib/dm-validations/format_validator.rb", "lib/dm-validations/formats/email.rb", "lib/dm-validations/generic_validator.rb", "lib/dm-validations/length_validator.rb", "lib/dm-validations/method_validator.rb", "lib/dm-validations/numeric_validator.rb", "lib/dm-validations/primitive_validator.rb", "lib/dm-validations/required_field_validator.rb", "lib/dm-validations/support/object.rb", "lib/dm-validations/uniqueness_validator.rb", "lib/dm-validations/validation_errors.rb", "lib/dm-validations/version.rb", "lib/dm-validations/within_validator.rb", "lib/dm-validations/formats/url.rb", "spec/integration/absent_field_validator_spec.rb", "spec/integration/acceptance_validator_spec.rb", "spec/integration/auto_validate_spec.rb", "spec/integration/block_validator_spec.rb", "spec/integration/confirmation_validator_spec.rb", "spec/integration/contextual_validators_spec.rb", "spec/integration/custom_validator_spec.rb", "spec/integration/format_validator_spec.rb", "spec/integration/generic_validator_spec.rb", "spec/integration/length_validator_spec.rb", "spec/integration/method_validator_spec.rb", "spec/integration/numeric_validator_spec.rb", "spec/integration/primitive_validator_spec.rb", "spec/integration/required_field_validator_spec.rb", "spec/integration/uniqueness_validator_spec.rb", "spec/integration/validation_errors_spec.rb", "spec/integration/validation_spec.rb", "spec/integration/within_validator_spec.rb", "spec/spec.opts", "spec/spec_helper.rb"] + s.has_rdoc = true + s.homepage = %q{http://github.com/sam/dm-more/tree/master/dm-validations} + s.rdoc_options = ["--main", "README.txt"] + s.require_paths = ["lib"] + s.rubyforge_project = %q{datamapper} + s.rubygems_version = %q{1.3.1} + s.summary = %q{DataMapper plugin for performing validations on data models} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, ["= 0.9.6"]) + s.add_development_dependency(%q, [">= 1.7.0"]) + else + s.add_dependency(%q, ["= 0.9.6"]) + s.add_dependency(%q, [">= 1.7.0"]) + end + else + s.add_dependency(%q, ["= 0.9.6"]) + s.add_dependency(%q, [">= 1.7.0"]) + end +end diff --git a/gems/specifications/do_sqlite3-0.9.6.gemspec b/gems/specifications/do_sqlite3-0.9.6.gemspec new file mode 100644 index 0000000..87518f1 --- /dev/null +++ b/gems/specifications/do_sqlite3-0.9.6.gemspec @@ -0,0 +1,37 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{do_sqlite3} + s.version = "0.9.6" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Bernerd Schaefer"] + s.date = %q{2008-10-11} + s.description = %q{A DataObject.rb driver for MySQL} + s.email = ["bj.schaefer@gmail.com"] + s.extensions = ["ext/extconf.rb"] + s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.txt"] + s.files = ["History.txt", "LICENSE", "Manifest.txt", "README.txt", "Rakefile", "TODO", "ext/do_sqlite3_ext.c", "ext/extconf.rb", "lib/do_sqlite3.rb", "lib/do_sqlite3/transaction.rb", "lib/do_sqlite3/version.rb", "spec/integration/do_sqlite3_spec.rb", "spec/integration/logging_spec.rb", "spec/integration/quoting_spec.rb", "spec/spec.opts", "spec/spec_helper.rb", "spec/unit/transaction_spec.rb"] + s.homepage = %q{http://rubyforge.org/projects/dorb} + s.rdoc_options = ["--main", "README.txt"] + s.require_paths = ["lib", "ext"] + s.rubyforge_project = %q{dorb} + s.rubygems_version = %q{1.3.1} + s.summary = %q{A DataObject.rb driver for MySQL} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, ["= 0.9.6"]) + s.add_development_dependency(%q, [">= 1.7.0"]) + else + s.add_dependency(%q, ["= 0.9.6"]) + s.add_dependency(%q, [">= 1.7.0"]) + end + else + s.add_dependency(%q, ["= 0.9.6"]) + s.add_dependency(%q, [">= 1.7.0"]) + end +end diff --git a/gems/specifications/erubis-2.6.2.gemspec b/gems/specifications/erubis-2.6.2.gemspec new file mode 100644 index 0000000..26816a4 --- /dev/null +++ b/gems/specifications/erubis-2.6.2.gemspec @@ -0,0 +1,34 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{erubis} + s.version = "2.6.2" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["makoto kuwata"] + s.date = %q{2008-06-12} + s.default_executable = %q{erubis} + s.description = %q{Erubis is an implementation of eRuby and has the following features: * Very fast, almost three times faster than ERB and about 10% faster than eruby. * Multi-language support (Ruby/PHP/C/Java/Scheme/Perl/Javascript) * Auto escaping support * Auto trimming spaces around '<% %>' * Embedded pattern changeable (default '<% %>') * Enable to handle Processing Instructions (PI) as embedded pattern (ex. '') * Context object available and easy to combine eRuby template with YAML datafile * Print statement available * Easy to extend and customize in subclass * Ruby on Rails support} + s.email = %q{kwa(at)kuwata-lab.com} + s.executables = ["erubis"] + s.files = ["lib/erubis", "lib/erubis/context.rb", "lib/erubis/converter.rb", "lib/erubis/engine", "lib/erubis/engine/ec.rb", "lib/erubis/engine/ejava.rb", "lib/erubis/engine/ejavascript.rb", "lib/erubis/engine/enhanced.rb", "lib/erubis/engine/eperl.rb", "lib/erubis/engine/ephp.rb", "lib/erubis/engine/eruby.rb", "lib/erubis/engine/escheme.rb", "lib/erubis/engine/optimized.rb", "lib/erubis/engine.rb", "lib/erubis/enhancer.rb", "lib/erubis/error.rb", "lib/erubis/evaluator.rb", "lib/erubis/generator.rb", "lib/erubis/helper.rb", "lib/erubis/helpers", "lib/erubis/helpers/rails_form_helper.rb", "lib/erubis/helpers/rails_helper.rb", "lib/erubis/local-setting.rb", "lib/erubis/main.rb", "lib/erubis/preprocessing.rb", "lib/erubis/tiny.rb", "lib/erubis.rb", "bin/erubis", "examples/basic", "examples/basic/example.ec", "examples/basic/example.ejava", "examples/basic/example.ejs", "examples/basic/example.eperl", "examples/basic/example.ephp", "examples/basic/example.eruby", "examples/basic/example.escheme", "examples/basic/Makefile", "examples/pi", "examples/pi/example.ec", "examples/pi/example.ejava", "examples/pi/example.ejs", "examples/pi/example.eperl", "examples/pi/example.ephp", "examples/pi/example.eruby", "examples/pi/example.escheme", "examples/pi/Makefile", "test/assert-text-equal.rb", "test/assert-text-equal.rbc", "test/data", "test/data/users-guide", "test/data/users-guide/array_example.result", "test/data/users-guide/arraybuffer_example.result", "test/data/users-guide/bipattern-example.rhtml", "test/data/users-guide/bipattern_example.result", "test/data/users-guide/context.rb", "test/data/users-guide/context.yaml", "test/data/users-guide/def_method.rb", "test/data/users-guide/def_method.result", "test/data/users-guide/escape_example.result", "test/data/users-guide/example.ec", "test/data/users-guide/Example.ejava", "test/data/users-guide/example.ejs", "test/data/users-guide/example.eperl", "test/data/users-guide/example.ephp", "test/data/users-guide/example.eruby", "test/data/users-guide/example.escheme", "test/data/users-guide/example1.eruby", "test/data/users-guide/example1.rb", "test/data/users-guide/example1.result", "test/data/users-guide/example10.rb", "test/data/users-guide/example10.result", "test/data/users-guide/example10.xhtml", "test/data/users-guide/example10_x.result", "test/data/users-guide/example11.php", "test/data/users-guide/example11.result", "test/data/users-guide/example11.rhtml", "test/data/users-guide/example11_C.result", "test/data/users-guide/example11_N.result", "test/data/users-guide/example11_php.result", "test/data/users-guide/example11_U.result", "test/data/users-guide/example1_x.result", "test/data/users-guide/example2.eruby", "test/data/users-guide/example2.rb", "test/data/users-guide/example2.result", "test/data/users-guide/example2_trim.result", "test/data/users-guide/example2_x.result", "test/data/users-guide/example3.eruby", "test/data/users-guide/example3.rb", "test/data/users-guide/example31.result", "test/data/users-guide/example32.result", "test/data/users-guide/example3_e.result", "test/data/users-guide/example4.eruby", "test/data/users-guide/example4.rb", "test/data/users-guide/example4.result", "test/data/users-guide/example4_x.result", "test/data/users-guide/example5.eruby", "test/data/users-guide/example5.rb", "test/data/users-guide/example5.result", "test/data/users-guide/example6.rb", "test/data/users-guide/example6.result", "test/data/users-guide/example7.eruby", "test/data/users-guide/example71.result", "test/data/users-guide/example72.result", "test/data/users-guide/example8.eruby", "test/data/users-guide/example8_ruby.result", "test/data/users-guide/example8_yaml.result", "test/data/users-guide/example9.eruby", "test/data/users-guide/example9.rb", "test/data/users-guide/example9.result", "test/data/users-guide/example91.result", "test/data/users-guide/example92.result", "test/data/users-guide/example_c.result", "test/data/users-guide/example_java.result", "test/data/users-guide/example_js.result", "test/data/users-guide/example_perl.result", "test/data/users-guide/example_php.result", "test/data/users-guide/example_scheme.result", "test/data/users-guide/example_scheme_display.result", "test/data/users-guide/fasteruby.rb", "test/data/users-guide/fasteruby.result", "test/data/users-guide/fasteruby.rhtml", "test/data/users-guide/headerfooter-example.eruby", "test/data/users-guide/headerfooter-example2.rb", "test/data/users-guide/headerfooter-example2.rhtml", "test/data/users-guide/headerfooter_example.result", "test/data/users-guide/headerfooter_example2.result", "test/data/users-guide/interpolation_example.result", "test/data/users-guide/main_program1.rb", "test/data/users-guide/main_program1.result", "test/data/users-guide/main_program2.rb", "test/data/users-guide/main_program2.result", "test/data/users-guide/nocode-example.eruby", "test/data/users-guide/nocode-php.result", "test/data/users-guide/nocode_example.result", "test/data/users-guide/normal-eruby-test.eruby", "test/data/users-guide/normal_eruby_test.result", "test/data/users-guide/notext-example.eruby", "test/data/users-guide/notext-example.php", "test/data/users-guide/notext-php.result", "test/data/users-guide/notext_example.result", "test/data/users-guide/percentline-example.rhtml", "test/data/users-guide/percentline_example.result", "test/data/users-guide/printenable_example.result", "test/data/users-guide/printenabled-example.eruby", "test/data/users-guide/printenabled-example.rb", "test/data/users-guide/printstatement_example.result", "test/data/users-guide/simplify_example.result", "test/data/users-guide/stdout_exmple.result", "test/data/users-guide/stringbuffer_example.result", "test/data/users-guide/tail_260.result", "test/data/users-guide/tailnewline.rhtml", "test/data/users-guide/template1.rhtml", "test/data/users-guide/template2.rhtml", "test/hoge.rb", "test/test-engines.rb", "test/test-engines.rbc", "test/test-enhancers.rb", "test/test-erubis.rb", "test/test-erubis.rbc", "test/test-main.rb", "test/test-users-guide.rb", "test/test-users-guide.rbc", "test/test.rb", "test/test.rbc", "test/testutil.rb", "test/testutil.rbc", "doc/docstyle.css", "doc/users-guide.html", "README.txt", "CHANGES.txt", "MIT-LICENSE", "setup.rb", "contrib/erubis", "contrib/erubis-run.rb", "contrib/inline-require", "benchmark/bench.rb", "benchmark/bench_context.yaml", "benchmark/Makefile", "benchmark/templates", "benchmark/templates/_footer.html", "benchmark/templates/_header.html", "benchmark/templates/bench_erb.rhtml", "benchmark/templates/bench_erubis.rhtml", "benchmark/templates/bench_eruby.rhtml", "doc-api/classes", "doc-api/classes/ActionView", "doc-api/classes/ActionView/TemplateHandlers", "doc-api/classes/ActionView/TemplateHandlers/ErubisHandler.html", "doc-api/classes/ActionView.html", "doc-api/classes/ERB.html", "doc-api/classes/Erubis", "doc-api/classes/Erubis/ArrayBufferEnhancer.html", "doc-api/classes/Erubis/ArrayBufferEruby.html", "doc-api/classes/Erubis/ArrayEnhancer.html", "doc-api/classes/Erubis/ArrayEruby.html", "doc-api/classes/Erubis/Basic", "doc-api/classes/Erubis/Basic/Converter.html", "doc-api/classes/Erubis/Basic/Engine.html", "doc-api/classes/Erubis/Basic.html", "doc-api/classes/Erubis/BiPatternEnhancer.html", "doc-api/classes/Erubis/BiPatternEruby.html", "doc-api/classes/Erubis/CGenerator.html", "doc-api/classes/Erubis/CommandOptionError.html", "doc-api/classes/Erubis/Context.html", "doc-api/classes/Erubis/Converter.html", "doc-api/classes/Erubis/DeleteIndentEnhancer.html", "doc-api/classes/Erubis/DeleteIndentEruby.html", "doc-api/classes/Erubis/Ec.html", "doc-api/classes/Erubis/Ejava.html", "doc-api/classes/Erubis/Ejavascript.html", "doc-api/classes/Erubis/Engine.html", "doc-api/classes/Erubis/Eperl.html", "doc-api/classes/Erubis/Ephp.html", "doc-api/classes/Erubis/ErboutEnhancer.html", "doc-api/classes/Erubis/ErboutEruby.html", "doc-api/classes/Erubis/ErubisError.html", "doc-api/classes/Erubis/Eruby.html", "doc-api/classes/Erubis/EscapedEc.html", "doc-api/classes/Erubis/EscapedEjava.html", "doc-api/classes/Erubis/EscapedEjavascript.html", "doc-api/classes/Erubis/EscapedEperl.html", "doc-api/classes/Erubis/EscapedEphp.html", "doc-api/classes/Erubis/EscapedEruby.html", "doc-api/classes/Erubis/EscapedEscheme.html", "doc-api/classes/Erubis/EscapeEnhancer.html", "doc-api/classes/Erubis/Escheme.html", "doc-api/classes/Erubis/Evaluator.html", "doc-api/classes/Erubis/FastEruby.html", "doc-api/classes/Erubis/Generator.html", "doc-api/classes/Erubis/HeaderFooterEnhancer.html", "doc-api/classes/Erubis/HeaderFooterEruby.html", "doc-api/classes/Erubis/Helpers", "doc-api/classes/Erubis/Helpers/RailsFormHelper.html", "doc-api/classes/Erubis/Helpers/RailsHelper", "doc-api/classes/Erubis/Helpers/RailsHelper/TemplateConverter.html", "doc-api/classes/Erubis/Helpers/RailsHelper.html", "doc-api/classes/Erubis/Helpers.html", "doc-api/classes/Erubis/InterpolationEnhancer.html", "doc-api/classes/Erubis/InterpolationEruby.html", "doc-api/classes/Erubis/JavaGenerator.html", "doc-api/classes/Erubis/JavascriptGenerator.html", "doc-api/classes/Erubis/Main.html", "doc-api/classes/Erubis/NoCodeEnhancer.html", "doc-api/classes/Erubis/NoCodeEruby.html", "doc-api/classes/Erubis/NoTextEnhancer.html", "doc-api/classes/Erubis/NoTextEruby.html", "doc-api/classes/Erubis/NotSupportedError.html", "doc-api/classes/Erubis/OptimizedEruby.html", "doc-api/classes/Erubis/OptimizedGenerator.html", "doc-api/classes/Erubis/OptimizedXmlEruby.html", "doc-api/classes/Erubis/PercentLineEnhancer.html", "doc-api/classes/Erubis/PercentLineEruby.html", "doc-api/classes/Erubis/PerlGenerator.html", "doc-api/classes/Erubis/PhpGenerator.html", "doc-api/classes/Erubis/PI", "doc-api/classes/Erubis/PI/Converter.html", "doc-api/classes/Erubis/PI/Ec.html", "doc-api/classes/Erubis/PI/Ejava.html", "doc-api/classes/Erubis/PI/Ejavascript.html", "doc-api/classes/Erubis/PI/Engine.html", "doc-api/classes/Erubis/PI/Eperl.html", "doc-api/classes/Erubis/PI/Ephp.html", "doc-api/classes/Erubis/PI/Eruby.html", "doc-api/classes/Erubis/PI/Escheme.html", "doc-api/classes/Erubis/PI/TinyEruby.html", "doc-api/classes/Erubis/PI.html", "doc-api/classes/Erubis/PreprocessingEruby.html", "doc-api/classes/Erubis/PreprocessingHelper.html", "doc-api/classes/Erubis/PrintEnabledEnhancer.html", "doc-api/classes/Erubis/PrintEnabledEruby.html", "doc-api/classes/Erubis/PrintOutEnhancer.html", "doc-api/classes/Erubis/PrintOutEruby.html", "doc-api/classes/Erubis/PrintOutSimplifiedEruby.html", "doc-api/classes/Erubis/RubyEvaluator.html", "doc-api/classes/Erubis/RubyGenerator.html", "doc-api/classes/Erubis/SchemeGenerator.html", "doc-api/classes/Erubis/SimplifiedEruby.html", "doc-api/classes/Erubis/SimplifyEnhancer.html", "doc-api/classes/Erubis/StdoutEnhancer.html", "doc-api/classes/Erubis/StdoutEruby.html", "doc-api/classes/Erubis/StdoutSimplifiedEruby.html", "doc-api/classes/Erubis/StringBufferEnhancer.html", "doc-api/classes/Erubis/StringBufferEruby.html", "doc-api/classes/Erubis/StringIOEruby.html", "doc-api/classes/Erubis/TinyEruby.html", "doc-api/classes/Erubis/XmlEruby.html", "doc-api/classes/Erubis/XmlHelper.html", "doc-api/classes/Erubis.html", "doc-api/created.rid", "doc-api/files", "doc-api/files/erubis", "doc-api/files/erubis/context_rb.html", "doc-api/files/erubis/converter_rb.html", "doc-api/files/erubis/engine", "doc-api/files/erubis/engine/ec_rb.html", "doc-api/files/erubis/engine/ejava_rb.html", "doc-api/files/erubis/engine/ejavascript_rb.html", "doc-api/files/erubis/engine/enhanced_rb.html", "doc-api/files/erubis/engine/eperl_rb.html", "doc-api/files/erubis/engine/ephp_rb.html", "doc-api/files/erubis/engine/eruby_rb.html", "doc-api/files/erubis/engine/escheme_rb.html", "doc-api/files/erubis/engine/optimized_rb.html", "doc-api/files/erubis/engine_rb.html", "doc-api/files/erubis/enhancer_rb.html", "doc-api/files/erubis/error_rb.html", "doc-api/files/erubis/evaluator_rb.html", "doc-api/files/erubis/generator_rb.html", "doc-api/files/erubis/helper_rb.html", "doc-api/files/erubis/helpers", "doc-api/files/erubis/helpers/rails_form_helper_rb.html", "doc-api/files/erubis/helpers/rails_helper_rb.html", "doc-api/files/erubis/local-setting_rb.html", "doc-api/files/erubis/main_rb.html", "doc-api/files/erubis/preprocessing_rb.html", "doc-api/files/erubis/tiny_rb.html", "doc-api/files/erubis_rb.html", "doc-api/files/README_txt.html", "doc-api/fr_class_index.html", "doc-api/fr_file_index.html", "doc-api/fr_method_index.html", "doc-api/index.html", "doc-api/rdoc-style.css"] + s.homepage = %q{http://www.kuwata-lab.com/erubis/} + s.require_paths = ["lib"] + s.rubyforge_project = %q{erubis} + s.rubygems_version = %q{1.3.1} + s.summary = %q{a fast and extensible eRuby implementation which supports multi-language} + s.test_files = ["test/test.rb"] + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, [">= 1.0.0"]) + else + s.add_dependency(%q, [">= 1.0.0"]) + end + else + s.add_dependency(%q, [">= 1.0.0"]) + end +end diff --git a/gems/specifications/extlib-0.9.8.gemspec b/gems/specifications/extlib-0.9.8.gemspec new file mode 100644 index 0000000..0db3822 --- /dev/null +++ b/gems/specifications/extlib-0.9.8.gemspec @@ -0,0 +1,28 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{extlib} + s.version = "0.9.8" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Sam Smoot"] + s.date = %q{2008-10-11} + s.description = %q{Support library for DataMapper and Merb.} + s.email = %q{ssmoot@gmail.com} + s.extra_rdoc_files = ["LICENSE", "README.txt"] + s.files = ["LICENSE", "README.txt", "Rakefile", "lib/extlib.rb", "lib/extlib", "lib/extlib/dictionary.rb", "lib/extlib/lazy_array.rb", "lib/extlib/nil.rb", "lib/extlib/class.rb", "lib/extlib/rubygems.rb", "lib/extlib/module.rb", "lib/extlib/string.rb", "lib/extlib/hook.rb", "lib/extlib/blank.rb", "lib/extlib/logger.rb", "lib/extlib/datetime.rb", "lib/extlib/assertions.rb", "lib/extlib/inflection.rb", "lib/extlib/pathname.rb", "lib/extlib/object_space.rb", "lib/extlib/mash.rb", "lib/extlib/virtual_file.rb", "lib/extlib/simple_set.rb", "lib/extlib/object.rb", "lib/extlib/hash.rb", "lib/extlib/version.rb", "lib/extlib/boolean.rb", "lib/extlib/symbol.rb", "lib/extlib/numeric.rb", "lib/extlib/struct.rb", "lib/extlib/pooling.rb", "lib/extlib/tasks", "lib/extlib/tasks/release.rb", "lib/extlib/time.rb"] + s.homepage = %q{http://extlib.rubyforge.org} + s.require_paths = ["lib"] + s.rubygems_version = %q{1.3.1} + s.summary = %q{Support library for DataMapper and Merb.} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + else + end + else + end +end diff --git a/gems/specifications/fastthread-1.0.1.gemspec b/gems/specifications/fastthread-1.0.1.gemspec new file mode 100644 index 0000000..b30b5b9 --- /dev/null +++ b/gems/specifications/fastthread-1.0.1.gemspec @@ -0,0 +1,32 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{fastthread} + s.version = "1.0.1" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["MenTaLguY "] + s.cert_chain = ["-----BEGIN CERTIFICATE-----\nMIIDUDCCAjigAwIBAgIBADANBgkqhkiG9w0BAQUFADBOMRwwGgYDVQQDDBNtb25n\ncmVsLWRldmVsb3BtZW50MRkwFwYKCZImiZPyLGQBGRYJcnVieWZvcmdlMRMwEQYK\nCZImiZPyLGQBGRYDb3JnMB4XDTA3MDkxNjEwMzI0OVoXDTA4MDkxNTEwMzI0OVow\nTjEcMBoGA1UEAwwTbW9uZ3JlbC1kZXZlbG9wbWVudDEZMBcGCgmSJomT8ixkARkW\nCXJ1Ynlmb3JnZTETMBEGCgmSJomT8ixkARkWA29yZzCCASIwDQYJKoZIhvcNAQEB\nBQADggEPADCCAQoCggEBAMb9v3B01eOHk3FyypbQgKXzJplUE5P6dXoG+xpPm0Lv\nP7BQmeMncOwqQ7zXpVQU+lTpXtQFTsOE3vL7KnhQFJKGvUAkbh24VFyopu1I0yqF\nmGu4nRqNXGXVj8TvLSj4S1WpSRLAa0acLPNyKhGmoV9+crqQypSjM6XKjBeppifo\n4eBmWGjiJEYMIJBvJZPJ4rAVDDA8C6CM1m3gMBGNh8ELDhU8HI9AP3dMIkTI2Wx9\n9xkJwHdroAaS0IFFtYChrwee4FbCF1FHDgoTosMwa47DrLHg4hZ6ojaKwK5QVWEV\nXGb6ju5UqpktnSWF2W+Lvl/K0tI42OH2CAhebT1gEVUCAwEAAaM5MDcwCQYDVR0T\nBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0OBBYEFGHChyMSZ16u9WOzKhgJSQ9lqDc5\nMA0GCSqGSIb3DQEBBQUAA4IBAQA/lfeN2WdB1xN+82tT7vNS4HOjRQw6MUh5yktu\nGQjaGqm0UB+aX0Z9y0B0qpfv9rj7nmIvEGiwBmDepNWYCGuW15JyqpN7QVVnG2xS\nMrame7VqgjM7A+VGDD5In5LtWbM/CHAATvvFlQ5Ph13YE1EdnVbZ65c+KQv+5sFY\nQ+zEop74d878uaC/SAHHXS46TiXneocaLSYw1CEZs/MAIy+9c4Q5ESbGpgnfg1Ad\n6lwl7k3hsNHO/+tZzx4HJtOXDI1yAl3+q6T9J0yI3z97EinwvAKhS1eyOI2Y5eeT\ntbQaNYkU127B3l/VNpd8fQm3Jkl/PqCCmDBQjUszFrJEODug\n-----END CERTIFICATE-----\n", "-----BEGIN CERTIFICATE-----\nMIIDPzCCAiegAwIBAgIBADANBgkqhkiG9w0BAQUFADBOMRwwGgYDVQQDDBNtb25n\ncmVsLWRldmVsb3BtZW50MRkwFwYKCZImiZPyLGQBGRYJcnVieWZvcmdlMRMwEQYK\nCZImiZPyLGQBGRYDb3JnMB4XDTA3MDkxNjEwMzMwMFoXDTA4MDkxNTEwMzMwMFow\nPTENMAsGA1UEAwwEZXZhbjEYMBYGCgmSJomT8ixkARkWCGNsb3VkYnVyMRIwEAYK\nCZImiZPyLGQBGRYCc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDk\nLQijz2fICmev4+9s0WB71WzJFYCUYFQQxqGlenbxWut9dlPSsBbskGjg+UITeOXi\ncTh3MTqAB0i1LJyNOiyvDsAivn7GjKXhVvflp2/npMhBBe83P4HOWqeQBjkk3QJI\nFFNBvqbFLeEXIP+HiqAOiyNHZEVXMepLEJLzGrg3Ly7M7A6L5fK7jDrt8jkm+c+8\nzGquVHV5ohAebGd/vpHMLjpA7lCG5+MBgYZd33rRfNtCxDJMNRgnOu9PsB05+LJn\nMpDKQq3x0SkOf5A+MVOcadNCaAkFflYk3SUcXaXWxu/eCHgqfW1m76RNSp5djpKE\nCgNPK9lGIWpB3CHzDaVNAgMBAAGjOTA3MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSw\nMB0GA1UdDgQWBBT5aonPfFBdJ5rWFG+8dZwgyB54LjANBgkqhkiG9w0BAQUFAAOC\nAQEAiKbzWgMcvZs/TPwJxr8tJ+7mSGz7+zDkWcbBl8FpQq1DtRcATh1oyTkQT7t+\nrFEBYMmb0FxbbUnojQp8hIFgFkUwFpStwWBL/okLSehntzI2iwjuEtfj4ac9Q3Y2\nuSdbmZqsQTuu+lEUc5C4qLK7YKwToaul+cx7vWxyk1YendcVwRlFLIBqA5cPrwo3\nyyGLTHlRYn2c9PSbM1B63Yg+LqSSAa4QSU3Wv9pNdffVpvwHPVEQpO7ZDo5slQFL\nGf6+gbD/eZAvhpvmn8JlXb+LxKaFVMs2Yvrk1xOuT76SsPjEGWxkr7jZCIpsYfgQ\nALN3mi/9z0Mf1YroliUgF0v5Yw==\n-----END CERTIFICATE-----\n"] + s.date = %q{2007-10-25} + s.description = %q{Optimized replacement for thread.rb primitives} + s.email = %q{} + s.extensions = ["ext/fastthread/extconf.rb"] + s.files = ["test/test_queue.rb", "test/test_mutex.rb", "test/test_condvar.rb", "test/test_all.rb", "setup.rb", "Manifest", "ext/fastthread/fastthread.c", "ext/fastthread/extconf.rb", "CHANGELOG", "fastthread.gemspec"] + s.has_rdoc = true + s.homepage = %q{} + s.require_paths = ["lib", "ext"] + s.rubyforge_project = %q{mongrel} + s.rubygems_version = %q{1.3.1} + s.summary = %q{Optimized replacement for thread.rb primitives} + s.test_files = ["test/test_all.rb"] + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + else + end + else + end +end diff --git a/gems/specifications/gem_plugin-0.2.3.gemspec b/gems/specifications/gem_plugin-0.2.3.gemspec new file mode 100644 index 0000000..a9a3e96 --- /dev/null +++ b/gems/specifications/gem_plugin-0.2.3.gemspec @@ -0,0 +1,33 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{gem_plugin} + s.version = "0.2.3" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Zed A. Shaw"] + s.cert_chain = ["-----BEGIN CERTIFICATE-----\nMIIDUDCCAjigAwIBAgIBADANBgkqhkiG9w0BAQUFADBOMRwwGgYDVQQDDBNtb25n\ncmVsLWRldmVsb3BtZW50MRkwFwYKCZImiZPyLGQBGRYJcnVieWZvcmdlMRMwEQYK\nCZImiZPyLGQBGRYDb3JnMB4XDTA3MDkxNjEwMzI0OVoXDTA4MDkxNTEwMzI0OVow\nTjEcMBoGA1UEAwwTbW9uZ3JlbC1kZXZlbG9wbWVudDEZMBcGCgmSJomT8ixkARkW\nCXJ1Ynlmb3JnZTETMBEGCgmSJomT8ixkARkWA29yZzCCASIwDQYJKoZIhvcNAQEB\nBQADggEPADCCAQoCggEBAMb9v3B01eOHk3FyypbQgKXzJplUE5P6dXoG+xpPm0Lv\nP7BQmeMncOwqQ7zXpVQU+lTpXtQFTsOE3vL7KnhQFJKGvUAkbh24VFyopu1I0yqF\nmGu4nRqNXGXVj8TvLSj4S1WpSRLAa0acLPNyKhGmoV9+crqQypSjM6XKjBeppifo\n4eBmWGjiJEYMIJBvJZPJ4rAVDDA8C6CM1m3gMBGNh8ELDhU8HI9AP3dMIkTI2Wx9\n9xkJwHdroAaS0IFFtYChrwee4FbCF1FHDgoTosMwa47DrLHg4hZ6ojaKwK5QVWEV\nXGb6ju5UqpktnSWF2W+Lvl/K0tI42OH2CAhebT1gEVUCAwEAAaM5MDcwCQYDVR0T\nBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0OBBYEFGHChyMSZ16u9WOzKhgJSQ9lqDc5\nMA0GCSqGSIb3DQEBBQUAA4IBAQA/lfeN2WdB1xN+82tT7vNS4HOjRQw6MUh5yktu\nGQjaGqm0UB+aX0Z9y0B0qpfv9rj7nmIvEGiwBmDepNWYCGuW15JyqpN7QVVnG2xS\nMrame7VqgjM7A+VGDD5In5LtWbM/CHAATvvFlQ5Ph13YE1EdnVbZ65c+KQv+5sFY\nQ+zEop74d878uaC/SAHHXS46TiXneocaLSYw1CEZs/MAIy+9c4Q5ESbGpgnfg1Ad\n6lwl7k3hsNHO/+tZzx4HJtOXDI1yAl3+q6T9J0yI3z97EinwvAKhS1eyOI2Y5eeT\ntbQaNYkU127B3l/VNpd8fQm3Jkl/PqCCmDBQjUszFrJEODug\n-----END CERTIFICATE-----\n", "-----BEGIN CERTIFICATE-----\nMIIDPzCCAiegAwIBAgIBADANBgkqhkiG9w0BAQUFADBOMRwwGgYDVQQDDBNtb25n\ncmVsLWRldmVsb3BtZW50MRkwFwYKCZImiZPyLGQBGRYJcnVieWZvcmdlMRMwEQYK\nCZImiZPyLGQBGRYDb3JnMB4XDTA3MDkxNjEwMzMwMFoXDTA4MDkxNTEwMzMwMFow\nPTENMAsGA1UEAwwEZXZhbjEYMBYGCgmSJomT8ixkARkWCGNsb3VkYnVyMRIwEAYK\nCZImiZPyLGQBGRYCc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDk\nLQijz2fICmev4+9s0WB71WzJFYCUYFQQxqGlenbxWut9dlPSsBbskGjg+UITeOXi\ncTh3MTqAB0i1LJyNOiyvDsAivn7GjKXhVvflp2/npMhBBe83P4HOWqeQBjkk3QJI\nFFNBvqbFLeEXIP+HiqAOiyNHZEVXMepLEJLzGrg3Ly7M7A6L5fK7jDrt8jkm+c+8\nzGquVHV5ohAebGd/vpHMLjpA7lCG5+MBgYZd33rRfNtCxDJMNRgnOu9PsB05+LJn\nMpDKQq3x0SkOf5A+MVOcadNCaAkFflYk3SUcXaXWxu/eCHgqfW1m76RNSp5djpKE\nCgNPK9lGIWpB3CHzDaVNAgMBAAGjOTA3MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSw\nMB0GA1UdDgQWBBT5aonPfFBdJ5rWFG+8dZwgyB54LjANBgkqhkiG9w0BAQUFAAOC\nAQEAiKbzWgMcvZs/TPwJxr8tJ+7mSGz7+zDkWcbBl8FpQq1DtRcATh1oyTkQT7t+\nrFEBYMmb0FxbbUnojQp8hIFgFkUwFpStwWBL/okLSehntzI2iwjuEtfj4ac9Q3Y2\nuSdbmZqsQTuu+lEUc5C4qLK7YKwToaul+cx7vWxyk1YendcVwRlFLIBqA5cPrwo3\nyyGLTHlRYn2c9PSbM1B63Yg+LqSSAa4QSU3Wv9pNdffVpvwHPVEQpO7ZDo5slQFL\nGf6+gbD/eZAvhpvmn8JlXb+LxKaFVMs2Yvrk1xOuT76SsPjEGWxkr7jZCIpsYfgQ\nALN3mi/9z0Mf1YroliUgF0v5Yw==\n-----END CERTIFICATE-----\n"] + s.date = %q{2007-10-25} + s.default_executable = %q{gpgen} + s.description = %q{A plugin system based on rubygems that uses dependencies only} + s.email = %q{} + s.executables = ["gpgen"] + s.files = ["test/test_plugins.rb", "setup.rb", "resources/resources/defaults.yaml", "resources/README", "resources/Rakefile", "resources/LICENSE", "resources/lib/project/init.rb", "resources/COPYING", "README", "Manifest", "LICENSE", "lib/gem_plugin.rb", "COPYING", "CHANGELOG", "bin/gpgen", "gem_plugin.gemspec"] + s.has_rdoc = true + s.homepage = %q{} + s.require_paths = ["lib"] + s.rubyforge_project = %q{mongrel} + s.rubygems_version = %q{1.3.1} + s.summary = %q{A plugin system based on rubygems that uses dependencies only} + s.test_files = ["test/test_plugins.rb"] + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + else + end + else + end +end diff --git a/gems/specifications/haml-2.0.4.gemspec b/gems/specifications/haml-2.0.4.gemspec new file mode 100644 index 0000000..e9bdcd9 --- /dev/null +++ b/gems/specifications/haml-2.0.4.gemspec @@ -0,0 +1,33 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{haml} + s.version = "2.0.4" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Nathan Weizenbaum", "Hampton Catlin"] + s.date = %q{2008-10-30} + s.description = %q{Haml (HTML Abstraction Markup Language) is a layer on top of XHTML or XML that's designed to express the structure of XHTML or XML documents in a non-repetitive, elegant, easy way, using indentation rather than closing tags and allowing Ruby to be embedded with ease. It was originally envisioned as a plugin for Ruby on Rails, but it can function as a stand-alone templating engine.} + s.email = %q{haml@googlegroups.com} + s.executables = ["haml", "html2haml", "sass", "css2sass"] + s.extra_rdoc_files = ["VERSION", "MIT-LICENSE", "README.rdoc", "FAQ", "REVISION"] + s.files = ["rails/init.rb", "lib/sass.rb", "lib/sass", "lib/sass/plugin", "lib/sass/plugin/rails.rb", "lib/sass/plugin/merb.rb", "lib/sass/error.rb", "lib/sass/tree", "lib/sass/tree/value_node.rb", "lib/sass/tree/attr_node.rb", "lib/sass/tree/directive_node.rb", "lib/sass/tree/node.rb", "lib/sass/tree/comment_node.rb", "lib/sass/tree/rule_node.rb", "lib/sass/constant.rb", "lib/sass/constant", "lib/sass/constant/color.rb", "lib/sass/constant/string.rb", "lib/sass/constant/number.rb", "lib/sass/constant/operation.rb", "lib/sass/constant/literal.rb", "lib/sass/constant/nil.rb", "lib/sass/plugin.rb", "lib/sass/css.rb", "lib/sass/engine.rb", "lib/haml", "lib/haml/exec.rb", "lib/haml/html.rb", "lib/haml/error.rb", "lib/haml/buffer.rb", "lib/haml/template.rb", "lib/haml/template", "lib/haml/template/plugin.rb", "lib/haml/template/patch.rb", "lib/haml/helpers.rb", "lib/haml/filters.rb", "lib/haml/engine.rb", "lib/haml/precompiler.rb", "lib/haml/helpers", "lib/haml/helpers/action_view_extensions.rb", "lib/haml/helpers/action_view_mods.rb", "lib/haml.rb", "bin/css2sass", "bin/sass", "bin/haml", "bin/html2haml", "test/sass", "test/sass/templates", "test/sass/templates/bork2.sass", "test/sass/templates/compressed.sass", "test/sass/templates/expanded.sass", "test/sass/templates/import.sass", "test/sass/templates/subdir", "test/sass/templates/subdir/subdir.sass", "test/sass/templates/subdir/nested_subdir", "test/sass/templates/subdir/nested_subdir/nested_subdir.sass", "test/sass/templates/basic.sass", "test/sass/templates/_partial.sass", "test/sass/templates/mixins.sass", "test/sass/templates/multiline.sass", "test/sass/templates/nested.sass", "test/sass/templates/compact.sass", "test/sass/templates/alt.sass", "test/sass/templates/constants.sass", "test/sass/templates/importee.sass", "test/sass/templates/parent_ref.sass", "test/sass/templates/bork.sass", "test/sass/templates/complex.sass", "test/sass/plugin_test.rb", "test/sass/results", "test/sass/results/nested.css", "test/sass/results/subdir", "test/sass/results/subdir/nested_subdir", "test/sass/results/subdir/nested_subdir/nested_subdir.css", "test/sass/results/subdir/subdir.css", "test/sass/results/import.css", "test/sass/results/compact.css", "test/sass/results/expanded.css", "test/sass/results/alt.css", "test/sass/results/mixins.css", "test/sass/results/complex.css", "test/sass/results/constants.css", "test/sass/results/compressed.css", "test/sass/results/parent_ref.css", "test/sass/results/multiline.css", "test/sass/results/basic.css", "test/sass/engine_test.rb", "test/haml", "test/haml/mocks", "test/haml/mocks/article.rb", "test/haml/template_test.rb", "test/haml/html2haml_test.rb", "test/haml/rhtml", "test/haml/rhtml/_av_partial_1.rhtml", "test/haml/rhtml/standard.rhtml", "test/haml/rhtml/action_view.rhtml", "test/haml/rhtml/_av_partial_2.rhtml", "test/haml/helper_test.rb", "test/haml/templates", "test/haml/templates/list.haml", "test/haml/templates/_text_area.haml", "test/haml/templates/_partial.haml", "test/haml/templates/nuke_outer_whitespace.haml", "test/haml/templates/_av_partial_2.haml", "test/haml/templates/partial_layout.haml", "test/haml/templates/helpful.haml", "test/haml/templates/just_stuff.haml", "test/haml/templates/silent_script.haml", "test/haml/templates/very_basic.haml", "test/haml/templates/nuke_inner_whitespace.haml", "test/haml/templates/eval_suppressed.haml", "test/haml/templates/tag_parsing.haml", "test/haml/templates/whitespace_handling.haml", "test/haml/templates/partials.haml", "test/haml/templates/standard.haml", "test/haml/templates/partialize.haml", "test/haml/templates/_layout_for_partial.haml", "test/haml/templates/_av_partial_1.haml", "test/haml/templates/filters.haml", "test/haml/templates/content_for_layout.haml", "test/haml/templates/helpers.haml", "test/haml/templates/original_engine.haml", "test/haml/templates/breakage.haml", "test/haml/templates/action_view.haml", "test/haml/results", "test/haml/results/content_for_layout.xhtml", "test/haml/results/just_stuff.xhtml", "test/haml/results/whitespace_handling.xhtml", "test/haml/results/nuke_outer_whitespace.xhtml", "test/haml/results/silent_script.xhtml", "test/haml/results/filters.xhtml", "test/haml/results/standard.xhtml", "test/haml/results/nuke_inner_whitespace.xhtml", "test/haml/results/helpful.xhtml", "test/haml/results/very_basic.xhtml", "test/haml/results/eval_suppressed.xhtml", "test/haml/results/partials.xhtml", "test/haml/results/original_engine.xhtml", "test/haml/results/helpers.xhtml", "test/haml/results/list.xhtml", "test/haml/results/partial_layout.xhtml", "test/haml/results/tag_parsing.xhtml", "test/haml/markaby", "test/haml/markaby/standard.mab", "test/haml/engine_test.rb", "test/linked_rails.rb", "test/rails", "test/benchmark.rb", "test/test_helper.rb", "Rakefile", "init.rb", "VERSION", "MIT-LICENSE", "README.rdoc", "FAQ", "REVISION"] + s.has_rdoc = true + s.homepage = %q{http://haml.hamptoncatlin.com/} + s.rdoc_options = ["--title", "Haml", "--main", "README.rdoc", "--exclude", "lib/haml/buffer.rb", "--line-numbers", "--inline-source"] + s.require_paths = ["lib"] + s.rubyforge_project = %q{haml} + s.rubygems_version = %q{1.3.1} + s.summary = %q{An elegant, structured XHTML/XML templating engine. Comes with Sass, a similar CSS templating engine.} + s.test_files = ["test/sass/plugin_test.rb", "test/sass/engine_test.rb", "test/haml/template_test.rb", "test/haml/html2haml_test.rb", "test/haml/helper_test.rb", "test/haml/engine_test.rb"] + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + else + end + else + end +end diff --git a/gems/specifications/highline-1.5.0.gemspec b/gems/specifications/highline-1.5.0.gemspec new file mode 100644 index 0000000..3f65b0d --- /dev/null +++ b/gems/specifications/highline-1.5.0.gemspec @@ -0,0 +1,32 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{highline} + s.version = "1.5.0" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["James Edward Gray II"] + s.date = %q{2008-11-04} + s.description = %q{A high-level IO library that provides validation, type conversion, and more for command-line interfaces. HighLine also includes a complete menu system that can crank out anything from simple list selection to complete shells with just minutes of work.} + s.email = %q{james@grayproductions.net} + s.extra_rdoc_files = ["README", "INSTALL", "TODO", "CHANGELOG", "LICENSE"] + s.files = ["examples/ansi_colors.rb", "examples/asking_for_arrays.rb", "examples/basic_usage.rb", "examples/color_scheme.rb", "examples/menus.rb", "examples/overwrite.rb", "examples/page_and_wrap.rb", "examples/password.rb", "examples/trapping_eof.rb", "examples/using_readline.rb", "lib/highline/color_scheme.rb", "lib/highline/import.rb", "lib/highline/menu.rb", "lib/highline/question.rb", "lib/highline/system_extensions.rb", "lib/highline.rb", "test/tc_color_scheme.rb", "test/tc_highline.rb", "test/tc_import.rb", "test/tc_menu.rb", "test/ts_all.rb", "Rakefile", "setup.rb", "README", "INSTALL", "TODO", "CHANGELOG", "LICENSE"] + s.has_rdoc = true + s.homepage = %q{http://highline.rubyforge.org} + s.rdoc_options = ["--title", "HighLine Documentation", "--main", "README"] + s.require_paths = ["lib"] + s.rubyforge_project = %q{highline} + s.rubygems_version = %q{1.3.1} + s.summary = %q{HighLine is a high-level command-line IO library.} + s.test_files = ["test/ts_all.rb"] + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + else + end + else + end +end diff --git a/gems/specifications/json_pure-1.1.3.gemspec b/gems/specifications/json_pure-1.1.3.gemspec new file mode 100644 index 0000000..37b76d7 --- /dev/null +++ b/gems/specifications/json_pure-1.1.3.gemspec @@ -0,0 +1,33 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{json_pure} + s.version = "1.1.3" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Florian Frank"] + s.date = %q{2008-07-10} + s.default_executable = %q{edit_json.rb} + s.description = %q{} + s.email = %q{flori@ping.de} + s.executables = ["edit_json.rb"] + s.files = ["install.rb", "lib", "lib/json.rb", "lib/json", "lib/json/Array.xpm", "lib/json/FalseClass.xpm", "lib/json/json.xpm", "lib/json/editor.rb", "lib/json/Hash.xpm", "lib/json/Key.xpm", "lib/json/common.rb", "lib/json/String.xpm", "lib/json/pure", "lib/json/pure/generator.rb", "lib/json/pure/parser.rb", "lib/json/Numeric.xpm", "lib/json/ext.rb", "lib/json/pure.rb", "lib/json/NilClass.xpm", "lib/json/add", "lib/json/add/rails.rb", "lib/json/add/core.rb", "lib/json/TrueClass.xpm", "lib/json/version.rb", "ext", "ext/json", "ext/json/ext", "ext/json/ext/parser", "ext/json/ext/parser/unicode.h", "ext/json/ext/parser/parser.c", "ext/json/ext/parser/extconf.rb", "ext/json/ext/parser/unicode.c", "ext/json/ext/parser/parser.rl", "ext/json/ext/generator", "ext/json/ext/generator/unicode.h", "ext/json/ext/generator/extconf.rb", "ext/json/ext/generator/generator.c", "ext/json/ext/generator/unicode.c", "README", "diagrams", "CHANGES", "RUBY", "TODO", "VERSION", "tests", "tests/test_json.rb", "tests/test_json_addition.rb", "tests/fixtures", "tests/fixtures/fail11.json", "tests/fixtures/fail5.json", "tests/fixtures/fail10.json", "tests/fixtures/fail3.json", "tests/fixtures/pass15.json", "tests/fixtures/fail9.json", "tests/fixtures/fail22.json", "tests/fixtures/fail6.json", "tests/fixtures/pass2.json", "tests/fixtures/fail20.json", "tests/fixtures/fail19.json", "tests/fixtures/fail12.json", "tests/fixtures/fail7.json", "tests/fixtures/fail4.json", "tests/fixtures/fail1.json", "tests/fixtures/fail24.json", "tests/fixtures/fail21.json", "tests/fixtures/pass1.json", "tests/fixtures/fail2.json", "tests/fixtures/fail25.json", "tests/fixtures/pass16.json", "tests/fixtures/pass3.json", "tests/fixtures/fail18.json", "tests/fixtures/fail28.json", "tests/fixtures/fail13.json", "tests/fixtures/fail27.json", "tests/fixtures/pass17.json", "tests/fixtures/pass26.json", "tests/fixtures/fail23.json", "tests/fixtures/fail14.json", "tests/fixtures/fail8.json", "tests/runner.rb", "tests/test_json_generate.rb", "tests/test_json_rails.rb", "tests/test_json_unicode.rb", "tests/test_json_fixtures.rb", "benchmarks", "benchmarks/benchmark_parser.rb", "benchmarks/benchmark_generator.rb", "benchmarks/benchmark_rails.rb", "benchmarks/benchmark.txt", "Rakefile", "GPL", "data", "data/example.json", "data/index.html", "data/prototype.js", "bin", "bin/edit_json.rb", "bin/prettify_json.rb", "tools", "tools/fuzz.rb", "tools/server.rb"] + s.has_rdoc = true + s.homepage = %q{http://json.rubyforge.org} + s.rdoc_options = ["--title", "JSON -- A JSON implemention", "--main", "JSON", "--line-numbers"] + s.require_paths = ["lib"] + s.rubyforge_project = %q{json} + s.rubygems_version = %q{1.3.1} + s.summary = %q{A JSON implementation in Ruby} + s.test_files = ["tests/runner.rb"] + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + else + end + else + end +end diff --git a/gems/specifications/linecache-0.43.gemspec b/gems/specifications/linecache-0.43.gemspec new file mode 100644 index 0000000..36f833a --- /dev/null +++ b/gems/specifications/linecache-0.43.gemspec @@ -0,0 +1,34 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{linecache} + s.version = "0.43" + + s.required_rubygems_version = nil if s.respond_to? :required_rubygems_version= + s.authors = ["R. Bernstein"] + s.cert_chain = nil + s.date = %q{2008-06-11} + s.description = %q{LineCache is a module for reading and caching lines. This may be useful for example in a debugger where the same lines are shown many times.} + s.email = %q{rockyb@rubyforge.net} + s.extensions = ["ext/extconf.rb"] + s.extra_rdoc_files = ["README", "lib/linecache.rb", "lib/tracelines.rb"] + s.files = ["AUTHORS", "COPYING", "ChangeLog", "NEWS", "README", "Rakefile", "VERSION", "ext/trace_nums.c", "ext/trace_nums.h", "ext/extconf.rb", "lib/tracelines.rb", "lib/linecache.rb", "test/rcov-bug.rb", "test/test-tracelines.rb", "test/test-lnum.rb", "test/test-linecache.rb", "test/parse-show.rb", "test/lnum-diag.rb", "test/data/for1.rb", "test/data/if6.rb", "test/data/comments1.rb", "test/data/if3.rb", "test/data/if5.rb", "test/data/begin3.rb", "test/data/end.rb", "test/data/case1.rb", "test/data/match.rb", "test/data/begin2.rb", "test/data/match3.rb", "test/data/case5.rb", "test/data/not-lit.rb", "test/data/match3a.rb", "test/data/if7.rb", "test/data/if4.rb", "test/data/case2.rb", "test/data/block2.rb", "test/data/begin1.rb", "test/data/def1.rb", "test/data/if1.rb", "test/data/class1.rb", "test/data/if2.rb", "test/data/block1.rb", "test/data/case3.rb", "test/data/each1.rb", "test/data/case4.rb", "test/short-file"] + s.has_rdoc = true + s.homepage = %q{http://rubyforge.org/projects/rocky-hacks/linecache} + s.require_paths = ["lib"] + s.required_ruby_version = Gem::Requirement.new(">= 1.8.2") + s.rubyforge_project = %q{rocky-hacks} + s.rubygems_version = %q{1.3.1} + s.summary = %q{Read file with caching} + s.test_files = ["test/rcov-bug.rb", "test/test-tracelines.rb", "test/test-lnum.rb", "test/test-linecache.rb", "test/parse-show.rb", "test/lnum-diag.rb"] + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 1 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + else + end + else + end +end diff --git a/gems/specifications/mailfactory-1.4.0.gemspec b/gems/specifications/mailfactory-1.4.0.gemspec new file mode 100644 index 0000000..81c438a --- /dev/null +++ b/gems/specifications/mailfactory-1.4.0.gemspec @@ -0,0 +1,33 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{mailfactory} + s.version = "1.4.0" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["David Powers"] + s.date = %q{2008-08-06} + s.description = %q{MailFactory is s simple module for producing RFC compliant mail that can include multiple attachments, multiple body parts, and arbitrary headers} + s.email = %q{david@grayskies.net} + s.files = ["./lib/mailfactory.rb", "./tests/test_mailfactory.rb"] + s.has_rdoc = true + s.homepage = %q{http://mailfactory.rubyforge.org} + s.require_paths = ["lib"] + s.rubyforge_project = %q{mailfactory} + s.rubygems_version = %q{1.3.1} + s.summary = %q{MailFactory is a pure-ruby MIME mail generator} + s.test_files = ["./tests/test_mailfactory.rb"] + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, [">= 1.13.1"]) + else + s.add_dependency(%q, [">= 1.13.1"]) + end + else + s.add_dependency(%q, [">= 1.13.1"]) + end +end diff --git a/gems/specifications/merb-1.0.gemspec b/gems/specifications/merb-1.0.gemspec new file mode 100644 index 0000000..b4d8ae4 --- /dev/null +++ b/gems/specifications/merb-1.0.gemspec @@ -0,0 +1,58 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{merb} + s.version = "1.0" + + s.required_rubygems_version = Gem::Requirement.new(">= 1.3.0") if s.respond_to? :required_rubygems_version= + s.authors = ["Merb Team"] + s.date = %q{2008-11-07} + s.description = %q{(merb-core + merb-more + DM) == Merb stack} + s.email = %q{team@merbivore.com} + s.files = ["LICENSE", "README", "Rakefile", "lib/merb.rb"] + s.homepage = %q{http://merbivore.com/} + s.require_paths = ["lib"] + s.rubyforge_project = %q{merb} + s.rubygems_version = %q{1.3.1} + s.summary = %q{(merb-core + merb-more + DM) == Merb stack} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, ["~> 1.0"]) + s.add_runtime_dependency(%q, ["~> 1.0"]) + s.add_runtime_dependency(%q, ["~> 0.9.6"]) + s.add_runtime_dependency(%q, ["~> 0.9.6"]) + s.add_runtime_dependency(%q, ["~> 0.9.6"]) + s.add_runtime_dependency(%q, ["~> 0.9.6"]) + s.add_runtime_dependency(%q, ["~> 0.9.6"]) + s.add_runtime_dependency(%q, ["~> 0.9.6"]) + s.add_runtime_dependency(%q, ["~> 0.9.6"]) + s.add_runtime_dependency(%q, ["~> 0.9.6"]) + else + s.add_dependency(%q, ["~> 1.0"]) + s.add_dependency(%q, ["~> 1.0"]) + s.add_dependency(%q, ["~> 0.9.6"]) + s.add_dependency(%q, ["~> 0.9.6"]) + s.add_dependency(%q, ["~> 0.9.6"]) + s.add_dependency(%q, ["~> 0.9.6"]) + s.add_dependency(%q, ["~> 0.9.6"]) + s.add_dependency(%q, ["~> 0.9.6"]) + s.add_dependency(%q, ["~> 0.9.6"]) + s.add_dependency(%q, ["~> 0.9.6"]) + end + else + s.add_dependency(%q, ["~> 1.0"]) + s.add_dependency(%q, ["~> 1.0"]) + s.add_dependency(%q, ["~> 0.9.6"]) + s.add_dependency(%q, ["~> 0.9.6"]) + s.add_dependency(%q, ["~> 0.9.6"]) + s.add_dependency(%q, ["~> 0.9.6"]) + s.add_dependency(%q, ["~> 0.9.6"]) + s.add_dependency(%q, ["~> 0.9.6"]) + s.add_dependency(%q, ["~> 0.9.6"]) + s.add_dependency(%q, ["~> 0.9.6"]) + end +end diff --git a/gems/specifications/merb-action-args-1.0.gemspec b/gems/specifications/merb-action-args-1.0.gemspec new file mode 100644 index 0000000..3b1fa61 --- /dev/null +++ b/gems/specifications/merb-action-args-1.0.gemspec @@ -0,0 +1,39 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{merb-action-args} + s.version = "1.0" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Yehuda Katz"] + s.date = %q{2008-11-07} + s.description = %q{Merb plugin that provides support for ActionArgs} + s.email = %q{ykatz@engineyard.com} + s.extra_rdoc_files = ["README", "LICENSE", "TODO"] + s.files = ["LICENSE", "README", "Rakefile", "TODO", "lib/merb-action-args.rb", "lib/merb-action-args", "lib/merb-action-args/get_args.rb", "lib/merb-action-args/abstract_controller.rb", "lib/merb-action-args/jruby_args.rb", "spec/controllers", "spec/controllers/action-args.rb", "spec/action_args_spec.rb", "spec/spec_helper.rb"] + s.has_rdoc = true + s.homepage = %q{http://merbivore.com} + s.require_paths = ["lib"] + s.rubyforge_project = %q{merb} + s.rubygems_version = %q{1.3.1} + s.summary = %q{Merb plugin that provides support for ActionArgs} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, [">= 1.0"]) + s.add_runtime_dependency(%q, [">= 1.1.9"]) + s.add_runtime_dependency(%q, [">= 2.1.1"]) + else + s.add_dependency(%q, [">= 1.0"]) + s.add_dependency(%q, [">= 1.1.9"]) + s.add_dependency(%q, [">= 2.1.1"]) + end + else + s.add_dependency(%q, [">= 1.0"]) + s.add_dependency(%q, [">= 1.1.9"]) + s.add_dependency(%q, [">= 2.1.1"]) + end +end diff --git a/gems/specifications/merb-assets-1.0.gemspec b/gems/specifications/merb-assets-1.0.gemspec new file mode 100644 index 0000000..0483b50 --- /dev/null +++ b/gems/specifications/merb-assets-1.0.gemspec @@ -0,0 +1,33 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{merb-assets} + s.version = "1.0" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Ezra Zygmuntowicz"] + s.date = %q{2008-11-07} + s.description = %q{Merb plugin that provides the helpers for assets and asset bundling} + s.email = %q{ez@engineyard.com} + s.extra_rdoc_files = ["README", "LICENSE", "TODO"] + s.files = ["LICENSE", "README", "Rakefile", "TODO", "lib/merb-assets.rb", "lib/merb-assets", "lib/merb-assets/assets_mixin.rb", "lib/merb-assets/assets.rb", "spec/merb-assets_spec.rb", "spec/spec_helper.rb"] + s.has_rdoc = true + s.homepage = %q{http://merbivore.com} + s.require_paths = ["lib"] + s.rubyforge_project = %q{merb} + s.rubygems_version = %q{1.3.1} + s.summary = %q{Merb plugin that provides the helpers for assets and asset bundling} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, [">= 1.0"]) + else + s.add_dependency(%q, [">= 1.0"]) + end + else + s.add_dependency(%q, [">= 1.0"]) + end +end diff --git a/gems/specifications/merb-auth-1.0.gemspec b/gems/specifications/merb-auth-1.0.gemspec new file mode 100644 index 0000000..68569f5 --- /dev/null +++ b/gems/specifications/merb-auth-1.0.gemspec @@ -0,0 +1,40 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{merb-auth} + s.version = "1.0" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Daniel Neighman"] + s.date = %q{2008-11-07} + s.description = %q{merb-auth. The official authentication plugin for merb. Setup for the default stack} + s.email = %q{has.sox@gmail.com} + s.files = ["LICENSE", "README.textile", "Rakefile", "TODO", "lib/merb-auth.rb"] + s.homepage = %q{http://www.merbivore.com} + s.require_paths = ["lib"] + s.rubyforge_project = %q{merb-auth} + s.rubygems_version = %q{1.3.1} + s.summary = %q{merb-auth. The official authentication plugin for merb. Setup for the default stack} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, ["~> 1.0"]) + s.add_runtime_dependency(%q, ["~> 1.0"]) + s.add_runtime_dependency(%q, ["~> 1.0"]) + s.add_runtime_dependency(%q, ["~> 1.0"]) + else + s.add_dependency(%q, ["~> 1.0"]) + s.add_dependency(%q, ["~> 1.0"]) + s.add_dependency(%q, ["~> 1.0"]) + s.add_dependency(%q, ["~> 1.0"]) + end + else + s.add_dependency(%q, ["~> 1.0"]) + s.add_dependency(%q, ["~> 1.0"]) + s.add_dependency(%q, ["~> 1.0"]) + s.add_dependency(%q, ["~> 1.0"]) + end +end diff --git a/gems/specifications/merb-auth-core-1.0.gemspec b/gems/specifications/merb-auth-core-1.0.gemspec new file mode 100644 index 0000000..37b746d --- /dev/null +++ b/gems/specifications/merb-auth-core-1.0.gemspec @@ -0,0 +1,36 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{merb-auth-core} + s.version = "1.0" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Adam French, Daniel Neighman"] + s.date = %q{2008-11-07} + s.description = %q{An Authentication framework for Merb} + s.email = %q{has.sox@gmail.com} + s.extra_rdoc_files = ["README.textile", "LICENSE", "TODO"] + s.files = ["LICENSE", "README.textile", "Rakefile", "TODO", "lib/merb-auth-core", "lib/merb-auth-core/authenticated_helper.rb", "lib/merb-auth-core/authentication.rb", "lib/merb-auth-core/bootloader.rb", "lib/merb-auth-core/callbacks.rb", "lib/merb-auth-core/customizations.rb", "lib/merb-auth-core/errors.rb", "lib/merb-auth-core/merbtasks.rb", "lib/merb-auth-core/responses.rb", "lib/merb-auth-core/router_helper.rb", "lib/merb-auth-core/session_mixin.rb", "lib/merb-auth-core/strategy.rb", "lib/merb-auth-core.rb", "spec/helpers", "spec/helpers/authentication_helper_spec.rb", "spec/merb-auth-core", "spec/merb-auth-core/activation_fixture.rb", "spec/merb-auth-core/authentication_spec.rb", "spec/merb-auth-core/callbacks_spec.rb", "spec/merb-auth-core/customizations_spec.rb", "spec/merb-auth-core/errors_spec.rb", "spec/merb-auth-core/failed_login_spec.rb", "spec/merb-auth-core/merb-auth-core_spec.rb", "spec/merb-auth-core/router_helper_spec.rb", "spec/merb-auth-core/strategy_spec.rb", "spec/spec_helper.rb"] + s.has_rdoc = true + s.homepage = %q{http://merbivore.com/} + s.require_paths = ["lib"] + s.rubyforge_project = %q{merb} + s.rubygems_version = %q{1.3.1} + s.summary = %q{An Authentication framework for Merb} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, ["~> 1.0"]) + s.add_runtime_dependency(%q, [">= 0"]) + else + s.add_dependency(%q, ["~> 1.0"]) + s.add_dependency(%q, [">= 0"]) + end + else + s.add_dependency(%q, ["~> 1.0"]) + s.add_dependency(%q, [">= 0"]) + end +end diff --git a/gems/specifications/merb-auth-more-1.0.gemspec b/gems/specifications/merb-auth-more-1.0.gemspec new file mode 100644 index 0000000..df7be79 --- /dev/null +++ b/gems/specifications/merb-auth-more-1.0.gemspec @@ -0,0 +1,33 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{merb-auth-more} + s.version = "1.0" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Daniel Neighman"] + s.date = %q{2008-11-07} + s.description = %q{Additional resources for use with the merb-auth-core authentication framework.} + s.email = %q{has.sox@gmail.com} + s.extra_rdoc_files = ["README.textile", "LICENSE", "TODO"] + s.files = ["LICENSE", "README.textile", "Rakefile", "TODO", "lib/merb-auth-more", "lib/merb-auth-more/mixins", "lib/merb-auth-more/mixins/redirect_back.rb", "lib/merb-auth-more/mixins/salted_user.rb", "lib/merb-auth-more/mixins/salted_user", "lib/merb-auth-more/mixins/salted_user/ar_salted_user.rb", "lib/merb-auth-more/mixins/salted_user/dm_salted_user.rb", "lib/merb-auth-more/mixins/salted_user/relaxdb_salted_user.rb", "lib/merb-auth-more/mixins/salted_user/sq_salted_user.rb", "lib/merb-auth-more/strategies", "lib/merb-auth-more/strategies/abstract_password.rb", "lib/merb-auth-more/strategies/basic", "lib/merb-auth-more/strategies/basic/password_form.rb", "lib/merb-auth-more/strategies/basic/basic_auth.rb", "lib/merb-auth-more/strategies/basic/openid.rb", "lib/merb-auth-more/merbtasks.rb", "lib/merb-auth-more.rb", "spec/mixins", "spec/mixins/redirect_back_spec.rb", "spec/mixins/salted_user_spec.rb", "spec/spec_helper.rb", "spec/merb-auth-more_spec.rb"] + s.has_rdoc = true + s.homepage = %q{http://merbivore.com/} + s.require_paths = ["lib"] + s.rubyforge_project = %q{merb} + s.rubygems_version = %q{1.3.1} + s.summary = %q{Additional resources for use with the merb-auth-core authentication framework.} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, [">= 1.0"]) + else + s.add_dependency(%q, [">= 1.0"]) + end + else + s.add_dependency(%q, [">= 1.0"]) + end +end diff --git a/gems/specifications/merb-auth-slice-password-1.0.gemspec b/gems/specifications/merb-auth-slice-password-1.0.gemspec new file mode 100644 index 0000000..d95225d --- /dev/null +++ b/gems/specifications/merb-auth-slice-password-1.0.gemspec @@ -0,0 +1,39 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{merb-auth-slice-password} + s.version = "1.0" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Daniel Neighman"] + s.date = %q{2008-11-07} + s.description = %q{Merb Slice that provides UI for password strategy of merb-auth.} + s.email = %q{has.sox@gmail.com} + s.extra_rdoc_files = ["README.textile", "LICENSE", "TODO"] + s.files = ["LICENSE", "README.textile", "Rakefile", "TODO", "lib/merb-auth-slice-password.rb", "lib/merb-auth-slice-password", "lib/merb-auth-slice-password/spectasks.rb", "lib/merb-auth-slice-password/slicetasks.rb", "lib/merb-auth-slice-password/merbtasks.rb", "spec/merb-auth-slice-password_spec.rb", "spec/spec_helper.rb", "app/controllers", "app/controllers/application.rb", "app/controllers/exceptions.rb", "app/controllers/sessions.rb", "app/views", "app/views/exceptions", "app/views/exceptions/unauthenticated.html.erb", "app/views/layout", "app/views/layout/merb-auth-slice-password.html.erb", "app/helpers", "app/helpers/application_helper.rb", "public/stylesheets", "public/stylesheets/master.css", "public/javascripts", "public/javascripts/master.js", "stubs/app", "stubs/app/controllers", "stubs/app/controllers/sessions.rb"] + s.has_rdoc = true + s.homepage = %q{http://merbivore.com/} + s.require_paths = ["lib"] + s.rubyforge_project = %q{merb} + s.rubygems_version = %q{1.3.1} + s.summary = %q{Merb Slice that provides UI for password strategy of merb-auth.} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, [">= 1.0"]) + s.add_runtime_dependency(%q, [">= 1.0"]) + s.add_runtime_dependency(%q, [">= 1.0"]) + else + s.add_dependency(%q, [">= 1.0"]) + s.add_dependency(%q, [">= 1.0"]) + s.add_dependency(%q, [">= 1.0"]) + end + else + s.add_dependency(%q, [">= 1.0"]) + s.add_dependency(%q, [">= 1.0"]) + s.add_dependency(%q, [">= 1.0"]) + end +end diff --git a/gems/specifications/merb-cache-1.0.gemspec b/gems/specifications/merb-cache-1.0.gemspec new file mode 100644 index 0000000..17b5e83 --- /dev/null +++ b/gems/specifications/merb-cache-1.0.gemspec @@ -0,0 +1,33 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{merb-cache} + s.version = "1.0" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Ben Burkert"] + s.date = %q{2008-11-07} + s.description = %q{Merb plugin that provides caching (page, action, fragment, object)} + s.email = %q{ben@benburkert.com} + s.extra_rdoc_files = ["README", "LICENSE", "TODO"] + s.files = ["LICENSE", "README", "Rakefile", "TODO", "lib/merb-cache", "lib/merb-cache/core_ext", "lib/merb-cache/core_ext/hash.rb", "lib/merb-cache/core_ext/enumerable.rb", "lib/merb-cache/merb_ext", "lib/merb-cache/merb_ext/controller.rb", "lib/merb-cache/cache_request.rb", "lib/merb-cache/cache.rb", "lib/merb-cache/stores", "lib/merb-cache/stores/strategy", "lib/merb-cache/stores/strategy/gzip_store.rb", "lib/merb-cache/stores/strategy/page_store.rb", "lib/merb-cache/stores/strategy/sha1_store.rb", "lib/merb-cache/stores/strategy/action_store.rb", "lib/merb-cache/stores/strategy/abstract_strategy_store.rb", "lib/merb-cache/stores/strategy/adhoc_store.rb", "lib/merb-cache/stores/fundamental", "lib/merb-cache/stores/fundamental/file_store.rb", "lib/merb-cache/stores/fundamental/abstract_store.rb", "lib/merb-cache/stores/fundamental/memcached_store.rb", "lib/merb-cache.rb", "spec/merb-cache", "spec/merb-cache/core_ext", "spec/merb-cache/core_ext/enumerable_spec.rb", "spec/merb-cache/core_ext/hash_spec.rb", "spec/merb-cache/merb_ext", "spec/merb-cache/merb_ext/controller_spec.rb", "spec/merb-cache/cache_request_spec.rb", "spec/merb-cache/cache_spec.rb", "spec/merb-cache/stores", "spec/merb-cache/stores/strategy", "spec/merb-cache/stores/strategy/gzip_store_spec.rb", "spec/merb-cache/stores/strategy/adhoc_store_spec.rb", "spec/merb-cache/stores/strategy/page_store_spec.rb", "spec/merb-cache/stores/strategy/action_store_spec.rb", "spec/merb-cache/stores/strategy/abstract_strategy_store_spec.rb", "spec/merb-cache/stores/strategy/sha1_store_spec.rb", "spec/merb-cache/stores/fundamental", "spec/merb-cache/stores/fundamental/file_store_spec.rb", "spec/merb-cache/stores/fundamental/memcached_store_spec.rb", "spec/merb-cache/stores/fundamental/abstract_store_spec.rb", "spec/spec_helper.rb"] + s.has_rdoc = true + s.homepage = %q{http://merbivore.com} + s.require_paths = ["lib"] + s.rubyforge_project = %q{merb} + s.rubygems_version = %q{1.3.1} + s.summary = %q{Merb plugin that provides caching (page, action, fragment, object)} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, [">= 1.0"]) + else + s.add_dependency(%q, [">= 1.0"]) + end + else + s.add_dependency(%q, [">= 1.0"]) + end +end diff --git a/gems/specifications/merb-core-1.0.gemspec b/gems/specifications/merb-core-1.0.gemspec new file mode 100644 index 0000000..3816fb7 --- /dev/null +++ b/gems/specifications/merb-core-1.0.gemspec @@ -0,0 +1,60 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{merb-core} + s.version = "1.0" + + s.required_rubygems_version = Gem::Requirement.new(">= 1.3.0") if s.respond_to? :required_rubygems_version= + s.authors = ["Ezra Zygmuntowicz"] + s.date = %q{2008-11-06} + s.default_executable = %q{merb} + s.description = %q{Merb. Pocket rocket web framework.} + s.email = %q{ez@engineyard.com} + s.executables = ["merb"] + s.extra_rdoc_files = ["README", "LICENSE", "TODO"] + s.files = ["LICENSE", "README", "Rakefile", "TODO", "CHANGELOG", "PUBLIC_CHANGELOG", "CONTRIBUTORS", "bin/merb", "bin/merb-specs", "lib/merb-core", "lib/merb-core/autoload.rb", "lib/merb-core/bootloader.rb", "lib/merb-core/config.rb", "lib/merb-core/constants.rb", "lib/merb-core/controller", "lib/merb-core/controller/abstract_controller.rb", "lib/merb-core/controller/exceptions.rb", "lib/merb-core/controller/merb_controller.rb", "lib/merb-core/controller/mime.rb", "lib/merb-core/controller/mixins", "lib/merb-core/controller/mixins/authentication.rb", "lib/merb-core/controller/mixins/conditional_get.rb", "lib/merb-core/controller/mixins/controller.rb", "lib/merb-core/controller/mixins/render.rb", "lib/merb-core/controller/mixins/responder.rb", "lib/merb-core/controller/template.rb", "lib/merb-core/core_ext", "lib/merb-core/core_ext/hash.rb", "lib/merb-core/core_ext/kernel.rb", "lib/merb-core/core_ext.rb", "lib/merb-core/dispatch", "lib/merb-core/dispatch/cookies.rb", "lib/merb-core/dispatch/default_exception", "lib/merb-core/dispatch/default_exception/default_exception.rb", "lib/merb-core/dispatch/default_exception/views", "lib/merb-core/dispatch/default_exception/views/_css.html.erb", "lib/merb-core/dispatch/default_exception/views/_javascript.html.erb", "lib/merb-core/dispatch/default_exception/views/index.html.erb", "lib/merb-core/dispatch/dispatcher.rb", "lib/merb-core/dispatch/request.rb", "lib/merb-core/dispatch/request_parsers.rb", "lib/merb-core/dispatch/router", "lib/merb-core/dispatch/router/behavior.rb", "lib/merb-core/dispatch/router/cached_proc.rb", "lib/merb-core/dispatch/router/resources.rb", "lib/merb-core/dispatch/router/route.rb", "lib/merb-core/dispatch/router.rb", "lib/merb-core/dispatch/session", "lib/merb-core/dispatch/session/container.rb", "lib/merb-core/dispatch/session/cookie.rb", "lib/merb-core/dispatch/session/memcached.rb", "lib/merb-core/dispatch/session/memory.rb", "lib/merb-core/dispatch/session/store_container.rb", "lib/merb-core/dispatch/session.rb", "lib/merb-core/dispatch/worker.rb", "lib/merb-core/gem_ext", "lib/merb-core/gem_ext/erubis.rb", "lib/merb-core/logger.rb", "lib/merb-core/plugins.rb", "lib/merb-core/rack", "lib/merb-core/rack/adapter", "lib/merb-core/rack/adapter/abstract.rb", "lib/merb-core/rack/adapter/ebb.rb", "lib/merb-core/rack/adapter/evented_mongrel.rb", "lib/merb-core/rack/adapter/fcgi.rb", "lib/merb-core/rack/adapter/irb.rb", "lib/merb-core/rack/adapter/mongrel.rb", "lib/merb-core/rack/adapter/runner.rb", "lib/merb-core/rack/adapter/swiftiplied_mongrel.rb", "lib/merb-core/rack/adapter/thin.rb", "lib/merb-core/rack/adapter/thin_turbo.rb", "lib/merb-core/rack/adapter/webrick.rb", "lib/merb-core/rack/adapter.rb", "lib/merb-core/rack/application.rb", "lib/merb-core/rack/handler", "lib/merb-core/rack/handler/mongrel.rb", "lib/merb-core/rack/helpers.rb", "lib/merb-core/rack/middleware", "lib/merb-core/rack/middleware/conditional_get.rb", "lib/merb-core/rack/middleware/content_length.rb", "lib/merb-core/rack/middleware/path_prefix.rb", "lib/merb-core/rack/middleware/profiler.rb", "lib/merb-core/rack/middleware/static.rb", "lib/merb-core/rack/middleware/tracer.rb", "lib/merb-core/rack/middleware.rb", "lib/merb-core/rack/stream_wrapper.rb", "lib/merb-core/rack.rb", "lib/merb-core/server.rb", "lib/merb-core/tasks", "lib/merb-core/tasks/audit.rake", "lib/merb-core/tasks/gem_management.rb", "lib/merb-core/tasks/merb.rb", "lib/merb-core/tasks/merb_rake_helper.rb", "lib/merb-core/tasks/stats.rake", "lib/merb-core/test", "lib/merb-core/test/helpers", "lib/merb-core/test/helpers/controller_helper.rb", "lib/merb-core/test/helpers/cookie_jar.rb", "lib/merb-core/test/helpers/mock_request_helper.rb", "lib/merb-core/test/helpers/multipart_request_helper.rb", "lib/merb-core/test/helpers/request_helper.rb", "lib/merb-core/test/helpers/route_helper.rb", "lib/merb-core/test/helpers.rb", "lib/merb-core/test/matchers", "lib/merb-core/test/matchers/controller_matchers.rb", "lib/merb-core/test/matchers/request_matchers.rb", "lib/merb-core/test/matchers/route_matchers.rb", "lib/merb-core/test/matchers.rb", "lib/merb-core/test/run_spec.rb", "lib/merb-core/test/run_specs.rb", "lib/merb-core/test/tasks", "lib/merb-core/test/tasks/spectasks.rb", "lib/merb-core/test/test_ext", "lib/merb-core/test/test_ext/hpricot.rb", "lib/merb-core/test/test_ext/object.rb", "lib/merb-core/test/test_ext/rspec.rb", "lib/merb-core/test/test_ext/string.rb", "lib/merb-core/test.rb", "lib/merb-core/version.rb", "lib/merb-core.rb"] + s.has_rdoc = true + s.homepage = %q{http://merbivore.com} + s.require_paths = ["lib"] + s.required_ruby_version = Gem::Requirement.new(">= 1.8.6") + s.requirements = ["install the json gem to get faster json parsing"] + s.rubygems_version = %q{1.3.1} + s.summary = %q{Merb. Pocket rocket web framework.} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, [">= 0.9.8"]) + s.add_runtime_dependency(%q, [">= 2.6.2"]) + s.add_runtime_dependency(%q, [">= 0"]) + s.add_runtime_dependency(%q, [">= 0"]) + s.add_runtime_dependency(%q, [">= 0"]) + s.add_runtime_dependency(%q, [">= 0"]) + s.add_runtime_dependency(%q, [">= 0"]) + s.add_runtime_dependency(%q, [">= 0.9.7"]) + s.add_development_dependency(%q, [">= 0.3.1"]) + else + s.add_dependency(%q, [">= 0.9.8"]) + s.add_dependency(%q, [">= 2.6.2"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0.9.7"]) + s.add_dependency(%q, [">= 0.3.1"]) + end + else + s.add_dependency(%q, [">= 0.9.8"]) + s.add_dependency(%q, [">= 2.6.2"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0.9.7"]) + s.add_dependency(%q, [">= 0.3.1"]) + end +end diff --git a/gems/specifications/merb-exceptions-1.0.gemspec b/gems/specifications/merb-exceptions-1.0.gemspec new file mode 100644 index 0000000..0a57ddd --- /dev/null +++ b/gems/specifications/merb-exceptions-1.0.gemspec @@ -0,0 +1,32 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{merb-exceptions} + s.version = "1.0" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Andy Kent"] + s.date = %q{2008-11-07} + s.description = %q{Email and web hook exceptions for Merb.} + s.email = %q{andy@new-bamboo.co.uk} + s.extra_rdoc_files = ["README.markdown", "LICENSE"] + s.files = ["LICENSE", "README.markdown", "Rakefile", "lib/merb-exceptions.rb", "lib/merb-exceptions", "lib/merb-exceptions/exceptions_helper.rb", "lib/merb-exceptions/templates", "lib/merb-exceptions/templates/email.erb", "lib/merb-exceptions/default_exception_extensions.rb", "lib/merb-exceptions/notification.rb", "spec/default_exception_extensions_spec.rb", "spec/exceptions_helper_spec.rb", "spec/notification_spec.rb", "spec/spec_helper.rb"] + s.has_rdoc = true + s.homepage = %q{http://merbivore.com} + s.require_paths = ["lib"] + s.rubygems_version = %q{1.3.1} + s.summary = %q{Email and web hook exceptions for Merb.} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, [">= 1.0"]) + else + s.add_dependency(%q, [">= 1.0"]) + end + else + s.add_dependency(%q, [">= 1.0"]) + end +end diff --git a/gems/specifications/merb-gen-1.0.gemspec b/gems/specifications/merb-gen-1.0.gemspec new file mode 100644 index 0000000..2b697f5 --- /dev/null +++ b/gems/specifications/merb-gen-1.0.gemspec @@ -0,0 +1,38 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{merb-gen} + s.version = "1.0" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Jonas Nicklas"] + s.date = %q{2008-11-07} + s.default_executable = %q{merb-gen} + s.description = %q{Generators suite for Merb.} + s.email = %q{jonas.nicklas@gmail.com} + s.executables = ["merb-gen"] + s.extra_rdoc_files = ["README", "LICENSE", "TODO"] + s.files = ["LICENSE", "README", "Rakefile", "TODO", "lib/generators", "lib/generators/controller.rb", "lib/generators/helper.rb", "lib/generators/layout.rb", "lib/generators/merb", "lib/generators/merb/merb_core.rb", "lib/generators/merb/merb_flat.rb", "lib/generators/merb/merb_stack.rb", "lib/generators/merb/merb_very_flat.rb", "lib/generators/merb_plugin.rb", "lib/generators/migration.rb", "lib/generators/model.rb", "lib/generators/part_controller.rb", "lib/generators/resource.rb", "lib/generators/resource_controller.rb", "lib/generators/session_migration.rb", "lib/generators/templates", "lib/generators/templates/application", "lib/generators/templates/application/common", "lib/generators/templates/application/common/doc.thor", "lib/generators/templates/application/common/dotgitignore", "lib/generators/templates/application/common/dothtaccess", "lib/generators/templates/application/common/jquery.js", "lib/generators/templates/application/common/merb.thor", "lib/generators/templates/application/common/Rakefile", "lib/generators/templates/application/merb_core", "lib/generators/templates/application/merb_core/app", "lib/generators/templates/application/merb_core/app/controllers", "lib/generators/templates/application/merb_core/app/controllers/application.rb", "lib/generators/templates/application/merb_core/app/controllers/exceptions.rb", "lib/generators/templates/application/merb_core/app/helpers", "lib/generators/templates/application/merb_core/app/helpers/global_helpers.rb", "lib/generators/templates/application/merb_core/app/views", "lib/generators/templates/application/merb_core/app/views/exceptions", "lib/generators/templates/application/merb_core/app/views/exceptions/not_acceptable.html.erb", "lib/generators/templates/application/merb_core/app/views/exceptions/not_found.html.erb", "lib/generators/templates/application/merb_core/autotest", "lib/generators/templates/application/merb_core/autotest/discover.rb", "lib/generators/templates/application/merb_core/autotest/merb.rb", "lib/generators/templates/application/merb_core/autotest/merb_rspec.rb", "lib/generators/templates/application/merb_core/config", "lib/generators/templates/application/merb_core/config/environments", "lib/generators/templates/application/merb_core/config/environments/development.rb", "lib/generators/templates/application/merb_core/config/environments/production.rb", "lib/generators/templates/application/merb_core/config/environments/rake.rb", "lib/generators/templates/application/merb_core/config/environments/staging.rb", "lib/generators/templates/application/merb_core/config/environments/test.rb", "lib/generators/templates/application/merb_core/config/init.rb", "lib/generators/templates/application/merb_core/config/rack.rb", "lib/generators/templates/application/merb_core/config/router.rb", "lib/generators/templates/application/merb_core/doc", "lib/generators/templates/application/merb_core/doc/rdoc", "lib/generators/templates/application/merb_core/doc/rdoc/generators", "lib/generators/templates/application/merb_core/doc/rdoc/generators/merb_generator.rb", "lib/generators/templates/application/merb_core/doc/rdoc/generators/template", "lib/generators/templates/application/merb_core/doc/rdoc/generators/template/merb", "lib/generators/templates/application/merb_core/doc/rdoc/generators/template/merb/api_grease.js", "lib/generators/templates/application/merb_core/doc/rdoc/generators/template/merb/index.html.erb", "lib/generators/templates/application/merb_core/doc/rdoc/generators/template/merb/merb.css", "lib/generators/templates/application/merb_core/doc/rdoc/generators/template/merb/merb.rb", "lib/generators/templates/application/merb_core/doc/rdoc/generators/template/merb/merb_doc_styles.css", "lib/generators/templates/application/merb_core/doc/rdoc/generators/template/merb/prototype.js", "lib/generators/templates/application/merb_core/lib", "lib/generators/templates/application/merb_core/lib/merb", "lib/generators/templates/application/merb_core/lib/merb/session.rb", "lib/generators/templates/application/merb_core/public", "lib/generators/templates/application/merb_core/public/favicon.ico", "lib/generators/templates/application/merb_core/public/images", "lib/generators/templates/application/merb_core/public/images/merb.jpg", "lib/generators/templates/application/merb_core/public/javascripts", "lib/generators/templates/application/merb_core/public/javascripts/application.js", "lib/generators/templates/application/merb_core/public/merb.fcgi", "lib/generators/templates/application/merb_core/public/robots.txt", "lib/generators/templates/application/merb_core/public/stylesheets", "lib/generators/templates/application/merb_core/public/stylesheets/master.css", "lib/generators/templates/application/merb_core/spec", "lib/generators/templates/application/merb_core/spec/spec.opts", "lib/generators/templates/application/merb_core/spec/spec_helper.rb", "lib/generators/templates/application/merb_core/test", "lib/generators/templates/application/merb_core/test/test_helper.rb", "lib/generators/templates/application/merb_flat", "lib/generators/templates/application/merb_flat/application.rbt", "lib/generators/templates/application/merb_flat/config", "lib/generators/templates/application/merb_flat/config/framework.rb", "lib/generators/templates/application/merb_flat/config/init.rb", "lib/generators/templates/application/merb_flat/README.txt", "lib/generators/templates/application/merb_flat/spec", "lib/generators/templates/application/merb_flat/spec/spec_helper.rb", "lib/generators/templates/application/merb_flat/test", "lib/generators/templates/application/merb_flat/test/test_helper.rb", "lib/generators/templates/application/merb_flat/views", "lib/generators/templates/application/merb_flat/views/foo.html.erb", "lib/generators/templates/application/merb_plugin", "lib/generators/templates/application/merb_plugin/lib", "lib/generators/templates/application/merb_plugin/lib/%base_name%", "lib/generators/templates/application/merb_plugin/lib/%base_name%/merbtasks.rb", "lib/generators/templates/application/merb_plugin/lib/%base_name%.rb", "lib/generators/templates/application/merb_plugin/LICENSE", "lib/generators/templates/application/merb_plugin/Rakefile", "lib/generators/templates/application/merb_plugin/README", "lib/generators/templates/application/merb_plugin/spec", "lib/generators/templates/application/merb_plugin/spec/%base_name%_spec.rb", "lib/generators/templates/application/merb_plugin/spec/spec_helper.rb", "lib/generators/templates/application/merb_plugin/test", "lib/generators/templates/application/merb_plugin/test/%base_name%_test.rb", "lib/generators/templates/application/merb_plugin/test/test_helper.rb", "lib/generators/templates/application/merb_plugin/TODO", "lib/generators/templates/application/merb_stack", "lib/generators/templates/application/merb_stack/app", "lib/generators/templates/application/merb_stack/app/controllers", "lib/generators/templates/application/merb_stack/app/controllers/application.rb", "lib/generators/templates/application/merb_stack/app/controllers/exceptions.rb", "lib/generators/templates/application/merb_stack/app/helpers", "lib/generators/templates/application/merb_stack/app/helpers/global_helpers.rb", "lib/generators/templates/application/merb_stack/app/models", "lib/generators/templates/application/merb_stack/app/models/user.rb", "lib/generators/templates/application/merb_stack/app/views", "lib/generators/templates/application/merb_stack/app/views/exceptions", "lib/generators/templates/application/merb_stack/app/views/exceptions/not_acceptable.html.erb", "lib/generators/templates/application/merb_stack/app/views/exceptions/not_found.html.erb", "lib/generators/templates/application/merb_stack/autotest", "lib/generators/templates/application/merb_stack/autotest/discover.rb", "lib/generators/templates/application/merb_stack/autotest/merb.rb", "lib/generators/templates/application/merb_stack/autotest/merb_rspec.rb", "lib/generators/templates/application/merb_stack/config", "lib/generators/templates/application/merb_stack/config/database.yml", "lib/generators/templates/application/merb_stack/config/dependencies.rb", "lib/generators/templates/application/merb_stack/config/environments", "lib/generators/templates/application/merb_stack/config/environments/development.rb", "lib/generators/templates/application/merb_stack/config/environments/production.rb", "lib/generators/templates/application/merb_stack/config/environments/rake.rb", "lib/generators/templates/application/merb_stack/config/environments/staging.rb", "lib/generators/templates/application/merb_stack/config/environments/test.rb", "lib/generators/templates/application/merb_stack/config/init.rb", "lib/generators/templates/application/merb_stack/config/rack.rb", "lib/generators/templates/application/merb_stack/config/router.rb", "lib/generators/templates/application/merb_stack/doc", "lib/generators/templates/application/merb_stack/doc/rdoc", "lib/generators/templates/application/merb_stack/doc/rdoc/generators", "lib/generators/templates/application/merb_stack/doc/rdoc/generators/merb_generator.rb", "lib/generators/templates/application/merb_stack/doc/rdoc/generators/template", "lib/generators/templates/application/merb_stack/doc/rdoc/generators/template/merb", "lib/generators/templates/application/merb_stack/doc/rdoc/generators/template/merb/api_grease.js", "lib/generators/templates/application/merb_stack/doc/rdoc/generators/template/merb/index.html.erb", "lib/generators/templates/application/merb_stack/doc/rdoc/generators/template/merb/merb.css", "lib/generators/templates/application/merb_stack/doc/rdoc/generators/template/merb/merb.rb", "lib/generators/templates/application/merb_stack/doc/rdoc/generators/template/merb/merb_doc_styles.css", "lib/generators/templates/application/merb_stack/doc/rdoc/generators/template/merb/prototype.js", "lib/generators/templates/application/merb_stack/merb", "lib/generators/templates/application/merb_stack/merb/merb-auth", "lib/generators/templates/application/merb_stack/merb/merb-auth/setup.rb", "lib/generators/templates/application/merb_stack/merb/merb-auth/strategies.rb", "lib/generators/templates/application/merb_stack/merb/session", "lib/generators/templates/application/merb_stack/merb/session/session.rb", "lib/generators/templates/application/merb_stack/public", "lib/generators/templates/application/merb_stack/public/favicon.ico", "lib/generators/templates/application/merb_stack/public/images", "lib/generators/templates/application/merb_stack/public/images/merb.jpg", "lib/generators/templates/application/merb_stack/public/javascripts", "lib/generators/templates/application/merb_stack/public/javascripts/application.js", "lib/generators/templates/application/merb_stack/public/merb.fcgi", "lib/generators/templates/application/merb_stack/public/robots.txt", "lib/generators/templates/application/merb_stack/public/stylesheets", "lib/generators/templates/application/merb_stack/public/stylesheets/master.css", "lib/generators/templates/application/merb_stack/spec", "lib/generators/templates/application/merb_stack/spec/spec.opts", "lib/generators/templates/application/merb_stack/spec/spec_helper.rb", "lib/generators/templates/application/merb_stack/test", "lib/generators/templates/application/merb_stack/test/test_helper.rb", "lib/generators/templates/application/merb_very_flat", "lib/generators/templates/application/merb_very_flat/application.rbt", "lib/generators/templates/application/merb_very_flat/spec", "lib/generators/templates/application/merb_very_flat/spec/spec_helper.rb", "lib/generators/templates/application/merb_very_flat/test", "lib/generators/templates/application/merb_very_flat/test/test_helper.rb", "lib/generators/templates/component", "lib/generators/templates/component/controller", "lib/generators/templates/component/controller/app", "lib/generators/templates/component/controller/app/controllers", "lib/generators/templates/component/controller/app/controllers/%file_name%.rb", "lib/generators/templates/component/controller/app/views", "lib/generators/templates/component/controller/app/views/%file_name%", "lib/generators/templates/component/controller/app/views/%file_name%/index.html.erb", "lib/generators/templates/component/controller/spec", "lib/generators/templates/component/controller/spec/requests", "lib/generators/templates/component/controller/spec/requests/%file_name%_spec.rb", "lib/generators/templates/component/controller/test", "lib/generators/templates/component/controller/test/requests", "lib/generators/templates/component/controller/test/requests/%file_name%_test.rb", "lib/generators/templates/component/helper", "lib/generators/templates/component/helper/app", "lib/generators/templates/component/helper/app/helpers", "lib/generators/templates/component/helper/app/helpers/%file_name%_helper.rb", "lib/generators/templates/component/layout", "lib/generators/templates/component/layout/app", "lib/generators/templates/component/layout/app/views", "lib/generators/templates/component/layout/app/views/layout", "lib/generators/templates/component/layout/app/views/layout/%file_name%.html.erb", "lib/generators/templates/component/layout/spec", "lib/generators/templates/component/layout/spec/views", "lib/generators/templates/component/layout/spec/views/layout", "lib/generators/templates/component/layout/spec/views/layout/%file_name%.html.erb_spec.rb", "lib/generators/templates/component/model", "lib/generators/templates/component/model/app", "lib/generators/templates/component/model/app/models", "lib/generators/templates/component/model/app/models/%file_name%.rb", "lib/generators/templates/component/model/spec", "lib/generators/templates/component/model/spec/models", "lib/generators/templates/component/model/spec/models/%file_name%_spec.rb", "lib/generators/templates/component/model/test", "lib/generators/templates/component/model/test/models", "lib/generators/templates/component/model/test/models/%file_name%_test.rb", "lib/generators/templates/component/part_controller", "lib/generators/templates/component/part_controller/app", "lib/generators/templates/component/part_controller/app/parts", "lib/generators/templates/component/part_controller/app/parts/%file_name%_part.rb", "lib/generators/templates/component/part_controller/app/parts/views", "lib/generators/templates/component/part_controller/app/parts/views/%file_name%_part", "lib/generators/templates/component/part_controller/app/parts/views/%file_name%_part/index.html.erb", "lib/generators/templates/component/resource_controller", "lib/generators/templates/component/resource_controller/app", "lib/generators/templates/component/resource_controller/app/controllers", "lib/generators/templates/component/resource_controller/app/controllers/%file_name%.rb", "lib/generators/templates/component/resource_controller/app/views", "lib/generators/templates/component/resource_controller/app/views/%file_name%", "lib/generators/templates/component/resource_controller/app/views/%file_name%/edit.html.erb", "lib/generators/templates/component/resource_controller/app/views/%file_name%/index.html.erb", "lib/generators/templates/component/resource_controller/app/views/%file_name%/new.html.erb", "lib/generators/templates/component/resource_controller/app/views/%file_name%/show.html.erb", "lib/generators/templates/component/resource_controller/spec", "lib/generators/templates/component/resource_controller/spec/requests", "lib/generators/templates/component/resource_controller/spec/requests/%file_name%_spec.rb", "lib/generators/templates/component/resource_controller/test", "lib/generators/templates/component/resource_controller/test/controllers", "lib/generators/templates/component/resource_controller/test/controllers/%file_name%_test.rb", "lib/merb-gen", "lib/merb-gen/app_generator.rb", "lib/merb-gen/generator.rb", "lib/merb-gen/named_generator.rb", "lib/merb-gen/namespaced_generator.rb", "lib/merb-gen.rb", "bin/merb-gen", "spec/controller_spec.rb", "spec/fixtures", "spec/fixtures/results", "spec/fixtures/results/no_modules.test", "spec/fixtures/results/some_modules.test", "spec/fixtures/templates", "spec/fixtures/templates/no_modules.test", "spec/fixtures/templates/some_modules.test", "spec/generator_spec.rb", "spec/layout_spec.rb", "spec/merb_core_spec.rb", "spec/merb_flat_spec.rb", "spec/merb_plugin_spec.rb", "spec/merb_stack_spec.rb", "spec/merb_very_flat_spec.rb", "spec/migration_spec.rb", "spec/model_spec.rb", "spec/named_generator_spec.rb", "spec/namespaced_generator_spec.rb", "spec/part_controller_spec.rb", "spec/resource_controller_spec.rb", "spec/resource_spec.rb", "spec/session_migration_spec.rb", "spec/spec_helper.rb"] + s.has_rdoc = true + s.homepage = %q{http://merbivore.com} + s.require_paths = ["lib"] + s.rubyforge_project = %q{merb} + s.rubygems_version = %q{1.3.1} + s.summary = %q{Generators suite for Merb.} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, [">= 1.0"]) + s.add_runtime_dependency(%q, [">= 0.3.3"]) + else + s.add_dependency(%q, [">= 1.0"]) + s.add_dependency(%q, [">= 0.3.3"]) + end + else + s.add_dependency(%q, [">= 1.0"]) + s.add_dependency(%q, [">= 0.3.3"]) + end +end diff --git a/gems/specifications/merb-haml-1.0.gemspec b/gems/specifications/merb-haml-1.0.gemspec new file mode 100644 index 0000000..51603f0 --- /dev/null +++ b/gems/specifications/merb-haml-1.0.gemspec @@ -0,0 +1,36 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{merb-haml} + s.version = "1.0" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Yehuda Katz"] + s.date = %q{2008-11-07} + s.description = %q{Merb plugin that provides HAML support} + s.email = %q{ykatz@engineyard.com} + s.extra_rdoc_files = ["README", "LICENSE", "TODO"] + s.files = ["LICENSE", "README", "Rakefile", "TODO", "Generators", "lib/generators", "lib/generators/controller.rb", "lib/generators/layout.rb", "lib/generators/resource_controller.rb", "lib/generators/templates", "lib/generators/templates/controller", "lib/generators/templates/controller/app", "lib/generators/templates/controller/app/views", "lib/generators/templates/controller/app/views/%file_name%", "lib/generators/templates/controller/app/views/%file_name%/index.html.haml", "lib/generators/templates/layout", "lib/generators/templates/layout/app", "lib/generators/templates/layout/app/views", "lib/generators/templates/layout/app/views/layout", "lib/generators/templates/layout/app/views/layout/%file_name%.html.haml", "lib/generators/templates/resource_controller", "lib/generators/templates/resource_controller/activerecord", "lib/generators/templates/resource_controller/activerecord/app", "lib/generators/templates/resource_controller/activerecord/app/views", "lib/generators/templates/resource_controller/activerecord/app/views/%file_name%", "lib/generators/templates/resource_controller/activerecord/app/views/%file_name%/edit.html.haml", "lib/generators/templates/resource_controller/activerecord/app/views/%file_name%/index.html.haml", "lib/generators/templates/resource_controller/activerecord/app/views/%file_name%/new.html.haml", "lib/generators/templates/resource_controller/activerecord/app/views/%file_name%/show.html.haml", "lib/generators/templates/resource_controller/datamapper", "lib/generators/templates/resource_controller/datamapper/app", "lib/generators/templates/resource_controller/datamapper/app/views", "lib/generators/templates/resource_controller/datamapper/app/views/%file_name%", "lib/generators/templates/resource_controller/datamapper/app/views/%file_name%/edit.html.haml", "lib/generators/templates/resource_controller/datamapper/app/views/%file_name%/index.html.haml", "lib/generators/templates/resource_controller/datamapper/app/views/%file_name%/new.html.haml", "lib/generators/templates/resource_controller/datamapper/app/views/%file_name%/show.html.haml", "lib/generators/templates/resource_controller/none", "lib/generators/templates/resource_controller/none/app", "lib/generators/templates/resource_controller/none/app/views", "lib/generators/templates/resource_controller/none/app/views/%file_name%", "lib/generators/templates/resource_controller/none/app/views/%file_name%/edit.html.haml", "lib/generators/templates/resource_controller/none/app/views/%file_name%/index.html.haml", "lib/generators/templates/resource_controller/none/app/views/%file_name%/new.html.haml", "lib/generators/templates/resource_controller/none/app/views/%file_name%/show.html.haml", "lib/generators/templates/resource_controller/sequel", "lib/generators/templates/resource_controller/sequel/app", "lib/generators/templates/resource_controller/sequel/app/views", "lib/generators/templates/resource_controller/sequel/app/views/%file_name%", "lib/generators/templates/resource_controller/sequel/app/views/%file_name%/edit.html.haml", "lib/generators/templates/resource_controller/sequel/app/views/%file_name%/index.html.haml", "lib/generators/templates/resource_controller/sequel/app/views/%file_name%/new.html.haml", "lib/generators/templates/resource_controller/sequel/app/views/%file_name%/show.html.haml", "lib/merb-haml", "lib/merb-haml/merbtasks.rb", "lib/merb-haml/template.rb", "lib/merb-haml.rb"] + s.has_rdoc = true + s.homepage = %q{http://merbivore.com} + s.require_paths = ["lib"] + s.rubyforge_project = %q{merb} + s.rubygems_version = %q{1.3.1} + s.summary = %q{Merb plugin that provides HAML support} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, ["= 1.0"]) + s.add_runtime_dependency(%q, [">= 2.0.3"]) + else + s.add_dependency(%q, ["= 1.0"]) + s.add_dependency(%q, [">= 2.0.3"]) + end + else + s.add_dependency(%q, ["= 1.0"]) + s.add_dependency(%q, [">= 2.0.3"]) + end +end diff --git a/gems/specifications/merb-helpers-1.0.gemspec b/gems/specifications/merb-helpers-1.0.gemspec new file mode 100644 index 0000000..7fdd7b0 --- /dev/null +++ b/gems/specifications/merb-helpers-1.0.gemspec @@ -0,0 +1,33 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{merb-helpers} + s.version = "1.0" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Michael D. Ivey"] + s.date = %q{2008-11-07} + s.description = %q{Helper support for Merb} + s.email = %q{ivey@gweezlebur.com} + s.extra_rdoc_files = ["README", "LICENSE", "TODO"] + s.files = ["LICENSE", "README", "Rakefile", "TODO", "lib/merb-helpers", "lib/merb-helpers/time_dsl.rb", "lib/merb-helpers/core_ext", "lib/merb-helpers/core_ext/numeric.rb", "lib/merb-helpers/form", "lib/merb-helpers/form/helpers.rb", "lib/merb-helpers/form/builder.rb", "lib/merb-helpers/form_helpers.rb", "lib/merb-helpers/date_time_formatting.rb", "lib/merb-helpers/tag_helpers.rb", "lib/merb-helpers/core_ext.rb", "lib/merb-helpers/text_helpers.rb", "lib/merb-helpers/date_time_helpers.rb", "lib/merb-helpers.rb", "spec/fixture", "spec/fixture/public", "spec/fixture/public/stylesheets", "spec/fixture/public/stylesheets/master.css", "spec/fixture/public/merb.fcgi", "spec/fixture/public/images", "spec/fixture/public/images/merb.jpg", "spec/fixture/app", "spec/fixture/app/controllers", "spec/fixture/app/controllers/relative_date_span.rb", "spec/fixture/app/controllers/bound_option_tag.rb", "spec/fixture/app/controllers/radio_group.rb", "spec/fixture/app/controllers/bound_file_field.rb", "spec/fixture/app/controllers/bound_text_field.rb", "spec/fixture/app/controllers/select.rb", "spec/fixture/app/controllers/label.rb", "spec/fixture/app/controllers/application.rb", "spec/fixture/app/controllers/exceptions.rb", "spec/fixture/app/controllers/field_set.rb", "spec/fixture/app/controllers/bound_radio_group.rb", "spec/fixture/app/controllers/form_for.rb", "spec/fixture/app/controllers/bound_check_box.rb", "spec/fixture/app/controllers/form.rb", "spec/fixture/app/controllers/bound_hidden_field.rb", "spec/fixture/app/controllers/bound_radio_button.rb", "spec/fixture/app/controllers/bound_text_area.rb", "spec/fixture/app/controllers/bound_password_field.rb", "spec/fixture/app/controllers/fields_for.rb", "spec/fixture/app/controllers/text_area.rb", "spec/fixture/app/controllers/foo.rb", "spec/fixture/app/controllers/submit.rb", "spec/fixture/app/controllers/button.rb", "spec/fixture/app/controllers/check_box.rb", "spec/fixture/app/controllers/custom_builder.rb", "spec/fixture/app/controllers/password_field.rb", "spec/fixture/app/controllers/radio_button.rb", "spec/fixture/app/controllers/tag_helper.rb", "spec/fixture/app/controllers/specs_controller.rb", "spec/fixture/app/controllers/numeric_ext.rb", "spec/fixture/app/controllers/delete_button.rb", "spec/fixture/app/controllers/bound_select.rb", "spec/fixture/app/controllers/file_field.rb", "spec/fixture/app/controllers/text_field.rb", "spec/fixture/app/controllers/hidden_field.rb", "spec/fixture/app/controllers/option_tag.rb", "spec/fixture/app/controllers/relative_date.rb", "spec/fixture/app/views", "spec/fixture/app/views/check_box_specs", "spec/fixture/app/views/check_box_specs/basic.html.erb", "spec/fixture/app/views/check_box_specs/raises_error_if_on_off_and_boolean_false.html.erb", "spec/fixture/app/views/check_box_specs/raise_unless_both_on_and_off.html.erb", "spec/fixture/app/views/check_box_specs/label.html.erb", "spec/fixture/app/views/check_box_specs/disabled.html.erb", "spec/fixture/app/views/check_box_specs/to_string.html.erb", "spec/fixture/app/views/check_box_specs/simple.html.erb", "spec/fixture/app/views/check_box_specs/boolean.html.erb", "spec/fixture/app/views/check_box_specs/unchecked.html.erb", "spec/fixture/app/views/check_box_specs/on_off_is_boolean.html.erb", "spec/fixture/app/views/check_box_specs/raises_error_if_not_boolean.html.erb", "spec/fixture/app/views/bound_password_field_specs", "spec/fixture/app/views/bound_password_field_specs/attributes.html.erb", "spec/fixture/app/views/bound_password_field_specs/basic.html.erb", "spec/fixture/app/views/bound_password_field_specs/label.html.erb", "spec/fixture/app/views/relative_date_span_specs", "spec/fixture/app/views/relative_date_span_specs/date_span_on_same_day.html.erb", "spec/fixture/app/views/relative_date_span_specs/date_span_on_same_day_on_different_year.html.erb", "spec/fixture/app/views/option_tag_specs", "spec/fixture/app/views/option_tag_specs/with_blank.html.erb", "spec/fixture/app/views/option_tag_specs/with_prompt.html.erb", "spec/fixture/app/views/option_tag_specs/collection.html.erb", "spec/fixture/app/views/option_tag_specs/array.html.erb", "spec/fixture/app/views/option_tag_specs/multiple_selects.html.erb", "spec/fixture/app/views/option_tag_specs/clean.html.erb", "spec/fixture/app/views/option_tag_specs/no_extra_attributes.html.erb", "spec/fixture/app/views/option_tag_specs/optgroups.html.erb", "spec/fixture/app/views/option_tag_specs/selected.html.erb", "spec/fixture/app/views/form_for_specs", "spec/fixture/app/views/form_for_specs/basic.html.erb", "spec/fixture/app/views/layout", "spec/fixture/app/views/layout/application.html.erb", "spec/fixture/app/views/bound_radio_group_specs", "spec/fixture/app/views/bound_radio_group_specs/basic.html.erb", "spec/fixture/app/views/bound_radio_group_specs/override_id.html.erb", "spec/fixture/app/views/bound_radio_group_specs/hashes.html.erb", "spec/fixture/app/views/bound_radio_group_specs/mixed.html.erb", "spec/fixture/app/views/label_specs", "spec/fixture/app/views/label_specs/basic.html.erb", "spec/fixture/app/views/password_field_specs", "spec/fixture/app/views/password_field_specs/basic.html.erb", "spec/fixture/app/views/password_field_specs/disabled.html.erb", "spec/fixture/app/views/bound_hidden_field_specs", "spec/fixture/app/views/bound_hidden_field_specs/basic.html.erb", "spec/fixture/app/views/bound_hidden_field_specs/label.html.erb", "spec/fixture/app/views/bound_hidden_field_specs/errors.html.erb", "spec/fixture/app/views/bound_hidden_field_specs/hidden_error.html.erb", "spec/fixture/app/views/button_specs", "spec/fixture/app/views/button_specs/button_with_values.html.erb", "spec/fixture/app/views/button_specs/button_with_label.html.erb", "spec/fixture/app/views/button_specs/disabled_button.html.erb", "spec/fixture/app/views/bound_option_tag_specs", "spec/fixture/app/views/bound_option_tag_specs/grouped.html.erb", "spec/fixture/app/views/bound_option_tag_specs/nested.html.erb", "spec/fixture/app/views/bound_option_tag_specs/text_and_value.html.erb", "spec/fixture/app/views/radio_button_specs", "spec/fixture/app/views/radio_button_specs/basic.html.erb", "spec/fixture/app/views/radio_button_specs/label.html.erb", "spec/fixture/app/views/radio_button_specs/disabled.html.erb", "spec/fixture/app/views/form_specs", "spec/fixture/app/views/form_specs/fake_put_if_set.html.erb", "spec/fixture/app/views/form_specs/get_if_set.html.erb", "spec/fixture/app/views/form_specs/create_a_form.html.erb", "spec/fixture/app/views/form_specs/create_a_multipart_form.html.erb", "spec/fixture/app/views/form_specs/post_by_default.html.erb", "spec/fixture/app/views/form_specs/resourceful_form.html.erb", "spec/fixture/app/views/form_specs/fake_delete_if_set.html.erb", "spec/fixture/app/views/exeptions", "spec/fixture/app/views/exeptions/not_acceptable.html.erb", "spec/fixture/app/views/exeptions/not_found.html.erb", "spec/fixture/app/views/exeptions/client_error.html.erb", "spec/fixture/app/views/exeptions/internal_server_error.html.erb", "spec/fixture/app/views/tag_helper", "spec/fixture/app/views/tag_helper/nested_tags.html.erb", "spec/fixture/app/views/tag_helper/tag_with_attributes.html.erb", "spec/fixture/app/views/tag_helper/tag_with_content.html.erb", "spec/fixture/app/views/tag_helper/tag_with_content_in_the_block.html.erb", "spec/fixture/app/views/select_specs", "spec/fixture/app/views/select_specs/multiple.html.erb", "spec/fixture/app/views/select_specs/blank.html.erb", "spec/fixture/app/views/bound_text_area_specs", "spec/fixture/app/views/bound_text_area_specs/basic.html.erb", "spec/fixture/app/views/delete_button_specs", "spec/fixture/app/views/delete_button_specs/delete_with_extra_params.html.erb", "spec/fixture/app/views/delete_button_specs/delete_with_label.html.erb", "spec/fixture/app/views/delete_button_specs/delete_with_explicit_url.html.erb", "spec/fixture/app/views/delete_button_specs/simple_delete.html.erb", "spec/fixture/app/views/bound_radio_button_specs", "spec/fixture/app/views/bound_radio_button_specs/basic.html.erb", "spec/fixture/app/views/radio_group_specs", "spec/fixture/app/views/radio_group_specs/attributes.html.erb", "spec/fixture/app/views/radio_group_specs/basic.html.erb", "spec/fixture/app/views/radio_group_specs/hash.html.erb", "spec/fixture/app/views/radio_group_specs/specific_attributes.html.erb", "spec/fixture/app/views/hidden_field_specs", "spec/fixture/app/views/hidden_field_specs/basic.html.erb", "spec/fixture/app/views/hidden_field_specs/label.html.erb", "spec/fixture/app/views/hidden_field_specs/disabled.html.erb", "spec/fixture/app/views/bound_select_specs", "spec/fixture/app/views/bound_select_specs/basic.html.erb", "spec/fixture/app/views/bound_select_specs/multiple.html.erb", "spec/fixture/app/views/bound_select_specs/prompt.html.erb", "spec/fixture/app/views/bound_select_specs/with_options_with_blank.html.erb", "spec/fixture/app/views/bound_select_specs/blank.html.erb", "spec/fixture/app/views/bound_select_specs/with_options.html.erb", "spec/fixture/app/views/foo", "spec/fixture/app/views/foo/bar.html.erb", "spec/fixture/app/views/numeric_ext_specs", "spec/fixture/app/views/numeric_ext_specs/minutes_to_hours.html.erb", "spec/fixture/app/views/numeric_ext_specs/to_concurrency_default.html.erb", "spec/fixture/app/views/numeric_ext_specs/two_digits.html.erb", "spec/fixture/app/views/fields_for_specs", "spec/fixture/app/views/fields_for_specs/basic.html.erb", "spec/fixture/app/views/fields_for_specs/nil.html.erb", "spec/fixture/app/views/fields_for_specs/midstream.html.erb", "spec/fixture/app/views/bound_text_field_specs", "spec/fixture/app/views/bound_text_field_specs/basic.html.erb", "spec/fixture/app/views/bound_file_field_specs", "spec/fixture/app/views/bound_file_field_specs/with_label.html.erb", "spec/fixture/app/views/bound_file_field_specs/additional_attributes.html.erb", "spec/fixture/app/views/bound_file_field_specs/takes_string.html.erb", "spec/fixture/app/views/custom_builder_specs", "spec/fixture/app/views/custom_builder_specs/everything.html.erb", "spec/fixture/app/views/bound_check_box_specs", "spec/fixture/app/views/bound_check_box_specs/basic.html.erb", "spec/fixture/app/views/bound_check_box_specs/on_and_off.html.erb", "spec/fixture/app/views/bound_check_box_specs/checked.html.erb", "spec/fixture/app/views/bound_check_box_specs/label.html.erb", "spec/fixture/app/views/bound_check_box_specs/errors.html.erb", "spec/fixture/app/views/bound_check_box_specs/raise_value_error.html.erb", "spec/fixture/app/views/fieldset_specs", "spec/fixture/app/views/fieldset_specs/legend.html.erb", "spec/fixture/app/views/relative_date_specs", "spec/fixture/app/views/relative_date_specs/relative_yesterday.html.erb", "spec/fixture/app/views/relative_date_specs/relative_date_with_year.html.erb", "spec/fixture/app/views/relative_date_specs/relative_today.html.erb", "spec/fixture/app/views/relative_date_specs/relative_date_without_year.html.erb", "spec/fixture/app/views/relative_date_specs/relative_tomorrow.html.erb", "spec/fixture/app/views/text_area_specs", "spec/fixture/app/views/text_area_specs/basic.html.erb", "spec/fixture/app/views/text_area_specs/nil.html.erb", "spec/fixture/app/views/text_area_specs/label.html.erb", "spec/fixture/app/views/text_area_specs/disabled.html.erb", "spec/fixture/app/views/file_field_specs", "spec/fixture/app/views/file_field_specs/with_label.html.erb", "spec/fixture/app/views/file_field_specs/makes_multipart.html.erb", "spec/fixture/app/views/file_field_specs/disabled.html.erb", "spec/fixture/app/views/file_field_specs/with_values.html.erb", "spec/fixture/app/views/text_field_specs", "spec/fixture/app/views/text_field_specs/basic.html.erb", "spec/fixture/app/views/text_field_specs/class.html.erb", "spec/fixture/app/views/text_field_specs/label.html.erb", "spec/fixture/app/views/text_field_specs/disabled.html.erb", "spec/fixture/app/views/submit_specs", "spec/fixture/app/views/submit_specs/submit_with_label.html.erb", "spec/fixture/app/views/submit_specs/submit_with_values.html.erb", "spec/fixture/app/views/submit_specs/disabled_submit.html.erb", "spec/fixture/app/helpers", "spec/fixture/app/helpers/global_helpers.rb", "spec/fixture/app/models", "spec/fixture/app/models/third_generic_fake_model.rb", "spec/fixture/app/models/fake_dm_model.rb", "spec/fixture/app/models/first_generic_fake_model.rb", "spec/fixture/app/models/second_generic_fake_model.rb", "spec/fixture/config", "spec/fixture/config/router.rb", "spec/fixture/config/init.rb", "spec/fixture/config/rack.rb", "spec/fixture/config/environments", "spec/fixture/config/environments/test.rb", "spec/fixture/config/environments/development.rb", "spec/fixture/config/environments/production.rb", "spec/merb_helpers_form_spec.rb", "spec/merb_helpers_text_spec.rb", "spec/numeric_extlib_spec.rb", "spec/time_dsl_spec.rb", "spec/core_ext_spec.rb", "spec/merb_helpers_tag_helper_spec.rb", "spec/ordinalize_spec.rb", "spec/spec_helper.rb", "spec/merb_helpers_config_spec.rb", "spec/merb_helpers_date_time_spec.rb"] + s.has_rdoc = true + s.homepage = %q{http://merbivore.com} + s.require_paths = ["lib"] + s.rubyforge_project = %q{merb} + s.rubygems_version = %q{1.3.1} + s.summary = %q{Helper support for Merb} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, [">= 1.0"]) + else + s.add_dependency(%q, [">= 1.0"]) + end + else + s.add_dependency(%q, [">= 1.0"]) + end +end diff --git a/gems/specifications/merb-mailer-1.0.gemspec b/gems/specifications/merb-mailer-1.0.gemspec new file mode 100644 index 0000000..08e0a7e --- /dev/null +++ b/gems/specifications/merb-mailer-1.0.gemspec @@ -0,0 +1,36 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{merb-mailer} + s.version = "1.0" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Yehuda Katz"] + s.date = %q{2008-11-07} + s.description = %q{Merb plugin that provides mailer functionality to Merb} + s.email = %q{ykatz@engineyard.com} + s.extra_rdoc_files = ["README.textile", "LICENSE", "TODO"] + s.files = ["LICENSE", "README.textile", "Rakefile", "TODO", "Generators", "lib/generators", "lib/generators/mailer_generator.rb", "lib/generators/templates", "lib/generators/templates/mailer", "lib/generators/templates/mailer/app", "lib/generators/templates/mailer/app/mailers", "lib/generators/templates/mailer/app/mailers/%file_name%_mailer.rb", "lib/generators/templates/mailer/app/mailers/views", "lib/generators/templates/mailer/app/mailers/views/%file_name%_mailer", "lib/generators/templates/mailer/app/mailers/views/%file_name%_mailer/notify_on_event.text.erb", "lib/generators/templates/mailer/spec", "lib/generators/templates/mailer/spec/mailers", "lib/generators/templates/mailer/spec/mailers/%file_name%_mailer_spec.rb", "lib/merb-mailer", "lib/merb-mailer/mail_controller.rb", "lib/merb-mailer/mailer.rb", "lib/merb-mailer/mailer_mixin.rb", "lib/merb-mailer.rb", "spec/mail_controller_spec.rb", "spec/mailer_generator_spec.rb", "spec/mailer_spec.rb", "spec/mailers", "spec/mailers/views", "spec/mailers/views/layout", "spec/mailers/views/layout/application.html.erb", "spec/mailers/views/layout/application.text.erb", "spec/mailers/views/test_mail_controller", "spec/mailers/views/test_mail_controller/eighth.html.erb", "spec/mailers/views/test_mail_controller/eighth.text.erb", "spec/mailers/views/test_mail_controller/first.html.erb", "spec/mailers/views/test_mail_controller/first.text.erb", "spec/mailers/views/test_mail_controller/generates_absolute_url.text.erb", "spec/mailers/views/test_mail_controller/generates_relative_url.text.erb", "spec/mailers/views/test_mail_controller/ninth.html.erb", "spec/mailers/views/test_mail_controller/ninth.text.erb", "spec/mailers/views/test_mail_controller/second.text.erb", "spec/mailers/views/test_mail_controller/third.html.erb", "spec/spec_helper.rb"] + s.has_rdoc = true + s.homepage = %q{http://merbivore.com} + s.require_paths = ["lib"] + s.rubyforge_project = %q{merb} + s.rubygems_version = %q{1.3.1} + s.summary = %q{Merb plugin that provides mailer functionality to Merb} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, [">= 1.0"]) + s.add_runtime_dependency(%q, [">= 1.2.3"]) + else + s.add_dependency(%q, [">= 1.0"]) + s.add_dependency(%q, [">= 1.2.3"]) + end + else + s.add_dependency(%q, [">= 1.0"]) + s.add_dependency(%q, [">= 1.2.3"]) + end +end diff --git a/gems/specifications/merb-more-1.0.gemspec b/gems/specifications/merb-more-1.0.gemspec new file mode 100644 index 0000000..255251f --- /dev/null +++ b/gems/specifications/merb-more-1.0.gemspec @@ -0,0 +1,67 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{merb-more} + s.version = "1.0" + + s.required_rubygems_version = Gem::Requirement.new(">= 1.3.0") if s.respond_to? :required_rubygems_version= + s.authors = ["Engine Yard"] + s.date = %q{2008-11-07} + s.description = %q{(merb - merb-core) == merb-more. The Full Stack. Take what you need; leave what you don't.} + s.email = %q{merb@engineyard.com} + s.files = ["LICENSE", "README", "Rakefile", "TODO", "lib/merb-more.rb"] + s.homepage = %q{http://www.merbivore.com} + s.require_paths = ["lib"] + s.rubyforge_project = %q{merb-more} + s.rubygems_version = %q{1.3.1} + s.summary = %q{(merb - merb-core) == merb-more. The Full Stack. Take what you need; leave what you don't.} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, [">= 1.0"]) + s.add_runtime_dependency(%q, [">= 1.0"]) + s.add_runtime_dependency(%q, [">= 1.0"]) + s.add_runtime_dependency(%q, [">= 1.0"]) + s.add_runtime_dependency(%q, [">= 1.0"]) + s.add_runtime_dependency(%q, [">= 1.0"]) + s.add_runtime_dependency(%q, [">= 1.0"]) + s.add_runtime_dependency(%q, [">= 1.0"]) + s.add_runtime_dependency(%q, [">= 1.0"]) + s.add_runtime_dependency(%q, [">= 1.0"]) + s.add_runtime_dependency(%q, [">= 1.0"]) + s.add_runtime_dependency(%q, [">= 1.0"]) + s.add_runtime_dependency(%q, [">= 1.0"]) + else + s.add_dependency(%q, [">= 1.0"]) + s.add_dependency(%q, [">= 1.0"]) + s.add_dependency(%q, [">= 1.0"]) + s.add_dependency(%q, [">= 1.0"]) + s.add_dependency(%q, [">= 1.0"]) + s.add_dependency(%q, [">= 1.0"]) + s.add_dependency(%q, [">= 1.0"]) + s.add_dependency(%q, [">= 1.0"]) + s.add_dependency(%q, [">= 1.0"]) + s.add_dependency(%q, [">= 1.0"]) + s.add_dependency(%q, [">= 1.0"]) + s.add_dependency(%q, [">= 1.0"]) + s.add_dependency(%q, [">= 1.0"]) + end + else + s.add_dependency(%q, [">= 1.0"]) + s.add_dependency(%q, [">= 1.0"]) + s.add_dependency(%q, [">= 1.0"]) + s.add_dependency(%q, [">= 1.0"]) + s.add_dependency(%q, [">= 1.0"]) + s.add_dependency(%q, [">= 1.0"]) + s.add_dependency(%q, [">= 1.0"]) + s.add_dependency(%q, [">= 1.0"]) + s.add_dependency(%q, [">= 1.0"]) + s.add_dependency(%q, [">= 1.0"]) + s.add_dependency(%q, [">= 1.0"]) + s.add_dependency(%q, [">= 1.0"]) + s.add_dependency(%q, [">= 1.0"]) + end +end diff --git a/gems/specifications/merb-param-protection-1.0.gemspec b/gems/specifications/merb-param-protection-1.0.gemspec new file mode 100644 index 0000000..79dcae9 --- /dev/null +++ b/gems/specifications/merb-param-protection-1.0.gemspec @@ -0,0 +1,33 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{merb-param-protection} + s.version = "1.0" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Lance Carlson"] + s.date = %q{2008-11-07} + s.description = %q{Merb plugin that provides params_accessible and params_protected class methods} + s.email = %q{lancecarlson@gmail.com} + s.extra_rdoc_files = ["README", "LICENSE"] + s.files = ["LICENSE", "README", "Rakefile", "lib/merb-param-protection", "lib/merb-param-protection/merbtasks.rb", "lib/merb-param-protection.rb"] + s.has_rdoc = true + s.homepage = %q{http://merbivore.com} + s.require_paths = ["lib"] + s.rubyforge_project = %q{merb} + s.rubygems_version = %q{1.3.1} + s.summary = %q{Merb plugin that provides params_accessible and params_protected class methods} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, [">= 1.0"]) + else + s.add_dependency(%q, [">= 1.0"]) + end + else + s.add_dependency(%q, [">= 1.0"]) + end +end diff --git a/gems/specifications/merb-slices-1.0.gemspec b/gems/specifications/merb-slices-1.0.gemspec new file mode 100644 index 0000000..718176c --- /dev/null +++ b/gems/specifications/merb-slices-1.0.gemspec @@ -0,0 +1,35 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{merb-slices} + s.version = "1.0" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Fabien Franzen"] + s.date = %q{2008-11-07} + s.default_executable = %q{slice} + s.description = %q{Merb-Slices is a Merb plugin for using and creating application 'slices' which help you modularize your application.} + s.email = %q{info@fabien.be} + s.executables = ["slice"] + s.extra_rdoc_files = ["README", "LICENSE", "TODO"] + s.files = ["LICENSE", "README", "Rakefile", "Generators", "TODO", "lib/generators", "lib/generators/base.rb", "lib/generators/full.rb", "lib/generators/templates", "lib/generators/templates/common", "lib/generators/templates/common/application.rb", "lib/generators/templates/common/lib", "lib/generators/templates/common/lib/%base_name%", "lib/generators/templates/common/lib/%base_name%/merbtasks.rb", "lib/generators/templates/common/lib/%base_name%/slicetasks.rb", "lib/generators/templates/common/lib/%base_name%/spectasks.rb", "lib/generators/templates/common/LICENSE", "lib/generators/templates/common/public", "lib/generators/templates/common/public/javascripts", "lib/generators/templates/common/public/javascripts/master.js", "lib/generators/templates/common/public/stylesheets", "lib/generators/templates/common/public/stylesheets/master.css", "lib/generators/templates/common/Rakefile", "lib/generators/templates/common/TODO", "lib/generators/templates/full", "lib/generators/templates/full/app", "lib/generators/templates/full/app/controllers", "lib/generators/templates/full/app/controllers/application.rb", "lib/generators/templates/full/app/controllers/main.rb", "lib/generators/templates/full/app/helpers", "lib/generators/templates/full/app/helpers/application_helper.rb", "lib/generators/templates/full/app/views", "lib/generators/templates/full/app/views/layout", "lib/generators/templates/full/app/views/layout/%symbol_name%.html.erb", "lib/generators/templates/full/app/views/main", "lib/generators/templates/full/app/views/main/index.html.erb", "lib/generators/templates/full/config", "lib/generators/templates/full/config/init.rb", "lib/generators/templates/full/config/router.rb", "lib/generators/templates/full/lib", "lib/generators/templates/full/lib/%base_name%.rb", "lib/generators/templates/full/Rakefile", "lib/generators/templates/full/README", "lib/generators/templates/full/spec", "lib/generators/templates/full/spec/%base_name%_spec.rb", "lib/generators/templates/full/spec/controllers", "lib/generators/templates/full/spec/controllers/main_spec.rb", "lib/generators/templates/full/spec/spec_helper.rb", "lib/generators/templates/full/stubs", "lib/generators/templates/full/stubs/app", "lib/generators/templates/full/stubs/app/controllers", "lib/generators/templates/full/stubs/app/controllers/application.rb", "lib/generators/templates/full/stubs/app/controllers/main.rb", "lib/generators/templates/full/TODO", "lib/generators/templates/thin", "lib/generators/templates/thin/lib", "lib/generators/templates/thin/lib/%base_name%.rb", "lib/generators/templates/thin/README", "lib/generators/templates/thin/stubs", "lib/generators/templates/thin/stubs/application.rb", "lib/generators/templates/thin/views", "lib/generators/templates/thin/views/layout", "lib/generators/templates/thin/views/layout/%symbol_name%.html.erb", "lib/generators/templates/thin/views/main", "lib/generators/templates/thin/views/main/index.html.erb", "lib/generators/templates/very_thin", "lib/generators/templates/very_thin/lib", "lib/generators/templates/very_thin/lib/%base_name%.rb", "lib/generators/templates/very_thin/README", "lib/generators/thin.rb", "lib/generators/very_thin.rb", "lib/merb-slices", "lib/merb-slices/controller_mixin.rb", "lib/merb-slices/merbtasks.rb", "lib/merb-slices/module.rb", "lib/merb-slices/module_mixin.rb", "lib/merb-slices/router_ext.rb", "lib/merb-slices.rb", "spec/full_slice_generator_spec.rb", "spec/full_slice_spec.rb", "spec/merb-slice_spec.rb", "spec/slice_generator_spec.rb", "spec/slices", "spec/slices/full-test-slice", "spec/slices/full-test-slice/app", "spec/slices/full-test-slice/app/controllers", "spec/slices/full-test-slice/app/controllers/application.rb", "spec/slices/full-test-slice/app/controllers/main.rb", "spec/slices/full-test-slice/app/helpers", "spec/slices/full-test-slice/app/helpers/application_helper.rb", "spec/slices/full-test-slice/app/views", "spec/slices/full-test-slice/app/views/layout", "spec/slices/full-test-slice/app/views/layout/full_test_slice.html.erb", "spec/slices/full-test-slice/app/views/main", "spec/slices/full-test-slice/app/views/main/index.html.erb", "spec/slices/full-test-slice/config", "spec/slices/full-test-slice/config/init.rb", "spec/slices/full-test-slice/lib", "spec/slices/full-test-slice/lib/full-test-slice", "spec/slices/full-test-slice/lib/full-test-slice/merbtasks.rb", "spec/slices/full-test-slice/lib/full-test-slice/slicetasks.rb", "spec/slices/full-test-slice/lib/full-test-slice/spectasks.rb", "spec/slices/full-test-slice/lib/full-test-slice.rb", "spec/slices/full-test-slice/LICENSE", "spec/slices/full-test-slice/public", "spec/slices/full-test-slice/public/javascripts", "spec/slices/full-test-slice/public/javascripts/master.js", "spec/slices/full-test-slice/public/stylesheets", "spec/slices/full-test-slice/public/stylesheets/master.css", "spec/slices/full-test-slice/Rakefile", "spec/slices/full-test-slice/README", "spec/slices/full-test-slice/stubs", "spec/slices/full-test-slice/stubs/app", "spec/slices/full-test-slice/stubs/app/controllers", "spec/slices/full-test-slice/stubs/app/controllers/application.rb", "spec/slices/full-test-slice/stubs/app/controllers/main.rb", "spec/slices/full-test-slice/TODO", "spec/slices/thin-test-slice", "spec/slices/thin-test-slice/application.rb", "spec/slices/thin-test-slice/lib", "spec/slices/thin-test-slice/lib/thin-test-slice", "spec/slices/thin-test-slice/lib/thin-test-slice/merbtasks.rb", "spec/slices/thin-test-slice/lib/thin-test-slice/slicetasks.rb", "spec/slices/thin-test-slice/lib/thin-test-slice.rb", "spec/slices/thin-test-slice/LICENSE", "spec/slices/thin-test-slice/public", "spec/slices/thin-test-slice/public/javascripts", "spec/slices/thin-test-slice/public/javascripts/master.js", "spec/slices/thin-test-slice/public/stylesheets", "spec/slices/thin-test-slice/public/stylesheets/master.css", "spec/slices/thin-test-slice/Rakefile", "spec/slices/thin-test-slice/README", "spec/slices/thin-test-slice/stubs", "spec/slices/thin-test-slice/stubs/application.rb", "spec/slices/thin-test-slice/TODO", "spec/slices/thin-test-slice/views", "spec/slices/thin-test-slice/views/layout", "spec/slices/thin-test-slice/views/layout/thin_test_slice.html.erb", "spec/slices/thin-test-slice/views/main", "spec/slices/thin-test-slice/views/main/index.html.erb", "spec/slices/very-thin-test-slice", "spec/slices/very-thin-test-slice/application.rb", "spec/slices/very-thin-test-slice/lib", "spec/slices/very-thin-test-slice/lib/very-thin-test-slice", "spec/slices/very-thin-test-slice/lib/very-thin-test-slice/merbtasks.rb", "spec/slices/very-thin-test-slice/lib/very-thin-test-slice/slicetasks.rb", "spec/slices/very-thin-test-slice/lib/very-thin-test-slice.rb", "spec/slices/very-thin-test-slice/LICENSE", "spec/slices/very-thin-test-slice/Rakefile", "spec/slices/very-thin-test-slice/README", "spec/slices/very-thin-test-slice/TODO", "spec/spec_helper.rb", "spec/thin_slice_generator_spec.rb", "spec/thin_slice_spec.rb", "spec/very_thin_slice_generator_spec.rb", "spec/very_thin_slice_spec.rb", "bin/slice"] + s.has_rdoc = true + s.homepage = %q{http://merbivore.com} + s.require_paths = ["lib"] + s.rubyforge_project = %q{merb} + s.rubygems_version = %q{1.3.1} + s.summary = %q{Merb-Slices is a Merb plugin for using and creating application 'slices' which help you modularize your application.} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, [">= 1.0"]) + else + s.add_dependency(%q, [">= 1.0"]) + end + else + s.add_dependency(%q, [">= 1.0"]) + end +end diff --git a/gems/specifications/merb_datamapper-1.0.gemspec b/gems/specifications/merb_datamapper-1.0.gemspec new file mode 100644 index 0000000..7dd032a --- /dev/null +++ b/gems/specifications/merb_datamapper-1.0.gemspec @@ -0,0 +1,39 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{merb_datamapper} + s.version = "1.0" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Jason Toy"] + s.date = %q{2008-11-07} + s.description = %q{DataMapper plugin providing DataMapper support for Merb} + s.email = %q{jtoy@rubynow.com} + s.extra_rdoc_files = ["LICENSE", "TODO"] + s.files = ["LICENSE", "Rakefile", "TODO", "Generators", "lib/generators", "lib/generators/data_mapper_migration.rb", "lib/generators/data_mapper_model.rb", "lib/generators/data_mapper_resource_controller.rb", "lib/generators/templates", "lib/generators/templates/migration.rb", "lib/generators/templates/model.rb", "lib/generators/templates/model_migration.rb", "lib/generators/templates/resource_controller.rb", "lib/generators/templates/views", "lib/generators/templates/views/edit.html.erb", "lib/generators/templates/views/index.html.erb", "lib/generators/templates/views/new.html.erb", "lib/generators/templates/views/show.html.erb", "lib/merb", "lib/merb/orms", "lib/merb/orms/data_mapper", "lib/merb/orms/data_mapper/connection.rb", "lib/merb/orms/data_mapper/database.yml.sample", "lib/merb/session", "lib/merb/session/data_mapper_session.rb", "lib/merb_datamapper", "lib/merb_datamapper/merbtasks.rb", "lib/merb_datamapper/version.rb", "lib/merb_datamapper.rb"] + s.has_rdoc = true + s.homepage = %q{http://merbivore.com} + s.require_paths = ["lib"] + s.rubyforge_project = %q{merb} + s.rubygems_version = %q{1.3.1} + s.summary = %q{DataMapper plugin providing DataMapper support for Merb} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, [">= 0.9.5"]) + s.add_runtime_dependency(%q, [">= 0.9.5"]) + s.add_runtime_dependency(%q, ["~> 1.0"]) + else + s.add_dependency(%q, [">= 0.9.5"]) + s.add_dependency(%q, [">= 0.9.5"]) + s.add_dependency(%q, ["~> 1.0"]) + end + else + s.add_dependency(%q, [">= 0.9.5"]) + s.add_dependency(%q, [">= 0.9.5"]) + s.add_dependency(%q, ["~> 1.0"]) + end +end diff --git a/gems/specifications/mime-types-1.15.gemspec b/gems/specifications/mime-types-1.15.gemspec new file mode 100644 index 0000000..eeacc0d --- /dev/null +++ b/gems/specifications/mime-types-1.15.gemspec @@ -0,0 +1,34 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{mime-types} + s.version = "1.15" + + s.required_rubygems_version = nil if s.respond_to? :required_rubygems_version= + s.authors = ["Austin Ziegler"] + s.cert_chain = nil + s.date = %q{2006-02-11} + s.description = %q{This library allows for the identification of a file's likely MIME content type. This is release 1.15. The identification of MIME content type is based on a file's filename extensions.} + s.email = %q{austin@rubyforge.org} + s.extra_rdoc_files = ["README", "ChangeLog", "Install"] + s.files = ["lib/mime", "lib/mime/types.rb", "tests/tc_mime_type.rb", "tests/tc_mime_types.rb", "tests/testall.rb", "ChangeLog", "README", "LICENCE", "setup.rb", "Rakefile", "pre-setup.rb", "Install"] + s.has_rdoc = true + s.homepage = %q{http://mime-types.rubyforge.org/} + s.rdoc_options = ["--title", "MIME::Types", "--main", "README", "--line-numbers"] + s.require_paths = ["lib"] + s.required_ruby_version = Gem::Requirement.new("> 0.0.0") + s.rubyforge_project = %q{mime-types} + s.rubygems_version = %q{1.3.1} + s.summary = %q{Manages a MIME Content-Type that will return the Content-Type for a given filename.} + s.test_files = ["tests/testall.rb"] + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 1 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + else + end + else + end +end diff --git a/gems/specifications/mongrel-1.1.5.gemspec b/gems/specifications/mongrel-1.1.5.gemspec new file mode 100644 index 0000000..e354a87 --- /dev/null +++ b/gems/specifications/mongrel-1.1.5.gemspec @@ -0,0 +1,49 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{mongrel} + s.version = "1.1.5" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Zed A. Shaw"] + s.cert_chain = ["-----BEGIN CERTIFICATE-----\nMIIDUDCCAjigAwIBAgIBADANBgkqhkiG9w0BAQUFADBOMRwwGgYDVQQDDBNtb25n\ncmVsLWRldmVsb3BtZW50MRkwFwYKCZImiZPyLGQBGRYJcnVieWZvcmdlMRMwEQYK\nCZImiZPyLGQBGRYDb3JnMB4XDTA3MDkxNjEwMzI0OVoXDTA4MDkxNTEwMzI0OVow\nTjEcMBoGA1UEAwwTbW9uZ3JlbC1kZXZlbG9wbWVudDEZMBcGCgmSJomT8ixkARkW\nCXJ1Ynlmb3JnZTETMBEGCgmSJomT8ixkARkWA29yZzCCASIwDQYJKoZIhvcNAQEB\nBQADggEPADCCAQoCggEBAMb9v3B01eOHk3FyypbQgKXzJplUE5P6dXoG+xpPm0Lv\nP7BQmeMncOwqQ7zXpVQU+lTpXtQFTsOE3vL7KnhQFJKGvUAkbh24VFyopu1I0yqF\nmGu4nRqNXGXVj8TvLSj4S1WpSRLAa0acLPNyKhGmoV9+crqQypSjM6XKjBeppifo\n4eBmWGjiJEYMIJBvJZPJ4rAVDDA8C6CM1m3gMBGNh8ELDhU8HI9AP3dMIkTI2Wx9\n9xkJwHdroAaS0IFFtYChrwee4FbCF1FHDgoTosMwa47DrLHg4hZ6ojaKwK5QVWEV\nXGb6ju5UqpktnSWF2W+Lvl/K0tI42OH2CAhebT1gEVUCAwEAAaM5MDcwCQYDVR0T\nBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0OBBYEFGHChyMSZ16u9WOzKhgJSQ9lqDc5\nMA0GCSqGSIb3DQEBBQUAA4IBAQA/lfeN2WdB1xN+82tT7vNS4HOjRQw6MUh5yktu\nGQjaGqm0UB+aX0Z9y0B0qpfv9rj7nmIvEGiwBmDepNWYCGuW15JyqpN7QVVnG2xS\nMrame7VqgjM7A+VGDD5In5LtWbM/CHAATvvFlQ5Ph13YE1EdnVbZ65c+KQv+5sFY\nQ+zEop74d878uaC/SAHHXS46TiXneocaLSYw1CEZs/MAIy+9c4Q5ESbGpgnfg1Ad\n6lwl7k3hsNHO/+tZzx4HJtOXDI1yAl3+q6T9J0yI3z97EinwvAKhS1eyOI2Y5eeT\ntbQaNYkU127B3l/VNpd8fQm3Jkl/PqCCmDBQjUszFrJEODug\n-----END CERTIFICATE-----\n", "-----BEGIN CERTIFICATE-----\nMIIDPzCCAiegAwIBAgIBADANBgkqhkiG9w0BAQUFADBOMRwwGgYDVQQDDBNtb25n\ncmVsLWRldmVsb3BtZW50MRkwFwYKCZImiZPyLGQBGRYJcnVieWZvcmdlMRMwEQYK\nCZImiZPyLGQBGRYDb3JnMB4XDTA3MDkxNjEwMzMwMFoXDTA4MDkxNTEwMzMwMFow\nPTENMAsGA1UEAwwEZXZhbjEYMBYGCgmSJomT8ixkARkWCGNsb3VkYnVyMRIwEAYK\nCZImiZPyLGQBGRYCc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDk\nLQijz2fICmev4+9s0WB71WzJFYCUYFQQxqGlenbxWut9dlPSsBbskGjg+UITeOXi\ncTh3MTqAB0i1LJyNOiyvDsAivn7GjKXhVvflp2/npMhBBe83P4HOWqeQBjkk3QJI\nFFNBvqbFLeEXIP+HiqAOiyNHZEVXMepLEJLzGrg3Ly7M7A6L5fK7jDrt8jkm+c+8\nzGquVHV5ohAebGd/vpHMLjpA7lCG5+MBgYZd33rRfNtCxDJMNRgnOu9PsB05+LJn\nMpDKQq3x0SkOf5A+MVOcadNCaAkFflYk3SUcXaXWxu/eCHgqfW1m76RNSp5djpKE\nCgNPK9lGIWpB3CHzDaVNAgMBAAGjOTA3MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSw\nMB0GA1UdDgQWBBT5aonPfFBdJ5rWFG+8dZwgyB54LjANBgkqhkiG9w0BAQUFAAOC\nAQEAiKbzWgMcvZs/TPwJxr8tJ+7mSGz7+zDkWcbBl8FpQq1DtRcATh1oyTkQT7t+\nrFEBYMmb0FxbbUnojQp8hIFgFkUwFpStwWBL/okLSehntzI2iwjuEtfj4ac9Q3Y2\nuSdbmZqsQTuu+lEUc5C4qLK7YKwToaul+cx7vWxyk1YendcVwRlFLIBqA5cPrwo3\nyyGLTHlRYn2c9PSbM1B63Yg+LqSSAa4QSU3Wv9pNdffVpvwHPVEQpO7ZDo5slQFL\nGf6+gbD/eZAvhpvmn8JlXb+LxKaFVMs2Yvrk1xOuT76SsPjEGWxkr7jZCIpsYfgQ\nALN3mi/9z0Mf1YroliUgF0v5Yw==\n-----END CERTIFICATE-----\n"] + s.date = %q{2008-05-21} + s.default_executable = %q{mongrel_rails} + s.description = %q{A small fast HTTP library and server that runs Rails, Camping, Nitro and Iowa apps.} + s.email = %q{} + s.executables = ["mongrel_rails"] + s.extensions = ["ext/http11/extconf.rb"] + s.extra_rdoc_files = ["CHANGELOG", "COPYING", "lib/mongrel/camping.rb", "lib/mongrel/cgi.rb", "lib/mongrel/command.rb", "lib/mongrel/configurator.rb", "lib/mongrel/const.rb", "lib/mongrel/debug.rb", "lib/mongrel/gems.rb", "lib/mongrel/handlers.rb", "lib/mongrel/header_out.rb", "lib/mongrel/http_request.rb", "lib/mongrel/http_response.rb", "lib/mongrel/init.rb", "lib/mongrel/rails.rb", "lib/mongrel/stats.rb", "lib/mongrel/tcphack.rb", "lib/mongrel/uri_classifier.rb", "lib/mongrel.rb", "LICENSE", "README"] + s.files = ["bin/mongrel_rails", "CHANGELOG", "COPYING", "examples/builder.rb", "examples/camping/blog.rb", "examples/camping/README", "examples/camping/tepee.rb", "examples/httpd.conf", "examples/mime.yaml", "examples/mongrel.conf", "examples/mongrel_simple_ctrl.rb", "examples/mongrel_simple_service.rb", "examples/monitrc", "examples/random_thrash.rb", "examples/simpletest.rb", "examples/webrick_compare.rb", "ext/http11/ext_help.h", "ext/http11/extconf.rb", "ext/http11/http11.c", "ext/http11/http11_parser.c", "ext/http11/http11_parser.h", "ext/http11/http11_parser.java.rl", "ext/http11/http11_parser.rl", "ext/http11/http11_parser_common.rl", "ext/http11_java/Http11Service.java", "ext/http11_java/org/jruby/mongrel/Http11.java", "ext/http11_java/org/jruby/mongrel/Http11Parser.java", "lib/mongrel/camping.rb", "lib/mongrel/cgi.rb", "lib/mongrel/command.rb", "lib/mongrel/configurator.rb", "lib/mongrel/const.rb", "lib/mongrel/debug.rb", "lib/mongrel/gems.rb", "lib/mongrel/handlers.rb", "lib/mongrel/header_out.rb", "lib/mongrel/http_request.rb", "lib/mongrel/http_response.rb", "lib/mongrel/init.rb", "lib/mongrel/mime_types.yml", "lib/mongrel/rails.rb", "lib/mongrel/stats.rb", "lib/mongrel/tcphack.rb", "lib/mongrel/uri_classifier.rb", "lib/mongrel.rb", "LICENSE", "Manifest", "mongrel-public_cert.pem", "mongrel.gemspec", "README", "setup.rb", "test/mime.yaml", "test/mongrel.conf", "test/test_cgi_wrapper.rb", "test/test_command.rb", "test/test_conditional.rb", "test/test_configurator.rb", "test/test_debug.rb", "test/test_handlers.rb", "test/test_http11.rb", "test/test_redirect_handler.rb", "test/test_request_progress.rb", "test/test_response.rb", "test/test_stats.rb", "test/test_uriclassifier.rb", "test/test_ws.rb", "test/testhelp.rb", "TODO", "tools/trickletest.rb"] + s.has_rdoc = true + s.homepage = %q{http://mongrel.rubyforge.org} + s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Mongrel", "--main", "README"] + s.require_paths = ["lib", "ext"] + s.required_ruby_version = Gem::Requirement.new(">= 1.8.4") + s.rubyforge_project = %q{mongrel} + s.rubygems_version = %q{1.3.1} + s.summary = %q{A small fast HTTP library and server that runs Rails, Camping, Nitro and Iowa apps.} + s.test_files = ["test/test_cgi_wrapper.rb", "test/test_command.rb", "test/test_conditional.rb", "test/test_configurator.rb", "test/test_debug.rb", "test/test_handlers.rb", "test/test_http11.rb", "test/test_redirect_handler.rb", "test/test_request_progress.rb", "test/test_response.rb", "test/test_stats.rb", "test/test_uriclassifier.rb", "test/test_ws.rb"] + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, [">= 0.2.3"]) + s.add_runtime_dependency(%q, [">= 1.0.3"]) + s.add_runtime_dependency(%q, [">= 1.0.1"]) + s.add_runtime_dependency(%q, [">= 2.4"]) + else + s.add_dependency(%q, [">= 0.2.3"]) + s.add_dependency(%q, [">= 1.0.3"]) + s.add_dependency(%q, [">= 1.0.1"]) + s.add_dependency(%q, [">= 2.4"]) + end + else + s.add_dependency(%q, [">= 0.2.3"]) + s.add_dependency(%q, [">= 1.0.3"]) + s.add_dependency(%q, [">= 1.0.1"]) + s.add_dependency(%q, [">= 2.4"]) + end +end diff --git a/gems/specifications/nokogiri-1.0.6.gemspec b/gems/specifications/nokogiri-1.0.6.gemspec new file mode 100644 index 0000000..5e8aaa2 --- /dev/null +++ b/gems/specifications/nokogiri-1.0.6.gemspec @@ -0,0 +1,33 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{nokogiri} + s.version = "1.0.6" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Aaron Patterson", "Mike Dalessio"] + s.date = %q{2008-11-14} + s.description = %q{Nokogiri (鋸) is an HTML, XML, SAX, and Reader parser.} + s.email = ["aaronp@rubyforge.org", "mike.dalessio@gmail.com"] + s.extensions = ["Rakefile"] + s.extra_rdoc_files = ["History.ja.txt", "History.txt", "Manifest.txt", "README.ja.txt", "README.txt"] + s.files = ["History.ja.txt", "History.txt", "Manifest.txt", "README.ja.txt", "README.txt", "Rakefile", "ext/nokogiri/extconf.rb", "ext/nokogiri/html_document.c", "ext/nokogiri/html_document.h", "ext/nokogiri/html_sax_parser.c", "ext/nokogiri/html_sax_parser.h", "ext/nokogiri/native.c", "ext/nokogiri/native.h", "ext/nokogiri/xml_cdata.c", "ext/nokogiri/xml_cdata.h", "ext/nokogiri/xml_document.c", "ext/nokogiri/xml_document.h", "ext/nokogiri/xml_dtd.c", "ext/nokogiri/xml_dtd.h", "ext/nokogiri/xml_io.c", "ext/nokogiri/xml_io.h", "ext/nokogiri/xml_node.c", "ext/nokogiri/xml_node.h", "ext/nokogiri/xml_node_set.c", "ext/nokogiri/xml_node_set.h", "ext/nokogiri/xml_reader.c", "ext/nokogiri/xml_reader.h", "ext/nokogiri/xml_sax_parser.c", "ext/nokogiri/xml_sax_parser.h", "ext/nokogiri/xml_syntax_error.c", "ext/nokogiri/xml_syntax_error.h", "ext/nokogiri/xml_text.c", "ext/nokogiri/xml_text.h", "ext/nokogiri/xml_xpath.c", "ext/nokogiri/xml_xpath.h", "ext/nokogiri/xml_xpath_context.c", "ext/nokogiri/xml_xpath_context.h", "ext/nokogiri/xslt_stylesheet.c", "ext/nokogiri/xslt_stylesheet.h", "lib/nokogiri.rb", "lib/nokogiri/css.rb", "lib/nokogiri/css/generated_parser.rb", "lib/nokogiri/css/generated_tokenizer.rb", "lib/nokogiri/css/node.rb", "lib/nokogiri/css/parser.rb", "lib/nokogiri/css/parser.y", "lib/nokogiri/css/syntax_error.rb", "lib/nokogiri/css/tokenizer.rb", "lib/nokogiri/css/tokenizer.rex", "lib/nokogiri/css/xpath_visitor.rb", "lib/nokogiri/decorators.rb", "lib/nokogiri/decorators/hpricot.rb", "lib/nokogiri/decorators/hpricot/node.rb", "lib/nokogiri/decorators/hpricot/node_set.rb", "lib/nokogiri/decorators/hpricot/xpath_visitor.rb", "lib/nokogiri/hpricot.rb", "lib/nokogiri/html.rb", "lib/nokogiri/html/builder.rb", "lib/nokogiri/html/document.rb", "lib/nokogiri/html/sax/parser.rb", "lib/nokogiri/version.rb", "lib/nokogiri/xml.rb", "lib/nokogiri/xml/after_handler.rb", "lib/nokogiri/xml/before_handler.rb", "lib/nokogiri/xml/builder.rb", "lib/nokogiri/xml/cdata.rb", "lib/nokogiri/xml/document.rb", "lib/nokogiri/xml/dtd.rb", "lib/nokogiri/xml/element.rb", "lib/nokogiri/xml/entity_declaration.rb", "lib/nokogiri/xml/node.rb", "lib/nokogiri/xml/node_set.rb", "lib/nokogiri/xml/notation.rb", "lib/nokogiri/xml/reader.rb", "lib/nokogiri/xml/sax.rb", "lib/nokogiri/xml/sax/document.rb", "lib/nokogiri/xml/sax/parser.rb", "lib/nokogiri/xml/syntax_error.rb", "lib/nokogiri/xml/text.rb", "lib/nokogiri/xml/xpath.rb", "lib/nokogiri/xml/xpath/syntax_error.rb", "lib/nokogiri/xml/xpath_context.rb", "lib/nokogiri/xslt.rb", "lib/nokogiri/xslt/stylesheet.rb", "test/css/test_nthiness.rb", "test/css/test_parser.rb", "test/css/test_tokenizer.rb", "test/css/test_xpath_visitor.rb", "test/files/dont_hurt_em_why.xml", "test/files/staff.xml", "test/files/staff.xslt", "test/files/tlm.html", "test/helper.rb", "test/hpricot/files/basic.xhtml", "test/hpricot/files/boingboing.html", "test/hpricot/files/cy0.html", "test/hpricot/files/immob.html", "test/hpricot/files/pace_application.html", "test/hpricot/files/tenderlove.html", "test/hpricot/files/uswebgen.html", "test/hpricot/files/utf8.html", "test/hpricot/files/week9.html", "test/hpricot/files/why.xml", "test/hpricot/load_files.rb", "test/hpricot/test_alter.rb", "test/hpricot/test_builder.rb", "test/hpricot/test_parser.rb", "test/hpricot/test_paths.rb", "test/hpricot/test_preserved.rb", "test/hpricot/test_xml.rb", "test/html/sax/test_parser.rb", "test/html/test_builder.rb", "test/html/test_document.rb", "test/test_convert_xpath.rb", "test/test_css_cache.rb", "test/test_gc.rb", "test/test_nokogiri.rb", "test/test_reader.rb", "test/test_xslt_transforms.rb", "test/xml/sax/test_parser.rb", "test/xml/test_builder.rb", "test/xml/test_cdata.rb", "test/xml/test_document.rb", "test/xml/test_dtd.rb", "test/xml/test_node.rb", "test/xml/test_node_set.rb", "test/xml/test_text.rb", "vendor/hoe.rb"] + s.has_rdoc = true + s.homepage = %q{http://nokogiri.rubyforge.org/} + s.rdoc_options = ["--main", "README.txt"] + s.require_paths = ["lib", "ext"] + s.rubyforge_project = %q{nokogiri} + s.rubygems_version = %q{1.3.1} + s.summary = %q{Nokogiri (鋸) is an HTML, XML, SAX, and Reader parser.} + s.test_files = ["test/css/test_nthiness.rb", "test/css/test_parser.rb", "test/css/test_tokenizer.rb", "test/css/test_xpath_visitor.rb", "test/hpricot/test_alter.rb", "test/hpricot/test_builder.rb", "test/hpricot/test_parser.rb", "test/hpricot/test_paths.rb", "test/hpricot/test_preserved.rb", "test/hpricot/test_xml.rb", "test/html/sax/test_parser.rb", "test/html/test_builder.rb", "test/html/test_document.rb", "test/test_convert_xpath.rb", "test/test_css_cache.rb", "test/test_gc.rb", "test/test_nokogiri.rb", "test/test_reader.rb", "test/test_xslt_transforms.rb", "test/xml/sax/test_parser.rb", "test/xml/test_builder.rb", "test/xml/test_cdata.rb", "test/xml/test_document.rb", "test/xml/test_dtd.rb", "test/xml/test_node.rb", "test/xml/test_node_set.rb", "test/xml/test_text.rb"] + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + else + end + else + end +end diff --git a/gems/specifications/rack-0.4.0.gemspec b/gems/specifications/rack-0.4.0.gemspec new file mode 100644 index 0000000..f705e2d --- /dev/null +++ b/gems/specifications/rack-0.4.0.gemspec @@ -0,0 +1,33 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{rack} + s.version = "0.4.0" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Christian Neukirchen"] + s.date = %q{2008-08-20} + s.default_executable = %q{rackup} + s.description = %q{Rack provides minimal, modular and adaptable interface for developing web applications in Ruby. By wrapping HTTP requests and responses in the simplest way possible, it unifies and distills the API for web servers, web frameworks, and software in between (the so-called middleware) into a single method call. Also see http://rack.rubyforge.org.} + s.email = %q{chneukirchen@gmail.com} + s.executables = ["rackup"] + s.extra_rdoc_files = ["README", "SPEC", "RDOX", "KNOWN-ISSUES"] + s.files = ["AUTHORS", "COPYING", "KNOWN-ISSUES", "README", "Rakefile", "bin/rackup", "contrib/rack_logo.svg", "example/lobster.ru", "example/protectedlobster.rb", "example/protectedlobster.ru", "lib/rack.rb", "lib/rack/adapter/camping.rb", "lib/rack/auth/abstract/handler.rb", "lib/rack/auth/abstract/request.rb", "lib/rack/auth/basic.rb", "lib/rack/auth/digest/md5.rb", "lib/rack/auth/digest/nonce.rb", "lib/rack/auth/digest/params.rb", "lib/rack/auth/digest/request.rb", "lib/rack/auth/openid.rb", "lib/rack/builder.rb", "lib/rack/cascade.rb", "lib/rack/commonlogger.rb", "lib/rack/deflater.rb", "lib/rack/directory.rb", "lib/rack/file.rb", "lib/rack/handler.rb", "lib/rack/handler/cgi.rb", "lib/rack/handler/evented_mongrel.rb", "lib/rack/handler/fastcgi.rb", "lib/rack/handler/lsws.rb", "lib/rack/handler/mongrel.rb", "lib/rack/handler/scgi.rb", "lib/rack/handler/webrick.rb", "lib/rack/lint.rb", "lib/rack/lobster.rb", "lib/rack/mock.rb", "lib/rack/recursive.rb", "lib/rack/reloader.rb", "lib/rack/request.rb", "lib/rack/response.rb", "lib/rack/session/abstract/id.rb", "lib/rack/session/cookie.rb", "lib/rack/session/memcache.rb", "lib/rack/session/pool.rb", "lib/rack/showexceptions.rb", "lib/rack/showstatus.rb", "lib/rack/static.rb", "lib/rack/urlmap.rb", "lib/rack/utils.rb", "test/cgi/lighttpd.conf", "test/cgi/test", "test/cgi/test.fcgi", "test/cgi/test.ru", "test/spec_rack_auth_basic.rb", "test/spec_rack_auth_digest.rb", "test/spec_rack_auth_openid.rb", "test/spec_rack_builder.rb", "test/spec_rack_camping.rb", "test/spec_rack_cascade.rb", "test/spec_rack_cgi.rb", "test/spec_rack_commonlogger.rb", "test/spec_rack_deflater.rb", "test/spec_rack_directory.rb", "test/spec_rack_fastcgi.rb", "test/spec_rack_file.rb", "test/spec_rack_handler.rb", "test/spec_rack_lint.rb", "test/spec_rack_lobster.rb", "test/spec_rack_mock.rb", "test/spec_rack_mongrel.rb", "test/spec_rack_recursive.rb", "test/spec_rack_request.rb", "test/spec_rack_response.rb", "test/spec_rack_session_cookie.rb", "test/spec_rack_session_memcache.rb", "test/spec_rack_session_pool.rb", "test/spec_rack_showexceptions.rb", "test/spec_rack_showstatus.rb", "test/spec_rack_static.rb", "test/spec_rack_urlmap.rb", "test/spec_rack_utils.rb", "test/spec_rack_webrick.rb", "test/testrequest.rb", "SPEC", "RDOX"] + s.has_rdoc = true + s.homepage = %q{http://rack.rubyforge.org} + s.require_paths = ["lib"] + s.rubyforge_project = %q{rack} + s.rubygems_version = %q{1.3.1} + s.summary = %q{a modular Ruby webserver interface} + s.test_files = ["test/spec_rack_auth_basic.rb", "test/spec_rack_auth_digest.rb", "test/spec_rack_auth_openid.rb", "test/spec_rack_builder.rb", "test/spec_rack_camping.rb", "test/spec_rack_cascade.rb", "test/spec_rack_cgi.rb", "test/spec_rack_commonlogger.rb", "test/spec_rack_deflater.rb", "test/spec_rack_directory.rb", "test/spec_rack_fastcgi.rb", "test/spec_rack_file.rb", "test/spec_rack_handler.rb", "test/spec_rack_lint.rb", "test/spec_rack_lobster.rb", "test/spec_rack_mock.rb", "test/spec_rack_mongrel.rb", "test/spec_rack_recursive.rb", "test/spec_rack_request.rb", "test/spec_rack_response.rb", "test/spec_rack_session_cookie.rb", "test/spec_rack_session_memcache.rb", "test/spec_rack_session_pool.rb", "test/spec_rack_showexceptions.rb", "test/spec_rack_showstatus.rb", "test/spec_rack_static.rb", "test/spec_rack_urlmap.rb", "test/spec_rack_utils.rb", "test/spec_rack_webrick.rb"] + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + else + end + else + end +end diff --git a/gems/specifications/rake-0.8.3.gemspec b/gems/specifications/rake-0.8.3.gemspec new file mode 100644 index 0000000..6e03751 --- /dev/null +++ b/gems/specifications/rake-0.8.3.gemspec @@ -0,0 +1,33 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{rake} + s.version = "0.8.3" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Jim Weirich"] + s.date = %q{2008-09-24} + s.default_executable = %q{rake} + s.description = %q{Rake is a Make-like program implemented in Ruby. Tasks and dependencies are specified in standard Ruby syntax.} + s.email = %q{jim@weirichhouse.org} + s.executables = ["rake"] + s.extra_rdoc_files = ["README", "MIT-LICENSE", "TODO", "CHANGES", "doc/glossary.rdoc", "doc/proto_rake.rdoc", "doc/rakefile.rdoc", "doc/rational.rdoc", "doc/release_notes/rake-0.4.14.rdoc", "doc/release_notes/rake-0.4.15.rdoc", "doc/release_notes/rake-0.5.0.rdoc", "doc/release_notes/rake-0.5.3.rdoc", "doc/release_notes/rake-0.5.4.rdoc", "doc/release_notes/rake-0.6.0.rdoc", "doc/release_notes/rake-0.7.0.rdoc", "doc/release_notes/rake-0.7.1.rdoc", "doc/release_notes/rake-0.7.2.rdoc", "doc/release_notes/rake-0.7.3.rdoc", "doc/release_notes/rake-0.8.0.rdoc", "doc/release_notes/rake-0.8.2.rdoc", "doc/release_notes/rake-0.8.3.rdoc"] + s.files = ["install.rb", "CHANGES", "MIT-LICENSE", "Rakefile", "README", "TODO", "bin/rake", "lib/rake/classic_namespace.rb", "lib/rake/clean.rb", "lib/rake/contrib/compositepublisher.rb", "lib/rake/contrib/ftptools.rb", "lib/rake/contrib/publisher.rb", "lib/rake/contrib/rubyforgepublisher.rb", "lib/rake/contrib/sshpublisher.rb", "lib/rake/contrib/sys.rb", "lib/rake/gempackagetask.rb", "lib/rake/loaders/makefile.rb", "lib/rake/packagetask.rb", "lib/rake/rake_test_loader.rb", "lib/rake/rdoctask.rb", "lib/rake/ruby182_test_unit_fix.rb", "lib/rake/runtest.rb", "lib/rake/tasklib.rb", "lib/rake/testtask.rb", "lib/rake/win32.rb", "lib/rake.rb", "test/capture_stdout.rb", "test/check_expansion.rb", "test/contrib/test_sys.rb", "test/data/rakelib/test1.rb", "test/data/rbext/rakefile.rb", "test/filecreation.rb", "test/functional.rb", "test/in_environment.rb", "test/rake_test_setup.rb", "test/reqfile.rb", "test/reqfile2.rb", "test/session_functional.rb", "test/shellcommand.rb", "test/test_application.rb", "test/test_clean.rb", "test/test_definitions.rb", "test/test_earlytime.rb", "test/test_extension.rb", "test/test_file_creation_task.rb", "test/test_file_task.rb", "test/test_filelist.rb", "test/test_fileutils.rb", "test/test_ftp.rb", "test/test_invocation_chain.rb", "test/test_makefile_loader.rb", "test/test_multitask.rb", "test/test_namespace.rb", "test/test_package_task.rb", "test/test_pathmap.rb", "test/test_rake.rb", "test/test_require.rb", "test/test_rules.rb", "test/test_task_arguments.rb", "test/test_task_manager.rb", "test/test_tasklib.rb", "test/test_tasks.rb", "test/test_test_task.rb", "test/test_top_level_functions.rb", "test/test_win32.rb", "test/data/imports/deps.mf", "test/data/sample.mf", "test/data/chains/Rakefile", "test/data/default/Rakefile", "test/data/dryrun/Rakefile", "test/data/file_creation_task/Rakefile", "test/data/imports/Rakefile", "test/data/multidesc/Rakefile", "test/data/namespace/Rakefile", "test/data/statusreturn/Rakefile", "test/data/unittest/Rakefile", "test/data/unittest/subdir", "doc/example", "doc/example/a.c", "doc/example/b.c", "doc/example/main.c", "doc/example/Rakefile1", "doc/example/Rakefile2", "doc/glossary.rdoc", "doc/jamis.rb", "doc/proto_rake.rdoc", "doc/rake.1.gz", "doc/rakefile.rdoc", "doc/rational.rdoc", "doc/release_notes", "doc/release_notes/rake-0.4.14.rdoc", "doc/release_notes/rake-0.4.15.rdoc", "doc/release_notes/rake-0.5.0.rdoc", "doc/release_notes/rake-0.5.3.rdoc", "doc/release_notes/rake-0.5.4.rdoc", "doc/release_notes/rake-0.6.0.rdoc", "doc/release_notes/rake-0.7.0.rdoc", "doc/release_notes/rake-0.7.1.rdoc", "doc/release_notes/rake-0.7.2.rdoc", "doc/release_notes/rake-0.7.3.rdoc", "doc/release_notes/rake-0.8.0.rdoc", "doc/release_notes/rake-0.8.2.rdoc", "doc/release_notes/rake-0.8.3.rdoc"] + s.has_rdoc = true + s.homepage = %q{http://rake.rubyforge.org} + s.rdoc_options = ["--line-numbers", "--inline-source", "--main", "README", "--title", "Rake -- Ruby Make"] + s.require_paths = ["lib"] + s.rubyforge_project = %q{rake} + s.rubygems_version = %q{1.3.1} + s.summary = %q{Ruby based make-like utility.} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + else + end + else + end +end diff --git a/gems/specifications/randexp-0.1.4.gemspec b/gems/specifications/randexp-0.1.4.gemspec new file mode 100644 index 0000000..e6122e3 --- /dev/null +++ b/gems/specifications/randexp-0.1.4.gemspec @@ -0,0 +1,30 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{randexp} + s.version = "0.1.4" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Ben Burkert"] + s.autorequire = %q{randexp} + s.date = %q{2008-10-07} + s.description = %q{Library for generating random strings.} + s.email = %q{ben@benburkert.com} + s.extra_rdoc_files = ["README", "LICENSE", "TODO"] + s.files = ["LICENSE", "README", "Rakefile", "TODO", "CHANGELOG", "lib/randexp", "lib/randexp/core", "lib/randexp/core_ext", "lib/randexp/core_ext/array.rb", "lib/randexp/core_ext/integer.rb", "lib/randexp/core_ext/range.rb", "lib/randexp/core_ext/regexp.rb", "lib/randexp/core_ext.rb", "lib/randexp/dictionary.rb", "lib/randexp/parser.rb", "lib/randexp/randgen.rb", "lib/randexp/reducer.rb", "lib/randexp/wordlists", "lib/randexp/wordlists/female_names.rb", "lib/randexp/wordlists/male_names.rb", "lib/randexp/wordlists/real_name.rb", "lib/randexp.rb", "spec/regression", "spec/regression/regexp_spec.rb", "spec/spec_helper.rb", "spec/unit", "spec/unit/core_ext", "spec/unit/core_ext/regexp_spec.rb", "spec/unit/randexp", "spec/unit/randexp/parser_spec.rb", "spec/unit/randexp/reducer_spec.rb", "spec/unit/randexp_spec.rb", "spec/unit/randgen_spec.rb", "wordlists/female_names", "wordlists/male_names", "wordlists/surnames"] + s.has_rdoc = true + s.homepage = %q{http://github.com/benburkert/randexp} + s.require_paths = ["lib"] + s.rubygems_version = %q{1.3.1} + s.summary = %q{Library for generating random strings.} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + else + end + else + end +end diff --git a/gems/specifications/rspec-1.1.11.gemspec b/gems/specifications/rspec-1.1.11.gemspec new file mode 100644 index 0000000..41f0212 --- /dev/null +++ b/gems/specifications/rspec-1.1.11.gemspec @@ -0,0 +1,35 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{rspec} + s.version = "1.1.11" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["RSpec Development Team"] + s.date = %q{2008-10-23} + s.description = %q{Behaviour Driven Development for Ruby.} + s.email = ["rspec-devel@rubyforge.org"] + s.executables = ["autospec", "spec"] + s.extra_rdoc_files = ["History.txt", "License.txt", "Manifest.txt", "README.txt", "TODO.txt", "examples/pure/priority.txt", "examples/stories/game-of-life/README.txt", "examples/stories/game-of-life/behaviour/stories/stories.txt", "failing_examples/README.txt", "spec/spec/runner/empty_file.txt", "spec/spec/runner/examples.txt", "spec/spec/runner/failed.txt"] + s.files = ["History.txt", "License.txt", "Manifest.txt", "README.txt", "Rakefile", "TODO.txt", "bin/autospec", "bin/spec", "examples/pure/autogenerated_docstrings_example.rb", "examples/pure/before_and_after_example.rb", "examples/pure/behave_as_example.rb", "examples/pure/custom_expectation_matchers.rb", "examples/pure/custom_formatter.rb", "examples/pure/dynamic_spec.rb", "examples/pure/file_accessor.rb", "examples/pure/file_accessor_spec.rb", "examples/pure/greeter_spec.rb", "examples/pure/helper_method_example.rb", "examples/pure/io_processor.rb", "examples/pure/io_processor_spec.rb", "examples/pure/legacy_spec.rb", "examples/pure/mocking_example.rb", "examples/pure/multi_threaded_behaviour_runner.rb", "examples/pure/nested_classes_example.rb", "examples/pure/partial_mock_example.rb", "examples/pure/pending_example.rb", "examples/pure/predicate_example.rb", "examples/pure/priority.txt", "examples/pure/shared_example_group_example.rb", "examples/pure/shared_stack_examples.rb", "examples/pure/spec_helper.rb", "examples/pure/stack.rb", "examples/pure/stack_spec.rb", "examples/pure/stack_spec_with_nested_example_groups.rb", "examples/pure/stubbing_example.rb", "examples/pure/yielding_example.rb", "examples/stories/adder.rb", "examples/stories/addition", "examples/stories/addition.rb", "examples/stories/calculator.rb", "examples/stories/game-of-life/.loadpath", "examples/stories/game-of-life/README.txt", "examples/stories/game-of-life/behaviour/everything.rb", "examples/stories/game-of-life/behaviour/examples/examples.rb", "examples/stories/game-of-life/behaviour/examples/game_behaviour.rb", "examples/stories/game-of-life/behaviour/examples/grid_behaviour.rb", "examples/stories/game-of-life/behaviour/stories/CellsWithLessThanTwoNeighboursDie.story", "examples/stories/game-of-life/behaviour/stories/CellsWithMoreThanThreeNeighboursDie.story", "examples/stories/game-of-life/behaviour/stories/EmptySpacesWithThreeNeighboursCreateACell.story", "examples/stories/game-of-life/behaviour/stories/ICanCreateACell.story", "examples/stories/game-of-life/behaviour/stories/ICanKillACell.story", "examples/stories/game-of-life/behaviour/stories/TheGridWraps.story", "examples/stories/game-of-life/behaviour/stories/create_a_cell.rb", "examples/stories/game-of-life/behaviour/stories/helper.rb", "examples/stories/game-of-life/behaviour/stories/kill_a_cell.rb", "examples/stories/game-of-life/behaviour/stories/steps.rb", "examples/stories/game-of-life/behaviour/stories/stories.rb", "examples/stories/game-of-life/behaviour/stories/stories.txt", "examples/stories/game-of-life/life.rb", "examples/stories/game-of-life/life/game.rb", "examples/stories/game-of-life/life/grid.rb", "examples/stories/helper.rb", "examples/stories/steps/addition_steps.rb", "failing_examples/README.txt", "failing_examples/diffing_spec.rb", "failing_examples/failing_autogenerated_docstrings_example.rb", "failing_examples/failure_in_setup.rb", "failing_examples/failure_in_teardown.rb", "failing_examples/mocking_example.rb", "failing_examples/mocking_with_flexmock.rb", "failing_examples/mocking_with_mocha.rb", "failing_examples/mocking_with_rr.rb", "failing_examples/partial_mock_example.rb", "failing_examples/predicate_example.rb", "failing_examples/raising_example.rb", "failing_examples/spec_helper.rb", "failing_examples/syntax_error_example.rb", "failing_examples/team_spec.rb", "failing_examples/timeout_behaviour.rb", "init.rb", "lib/autotest/discover.rb", "lib/autotest/rspec.rb", "lib/spec.rb", "lib/spec/adapters.rb", "lib/spec/adapters/ruby_engine.rb", "lib/spec/adapters/ruby_engine/mri.rb", "lib/spec/adapters/ruby_engine/rubinius.rb", "lib/spec/example.rb", "lib/spec/example/before_and_after_hooks.rb", "lib/spec/example/configuration.rb", "lib/spec/example/errors.rb", "lib/spec/example/example_group.rb", "lib/spec/example/example_group_factory.rb", "lib/spec/example/example_group_methods.rb", "lib/spec/example/example_matcher.rb", "lib/spec/example/example_methods.rb", "lib/spec/example/module_reopening_fix.rb", "lib/spec/example/pending.rb", "lib/spec/example/shared_example_group.rb", "lib/spec/expectations.rb", "lib/spec/expectations/differs/default.rb", "lib/spec/expectations/errors.rb", "lib/spec/expectations/extensions.rb", "lib/spec/expectations/extensions/object.rb", "lib/spec/expectations/extensions/string_and_symbol.rb", "lib/spec/expectations/handler.rb", "lib/spec/extensions.rb", "lib/spec/extensions/class.rb", "lib/spec/extensions/main.rb", "lib/spec/extensions/metaclass.rb", "lib/spec/extensions/object.rb", "lib/spec/interop/test.rb", "lib/spec/interop/test/unit/autorunner.rb", "lib/spec/interop/test/unit/testcase.rb", "lib/spec/interop/test/unit/testresult.rb", "lib/spec/interop/test/unit/testsuite_adapter.rb", "lib/spec/interop/test/unit/ui/console/testrunner.rb", "lib/spec/matchers.rb", "lib/spec/matchers/be.rb", "lib/spec/matchers/be_close.rb", "lib/spec/matchers/change.rb", "lib/spec/matchers/eql.rb", "lib/spec/matchers/equal.rb", "lib/spec/matchers/exist.rb", "lib/spec/matchers/has.rb", "lib/spec/matchers/have.rb", "lib/spec/matchers/include.rb", "lib/spec/matchers/match.rb", "lib/spec/matchers/operator_matcher.rb", "lib/spec/matchers/raise_error.rb", "lib/spec/matchers/respond_to.rb", "lib/spec/matchers/satisfy.rb", "lib/spec/matchers/simple_matcher.rb", "lib/spec/matchers/throw_symbol.rb", "lib/spec/mocks.rb", "lib/spec/mocks/argument_constraints.rb", "lib/spec/mocks/argument_expectation.rb", "lib/spec/mocks/error_generator.rb", "lib/spec/mocks/errors.rb", "lib/spec/mocks/extensions.rb", "lib/spec/mocks/extensions/object.rb", "lib/spec/mocks/framework.rb", "lib/spec/mocks/message_expectation.rb", "lib/spec/mocks/methods.rb", "lib/spec/mocks/mock.rb", "lib/spec/mocks/order_group.rb", "lib/spec/mocks/proxy.rb", "lib/spec/mocks/space.rb", "lib/spec/mocks/spec_methods.rb", "lib/spec/rake/spectask.rb", "lib/spec/rake/verify_rcov.rb", "lib/spec/runner.rb", "lib/spec/runner/backtrace_tweaker.rb", "lib/spec/runner/class_and_arguments_parser.rb", "lib/spec/runner/command_line.rb", "lib/spec/runner/drb_command_line.rb", "lib/spec/runner/example_group_runner.rb", "lib/spec/runner/formatter/base_formatter.rb", "lib/spec/runner/formatter/base_text_formatter.rb", "lib/spec/runner/formatter/failing_example_groups_formatter.rb", "lib/spec/runner/formatter/failing_examples_formatter.rb", "lib/spec/runner/formatter/html_formatter.rb", "lib/spec/runner/formatter/nested_text_formatter.rb", "lib/spec/runner/formatter/profile_formatter.rb", "lib/spec/runner/formatter/progress_bar_formatter.rb", "lib/spec/runner/formatter/snippet_extractor.rb", "lib/spec/runner/formatter/specdoc_formatter.rb", "lib/spec/runner/formatter/story/html_formatter.rb", "lib/spec/runner/formatter/story/plain_text_formatter.rb", "lib/spec/runner/formatter/story/progress_bar_formatter.rb", "lib/spec/runner/formatter/text_mate_formatter.rb", "lib/spec/runner/heckle_runner.rb", "lib/spec/runner/heckle_runner_unsupported.rb", "lib/spec/runner/option_parser.rb", "lib/spec/runner/options.rb", "lib/spec/runner/reporter.rb", "lib/spec/runner/spec_parser.rb", "lib/spec/story.rb", "lib/spec/story/extensions.rb", "lib/spec/story/extensions/main.rb", "lib/spec/story/extensions/regexp.rb", "lib/spec/story/extensions/string.rb", "lib/spec/story/given_scenario.rb", "lib/spec/story/runner.rb", "lib/spec/story/runner/plain_text_story_runner.rb", "lib/spec/story/runner/scenario_collector.rb", "lib/spec/story/runner/scenario_runner.rb", "lib/spec/story/runner/story_mediator.rb", "lib/spec/story/runner/story_parser.rb", "lib/spec/story/runner/story_runner.rb", "lib/spec/story/scenario.rb", "lib/spec/story/step.rb", "lib/spec/story/step_group.rb", "lib/spec/story/step_mother.rb", "lib/spec/story/story.rb", "lib/spec/story/world.rb", "lib/spec/version.rb", "plugins/mock_frameworks/flexmock.rb", "plugins/mock_frameworks/mocha.rb", "plugins/mock_frameworks/rr.rb", "plugins/mock_frameworks/rspec.rb", "rake_tasks/examples.rake", "rake_tasks/examples_with_rcov.rake", "rake_tasks/failing_examples_with_html.rake", "rake_tasks/verify_rcov.rake", "rspec.gemspec", "spec/README.jruby", "spec/autotest/autotest_helper.rb", "spec/autotest/autotest_matchers.rb", "spec/autotest/discover_spec.rb", "spec/autotest/rspec_spec.rb", "spec/rspec_suite.rb", "spec/ruby_forker.rb", "spec/spec.opts", "spec/spec/adapters/ruby_engine_spec.rb", "spec/spec/example/configuration_spec.rb", "spec/spec/example/example_group_class_definition_spec.rb", "spec/spec/example/example_group_factory_spec.rb", "spec/spec/example/example_group_methods_spec.rb", "spec/spec/example/example_group_spec.rb", "spec/spec/example/example_matcher_spec.rb", "spec/spec/example/example_methods_spec.rb", "spec/spec/example/example_runner_spec.rb", "spec/spec/example/nested_example_group_spec.rb", "spec/spec/example/pending_module_spec.rb", "spec/spec/example/predicate_matcher_spec.rb", "spec/spec/example/shared_example_group_spec.rb", "spec/spec/example/subclassing_example_group_spec.rb", "spec/spec/expectations/differs/default_spec.rb", "spec/spec/expectations/extensions/object_spec.rb", "spec/spec/expectations/fail_with_spec.rb", "spec/spec/extensions/main_spec.rb", "spec/spec/interop/test/unit/resources/spec_that_fails.rb", "spec/spec/interop/test/unit/resources/spec_that_passes.rb", "spec/spec/interop/test/unit/resources/spec_with_errors.rb", "spec/spec/interop/test/unit/resources/spec_with_options_hash.rb", "spec/spec/interop/test/unit/resources/test_case_that_fails.rb", "spec/spec/interop/test/unit/resources/test_case_that_passes.rb", "spec/spec/interop/test/unit/resources/test_case_with_errors.rb", "spec/spec/interop/test/unit/resources/testsuite_adapter_spec_with_test_unit.rb", "spec/spec/interop/test/unit/spec_spec.rb", "spec/spec/interop/test/unit/test_unit_spec_helper.rb", "spec/spec/interop/test/unit/testcase_spec.rb", "spec/spec/interop/test/unit/testsuite_adapter_spec.rb", "spec/spec/matchers/be_close_spec.rb", "spec/spec/matchers/be_spec.rb", "spec/spec/matchers/change_spec.rb", "spec/spec/matchers/description_generation_spec.rb", "spec/spec/matchers/eql_spec.rb", "spec/spec/matchers/equal_spec.rb", "spec/spec/matchers/exist_spec.rb", "spec/spec/matchers/handler_spec.rb", "spec/spec/matchers/has_spec.rb", "spec/spec/matchers/have_spec.rb", "spec/spec/matchers/include_spec.rb", "spec/spec/matchers/match_spec.rb", "spec/spec/matchers/matcher_methods_spec.rb", "spec/spec/matchers/mock_constraint_matchers_spec.rb", "spec/spec/matchers/operator_matcher_spec.rb", "spec/spec/matchers/raise_error_spec.rb", "spec/spec/matchers/respond_to_spec.rb", "spec/spec/matchers/satisfy_spec.rb", "spec/spec/matchers/simple_matcher_spec.rb", "spec/spec/matchers/throw_symbol_spec.rb", "spec/spec/mocks/any_number_of_times_spec.rb", "spec/spec/mocks/argument_expectation_spec.rb", "spec/spec/mocks/at_least_spec.rb", "spec/spec/mocks/at_most_spec.rb", "spec/spec/mocks/bug_report_10260_spec.rb", "spec/spec/mocks/bug_report_10263_spec.rb", "spec/spec/mocks/bug_report_11545_spec.rb", "spec/spec/mocks/bug_report_15719_spec.rb", "spec/spec/mocks/bug_report_496.rb", "spec/spec/mocks/bug_report_7611_spec.rb", "spec/spec/mocks/bug_report_7805_spec.rb", "spec/spec/mocks/bug_report_8165_spec.rb", "spec/spec/mocks/bug_report_8302_spec.rb", "spec/spec/mocks/failing_mock_argument_constraints_spec.rb", "spec/spec/mocks/hash_including_matcher_spec.rb", "spec/spec/mocks/mock_ordering_spec.rb", "spec/spec/mocks/mock_space_spec.rb", "spec/spec/mocks/mock_spec.rb", "spec/spec/mocks/multiple_return_value_spec.rb", "spec/spec/mocks/nil_expectation_warning_spec.rb", "spec/spec/mocks/null_object_mock_spec.rb", "spec/spec/mocks/once_counts_spec.rb", "spec/spec/mocks/options_hash_spec.rb", "spec/spec/mocks/partial_mock_spec.rb", "spec/spec/mocks/partial_mock_using_mocks_directly_spec.rb", "spec/spec/mocks/passing_mock_argument_constraints_spec.rb", "spec/spec/mocks/precise_counts_spec.rb", "spec/spec/mocks/record_messages_spec.rb", "spec/spec/mocks/stub_spec.rb", "spec/spec/mocks/twice_counts_spec.rb", "spec/spec/package/bin_spec_spec.rb", "spec/spec/runner/class_and_argument_parser_spec.rb", "spec/spec/runner/command_line_spec.rb", "spec/spec/runner/drb_command_line_spec.rb", "spec/spec/runner/empty_file.txt", "spec/spec/runner/examples.txt", "spec/spec/runner/failed.txt", "spec/spec/runner/formatter/base_formatter_spec.rb", "spec/spec/runner/formatter/failing_example_groups_formatter_spec.rb", "spec/spec/runner/formatter/failing_examples_formatter_spec.rb", "spec/spec/runner/formatter/html_formatted-1.8.4.html", "spec/spec/runner/formatter/html_formatted-1.8.5-jruby.html", "spec/spec/runner/formatter/html_formatted-1.8.5.html", "spec/spec/runner/formatter/html_formatted-1.8.6-jruby.html", "spec/spec/runner/formatter/html_formatted-1.8.6.html", "spec/spec/runner/formatter/html_formatter_spec.rb", "spec/spec/runner/formatter/nested_text_formatter_spec.rb", "spec/spec/runner/formatter/profile_formatter_spec.rb", "spec/spec/runner/formatter/progress_bar_formatter_spec.rb", "spec/spec/runner/formatter/snippet_extractor_spec.rb", "spec/spec/runner/formatter/spec_mate_formatter_spec.rb", "spec/spec/runner/formatter/specdoc_formatter_spec.rb", "spec/spec/runner/formatter/story/html_formatter_spec.rb", "spec/spec/runner/formatter/story/plain_text_formatter_spec.rb", "spec/spec/runner/formatter/story/progress_bar_formatter_spec.rb", "spec/spec/runner/formatter/text_mate_formatted-1.8.4.html", "spec/spec/runner/formatter/text_mate_formatted-1.8.6.html", "spec/spec/runner/heckle_runner_spec.rb", "spec/spec/runner/heckler_spec.rb", "spec/spec/runner/noisy_backtrace_tweaker_spec.rb", "spec/spec/runner/option_parser_spec.rb", "spec/spec/runner/options_spec.rb", "spec/spec/runner/output_one_time_fixture.rb", "spec/spec/runner/output_one_time_fixture_runner.rb", "spec/spec/runner/output_one_time_spec.rb", "spec/spec/runner/quiet_backtrace_tweaker_spec.rb", "spec/spec/runner/reporter_spec.rb", "spec/spec/runner/resources/a_bar.rb", "spec/spec/runner/resources/a_foo.rb", "spec/spec/runner/resources/a_spec.rb", "spec/spec/runner/spec.opts", "spec/spec/runner/spec_drb.opts", "spec/spec/runner/spec_parser/spec_parser_fixture.rb", "spec/spec/runner/spec_parser_spec.rb", "spec/spec/runner/spec_spaced.opts", "spec/spec/runner_spec.rb", "spec/spec/spec_classes.rb", "spec/spec/story/builders.rb", "spec/spec/story/extensions/main_spec.rb", "spec/spec/story/extensions_spec.rb", "spec/spec/story/given_scenario_spec.rb", "spec/spec/story/runner/plain_text_story_runner_spec.rb", "spec/spec/story/runner/scenario_collector_spec.rb", "spec/spec/story/runner/scenario_runner_spec.rb", "spec/spec/story/runner/story_mediator_spec.rb", "spec/spec/story/runner/story_parser_spec.rb", "spec/spec/story/runner/story_runner_spec.rb", "spec/spec/story/runner_spec.rb", "spec/spec/story/scenario_spec.rb", "spec/spec/story/step_group_spec.rb", "spec/spec/story/step_mother_spec.rb", "spec/spec/story/step_spec.rb", "spec/spec/story/story_helper.rb", "spec/spec/story/story_spec.rb", "spec/spec/story/world_spec.rb", "spec/spec_helper.rb", "stories/all.rb", "stories/configuration/before_blocks.story", "stories/configuration/stories.rb", "stories/example_groups/autogenerated_docstrings", "stories/example_groups/example_group_with_should_methods", "stories/example_groups/nested_groups", "stories/example_groups/output", "stories/example_groups/stories.rb", "stories/helper.rb", "stories/interop/examples_and_tests_together", "stories/interop/stories.rb", "stories/interop/test_case_with_should_methods", "stories/mock_framework_integration/stories.rb", "stories/mock_framework_integration/use_flexmock.story", "stories/pending_stories/README", "stories/resources/helpers/cmdline.rb", "stories/resources/helpers/story_helper.rb", "stories/resources/matchers/smart_match.rb", "stories/resources/spec/before_blocks_example.rb", "stories/resources/spec/example_group_with_should_methods.rb", "stories/resources/spec/simple_spec.rb", "stories/resources/spec/spec_with_flexmock.rb", "stories/resources/steps/running_rspec.rb", "stories/resources/stories/failing_story.rb", "stories/resources/test/spec_and_test_together.rb", "stories/resources/test/test_case_with_should_methods.rb", "stories/stories/multiline_steps.story", "stories/stories/steps/multiline_steps.rb", "stories/stories/stories.rb", "story_server/prototype/javascripts/builder.js", "story_server/prototype/javascripts/controls.js", "story_server/prototype/javascripts/dragdrop.js", "story_server/prototype/javascripts/effects.js", "story_server/prototype/javascripts/prototype.js", "story_server/prototype/javascripts/rspec.js", "story_server/prototype/javascripts/scriptaculous.js", "story_server/prototype/javascripts/slider.js", "story_server/prototype/javascripts/sound.js", "story_server/prototype/javascripts/unittest.js", "story_server/prototype/lib/server.rb", "story_server/prototype/stories.html", "story_server/prototype/stylesheets/rspec.css", "story_server/prototype/stylesheets/test.css"] + s.has_rdoc = true + s.homepage = %q{http://rspec.info/} + s.rdoc_options = ["--main", "README.txt"] + s.require_paths = ["lib"] + s.rubyforge_project = %q{rspec} + s.rubygems_version = %q{1.3.1} + s.summary = %q{rspec 1.1.11} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_development_dependency(%q, [">= 1.8.1"]) + else + s.add_dependency(%q, [">= 1.8.1"]) + end + else + s.add_dependency(%q, [">= 1.8.1"]) + end +end diff --git a/gems/specifications/ruby-debug-0.10.2.gemspec b/gems/specifications/ruby-debug-0.10.2.gemspec new file mode 100644 index 0000000..e6c46b4 --- /dev/null +++ b/gems/specifications/ruby-debug-0.10.2.gemspec @@ -0,0 +1,39 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{ruby-debug} + s.version = "0.10.2" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Kent Sibilev"] + s.date = %q{2008-08-27} + s.default_executable = %q{rdebug} + s.description = %q{A generic command line interface for ruby-debug.} + s.email = %q{ksibilev@yahoo.com} + s.executables = ["rdebug"] + s.extra_rdoc_files = ["README"] + s.files = ["AUTHORS", "CHANGES", "LICENSE", "README", "Rakefile", "cli/ruby-debug", "cli/ruby-debug/command.rb", "cli/ruby-debug/commands", "cli/ruby-debug/commands/breakpoints.rb", "cli/ruby-debug/commands/catchpoint.rb", "cli/ruby-debug/commands/condition.rb", "cli/ruby-debug/commands/continue.rb", "cli/ruby-debug/commands/control.rb", "cli/ruby-debug/commands/display.rb", "cli/ruby-debug/commands/edit.rb", "cli/ruby-debug/commands/enable.rb", "cli/ruby-debug/commands/eval.rb", "cli/ruby-debug/commands/finish.rb", "cli/ruby-debug/commands/frame.rb", "cli/ruby-debug/commands/help.rb", "cli/ruby-debug/commands/info.rb", "cli/ruby-debug/commands/irb.rb", "cli/ruby-debug/commands/list.rb", "cli/ruby-debug/commands/method.rb", "cli/ruby-debug/commands/quit.rb", "cli/ruby-debug/commands/reload.rb", "cli/ruby-debug/commands/save.rb", "cli/ruby-debug/commands/set.rb", "cli/ruby-debug/commands/show.rb", "cli/ruby-debug/commands/source.rb", "cli/ruby-debug/commands/stepping.rb", "cli/ruby-debug/commands/threads.rb", "cli/ruby-debug/commands/tmate.rb", "cli/ruby-debug/commands/trace.rb", "cli/ruby-debug/commands/variables.rb", "cli/ruby-debug/debugger.rb", "cli/ruby-debug/helper.rb", "cli/ruby-debug/interface.rb", "cli/ruby-debug/processor.rb", "cli/ruby-debug.rb", "ChangeLog", "bin/rdebug", "doc/rdebug.1", "test/data/annotate.cmd", "test/data/break_bad.cmd", "test/data/break_loop_bug.cmd", "test/data/breakpoints.cmd", "test/data/catch.cmd", "test/data/condition.cmd", "test/data/ctrl.cmd", "test/data/display.cmd", "test/data/edit.cmd", "test/data/emacs_basic.cmd", "test/data/enable.cmd", "test/data/finish.cmd", "test/data/frame.cmd", "test/data/help.cmd", "test/data/info-thread.cmd", "test/data/info-var-bug2.cmd", "test/data/info-var.cmd", "test/data/info.cmd", "test/data/linetrace.cmd", "test/data/linetracep.cmd", "test/data/list.cmd", "test/data/method.cmd", "test/data/methodsig.cmd", "test/data/output.cmd", "test/data/post-mortem-next.cmd", "test/data/post-mortem.cmd", "test/data/quit.cmd", "test/data/raise.cmd", "test/data/save.cmd", "test/data/setshow.cmd", "test/data/source.cmd", "test/data/stepping.cmd", "test/data/annotate.right", "test/data/break_bad.right", "test/data/break_loop_bug.right", "test/data/breakpoints.right", "test/data/catch.right", "test/data/condition.right", "test/data/ctrl.right", "test/data/display.right", "test/data/dollar-0.right", "test/data/dollar-0a.right", "test/data/dollar-0b.right", "test/data/edit.right", "test/data/emacs_basic.right", "test/data/enable.right", "test/data/finish.right", "test/data/frame.right", "test/data/help.right", "test/data/history.right", "test/data/info-thread.right", "test/data/info-var-bug2.right", "test/data/info-var.right", "test/data/info.right", "test/data/linetrace.right", "test/data/linetracep.right", "test/data/list.right", "test/data/method.right", "test/data/methodsig.right", "test/data/noquit.right", "test/data/output.right", "test/data/post-mortem-next.right", "test/data/post-mortem-osx.right", "test/data/post-mortem.right", "test/data/quit.right", "test/data/raise.right", "test/data/save.right", "test/data/setshow.right", "test/data/source.right", "test/data/stepping.right", "test/data/test-init-cygwin.right", "test/data/test-init-osx.right", "test/data/test-init.right", "test/data/trace.right", "test/base/base.rb", "test/base/binding.rb", "test/base/catchpoint.rb", "test/base/load.rb", "test/bp_loop_issue.rb", "test/classes.rb", "test/cli/commands/catchpoint_test.rb", "test/dollar-0.rb", "test/gcd-dbg-nox.rb", "test/gcd-dbg.rb", "test/gcd.rb", "test/helper.rb", "test/info-var-bug.rb", "test/info-var-bug2.rb", "test/null.rb", "test/output.rb", "test/pm-base.rb", "test/pm.rb", "test/raise.rb", "test/tdebug.rb", "test/test-annotate.rb", "test/test-break-bad.rb", "test/test-breakpoints.rb", "test/test-catch.rb", "test/test-condition.rb", "test/test-ctrl.rb", "test/test-display.rb", "test/test-dollar-0.rb", "test/test-edit.rb", "test/test-emacs-basic.rb", "test/test-enable.rb", "test/test-finish.rb", "test/test-frame.rb", "test/test-help.rb", "test/test-hist.rb", "test/test-info-thread.rb", "test/test-info-var.rb", "test/test-info.rb", "test/test-init.rb", "test/test-list.rb", "test/test-method.rb", "test/test-output.rb", "test/test-pm.rb", "test/test-quit.rb", "test/test-raise.rb", "test/test-save.rb", "test/test-setshow.rb", "test/test-source.rb", "test/test-stepping.rb", "test/test-trace.rb", "test/thread1.rb", "rdbg.rb"] + s.has_rdoc = true + s.homepage = %q{http://rubyforge.org/projects/ruby-debug/} + s.require_paths = ["cli"] + s.required_ruby_version = Gem::Requirement.new(">= 1.8.2") + s.rubyforge_project = %q{ruby-debug} + s.rubygems_version = %q{1.3.1} + s.summary = %q{Command line interface (CLI) for ruby-debug-base} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, [">= 0.1"]) + s.add_runtime_dependency(%q, ["= 0.10.2"]) + else + s.add_dependency(%q, [">= 0.1"]) + s.add_dependency(%q, ["= 0.10.2"]) + end + else + s.add_dependency(%q, [">= 0.1"]) + s.add_dependency(%q, ["= 0.10.2"]) + end +end diff --git a/gems/specifications/ruby-debug-base-0.10.2.gemspec b/gems/specifications/ruby-debug-base-0.10.2.gemspec new file mode 100644 index 0000000..e195ac3 --- /dev/null +++ b/gems/specifications/ruby-debug-base-0.10.2.gemspec @@ -0,0 +1,36 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{ruby-debug-base} + s.version = "0.10.2" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Kent Sibilev"] + s.date = %q{2008-08-27} + s.description = %q{ruby-debug is a fast implementation of the standard Ruby debugger debug.rb. It is implemented by utilizing a new Ruby C API hook. The core component provides support that front-ends can build on. It provides breakpoint handling, bindings for stack frames among other things.} + s.email = %q{ksibilev@yahoo.com} + s.extensions = ["ext/extconf.rb"] + s.extra_rdoc_files = ["README", "ext/ruby_debug.c"] + s.files = ["AUTHORS", "CHANGES", "LICENSE", "README", "Rakefile", "ext/breakpoint.c", "ext/extconf.rb", "ext/ruby_debug.c", "ext/ruby_debug.h", "ext/win32/ruby_debug.so", "lib/ChangeLog", "lib/ruby-debug-base.rb", "test/base/base.rb", "test/base/binding.rb", "test/base/catchpoint.rb"] + s.has_rdoc = true + s.homepage = %q{http://rubyforge.org/projects/ruby-debug/} + s.require_paths = ["lib"] + s.required_ruby_version = Gem::Requirement.new(">= 1.8.2") + s.rubyforge_project = %q{ruby-debug} + s.rubygems_version = %q{1.3.1} + s.summary = %q{Fast Ruby debugger - core component} + s.test_files = ["test/base/base.rb", "test/base/binding.rb", "test/base/catchpoint.rb"] + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, [">= 0.3"]) + else + s.add_dependency(%q, [">= 0.3"]) + end + else + s.add_dependency(%q, [">= 0.3"]) + end +end diff --git a/gems/specifications/ruby2ruby-1.2.1.gemspec b/gems/specifications/ruby2ruby-1.2.1.gemspec new file mode 100644 index 0000000..13f8c29 --- /dev/null +++ b/gems/specifications/ruby2ruby-1.2.1.gemspec @@ -0,0 +1,40 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{ruby2ruby} + s.version = "1.2.1" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Ryan Davis"] + s.date = %q{2008-11-04} + s.default_executable = %q{r2r_show} + s.description = %q{ruby2ruby provides a means of generating pure ruby code easily from ParseTree's Sexps. This makes making dynamic language processors much easier in ruby than ever before.} + s.email = ["ryand-ruby@zenspider.com"] + s.executables = ["r2r_show"] + s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.txt"] + s.files = [".autotest", "History.txt", "Manifest.txt", "README.txt", "Rakefile", "bin/r2r_show", "lib/ruby2ruby.rb", "test/test_ruby2ruby.rb"] + s.has_rdoc = true + s.homepage = %q{http://seattlerb.rubyforge.org/} + s.rdoc_options = ["--main", "README.txt"] + s.require_paths = ["lib"] + s.rubyforge_project = %q{seattlerb} + s.rubygems_version = %q{1.3.1} + s.summary = %q{ruby2ruby provides a means of generating pure ruby code easily from ParseTree's Sexps} + s.test_files = ["test/test_ruby2ruby.rb"] + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, ["~> 3.0"]) + s.add_development_dependency(%q, [">= 1.8.0"]) + else + s.add_dependency(%q, ["~> 3.0"]) + s.add_dependency(%q, [">= 1.8.0"]) + end + else + s.add_dependency(%q, ["~> 3.0"]) + s.add_dependency(%q, [">= 1.8.0"]) + end +end diff --git a/gems/specifications/sexp_processor-3.0.0.gemspec b/gems/specifications/sexp_processor-3.0.0.gemspec new file mode 100644 index 0000000..3ab8512 --- /dev/null +++ b/gems/specifications/sexp_processor-3.0.0.gemspec @@ -0,0 +1,35 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{sexp_processor} + s.version = "3.0.0" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Ryan Davis"] + s.date = %q{2008-10-21} + s.description = %q{FIX (describe your package)} + s.email = ["ryand-ruby@zenspider.com"] + s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.txt"] + s.files = ["History.txt", "Manifest.txt", "README.txt", "Rakefile", "lib/composite_sexp_processor.rb", "lib/sexp.rb", "lib/sexp_processor.rb", "test/test_composite_sexp_processor.rb", "test/test_environment.rb", "test/test_sexp.rb", "test/test_sexp_processor.rb"] + s.has_rdoc = true + s.homepage = %q{FIX (url)} + s.rdoc_options = ["--main", "README.txt"] + s.require_paths = ["lib"] + s.rubyforge_project = %q{parsetree} + s.rubygems_version = %q{1.3.1} + s.summary = %q{FIX (describe your package)} + s.test_files = ["test/test_composite_sexp_processor.rb", "test/test_environment.rb", "test/test_sexp.rb", "test/test_sexp_processor.rb"] + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_development_dependency(%q, [">= 1.8.0"]) + else + s.add_dependency(%q, [">= 1.8.0"]) + end + else + s.add_dependency(%q, [">= 1.8.0"]) + end +end diff --git a/gems/specifications/templater-0.4.0.gemspec b/gems/specifications/templater-0.4.0.gemspec new file mode 100644 index 0000000..5797f73 --- /dev/null +++ b/gems/specifications/templater-0.4.0.gemspec @@ -0,0 +1,39 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{templater} + s.version = "0.4.0" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Jonas Nicklas"] + s.autorequire = %q{templater} + s.date = %q{2008-11-10} + s.description = %q{File generation system} + s.email = %q{jonas.nicklas@gmail.com} + s.extra_rdoc_files = ["README", "LICENSE", "TODO"] + s.files = ["LICENSE", "README", "Rakefile", "TODO", "lib/templater", "lib/templater/actions", "lib/templater/actions/action.rb", "lib/templater/actions/directory.rb", "lib/templater/actions/empty_directory.rb", "lib/templater/actions/file.rb", "lib/templater/actions/template.rb", "lib/templater/capture_helpers.rb", "lib/templater/cli", "lib/templater/cli/generator.rb", "lib/templater/cli/manifold.rb", "lib/templater/cli/parser.rb", "lib/templater/core_ext", "lib/templater/core_ext/kernel.rb", "lib/templater/core_ext/string.rb", "lib/templater/description.rb", "lib/templater/discovery.rb", "lib/templater/generator.rb", "lib/templater/manifold.rb", "lib/templater/spec", "lib/templater/spec/helpers.rb", "lib/templater.rb", "spec/actions", "spec/actions/directory_spec.rb", "spec/actions/empty_directory_spec.rb", "spec/actions/file_spec.rb", "spec/actions/template_spec.rb", "spec/core_ext", "spec/core_ext/string_spec.rb", "spec/generator", "spec/generator/actions_spec.rb", "spec/generator/arguments_spec.rb", "spec/generator/desc_spec.rb", "spec/generator/destination_root_spec.rb", "spec/generator/empty_directories_spec.rb", "spec/generator/files_spec.rb", "spec/generator/generators_spec.rb", "spec/generator/glob_spec.rb", "spec/generator/invocations_spec.rb", "spec/generator/invoke_spec.rb", "spec/generator/options_spec.rb", "spec/generator/render_spec.rb", "spec/generator/source_root_spec.rb", "spec/generator/templates_spec.rb", "spec/manifold_spec.rb", "spec/results", "spec/results/erb.rbs", "spec/results/file.rbs", "spec/results/random.rbs", "spec/results/simple_erb.rbs", "spec/spec_helper.rb", "spec/spec_helpers_spec.rb", "spec/templater_spec.rb", "spec/templates", "spec/templates/erb.rbt", "spec/templates/glob", "spec/templates/glob/arg.js", "spec/templates/glob/hellothar.%feh%", "spec/templates/glob/hellothar.html.%feh%", "spec/templates/glob/README", "spec/templates/glob/subfolder", "spec/templates/glob/subfolder/jessica_alba.jpg", "spec/templates/glob/subfolder/monkey.rb", "spec/templates/glob/test.rb", "spec/templates/literals_erb.rbt", "spec/templates/simple.rbt", "spec/templates/simple_erb.rbt"] + s.has_rdoc = true + s.homepage = %q{http://templater.rubyforge.org/} + s.require_paths = ["lib"] + s.rubygems_version = %q{1.3.1} + s.summary = %q{File generation system} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, [">= 1.4.0"]) + s.add_runtime_dependency(%q, [">= 1.1.2"]) + s.add_runtime_dependency(%q, [">= 0.9.5"]) + else + s.add_dependency(%q, [">= 1.4.0"]) + s.add_dependency(%q, [">= 1.1.2"]) + s.add_dependency(%q, [">= 0.9.5"]) + end + else + s.add_dependency(%q, [">= 1.4.0"]) + s.add_dependency(%q, [">= 1.1.2"]) + s.add_dependency(%q, [">= 0.9.5"]) + end +end diff --git a/gems/specifications/thor-0.9.8.gemspec b/gems/specifications/thor-0.9.8.gemspec new file mode 100644 index 0000000..1d0642c --- /dev/null +++ b/gems/specifications/thor-0.9.8.gemspec @@ -0,0 +1,31 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{thor} + s.version = "0.9.8" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Yehuda Katz"] + s.date = %q{2008-10-20} + s.description = %q{A gem that maps options to a class} + s.email = %q{wycats@gmail.com} + s.executables = ["thor", "rake2thor"] + s.extra_rdoc_files = ["README.markdown", "LICENSE", "CHANGELOG.rdoc"] + s.files = ["README.markdown", "LICENSE", "CHANGELOG.rdoc", "Rakefile", "bin/rake2thor", "bin/thor", "lib/thor", "lib/thor/error.rb", "lib/thor/options.rb", "lib/thor/ordered_hash.rb", "lib/thor/runner.rb", "lib/thor/task.rb", "lib/thor/task_hash.rb", "lib/thor/tasks", "lib/thor/tasks/package.rb", "lib/thor/tasks.rb", "lib/thor/util.rb", "lib/thor.rb"] + s.has_rdoc = true + s.homepage = %q{http://yehudakatz.com} + s.require_paths = ["lib"] + s.rubyforge_project = %q{thor} + s.rubygems_version = %q{1.3.1} + s.summary = %q{A gem that maps options to a class} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + else + end + else + end +end diff --git a/gems/specifications/uuidtools-1.0.4.gemspec b/gems/specifications/uuidtools-1.0.4.gemspec new file mode 100644 index 0000000..e91a2bd --- /dev/null +++ b/gems/specifications/uuidtools-1.0.4.gemspec @@ -0,0 +1,37 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{uuidtools} + s.version = "1.0.4" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Bob Aman"] + s.date = %q{2008-09-28} + s.description = %q{A simple universally unique ID generation library.} + s.email = %q{bob@sporkmonger.com} + s.extra_rdoc_files = ["README"] + s.files = ["lib/uuidtools", "lib/uuidtools/version.rb", "lib/uuidtools.rb", "spec/spec.opts", "spec/spec_helper.rb", "spec/uuidtools", "spec/uuidtools/mac_address_spec.rb", "spec/uuidtools/uuid_creation_spec.rb", "spec/uuidtools/uuid_parsing_spec.rb", "tasks/benchmark.rake", "tasks/clobber.rake", "tasks/gem.rake", "tasks/git.rake", "tasks/metrics.rake", "tasks/rdoc.rake", "tasks/rubyforge.rake", "tasks/spec.rake", "website/index.html", "CHANGELOG", "LICENSE", "Rakefile", "README"] + s.has_rdoc = true + s.homepage = %q{http://uuidtools.rubyforge.org/} + s.rdoc_options = ["--main", "README"] + s.require_paths = ["lib"] + s.rubyforge_project = %q{uuidtools} + s.rubygems_version = %q{1.3.1} + s.summary = %q{UUID generator} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, [">= 0.7.3"]) + s.add_runtime_dependency(%q, [">= 1.0.8"]) + else + s.add_dependency(%q, [">= 0.7.3"]) + s.add_dependency(%q, [">= 1.0.8"]) + end + else + s.add_dependency(%q, [">= 0.7.3"]) + s.add_dependency(%q, [">= 1.0.8"]) + end +end diff --git a/gems/specifications/webrat-0.3.1.gemspec b/gems/specifications/webrat-0.3.1.gemspec new file mode 100644 index 0000000..533847f --- /dev/null +++ b/gems/specifications/webrat-0.3.1.gemspec @@ -0,0 +1,32 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{webrat} + s.version = "0.3.1" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Bryan Helmkamp"] + s.date = %q{2008-11-06} + s.description = %q{Webrat. Ruby Acceptance Testing for Web applications} + s.email = %q{bryan@brynary.com} + s.extra_rdoc_files = ["README.txt", "MIT-LICENSE.txt"] + s.files = ["History.txt", "init.rb", "install.rb", "MIT-LICENSE.txt", "README.txt", "Rakefile", "TODO.txt", "lib/webrat", "lib/webrat/core", "lib/webrat/core/area.rb", "lib/webrat/core/field.rb", "lib/webrat/core/flunk.rb", "lib/webrat/core/form.rb", "lib/webrat/core/label.rb", "lib/webrat/core/link.rb", "lib/webrat/core/locators.rb", "lib/webrat/core/logging.rb", "lib/webrat/core/matchers", "lib/webrat/core/matchers/have_content.rb", "lib/webrat/core/matchers/have_selector.rb", "lib/webrat/core/matchers/have_tag.rb", "lib/webrat/core/matchers/have_xpath.rb", "lib/webrat/core/matchers.rb", "lib/webrat/core/methods.rb", "lib/webrat/core/mime.rb", "lib/webrat/core/nokogiri.rb", "lib/webrat/core/scope.rb", "lib/webrat/core/select_option.rb", "lib/webrat/core/session.rb", "lib/webrat/core.rb", "lib/webrat/core_extensions", "lib/webrat/core_extensions/blank.rb", "lib/webrat/core_extensions/deprecate.rb", "lib/webrat/core_extensions/detect_mapped.rb", "lib/webrat/core_extensions/hash_with_indifferent_access.rb", "lib/webrat/core_extensions/meta_class.rb", "lib/webrat/core_extensions/nil_to_param.rb", "lib/webrat/mechanize.rb", "lib/webrat/merb.rb", "lib/webrat/rack.rb", "lib/webrat/rails", "lib/webrat/rails/redirect_actions.rb", "lib/webrat/rails.rb", "lib/webrat/selenium", "lib/webrat/selenium/location_strategy_javascript", "lib/webrat/selenium/location_strategy_javascript/button.js", "lib/webrat/selenium/location_strategy_javascript/label.js", "lib/webrat/selenium/location_strategy_javascript/webrat.js", "lib/webrat/selenium/location_strategy_javascript/webratlink.js", "lib/webrat/selenium/location_strategy_javascript/webratlinkwithin.js", "lib/webrat/selenium/location_strategy_javascript/webratselectwithoption.js", "lib/webrat/selenium/selenium_extensions.js", "lib/webrat/selenium/selenium_session.rb", "lib/webrat/selenium.rb", "lib/webrat/sinatra.rb", "lib/webrat.rb"] + s.has_rdoc = true + s.homepage = %q{http://github.com/brynary/webrat} + s.require_paths = ["lib"] + s.rubygems_version = %q{1.3.1} + s.summary = %q{Webrat. Ruby Acceptance Testing for Web applications} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 2 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, [">= 1.0.3"]) + else + s.add_dependency(%q, [">= 1.0.3"]) + end + else + s.add_dependency(%q, [">= 1.0.3"]) + end +end diff --git a/merb/merb-auth/setup.rb b/merb/merb-auth/setup.rb new file mode 100644 index 0000000..612f01d --- /dev/null +++ b/merb/merb-auth/setup.rb @@ -0,0 +1,44 @@ +# This file is specifically setup for use with the merb-auth plugin. +# This file should be used to setup and configure your authentication stack. +# It is not required and may safely be deleted. +# +# To change the parameter names for the password or login field you may set either of these two options +# +# Merb::Plugins.config[:"merb-auth"][:login_param] = :email +# Merb::Plugins.config[:"merb-auth"][:password_param] = :my_password_field_name + +begin + # Sets the default class ofr authentication. This is primarily used for + # Plugins and the default strategies + Merb::Authentication.user_class = User + + + # Mixin the salted user mixin + require 'merb-auth-more/mixins/salted_user' + Merb::Authentication.user_class.class_eval{ include Merb::Authentication::Mixins::SaltedUser } + + # Setup the session serialization + class Merb::Authentication + + def fetch_user(session_user_id) + Merb::Authentication.user_class.get(session_user_id) + end + + def store_user(user) + user.nil? ? user : user.id + end + end + +rescue + Merb.logger.error <<-TEXT + + You need to setup some kind of user class with merb-auth. + Merb::Authentication.user_class = User + + If you want to fully customize your authentication you should use merb-core directly. + + See merb/merb-auth/setup.rb and strategies.rb to customize your setup + + TEXT +end + diff --git a/merb/merb-auth/strategies.rb b/merb/merb-auth/strategies.rb new file mode 100644 index 0000000..fd6f20a --- /dev/null +++ b/merb/merb-auth/strategies.rb @@ -0,0 +1,11 @@ +# This file is specifically for you to define your strategies +# +# You should declare you strategies directly and/or use +# Merb::Authentication.activate!(:label_of_strategy) +# +# To load and set the order of strategy processing + +Merb::Slices::config[:"merb-auth-slice-password"][:no_default_strategies] = true + +Merb::Authentication.activate!(:default_password_form) +Merb::Authentication.activate!(:default_basic_auth) \ No newline at end of file diff --git a/merb/session/session.rb b/merb/session/session.rb new file mode 100644 index 0000000..5d05316 --- /dev/null +++ b/merb/session/session.rb @@ -0,0 +1,9 @@ +module Merb + module Session + + # The Merb::Session module gets mixed into Merb::SessionContainer to allow + # app-level functionality; it will be included and methods will be available + # through request.session as instance methods. + + end +end \ No newline at end of file diff --git a/public/.htaccess b/public/.htaccess new file mode 100644 index 0000000..455e706 --- /dev/null +++ b/public/.htaccess @@ -0,0 +1,17 @@ +# Sets the default handler for FastCGI scripts +AddHandler fastcgi-script .fcgi + +# If Apache2 is used together with mod_fcgid, +# uncomment the line below and comment in the line +# above to set the correct script handler +#AddHandler fcgid-script .fcgi + +RewriteEngine On + +RewriteRule ^$ index.html [QSA] +RewriteRule ^([^.]+)$ $1.html [QSA] +RewriteCond %{REQUEST_FILENAME} !-f +RewriteRule ^(.*)$ merb.fcgi [QSA,L] + + +ErrorDocument 500 "

    Application Error

    Merb could not be reached" diff --git a/public/cache/klasses.html b/public/cache/klasses.html new file mode 100644 index 0000000..7958b34 --- /dev/null +++ b/public/cache/klasses.html @@ -0,0 +1,29 @@ + + + + Fresh Merb App + + + + + + + + + \ No newline at end of file diff --git a/public/cache/klasses/Merb::BootLoader.html b/public/cache/klasses/Merb::BootLoader.html new file mode 100644 index 0000000..7cfe8f0 --- /dev/null +++ b/public/cache/klasses/Merb::BootLoader.html @@ -0,0 +1,127 @@ + + + + Fresh Merb App + + + + + + +
    +

    Merb::BootLoader

    +

    Class Methods

    +
    +

    Merb::BootLoader

    +

    + after_app_loads(&block) +

    +
    +
    +

    + Execute a block of code after the app loads. +

    Parameters

    + + + + +
    &block:A block to be added to the callbacks that will be executed after the app + loads. + +

    + :api: public +

    + Show source +
    # File lib/merb-core/bootloader.rb, line 157
          def after_app_loads(&block)
            after_load_callbacks << block
          end
    +
    +
    +

    Merb::BootLoader

    +

    + before_app_loads(&block) +

    +
    +
    +

    + Execute a block of code before the app loads but after dependencies load. +

    Parameters

    + + + + +
    &block:A block to be added to the callbacks that will be executed before the app + loads. + +

    + :api: public +

    + Show source +
    # File lib/merb-core/bootloader.rb, line 169
          def before_app_loads(&block)
            before_load_callbacks << block
          end
    +
    +
    +

    Merb::BootLoader

    +

    + before_master_shutdown(&block) +

    +
    +
    +

    + Execute a block of code before master process is shut down. Only makes + sense on platforms where Merb server can use forking. +

    Parameters

    + + + + +
    &block:A block to be added to the callbacks that will be executed before master + process is shut down. + +

    + :api: public +

    + Show source +
    # File lib/merb-core/bootloader.rb, line 182
          def before_master_shutdown(&block)
            before_master_shutdown_callbacks << block
          end
    +
    +
    +

    Merb::BootLoader

    +

    + before_worker_shutdown(&block) +

    +
    +
    +

    + Execute a block of code before worker process is shut down. Only makes + sense on platforms where Merb server can use forking. +

    Parameters

    + + + + +
    &block:A block to be added to the callbacks that will be executed before worker + process is shut down. + +

    + :api: public +

    + Show source +
    # File lib/merb-core/bootloader.rb, line 195
          def before_worker_shutdown(&block)
            before_worker_shutdown_callbacks << block
          end
    +
    +
    + + + \ No newline at end of file diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..c908d63 Binary files /dev/null and b/public/favicon.ico differ diff --git a/public/images/merb.jpg b/public/images/merb.jpg new file mode 100644 index 0000000..a19dcf4 Binary files /dev/null and b/public/images/merb.jpg differ diff --git a/public/images/up.png b/public/images/up.png new file mode 100644 index 0000000..5a25ae7 Binary files /dev/null and b/public/images/up.png differ diff --git a/public/javascripts/application.js b/public/javascripts/application.js new file mode 100644 index 0000000..bf9b3b0 --- /dev/null +++ b/public/javascripts/application.js @@ -0,0 +1,11 @@ +// Common JavaScript code across your application goes here. + +$(function() { + $("a.source").click(function() { + if($(this).next().is(":visible")) + $(this).html("Show source").next().hide(); + else + $(this).html("Hide source").next().show(); + return false; + }); +}); \ No newline at end of file diff --git a/public/javascripts/jquery.js b/public/javascripts/jquery.js new file mode 100644 index 0000000..82b98e1 --- /dev/null +++ b/public/javascripts/jquery.js @@ -0,0 +1,32 @@ +/* + * jQuery 1.2.6 - New Wave Javascript + * + * Copyright (c) 2008 John Resig (jquery.com) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * $Date: 2008-05-24 14:22:17 -0400 (Sat, 24 May 2008) $ + * $Rev: 5685 $ + */ +(function(){var _jQuery=window.jQuery,_$=window.$;var jQuery=window.jQuery=window.$=function(selector,context){return new jQuery.fn.init(selector,context);};var quickExpr=/^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/,isSimple=/^.[^:#\[\.]*$/,undefined;jQuery.fn=jQuery.prototype={init:function(selector,context){selector=selector||document;if(selector.nodeType){this[0]=selector;this.length=1;return this;}if(typeof selector=="string"){var match=quickExpr.exec(selector);if(match&&(match[1]||!context)){if(match[1])selector=jQuery.clean([match[1]],context);else{var elem=document.getElementById(match[3]);if(elem){if(elem.id!=match[3])return jQuery().find(selector);return jQuery(elem);}selector=[];}}else +return jQuery(context).find(selector);}else if(jQuery.isFunction(selector))return jQuery(document)[jQuery.fn.ready?"ready":"load"](selector);return this.setArray(jQuery.makeArray(selector));},jquery:"1.2.6",size:function(){return this.length;},length:0,get:function(num){return num==undefined?jQuery.makeArray(this):this[num];},pushStack:function(elems){var ret=jQuery(elems);ret.prevObject=this;return ret;},setArray:function(elems){this.length=0;Array.prototype.push.apply(this,elems);return this;},each:function(callback,args){return jQuery.each(this,callback,args);},index:function(elem){var ret=-1;return jQuery.inArray(elem&&elem.jquery?elem[0]:elem,this);},attr:function(name,value,type){var options=name;if(name.constructor==String)if(value===undefined)return this[0]&&jQuery[type||"attr"](this[0],name);else{options={};options[name]=value;}return this.each(function(i){for(name in options)jQuery.attr(type?this.style:this,name,jQuery.prop(this,options[name],type,i,name));});},css:function(key,value){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])jQuery(html,this[0].ownerDocument).clone().insertBefore(this[0]).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,false,function(elem){if(this.nodeType==1)this.appendChild(elem);});},prepend:function(){return this.domManip(arguments,true,true,function(elem){if(this.nodeType==1)this.insertBefore(elem,this.firstChild);});},before:function(){return this.domManip(arguments,false,false,function(elem){this.parentNode.insertBefore(elem,this);});},after:function(){return this.domManip(arguments,false,true,function(elem){this.parentNode.insertBefore(elem,this.nextSibling);});},end:function(){return this.prevObject||jQuery([]);},find:function(selector){var elems=jQuery.map(this,function(elem){return jQuery.find(selector,elem);});return this.pushStack(/[^+>] [^+>]/.test(selector)||selector.indexOf("..")>-1?jQuery.unique(elems):elems);},clone:function(events){var ret=this.map(function(){if(jQuery.browser.msie&&!jQuery.isXMLDoc(this)){var clone=this.cloneNode(true),container=document.createElement("div");container.appendChild(clone);return jQuery.clean([container.innerHTML])[0];}else +return this.cloneNode(true);});var clone=ret.find("*").andSelf().each(function(){if(this[expando]!=undefined)this[expando]=null;});if(events===true)this.find("*").andSelf().each(function(i){if(this.nodeType==3)return;var events=jQuery.data(this,"events");for(var type in events)for(var handler in events[type])jQuery.event.add(clone[i],type,events[type][handler],events[type][handler].data);});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,this));},not:function(selector){if(selector.constructor==String)if(isSimple.test(selector))return this.pushStack(jQuery.multiFilter(selector,this,true));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 this.is("."+selector);},val:function(value){if(value==undefined){if(this.length){var elem=this[0];if(jQuery.nodeName(elem,"select")){var index=elem.selectedIndex,values=[],options=elem.options,one=elem.type=="select-one";if(index<0)return null;for(var i=one?index:0,max=one?index+1:options.length;i=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: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));},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);},data:function(key,value){var parts=key.split(".");parts[1]=parts[1]?"."+parts[1]:"";if(value===undefined){var data=this.triggerHandler("getData"+parts[1]+"!",[parts[0]]);if(data===undefined&&this.length)data=jQuery.data(this[0],key);return data===undefined&&parts[1]?this.data(parts[0]):data;}else +return this.trigger("setData"+parts[1]+"!",[parts[0],value]).each(function(){jQuery.data(this,key,value);});},removeData:function(key){return this.each(function(){jQuery.removeData(this,key);});},domManip:function(args,table,reverse,callback){var clone=this.length>1,elems;return this.each(function(){if(!elems){elems=jQuery.clean(args,this.ownerDocument);if(reverse)elems.reverse();}var obj=this;if(table&&jQuery.nodeName(this,"table")&&jQuery.nodeName(elems[0],"tr"))obj=this.getElementsByTagName("tbody")[0]||this.appendChild(this.ownerDocument.createElement("tbody"));var scripts=jQuery([]);jQuery.each(elems,function(){var elem=clone?jQuery(this).clone(true)[0]:this;if(jQuery.nodeName(elem,"script"))scripts=scripts.add(elem);else{if(elem.nodeType==1)scripts=scripts.add(jQuery("script",elem).remove());callback.call(obj,elem);}});scripts.each(evalScript);});}};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(){var target=arguments[0]||{},i=1,length=arguments.length,deep=false,options;if(target.constructor==Boolean){deep=target;target=arguments[1]||{};i=2;}if(typeof target!="object"&&typeof target!="function")target={};if(length==i){target=this;--i;}for(;i-1;}},swap:function(elem,options,callback){var old={};for(var name in options){old[name]=elem.style[name];elem.style[name]=options[name];}callback.call(elem);for(var name in options)elem.style[name]=old[name];},css:function(elem,name,force){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;var padding=0,border=0;jQuery.each(which,function(){padding+=parseFloat(jQuery.curCSS(elem,"padding"+this,true))||0;border+=parseFloat(jQuery.curCSS(elem,"border"+this+"Width",true))||0;});val-=Math.round(padding+border);}if(jQuery(elem).is(":visible"))getWH();else +jQuery.swap(elem,props,getWH);return Math.max(0,val);}return jQuery.curCSS(elem,name,force);},curCSS:function(elem,name,force){var ret,style=elem.style;function color(elem){if(!jQuery.browser.safari)return false;var ret=defaultView.getComputedStyle(elem,null);return!ret||ret.getPropertyValue("color")=="";}if(name=="opacity"&&jQuery.browser.msie){ret=jQuery.attr(style,"opacity");return ret==""?"1":ret;}if(jQuery.browser.opera&&name=="display"){var save=style.outline;style.outline="0 solid black";style.outline=save;}if(name.match(/float/i))name=styleFloat;if(!force&&style&&style[name])ret=style[name];else if(defaultView.getComputedStyle){if(name.match(/float/i))name="float";name=name.replace(/([A-Z])/g,"-$1").toLowerCase();var computedStyle=defaultView.getComputedStyle(elem,null);if(computedStyle&&!color(elem))ret=computedStyle.getPropertyValue(name);else{var swap=[],stack=[],a=elem,i=0;for(;a&&color(a);a=a.parentNode)stack.unshift(a);for(;i]*?)\/>/g,function(all,front,tag){return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?all:front+">";});var tags=jQuery.trim(elem).toLowerCase(),div=context.createElement("div");var wrap=!tags.indexOf("",""]||!tags.indexOf("",""]||tags.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"","
    "]||!tags.indexOf("",""]||(!tags.indexOf("",""]||!tags.indexOf("",""]||jQuery.browser.msie&&[1,"div
    ","
    "]||[0,"",""];div.innerHTML=wrap[1]+elem+wrap[2];while(wrap[0]--)div=div.lastChild;if(jQuery.browser.msie){var tbody=!tags.indexOf(""&&tags.indexOf("=0;--j)if(jQuery.nodeName(tbody[j],"tbody")&&!tbody[j].childNodes.length)tbody[j].parentNode.removeChild(tbody[j]);if(/^\s/.test(elem))div.insertBefore(context.createTextNode(elem.match(/^\s*/)[0]),div.firstChild);}elem=jQuery.makeArray(div.childNodes);}if(elem.length===0&&(!jQuery.nodeName(elem,"form")&&!jQuery.nodeName(elem,"select")))return;if(elem[0]==undefined||jQuery.nodeName(elem,"form")||elem.options)ret.push(elem);else +ret=jQuery.merge(ret,elem);});return ret;},attr:function(elem,name,value){if(!elem||elem.nodeType==3||elem.nodeType==8)return undefined;var notxml=!jQuery.isXMLDoc(elem),set=value!==undefined,msie=jQuery.browser.msie;name=notxml&&jQuery.props[name]||name;if(elem.tagName){var special=/href|src|style/.test(name);if(name=="selected"&&jQuery.browser.safari)elem.parentNode.selectedIndex;if(name in elem&¬xml&&!special){if(set){if(name=="type"&&jQuery.nodeName(elem,"input")&&elem.parentNode)throw"type property can't be changed";elem[name]=value;}if(jQuery.nodeName(elem,"form")&&elem.getAttributeNode(name))return elem.getAttributeNode(name).nodeValue;return elem[name];}if(msie&¬xml&&name=="style")return jQuery.attr(elem.style,"cssText",value);if(set)elem.setAttribute(name,""+value);var attr=msie&¬xml&&special?elem.getAttribute(name,2):elem.getAttribute(name);return attr===null?undefined:attr;}if(msie&&name=="opacity"){if(set){elem.zoom=1;elem.filter=(elem.filter||"").replace(/alpha\([^)]*\)/,"")+(parseInt(value)+''=="NaN"?"":"alpha(opacity="+value*100+")");}return elem.filter&&elem.filter.indexOf("opacity=")>=0?(parseFloat(elem.filter.match(/opacity=([^)]*)/)[1])/100)+'':"";}name=name.replace(/-([a-z])/ig,function(all,letter){return letter.toUpperCase();});if(set)elem[name]=value;return elem[name];},trim:function(text){return(text||"").replace(/^\s+|\s+$/g,"");},makeArray:function(array){var ret=[];if(array!=null){var i=array.length;if(i==null||array.split||array.setInterval||array.call)ret[0]=array;else +while(i)ret[--i]=array[i];}return ret;},inArray:function(elem,array){for(var i=0,length=array.length;i*",this).remove();while(this.firstChild)this.removeChild(this.firstChild);}},function(name,fn){jQuery.fn[name]=function(){return this.each(fn,arguments);};});jQuery.each(["Height","Width"],function(i,name){var type=name.toLowerCase();jQuery.fn[type]=function(size){return this[0]==window?jQuery.browser.opera&&document.body["client"+name]||jQuery.browser.safari&&window["inner"+name]||document.compatMode=="CSS1Compat"&&document.documentElement["client"+name]||document.body["client"+name]:this[0]==document?Math.max(Math.max(document.body["scroll"+name],document.documentElement["scroll"+name]),Math.max(document.body["offset"+name],document.documentElement["offset"+name])):size==undefined?(this.length?jQuery.css(this[0],type):null):this.css(type,size.constructor==String?size:size+"px");};});function num(elem,prop){return elem[0]&&parseInt(jQuery.curCSS(elem[0],prop,true),10)||0;}var chars=jQuery.browser.safari&&parseInt(jQuery.browser.version)<417?"(?:[\\w*_-]|\\\\.)":"(?:[\\w\u0128-\uFFFF*_-]|\\\\.)",quickChild=new RegExp("^>\\s*("+chars+"+)"),quickID=new RegExp("^("+chars+"+)(#)("+chars+"+)"),quickClass=new RegExp("^([#.]?)("+chars+"*)");jQuery.extend({expr:{"":function(a,i,m){return m[2]=="*"||jQuery.nodeName(a,m[2]);},"#":function(a,i,m){return a.getAttribute("id")==m[2];},":":{lt:function(a,i,m){return im[3]-0;},nth:function(a,i,m){return m[3]-0==i;},eq:function(a,i,m){return m[3]-0==i;},first:function(a,i){return i==0;},last:function(a,i,m,r){return i==r.length-1;},even:function(a,i){return i%2==0;},odd:function(a,i){return i%2;},"first-child":function(a){return a.parentNode.getElementsByTagName("*")[0]==a;},"last-child":function(a){return jQuery.nth(a.parentNode.lastChild,1,"previousSibling")==a;},"only-child":function(a){return!jQuery.nth(a.parentNode.lastChild,2,"previousSibling");},parent:function(a){return a.firstChild;},empty:function(a){return!a.firstChild;},contains:function(a,i,m){return(a.textContent||a.innerText||jQuery(a).text()||"").indexOf(m[3])>=0;},visible:function(a){return"hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden";},hidden:function(a){return"hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden";},enabled:function(a){return!a.disabled;},disabled:function(a){return a.disabled;},checked:function(a){return a.checked;},selected:function(a){return a.selected||jQuery.attr(a,"selected");},text:function(a){return"text"==a.type;},radio:function(a){return"radio"==a.type;},checkbox:function(a){return"checkbox"==a.type;},file:function(a){return"file"==a.type;},password:function(a){return"password"==a.type;},submit:function(a){return"submit"==a.type;},image:function(a){return"image"==a.type;},reset:function(a){return"reset"==a.type;},button:function(a){return"button"==a.type||jQuery.nodeName(a,"button");},input:function(a){return/input|select|textarea|button/i.test(a.nodeName);},has:function(a,i,m){return jQuery.find(m[3],a).length;},header:function(a){return/h\d/i.test(a.nodeName);},animated:function(a){return jQuery.grep(jQuery.timers,function(fn){return a==fn.elem;}).length;}}},parse:[/^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,/^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,new RegExp("^([:.#]*)("+chars+"+)")],multiFilter:function(expr,elems,not){var old,cur=[];while(expr&&expr!=old){old=expr;var f=jQuery.filter(expr,elems,not);expr=f.t.replace(/^\s*,\s*/,"");cur=not?elems=f.r:jQuery.merge(cur,f.r);}return cur;},find:function(t,context){if(typeof t!="string")return[t];if(context&&context.nodeType!=1&&context.nodeType!=9)return[];context=context||document;var ret=[context],done=[],last,nodeName;while(t&&last!=t){var r=[];last=t;t=jQuery.trim(t);var foundToken=false,re=quickChild,m=re.exec(t);if(m){nodeName=m[1].toUpperCase();for(var i=0;ret[i];i++)for(var c=ret[i].firstChild;c;c=c.nextSibling)if(c.nodeType==1&&(nodeName=="*"||c.nodeName.toUpperCase()==nodeName))r.push(c);ret=r;t=t.replace(re,"");if(t.indexOf(" ")==0)continue;foundToken=true;}else{re=/^([>+~])\s*(\w*)/i;if((m=re.exec(t))!=null){r=[];var merge={};nodeName=m[2].toUpperCase();m=m[1];for(var j=0,rl=ret.length;j=0;if(!not&&pass||not&&!pass)tmp.push(r[i]);}return tmp;},filter:function(t,r,not){var last;while(t&&t!=last){last=t;var p=jQuery.parse,m;for(var i=0;p[i];i++){m=p[i].exec(t);if(m){t=t.substring(m[0].length);m[2]=m[2].replace(/\\/g,"");break;}}if(!m)break;if(m[1]==":"&&m[2]=="not")r=isSimple.test(m[3])?jQuery.filter(m[3],r,true).r:jQuery(r).not(m[3]);else if(m[1]==".")r=jQuery.classFilter(r,m[2],not);else if(m[1]=="["){var tmp=[],type=m[3];for(var i=0,rl=r.length;i=0)^not)tmp.push(a);}r=tmp;}else if(m[1]==":"&&m[2]=="nth-child"){var merge={},tmp=[],test=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(m[3]=="even"&&"2n"||m[3]=="odd"&&"2n+1"||!/\D/.test(m[3])&&"0n+"+m[3]||m[3]),first=(test[1]+(test[2]||1))-0,last=test[3]-0;for(var i=0,rl=r.length;i=0)add=true;if(add^not)tmp.push(node);}r=tmp;}else{var fn=jQuery.expr[m[1]];if(typeof fn=="object")fn=fn[m[2]];if(typeof fn=="string")fn=eval("false||function(a,i){return "+fn+";}");r=jQuery.grep(r,function(elem,i){return fn(elem,i,m,r);},not);}}return{r:r,t:t};},dir:function(elem,dir){var matched=[],cur=elem[dir];while(cur&&cur!=document){if(cur.nodeType==1)matched.push(cur);cur=cur[dir];}return matched;},nth:function(cur,result,dir,elem){result=result||1;var num=0;for(;cur;cur=cur[dir])if(cur.nodeType==1&&++num==result)break;return cur;},sibling:function(n,elem){var r=[];for(;n;n=n.nextSibling){if(n.nodeType==1&&n!=elem)r.push(n);}return r;}});jQuery.event={add:function(elem,types,handler,data){if(elem.nodeType==3||elem.nodeType==8)return;if(jQuery.browser.msie&&elem.setInterval)elem=window;if(!handler.guid)handler.guid=this.guid++;if(data!=undefined){var fn=handler;handler=this.proxy(fn,function(){return fn.apply(this,arguments);});handler.data=data;}var events=jQuery.data(elem,"events")||jQuery.data(elem,"events",{}),handle=jQuery.data(elem,"handle")||jQuery.data(elem,"handle",function(){if(typeof jQuery!="undefined"&&!jQuery.event.triggered)return jQuery.event.handle.apply(arguments.callee.elem,arguments);});handle.elem=elem;jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];handler.type=parts[1];var handlers=events[type];if(!handlers){handlers=events[type]={};if(!jQuery.event.special[type]||jQuery.event.special[type].setup.call(elem)===false){if(elem.addEventListener)elem.addEventListener(type,handle,false);else if(elem.attachEvent)elem.attachEvent("on"+type,handle);}}handlers[handler.guid]=handler;jQuery.event.global[type]=true;});elem=null;},guid:1,global:{},remove:function(elem,types,handler){if(elem.nodeType==3||elem.nodeType==8)return;var events=jQuery.data(elem,"events"),ret,index;if(events){if(types==undefined||(typeof types=="string"&&types.charAt(0)=="."))for(var type in events)this.remove(elem,type+(types||""));else{if(types.type){handler=types.handler;types=types.type;}jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];if(events[type]){if(handler)delete events[type][handler.guid];else +for(handler in events[type])if(!parts[1]||events[type][handler].type==parts[1])delete events[type][handler];for(ret in events[type])break;if(!ret){if(!jQuery.event.special[type]||jQuery.event.special[type].teardown.call(elem)===false){if(elem.removeEventListener)elem.removeEventListener(type,jQuery.data(elem,"handle"),false);else if(elem.detachEvent)elem.detachEvent("on"+type,jQuery.data(elem,"handle"));}ret=null;delete events[type];}}});}for(ret in events)break;if(!ret){var handle=jQuery.data(elem,"handle");if(handle)handle.elem=null;jQuery.removeData(elem,"events");jQuery.removeData(elem,"handle");}}},trigger:function(type,data,elem,donative,extra){data=jQuery.makeArray(data);if(type.indexOf("!")>=0){type=type.slice(0,-1);var exclusive=true;}if(!elem){if(this.global[type])jQuery("*").add([window,document]).trigger(type,data);}else{if(elem.nodeType==3||elem.nodeType==8)return undefined;var val,ret,fn=jQuery.isFunction(elem[type]||null),event=!data[0]||!data[0].preventDefault;if(event){data.unshift({type:type,target:elem,preventDefault:function(){},stopPropagation:function(){},timeStamp:now()});data[0][expando]=true;}data[0].type=type;if(exclusive)data[0].exclusive=true;var handle=jQuery.data(elem,"handle");if(handle)val=handle.apply(elem,data);if((!fn||(jQuery.nodeName(elem,'a')&&type=="click"))&&elem["on"+type]&&elem["on"+type].apply(elem,data)===false)val=false;if(event)data.shift();if(extra&&jQuery.isFunction(extra)){ret=extra.apply(elem,val==null?data:data.concat(val));if(ret!==undefined)val=ret;}if(fn&&donative!==false&&val!==false&&!(jQuery.nodeName(elem,'a')&&type=="click")){this.triggered=true;try{elem[type]();}catch(e){}}this.triggered=false;}return val;},handle:function(event){var val,ret,namespace,all,handlers;event=arguments[0]=jQuery.event.fix(event||window.event);namespace=event.type.split(".");event.type=namespace[0];namespace=namespace[1];all=!namespace&&!event.exclusive;handlers=(jQuery.data(this,"events")||{})[event.type];for(var j in handlers){var handler=handlers[j];if(all||handler.type==namespace){event.handler=handler;event.data=handler.data;ret=handler.apply(this,arguments);if(val!==false)val=ret;if(ret===false){event.preventDefault();event.stopPropagation();}}}return val;},fix:function(event){if(event[expando]==true)return event;var originalEvent=event;event={originalEvent:originalEvent};var props="altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target timeStamp toElement type view wheelDelta which".split(" ");for(var i=props.length;i;i--)event[props[i]]=originalEvent[props[i]];event[expando]=true;event.preventDefault=function(){if(originalEvent.preventDefault)originalEvent.preventDefault();originalEvent.returnValue=false;};event.stopPropagation=function(){if(originalEvent.stopPropagation)originalEvent.stopPropagation();originalEvent.cancelBubble=true;};event.timeStamp=event.timeStamp||now();if(!event.target)event.target=event.srcElement||document;if(event.target.nodeType==3)event.target=event.target.parentNode;if(!event.relatedTarget&&event.fromElement)event.relatedTarget=event.fromElement==event.target?event.toElement:event.fromElement;if(event.pageX==null&&event.clientX!=null){var doc=document.documentElement,body=document.body;event.pageX=event.clientX+(doc&&doc.scrollLeft||body&&body.scrollLeft||0)-(doc.clientLeft||0);event.pageY=event.clientY+(doc&&doc.scrollTop||body&&body.scrollTop||0)-(doc.clientTop||0);}if(!event.which&&((event.charCode||event.charCode===0)?event.charCode:event.keyCode))event.which=event.charCode||event.keyCode;if(!event.metaKey&&event.ctrlKey)event.metaKey=event.ctrlKey;if(!event.which&&event.button)event.which=(event.button&1?1:(event.button&2?3:(event.button&4?2:0)));return event;},proxy:function(fn,proxy){proxy.guid=fn.guid=fn.guid||proxy.guid||this.guid++;return proxy;},special:{ready:{setup:function(){bindReady();return;},teardown:function(){return;}},mouseenter:{setup:function(){if(jQuery.browser.msie)return false;jQuery(this).bind("mouseover",jQuery.event.special.mouseenter.handler);return true;},teardown:function(){if(jQuery.browser.msie)return false;jQuery(this).unbind("mouseover",jQuery.event.special.mouseenter.handler);return true;},handler:function(event){if(withinElement(event,this))return true;event.type="mouseenter";return jQuery.event.handle.apply(this,arguments);}},mouseleave:{setup:function(){if(jQuery.browser.msie)return false;jQuery(this).bind("mouseout",jQuery.event.special.mouseleave.handler);return true;},teardown:function(){if(jQuery.browser.msie)return false;jQuery(this).unbind("mouseout",jQuery.event.special.mouseleave.handler);return true;},handler:function(event){if(withinElement(event,this))return true;event.type="mouseleave";return jQuery.event.handle.apply(this,arguments);}}}};jQuery.fn.extend({bind:function(type,data,fn){return type=="unload"?this.one(type,data,fn):this.each(function(){jQuery.event.add(this,type,fn||data,fn&&data);});},one:function(type,data,fn){var one=jQuery.event.proxy(fn||data,function(event){jQuery(this).unbind(event,one);return(fn||data).apply(this,arguments);});return this.each(function(){jQuery.event.add(this,type,one,fn&&data);});},unbind:function(type,fn){return this.each(function(){jQuery.event.remove(this,type,fn);});},trigger:function(type,data,fn){return this.each(function(){jQuery.event.trigger(type,data,this,true,fn);});},triggerHandler:function(type,data,fn){return this[0]&&jQuery.event.trigger(type,data,this[0],false,fn);},toggle:function(fn){var args=arguments,i=1;while(i=0){var selector=url.slice(off,url.length);url=url.slice(0,off);}callback=callback||function(){};var type="GET";if(params)if(jQuery.isFunction(params)){callback=params;params=null;}else{params=jQuery.param(params);type="POST";}var self=this;jQuery.ajax({url:url,type:type,dataType:"html",data:params,complete:function(res,status){if(status=="success"||status=="notmodified")self.html(selector?jQuery("
    ").append(res.responseText.replace(//g,"")).find(selector):res.responseText);self.each(callback,[res.responseText,status,res]);}});return this;},serialize:function(){return jQuery.param(this.serializeArray());},serializeArray:function(){return this.map(function(){return jQuery.nodeName(this,"form")?jQuery.makeArray(this.elements):this;}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password/i.test(this.type));}).map(function(i,elem){var val=jQuery(this).val();return val==null?null:val.constructor==Array?jQuery.map(val,function(val,i){return{name:elem.name,value:val};}):{name:elem.name,value:val};}).get();}});jQuery.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(i,o){jQuery.fn[o]=function(f){return this.bind(o,f);};});var jsc=now();jQuery.extend({get:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data=null;}return jQuery.ajax({type:"GET",url:url,data:data,success:callback,dataType:type});},getScript:function(url,callback){return jQuery.get(url,null,callback,"script");},getJSON:function(url,data,callback){return jQuery.get(url,data,callback,"json");},post:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data={};}return jQuery.ajax({type:"POST",url:url,data:data,success:callback,dataType:type});},ajaxSetup:function(settings){jQuery.extend(jQuery.ajaxSettings,settings);},ajaxSettings:{url:location.href,global:true,type:"GET",timeout:0,contentType:"application/x-www-form-urlencoded",processData:true,async:true,data:null,username:null,password:null,accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(s){s=jQuery.extend(true,s,jQuery.extend(true,{},jQuery.ajaxSettings,s));var jsonp,jsre=/=\?(&|$)/g,status,data,type=s.type.toUpperCase();if(s.data&&s.processData&&typeof s.data!="string")s.data=jQuery.param(s.data);if(s.dataType=="jsonp"){if(type=="GET"){if(!s.url.match(jsre))s.url+=(s.url.match(/\?/)?"&":"?")+(s.jsonp||"callback")+"=?";}else if(!s.data||!s.data.match(jsre))s.data=(s.data?s.data+"&":"")+(s.jsonp||"callback")+"=?";s.dataType="json";}if(s.dataType=="json"&&(s.data&&s.data.match(jsre)||s.url.match(jsre))){jsonp="jsonp"+jsc++;if(s.data)s.data=(s.data+"").replace(jsre,"="+jsonp+"$1");s.url=s.url.replace(jsre,"="+jsonp+"$1");s.dataType="script";window[jsonp]=function(tmp){data=tmp;success();complete();window[jsonp]=undefined;try{delete window[jsonp];}catch(e){}if(head)head.removeChild(script);};}if(s.dataType=="script"&&s.cache==null)s.cache=false;if(s.cache===false&&type=="GET"){var ts=now();var ret=s.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+ts+"$2");s.url=ret+((ret==s.url)?(s.url.match(/\?/)?"&":"?")+"_="+ts:"");}if(s.data&&type=="GET"){s.url+=(s.url.match(/\?/)?"&":"?")+s.data;s.data=null;}if(s.global&&!jQuery.active++)jQuery.event.trigger("ajaxStart");var remote=/^(?:\w+:)?\/\/([^\/?#]+)/;if(s.dataType=="script"&&type=="GET"&&remote.test(s.url)&&remote.exec(s.url)[1]!=location.host){var head=document.getElementsByTagName("head")[0];var script=document.createElement("script");script.src=s.url;if(s.scriptCharset)script.charset=s.scriptCharset;if(!jsonp){var done=false;script.onload=script.onreadystatechange=function(){if(!done&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){done=true;success();complete();head.removeChild(script);}};}head.appendChild(script);return undefined;}var requestDone=false;var xhr=window.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest();if(s.username)xhr.open(type,s.url,s.async,s.username,s.password);else +xhr.open(type,s.url,s.async);try{if(s.data)xhr.setRequestHeader("Content-Type",s.contentType);if(s.ifModified)xhr.setRequestHeader("If-Modified-Since",jQuery.lastModified[s.url]||"Thu, 01 Jan 1970 00:00:00 GMT");xhr.setRequestHeader("X-Requested-With","XMLHttpRequest");xhr.setRequestHeader("Accept",s.dataType&&s.accepts[s.dataType]?s.accepts[s.dataType]+", */*":s.accepts._default);}catch(e){}if(s.beforeSend&&s.beforeSend(xhr,s)===false){s.global&&jQuery.active--;xhr.abort();return false;}if(s.global)jQuery.event.trigger("ajaxSend",[xhr,s]);var onreadystatechange=function(isTimeout){if(!requestDone&&xhr&&(xhr.readyState==4||isTimeout=="timeout")){requestDone=true;if(ival){clearInterval(ival);ival=null;}status=isTimeout=="timeout"&&"timeout"||!jQuery.httpSuccess(xhr)&&"error"||s.ifModified&&jQuery.httpNotModified(xhr,s.url)&&"notmodified"||"success";if(status=="success"){try{data=jQuery.httpData(xhr,s.dataType,s.dataFilter);}catch(e){status="parsererror";}}if(status=="success"){var modRes;try{modRes=xhr.getResponseHeader("Last-Modified");}catch(e){}if(s.ifModified&&modRes)jQuery.lastModified[s.url]=modRes;if(!jsonp)success();}else +jQuery.handleError(s,xhr,status);complete();if(s.async)xhr=null;}};if(s.async){var ival=setInterval(onreadystatechange,13);if(s.timeout>0)setTimeout(function(){if(xhr){xhr.abort();if(!requestDone)onreadystatechange("timeout");}},s.timeout);}try{xhr.send(s.data);}catch(e){jQuery.handleError(s,xhr,null,e);}if(!s.async)onreadystatechange();function success(){if(s.success)s.success(data,status);if(s.global)jQuery.event.trigger("ajaxSuccess",[xhr,s]);}function complete(){if(s.complete)s.complete(xhr,status);if(s.global)jQuery.event.trigger("ajaxComplete",[xhr,s]);if(s.global&&!--jQuery.active)jQuery.event.trigger("ajaxStop");}return xhr;},handleError:function(s,xhr,status,e){if(s.error)s.error(xhr,status,e);if(s.global)jQuery.event.trigger("ajaxError",[xhr,s,e]);},active:0,httpSuccess:function(xhr){try{return!xhr.status&&location.protocol=="file:"||(xhr.status>=200&&xhr.status<300)||xhr.status==304||xhr.status==1223||jQuery.browser.safari&&xhr.status==undefined;}catch(e){}return false;},httpNotModified:function(xhr,url){try{var xhrRes=xhr.getResponseHeader("Last-Modified");return xhr.status==304||xhrRes==jQuery.lastModified[url]||jQuery.browser.safari&&xhr.status==undefined;}catch(e){}return false;},httpData:function(xhr,type,filter){var ct=xhr.getResponseHeader("content-type"),xml=type=="xml"||!type&&ct&&ct.indexOf("xml")>=0,data=xml?xhr.responseXML:xhr.responseText;if(xml&&data.documentElement.tagName=="parsererror")throw"parsererror";if(filter)data=filter(data,type);if(type=="script")jQuery.globalEval(data);if(type=="json")data=eval("("+data+")");return data;},param:function(a){var s=[];if(a.constructor==Array||a.jquery)jQuery.each(a,function(){s.push(encodeURIComponent(this.name)+"="+encodeURIComponent(this.value));});else +for(var j in a)if(a[j]&&a[j].constructor==Array)jQuery.each(a[j],function(){s.push(encodeURIComponent(j)+"="+encodeURIComponent(this));});else +s.push(encodeURIComponent(j)+"="+encodeURIComponent(jQuery.isFunction(a[j])?a[j]():a[j]));return s.join("&").replace(/%20/g,"+");}});jQuery.fn.extend({show:function(speed,callback){return speed?this.animate({height:"show",width:"show",opacity:"show"},speed,callback):this.filter(":hidden").each(function(){this.style.display=this.oldblock||"";if(jQuery.css(this,"display")=="none"){var elem=jQuery("<"+this.tagName+" />").appendTo("body");this.style.display=elem.css("display");if(this.style.display=="none")this.style.display="block";elem.remove();}}).end();},hide:function(speed,callback){return speed?this.animate({height:"hide",width:"hide",opacity:"hide"},speed,callback):this.filter(":visible").each(function(){this.oldblock=this.oldblock||jQuery.css(this,"display");this.style.display="none";}).end();},_toggle:jQuery.fn.toggle,toggle:function(fn,fn2){return jQuery.isFunction(fn)&&jQuery.isFunction(fn2)?this._toggle.apply(this,arguments):fn?this.animate({height:"toggle",width:"toggle",opacity:"toggle"},fn,fn2):this.each(function(){jQuery(this)[jQuery(this).is(":hidden")?"show":"hide"]();});},slideDown:function(speed,callback){return this.animate({height:"show"},speed,callback);},slideUp:function(speed,callback){return this.animate({height:"hide"},speed,callback);},slideToggle:function(speed,callback){return this.animate({height:"toggle"},speed,callback);},fadeIn:function(speed,callback){return this.animate({opacity:"show"},speed,callback);},fadeOut:function(speed,callback){return this.animate({opacity:"hide"},speed,callback);},fadeTo:function(speed,to,callback){return this.animate({opacity:to},speed,callback);},animate:function(prop,speed,easing,callback){var optall=jQuery.speed(speed,easing,callback);return this[optall.queue===false?"each":"queue"](function(){if(this.nodeType!=1)return false;var opt=jQuery.extend({},optall),p,hidden=jQuery(this).is(":hidden"),self=this;for(p in prop){if(prop[p]=="hide"&&hidden||prop[p]=="show"&&!hidden)return opt.complete.call(this);if(p=="height"||p=="width"){opt.display=jQuery.css(this,"display");opt.overflow=this.style.overflow;}}if(opt.overflow!=null)this.style.overflow="hidden";opt.curAnim=jQuery.extend({},prop);jQuery.each(prop,function(name,val){var e=new jQuery.fx(self,opt,name);if(/toggle|show|hide/.test(val))e[val=="toggle"?hidden?"show":"hide":val](prop);else{var parts=val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),start=e.cur(true)||0;if(parts){var end=parseFloat(parts[2]),unit=parts[3]||"px";if(unit!="px"){self.style[name]=(end||1)+unit;start=((end||1)/e.cur(true))*start;self.style[name]=start+unit;}if(parts[1])end=((parts[1]=="-="?-1:1)*end)+start;e.custom(start,end,unit);}else +e.custom(start,val,"");}});return true;});},queue:function(type,fn){if(jQuery.isFunction(type)||(type&&type.constructor==Array)){fn=type;type="fx";}if(!type||(typeof type=="string"&&!fn))return queue(this[0],type);return this.each(function(){if(fn.constructor==Array)queue(this,type,fn);else{queue(this,type).push(fn);if(queue(this,type).length==1)fn.call(this);}});},stop:function(clearQueue,gotoEnd){var timers=jQuery.timers;if(clearQueue)this.queue([]);this.each(function(){for(var i=timers.length-1;i>=0;i--)if(timers[i].elem==this){if(gotoEnd)timers[i](true);timers.splice(i,1);}});if(!gotoEnd)this.dequeue();return this;}});var queue=function(elem,type,array){if(elem){type=type||"fx";var q=jQuery.data(elem,type+"queue");if(!q||array)q=jQuery.data(elem,type+"queue",jQuery.makeArray(array));}return q;};jQuery.fn.dequeue=function(type){type=type||"fx";return this.each(function(){var q=queue(this,type);q.shift();if(q.length)q[0].call(this);});};jQuery.extend({speed:function(speed,easing,fn){var opt=speed&&speed.constructor==Object?speed:{complete:fn||!fn&&easing||jQuery.isFunction(speed)&&speed,duration:speed,easing:fn&&easing||easing&&easing.constructor!=Function&&easing};opt.duration=(opt.duration&&opt.duration.constructor==Number?opt.duration:jQuery.fx.speeds[opt.duration])||jQuery.fx.speeds.def;opt.old=opt.complete;opt.complete=function(){if(opt.queue!==false)jQuery(this).dequeue();if(jQuery.isFunction(opt.old))opt.old.call(this);};return opt;},easing:{linear:function(p,n,firstNum,diff){return firstNum+diff*p;},swing:function(p,n,firstNum,diff){return((-Math.cos(p*Math.PI)/2)+0.5)*diff+firstNum;}},timers:[],timerId:null,fx:function(elem,options,prop){this.options=options;this.elem=elem;this.prop=prop;if(!options.orig)options.orig={};}});jQuery.fx.prototype={update:function(){if(this.options.step)this.options.step.call(this.elem,this.now,this);(jQuery.fx.step[this.prop]||jQuery.fx.step._default)(this);if(this.prop=="height"||this.prop=="width")this.elem.style.display="block";},cur:function(force){if(this.elem[this.prop]!=null&&this.elem.style[this.prop]==null)return this.elem[this.prop];var r=parseFloat(jQuery.css(this.elem,this.prop,force));return r&&r>-10000?r:parseFloat(jQuery.curCSS(this.elem,this.prop))||0;},custom:function(from,to,unit){this.startTime=now();this.start=from;this.end=to;this.unit=unit||this.unit||"px";this.now=this.start;this.pos=this.state=0;this.update();var self=this;function t(gotoEnd){return self.step(gotoEnd);}t.elem=this.elem;jQuery.timers.push(t);if(jQuery.timerId==null){jQuery.timerId=setInterval(function(){var timers=jQuery.timers;for(var i=0;ithis.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var done=true;for(var i in this.options.curAnim)if(this.options.curAnim[i]!==true)done=false;if(done){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(jQuery.css(this.elem,"display")=="none")this.elem.style.display="block";}if(this.options.hide)this.elem.style.display="none";if(this.options.hide||this.options.show)for(var p in this.options.curAnim)jQuery.attr(this.elem.style,p,this.options.orig[p]);}if(done)this.options.complete.call(this.elem);return false;}else{var n=t-this.startTime;this.state=n/this.options.duration;this.pos=jQuery.easing[this.options.easing||(jQuery.easing.swing?"swing":"linear")](this.state,n,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update();}return true;}};jQuery.extend(jQuery.fx,{speeds:{slow:600,fast:200,def:400},step:{scrollLeft:function(fx){fx.elem.scrollLeft=fx.now;},scrollTop:function(fx){fx.elem.scrollTop=fx.now;},opacity:function(fx){jQuery.attr(fx.elem.style,"opacity",fx.now);},_default:function(fx){fx.elem.style[fx.prop]=fx.now+fx.unit;}}});jQuery.fn.offset=function(){var left=0,top=0,elem=this[0],results;if(elem)with(jQuery.browser){var parent=elem.parentNode,offsetChild=elem,offsetParent=elem.offsetParent,doc=elem.ownerDocument,safari2=safari&&parseInt(version)<522&&!/adobeair/i.test(userAgent),css=jQuery.curCSS,fixed=css(elem,"position")=="fixed";if(elem.getBoundingClientRect){var box=elem.getBoundingClientRect();add(box.left+Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),box.top+Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));add(-doc.documentElement.clientLeft,-doc.documentElement.clientTop);}else{add(elem.offsetLeft,elem.offsetTop);while(offsetParent){add(offsetParent.offsetLeft,offsetParent.offsetTop);if(mozilla&&!/^t(able|d|h)$/i.test(offsetParent.tagName)||safari&&!safari2)border(offsetParent);if(!fixed&&css(offsetParent,"position")=="fixed")fixed=true;offsetChild=/^body$/i.test(offsetParent.tagName)?offsetChild:offsetParent;offsetParent=offsetParent.offsetParent;}while(parent&&parent.tagName&&!/^body|html$/i.test(parent.tagName)){if(!/^inline|table.*$/i.test(css(parent,"display")))add(-parent.scrollLeft,-parent.scrollTop);if(mozilla&&css(parent,"overflow")!="visible")border(parent);parent=parent.parentNode;}if((safari2&&(fixed||css(offsetChild,"position")=="absolute"))||(mozilla&&css(offsetChild,"position")!="absolute"))add(-doc.body.offsetLeft,-doc.body.offsetTop);if(fixed)add(Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));}results={top:top,left:left};}function border(elem){add(jQuery.curCSS(elem,"borderLeftWidth",true),jQuery.curCSS(elem,"borderTopWidth",true));}function add(l,t){left+=parseInt(l,10)||0;top+=parseInt(t,10)||0;}return results;};jQuery.fn.extend({position:function(){var left=0,top=0,results;if(this[0]){var offsetParent=this.offsetParent(),offset=this.offset(),parentOffset=/^body|html$/i.test(offsetParent[0].tagName)?{top:0,left:0}:offsetParent.offset();offset.top-=num(this,'marginTop');offset.left-=num(this,'marginLeft');parentOffset.top+=num(offsetParent,'borderTopWidth');parentOffset.left+=num(offsetParent,'borderLeftWidth');results={top:offset.top-parentOffset.top,left:offset.left-parentOffset.left};}return results;},offsetParent:function(){var offsetParent=this[0].offsetParent;while(offsetParent&&(!/^body|html$/i.test(offsetParent.tagName)&&jQuery.css(offsetParent,'position')=='static'))offsetParent=offsetParent.offsetParent;return jQuery(offsetParent);}});jQuery.each(['Left','Top'],function(i,name){var method='scroll'+name;jQuery.fn[method]=function(val){if(!this[0])return;return val!=undefined?this.each(function(){this==window||this==document?window.scrollTo(!i?val:jQuery(window).scrollLeft(),i?val:jQuery(window).scrollTop()):this[method]=val;}):this[0]==window||this[0]==document?self[i?'pageYOffset':'pageXOffset']||jQuery.boxModel&&document.documentElement[method]||document.body[method]:this[0][method];};});jQuery.each(["Height","Width"],function(i,name){var tl=i?"Left":"Top",br=i?"Right":"Bottom";jQuery.fn["inner"+name]=function(){return this[name.toLowerCase()]()+num(this,"padding"+tl)+num(this,"padding"+br);};jQuery.fn["outer"+name]=function(margin){return this["inner"+name]()+num(this,"border"+tl+"Width")+num(this,"border"+br+"Width")+(margin?num(this,"margin"+tl)+num(this,"margin"+br):0);};});})(); \ No newline at end of file diff --git a/public/merb.fcgi b/public/merb.fcgi new file mode 100755 index 0000000..9804e0f --- /dev/null +++ b/public/merb.fcgi @@ -0,0 +1,22 @@ +#!/usr/bin/env ruby + +require 'rubygems' +require 'merb-core' + +# this is Merb.root, change this if you have some funky setup. +merb_root = File.expand_path(File.dirname(__FILE__) / '../') + +# If the fcgi process runs as apache, make sure +# we have an inlinedir set for Rubyinline action-args to work +unless ENV["INLINEDIR"] || ENV["HOME"] + tmpdir = merb_root / "tmp" + unless File.directory?(tmpdir) + Dir.mkdir(tmpdir) + end + ENV["INLINEDIR"] = tmpdir +end + +# start merb with the fcgi adapter, add options or change the log dir here +Merb.start(:adapter => 'fcgi', + :merb_root => merb_root, + :log_file => merb_root /'log'/'merb.log') \ No newline at end of file diff --git a/public/robots.txt b/public/robots.txt new file mode 100644 index 0000000..f85a11b --- /dev/null +++ b/public/robots.txt @@ -0,0 +1,5 @@ +# See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file +# +# To ban all spiders from the entire site uncomment the next two lines: +# User-Agent: * +# Disallow: / \ No newline at end of file diff --git a/public/stylesheets/master.css b/public/stylesheets/master.css new file mode 100644 index 0000000..5405991 --- /dev/null +++ b/public/stylesheets/master.css @@ -0,0 +1,206 @@ +body { + font-family: Arial, Verdana, sans-serif; + font-size: 12px; + background-color: #fff; + margin: 10px; } + +* { + margin: 0px; + padding: 0px; + text-decoration: none; } + +html { + height: 100%; + margin-bottom: 1px; } + +h1 { + margin-bottom: 20px; } + +#container { + width: 80%; + text-align: left; + background-color: #fff; + margin-right: auto; + margin-left: auto; } + +#header-container { + width: 100%; + padding-top: 15px; } + #header-container h1 h2 { + margin-left: 6px; + margin-bottom: 6px; } + +.spacer { + width: 100%; + height: 15px; } + +hr { + border: 0px; + color: #ccc; + background-color: #cdcdcd; + height: 1px; + width: 100%; + text-align: left; } + +h1 { + font-size: 28px; + color: #c55; + background-color: #fff; + font-family: Arial, Verdana, sans-serif; + font-weight: 300; } + +h2 { + font-size: 15px; + color: #ccc; + font-family: Arial, Verdana, sans-serif; + font-weight: 300; + background-color: #333; + padding: 5px; } + +h3 { + color: #4d9b12; + font-size: 15px; + text-align: left; + font-weight: 300; + padding: 5px; + margin-top: 5px; } + +h4 { + margin-top: 10px; + color: #333; + padding: 5px; + background-color: #fff; } + +#left-container { + float: left; + width: 250px; + background-color: #FFFFFF; + color: black; } + #left-container h3 { + color: #c55; } + +#main-container { + margin: 5px 5px 5px 260px; + padding: 15px; + border-left: 1px solid silver; + min-height: 400px; } + #main-container ul { + margin-left: 3.0em; } + +p { + color: #000; + line-height: 20px; + padding: 5px; } + +a { + color: #4d9b12; + background-color: #fff; + text-decoration: none; } + a:hover { + text-decoration: underline; } + +#footer-container { + clear: both; + font-size: 12px; + font-family: Verdana, Arial, sans-serif; } + +.right { + float: right; + font-size: 100%; + margin-top: 5px; + color: #999; + background-color: #fff; } + +.left { + float: left; + font-size: 100%; + margin-top: 5px; + color: #999; + background-color: #fff; } + +ul.method-list { + list-style-type: none; + margin-top: 5px; + margin-bottom: 20px; } + ul.method-list li { + padding-left: 20px; } + ul.method-list li.inherit { + background: url(/images/up.png) no-repeat 2px; } + +h3.from { + float: right; } + +div.desc { + margin: 0 20px 20px 20px; + padding: 10px; + background-color: #ccc; } + div.desc ul { + margin-left: 20px; } + div.desc table { + margin: 5px 0 5px 5px; } + div.desc pre { + padding: 5px; } + div.desc pre.source { + white-space: pre; + background-color: #111; + color: #fff; + display: none; } + +div.method-details { + overflow: hidden; + margin-right: 20px; } + div.method-details p.from { + float: right; } + div.method-details p.inherit { + padding-left: 20px; + background: url(/images/up.png) no-repeat 2px; } + +div.sidebar { + position: fixed; + height: 100%; + overflow: auto; + width: 200px; + top: 10px; + left: 10px; } + +div.main { + margin-left: 210px; + border-left: 1px solid #000; + padding-left: 10px; } + +.ruby-constant { + color: #7fffd4; + background: transparent; } + +.ruby-keyword { + color: #00ffff; + background: transparent; } + +.ruby-ivar { + color: #eedd82; + background: transparent; } + +.ruby-operator { + color: #00ffee; + background: transparent; } + +.ruby-identifier { + color: #ffdead; + background: transparent; } + +.ruby-node { + color: #ffa07a; + background: transparent; } + +.ruby-comment { + color: #999; + font-weight: bold; + background: transparent; } + +.ruby-regexp { + color: #ffa07a; + background: transparent; } + +.ruby-value { + color: #7fffd4; + background: transparent`; } diff --git a/public/stylesheets/master.old b/public/stylesheets/master.old new file mode 100644 index 0000000..b779652 --- /dev/null +++ b/public/stylesheets/master.old @@ -0,0 +1,185 @@ +body { + font-family: Arial, Verdana, sans-serif; + font-size: 12px; + background-color: #fff; + margin: 10px; +} +* { + margin: 0px; + padding: 0px; + text-decoration: none; +} +html { + height: 100%; + margin-bottom: 1px; +} + +h1 { + margin-bottom: 20px; +} + +#container { + width: 80%; + text-align: left; + background-color: #fff; + margin-right: auto; + margin-left: auto; +} +#header-container { + width: 100%; + padding-top: 15px; +} +#header-container h1, #header-container h2 { + margin-left: 6px; + margin-bottom: 6px; +} +.spacer { + width: 100%; + height: 15px; +} +hr { + border: 0px; + color: #ccc; + background-color: #cdcdcd; + height: 1px; + width: 100%; + text-align: left; +} +h1 { + font-size: 28px; + color: #c55; + background-color: #fff; + font-family: Arial, Verdana, sans-serif; + font-weight: 300; +} +h2 { + font-size: 15px; + color: #ccc; + font-family: Arial, Verdana, sans-serif; + font-weight: 300; + background-color: #333; + padding: 5px; +} +h3 { + color: #4d9b12; + font-size: 15px; + text-align: left; + font-weight: 300; + padding: 5px; + margin-top: 5px; +} + +h4 { + margin-top: 10px; + color: #333; + padding: 5px; + background-color: #fff; +} + +#left-container { + float: left; + width: 250px; + background-color: #FFFFFF; + color: black; +} + +#left-container h3 { + color: #c55; +} + +#main-container { + margin: 5px 5px 5px 260px; + padding: 15px; + border-left: 1px solid silver; + min-height: 400px; +} +p { + color: #000; + line-height: 20px; + padding: 5px; +} +a { + color: #4d9b12; + background-color: #fff; + text-decoration: none; +} +a:hover { + color: #4d9b12; + background-color: #fff; + text-decoration: underline; +} +#footer-container { + clear: both; + font-size: 12px; + font-family: Verdana, Arial, sans-serif; +} +.right { + float: right; + font-size: 100%; + margin-top: 5px; + color: #999; + background-color: #fff; +} +.left { + float: left; + font-size: 100%; + margin-top: 5px; + color: #999; + background-color: #fff; +} +#main-container ul { + margin-left: 3.0em; +} + +ul.method-list { + list-style-type: none; + margin-top: 5px; + margin-bottom: 20px; +} + +div.desc { + margin: 0 20px 20px 20px; + padding: 10px; + background-color: #ccc; +} + +h3.from { + float: right; +} + +div.method-details { + overflow: hidden; + margin-right: 20px; +} + +div.method-details p.from { + float: right; +} + +div.desc ul { + margin-left: 20px; +} + +div.desc table { + margin: 5px 0 5px 5px; +} + +div.desc pre { + padding: 5px; +} + +div.desc pre.source { + white-space: pre; + padding: 5px; + background-color: #555; +} + +.ruby-constant { color: #7fffd4; background: transparent; } +.ruby-keyword { color: #00ffff; background: transparent; } +.ruby-ivar { color: #eedd82; background: transparent; } +.ruby-operator { color: #00ffee; background: transparent; } +.ruby-identifier { color: #ffdead; background: transparent; } +.ruby-node { color: #ffa07a; background: transparent; } +.ruby-comment { color: #b22222; font-weight: bold; background: transparent; } +.ruby-regexp { color: #ffa07a; background: transparent; } +.ruby-value { color: #7fffd4; background: transparent; } diff --git a/public/stylesheets/sass/master.sass b/public/stylesheets/sass/master.sass new file mode 100644 index 0000000..9dbf970 --- /dev/null +++ b/public/stylesheets/sass/master.sass @@ -0,0 +1,200 @@ +body + font-family: Arial, Verdana, sans-serif + font-size: 12px + background-color: #fff + margin: 10px + +* + margin: 0px + padding: 0px + text-decoration: none + +html + height: 100% + margin-bottom: 1px + +h1 + margin-bottom: 20px + +#container + width: 80% + text-align: left + background-color: #fff + margin-right: auto + margin-left: auto + +#header-container + width: 100% + padding-top: 15px + h1 h2 + margin-left: 6px + margin-bottom: 6px + +.spacer + width: 100% + height: 15px + +hr + border: 0px + color: #ccc + background-color: #cdcdcd + height: 1px + width: 100% + text-align: left + +h1 + font-size: 28px + color: #c55 + background-color: #fff + font-family: Arial, Verdana, sans-serif + font-weight: 300 + +h2 + font-size: 15px + color: #ccc + font-family: Arial, Verdana, sans-serif + font-weight: 300 + background-color: #333 + padding: 5px + +h3 + color: #4d9b12 + font-size: 15px + text-align: left + font-weight: 300 + padding: 5px + margin-top: 5px + + +h4 + margin-top: 10px + color: #333 + padding: 5px + background-color: #fff + + +#left-container + float: left + width: 250px + background-color: #FFFFFF + color: black + h3 + color: #c55 + +#main-container + margin: 5px 5px 5px 260px + padding: 15px + border-left: 1px solid silver + min-height: 400px + ul + margin-left: 3.0em + +p + color: #000 + line-height: 20px + padding: 5px + +a + color: #4d9b12 + background-color: #fff + text-decoration: none + &:hover + text-decoration: underline + +#footer-container + clear: both + font-size: 12px + font-family: Verdana, Arial, sans-serif + +.right + float: right + font-size: 100% + margin-top: 5px + color: #999 + background-color: #fff + +.left + float: left + font-size: 100% + margin-top: 5px + color: #999 + background-color: #fff + +ul.method-list + list-style-type: none + margin-top: 5px + margin-bottom: 20px + li + padding-left: 20px + &.inherit + background: url(/images/up.png) no-repeat 2px + +h3.from + float: right + +div.desc + margin: 0 20px 20px 20px + padding: 10px + background-color: #ccc + ul + margin-left: 20px + table + margin: 5px 0 5px 5px + pre + padding: 5px + &.source + white-space: pre + background-color: #111 + color: #fff + display: none + +div.method-details + overflow: hidden + margin-right: 20px + p.from + float: right + p.inherit + padding-left: 20px + background: url(/images/up.png) no-repeat 2px + +div.sidebar + position: fixed + height: 100% + overflow: auto + width: 200px + top: 10px + left: 10px + +div.main + margin-left: 210px + border-left: 1px solid #000 + padding-left: 10px + +.ruby-constant + color: #7fffd4 + background: transparent +.ruby-keyword + color: #00ffff + background: transparent +.ruby-ivar + color: #eedd82 + background: transparent +.ruby-operator + color: #00ffee + background: transparent +.ruby-identifier + color: #ffdead + background: transparent +.ruby-node + color: #ffa07a + background: transparent +.ruby-comment + color: #999 + font-weight: bold + background: transparent +.ruby-regexp + color: #ffa07a + background: transparent +.ruby-value + color: #7fffd4 + background: transparent` diff --git a/spec/models/klass_spec.rb b/spec/models/klass_spec.rb new file mode 100644 index 0000000..22441a1 --- /dev/null +++ b/spec/models/klass_spec.rb @@ -0,0 +1,7 @@ +require File.join( File.dirname(__FILE__), '..', "spec_helper" ) + +describe Klass do + + it "should have specs" + +end \ No newline at end of file diff --git a/spec/models/method_spec.rb b/spec/models/method_spec.rb new file mode 100644 index 0000000..d6567de --- /dev/null +++ b/spec/models/method_spec.rb @@ -0,0 +1,7 @@ +require File.join( File.dirname(__FILE__), '..', "spec_helper" ) + +describe Method do + + it "should have specs" + +end \ No newline at end of file diff --git a/spec/requests/klass_spec.rb b/spec/requests/klass_spec.rb new file mode 100644 index 0000000..e7543e7 --- /dev/null +++ b/spec/requests/klass_spec.rb @@ -0,0 +1,7 @@ +require File.join(File.dirname(__FILE__), '..', 'spec_helper.rb') + +describe "/klass" do + before(:each) do + @response = request("/klass") + end +end \ No newline at end of file diff --git a/spec/spec.opts b/spec/spec.opts new file mode 100644 index 0000000..e69de29 diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 0000000..32c65b5 --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1,20 @@ +require "rubygems" + +# Add the local gems dir if found within the app root; any dependencies loaded +# hereafter will try to load from the local gems before loading system gems. +if (local_gem_dir = File.join(File.dirname(__FILE__), '..', 'gems')) && $BUNDLE.nil? + $BUNDLE = true; Gem.clear_paths; Gem.path.unshift(local_gem_dir) +end + +require "merb-core" +require "spec" # Satisfies Autotest and anyone else not using the Rake tasks + +# this loads all plugins required in your init file so don't add them +# here again, Merb will do it for you +Merb.start_environment(:testing => true, :adapter => 'runner', :environment => ENV['MERB_ENV'] || 'test') + +Spec::Runner.configure do |config| + config.include(Merb::Test::ViewHelper) + config.include(Merb::Test::RouteHelper) + config.include(Merb::Test::ControllerHelper) +end diff --git a/tasks/doc.thor b/tasks/doc.thor new file mode 100644 index 0000000..77e3222 --- /dev/null +++ b/tasks/doc.thor @@ -0,0 +1,149 @@ +$: << File.join("doc") +require 'rubygems' +require 'rdoc/rdoc' +require 'fileutils' +require 'erb' + +module Merb + + class GemNotFoundException < Exception + end + + module DocMethods + def setup_gem_path + if File.directory?(gems_dir = File.join(File.dirname(__FILE__), 'gems')) + $BUNDLE = true; Gem.clear_paths; Gem.path.unshift(gems_dir) + end + end + + def get_more + libs = [] + more_library = find_library("merb-more") + File.open("#{more_library}/lib/merb-more.rb").read.each_line do |line| + if line['require'] + libs << line.gsub("require '", '').gsub("'\n", '') + end + end + return libs + end + + def generate_documentation(file_list, destination, arguments = []) + output_dir = File.join("/../doc", "rdoc", destination) + FileUtils.rm_rf(output_dir) + + arguments += [ + "--fmt", "merb", + "--op", output_dir + ] + RDoc::RDoc.new.document(arguments + file_list) + AdvancedDoc.new.index + end + + def find_library(directory_snippet) + gem_dir = nil + Gem.path.find do |path| + dir = Dir.glob("#{path}/gems/#{directory_snippet}*") + dir.empty? ? false : gem_dir = dir.last + end + raise GemNotFoundException if gem_dir.nil? + return gem_dir + end + + def get_file_list(directory_snippet) + gem_dir = find_library(directory_snippet) + files = Dir.glob("#{gem_dir}/**/lib/**/*.rb") + files += ["#{gem_dir}/README"] if File.exists?("#{gem_dir}/README") + return files + end + end + + class AdvancedDoc < Thor + + group 'core' + include DocMethods + + def initialize + super + setup_gem_path + end + + desc 'index', "Regenerate the index file for your framework documentation" + def index + @directories = Dir.entries(File.join(File.dirname(__FILE__) + "/../", "doc", "rdoc")) + @directories.delete(".") + @directories.delete("..") + @directories.delete("generators") + @directories.delete("index.html") + index_template = File.read(File.join("doc", "rdoc", "generators", "template", "merb", "index.html.erb")) + + File.open(File.join("doc", "rdoc", "index.html"), "w") do |file| + file.write(ERB.new(index_template).result(binding)) + end + end + + desc 'plugins', 'Generate the rdoc for each merb-plugins seperatly' + def plugins + libs = ["merb_activerecord", "merb_builder", "merb_jquery", "merb_laszlo", "merb_parts", "merb_screw_unit", "merb_sequel", "merb_stories", "merb_test_unit"] + + libs.each do |lib| + options[:gem] = lib + gem + end + end + + desc 'more', 'Generate the rdoc for each merb-more gem seperatly' + def more + libs = get_more + libs.each do |lib| + options[:gem] = lib + gem + end + end + + desc 'core', 'Generate the rdoc for merb-core' + def core + options[:gem] = "merb-core" + gem + end + + desc 'gem', 'Generate the rdoc for a specific gem' + method_options "--gem" => :required + def gem + file_list = get_file_list(options[:gem]) + readme = File.join(find_library("merb-core"), "README") + generate_documentation(file_list, options[:gem], ["-m", readme]) + rescue GemNotFoundException + puts "Can not find the gem in the gem path #{options[:gem]}" + end + + end + + class Doc < Thor + + include DocMethods + + def initialize + super + setup_gem_path + + end + + desc 'stack', 'Generate the rdoc for merb-core, merb-more merged together' + def stack + libs = ["merb"] + + file_list = [] + libs.each do |gem_name| + begin + file_list += get_file_list(gem_name) + rescue GemNotFoundException + puts "Could not find #{gem_name} in #{Gem.path}. Continuing with out it." + end + end + readme = File.join(find_library("merb"), "README") + generate_documentation(file_list, "stack", ["-m", readme]) + end + + end + +end \ No newline at end of file diff --git a/tasks/merb.thor b/tasks/merb.thor new file mode 100644 index 0000000..6f7f60f --- /dev/null +++ b/tasks/merb.thor @@ -0,0 +1,2020 @@ +#!/usr/bin/env ruby +require 'rubygems' +require 'thor' +require 'fileutils' +require 'yaml' + +# Important - don't change this line or its position +MERB_THOR_VERSION = '0.2.1' + +############################################################################## + +module ColorfulMessages + + # red + def error(*messages) + puts messages.map { |msg| "\033[1;31m#{msg}\033[0m" } + end + + # yellow + def warning(*messages) + puts messages.map { |msg| "\033[1;33m#{msg}\033[0m" } + end + + # green + def success(*messages) + puts messages.map { |msg| "\033[1;32m#{msg}\033[0m" } + end + + alias_method :message, :success + + # magenta + def note(*messages) + puts messages.map { |msg| "\033[1;35m#{msg}\033[0m" } + end + + # blue + def info(*messages) + puts messages.map { |msg| "\033[1;34m#{msg}\033[0m" } + end + +end + +############################################################################## + +require 'rubygems/dependency_installer' +require 'rubygems/uninstaller' +require 'rubygems/dependency' + +module GemManagement + + include ColorfulMessages + + # Install a gem - looks remotely and local gem cache; + # won't process rdoc or ri options. + def install_gem(gem, options = {}) + refresh = options.delete(:refresh) || [] + from_cache = (options.key?(:cache) && options.delete(:cache)) + if from_cache + install_gem_from_cache(gem, options) + else + version = options.delete(:version) + Gem.configuration.update_sources = false + + # Limit source index to install dir + update_source_index(options[:install_dir]) if options[:install_dir] + + installer = Gem::DependencyInstaller.new(options.merge(:user_install => false)) + + # Force-refresh certain gems by excluding them from the current index + if !options[:ignore_dependencies] && refresh.respond_to?(:include?) && !refresh.empty? + source_index = installer.instance_variable_get(:@source_index) + source_index.gems.each do |name, spec| + source_index.gems.delete(name) if refresh.include?(spec.name) + end + end + + exception = nil + begin + installer.install gem, version + rescue Gem::InstallError => e + exception = e + rescue Gem::GemNotFoundException => e + if from_cache && gem_file = find_gem_in_cache(gem, version) + puts "Located #{gem} in gem cache..." + installer.install gem_file + else + exception = e + end + rescue => e + exception = e + end + if installer.installed_gems.empty? && exception + error "Failed to install gem '#{gem} (#{version || 'any version'})' (#{exception.message})" + end + ensure_bin_wrapper_for_installed_gems(installer.installed_gems, options) + installer.installed_gems.each do |spec| + success "Successfully installed #{spec.full_name}" + end + return !installer.installed_gems.empty? + end + end + + # Install a gem - looks in the system's gem cache instead of remotely; + # won't process rdoc or ri options. + def install_gem_from_cache(gem, options = {}) + version = options.delete(:version) + Gem.configuration.update_sources = false + installer = Gem::DependencyInstaller.new(options.merge(:user_install => false)) + exception = nil + begin + if gem_file = find_gem_in_cache(gem, version) + puts "Located #{gem} in gem cache..." + installer.install gem_file + else + raise Gem::InstallError, "Unknown gem #{gem}" + end + rescue Gem::InstallError => e + exception = e + end + if installer.installed_gems.empty? && exception + error "Failed to install gem '#{gem}' (#{e.message})" + end + ensure_bin_wrapper_for_installed_gems(installer.installed_gems, options) + installer.installed_gems.each do |spec| + success "Successfully installed #{spec.full_name}" + end + end + + # Install a gem from source - builds and packages it first then installs. + # + # Examples: + # install_gem_from_source(source_dir, :install_dir => ...) + # install_gem_from_source(source_dir, gem_name) + # install_gem_from_source(source_dir, :skip => [...]) + def install_gem_from_source(source_dir, *args) + installed_gems = [] + opts = args.last.is_a?(Hash) ? args.pop : {} + Dir.chdir(source_dir) do + gem_name = args[0] || File.basename(source_dir) + gem_pkg_dir = File.join(source_dir, 'pkg') + gem_pkg_glob = File.join(gem_pkg_dir, "#{gem_name}-*.gem") + skip_gems = opts.delete(:skip) || [] + + # Cleanup what's already there + clobber(source_dir) + FileUtils.mkdir_p(gem_pkg_dir) unless File.directory?(gem_pkg_dir) + + # Recursively process all gem packages within the source dir + skip_gems << gem_name + packages = package_all(source_dir, skip_gems) + + if packages.length == 1 + # The are no subpackages for the main package + refresh = [gem_name] + else + # Gather all packages into the top-level pkg directory + packages.each do |pkg| + FileUtils.copy_entry(pkg, File.join(gem_pkg_dir, File.basename(pkg))) + end + + # Finally package the main gem - without clobbering the already copied pkgs + package(source_dir, false) + + # Gather subgems to refresh during installation of the main gem + refresh = packages.map do |pkg| + File.basename(pkg, '.gem')[/^(.*?)-([\d\.]+)$/, 1] rescue nil + end.compact + + # Install subgems explicitly even if ignore_dependencies is set + if opts[:ignore_dependencies] + refresh.each do |name| + gem_pkg = Dir[File.join(gem_pkg_dir, "#{name}-*.gem")][0] + install_pkg(gem_pkg, opts) + end + end + end + + ensure_bin_wrapper_for(opts[:install_dir], opts[:bin_dir], *installed_gems) + + # Finally install the main gem + if install_pkg(Dir[gem_pkg_glob][0], opts.merge(:refresh => refresh)) + installed_gems = refresh + else + installed_gems = [] + end + end + installed_gems + end + + def install_pkg(gem_pkg, opts = {}) + if (gem_pkg && File.exists?(gem_pkg)) + # Needs to be executed from the directory that contains all packages + Dir.chdir(File.dirname(gem_pkg)) { install_gem(gem_pkg, opts) } + else + false + end + end + + # Uninstall a gem. + def uninstall_gem(gem, options = {}) + if options[:version] && !options[:version].is_a?(Gem::Requirement) + options[:version] = Gem::Requirement.new ["= #{options[:version]}"] + end + update_source_index(options[:install_dir]) if options[:install_dir] + Gem::Uninstaller.new(gem, options).uninstall rescue nil + end + + def clobber(source_dir) + Dir.chdir(source_dir) do + system "#{Gem.ruby} -S rake -s clobber" unless File.exists?('Thorfile') + end + end + + def package(source_dir, clobber = true) + Dir.chdir(source_dir) do + if File.exists?('Thorfile') + thor ":package" + elsif File.exists?('Rakefile') + rake "clobber" if clobber + rake "package" + end + end + Dir[File.join(source_dir, 'pkg/*.gem')] + end + + def package_all(source_dir, skip = [], packages = []) + if Dir[File.join(source_dir, '{Rakefile,Thorfile}')][0] + name = File.basename(source_dir) + Dir[File.join(source_dir, '*', '{Rakefile,Thorfile}')].each do |taskfile| + package_all(File.dirname(taskfile), skip, packages) + end + packages.push(*package(source_dir)) unless skip.include?(name) + end + packages.uniq + end + + def rake(cmd) + cmd << " >/dev/null" if $SILENT && !Gem.win_platform? + system "#{Gem.ruby} -S #{which('rake')} -s #{cmd} >/dev/null" + end + + def thor(cmd) + cmd << " >/dev/null" if $SILENT && !Gem.win_platform? + system "#{Gem.ruby} -S #{which('thor')} #{cmd}" + end + + # Use the local bin/* executables if available. + def which(executable) + if File.executable?(exec = File.join(Dir.pwd, 'bin', executable)) + exec + else + executable + end + end + + # Partition gems into system, local and missing gems + def partition_dependencies(dependencies, gem_dir) + system_specs, local_specs, missing_deps = [], [], [] + if gem_dir && File.directory?(gem_dir) + gem_dir = File.expand_path(gem_dir) + ::Gem.clear_paths; ::Gem.path.unshift(gem_dir) + ::Gem.source_index.refresh! + dependencies.each do |dep| + gemspecs = ::Gem.source_index.search(dep) + local = gemspecs.reverse.find { |s| s.loaded_from.index(gem_dir) == 0 } + if local + local_specs << local + elsif gemspecs.last + system_specs << gemspecs.last + else + missing_deps << dep + end + end + ::Gem.clear_paths + else + dependencies.each do |dep| + gemspecs = ::Gem.source_index.search(dep) + if gemspecs.last + system_specs << gemspecs.last + else + missing_deps << dep + end + end + end + [system_specs, local_specs, missing_deps] + end + + # Create a modified executable wrapper in the specified bin directory. + def ensure_bin_wrapper_for(gem_dir, bin_dir, *gems) + options = gems.last.is_a?(Hash) ? gems.last : {} + options[:no_minigems] ||= [] + if bin_dir && File.directory?(bin_dir) + gems.each do |gem| + if gemspec_path = Dir[File.join(gem_dir, 'specifications', "#{gem}-*.gemspec")].last + spec = Gem::Specification.load(gemspec_path) + enable_minigems = !options[:no_minigems].include?(spec.name) + spec.executables.each do |exec| + executable = File.join(bin_dir, exec) + message "Writing executable wrapper #{executable}" + File.open(executable, 'w', 0755) do |f| + f.write(executable_wrapper(spec, exec, enable_minigems)) + end + end + end + end + end + end + + def ensure_bin_wrapper_for_installed_gems(gemspecs, options) + if options[:install_dir] && options[:bin_dir] + gems = gemspecs.map { |spec| spec.name } + ensure_bin_wrapper_for(options[:install_dir], options[:bin_dir], *gems) + end + end + + private + + def executable_wrapper(spec, bin_file_name, minigems = true) + requirements = ['minigems', 'rubygems'] + requirements.reverse! unless minigems + try_req, then_req = requirements + <<-TEXT +#!/usr/bin/env ruby +# +# This file was generated by Merb's GemManagement +# +# The application '#{spec.name}' is installed as part of a gem, and +# this file is here to facilitate running it. + +begin + require '#{try_req}' +rescue LoadError + require '#{then_req}' +end + +# use gems dir if ../gems exists - eg. only for ./bin/#{bin_file_name} +if File.directory?(gems_dir = File.join(File.dirname(__FILE__), '..', 'gems')) + $BUNDLE = true; Gem.clear_paths; Gem.path.replace([File.expand_path(gems_dir)]) + ENV["PATH"] = "\#{File.dirname(__FILE__)}:\#{gems_dir}/bin:\#{ENV["PATH"]}" + if (local_gem = Dir[File.join(gems_dir, "specifications", "#{spec.name}-*.gemspec")].last) + version = File.basename(local_gem)[/-([\\.\\d]+)\\.gemspec$/, 1] + end +end + +version ||= "#{Gem::Requirement.default}" + +if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then + version = $1 + ARGV.shift +end + +gem '#{spec.name}', version +load '#{bin_file_name}' +TEXT + end + + def find_gem_in_cache(gem, version) + spec = if version + version = Gem::Requirement.new ["= #{version}"] unless version.is_a?(Gem::Requirement) + Gem.source_index.find_name(gem, version).first + else + Gem.source_index.find_name(gem).sort_by { |g| g.version }.last + end + if spec && File.exists?(gem_file = "#{spec.installation_path}/cache/#{spec.full_name}.gem") + gem_file + end + end + + def update_source_index(dir) + Gem.source_index.load_gems_in(File.join(dir, 'specifications')) + end + +end + +############################################################################## + +class SourceManager + + include ColorfulMessages + + attr_accessor :source_dir + + def initialize(source_dir) + self.source_dir = source_dir + end + + def clone(name, url) + FileUtils.cd(source_dir) do + raise "destination directory already exists" if File.directory?(name) + system("git clone --depth 1 #{url} #{name}") + end + rescue => e + error "Unable to clone #{name} repository (#{e.message})" + end + + def update(name, url) + if File.directory?(repository_dir = File.join(source_dir, name)) + FileUtils.cd(repository_dir) do + repos = existing_repos(name) + fork_name = url[/.com\/+?(.+)\/.+\.git/u, 1] + if url == repos["origin"] + # Pull from the original repository - no branching needed + info "Pulling from origin: #{url}" + system "git fetch; git checkout master; git rebase origin/master" + elsif repos.values.include?(url) && fork_name + # Update and switch to a remote branch for a particular github fork + info "Switching to remote branch: #{fork_name}" + system "git checkout -b #{fork_name} #{fork_name}/master" + system "git rebase #{fork_name}/master" + elsif fork_name + # Create a new remote branch for a particular github fork + info "Adding a new remote branch: #{fork_name}" + system "git remote add -f #{fork_name} #{url}" + system "git checkout -b #{fork_name} #{fork_name}/master" + else + warning "No valid repository found for: #{name}" + end + end + return true + else + warning "No valid repository found at: #{repository_dir}" + end + rescue => e + error "Unable to update #{name} repository (#{e.message})" + return false + end + + def existing_repos(name) + repos = [] + FileUtils.cd(File.join(source_dir, name)) do + repos = %x[git remote -v].split("\n").map { |branch| branch.split(/\s+/) } + end + Hash[*repos.flatten] + end + +end + +############################################################################## + +module MerbThorHelper + + attr_accessor :force_gem_dir + + def self.included(base) + base.send(:include, ColorfulMessages) + base.extend ColorfulMessages + end + + def use_edge_gem_server + ::Gem.sources << 'http://edge.merbivore.com' + end + + def source_manager + @_source_manager ||= SourceManager.new(source_dir) + end + + def extract_repositories(names) + repos = [] + names.each do |name| + if repo_url = Merb::Source.repo(name, options[:sources]) + # A repository entry for this dependency exists + repo = [name, repo_url] + repos << repo unless repos.include?(repo) + elsif (repo_name = Merb::Stack.lookup_repository_name(name)) && + (repo_url = Merb::Source.repo(repo_name, options[:sources])) + # A parent repository entry for this dependency exists + repo = [repo_name, repo_url] + unless repos.include?(repo) + puts "Found #{repo_name}/#{name} at #{repo_url}" + repos << repo + end + end + end + repos + end + + def update_dependency_repositories(dependencies) + repos = extract_repositories(dependencies.map { |d| d.name }) + update_repositories(repos) + end + + def update_repositories(repos) + repos.each do |(name, url)| + if File.directory?(repository_dir = File.join(source_dir, name)) + message "Updating or branching #{name}..." + source_manager.update(name, url) + else + message "Cloning #{name} repository from #{url}..." + source_manager.clone(name, url) + end + end + end + + def install_dependency(dependency, opts = {}) + version = dependency.version_requirements.to_s + install_opts = default_install_options.merge(:version => version) + Merb::Gem.install(dependency.name, install_opts.merge(opts)) + end + + def install_dependency_from_source(dependency, opts = {}) + matches = Dir[File.join(source_dir, "**", dependency.name, "{Rakefile,Thorfile}")] + matches.reject! { |m| File.basename(m) == 'Thorfile' } + if matches.length == 1 && matches[0] + if File.directory?(gem_src_dir = File.dirname(matches[0])) + begin + Merb::Gem.install_gem_from_source(gem_src_dir, default_install_options.merge(opts)) + puts "Installed #{dependency.name}" + return true + rescue => e + warning "Unable to install #{dependency.name} from source (#{e.message})" + end + else + msg = "Unknown directory: #{gem_src_dir}" + warning "Unable to install #{dependency.name} from source (#{msg})" + end + elsif matches.length > 1 + error "Ambigous source(s) for dependency: #{dependency.name}" + matches.each { |m| puts "- #{m}" } + end + return false + end + + def clobber_dependencies! + if options[:force] && gem_dir && File.directory?(gem_dir) + # Remove all existing local gems by clearing the gems directory + if dry_run? + note 'Clearing existing local gems...' + else + message 'Clearing existing local gems...' + FileUtils.rm_rf(gem_dir) && FileUtils.mkdir_p(default_gem_dir) + end + elsif !local.empty? + # Uninstall all local versions of the gems to install + if dry_run? + note 'Uninstalling existing local gems:' + local.each { |gemspec| note "Uninstalled #{gemspec.name}" } + else + message 'Uninstalling existing local gems:' if local.size > 1 + local.each do |gemspec| + Merb::Gem.uninstall(gemspec.name, default_uninstall_options) + end + end + end + end + + def display_gemspecs(gemspecs) + if gemspecs.empty? + puts "- none" + else + gemspecs.each do |spec| + if hint = Dir[File.join(spec.full_gem_path, '*.strategy')][0] + strategy = File.basename(hint, '.strategy') + puts "- #{spec.full_name} (#{strategy})" + else + puts "~ #{spec.full_name}" # unknown strategy + end + end + end + end + + def display_dependencies(dependencies) + if dependencies.empty? + puts "- none" + else + dependencies.each { |d| puts "- #{d.name} (#{d.version_requirements})" } + end + end + + def default_install_options + { :install_dir => gem_dir, :bin_dir => bin_dir, :ignore_dependencies => ignore_dependencies? } + end + + def default_uninstall_options + { :install_dir => gem_dir, :bin_dir => bin_dir, :ignore => true, :all => true, :executables => true } + end + + def dry_run? + options[:"dry-run"] + end + + def ignore_dependencies? + options[:"ignore-dependencies"] + end + + # The current working directory, or Merb app root (--merb-root option). + def working_dir + @_working_dir ||= File.expand_path(options['merb-root'] || Dir.pwd) + end + + # We should have a ./src dir for local and system-wide management. + def source_dir + @_source_dir ||= File.join(working_dir, 'src') + create_if_missing(@_source_dir) + @_source_dir + end + + # If a local ./gems dir is found, return it. + def gem_dir + return force_gem_dir if force_gem_dir + if File.directory?(dir = default_gem_dir) + dir + end + end + + def default_gem_dir + File.join(working_dir, 'gems') + end + + # If we're in a Merb app, we can have a ./bin directory; + # create it if it's not there. + def bin_dir + @_bin_dir ||= begin + if gem_dir + dir = File.join(working_dir, 'bin') + create_if_missing(dir) + dir + end + end + end + + # Helper to create dir unless it exists. + def create_if_missing(path) + FileUtils.mkdir(path) unless File.exists?(path) + end + + def sudo + ENV['THOR_SUDO'] ||= "sudo" + sudo = Gem.win_platform? ? "" : ENV['THOR_SUDO'] + end + + def local_gemspecs(directory = gem_dir) + if File.directory?(specs_dir = File.join(directory, 'specifications')) + Dir[File.join(specs_dir, '*.gemspec')].map do |gemspec_path| + gemspec = Gem::Specification.load(gemspec_path) + gemspec.loaded_from = gemspec_path + gemspec + end + else + [] + end + end + +end + +############################################################################## + +$SILENT = true # don't output all the mess some rake package tasks spit out + +module Merb + + class Gem < Thor + + include MerbThorHelper + extend GemManagement + + attr_accessor :system, :local, :missing + + global_method_options = { + "--merb-root" => :optional, # the directory to operate on + "--version" => :optional, # gather specific version of gem + "--ignore-dependencies" => :boolean # don't install sub-dependencies + } + + method_options global_method_options + def initialize(*args); super; end + + # List gems that match the specified criteria. + # + # By default all local gems are listed. When the first argument is 'all' the + # list is partitioned into system an local gems; specify 'system' to show + # only system gems. A second argument can be used to filter on a set of known + # components, like all merb-more gems for example. + # + # Examples: + # + # merb:gem:list # list all local gems - the default + # merb:gem:list all # list system and local gems + # merb:gem:list system # list only system gems + # merb:gem:list all merb-more # list only merb-more related gems + # merb:gem:list --version 0.9.8 # list gems that match the version + + desc 'list [all|local|system] [comp]', 'Show installed gems' + def list(filter = 'local', comp = nil) + deps = comp ? Merb::Stack.select_component_dependencies(dependencies, comp) : dependencies + self.system, self.local, self.missing = Merb::Gem.partition_dependencies(deps, gem_dir) + case filter + when 'all' + message 'Installed system gems:' + display_gemspecs(system) + message 'Installed local gems:' + display_gemspecs(local) + when 'system' + message 'Installed system gems:' + display_gemspecs(system) + when 'local' + message 'Installed local gems:' + display_gemspecs(local) + else + warning "Invalid listing filter '#{filter}'" + end + end + + # Install the specified gems. + # + # All arguments should be names of gems to install. + # + # When :force => true then any existing versions of the gems to be installed + # will be uninstalled first. It's important to note that so-called meta-gems + # or gems that exactly match a set of Merb::Stack.components will have their + # sub-gems uninstalled too. For example, uninstalling merb-more will install + # all contained gems: merb-action-args, merb-assets, merb-gen, ... + # + # Examples: + # + # merb:gem:install merb-core merb-slices # install all specified gems + # merb:gem:install merb-core --version 0.9.8 # install a specific version of a gem + # merb:gem:install merb-core --force # uninstall then subsequently install the gem + # merb:gem:install merb-core --cache # try to install locally from system gems + # merb:gem:install merb --merb-edge # install from edge.merbivore.com + + desc 'install GEM_NAME [GEM_NAME, ...]', 'Install a gem from rubygems' + method_options "--cache" => :boolean, + "--dry-run" => :boolean, + "--force" => :boolean, + "--merb-edge" => :boolean + def install(*names) + opts = { :version => options[:version], :cache => options[:cache] } + use_edge_gem_server if options[:"merb-edge"] + current_gem = nil + + # uninstall existing gems of the ones we're going to install + uninstall(*names) if options[:force] + + message "Installing #{names.length} #{names.length == 1 ? 'gem' : 'gems'}..." + puts "This may take a while..." + + names.each do |gem_name| + current_gem = gem_name + if dry_run? + note "Installing #{current_gem}..." + else + message "Installing #{current_gem}..." + self.class.install(gem_name, default_install_options.merge(opts)) + end + end + rescue => e + error "Failed to install #{current_gem ? current_gem : 'gem'} (#{e.message})" + end + + # Uninstall the specified gems. + # + # By default all specified gems are uninstalled. It's important to note that + # so-called meta-gems or gems that match a set of Merb::Stack.components will + # have their sub-gems uninstalled too. For example, uninstalling merb-more + # will install all contained gems: merb-action-args, merb-assets, ... + # + # Existing dependencies will be clobbered; when :force => true then all gems + # will be cleared, otherwise only existing local dependencies of the + # matching component set will be removed. + # + # Examples: + # + # merb:gem:uninstall merb-core merb-slices # uninstall all specified gems + # merb:gem:uninstall merb-core --version 0.9.8 # uninstall a specific version of a gem + + desc 'uninstall GEM_NAME [GEM_NAME, ...]', 'Unstall a gem' + method_options "--dry-run" => :boolean + def uninstall(*names) + opts = { :version => options[:version] } + current_gem = nil + if dry_run? + note "Uninstalling any existing gems of: #{names.join(', ')}" + else + message "Uninstalling any existing gems of: #{names.join(', ')}" + names.each do |gem_name| + current_gem = gem_name + Merb::Gem.uninstall(gem_name, default_uninstall_options) rescue nil + # if this gem is a meta-gem or a component set name, remove sub-gems + (Merb::Stack.components(gem_name) || []).each do |comp| + Merb::Gem.uninstall(comp, default_uninstall_options) rescue nil + end + end + end + rescue => e + error "Failed to uninstall #{current_gem ? current_gem : 'gem'} (#{e.message})" + end + + # Recreate all gems from gems/cache on the current platform. + # + # This task should be executed as part of a deployment setup, where the + # deployment system runs this after the app has been installed. + # Usually triggered by Capistrano, God... + # + # It will regenerate gems from the bundled gems cache for any gem that has + # C extensions - which need to be recompiled for the target deployment platform. + # + # Note: at least gems/cache and gems/specifications should be in your SCM. + + desc 'redeploy', 'Recreate all gems on the current platform' + method_options "--dry-run" => :boolean, "--force" => :boolean + def redeploy + require 'tempfile' # for Dir::tmpdir access + if gem_dir && File.directory?(cache_dir = File.join(gem_dir, 'cache')) + specs = local_gemspecs + message "Recreating #{specs.length} gems from cache..." + puts "This may take a while..." + specs.each do |gemspec| + if File.exists?(gem_file = File.join(cache_dir, "#{gemspec.full_name}.gem")) + gem_file_copy = File.join(Dir::tmpdir, File.basename(gem_file)) + if dry_run? + note "Recreating #{gemspec.full_name}" + else + message "Recreating #{gemspec.full_name}" + if options[:force] && File.directory?(gem = File.join(gem_dir, 'gems', gemspec.full_name)) + puts "Removing existing #{gemspec.full_name}" + FileUtils.rm_rf(gem) + end + # Copy the gem to a temporary file, because otherwise RubyGems/FileUtils + # will complain about copying identical files (same source/destination). + FileUtils.cp(gem_file, gem_file_copy) + Merb::Gem.install(gem_file_copy, :install_dir => gem_dir, :ignore_dependencies => true) + File.delete(gem_file_copy) + end + end + end + else + error "No application local gems directory found" + end + end + + private + + # Return dependencies for all installed gems; both system-wide and locally; + # optionally filters on :version requirement. + def dependencies + version_req = if options[:version] + ::Gem::Requirement.create(options[:version]) + else + ::Gem::Requirement.default + end + if gem_dir + ::Gem.clear_paths; ::Gem.path.unshift(gem_dir) + ::Gem.source_index.refresh! + end + deps = [] + ::Gem.source_index.each do |fullname, gemspec| + if version_req.satisfied_by?(gemspec.version) + deps << ::Gem::Dependency.new(gemspec.name, "= #{gemspec.version}") + end + end + ::Gem.clear_paths if gem_dir + deps.sort + end + + public + + # Install gem with some default options. + def self.install(name, options = {}) + defaults = {} + defaults[:cache] = false unless opts[:install_dir] + install_gem(name, defaults.merge(options)) + end + + # Uninstall gem with some default options. + def self.uninstall(name, options = {}) + defaults = { :ignore => true, :executables => true } + uninstall_gem(name, defaults.merge(options)) + end + + end + + class Tasks < Thor + + include MerbThorHelper + + # Show merb.thor version information + # + # merb:tasks:version # show the current version info + # merb:tasks:version --info # show extended version info + + desc 'version', 'Show verion info' + method_options "--info" => :boolean + def version + message "Currently installed merb.thor version: #{MERB_THOR_VERSION}" + if options[:version] + self.options = { :"dry-run" => true } + self.update # run update task with dry-run enabled + end + end + + # Update merb.thor tasks from remotely available version + # + # merb:tasks:update # update merb.thor + # merb:tasks:update --force # force-update merb.thor + # merb:tasks:update --dry-run # show version info only + + desc 'update [URL]', 'Fetch the latest merb.thor and install it locally' + method_options "--dry-run" => :boolean, "--force" => :boolean + def update(url = 'http://merbivore.com/merb.thor') + require 'open-uri' + require 'rubygems/version' + remote_file = open(url) + code = remote_file.read + + # Extract version information from the source code + if version = code[/^MERB_THOR_VERSION\s?=\s?('|")([\.\d]+)('|")/,2] + # borrow version comparison from rubygems' Version class + current_version = ::Gem::Version.new(MERB_THOR_VERSION) + remote_version = ::Gem::Version.new(version) + + if current_version >= remote_version + puts "currently installed: #{current_version}" + if current_version != remote_version + puts "available version: #{remote_version}" + end + info "No update of merb.thor necessary#{options[:force] ? ' (forced)' : ''}" + proceed = options[:force] + elsif current_version < remote_version + puts "currently installed: #{current_version}" + puts "available version: #{remote_version}" + proceed = true + end + + if proceed && !dry_run? + File.open(File.join(__FILE__), 'w') do |f| + f.write(code) + end + success "Installed the latest merb.thor (v#{version})" + end + else + raise "invalid source-code data" + end + rescue OpenURI::HTTPError + error "Error opening #{url}" + rescue => e + error "An error occurred (#{e.message})" + end + + end + + #### MORE LOW-LEVEL TASKS #### + + class Source < Thor + + group 'core' + + include MerbThorHelper + extend GemManagement + + attr_accessor :system, :local, :missing + + global_method_options = { + "--merb-root" => :optional, # the directory to operate on + "--ignore-dependencies" => :boolean, # don't install sub-dependencies + "--sources" => :optional # a yml config to grab sources from + } + + method_options global_method_options + def initialize(*args); super; end + + # List source repositories, of either local or known sources. + # + # Examples: + # + # merb:source:list # list all local sources + # merb:source:list available # list all known sources + + desc 'list [local|available]', 'Show git source repositories' + def list(mode = 'local') + if mode == 'available' + message 'Available source repositories:' + repos = self.class.repos(options[:sources]) + repos.keys.sort.each { |name| puts "- #{name}: #{repos[name]}" } + elsif mode == 'local' + message 'Current source repositories:' + Dir[File.join(source_dir, '*')].each do |src| + next unless File.directory?(src) + src_name = File.basename(src) + unless (repos = source_manager.existing_repos(src_name)).empty? + puts "#{src_name}" + repos.keys.sort.each { |b| puts "- #{b}: #{repos[b]}" } + end + end + else + error "Unknown listing: #{mode}" + end + end + + # Install the specified gems. + # + # All arguments should be names of gems to install. + # + # When :force => true then any existing versions of the gems to be installed + # will be uninstalled first. It's important to note that so-called meta-gems + # or gems that exactly match a set of Merb::Stack.components will have their + # sub-gems uninstalled too. For example, uninstalling merb-more will install + # all contained gems: merb-action-args, merb-assets, merb-gen, ... + # + # Examples: + # + # merb:source:install merb-core merb-slices # install all specified gems + # merb:source:install merb-core --force # uninstall then subsequently install the gem + # merb:source:install merb-core --wipe # clear repo then install the gem + + desc 'install GEM_NAME [GEM_NAME, ...]', 'Install a gem from git source/edge' + method_options "--dry-run" => :boolean, + "--force" => :boolean, + "--wipe" => :boolean + def install(*names) + use_edge_gem_server + # uninstall existing gems of the ones we're going to install + uninstall(*names) if options[:force] || options[:wipe] + + # We want dependencies instead of just names + deps = names.map { |n| ::Gem::Dependency.new(n, ::Gem::Requirement.default) } + + # Selectively update repositories for the matching dependencies + update_dependency_repositories(deps) unless dry_run? + + current_gem = nil + deps.each do |dependency| + current_gem = dependency.name + if dry_run? + note "Installing #{current_gem} from source..." + else + message "Installing #{current_gem} from source..." + puts "This may take a while..." + unless install_dependency_from_source(dependency) + raise "gem source not found" + end + end + end + rescue => e + error "Failed to install #{current_gem ? current_gem : 'gem'} (#{e.message})" + end + + # Uninstall the specified gems. + # + # By default all specified gems are uninstalled. It's important to note that + # so-called meta-gems or gems that match a set of Merb::Stack.components will + # have their sub-gems uninstalled too. For example, uninstalling merb-more + # will install all contained gems: merb-action-args, merb-assets, ... + # + # Existing dependencies will be clobbered; when :force => true then all gems + # will be cleared, otherwise only existing local dependencies of the + # matching component set will be removed. Additionally when :wipe => true, + # the matching git repositories will be removed from the source directory. + # + # Examples: + # + # merb:source:uninstall merb-core merb-slices # uninstall all specified gems + # merb:source:uninstall merb-core --wipe # force-uninstall a gem and clear repo + + desc 'uninstall GEM_NAME [GEM_NAME, ...]', 'Unstall a gem (specify --force to remove the repo)' + method_options "--version" => :optional, "--dry-run" => :boolean, "--wipe" => :boolean + def uninstall(*names) + # Remove the repos that contain the gem + if options[:wipe] + extract_repositories(names).each do |(name, url)| + if File.directory?(src = File.join(source_dir, name)) + if dry_run? + note "Removing #{src}..." + else + info "Removing #{src}..." + FileUtils.rm_rf(src) + end + end + end + end + + # Use the Merb::Gem#uninstall task to handle this + gem_tasks = Merb::Gem.new + gem_tasks.options = options + gem_tasks.uninstall(*names) + end + + # Update the specified source repositories. + # + # The arguments can be actual repository names (from Merb::Source.repos) + # or names of known merb stack gems. If the repo doesn't exist already, + # it will be created and cloned. + # + # merb:source:pull merb-core # update source of specified gem + # merb:source:pull merb-slices # implicitly updates merb-more + + desc 'pull REPO_NAME [GEM_NAME, ...]', 'Update git source repository from edge' + def pull(*names) + repos = extract_repositories(names) + update_repositories(repos) + unless repos.empty? + message "Updated the following repositories:" + repos.each { |name, url| puts "- #{name}: #{url}" } + else + warning "No repositories found to update!" + end + end + + # Clone a git repository into ./src. + + # The repository can be a direct git url or a known -named- repository. + # + # Examples: + # + # merb:source:clone merb-core + # merb:source:clone dm-core awesome-repo + # merb:source:clone dm-core --sources ./path/to/sources.yml + # merb:source:clone git://github.com/sam/dm-core.git + + desc 'clone (REPO_NAME|URL) [DIR_NAME]', 'Clone git source repository by name or url' + def clone(repository, name = nil) + if repository =~ /^git:\/\// + repository_url = repository + repository_name = File.basename(repository_url, '.git') + elsif url = Merb::Source.repo(repository, options[:sources]) + repository_url = url + repository_name = repository + end + source_manager.clone(name || repository_name, repository_url) + end + + # Git repository sources - pass source_config option to load a yaml + # configuration file - defaults to ./config/git-sources.yml and + # ~/.merb/git-sources.yml - which you need to create yourself. + # + # Example of contents: + # + # merb-core: git://github.com/myfork/merb-core.git + # merb-more: git://github.com/myfork/merb-more.git + + def self.repos(source_config = nil) + source_config ||= begin + local_config = File.join(Dir.pwd, 'config', 'git-sources.yml') + user_config = File.join(ENV["HOME"] || ENV["APPDATA"], '.merb', 'git-sources.yml') + File.exists?(local_config) ? local_config : user_config + end + if source_config && File.exists?(source_config) + default_repos.merge(YAML.load(File.read(source_config))) + else + default_repos + end + end + + def self.repo(name, source_config = nil) + self.repos(source_config)[name] + end + + # Default Git repositories + def self.default_repos + @_default_repos ||= { + 'merb' => "git://github.com/wycats/merb.git", + 'merb-plugins' => "git://github.com/wycats/merb-plugins.git", + 'extlib' => "git://github.com/sam/extlib.git", + 'dm-core' => "git://github.com/sam/dm-core.git", + 'dm-more' => "git://github.com/sam/dm-more.git", + 'sequel' => "git://github.com/wayneeseguin/sequel.git", + 'do' => "git://github.com/sam/do.git", + 'thor' => "git://github.com/wycats/thor.git", + 'rake' => "git://github.com/jimweirich/rake.git" + } + end + + end + + class Dependencies < Thor + + group 'core' + + # The Dependencies tasks will install dependencies based on actual application + # dependencies. For this, the application is queried for any dependencies. + # All operations will be performed within this context. + + attr_accessor :system, :local, :missing, :extract_dependencies + + include MerbThorHelper + + global_method_options = { + "--merb-root" => :optional, # the directory to operate on + "--ignore-dependencies" => :boolean, # ignore sub-dependencies + "--stack" => :boolean, # gather only stack dependencies + "--no-stack" => :boolean, # gather only non-stack dependencies + "--extract" => :boolean, # gather dependencies from the app itself + "--config-file" => :optional, # gather from the specified yaml config + "--version" => :optional # gather specific version of framework + } + + method_options global_method_options + def initialize(*args); super; end + + # List application dependencies. + # + # By default all dependencies are listed, partitioned into system, local and + # currently missing dependencies. The first argument allows you to filter + # on any of the partitionings. A second argument can be used to filter on + # a set of known components, like all merb-more gems for example. + # + # Examples: + # + # merb:dependencies:list # list all dependencies - the default + # merb:dependencies:list local # list only local gems + # merb:dependencies:list all merb-more # list only merb-more related dependencies + # merb:dependencies:list --stack # list framework dependencies + # merb:dependencies:list --no-stack # list 3rd party dependencies + # merb:dependencies:list --extract # list dependencies by extracting them + # merb:dependencies:list --config-file file.yml # list from the specified config file + + desc 'list [all|local|system|missing] [comp]', 'Show application dependencies' + def list(filter = 'all', comp = nil) + deps = comp ? Merb::Stack.select_component_dependencies(dependencies, comp) : dependencies + self.system, self.local, self.missing = Merb::Gem.partition_dependencies(deps, gem_dir) + case filter + when 'all' + message 'Installed system gem dependencies:' + display_gemspecs(system) + message 'Installed local gem dependencies:' + display_gemspecs(local) + unless missing.empty? + error 'Missing gem dependencies:' + display_dependencies(missing) + end + when 'system' + message 'Installed system gem dependencies:' + display_gemspecs(system) + when 'local' + message 'Installed local gem dependencies:' + display_gemspecs(local) + when 'missing' + error 'Missing gem dependencies:' + display_dependencies(missing) + else + warning "Invalid listing filter '#{filter}'" + end + if missing.size > 0 + info "Some dependencies are currently missing!" + elsif local.size == deps.size + info "All dependencies have been bundled with the application." + elsif local.size > system.size + info "Most dependencies have been bundled with the application." + elsif system.size > 0 && local.size > 0 + info "Some dependencies have been bundled with the application." + elsif local.empty? && system.size == deps.size + info "All dependencies are available on the system." + end + end + + # Install application dependencies. + # + # By default all required dependencies are installed. The first argument + # specifies which strategy to use: stable or edge. A second argument can be + # used to filter on a set of known components. + # + # Existing dependencies will be clobbered; when :force => true then all gems + # will be cleared first, otherwise only existing local dependencies of the + # gems to be installed will be removed. + # + # Examples: + # + # merb:dependencies:install # install all dependencies using stable strategy + # merb:dependencies:install stable --version 0.9.8 # install a specific version of the framework + # merb:dependencies:install stable missing # install currently missing gems locally + # merb:dependencies:install stable merb-more # install only merb-more related dependencies + # merb:dependencies:install stable --stack # install framework dependencies + # merb:dependencies:install stable --no-stack # install 3rd party dependencies + # merb:dependencies:install stable --extract # extract dependencies from the actual app + # merb:dependencies:install stable --config-file file.yml # read from the specified config file + # + # In addition to the options above, edge install uses the following: + # + # merb:dependencies:install edge # install all dependencies using edge strategy + # merb:dependencies:install edge --sources file.yml # install edge from the specified git sources config + + desc 'install [stable|edge] [comp]', 'Install application dependencies' + method_options "--sources" => :optional, # only for edge strategy + "--local" => :boolean, # force local install + "--dry-run" => :boolean, + "--force" => :boolean + def install(strategy = 'stable', comp = nil) + if strategy?(strategy) + # Force local dependencies by creating ./gems before proceeding + create_if_missing(default_gem_dir) if options[:local] + + where = gem_dir ? 'locally' : 'system-wide' + + # When comp == 'missing' then filter on missing dependencies + if only_missing = comp == 'missing' + message "Preparing to install missing gems #{where} using #{strategy} strategy..." + comp = nil + clobber = false + else + message "Preparing to install #{where} using #{strategy} strategy..." + clobber = true + end + + # If comp given, filter on known stack components + deps = comp ? Merb::Stack.select_component_dependencies(dependencies, comp) : dependencies + self.system, self.local, self.missing = Merb::Gem.partition_dependencies(deps, gem_dir) + + # Only install currently missing gems (for comp == missing) + if only_missing + deps.reject! { |dep| not missing.include?(dep) } + end + + if deps.empty? + warning "No dependencies to install..." + else + puts "#{deps.length} dependencies to install..." + puts "This may take a while..." + install_dependencies(strategy, deps, clobber) + end + + # Show current dependency info now that we're done + puts # Seperate output + list('local', comp) + else + warning "Invalid install strategy '#{strategy}'" + puts + message "Please choose one of the following installation strategies: stable or edge:" + puts "$ thor merb:dependencies:install stable" + puts "$ thor merb:dependencies:install edge" + end + end + + # Uninstall application dependencies. + # + # By default all required dependencies are installed. An optional argument + # can be used to filter on a set of known components. + # + # Existing dependencies will be clobbered; when :force => true then all gems + # will be cleared, otherwise only existing local dependencies of the + # matching component set will be removed. + # + # Examples: + # + # merb:dependencies:uninstall # uninstall all dependencies - the default + # merb:dependencies:uninstall merb-more # uninstall merb-more related gems locally + + desc 'uninstall [comp]', 'Uninstall application dependencies' + method_options "--dry-run" => :boolean, "--force" => :boolean + def uninstall(comp = nil) + # If comp given, filter on known stack components + deps = comp ? Merb::Stack.select_component_dependencies(dependencies, comp) : dependencies + self.system, self.local, self.missing = Merb::Gem.partition_dependencies(deps, gem_dir) + # Clobber existing local dependencies - based on self.local + clobber_dependencies! + end + + # Recreate all gems from gems/cache on the current platform. + # + # Note: use merb:gem:redeploy instead + + desc 'redeploy', 'Recreate all gems on the current platform' + method_options "--dry-run" => :boolean, "--force" => :boolean + def redeploy + warning 'Warning: merb:dependencies:redeploy has been deprecated - use merb:gem:redeploy instead' + gem = Merb::Gem.new + gem.options = options + gem.redeploy + end + + # Create a dependencies configuration file. + # + # A configuration yaml file will be created from the extracted application + # dependencies. The format of the configuration is as follows: + # + # --- + # - merb-core (= 0.9.8, runtime) + # - merb-slices (= 0.9.8, runtime) + # + # This format is exactly the same as Gem::Dependency#to_s returns. + # + # Examples: + # + # merb:dependencies:configure --force # overwrite the default config file + # merb:dependencies:configure --version 0.9.8 # configure specific framework version + # merb:dependencies:configure --config-file file.yml # write to the specified config file + + desc 'configure [comp]', 'Create a dependencies config file' + method_options "--dry-run" => :boolean, "--force" => :boolean, "--versions" => :boolean + def configure(comp = nil) + self.extract_dependencies = true # of course we need to consult the app itself + # If comp given, filter on known stack components + deps = comp ? Merb::Stack.select_component_dependencies(dependencies, comp) : dependencies + + # If --versions is set, update the version_requirements with the actual version available + if options[:versions] + specs = local_gemspecs + deps.each do |dep| + if spec = specs.find { |s| s.name == dep.name } + dep.version_requirements = ::Gem::Requirement.create(spec.version) + end + end + end + + config = YAML.dump(deps.map { |d| d.to_s }) + puts "#{config}\n" + if File.exists?(config_file) && !options[:force] + error "File already exists! Use --force to overwrite." + else + if dry_run? + note "Written #{config_file}" + else + FileUtils.mkdir_p(config_dir) unless File.directory?(config_dir) + File.open(config_file, 'w') { |f| f.write config } + success "Written #{config_file}" + end + end + rescue + error "Failed to write to #{config_file}" + end + + ### Helper Methods + + def strategy?(strategy) + if self.respond_to?(method = :"#{strategy}_strategy", true) + method + end + end + + def install_dependencies(strategy, deps, clobber = true) + if method = strategy?(strategy) + # Clobber existing local dependencies + clobber_dependencies! if clobber + + # Run the chosen strategy - collect files installed from stable gems + installed_from_stable = send(method, deps).map { |d| d.name } + + unless dry_run? + # Sleep a bit otherwise the following steps won't see the new files + sleep(deps.length) if deps.length > 0 && deps.length <= 10 + + # Leave a file to denote the strategy that has been used for this dependency + self.local.each do |spec| + next unless File.directory?(spec.full_gem_path) + unless installed_from_stable.include?(spec.name) + FileUtils.touch(File.join(spec.full_gem_path, "#{strategy}.strategy")) + else + FileUtils.touch(File.join(spec.full_gem_path, "stable.strategy")) + end + end + end + return true + end + false + end + + def dependencies + if extract_dependencies? + # Extract dependencies from the current application + deps = Merb::Stack.core_dependencies(gem_dir, ignore_dependencies?) + deps += Merb::Dependencies.extract_dependencies(working_dir) + else + # Use preconfigured dependencies from yaml file + deps = config_dependencies + end + + stack_components = Merb::Stack.components + + if options[:stack] + # Limit to stack components only + deps.reject! { |dep| not stack_components.include?(dep.name) } + elsif options[:"no-stack"] + # Limit to non-stack components + deps.reject! { |dep| stack_components.include?(dep.name) } + end + + if options[:version] + version_req = ::Gem::Requirement.create("= #{options[:version]}") + elsif core = deps.find { |d| d.name == 'merb-core' } + version_req = core.version_requirements + end + + if version_req + # Handle specific version requirement for framework components + framework_components = Merb::Stack.framework_components + deps.each do |dep| + if framework_components.include?(dep.name) + dep.version_requirements = version_req + end + end + end + + deps + end + + def config_dependencies + if File.exists?(config_file) + self.class.parse_dependencies_yaml(File.read(config_file)) + else + warning "No dependencies.yml file found at: #{config_file}" + [] + end + end + + def extract_dependencies? + options[:extract] || extract_dependencies + end + + def config_file + @config_file ||= begin + options[:"config-file"] || File.join(working_dir, 'config', 'dependencies.yml') + end + end + + def config_dir + File.dirname(config_file) + end + + ### Strategy handlers + + private + + def stable_strategy(deps) + installed_from_rubygems = [] + if core = deps.find { |d| d.name == 'merb-core' } + if dry_run? + note "Installing #{core.name}..." + else + if install_dependency(core) + installed_from_rubygems << core + else + msg = "Try specifying a lower version of merb-core with --version" + if version_no = core.version_requirements.to_s[/([\.\d]+)$/, 1] + num = "%03d" % (version_no.gsub('.', '').to_i - 1) + puts "The required version (#{version_no}) probably isn't available as a stable rubygem yet." + info "#{msg} #{num.split(//).join('.')}" + else + puts "The required version probably isn't available as a stable rubygem yet." + info msg + end + end + end + end + + deps.each do |dependency| + next if dependency.name == 'merb-core' + if dry_run? + note "Installing #{dependency.name}..." + else + install_dependency(dependency) + installed_from_rubygems << dependency + end + end + installed_from_rubygems + end + + def edge_strategy(deps) + use_edge_gem_server + installed_from_rubygems = [] + + # Selectively update repositories for the matching dependencies + update_dependency_repositories(deps) unless dry_run? + + if core = deps.find { |d| d.name == 'merb-core' } + if dry_run? + note "Installing #{core.name}..." + else + if install_dependency_from_source(core) + elsif install_dependency(core) + info "Installed #{core.name} from rubygems..." + installed_from_rubygems << core + end + end + end + + deps.each do |dependency| + next if dependency.name == 'merb-core' + if dry_run? + note "Installing #{dependency.name}..." + else + if install_dependency_from_source(dependency) + elsif install_dependency(dependency) + info "Installed #{dependency.name} from rubygems..." + installed_from_rubygems << dependency + end + end + end + + installed_from_rubygems + end + + ### Class Methods + + public + + def self.list(filter = 'all', comp = nil, options = {}) + instance = Merb::Dependencies.new + instance.options = options + instance.list(filter, comp) + end + + # Extract application dependencies by querying the app directly. + def self.extract_dependencies(merb_root) + require 'merb-core' + if !@_merb_loaded || Merb.root != merb_root + Merb.start_environment( + :log_level => :fatal, + :testing => true, + :adapter => 'runner', + :environment => ENV['MERB_ENV'] || 'development', + :merb_root => merb_root + ) + @_merb_loaded = true + end + Merb::BootLoader::Dependencies.dependencies + rescue StandardError => e + error "Couldn't extract dependencies from application!" + error e.message + puts "Make sure you're executing the task from your app (--merb-root)" + return [] + rescue SystemExit + error "Couldn't extract dependencies from application!" + error "application failed to run" + puts "Please check if your application runs using 'merb'; for example," + puts "look for any gem version mismatches in dependencies.rb" + return [] + end + + # Parse the basic YAML config data, and process Gem::Dependency output. + # Formatting example: merb_helpers (>= 0.9.8, runtime) + def self.parse_dependencies_yaml(yaml) + dependencies = [] + entries = YAML.load(yaml) rescue [] + entries.each do |entry| + if matches = entry.match(/^(\S+) \(([^,]+)?, ([^\)]+)\)/) + name, version_req, type = matches.captures + dependencies << ::Gem::Dependency.new(name, version_req, type.to_sym) + else + error "Invalid entry: #{entry}" + end + end + dependencies + end + + end + + class Stack < Thor + + group 'core' + + # The Stack tasks will install dependencies based on known sets of gems, + # regardless of actual application dependency settings. + + DM_STACK = %w[ + extlib + data_objects + dm-core + dm-aggregates + dm-migrations + dm-timestamps + dm-types + dm-validations + merb_datamapper + ] + + MERB_STACK = %w[ + extlib + merb-core + merb-action-args + merb-assets + merb-cache + merb-helpers + merb-mailer + merb-slices + merb-auth + merb-auth-core + merb-auth-more + merb-auth-slice-password + merb-param-protection + merb-exceptions + ] + DM_STACK + + MERB_BASICS = %w[ + extlib + merb-core + merb-action-args + merb-assets + merb-cache + merb-helpers + merb-mailer + merb-slices + ] + + # The following sets are meant for repository lookup; unlike the sets above + # these correspond to specific git repository items. + + MERB_MORE = %w[ + merb-action-args + merb-assets + merb-auth + merb-auth-core + merb-auth-more + merb-auth-slice-password + merb-cache + merb-exceptions + merb-gen + merb-haml + merb-helpers + merb-mailer + merb-param-protection + merb-slices + merb_datamapper + ] + + MERB_PLUGINS = %w[ + merb_activerecord + merb_builder + merb_jquery + merb_laszlo + merb_parts + merb_screw_unit + merb_sequel + merb_stories + merb_test_unit + ] + + DM_MORE = %w[ + dm-adjust + dm-aggregates + dm-ar-finders + dm-cli + dm-constraints + dm-is-example + dm-is-list + dm-is-nested_set + dm-is-remixable + dm-is-searchable + dm-is-state_machine + dm-is-tree + dm-is-versioned + dm-migrations + dm-observer + dm-querizer + dm-serializer + dm-shorthand + dm-sweatshop + dm-tags + dm-timestamps + dm-types + dm-validations + + dm-couchdb-adapter + dm-ferret-adapter + dm-rest-adapter + ] + + DATA_OBJECTS = %w[ + data_objects + do_derby do_hsqldb + do_jdbc + do_mysql + do_postgres + do_sqlite3 + ] + + attr_accessor :system, :local, :missing + + include MerbThorHelper + + global_method_options = { + "--merb-root" => :optional, # the directory to operate on + "--ignore-dependencies" => :boolean, # skip sub-dependencies + "--version" => :optional # gather specific version of framework + } + + method_options global_method_options + def initialize(*args); super; end + + # List components and their dependencies. + # + # Examples: + # + # merb:stack:list # list all standard stack components + # merb:stack:list all # list all component sets + # merb:stack:list merb-more # list all dependencies of merb-more + + desc 'list [all|comp]', 'List available components (optionally filtered, defaults to merb stack)' + def list(comp = 'stack') + if comp == 'all' + Merb::Stack.component_sets.keys.sort.each do |comp| + unless (components = Merb::Stack.component_sets[comp]).empty? + message "Dependencies for '#{comp}' set:" + components.each { |c| puts "- #{c}" } + end + end + else + message "Dependencies for '#{comp}' set:" + Merb::Stack.components(comp).each { |c| puts "- #{c}" } + end + end + + # Install stack components or individual gems - from stable rubygems by default. + # + # See also: Merb::Dependencies#install and Merb::Dependencies#install_dependencies + # + # Examples: + # + # merb:stack:install # install the default merb stack + # merb:stack:install basics # install a basic set of dependencies + # merb:stack:install merb-core # install merb-core from stable + # merb:stack:install merb-more --edge # install merb-core from edge + # merb:stack:install merb-core thor merb-slices # install the specified gems + + desc 'install [COMP, ...]', 'Install stack components' + method_options "--edge" => :boolean, + "--sources" => :optional, + "--force" => :boolean, + "--dry-run" => :boolean, + "--strategy" => :optional + def install(*comps) + use_edge_gem_server if options[:edge] + mngr = self.dependency_manager + deps = gather_dependencies(comps) + mngr.system, mngr.local, mngr.missing = Merb::Gem.partition_dependencies(deps, gem_dir) + mngr.install_dependencies(strategy, deps) + end + + # Uninstall stack components or individual gems. + # + # See also: Merb::Dependencies#uninstall + # + # Examples: + # + # merb:stack:uninstall # uninstall the default merb stack + # merb:stack:uninstall merb-more # uninstall merb-more + # merb:stack:uninstall merb-core thor merb-slices # uninstall the specified gems + + desc 'uninstall [COMP, ...]', 'Uninstall stack components' + method_options "--dry-run" => :boolean, "--force" => :boolean + def uninstall(*comps) + deps = gather_dependencies(comps) + self.system, self.local, self.missing = Merb::Gem.partition_dependencies(deps, gem_dir) + # Clobber existing local dependencies - based on self.local + clobber_dependencies! + end + + # Install or uninstall minigems from the system. + # + # Due to the specific nature of MiniGems it can only be installed system-wide. + # + # Examples: + # + # merb:stack:minigems install # install minigems + # merb:stack:minigems uninstall # uninstall minigems + + desc 'minigems (install|uninstall)', 'Install or uninstall minigems (needs sudo privileges)' + def minigems(action) + case action + when 'install' + Kernel.system "#{sudo} thor merb:stack:install_minigems" + when 'uninstall' + Kernel.system "#{sudo} thor merb:stack:uninstall_minigems" + else + error "Invalid command: merb:stack:minigems #{action}" + end + end + + # hidden minigems install task + def install_minigems + message "Installing MiniGems" + mngr = self.dependency_manager + deps = gather_dependencies('minigems') + mngr.system, mngr.local, mngr.missing = Merb::Gem.partition_dependencies(deps, gem_dir) + mngr.force_gem_dir = ::Gem.dir + mngr.install_dependencies(strategy, deps) + Kernel.system "#{sudo} minigem install" + end + + # hidden minigems uninstall task + def uninstall_minigems + message "Uninstalling MiniGems" + Kernel.system "#{sudo} minigem uninstall" + deps = gather_dependencies('minigems') + self.system, self.local, self.missing = Merb::Gem.partition_dependencies(deps, gem_dir) + # Clobber existing local dependencies - based on self.local + clobber_dependencies! + end + + protected + + def gather_dependencies(comps = []) + if comps.empty? + gems = MERB_STACK + else + gems = comps.map { |c| Merb::Stack.components(c) }.flatten + end + + version_req = if options[:version] + ::Gem::Requirement.create(options[:version]) + end + + framework_components = Merb::Stack.framework_components + + gems.map do |gem| + if version_req && framework_components.include?(gem) + ::Gem::Dependency.new(gem, version_req) + else + ::Gem::Dependency.new(gem, ::Gem::Requirement.default) + end + end + end + + def strategy + options[:strategy] || (options[:edge] ? 'edge' : 'stable') + end + + def dependency_manager + @_dependency_manager ||= begin + instance = Merb::Dependencies.new + instance.options = options + instance + end + end + + public + + def self.repository_sets + @_repository_sets ||= begin + # the component itself as a fallback + comps = Hash.new { |(hsh,c)| [c] } + + # git repository based component sets + comps["merb"] = ["merb-core"] + MERB_MORE + comps["merb-more"] = MERB_MORE.sort + comps["merb-plugins"] = MERB_PLUGINS.sort + comps["dm-more"] = DM_MORE.sort + comps["do"] = DATA_OBJECTS.sort + + comps + end + end + + def self.component_sets + @_component_sets ||= begin + # the component itself as a fallback + comps = Hash.new { |(hsh,c)| [c] } + comps.update(repository_sets) + + # specific set of dependencies + comps["stack"] = MERB_STACK.sort + comps["basics"] = MERB_BASICS.sort + + # orm dependencies + comps["datamapper"] = DM_STACK.sort + comps["sequel"] = ["merb_sequel", "sequel"] + comps["activerecord"] = ["merb_activerecord", "activerecord"] + + comps + end + end + + def self.framework_components + %w[merb-core merb-more].inject([]) do |all, comp| + all + components(comp) + end + end + + def self.components(comp = nil) + if comp + component_sets[comp] + else + comps = %w[merb-core merb-more merb-plugins dm-core dm-more] + comps.inject([]) do |all, grp| + all + (component_sets[grp] || []) + end + end + end + + def self.select_component_dependencies(dependencies, comp = nil) + comps = components(comp) || [] + dependencies.select { |dep| comps.include?(dep.name) } + end + + def self.base_components + %w[thor rake extlib] + end + + def self.all_components + base_components + framework_components + end + + # Find the latest merb-core and gather its dependencies. + # We check for 0.9.8 as a minimum release version. + def self.core_dependencies(gem_dir = nil, ignore_deps = false) + @_core_dependencies ||= begin + if gem_dir # add local gems to index + orig_gem_path = ::Gem.path + ::Gem.clear_paths; ::Gem.path.unshift(gem_dir) + end + deps = [] + merb_core = ::Gem::Dependency.new('merb-core', '>= 0.9.8') + if gemspec = ::Gem.source_index.search(merb_core).last + deps << ::Gem::Dependency.new('merb-core', gemspec.version) + if ignore_deps + deps += gemspec.dependencies.select do |d| + base_components.include?(d.name) + end + else + deps += gemspec.dependencies + end + end + ::Gem.path.replace(orig_gem_path) if gem_dir # reset + deps + end + end + + def self.lookup_repository_name(item) + set_name = nil + # The merb repo contains -more as well, so it needs special attention + return 'merb' if self.repository_sets['merb'].include?(item) + + # Proceed with finding the item in a known component set + self.repository_sets.find do |set, items| + next if set == 'merb' + items.include?(item) ? (set_name = set) : nil + end + set_name + end + + end + +end \ No newline at end of file