Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

not falling behind the times! #7

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
.bundle
*.gem
*.gem
.DS_Store
55 changes: 55 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
GEM
remote: http://rubygems.org/
specs:
actionpack (3.1.3)
activemodel (= 3.1.3)
activesupport (= 3.1.3)
builder (~> 3.0.0)
erubis (~> 2.7.0)
i18n (~> 0.6)
rack (~> 1.3.5)
rack-cache (~> 1.1)
rack-mount (~> 0.8.2)
rack-test (~> 0.6.1)
sprockets (~> 2.0.3)
activemodel (3.1.3)
activesupport (= 3.1.3)
builder (~> 3.0.0)
i18n (~> 0.6)
activesupport (3.1.3)
multi_json (~> 1.0)
builder (3.0.0)
diff-lcs (1.1.3)
erubis (2.7.0)
hike (1.2.1)
i18n (0.6.0)
multi_json (1.0.4)
rack (1.3.6)
rack-cache (1.1)
rack (>= 0.4)
rack-mount (0.8.3)
rack (>= 1.0.0)
rack-test (0.6.1)
rack (>= 1.0)
rake (0.9.2.2)
rspec (2.8.0)
rspec-core (~> 2.8.0)
rspec-expectations (~> 2.8.0)
rspec-mocks (~> 2.8.0)
rspec-core (2.8.0)
rspec-expectations (2.8.0)
diff-lcs (~> 1.1.2)
rspec-mocks (2.8.0)
sprockets (2.0.3)
hike (~> 1.2)
rack (~> 1.0)
tilt (~> 1.1, != 1.3.0)
tilt (1.3.3)

PLATFORMS
ruby

DEPENDENCIES
actionpack
rake
rspec
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,4 @@ Astaire supports inline templates in the same style as Sinatra. For example:
### TODO

I guess, at this point I'm just putting what I have into the wild. Next
steps will be determined by feedback that I get.
steps will be determined by feedback that I get.
4 changes: 2 additions & 2 deletions astaire.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@ Gem::Specification.new do |s|
s.files = Dir['README.md', 'LICENSE', 'lib/**/*']
s.require_path = 'lib'

s.add_dependency 'actionpack', '~> 3.0.0.beta2'
end
# s.add_dependency 'actionpack', '> 3.0.0.beta2'
end
167 changes: 5 additions & 162 deletions lib/astaire.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,166 +14,9 @@ module Astaire

# add rubinius (and hopefully other VM impls) ignore patterns ...
CALLERS_TO_IGNORE.concat(RUBY_IGNORE_CALLERS) if defined?(RUBY_IGNORE_CALLERS)

class InlineTemplates < ActionView::PathResolver
def initialize
super
@templates = {}
end

def add_controller(controller)
file = caller_files.first

begin
app, data =
::IO.read(file).gsub("\r\n", "\n").split(/^__END__$/, 2)
rescue Errno::ENOENT
app, data = nil
end

if data
lines = app.count("\n") + 1
template = nil
data.each_line do |line|
lines += 1
if line =~ /^@@\s*(.*)/
template = ''
@templates["#{controller.controller_path}/#{$1}"] =
[template, file, lines]
elsif template
template << line
end
end
end
end

def query(path, exts, formats)
query = Regexp.escape(path)
exts.each do |ext|
query << '(' << ext.map {|e| e && Regexp.escape(".#{e}") }.join('|') << '|)'
end

