optionsful 0.2.3 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/.autotest ADDED
@@ -0,0 +1,23 @@
1
+ require "autotest/growl"
2
+ require 'autotest/fsevent'
3
+ require 'autotest/timestamp'
4
+ require 'autotest/autoupdate'
5
+ require 'autotest/once'
6
+ require 'autotest/restart'
7
+ require 'redgreen'
8
+
9
+ Autotest::Growl::show_modified_files = true
10
+
11
+ Autotest.add_hook :initialize do |autotest|
12
+ %w{.git .svn .hg .DS_Store ._* vendor tmp log doc coverage}.each do |exception|
13
+ autotest.add_exception(exception)
14
+ end
15
+ end
16
+
17
+ Autotest.add_hook :run_command do |at|
18
+ system "export RSPEC=true"
19
+ system "export AUTOFEATURE=true"
20
+ end
21
+
22
+ require 'autotest/rcov'
23
+ # Autotest::RCov.command = 'rcov_info'
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,25 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+ .rvmrc
21
+ .yardoc
22
+ doc
23
+ log
24
+ tmp
25
+ ## PROJECT::SPECIFIC
@@ -1,4 +1,4 @@
1
- Copyright (c) 2010 Marco Antonio Gonzalez Junior (kayaman@baurets.net).
1
+ Copyright (c) 2010 Marco Antonio Gonzalez Junior
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
4
4
  documentation files (the "Software"), to deal in the Software without restriction, including without limitation
@@ -12,4 +12,4 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
12
12
  TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
13
13
  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
14
14
  CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
15
- DEALINGS IN THE SOFTWARE.
15
+ DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,17 @@
1
+ = optionsful3
2
+
3
+ Description goes here.
4
+
5
+ == Note on Patches/Pull Requests
6
+
7
+ * Fork the project.
8
+ * Make your feature addition or bug fix.
9
+ * Add tests for it. This is important so I don't break it in a
10
+ future version unintentionally.
11
+ * Commit, do not mess with rakefile, version, or history.
12
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
13
+ * Send me a pull request. Bonus points for topic branches.
14
+
15
+ == Copyright
16
+
17
+ Copyright (c) 2010 Marco Antonio Gonzalez Junior. See LICENSE for details.
data/Rakefile CHANGED
@@ -1,11 +1,66 @@
1
- require 'metric_fu'
2
1
  require 'rubygems'
2
+ require 'rake'
3
+ require 'fileutils'
4
+
5
+ begin
6
+ require 'jeweler'
7
+ Jeweler::Tasks.new do |gem|
8
+ gem.name = "optionsful"
9
+ gem.summary = %Q{Support HTTP OPTIONS verb on your Rails 3 app.}
10
+ gem.description = %Q{Help building RESTful web services by supporting the HTTP OPTIONS verb on Ruby on Rails applications.}
11
+ gem.email = "kayaman@baurets.net"
12
+ gem.homepage = "http://github.com/kayaman/optionsful3"
13
+ gem.authors = ["Marco Antonio Gonzalez Junior"]
14
+ gem.rubyforge_project = "optionsful3"
15
+ gem.add_development_dependency "rspec", ">= 1.2.9"
16
+ gem.add_development_dependency "yard", ">= 0"
17
+ gem.add_development_dependency "cucumber", ">= 0"
18
+ gem.add_dependency "rails", ">= 3.0.0"
19
+ end
20
+ Jeweler::GemcutterTasks.new
21
+ Jeweler::RubyforgeTasks.new do |rubyforge|
22
+ rubyforge.doc_task = "yardoc"
23
+ end
24
+ rescue LoadError
25
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
26
+ end
27
+
3
28
  require 'spec/rake/spectask'
29
+ Spec::Rake::SpecTask.new(:spec) do |spec|
30
+ spec.libs << 'lib' << 'spec'
31
+ spec.spec_opts << '--color --format specdoc'
32
+ spec.verbose = true
33
+ spec.warning = false
34
+ spec.spec_files = FileList['spec/**/*_spec.rb']
35
+ end
4
36
 
