grippy-doozer 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +5 -0
- data/.gitignore +5 -0
- data/LICENSE +20 -0
- data/README.rdoc +57 -0
- data/Rakefile +59 -0
- data/VERSION +1 -0
- data/bin/doozer +8 -0
- data/doozer.gemspec +114 -0
- data/lib/doozer/README.rb +40 -0
- data/lib/doozer/active_support/array.rb +14 -0
- data/lib/doozer/active_support/class.rb +221 -0
- data/lib/doozer/active_support/date_time.rb +23 -0
- data/lib/doozer/active_support/object.rb +43 -0
- data/lib/doozer/active_support/time.rb +32 -0
- data/lib/doozer/app.rb +265 -0
- data/lib/doozer/configs.rb +131 -0
- data/lib/doozer/controller.rb +335 -0
- data/lib/doozer/extend.rb +10 -0
- data/lib/doozer/initializer.rb +95 -0
- data/lib/doozer/lib.rb +32 -0
- data/lib/doozer/logger.rb +11 -0
- data/lib/doozer/orm/active_record.rb +19 -0
- data/lib/doozer/orm/data_mapper.rb +19 -0
- data/lib/doozer/orm/sequel.rb +18 -0
- data/lib/doozer/partial.rb +99 -0
- data/lib/doozer/plugins/paginate/init.rb +2 -0
- data/lib/doozer/plugins/paginate/lib/paginate/collection.rb +60 -0
- data/lib/doozer/plugins/paginate/lib/paginate/finder.rb +116 -0
- data/lib/doozer/plugins/paginate/lib/paginate/view_helpers.rb +37 -0
- data/lib/doozer/plugins/paginate/lib/paginate.rb +32 -0
- data/lib/doozer/rackup/server.ru +37 -0
- data/lib/doozer/rackup/test.rb +19 -0
- data/lib/doozer/redirect.rb +12 -0
- data/lib/doozer/route.rb +264 -0
- data/lib/doozer/scripts/cluster.rb +132 -0
- data/lib/doozer/scripts/migrate.rb +108 -0
- data/lib/doozer/scripts/task.rb +60 -0
- data/lib/doozer/scripts/test.rb +23 -0
- data/lib/doozer/version.rb +8 -0
- data/lib/doozer/view_helpers.rb +163 -0
- data/lib/doozer/watcher.rb +375 -0
- data/lib/doozer.rb +30 -0
- data/lib/generator/generator.rb +547 -0
- data/templates/skeleton/Rakefile +3 -0
- data/templates/skeleton/app/controllers/application_controller.rb +2 -0
- data/templates/skeleton/app/controllers/index_controller.rb +7 -0
- data/templates/skeleton/app/helpers/application_helper.rb +17 -0
- data/templates/skeleton/app/views/global/_header.html.erb +7 -0
- data/templates/skeleton/app/views/global/_navigation.html.erb +6 -0
- data/templates/skeleton/app/views/index/index.html.erb +108 -0
- data/templates/skeleton/app/views/layouts/default.html.erb +23 -0
- data/templates/skeleton/config/app.yml +31 -0
- data/templates/skeleton/config/database.yml +25 -0
- data/templates/skeleton/config/environment.rb +13 -0
- data/templates/skeleton/config/rack.rb +30 -0
- data/templates/skeleton/config/routes.rb +69 -0
- data/templates/skeleton/script/cluster +5 -0
- data/templates/skeleton/script/migrate +5 -0
- data/templates/skeleton/script/task +5 -0
- data/templates/skeleton/script/test +4 -0
- data/templates/skeleton/static/404.html +16 -0
- data/templates/skeleton/static/500.html +16 -0
- data/templates/skeleton/static/css/style.css +32 -0
- data/templates/skeleton/static/favicon.ico +0 -0
- data/templates/skeleton/static/js/application.js +1 -0
- data/templates/skeleton/static/js/jquery-1.3.min.js +19 -0
- data/templates/skeleton/static/robots.txt +5 -0
- data/templates/skeleton/test/fixtures/setup.rb +6 -0
- data/templates/skeleton/test/setup.rb +33 -0
- data/test/doozer_test.rb +7 -0
- data/test/test_helper.rb +10 -0
- metadata +126 -0
@@ -0,0 +1,60 @@
|
|
1
|
+
module Paginate
|
2
|
+
|
3
|
+
class InvalidPage < ArgumentError
|
4
|
+
def initialize(page, page_num)
|
5
|
+
super "#{page.inspect} given as value, which translates to '#{page_num}' as page number"
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class Collection < Array
|
10
|
+
attr_reader :current_page, :per_page, :total_entries, :total_pages
|
11
|
+
|
12
|
+
def initialize(page, per_page, total = nil)
|
13
|
+
@current_page = page.to_i
|
14
|
+
raise InvalidPage.new(page, @current_page) if @current_page < 1
|
15
|
+
@per_page = per_page.to_i
|
16
|
+
raise ArgumentError, "`per_page` setting cannot be less than 1 (#{@per_page} given)" if @per_page < 1
|
17
|
+
|
18
|
+
self.total_entries = total if total
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.create(page, per_page, total = nil)
|
22
|
+
pager = new(page, per_page, total)
|
23
|
+
yield pager
|
24
|
+
pager
|
25
|
+
end
|
26
|
+
|
27
|
+
def out_of_bounds?
|
28
|
+
current_page > total_pages
|
29
|
+
end
|
30
|
+
|
31
|
+
def offset
|
32
|
+
(current_page - 1) * per_page
|
33
|
+
end
|
34
|
+
|
35
|
+
def previous_page
|
36
|
+
current_page > 1 ? (current_page - 1) : nil
|
37
|
+
end
|
38
|
+
|
39
|
+
def next_page
|
40
|
+
current_page < total_pages ? (current_page + 1) : nil
|
41
|
+
end
|
42
|
+
|
43
|
+
def total_entries=(number)
|
44
|
+
@total_entries = number.to_i
|
45
|
+
@total_pages = (@total_entries / per_page.to_f).ceil
|
46
|
+
end
|
47
|
+
|
48
|
+
def replace(array)
|
49
|
+
result = super
|
50
|
+
|
51
|
+
# The collection is shorter then page limit? Rejoice, because
|
52
|
+
# then we know that we are on the last page!
|
53
|
+
if total_entries.nil? and length < per_page and (current_page == 1 or length > 0)
|
54
|
+
self.total_entries = offset + length
|
55
|
+
end
|
56
|
+
|
57
|
+
result
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
module Paginate
|
2
|
+
module Finder
|
3
|
+
|
4
|
+
def self.included(base)
|
5
|
+
base.extend ClassMethods
|
6
|
+
class << base
|
7
|
+
# alias_method_chain :method_missing, :paginate
|
8
|
+
# # alias_method_chain :find_every, :paginate
|
9
|
+
define_method(:per_page) { 30 } unless respond_to?(:per_page)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
module ClassMethods
|
14
|
+
|
15
|
+
def paginate(*args)
|
16
|
+
options = args.pop
|
17
|
+
page, per_page, total_entries = paginate_parse_options(options)
|
18
|
+
|
19
|
+
finder = (options[:finder] || 'find').to_s
|
20
|
+
|
21
|
+
if finder == 'find'
|
22
|
+
# an array of IDs may have been given:
|
23
|
+
total_entries ||= (Array === args.first and args.first.size)
|
24
|
+
# :all is implicit
|
25
|
+
args.unshift(:all) if args.empty?
|
26
|
+
end
|
27
|
+
|
28
|
+
Paginate::Collection.create(page, per_page, total_entries) do |pager|
|
29
|
+
count_options = options.except :page, :per_page, :total_entries, :finder
|
30
|
+
find_options = count_options.except(:count).update(:offset => pager.offset, :limit => pager.per_page)
|
31
|
+
|
32
|
+
args << find_options
|
33
|
+
# @options_from_last_find = nil
|
34
|
+
pager.replace(send(finder, *args) { |*a| yield(*a) if block_given? })
|
35
|
+
|
36
|
+
# magic counting for user convenience:
|
37
|
+
pager.total_entries = paginate_count(count_options, args, finder) unless pager.total_entries
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
def paginate_parse_options(options)
|
44
|
+
raise ArgumentError, 'parameter hash expected' unless options.respond_to? :symbolize_keys
|
45
|
+
options = options.symbolize_keys
|
46
|
+
raise ArgumentError, ':page parameter required' unless options.key? :page
|
47
|
+
|
48
|
+
if options[:count] and options[:total_entries]
|
49
|
+
raise ArgumentError, ':count and :total_entries are mutually exclusive'
|
50
|
+
end
|
51
|
+
|
52
|
+
page = options[:page] || 1
|
53
|
+
per_page = options[:per_page] || self.per_page
|
54
|
+
total = options[:total_entries]
|
55
|
+
[page, per_page, total]
|
56
|
+
end
|
57
|
+
|
58
|
+
# Does the not-so-trivial job of finding out the total number of entries
|
59
|
+
# in the database. It relies on the ActiveRecord +count+ method.
|
60
|
+
def paginate_count(options, args, finder)
|
61
|
+
excludees = [:count, :order, :limit, :offset, :readonly]
|
62
|
+
excludees << :from unless ActiveRecord::Calculations::CALCULATIONS_OPTIONS.include?(:from)
|
63
|
+
|
64
|
+
# we may be in a model or an association proxy
|
65
|
+
klass = (@owner and @reflection) ? @reflection.klass : self
|
66
|
+
|
67
|
+
# Use :select from scope if it isn't already present.
|
68
|
+
options[:select] = scope(:find, :select) unless options[:select]
|
69
|
+
|
70
|
+
if options[:select] and options[:select] =~ /^\s*DISTINCT\b/i
|
71
|
+
# Remove quoting and check for table_name.*-like statement.
|
72
|
+
if options[:select].gsub('`', '') =~ /\w+\.\*/
|
73
|
+
options[:select] = "DISTINCT #{klass.table_name}.#{klass.primary_key}"
|
74
|
+
end
|
75
|
+
else
|
76
|
+
excludees << :select # only exclude the select param if it doesn't begin with DISTINCT
|
77
|
+
end
|
78
|
+
|
79
|
+
# count expects (almost) the same options as find
|
80
|
+
count_options = options.except *excludees
|
81
|
+
|
82
|
+
# merge the hash found in :count
|
83
|
+
# this allows you to specify :select, :order, or anything else just for the count query
|
84
|
+
count_options.update options[:count] if options[:count]
|
85
|
+
|
86
|
+
# forget about includes if they are irrelevant (Rails 2.1)
|
87
|
+
# if count_options[:include] and
|
88
|
+
# klass.private_methods.include_method?(:references_eager_loaded_tables?) and
|
89
|
+
# !klass.send(:references_eager_loaded_tables?, count_options)
|
90
|
+
# count_options.delete :include
|
91
|
+
# end
|
92
|
+
|
93
|
+
# we may have to scope ...
|
94
|
+
counter = Proc.new { count(count_options) }
|
95
|
+
|
96
|
+
count = if finder.index('find_') == 0 and klass.respond_to?(scoper = finder.sub('find', 'with'))
|
97
|
+
# scope_out adds a 'with_finder' method which acts like with_scope, if it's present
|
98
|
+
# then execute the count with the scoping provided by the with_finder
|
99
|
+
send(scoper, &counter)
|
100
|
+
# elsif finder =~ /^find_(all_by|by)_([_a-zA-Z]\w*)$/
|
101
|
+
# # extract conditions from calls like "paginate_by_foo_and_bar"
|
102
|
+
# attribute_names = $2.split('_and_')
|
103
|
+
# conditions = construct_attributes_from_arguments(attribute_names, args)
|
104
|
+
# with_scope(:find => { :conditions => conditions }, &counter)
|
105
|
+
else
|
106
|
+
counter.call
|
107
|
+
end
|
108
|
+
|
109
|
+
count.respond_to?(:length) ? count.length : count
|
110
|
+
end
|
111
|
+
|
112
|
+
|
113
|
+
end # ClassMethods
|
114
|
+
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Paginate
|
2
|
+
module ViewHelpers
|
3
|
+
# default options that can be overridden on the global level
|
4
|
+
@@pagination_options = {
|
5
|
+
:class => 'pagination',
|
6
|
+
:previous_label => '« Previous',
|
7
|
+
:next_label => 'Next »',
|
8
|
+
:inner_window => 4, # links around the current page
|
9
|
+
:outer_window => 1, # links around beginning and end
|
10
|
+
:separator => ' ', # single space is friendly to spiders and non-graphic browsers
|
11
|
+
:param_name => :page,
|
12
|
+
:params => {},
|
13
|
+
:page_links => true,
|
14
|
+
:container => true,
|
15
|
+
:debug => false
|
16
|
+
}
|
17
|
+
mattr_reader :pagination_options
|
18
|
+
|
19
|
+
def paginate(collection, options={})
|
20
|
+
#Collection => :current_page, :per_page, :total_entries, :total_pages
|
21
|
+
opt = @@pagination_options
|
22
|
+
opt.update(options)
|
23
|
+
out=[]
|
24
|
+
if opt[:debug]
|
25
|
+
out.push("current_page:#{collection.current_page} / ")
|
26
|
+
out.push("per_page:#{collection.per_page} / ")
|
27
|
+
out.push("total_entries:#{collection.total_entries} / ")
|
28
|
+
out.push("total_pages:#{collection.total_pages} <br />")
|
29
|
+
end
|
30
|
+
out.push("<div class=\"pagination_container\">") if opt[:container]
|
31
|
+
out.push(link(opt[:previous_label], {:page=>collection.previous_page}.update(opt[:params]), {:class=>opt[:class]}) ) if collection.previous_page
|
32
|
+
out.push(link(opt[:next_label], {:page=>collection.next_page}.update(opt[:params]), {:class=>opt[:class]}) ) if collection.next_page
|
33
|
+
out.push("</div>") if opt[:container]
|
34
|
+
return out.join(opt[:separator])
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# = Doozer Paginate
|
2
|
+
# This code was lifted (i mean...ported) from the WillPaginate gem for ActiveRecord with a few modifications.
|
3
|
+
#
|
4
|
+
# Not supported by this plugin but in WillPAginate:
|
5
|
+
# * Page numbers between 'Previous' and 'Next' links
|
6
|
+
# * NamedScopes
|
7
|
+
#
|
8
|
+
# See http://wiki.github.com/mislav/will_paginate for more details on useage and license.
|
9
|
+
require "#{PAGINATE_PLUGIN_ROOT}/paginate/collection"
|
10
|
+
module Paginate
|
11
|
+
class << self
|
12
|
+
def enable_activerecord
|
13
|
+
return if ActiveRecord::Base.respond_to? :paginate
|
14
|
+
require "#{PAGINATE_PLUGIN_ROOT}/paginate/finder"
|
15
|
+
ActiveRecord::Base.send :include, Paginate::Finder
|
16
|
+
end
|
17
|
+
def enable_view_helpers
|
18
|
+
# return if Doozer::Initializer.respond_to? :paginate
|
19
|
+
require "#{PAGINATE_PLUGIN_ROOT}/paginate/view_helpers"
|
20
|
+
Doozer::Controller.send :include, Paginate::ViewHelpers
|
21
|
+
Doozer::Partial.send :include, Paginate::ViewHelpers
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Enable ActiveRecord if it's defined
|
27
|
+
Paginate.enable_activerecord if defined? ActiveRecord
|
28
|
+
|
29
|
+
# Load the View Helpers if Doozer::Initializer is loaded
|
30
|
+
Doozer::Initializer.before_rackup do | config |
|
31
|
+
Paginate.enable_view_helpers
|
32
|
+
end if defined? Doozer::Initializer
|
@@ -0,0 +1,37 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'rubygems'
|
3
|
+
require 'doozer'
|
4
|
+
|
5
|
+
#--load initializers
|
6
|
+
# require 'doozer/initializer'
|
7
|
+
|
8
|
+
#--boot it up
|
9
|
+
Doozer::Initializer.boot(env)
|
10
|
+
|
11
|
+
#--hookup the logger for production only since the base rackup builder doesn't load it. this avoids double logging in development
|
12
|
+
use Rack::CommonLogger, Doozer::Configs.logger if Doozer::Configs.rack_env == :deployment
|
13
|
+
|
14
|
+
#--map root to doozer
|
15
|
+
map "/" do
|
16
|
+
# use Rack::ShowExceptions
|
17
|
+
if Doozer::Configs.rack_env != :deployment
|
18
|
+
use Rack::Reloader, secs=1
|
19
|
+
end
|
20
|
+
|
21
|
+
use Rack::Static, {:urls => Doozer::Configs.app["static_urls"], :root => "#{Dir.pwd}/#{Doozer::Configs.app["static_root"]}"} if Doozer::Configs.app
|
22
|
+
|
23
|
+
use Rack::Session::Cookie, :key => 'rack.session',
|
24
|
+
:domain => '',
|
25
|
+
:path => '/',
|
26
|
+
:expire_after => 2592000
|
27
|
+
|
28
|
+
run Doozer::App.new(args=options)
|
29
|
+
end
|
30
|
+
|
31
|
+
#--stack additional rack apps
|
32
|
+
begin
|
33
|
+
require "#{Dir.pwd}/config/rack"
|
34
|
+
stack()
|
35
|
+
rescue => e
|
36
|
+
Doozer::Configs.logger.error(e)
|
37
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
"""
|
2
|
+
script to bootstrap the doozer/rackup/server.ru in test mode
|
3
|
+
since rackup doesn't call Rackup::Builder in test (in rackup this is 'none') mode
|
4
|
+
|
5
|
+
"""
|
6
|
+
config = 'doozer/rackup/server.ru'
|
7
|
+
env = :test
|
8
|
+
cfgfile = File.read(config)
|
9
|
+
if cfgfile[/^#\\(.*)/]
|
10
|
+
opts.parse! $1.split(/\s+/)
|
11
|
+
end
|
12
|
+
ru=[]
|
13
|
+
ru.push("options = {:Port => 5000, :Host => '127.0.0.1', :AccessLog => []}")
|
14
|
+
ru.push("app = Rack::Builder.new do")
|
15
|
+
ru.push("use Rack::CommonLogger")
|
16
|
+
ru.push(cfgfile)
|
17
|
+
ru.push("end.to_app")
|
18
|
+
ru.push("Rack::Handler::Mongrel.run app, :Port => 5000")
|
19
|
+
app = eval "Rack::Builder.new {( " + ru.join("\n") + "\n )}.to_app", nil, config
|
data/lib/doozer/route.rb
ADDED
@@ -0,0 +1,264 @@
|
|
1
|
+
require 'doozer/app'
|
2
|
+
|
3
|
+
module Doozer
|
4
|
+
module Routing
|
5
|
+
class Routes
|
6
|
+
@@parts=[] # stored as [route.name, route.path]
|
7
|
+
@@dict={} # route hash
|
8
|
+
@@cache={} # lookup for matches
|
9
|
+
@@magics=[] # hold raw magic routes before processing
|
10
|
+
@@inner_apps={} # holds the app dedicated to processing this path
|
11
|
+
|
12
|
+
def self.draw(&block)
|
13
|
+
# p "draw routes"
|
14
|
+
instance_eval(&block) if block_given?
|
15
|
+
|
16
|
+
# init magic routes :conrtoller/:action or just /:action with predefined :controller
|
17
|
+
# Routes.init_magic_routes
|
18
|
+
|
19
|
+
# sort routes here
|
20
|
+
@@parts.sort! do |a, b| a[1].length <=> b[1].length end
|
21
|
+
@@parts.reverse!
|
22
|
+
p "Routes drawn and sorted..."
|
23
|
+
# @@parts.each { | i | p i[1] }
|
24
|
+
end
|
25
|
+
def self.add(name=nil, path=nil, args=nil)
|
26
|
+
# p name
|
27
|
+
# p path
|
28
|
+
# p args.inspect
|
29
|
+
if not name.nil? and not path.nil? and not args.nil?
|
30
|
+
args = Routes::init_formats(args)
|
31
|
+
formats = args[:formats]
|
32
|
+
# p formats.inspect
|
33
|
+
for format in formats
|
34
|
+
args.delete(:formats)
|
35
|
+
if name != :magic
|
36
|
+
parts = [name, path, args]
|
37
|
+
# p parts.inspect
|
38
|
+
args[:format] = format
|
39
|
+
route = Doozer::Routing::Route.new(parts)
|
40
|
+
# p route.inspect
|
41
|
+
@@parts.push([route.name, route.path])
|
42
|
+
@@dict[route.name] = route
|
43
|
+
else
|
44
|
+
p "magic routes init turned off"
|
45
|
+
# Routes.magic(parts)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.init_formats(args)
|
52
|
+
formats = args[:formats]
|
53
|
+
formats = [] if formats.nil?
|
54
|
+
formats.push(:html) if not formats.include?(:html)
|
55
|
+
args[:formats] = formats
|
56
|
+
return args
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.get_by_name(name)
|
60
|
+
# p @@dict.inspect
|
61
|
+
return @@dict[name]
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.match(path)
|
65
|
+
# p path
|
66
|
+
# p @@cache.inspect
|
67
|
+
# return @@dict[@@cache[path]] if @@cache[path]
|
68
|
+
for part in @@parts
|
69
|
+
route = @@dict[part[0]]
|
70
|
+
# p route.inspect
|
71
|
+
if route.match(path)
|
72
|
+
# Routes.cache_request_path(route, path)
|
73
|
+
return route
|
74
|
+
end
|
75
|
+
end
|
76
|
+
return nil
|
77
|
+
end
|
78
|
+
|
79
|
+
def self.cache_request_path(route,path)
|
80
|
+
# p "route cache request path"
|
81
|
+
@@cache[path] = route.name
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.magic(route)
|
85
|
+
@@magics.push(route)
|
86
|
+
end
|
87
|
+
|
88
|
+
def self.init_magic_routes
|
89
|
+
@@controllers={}
|
90
|
+
controller_files = Dir.glob(File.join(File.dirname(__FILE__),'../app/controllers/*_controller.rb'))
|
91
|
+
|
92
|
+
if controller_files.length > 0
|
93
|
+
i=0
|
94
|
+
for f in controller_files
|
95
|
+
break if i==0 and f.index('application_controller.rb')
|
96
|
+
if f.index('application_controller.rb')
|
97
|
+
controller_files.insert(0, controller_files.delete(f))
|
98
|
+
break
|
99
|
+
end
|
100
|
+
i+=1
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
controller_files.each {|f|
|
105
|
+
require f
|
106
|
+
key = f.split("controllers/")[1].split("_controller.rb")[0]
|
107
|
+
if key.index("_")
|
108
|
+
value = key.split('_').each{ | k | k.capitalize! }.join('')
|
109
|
+
else
|
110
|
+
value = key.capitalize
|
111
|
+
end
|
112
|
+
@@controllers[key.to_sym] = "#{value}Controller"
|
113
|
+
# p "cache controller: #{key.to_sym}"
|
114
|
+
}
|
115
|
+
# p @@controllers.inspect
|
116
|
+
# grab all controllers
|
117
|
+
routes = []
|
118
|
+
dup_lu = {}
|
119
|
+
obj = Doozer::Controller
|
120
|
+
obj.public_instance_methods.each { | name | dup_lu[name]=''}
|
121
|
+
# p dup_lu.inspect
|
122
|
+
|
123
|
+
@@magics.each { | route |
|
124
|
+
path = route[1]
|
125
|
+
if path.index(':controller') and path.index(':action')
|
126
|
+
## loop all controller and then loop all #methods
|
127
|
+
@@controllers.each{ |key,value |
|
128
|
+
klass = Object.const_get(value)
|
129
|
+
methods = klass.public_instance_methods()
|
130
|
+
methods.push('index')
|
131
|
+
methods.uniq! # filter duplicate indexes
|
132
|
+
methods.each { | val |
|
133
|
+
if dup_lu[val].nil?
|
134
|
+
controller= route[2][:controller] || key.to_s
|
135
|
+
action = route[2][:action] || val
|
136
|
+
# p "#{controller}##{action}"
|
137
|
+
name = "#{controller}_#{action}".to_sym
|
138
|
+
new_path = path.gsub(/:controller/, controller).gsub(/:action/,action)
|
139
|
+
new_path = new_path.gsub(/\/index/) if new_path.endswith('/index')
|
140
|
+
new_path = "/#{new_path}" if not new_path =~ /^\//
|
141
|
+
add([name, new_path, {:controller=>controller, :action=>action, :status=>200, :formats=>route[2][:formats]}])
|
142
|
+
end
|
143
|
+
}
|
144
|
+
}
|
145
|
+
elsif path.index(':action') and not route[2][:controller].nil?
|
146
|
+
## loop all methods on this controller
|
147
|
+
#p "load route controller:" + @@controllers[route[2][:controller].to_sym].inspect
|
148
|
+
controller= route[2][:controller]
|
149
|
+
|
150
|
+
klass = Object.const_get(@@controllers[controller.to_sym])
|
151
|
+
methods = klass.public_instance_methods()
|
152
|
+
methods.push('index')
|
153
|
+
methods.uniq! # filter duplicate indexes
|
154
|
+
methods.each { | val |
|
155
|
+
if dup_lu[val].nil?
|
156
|
+
action = val
|
157
|
+
# p "#{controller}##{action}"
|
158
|
+
name = "#{controller}_#{action}".to_sym
|
159
|
+
new_path = path.gsub(/:action/,action)
|
160
|
+
new_path = new_path.gsub(/\/index/,'') if new_path =~ /\/index/
|
161
|
+
new_path = "/#{new_path}" if not new_path =~ /^\//
|
162
|
+
|
163
|
+
# p [name, new_path, {:controller=>controller, :action=>action, :status=>200}].inspect
|
164
|
+
add([name, new_path, {:controller=>controller, :action=>action, :status=>200, :formats=>route[2][:formats]}])
|
165
|
+
end
|
166
|
+
}
|
167
|
+
end
|
168
|
+
}
|
169
|
+
|
170
|
+
## make sure to route index to '/'
|
171
|
+
## loop route/methods pairs
|
172
|
+
# save new path for action controller
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
class Route
|
177
|
+
attr_accessor :name, :path, :controller, :action,
|
178
|
+
:layout, :status, :content_type, :tokens,
|
179
|
+
:grouping, :app, :format, :view, :view_path
|
180
|
+
def initialize(route)
|
181
|
+
#p "Doozer::Route#new: #{route}"
|
182
|
+
args = route[2]
|
183
|
+
@controller = args[:controller]
|
184
|
+
@action = args[:action]
|
185
|
+
@layout = (args[:layout]) ? args[:layout] : 'default'
|
186
|
+
@status = (args[:status]) ? args[:status] : 200
|
187
|
+
@app=args[:app]
|
188
|
+
@format = (args[:format]) ? args[:format] : :html
|
189
|
+
#@content_type = (args[:content_type]) ? args[:content_type] : 'text/html'
|
190
|
+
case @format
|
191
|
+
when :js
|
192
|
+
content_type = 'text/javascript'
|
193
|
+
when :xml
|
194
|
+
content_type = 'text/xml'
|
195
|
+
when :json
|
196
|
+
content_type = 'application/json'
|
197
|
+
when :rss
|
198
|
+
content_type = 'application/rss+xml'
|
199
|
+
when :atom
|
200
|
+
content_type = 'application/atom+xml'
|
201
|
+
else
|
202
|
+
content_type = 'text/html'
|
203
|
+
end
|
204
|
+
@content_type = content_type
|
205
|
+
@tokens = []
|
206
|
+
path = route[1]
|
207
|
+
path = '/' if path == ''
|
208
|
+
@path = (@format == :html) ? path : "#{path}.#{format}"
|
209
|
+
@name = (@format == :html) ? route[0] : "#{route[0]}_#{format.to_s}".to_sym
|
210
|
+
@layout = :none if @format != :html and @layout == 'default'
|
211
|
+
|
212
|
+
@view = "#{@action}_#{@format.to_s}"
|
213
|
+
@view_path = "#{@controller}/#{@action}.#{@format.to_s}.erb"
|
214
|
+
regify()
|
215
|
+
end
|
216
|
+
|
217
|
+
def regify
|
218
|
+
if (@path.index('/'))
|
219
|
+
grouping = []
|
220
|
+
url = @path.split('/')
|
221
|
+
for part in url
|
222
|
+
if /^:/.match(part)
|
223
|
+
token = part.gsub(/:/,'')
|
224
|
+
# part = '(?P<'+token+'>.)'
|
225
|
+
# part = '(\.*)'
|
226
|
+
# part = '(\w*)'
|
227
|
+
part = '([a-zA-Z0-9,-.%]*)' # this picks up all allowable route tokens (a-zA-Z0-9,-.%)
|
228
|
+
@tokens.push(token)
|
229
|
+
end
|
230
|
+
grouping.push(part)
|
231
|
+
end
|
232
|
+
out = "^#{grouping.join('/')}"
|
233
|
+
@grouping = Regexp.compile(out)
|
234
|
+
else
|
235
|
+
#handle default index route
|
236
|
+
@grouping = Regexp.compile("/")
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
def match(path)
|
241
|
+
# p "#{path} vs #{@path}"
|
242
|
+
# p path =~ @grouping
|
243
|
+
#short-circut for root
|
244
|
+
return false if path == '/' and @path != '/' #handles root condition
|
245
|
+
pass=(path =~ @grouping) == 0 ? true : false
|
246
|
+
# p @tokens.inspect if pass
|
247
|
+
if @tokens.empty?; pass=false if @path != path; end #handles root condition '/'
|
248
|
+
pass=false if path.split('/').length != @path.split('/').length #handles the root condition /:token
|
249
|
+
return pass
|
250
|
+
end
|
251
|
+
|
252
|
+
def extra_params(path)
|
253
|
+
hashish = {}
|
254
|
+
params = @grouping.match(path)
|
255
|
+
i = 1
|
256
|
+
for token in @tokens
|
257
|
+
hashish[token.to_sym] = params[i]
|
258
|
+
i += 1
|
259
|
+
end
|
260
|
+
return hashish
|
261
|
+
end
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|