equipment 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.
@@ -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
+