templates = []
@templates.select { |k,v| k =~ /^#{query}$/ }.each do |path, (source, file, lines)|
handler, format = extract_handler_and_format(path, formats)
templates << ActionView::Template.new(source, path, handler,
:virtual_path => path, :format => format)
end

templates.sort_by {|t| -t.identifier.match(/^#{query}$/).captures.reject(&:blank?).size }
end

# Like Kernel#caller but excluding certain magic entries and without
# line / method information; the resulting array contains filenames only.
def caller_files
caller_locations.
map { |file,line| file }
end

def caller_locations
caller(1).
map { |line| line.split(/:(?=\d|in )/)[0,2] }.
reject { |file,line| CALLERS_TO_IGNORE.any? { |pattern| file =~ pattern } }
end
end

module DSL
extend ActiveSupport::Concern

include AbstractController::Helpers

included do
class_attribute :_astaire_router
self._astaire_router = ActionDispatch::Routing::RouteSet.new

class_attribute :_astaire_helpers
self._astaire_helpers = url_helper_module

class_attribute :_inline_resolver
self._inline_resolver = InlineTemplates.new

_inline_resolver.add_controller(self)

include _astaire_helpers
helper _astaire_helpers

append_view_path _inline_resolver
end

module ClassMethods
def call(env)
_astaire_router.call(env)
end

def mapper
@mapper ||= ActionDispatch::Routing::Mapper.new(_astaire_router)
end

%w(get post put delete).each do |method|
class_eval <<-R, __FILE__, __LINE__+1
def #{method}(path, opts = {}, &blk)
map_astaire_action "#{method}", path, opts, blk
end
R
end

def inherited(klass)
super
_inline_resolver.add_controller(klass)
end

private

def map_astaire_action(method, path, opts, blk)
action_name = "[#{method}] #{path}"
define_method action_name, &blk
opts.merge! :via => method, :to => action(action_name)

mapper.match(path, opts)
make_url_helper(opts[:as]) if opts[:as]
end

def url_helper_module
Module.new do
def _astaire_url_opts_from_args(name, route, args, only_path)
opts = args.extract_options!

if args.any?
opts[:_positional_args] = args
opts[:_positional_keys] = route.segment_keys
end

opts = url_options.merge(opts)
opts.merge!(:use_route => name, :only_path => only_path)

if path_segments = opts[:_path_segments]
path_segments.delete(:controller)
path_segments.delete(:action)
end

opts
end
end
end

def make_url_helper(name)
name = name.to_sym
router = _astaire_router

_astaire_helpers.module_eval do
define_method "#{name}_path" do |*args|
route = router.named_routes[name]
opts = _astaire_url_opts_from_args(name, route, args, true)
router.url_for(opts)
end

define_method "#{name}_url" do |*args|
route = router.named_routes[name]
opts = _astaire_url_opts_from_args(name, route, args, false)
router.url_for(opts)
end
end
end
end
end

# autoload the sub modules
autoload :Cascade, 'astaire/cascade'
autoload :DSL, 'astaire/dsl'
autoload :InlineTemplates, 'astaire/inline_templates'
end
30 changes: 30 additions & 0 deletions lib/astaire/cascade.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
module Astaire
class Cascade
def self.new(*apps)
apps = apps.flatten

case apps.length
when 0
raise ArgumentError, "app is required"
when 1
apps.first
else
super(apps)
end
end

def initialize(apps)
@apps = apps
end

def call(env)
result = nil
@apps.each do |app|
result = app.call(env)
break unless result[1]["X-Cascade"] == "pass"
end

result
end
end
end
100 changes: 100 additions & 0 deletions lib/astaire/dsl.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
module Astaire
module DSL
extend ActiveSupport::Concern
include AbstractController::Helpers

included do
class_attribute :_astaire_router
self._astaire_router = ActionDispatch::Routing::RouteSet.new

class_attribute :_astaire_helpers
self._astaire_helpers = url_helper_module

class_attribute :_inline_resolver
self._inline_resolver = InlineTemplates.new

_inline_resolver.add_controller(self)

include _astaire_helpers
helper _astaire_helpers

append_view_path _inline_resolver
end

module ClassMethods
def call(env)
_astaire_router.call(env)
end

def mapper
@mapper ||= ActionDispatch::Routing::Mapper.new(_astaire_router)
end

%w(get post put delete).each do |method|
class_eval <<-R, __FILE__, __LINE__+1
def #{method}(path, opts = {}, &blk)
map_astaire_action "#{method}", path, opts, blk
end
R
end

def inherited(klass)
super
_inline_resolver.add_controller(klass)
end

private

def map_astaire_action(method, path, opts, blk)
action_name = "[#{method}] #{path}"
define_method action_name, &blk
opts.merge! :via => method, :to => action(action_name)

mapper.match(path, opts)
make_url_helper(opts[:as]) if opts[:as]
end

def url_helper_module
Module.new do
def _astaire_url_opts_from_args(name, route, args, only_path)
opts = args.extract_options!

if args.any?
opts[:_positional_args] = args
opts[:_positional_keys] = route.segment_keys
end

opts = url_options.merge(opts)
opts.merge!(:use_route => name, :only_path => only_path)

if path_segments = opts[:_path_segments]
path_segments.delete(:controller)
path_segments.delete(:action)
end

opts
end
end
end

def make_url_helper(name)
name = name.to_sym
router = _astaire_router

_astaire_helpers.module_eval do
define_method "#{name}_path" do |*args|
route = router.named_routes[name]
opts = _astaire_url_opts_from_args(name, route, args, true)
router.url_for(opts)
end

define_method "#{name}_url" do |*args|
route = router.named_routes[name]
opts = _astaire_url_opts_from_args(name, route, args, false)
router.url_for(opts)
end
end
end
end
end
end
Loading