5
- Spec::Rake::SpecTask.new(:spec) do |t|
6
- t.spec_files = Dir.glob( File.dirname(__FILE__) + '/spec/**/*_spec.rb' )
7
- t.spec_opts << '--color --format specdoc'
8
- t.rcov = true
37
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
38
+ spec.libs << 'lib' << 'spec'
39
+ spec.pattern = 'spec/**/*_spec.rb'
40
+ spec.rcov = true
41
+ end
42
+
43
+ task :spec => :check_dependencies
44
+
45
+ begin
46
+ require 'cucumber/rake/task'
47
+ Cucumber::Rake::Task.new(:features)
48
+
49
+ task :features => :check_dependencies
50
+ rescue LoadError
51
+ task :features do
52
+ abort "Cucumber is not available. In order to run features, you must: sudo gem install cucumber"
53
+ end
9
54
  end
10
55
 
11
56
  task :default => :spec
57
+
58
+ begin
59
+ require 'yard'
60
+ YARD::Rake::YardocTask.new
61
+ rescue LoadError
62
+ task :yardoc do
63
+ abort "YARD is not available. In order to run yardoc, you must: sudo gem install yard"
64
+ end
65
+ end
66
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.3.0
@@ -0,0 +1,18 @@
1
+
2
+ development:
3
+ link: true
4
+ host: auto
5
+ base_path: /blopts
6
+ propagate: false
7
+
8
+ test:
9
+ link: true
10
+ host: auto
11
+ base_path: /blopts
12
+ propagate: false
13
+
14
+ production:
15
+ link: true
16
+ host: auto
17
+ base_path: /blopts
18
+ propagate: false
@@ -0,0 +1,9 @@
1
+ Feature: something something
2
+ In order to something something
3
+ A user something something
4
+ something something something
5
+
6
+ Scenario: something something
7
+ Given inspiration
8
+ When I create a sweet new gem
9
+ Then everyone should see how awesome I am
@@ -0,0 +1,4 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../../lib')
2
+ require 'optionsful'
3
+
4
+ require 'spec/expectations'
@@ -2,48 +2,53 @@ module Baurets
2
2
  module Optionsful
3
3
  class Config
4
4
 
5
- def initialize(options = {})
6
- @config = configure_options(options)
7
- setup
8
- self
9
- end
5
+ DEFAULT = { :link => false, :host => 'auto', :base_path => "/optionsful", :propagate => true }
10
6
 
11
- def base_path
12
- @config[:http][:base_path]
7
+ def initialize(file = nil, options = {})
8
+ unless file.nil?
9
+ @config = load_from_file(file, get_env)
10
+ else
11
+ begin
12
+ if (defined? Rails && File.exist?(File.join(Rails.root, 'config', 'optionsful.yml')))
13
+ envs = YAML::load_file(File.join(Rails.root, 'config', 'optionsful.yml')).symbolize_keys
14
+ @config = envs[get_env].symbolize_keys
15
+ end
16
+ rescue
17
+ end
18
+ end
19
+ @config = DEFAULT if @config.nil?
20
+ @config
13
21
  end
14
22
 
15
- private
16
-
17
- def configure_options(options = {})
18
- default_opts = { :http => { :base_path => "/optionsful"}, :file => "", :environment => "development" }
19
- conf = {}
20
- if defined? RAILS_ROOT
21
- conf = default_opts.merge!({:file => (File.join(RAILS_ROOT, 'config', 'optionsful.yml'))})
23
+ def get_env
24
+ if defined? Rails
25
+ env = :test if Rails.env.test?
26
+ env = :development if Rails.env.development?
27
+ env = :production if Rails.env.production?
22
28
  else
23
- conf = default_opts.merge!({ :http => { :base_path => "/optionsful"} })
29
+ env = :development
24
30
  end
25
- conf = conf.merge!(options) unless options.empty?
26
- conf
31
+ env
27
32
  end
28
33
 
29
- def setup
30
- require "yaml"
31
- yaml_file = @config[:file]
32
- begin
33
- if File.exist? yaml_file
34
- conf = YAML::load_file(yaml_file)[@config[:environment]].symbolize_keys
35
- configure(conf) if conf
34
+ def load_from_file(file, environment)
35
+ config = nil
36
+ require 'yaml'
37
+ if File.exist?(file)
38
+ begin
39
+ envs = YAML::load_file(file).symbolize_keys
40
+ config = envs[environment].symbolize_keys
41
+ rescue => e
42
+ puts e.backtrace
36
43
  end
37
- rescue
38
44
  end
