dope 0.0.2
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/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
|
+
|