equipment 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/ProjectInfo +55 -0
- data/README +67 -0
- data/examples/basicauthtest.rb +59 -0
- data/examples/erubytest.rb +36 -0
- data/examples/flashtest.rb +46 -0
- data/examples/index.erb +9 -0
- data/examples/mounttest.rb +34 -0
- data/examples/ogtest.rb +41 -0
- data/examples/patchestest.rb +40 -0
- data/examples/sendfiletest.rb +29 -0
- data/lib/equipment.rb +195 -0
- data/lib/ext/app_util.rb +28 -0
- data/lib/ext/basic_auth.rb +71 -0
- data/lib/ext/controls.rb +26 -0
- data/lib/ext/eruby_view.rb +83 -0
- data/lib/ext/flash.rb +81 -0
- data/lib/ext/forms.rb +22 -0
- data/lib/ext/forward.rb +70 -0
- data/lib/ext/js_helpers.rb +50 -0
- data/lib/ext/mount.rb +152 -0
- data/lib/ext/og.rb +95 -0
- data/lib/ext/og_scaffold.rb +119 -0
- data/lib/ext/og_session.rb +76 -0
- data/lib/ext/patches.rb +130 -0
- data/lib/ext/ressource.rb +88 -0
- data/lib/ext/security.rb +83 -0
- data/lib/ext/sendfile.rb +84 -0
- data/lib/ext/template_view.rb +72 -0
- data/lib/ext/use_helper.rb +83 -0
- data/lib/ext/xml_view.rb +47 -0
- metadata +78 -0
data/lib/ext/og.rb
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'equipment'
|
2
|
+
require 'og'
|
3
|
+
|
4
|
+
module Ext
|
5
|
+
|
6
|
+
# Add some facilities for using Og in Camping. Stores the manager outside of
|
7
|
+
# the app so that you can reload it without sideeffects.
|
8
|
+
#
|
9
|
+
# == BUGS
|
10
|
+
#
|
11
|
+
# Does not work if app.create was defined before inclusion of that module
|
12
|
+
# and doesn't call `super`.
|
13
|
+
#
|
14
|
+
# == TODO
|
15
|
+
#
|
16
|
+
# * Change table names
|
17
|
+
# * Add E as Entity in Models
|
18
|
+
module Og
|
19
|
+
extend Equipment
|
20
|
+
|
21
|
+
module CClassMethods
|
22
|
+
# Useful for extenal control. Filled by .create.
|
23
|
+
attr_reader :og_manager
|
24
|
+
|
25
|
+
# Adds Og initialization when you start your app.
|
26
|
+
def create
|
27
|
+
@og_manager = ::Equipment::Og.setup(self) if self::Models.og
|
28
|
+
super
|
29
|
+
rescue NoMethodError, ArgumentError
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
module ModelsClassMethods
|
34
|
+
# Og setting.
|
35
|
+
#
|
36
|
+
# == Sqlite example
|
37
|
+
#
|
38
|
+
# MyApp::Models.og = { :store => :sqlite }
|
39
|
+
#
|
40
|
+
# == MySQL example
|
41
|
+
#
|
42
|
+
# MyApp::Models.og = {
|
43
|
+
# :store => :mysql,
|
44
|
+
# :name => 'data',
|
45
|
+
# :hostname => 'localhost',
|
46
|
+
# :user => 'root',
|
47
|
+
# :pass => '1234'
|
48
|
+
# }
|
49
|
+
attr_accessor :og
|
50
|
+
end
|
51
|
+
|
52
|
+
module Views
|
53
|
+
|
54
|
+
def _form_for(entity, opts)
|
55
|
+
entity = entity.new if entity.kind_of? Class
|
56
|
+
form({:method=>:post}.merge(opts)) do
|
57
|
+
entity.class.serializable_attributes.each do |prop|
|
58
|
+
unless /^oid$|_oid$/.match prop.to_s
|
59
|
+
label prop.to_s, :for=>prop; br
|
60
|
+
input :type=>:text, :name=>prop, :value=>entity.send(prop); br
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
input :type=>:hidden, :name=>'oid', :value=>entity.oid
|
65
|
+
input :type=>:submit
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
class << Og
|
73
|
+
# Returns a manager for you app.
|
74
|
+
def setup(app)
|
75
|
+
::Og.thread_safe = false
|
76
|
+
unless manager = managers[app.name]
|
77
|
+
manager = ::Og::Manager.new(app::Models.og || {})
|
78
|
+
managers[app.name] = manager
|
79
|
+
end
|
80
|
+
|
81
|
+
manager.unmanage_classes # needed ?
|
82
|
+
|
83
|
+
app::Models.constants.each do |model|
|
84
|
+
manager.manage_class(model) if manager.manageable?(model)
|
85
|
+
end
|
86
|
+
|
87
|
+
manager
|
88
|
+
end
|
89
|
+
|
90
|
+
def managers
|
91
|
+
@managers ||= {}
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
@@ -0,0 +1,119 @@
|
|
1
|
+
require 'equipment'
|
2
|
+
require 'ext/flash'
|
3
|
+
require 'ext/og'
|
4
|
+
require 'ext/ressource'
|
5
|
+
require 'ext/forms'
|
6
|
+
|
7
|
+
module Ext
|
8
|
+
|
9
|
+
# Allows Og Entities scaffolding. Not working yet.
|
10
|
+
#
|
11
|
+
# == Dependencies
|
12
|
+
#
|
13
|
+
# * Equipment
|
14
|
+
# * Og
|
15
|
+
# * Ressources
|
16
|
+
# * Flash
|
17
|
+
# * FormHelper
|
18
|
+
#
|
19
|
+
# == TODO
|
20
|
+
#
|
21
|
+
# * Not working. Finish this.
|
22
|
+
module OgScaffold
|
23
|
+
extend Equipment
|
24
|
+
depends_on Flash
|
25
|
+
depends_on Og
|
26
|
+
depends_on Ressource
|
27
|
+
depends_on Forms
|
28
|
+
|
29
|
+
module ControllersClassMethods
|
30
|
+
def scaffold(model, opts={})
|
31
|
+
defaults = {
|
32
|
+
:path => "/#{model.downcase}",
|
33
|
+
:name => "#{model}Scaffold"
|
34
|
+
}
|
35
|
+
opts = opts.merge(defaults)
|
36
|
+
|
37
|
+
klass = Class.new(OgScaffolder)
|
38
|
+
klass.path, klass.model = opts[:path], model
|
39
|
+
|
40
|
+
const_set(opts[:name], klass) if opts[:name]
|
41
|
+
|
42
|
+
klass
|
43
|
+
end
|
44
|
+
alias :S :scaffold
|
45
|
+
end
|
46
|
+
|
47
|
+
class OgScaffolder < Equipment::Ressource::RestController
|
48
|
+
class << self
|
49
|
+
attr_accessor :model
|
50
|
+
end
|
51
|
+
|
52
|
+
### CRUD ###
|
53
|
+
def create
|
54
|
+
m = model.new
|
55
|
+
input.fill(m) # TODO : Make this work
|
56
|
+
m.save
|
57
|
+
flash.errors = m.errors
|
58
|
+
redirect R(self, :show, m.oid)
|
59
|
+
end
|
60
|
+
|
61
|
+
def show(oid)
|
62
|
+
@model = model
|
63
|
+
@model_instance = model[oid]
|
64
|
+
render :show
|
65
|
+
end
|
66
|
+
|
67
|
+
def update(oid)
|
68
|
+
m = model[oid]
|
69
|
+
input.fill(m)
|
70
|
+
m.save
|
71
|
+
flash.errors = m.errors
|
72
|
+
redirect R(self, :show, m.oid)
|
73
|
+
end
|
74
|
+
|
75
|
+
def destroy(oid)
|
76
|
+
flash.errors = model.delete(oid)
|
77
|
+
redirect R(self)
|
78
|
+
end
|
79
|
+
|
80
|
+
### Views ###
|
81
|
+
|
82
|
+
def index
|
83
|
+
@model = model
|
84
|
+
render :index
|
85
|
+
end
|
86
|
+
|
87
|
+
def edit(oid)
|
88
|
+
@model = model
|
89
|
+
@model_instance = model[oid]
|
90
|
+
render :edit
|
91
|
+
end
|
92
|
+
|
93
|
+
private
|
94
|
+
def _model; self.class.model; end
|
95
|
+
def render(view, *a, &b) # look for local redefinition
|
96
|
+
if has_view?("#{self.class.name.downcase}_#{view}")
|
97
|
+
super("#{self.class.name.downcase}_#{view}", *a, &b)
|
98
|
+
else
|
99
|
+
super("og_scaffold_#{view}", *a, &b)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
module Views
|
105
|
+
def og_scaffold_index
|
106
|
+
form_for(@model)
|
107
|
+
end
|
108
|
+
|
109
|
+
def og_scaffold_show
|
110
|
+
print(@model_instance)
|
111
|
+
end
|
112
|
+
|
113
|
+
def og_scaffold_edit
|
114
|
+
form_for(@model, @model_instance)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'equipment'
|
2
|
+
require 'ext/og'
|
3
|
+
require 'glue/timestamped'
|
4
|
+
|
5
|
+
module Ext
|
6
|
+
|
7
|
+
# It's like Camping's Session but works with Og.
|
8
|
+
#
|
9
|
+
# TODO : Not working. Test this.
|
10
|
+
module OgSession
|
11
|
+
include Equipment
|
12
|
+
depends_on Og
|
13
|
+
|
14
|
+
module Models
|
15
|
+
class OgSession
|
16
|
+
attr_accessor :hashid, String
|
17
|
+
attr_accessor :ivars, Hash
|
18
|
+
|
19
|
+
is Glue::Timestamped
|
20
|
+
|
21
|
+
def []=(k, v)
|
22
|
+
self.ivars[k] = v
|
23
|
+
end
|
24
|
+
def [](k)
|
25
|
+
self.ivars[k] rescue nil
|
26
|
+
end
|
27
|
+
|
28
|
+
RAND_CHARS = [*'A'..'Z'] + [*'0'..'9'] + [*'a'..'z']
|
29
|
+
|
30
|
+
# Generates a new session ID and creates a row for the new session in the database.
|
31
|
+
def self.generate cookies
|
32
|
+
rand_max = RAND_CHARS.size
|
33
|
+
sid = (0...32).inject("") { |ret,_| ret << RAND_CHARS[rand(rand_max)] }
|
34
|
+
sess = self.create :hashid => sid, :ivars => Camping::H[]
|
35
|
+
cookies.camping_sid = sess.hashid
|
36
|
+
sess
|
37
|
+
end
|
38
|
+
|
39
|
+
# Gets the existing session based on the <tt>camping_sid</tt> available in cookies.
|
40
|
+
# If none is found, generates a new session.
|
41
|
+
def self.persist cookies
|
42
|
+
if cookies.camping_sid
|
43
|
+
session = self.find_by_hashid cookies.camping_sid
|
44
|
+
end
|
45
|
+
unless session
|
46
|
+
session = self.generate cookies
|
47
|
+
end
|
48
|
+
session
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
module Base
|
54
|
+
# This <tt>service</tt> method, when mixed into controllers, intercepts requests
|
55
|
+
# and wraps them with code to start and close the session. If a session isn't found
|
56
|
+
# in the database it is created. The <tt>@state</tt> variable is set and if it changes,
|
57
|
+
# it is saved back into the database.
|
58
|
+
def service(*a)
|
59
|
+
session = OgSession.persist @cookies
|
60
|
+
app = self.class.name.gsub(/^(\w+)::.+$/, '\1')
|
61
|
+
@state = (session[app] ||= Camping::H[])
|
62
|
+
hash_before = Marshal.dump(@state).hash
|
63
|
+
s = super(*a)
|
64
|
+
if session
|
65
|
+
hash_after = Marshal.dump(@state).hash
|
66
|
+
unless hash_before == hash_after
|
67
|
+
session[app] = @state
|
68
|
+
session.save
|
69
|
+
end
|
70
|
+
end
|
71
|
+
s
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
data/lib/ext/patches.rb
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
require 'equipment'
|
2
|
+
require 'ext/app_util'
|
3
|
+
|
4
|
+
module Ext
|
5
|
+
|
6
|
+
# Fixes some Camping defaults.
|
7
|
+
#
|
8
|
+
# == Dependencies
|
9
|
+
#
|
10
|
+
# * Equipment
|
11
|
+
# * AppUtil
|
12
|
+
#
|
13
|
+
module Patches
|
14
|
+
extend Equipment
|
15
|
+
depends_on AppUtil
|
16
|
+
|
17
|
+
# Removes method_missing, it makes things too complicated and debug
|
18
|
+
# unclear.
|
19
|
+
#
|
20
|
+
# Redefines the D method
|
21
|
+
def self.equip(app)
|
22
|
+
super
|
23
|
+
|
24
|
+
=begin
|
25
|
+
# remove method_missing, it makes things too complicated
|
26
|
+
if app::Base.method_defined? :method_missing
|
27
|
+
app::Base.send :undef_method, :method_missing
|
28
|
+
end
|
29
|
+
=end
|
30
|
+
|
31
|
+
=begin # not needed in 1.5
|
32
|
+
app::Controllers.module_eval do
|
33
|
+
# New D method which uses respond_to? instead of kind_of?(R)
|
34
|
+
def self.D(path)
|
35
|
+
puts "REQUEST: #{path}" if $DBG
|
36
|
+
constants.inject(nil) do |d,c|
|
37
|
+
k = const_get(c)
|
38
|
+
k.meta_def(:urls){["/#{c.downcase}"]}unless k.respond_to? :urls
|
39
|
+
d||([k, $~[1..-1]] if k.urls.find { |x| path =~ /^#{x}\/?$/ })
|
40
|
+
end||[self::NotFound, [path]]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
=end
|
44
|
+
|
45
|
+
# app::Controllers::NotFound.send :include, app::C, app::Base, app::Models
|
46
|
+
# app::Controllers::ServerError.send :include, app::C, app::Base, app::Models
|
47
|
+
end
|
48
|
+
module Base
|
49
|
+
|
50
|
+
# = Re-defined render
|
51
|
+
#
|
52
|
+
# The method_missing method is great but it ties the system too much to
|
53
|
+
# markaby. It makes also harder to debunk wrong methods since the call-
|
54
|
+
# stack is longer. Finally, it encourages to put the view in the
|
55
|
+
# controller, which is considered bad in MVC style (that's what ppl say)
|
56
|
+
#
|
57
|
+
# Render is a method that gets the view and puts a layout around it if
|
58
|
+
# found.
|
59
|
+
#
|
60
|
+
# Layout was renamed to _layout because it is a partial. Also partials
|
61
|
+
# don't use the layout feature (so layout doesn't have a layout)
|
62
|
+
def render(m, *a, &b)
|
63
|
+
str = view(m, *a, &b)
|
64
|
+
# allow content-negotiation
|
65
|
+
if m.to_s[0] != ?_ and has_view? :_layout
|
66
|
+
str = view(:_layout) { str }
|
67
|
+
end
|
68
|
+
str
|
69
|
+
end
|
70
|
+
|
71
|
+
# Temporary there until markaview is restored or replaced in
|
72
|
+
# camping-unabridged.
|
73
|
+
def markaview(m,*a,&b)
|
74
|
+
h=markaby
|
75
|
+
h.send m,*a,&b
|
76
|
+
h.to_s
|
77
|
+
end
|
78
|
+
|
79
|
+
# Useful if you want to implement your own view
|
80
|
+
alias :view :markaview
|
81
|
+
|
82
|
+
# Shortcut.
|
83
|
+
#
|
84
|
+
# This is useful if you want to implement your own view lookup
|
85
|
+
# (cf. TemplateView, ErubisView)
|
86
|
+
def has_view?(v)
|
87
|
+
/text\/html|\*\/\*/ =~ (env.HTTP_ACCEPT || '*/*') and
|
88
|
+
app::Views.method_defined? v # this is specific to markaby
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
=begin
|
93
|
+
module Controllers
|
94
|
+
# Changed usage of markaby template after removing method_missing.
|
95
|
+
class NotFound
|
96
|
+
def self.urls; [] end # do not serve urls directly
|
97
|
+
def get(p); r(404, app::Mab.new { h1 "Camping Problem!"; h2 "#{p} not found"}) end
|
98
|
+
end
|
99
|
+
|
100
|
+
class ServerError
|
101
|
+
def self.urls; [] end # do not serve urls directly
|
102
|
+
def get(k,m,e)
|
103
|
+
r(500, app::Mab.new do
|
104
|
+
h1 "Camping Problem!"
|
105
|
+
# if $DBG
|
106
|
+
h2 "#{k}.#{m}"
|
107
|
+
h3 "#{e.class} #{e.message}:"
|
108
|
+
ul { e.backtrace.each { |bt| li bt } }
|
109
|
+
# end
|
110
|
+
end.to_s
|
111
|
+
)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
=end
|
116
|
+
|
117
|
+
=begin
|
118
|
+
module CClassMethods
|
119
|
+
# Does noting. Allows calling super to chain initialization processes
|
120
|
+
# without having to check for NoMethodError.
|
121
|
+
def create
|
122
|
+
super
|
123
|
+
rescue NoMethodError, ArgumentError
|
124
|
+
end
|
125
|
+
end
|
126
|
+
=end
|
127
|
+
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'equipment'
|
2
|
+
|
3
|
+
module Ext
|
4
|
+
# Unfinished work.
|
5
|
+
#
|
6
|
+
# I'm currently implementing a Controller that works like rail's
|
7
|
+
# ActiveRessouce.
|
8
|
+
#
|
9
|
+
# == Dependencies
|
10
|
+
#
|
11
|
+
# * None
|
12
|
+
#
|
13
|
+
module Ressource
|
14
|
+
class RestController
|
15
|
+
class << self
|
16
|
+
attr_accessor :model, :path
|
17
|
+
|
18
|
+
def urls
|
19
|
+
@__urls ||= [
|
20
|
+
# POST GET POST POST
|
21
|
+
"#{path}/(create)", "#{path}/(show)/(\d+)", "#{path}/(update)/(\d+)", "#{path}/(destroy)/(\d+)",
|
22
|
+
"#{path}/(\d+)", "#{path}", # POST,GET,PUT,DELETE : rest methods
|
23
|
+
"#{path};(\w+)", "#{path}/(\d+);(\w+)" # POST,GET : forms
|
24
|
+
]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# GET method dispatching
|
29
|
+
def get(action, id)
|
30
|
+
if action.to_i > 0 #/id , /id;actions
|
31
|
+
id = 'show' unless id
|
32
|
+
send(id, action)
|
33
|
+
elsif id #/show/id
|
34
|
+
show(id)
|
35
|
+
else # ;actions
|
36
|
+
action = 'index' if action.empty?
|
37
|
+
send(action)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# POST method dispatching
|
42
|
+
def post(action, id)
|
43
|
+
if action.to_i > 0
|
44
|
+
id = id ? "_#{id}" : 'update'
|
45
|
+
send(id, action)
|
46
|
+
elsif id
|
47
|
+
send(action, id)
|
48
|
+
elsif action=='create'
|
49
|
+
create
|
50
|
+
else
|
51
|
+
send("_#{action}")
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def put(id); update(id); end
|
56
|
+
def delete(id); destroy(id); end
|
57
|
+
|
58
|
+
### CRUD operations ###
|
59
|
+
|
60
|
+
def create # POST
|
61
|
+
end
|
62
|
+
|
63
|
+
def show(id) # GET
|
64
|
+
end
|
65
|
+
|
66
|
+
def update(id) # PUT
|
67
|
+
redirect R(self, :show, id)
|
68
|
+
end
|
69
|
+
|
70
|
+
def destroy(id) # DELETE
|
71
|
+
redirect R(self, :index)
|
72
|
+
end
|
73
|
+
|
74
|
+
### Pages ###
|
75
|
+
|
76
|
+
def index
|
77
|
+
end
|
78
|
+
|
79
|
+
def new
|
80
|
+
end
|
81
|
+
|
82
|
+
def edit
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|