45
+ config
39
46
  end
40
47
 
41
- def configure(conf)
42
- @config[:http][:base_path] = conf[:http]["base_path"] if (conf[:http] && conf[:http]["base_path"])
43
- @config[:file] = conf[:file] if conf[:file]
44
- @config[:environment] = conf[:environment] if conf[:environment]
48
+ def method_missing(name, *args)
49
+ return @config[name.to_sym]
45
50
  end
46
51
 
47
52
  end
48
53
  end
49
- end
54
+ end
@@ -2,71 +2,23 @@ module Baurets
2
2
  module Optionsful
3
3
  module Introspections
4
4
 
5
- def self.is_part_static?(routes, index, value)
6
- routes.each do |route|
7
- return true if route[0][index] == value
8
- end
9
- return false
10
-
11
- end
12
-
13
-
14
- def self.do_routing_introspection
15
- returning Array.new do |routes|
16
- route_requirements = nil
17
- ActionController::Routing::Routes.named_routes.map.each do |named_route|
18
- name = named_route[0].to_s
19
- routes << [[name], ["GET", named_route[1].requirements[:action]], {:controller => named_route[1].requirements[:controller], :action => named_route[1].requirements[:action]}]
20
- #TODO ANY ?!?
21
- end
22
- ActionController::Routing::Routes.routes.each do |route|
23
- static_path = []
24
- route.segments.each do |segment|
25
- route_requirements = route.requirements #TODO validate
26
- if segment.kind_of?(ActionController::Routing::StaticSegment)
27
- static_path << segment.value if (segment.respond_to?(:value) && segment.value != "/")
28
- elsif segment.kind_of?(ActionController::Routing::DynamicSegment)
29
- static_path << :dynamic unless (segment.respond_to?(:key) && segment.key == :format)
30
- end
31
- end
32
- routes << [static_path, [route.conditions[:method].to_s.upcase, route_requirements[:action]], route_requirements] unless route.conditions[:method].nil?
33
- end
34
- end
35
- end
36
-
37
- def self.guess_route(routes, path)
38
- guess = []
39
- parts = prepare_request_path(path)
40
- index = 0
41
- parts.each do |part|
42
- if is_part_static?(routes, index, part)
43
- guess << part
44
- else
45
- guess << :dynamic
46
- end
47
- index += 1
48
- end
49
- guess
50
- end
51
-
52
- def self.do_the_matches(routes, route_guess)
5
+ def self.do_the_matches(path_info)
6
+ routes = Rails.application.routes.routes if defined? Rails # Rails major = 3
7
+ routes.reject!{ |r| r.path == "/rails/info/properties" } # skip the route if it's internal info route
53
8
  allow = ""
54
9
  routes.each do |route|
55
- if route.first == route_guess
56
- allow += (route[1][0].to_s.upcase + "|") unless allow.include?(route[1][0].to_s.upcase)
10
+ if path_info =~ route.conditions[:path_info]
11
+ if route.verb
12
+ allow += (route.verb.to_s.upcase + "|") unless allow.include?(route.verb.to_s.upcase)
13
+ else
14
+ # TODO - return 'ANY' doesn't sound ANY good ;p
15
+ allow = "GET"
16
+ end
57
17
  end
58
18
  end
59
19
  allow = allow.split("|").join(", ")
60
20
  end
61
21
 
62
- def self.prepare_request_path(path)
63
- path_parts = []
64
- path = path[0..(path.rindex('.')-1)] if path.include?('.')
65
- path_parts = path.split("/")
66
- path_parts.delete("")
67
- path_parts
68
- end
69
-
70
22
  end
71
23
  end
72
- end
24
+ end
@@ -4,49 +4,63 @@ module Baurets
4
4
 
5
5
  def initialize(app)
6
6
  @app = app
7
- @config = ::Baurets::Optionsful::Config.new
7
+ @config = Config.new
8
8
  end
9
9
 
10
10
  def call(env)
11
11
  unless env["REQUEST_METHOD"] == "OPTIONS"
12
12
  @app.call(env)
13
13
  else
14
- extract_options_information(env)
14
+ @env = env
15
+ build_response
15
16
  end
16
17
  end
17
18
 
18
19
  private
19
20
 
