dope 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +63 -0
- data/TODO +16 -0
- data/lib/dope/core/application.rb +185 -0
- data/lib/dope/core/context.rb +60 -0
- data/lib/dope/core/handler.rb +105 -0
- data/lib/dope/core/resource.rb +30 -0
- data/lib/dope/core/view.rb +13 -0
- data/lib/dope.rb +10 -0
- metadata +71 -0
data/Rakefile
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
|
2
|
+
require 'rubygems'
|
3
|
+
require 'rake/gempackagetask'
|
4
|
+
|
5
|
+
$LOAD_PATH.unshift('lib')
|
6
|
+
require 'dope'
|
7
|
+
|
8
|
+
spec = Gem::Specification.new do |s|
|
9
|
+
|
10
|
+
s.name = 'dope'
|
11
|
+
s.rubyforge_project = 'dope'
|
12
|
+
s.version = Dope::VERSION
|
13
|
+
s.author = Dope::AUTHORS.first
|
14
|
+
s.homepage = Dope::WEBSITE
|
15
|
+
s.summary = "A way to export Welo resources on Derailleur"
|
16
|
+
s.email = "crapooze@gmail.com"
|
17
|
+
s.platform = Gem::Platform::RUBY
|
18
|
+
|
19
|
+
s.files = [
|
20
|
+
'Rakefile',
|
21
|
+
'TODO',
|
22
|
+
'lib/dope.rb',
|
23
|
+
'lib/dope/core/application.rb',
|
24
|
+
'lib/dope/core/context.rb',
|
25
|
+
'lib/dope/core/handler.rb',
|
26
|
+
'lib/dope/core/resource.rb',
|
27
|
+
'lib/dope/core/view.rb',
|
28
|
+
]
|
29
|
+
|
30
|
+
s.require_path = 'lib'
|
31
|
+
s.bindir = 'bin'
|
32
|
+
s.executables = []
|
33
|
+
s.has_rdoc = true
|
34
|
+
end
|
35
|
+
|
36
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
37
|
+
pkg.need_tar = true
|
38
|
+
end
|
39
|
+
|
40
|
+
task :gem => ["pkg/#{spec.name}-#{spec.version}.gem"] do
|
41
|
+
puts "generated #{spec.version}"
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
desc "run an example"
|
46
|
+
task :example, :ex, :server, :port do |t, params|
|
47
|
+
path = "./example/#{params[:ex]}.rb"
|
48
|
+
servername = params[:server] || 'thin'
|
49
|
+
port = params[:port] || '3000'
|
50
|
+
if File.file? path
|
51
|
+
require path
|
52
|
+
require 'rack'
|
53
|
+
app = Rack::Builder.new {
|
54
|
+
run ExampleApplication
|
55
|
+
}
|
56
|
+
server = Rack::Handler.get(servername)
|
57
|
+
server.run(app, :Port => port.to_i)
|
58
|
+
else
|
59
|
+
puts "no such example: #{path}
|
60
|
+
use ls example to see the possibilities"
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
data/TODO
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
* specs
|
2
|
+
* static file handler
|
3
|
+
- create a class generator instead of current one and only one static approach
|
4
|
+
- better mime-types handling
|
5
|
+
* export resource models
|
6
|
+
- relations: get the data from the relationship:
|
7
|
+
-> currently values to iterate on are passed as parameters
|
8
|
+
-> we could get them from the relationship
|
9
|
+
-> ideally, the model could also be taken internally
|
10
|
+
- epithet
|
11
|
+
-> handler for epithet, current model handler uses match?, we will need to use
|
12
|
+
epithet_resource_match_params?
|
13
|
+
* use perspectives in the handlers
|
14
|
+
- possibility to export one resource with a limited number of perspectives?
|
15
|
+
* (unlikely) case which may break
|
16
|
+
- multiple nesting of similar resources => risk of parameter namespacing issue?
|
@@ -0,0 +1,185 @@
|
|
1
|
+
|
2
|
+
require 'derailleur'
|
3
|
+
require 'dope/core/handler'
|
4
|
+
autoload :Find, 'find'
|
5
|
+
|
6
|
+
module Dope
|
7
|
+
module Application
|
8
|
+
include Derailleur::Application
|
9
|
+
|
10
|
+
def get_resource_at_path(resource, path)
|
11
|
+
puts "R: #{path}"
|
12
|
+
get(path, ResourceHandler.new(resource))
|
13
|
+
end
|
14
|
+
|
15
|
+
def get_resource(resource, root='', ident=:default)
|
16
|
+
path = File.join(root, resource.path(ident))
|
17
|
+
get_resource_at_path(resource, path)
|
18
|
+
end
|
19
|
+
|
20
|
+
def unget_resource(resource, root='', ident=:default)
|
21
|
+
path = File.join(root, resource.path(ident))
|
22
|
+
unget(path)
|
23
|
+
end
|
24
|
+
|
25
|
+
def get_linked_resource(link, root='')
|
26
|
+
branch = link.to_s.sub(/^\.\//,'')
|
27
|
+
path = File.join(root, branch)
|
28
|
+
get_resource_at_path(link.to, path)
|
29
|
+
end
|
30
|
+
|
31
|
+
def unget_linked_resource(link, root='')
|
32
|
+
branch = link.to_s.sub(/^\.\//,'')
|
33
|
+
path = File.join(root, branch)
|
34
|
+
unget(path)
|
35
|
+
end
|
36
|
+
|
37
|
+
def get_resource_relation(resource, relname, root='', ident=:default)
|
38
|
+
rel = resource.relationship(relname)
|
39
|
+
raise ArgumentError, "no relationship: #{relname} for #{resource}" unless rel
|
40
|
+
link = resource.link_for_rel(rel)
|
41
|
+
path = File.join(root, resource.path(ident))
|
42
|
+
case link
|
43
|
+
when Welo::Link
|
44
|
+
get_linked_resource(link, path)
|
45
|
+
when Welo::LinksEnumerator
|
46
|
+
link.each do |l|
|
47
|
+
get_linked_resource(l, path)
|
48
|
+
end
|
49
|
+
else
|
50
|
+
raise RuntimeError, "unknown kind of link: #{link}"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def unget_resource_relation(resource, relname, root='', ident=:default)
|
55
|
+
rel = resource.relationship(relname)
|
56
|
+
raise ArgumentError, "no relationship: #{relname} for #{resource}" unless rel
|
57
|
+
link = resource.link_for_rel(rel)
|
58
|
+
path = File.join(root, resource.path(ident))
|
59
|
+
case link
|
60
|
+
when Welo::Link
|
61
|
+
unget_linked_resource(link, path)
|
62
|
+
when Welo::LinksEnumerator
|
63
|
+
link.each do |l|
|
64
|
+
unget_linked_resource(l, path)
|
65
|
+
end
|
66
|
+
else
|
67
|
+
raise RuntimeError, "unknown kind of link: #{link}"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def get_resource_model_at_path(model, ident, resources, path)
|
72
|
+
puts "M: #{path}"
|
73
|
+
get(path, ResourceModelHandler.new([model, ident, resources]))
|
74
|
+
end
|
75
|
+
|
76
|
+
def get_resource_model(model, resources, root='', ident=:default)
|
77
|
+
path = File.join(root, model.path_model(ident, "#{model.base_path}."))
|
78
|
+
get_resource_model_at_path(model, ident, resources, path)
|
79
|
+
end
|
80
|
+
|
81
|
+
def unget_resource_model(model, root='', ident=:default)
|
82
|
+
path = File.join(root, model.path_model(ident, "#{model.base_path}."))
|
83
|
+
unget(path)
|
84
|
+
end
|
85
|
+
|
86
|
+
def get_resource_nesting_model(resource, relname, model, resources, root='', ident=:default)
|
87
|
+
nesting = resource.nesting(relname)
|
88
|
+
raise ArgumentError, "no nesting: #{relname} for #{resource}" unless nesting
|
89
|
+
model_ident = nesting.identifier_sym
|
90
|
+
path = File.join(root, resource.path(ident))
|
91
|
+
get_resource_model(model, resources, path, model_ident)
|
92
|
+
end
|
93
|
+
|
94
|
+
def unget_resource_nesting_model(resource, relname, model, root='', ident=:default)
|
95
|
+
nesting = resource.nesting(relname)
|
96
|
+
raise ArgumentError, "no nesting: #{relname} for #{resource}" unless nesting
|
97
|
+
model_ident = nesting.identifier_sym
|
98
|
+
path = File.join(root, resource.path(ident))
|
99
|
+
unget_resource_model(model, path, model_ident)
|
100
|
+
end
|
101
|
+
|
102
|
+
def get_resource_epitheting_model(resource, label, model, resources, root='', ident=:default)
|
103
|
+
epithet = resource.epithet(label)
|
104
|
+
raise ArgumentError, "no epithet: #{label} for #{resource}" unless epithet
|
105
|
+
branch = resource.epithets(label, "#{model.base_path}.")
|
106
|
+
path = File.join(root, resource.path(ident), label.to_s, branch)
|
107
|
+
get_resource_epitheting_model_at_path(resource, model, label, resources, path)
|
108
|
+
end
|
109
|
+
|
110
|
+
def get_resource_epitheting_model_at_path(resource, model, label, resources, path)
|
111
|
+
puts "E: #{path}"
|
112
|
+
get(path, ResourceEpithetingModelHandler.new([model, label, resources, resource]))
|
113
|
+
end
|
114
|
+
|
115
|
+
# multi-level
|
116
|
+
|
117
|
+
def get_resource_relation_tree(resource, tree=[], root='', ident=:default)
|
118
|
+
path = if ident
|
119
|
+
File.join(root, resource.path(ident))
|
120
|
+
else
|
121
|
+
root
|
122
|
+
end
|
123
|
+
tree.each do |node|
|
124
|
+
relname, subtree = if node.is_a? Array
|
125
|
+
[node.first, node[1 .. -1]]
|
126
|
+
else
|
127
|
+
[node, []]
|
128
|
+
end
|
129
|
+
rel = resource.relationship(relname)
|
130
|
+
raise ArgumentError, "no relationship: #{relname} for #{resource}" unless rel
|
131
|
+
link = resource.link_for_rel(rel)
|
132
|
+
case link
|
133
|
+
when Welo::Link
|
134
|
+
get_linked_resource(link, path)
|
135
|
+
unless subtree.empty?
|
136
|
+
branch = link.to_s.sub(/^\.\//,'')
|
137
|
+
new_root = File.join(path, branch)
|
138
|
+
get_resource_relation_tree(link.to, subtree, new_root, nil)
|
139
|
+
end
|
140
|
+
when Welo::LinksEnumerator
|
141
|
+
link.each do |l|
|
142
|
+
get_linked_resource(l, path)
|
143
|
+
unless subtree.empty?
|
144
|
+
branch = link.to_s.sub(/^\.\//,'')
|
145
|
+
new_root = File.join(path, branch)
|
146
|
+
get_resource_relation_tree(link.to, subtree, new_root, nil)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
else
|
150
|
+
raise RuntimeError, "unknown kind of link: #{link}"
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def get_resource_relation_chain(resource, relnames=[], root='', ident=:default)
|
156
|
+
tree = []
|
157
|
+
last = tree
|
158
|
+
relnames.each do |sym|
|
159
|
+
ary = [sym]
|
160
|
+
last << ary
|
161
|
+
last = ary
|
162
|
+
end
|
163
|
+
get_resource_relation_tree(resource, tree, root, ident)
|
164
|
+
end
|
165
|
+
|
166
|
+
|
167
|
+
# file-system assets' handling
|
168
|
+
|
169
|
+
def static_dir(dir)
|
170
|
+
Find.find(dir) do |path|
|
171
|
+
if File.file?(path)
|
172
|
+
static_file path, dir
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def static_file(path, dir='')
|
178
|
+
route = path.sub(dir,'')
|
179
|
+
puts "F: #{route}"
|
180
|
+
StaticFileHandler.register(route, path)
|
181
|
+
get(route.sub(/\.\w+$/,''), StaticFileHandler)
|
182
|
+
rescue Derailleur::RouteObjectAlreadyPresent
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
|
2
|
+
autoload :Rack, 'rack/utils'
|
3
|
+
require 'derailleur/base/context'
|
4
|
+
require 'mime/types'
|
5
|
+
|
6
|
+
module Dope
|
7
|
+
class ResourceContext < Derailleur::Context
|
8
|
+
attr_reader :resource
|
9
|
+
def initialize(env, ctx, resource, &blk)
|
10
|
+
super(env, ctx, &blk)
|
11
|
+
@resource = resource
|
12
|
+
end
|
13
|
+
|
14
|
+
def perspective
|
15
|
+
(Rack::Utils.parse_query(env['QUERY_STRING'])['perspective'] || 'default').to_sym
|
16
|
+
end
|
17
|
+
|
18
|
+
def default_ext
|
19
|
+
'.html'
|
20
|
+
end
|
21
|
+
|
22
|
+
def default_content_type
|
23
|
+
'text/plain'
|
24
|
+
end
|
25
|
+
|
26
|
+
def ext
|
27
|
+
ret = extname
|
28
|
+
return default_ext if ret.empty?
|
29
|
+
ret
|
30
|
+
end
|
31
|
+
|
32
|
+
#XXX bitchy: all the if ext == '.html' may go to the code in the view
|
33
|
+
def content
|
34
|
+
e = ext
|
35
|
+
if e == '.html'
|
36
|
+
resource.view.render(self)
|
37
|
+
else
|
38
|
+
resource.to_ext(e, self)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def mime_types
|
43
|
+
MIME::Types.of(ext)
|
44
|
+
end
|
45
|
+
|
46
|
+
def content_type
|
47
|
+
m = mime_types
|
48
|
+
if m
|
49
|
+
m.first.to_s
|
50
|
+
else
|
51
|
+
default_content_type
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def headers
|
56
|
+
{'Content-Type' => content_type}
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
|
2
|
+
require 'dope/core/context'
|
3
|
+
require 'derailleur/core/handler'
|
4
|
+
require 'mime/types'
|
5
|
+
|
6
|
+
module Dope
|
7
|
+
class StaticFileHandler < Derailleur::RackHandler
|
8
|
+
class NoSuchStaticFile < Derailleur::NoSuchRoute
|
9
|
+
end
|
10
|
+
|
11
|
+
@registrations = {}
|
12
|
+
|
13
|
+
class << self
|
14
|
+
attr_reader :registrations
|
15
|
+
|
16
|
+
def register(route, path)
|
17
|
+
registrations[route] = path
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def path
|
22
|
+
self.class.registrations[env['PATH_INFO']]
|
23
|
+
end
|
24
|
+
|
25
|
+
def extname
|
26
|
+
File.extname(env['PATH_INFO'])
|
27
|
+
end
|
28
|
+
|
29
|
+
def mime_types
|
30
|
+
MIME::Types.of(path)
|
31
|
+
end
|
32
|
+
|
33
|
+
def content_type
|
34
|
+
m = mime_types
|
35
|
+
m.first.to_s if m
|
36
|
+
end
|
37
|
+
|
38
|
+
def to_rack_output
|
39
|
+
raise NoSuchStaticFile, "no such file (#{path}) for #{env['PATH_INFO']}" unless path and File.file?(path)
|
40
|
+
[200, {'Content-Type' => content_type}, File.read(path)]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class ResourceHandler < Derailleur::Handler
|
45
|
+
alias :resource :object
|
46
|
+
|
47
|
+
def to_rack_output
|
48
|
+
context = ResourceContext.new(env, ctx, resource)
|
49
|
+
context.result
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
class ResourceNotFound < Derailleur::NoSuchRoute
|
54
|
+
end
|
55
|
+
|
56
|
+
class ResourceModelHandler < Derailleur::Handler
|
57
|
+
def model
|
58
|
+
object[0]
|
59
|
+
end
|
60
|
+
|
61
|
+
def resources
|
62
|
+
object[2]
|
63
|
+
end
|
64
|
+
|
65
|
+
def prefix
|
66
|
+
":#{model.base_path}."
|
67
|
+
end
|
68
|
+
|
69
|
+
def to_rack_output
|
70
|
+
resource = find_resource
|
71
|
+
raise ResourceNotFound unless resource
|
72
|
+
ResourceHandler.new(resource, env, ctx).to_rack_output
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
class ResourceNestingModelHandler < ResourceModelHandler
|
77
|
+
def ident
|
78
|
+
object[1]
|
79
|
+
end
|
80
|
+
|
81
|
+
def find_resource
|
82
|
+
params = ctx['derailleur.params'].dup
|
83
|
+
params.delete(:splat)
|
84
|
+
resources.find{|r| r.match_params?(params, ident, prefix)}
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
class ResourceEpithetingModelHandler < ResourceModelHandler
|
89
|
+
def label
|
90
|
+
object[1]
|
91
|
+
end
|
92
|
+
|
93
|
+
def resource
|
94
|
+
object[3]
|
95
|
+
end
|
96
|
+
|
97
|
+
def find_resource
|
98
|
+
params = ctx['derailleur.params'].dup
|
99
|
+
params.delete(:splat)
|
100
|
+
found = resources.find do |r|
|
101
|
+
resource.epithet_resource_match_params?(r, params, label, prefix)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
|
2
|
+
require 'welo'
|
3
|
+
|
4
|
+
module Dope
|
5
|
+
autoload :View, 'dope/core/view'
|
6
|
+
module Resource
|
7
|
+
include Welo::Resource
|
8
|
+
def self.included(mod)
|
9
|
+
mod.extend Welo::Resource::ClassMethods
|
10
|
+
mod.extend ClassMethods
|
11
|
+
end
|
12
|
+
|
13
|
+
module ClassMethods
|
14
|
+
def view(val=nil)
|
15
|
+
if val
|
16
|
+
@view = val
|
17
|
+
end
|
18
|
+
@view
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def view_klass
|
23
|
+
self.class.view
|
24
|
+
end
|
25
|
+
|
26
|
+
def view
|
27
|
+
view_klass.new(self)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/dope.rb
ADDED
metadata
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dope
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 2
|
9
|
+
version: 0.0.2
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- crapooze
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2011-02-14 00:00:00 +01:00
|
18
|
+
default_executable:
|
19
|
+
dependencies: []
|
20
|
+
|
21
|
+
description:
|
22
|
+
email: crapooze@gmail.com
|
23
|
+
executables: []
|
24
|
+
|
25
|
+
extensions: []
|
26
|
+
|
27
|
+
extra_rdoc_files: []
|
28
|
+
|
29
|
+
files:
|
30
|
+
- Rakefile
|
31
|
+
- TODO
|
32
|
+
- lib/dope.rb
|
33
|
+
- lib/dope/core/application.rb
|
34
|
+
- lib/dope/core/context.rb
|
35
|
+
- lib/dope/core/handler.rb
|
36
|
+
- lib/dope/core/resource.rb
|
37
|
+
- lib/dope/core/view.rb
|
38
|
+
has_rdoc: true
|
39
|
+
homepage: https://github.com/crapooze/dope
|
40
|
+
licenses: []
|
41
|
+
|
42
|
+
post_install_message:
|
43
|
+
rdoc_options: []
|
44
|
+
|
45
|
+
require_paths:
|
46
|
+
- lib
|
47
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
48
|
+
none: false
|
49
|
+
requirements:
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
segments:
|
53
|
+
- 0
|
54
|
+
version: "0"
|
55
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
56
|
+
none: false
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
segments:
|
61
|
+
- 0
|
62
|
+
version: "0"
|
63
|
+
requirements: []
|
64
|
+
|
65
|
+
rubyforge_project: dope
|
66
|
+
rubygems_version: 1.3.7
|
67
|
+
signing_key:
|
68
|
+
specification_version: 3
|
69
|
+
summary: A way to export Welo resources on Derailleur
|
70
|
+
test_files: []
|
71
|
+
|