equipment 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+
@@ -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
+