20
- def extract_options_information(env)
21
- allows = extract_allowed_methods(env)
22
- if allows.empty?
23
- [404, {}, "Not found."]
21
+ def build_response
22
+ allows = extract_options_information
23
+ headers = {}
24
+ status = 500
25
+ body = ""
26
+ unless allows.empty?
27
+ headers.merge!({"Allow" => allows})
28
+ status = 204
29
+ if @config.link
30
+ headers.merge!({"Link" => build_link_header})
31
+ end
24
32
  else
25
- [204, {"Allow" => allows, "Link" => "\"#{build_help_link(env)}\""}, ""]
33
+ status = 404
34
+ body = "Not found"
26
35
  end
36
+ [status, headers, body]
27
37
  end
28
-
29
- def extract_allowed_methods(env)
30
- # do routing introspection:
31
- routes = ::Baurets::Optionsful::Introspections.do_routing_introspection
32
- # do request path investigation
33
- path = env["PATH_INFO"]
34
- route_guess = ::Baurets::Optionsful::Introspections.guess_route(routes, path)
35
-
36
- puts "\nPATH: \n #{path}\n"
37
- puts "\nROUTES: \n #{routes.inspect}\n"
38
- puts "\nGUESS: \n #{route_guess.inspect}\n"
38
+
39
+ def build_link_header
40
+ link = ""
41
+ if @config.host == "auto"
42
+ server_name = @env["SERVER_NAME"]
43
+ server_port = @env["SERVER_PORT"]
44
+ link = "\"<http://#{server_name}:#{server_port}"
45
+ else
46
+ link = "\"<http://#{@config.host}"
47
+ end
48
+ unless @config.base_path.empty?
49
+ link += @config.base_path unless @config.base_path == "/"
50
+ end
51
+ if @config.propagate == true
52
+ link += @env["PATH_INFO"]
53
+ end
39
54
 
40
- # do the matches:
41
- allow = ::Baurets::Optionsful::Introspections.do_the_matches(routes, route_guess)
55
+ link += ">; type=text/html; rel=help\""
56
+ link
42
57
  end
43
58
 
44
- def build_help_link(env)
45
- server_name = env["SERVER_NAME"]
46
- server_port = env["SERVER_PORT"]
47
- "<http://#{server_name}:#{server_port}" + @config.base_path + "#{env["PATH_INFO"]}>; type=text/html; rel=help"
59
+ def extract_options_information
60
+ allows = ::Baurets::Optionsful::Introspections.do_the_matches(@env["PATH_INFO"])
48
61
  end
49
62
 
50
63
  end
51
64
  end
52
- end
65
+ end
66
+
data/lib/optionsful.rb CHANGED
@@ -1,10 +1,11 @@
1
- $:.unshift(File.dirname(__FILE__)) unless $:.include?(File.dirname(__FILE__))
2
-
3
- require 'baurets/optionsful/config'
4
- require 'baurets/optionsful/introspections'
5
- require 'baurets/optionsful/server'
6
-
7
- module Optionsful
8
-
9
-
1
+ ##
2
+ # Baurets Software
3
+ # kayaman@baurets.net
4
+ #
5
+ module Baurets
6
+ module Optionsful
7
+ autoload :Server, 'baurets/optionsful/server'
8
+ autoload :Introspections, 'baurets/optionsful/introspections'
9
+ autoload :Config, 'baurets/optionsful/config'
10
+ end
10
11
  end
@@ -0,0 +1,82 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{optionsful}
8
+ s.version = "0.3.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Marco Antonio Gonzalez Junior"]
12
+ s.date = %q{2010-08-05}
13
+ s.description = %q{Help building RESTful web services by supporting the HTTP OPTIONS verb on Ruby on Rails applications.}
14
+ s.email = %q{kayaman@baurets.net}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".autotest",
21
+ ".document",
22
+ ".gitignore",
23
+ "LICENSE",
24
+ "README.rdoc",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "config/optionsful.yml",
28
+ "features/optionsful.feature",
29
+ "features/step_definitions/optionsful3_steps.rb",
30
+ "features/support/env.rb",
31
+ "lib/baurets/optionsful/config.rb",
32
+ "lib/baurets/optionsful/introspections.rb",
33
+ "lib/baurets/optionsful/server.rb",
34
+ "lib/optionsful.rb",
35
+ "lib/tasks/optionsful.rake",
36
+ "optionsful.gemspec",
37
+ "rails/init.rb",
38
+ "spec/config/optionsful.yml",
39
+ "spec/config/optionsful_host_auto.yml",
40
+ "spec/config/optionsful_link_false.yml",
41
+ "spec/fake_app.rb",
42
+ "spec/optionsful_config_spec.rb",
43
+ "spec/optionsful_server_spec.rb",
44
+ "spec/spec.opts",
45
+ "spec/spec_helper.rb"
46
+ ]
47
+ s.homepage = %q{http://github.com/kayaman/optionsful3}
48
+ s.rdoc_options = ["--charset=UTF-8"]
49
+ s.require_paths = ["lib"]
50
+ s.rubyforge_project = %q{optionsful3}
51
+ s.rubygems_version = %q{1.3.7}
52
+ s.summary = %q{Support HTTP OPTIONS verb on your Rails 3 app.}
53
+ s.test_files = [
54
+ "spec/fake_app.rb",
55
+ "spec/optionsful_config_spec.rb",
56
+ "spec/optionsful_server_spec.rb",
57
+ "spec/spec_helper.rb"
58
+ ]
59
+
60
+ if s.respond_to? :specification_version then
61
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
62
+ s.specification_version = 3
63
+
64
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
65
+ s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
66
+ s.add_development_dependency(%q<yard>, [">= 0"])
67
+ s.add_development_dependency(%q<cucumber>, [">= 0"])
68
+ s.add_runtime_dependency(%q<rails>, [">= 3.0.0"])
69
+ else
70
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
71
+ s.add_dependency(%q<yard>, [">= 0"])
72
+ s.add_dependency(%q<cucumber>, [">= 0"])
73
+ s.add_dependency(%q<rails>, [">= 3.0.0"])
74
+ end
75
+ else
76
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
77
+ s.add_dependency(%q<yard>, [">= 0"])
78
+ s.add_dependency(%q<cucumber>, [">= 0"])
79
+ s.add_dependency(%q<rails>, [">= 3.0.0"])
80
+ end
81
+ end
82
+
data/rails/init.rb CHANGED
@@ -1,9 +1,5 @@
1
- # Adding Optionsful to the Rack middleware stack:
2
- ActionController::Dispatcher.middleware.use Baurets::Optionsful::Server
3
1
 
4
- puts "Gem.searcher.find('optionsful').full_gem_path = #{Gem.searcher.find('optionsful').full_gem_path}"
5
2
 
6
- Dir["#{Gem.searcher.find('optionsful').full_gem_path}/**/tasks/*.rake"].each do |ext|
7
- puts "Loading: #{ext}"
8
- load ext
9
- end
3
+ unless defined? Rails
4
+ puts "This requires Rails 3. Please look for 'optionsful2'."
5
+ end
@@ -0,0 +1,18 @@
1
+
2
+ development:
3
+ link: true
4
+ host: auto
5
+ base_path: /blopts
6
+ propagate: false
7
+
8
+ test:
9
+ link: true
10
+ host: auto
11
+ base_path: /blopts
12
+ propagate: false
13
+
14
+ production:
15
+ link: true
16
+ host: auto
17
+ base_path: /blopts
18
+ propagate: false
@@ -0,0 +1,18 @@
1
+
2
+ development:
3
+ link: true
4
+ host: auto
5
+ base_path: /blopts
6
+ propagate: false
7
+
8
+ test:
9
+ link: true
10
+ host: auto
11
+ base_path: /blopts
12
+ propagate: false
13
+
14
+ production:
15
+ link: true
16
+ host: auto
17
+ base_path: /blopts
18
+ propagate: false
@@ -0,0 +1,18 @@
1
+
2
+ development:
3
+ link: false
4
+ host: auto
5
+ base_path: /blopts
6
+ propagate: false
7
+
8
+ test:
9
+ link: false
10
+ host: auto
11
+ base_path: /blopts
12
+ propagate: false
13
+
14
+ production:
15
+ link: false
16
+ host: auto
17
+ base_path: /blopts
18
+ propagate: false
data/spec/fake_app.rb ADDED
@@ -0,0 +1,6 @@
1
+ require 'rubygems'
2
+ require 'rails'
3
+
4
+ class FakeApp < Rails::Application
5
+
6
+ end