runo 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.
- data/LICENSE +19 -0
- data/README.rdoc +120 -0
- data/bin/runo +35 -0
- data/lib/_error.rb +14 -0
- data/lib/_field.rb +260 -0
- data/lib/_i18n.rb +141 -0
- data/lib/_parser.rb +243 -0
- data/lib/_path.rb +86 -0
- data/lib/_storage/_storage.rb +213 -0
- data/lib/_storage/file.rb +200 -0
- data/lib/_storage/sequel.rb +174 -0
- data/lib/_storage/temp.rb +73 -0
- data/lib/_widget/action_create.rb +23 -0
- data/lib/_widget/action_login.rb +22 -0
- data/lib/_widget/action_signup.rb +16 -0
- data/lib/_widget/action_update.rb +16 -0
- data/lib/_widget/crumb.rb +24 -0
- data/lib/_widget/done.rb +16 -0
- data/lib/_widget/login.rb +25 -0
- data/lib/_widget/me.rb +31 -0
- data/lib/_widget/message.rb +51 -0
- data/lib/_widget/navi.rb +88 -0
- data/lib/_widget/submit.rb +49 -0
- data/lib/_widget/view_ym.rb +77 -0
- data/lib/_workflow/_workflow.rb +89 -0
- data/lib/_workflow/attachment.rb +50 -0
- data/lib/_workflow/blog.rb +28 -0
- data/lib/_workflow/contact.rb +23 -0
- data/lib/_workflow/forum.rb +26 -0
- data/lib/_workflow/register.rb +39 -0
- data/lib/meta/_meta.rb +20 -0
- data/lib/meta/group.rb +19 -0
- data/lib/meta/id.rb +59 -0
- data/lib/meta/owner.rb +21 -0
- data/lib/meta/timestamp.rb +118 -0
- data/lib/runo.rb +396 -0
- data/lib/scalar/checkbox.rb +68 -0
- data/lib/scalar/file.rb +144 -0
- data/lib/scalar/img.rb +112 -0
- data/lib/scalar/password.rb +58 -0
- data/lib/scalar/radio.rb +47 -0
- data/lib/scalar/select.rb +47 -0
- data/lib/scalar/text.rb +38 -0
- data/lib/scalar/textarea.rb +35 -0
- data/lib/scalar/textarea_pre.rb +14 -0
- data/lib/scalar/textarea_wiki.rb +173 -0
- data/lib/set/_set.rb +195 -0
- data/lib/set/dynamic.rb +177 -0
- data/lib/set/static.rb +102 -0
- data/lib/set/static_folder.rb +96 -0
- data/locale/en/index.po +242 -0
- data/locale/index.pot +243 -0
- data/locale/ja/index.po +242 -0
- data/locale/lazy_parser.rb +54 -0
- data/skel/config.ru +27 -0
- data/skel/skin/_users/00000000_frank-avatar.jpg +0 -0
- data/skel/skin/_users/00000000_frank-avatar_small.jpg +0 -0
- data/skel/skin/_users/00000000_frank.yaml +12 -0
- data/skel/skin/_users/00000000_root-avatar.jpg +0 -0
- data/skel/skin/_users/00000000_root-avatar_small.jpg +0 -0
- data/skel/skin/_users/00000000_root.yaml +11 -0
- data/skel/skin/_users/css/users.css +21 -0
- data/skel/skin/_users/css/users.less +25 -0
- data/skel/skin/_users/done.html +42 -0
- data/skel/skin/_users/index.html +46 -0
- data/skel/skin/_users/index.yaml +3 -0
- data/skel/skin/_users/summary.html +40 -0
- data/skel/skin/css/base.css +93 -0
- data/skel/skin/css/base.less +139 -0
- data/skel/skin/css/coax.css +199 -0
- data/skel/skin/css/coax.less +244 -0
- data/skel/skin/examples/blog/20091214_0001.yaml +8 -0
- data/skel/skin/examples/blog/20100630_0001.yaml +8 -0
- data/skel/skin/examples/blog/20100630_0002.yaml +14 -0
- data/skel/skin/examples/blog/20100701_0001.yaml +8 -0
- data/skel/skin/examples/blog/20100701_0002-a-20100701_0001-f.jpg +0 -0
- data/skel/skin/examples/blog/20100701_0002-a-20100701_0001-f_small.jpg +0 -0
- data/skel/skin/examples/blog/20100701_0002.yaml +19 -0
- data/skel/skin/examples/blog/frank/20100701_0001.yaml +10 -0
- data/skel/skin/examples/blog/frank/index.yaml +4 -0
- data/skel/skin/examples/blog/index.html +51 -0
- data/skel/skin/examples/blog/rss.xml +18 -0
- data/skel/skin/examples/contact/20100701_0001-file.txt +1 -0
- data/skel/skin/examples/contact/20100701_0001.yaml +15 -0
- data/skel/skin/examples/contact/20100701_0002.yaml +8 -0
- data/skel/skin/examples/contact/20100701_0003.yaml +9 -0
- data/skel/skin/examples/contact/index.html +47 -0
- data/skel/skin/examples/contact/js/contact.js +13 -0
- data/skel/skin/examples/contact/summary.html +54 -0
- data/skel/skin/examples/forum/20100701_0001.yaml +41 -0
- data/skel/skin/examples/forum/20100701_0002.yaml +25 -0
- data/skel/skin/examples/forum/index.html +68 -0
- data/skel/skin/examples/forum/summary.html +47 -0
- data/skel/skin/examples/index.html +75 -0
- data/skel/skin/index.html +41 -0
- data/skel/skin/js/base.js +50 -0
- data/t/locale/de/index.po +19 -0
- data/t/locale/en-GB/index.po +25 -0
- data/t/locale/ja/index.po +30 -0
- data/t/skin/_users/00000000_test.yaml +3 -0
- data/t/skin/_users/index.html +13 -0
- data/t/skin/foo/20091120_0001.yaml +7 -0
- data/t/skin/foo/bar/20091120_0001.yaml +5 -0
- data/t/skin/foo/bar/index.yaml +5 -0
- data/t/skin/foo/baz/css/baz.css +1 -0
- data/t/skin/foo/css/foo.css +1 -0
- data/t/skin/foo/index.html +14 -0
- data/t/skin/foo/index.yaml +7 -0
- data/t/skin/foo/not_css/foo.css +1 -0
- data/t/skin/foo/sub-20100306_0001.yaml +3 -0
- data/t/skin/index.yaml +3 -0
- data/t/skin/t_attachment/index.html +13 -0
- data/t/skin/t_contact/done.html +6 -0
- data/t/skin/t_contact/index.html +9 -0
- data/t/skin/t_file/index.html +16 -0
- data/t/skin/t_img/index.html +14 -0
- data/t/skin/t_img/test.jpg +0 -0
- data/t/skin/t_select/index.html +9 -0
- data/t/skin/t_store/index.html +9 -0
- data/t/skin/t_summary/20100326_0001.yaml +3 -0
- data/t/skin/t_summary/create.html +9 -0
- data/t/skin/t_summary/index.html +9 -0
- data/t/skin/t_summary/summary.html +9 -0
- data/t/t.rb +27 -0
- data/t/test_checkbox.rb +273 -0
- data/t/test_field.rb +330 -0
- data/t/test_file.rb +900 -0
- data/t/test_id.rb +215 -0
- data/t/test_img.rb +328 -0
- data/t/test_meta.rb +57 -0
- data/t/test_parser.rb +1266 -0
- data/t/test_password.rb +188 -0
- data/t/test_radio.rb +226 -0
- data/t/test_role.rb +249 -0
- data/t/test_runo.rb +742 -0
- data/t/test_runo_call.rb +1286 -0
- data/t/test_runo_i18n.rb +318 -0
- data/t/test_select.rb +182 -0
- data/t/test_set_complex.rb +527 -0
- data/t/test_set_dynamic.rb +1504 -0
- data/t/test_set_folder.rb +515 -0
- data/t/test_set_permit.rb +246 -0
- data/t/test_set_static.rb +445 -0
- data/t/test_storage.rb +915 -0
- data/t/test_text.rb +125 -0
- data/t/test_textarea.rb +138 -0
- data/t/test_timestamp.rb +473 -0
- data/t/test_workflow.rb +367 -0
- metadata +345 -0
data/LICENSE
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Copyright (c) 2010 Akira FUNAI <akira -at- funai -dot- com>
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a
|
|
4
|
+
copy of this software and associated documentation files (the "Software"),
|
|
5
|
+
to deal in the Software without restriction, including without limitation
|
|
6
|
+
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
7
|
+
and/or sell copies of the Software, and to permit persons to whom the
|
|
8
|
+
Software is furnished to do so, subject to the following conditions:
|
|
9
|
+
|
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
|
11
|
+
all copies or substantial portions of the Software.
|
|
12
|
+
|
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
16
|
+
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
18
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
19
|
+
DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
= Runo
|
|
2
|
+
|
|
3
|
+
Runo is the easiest web application framework ever.
|
|
4
|
+
You can make various apps such like blog, forum, contact form by putting single (or several) HTML file with a bit of special markups. The view rules. There is no model definition, no server restart, and no coding at all.
|
|
5
|
+
|
|
6
|
+
== Features
|
|
7
|
+
|
|
8
|
+
* Model / View / Controller defined dynamically by good old HTML.
|
|
9
|
+
* Any block tags (<ul>, <table> etc.) can be an "app", by adding a workflow class like "runo-blog".
|
|
10
|
+
* The contents inside the app tag will be the "model".
|
|
11
|
+
* The model is defined by special tags, like "$(foo = text 1..32)" or "$(bar = select a,b,c)".
|
|
12
|
+
* You can make nested apps inside an app (e.g. blog comments inside a blog entry).
|
|
13
|
+
* Authentication / Authorization / User admin are built in by default.
|
|
14
|
+
* Storage can be plain YAML files (default), or any RDB via Sequel.
|
|
15
|
+
* Runo itself is a Rack application.
|
|
16
|
+
|
|
17
|
+
== Quick Start
|
|
18
|
+
|
|
19
|
+
This is a quick tutorial for making a simple web application using Runo.
|
|
20
|
+
|
|
21
|
+
=== Step 1 - Install Runo
|
|
22
|
+
|
|
23
|
+
Open a command line terminal. Type:
|
|
24
|
+
|
|
25
|
+
gem install runo
|
|
26
|
+
|
|
27
|
+
If you want to make thumbnails for submitted images, you have to install QuickMagick as well.
|
|
28
|
+
http://rubyforge.org/projects/quickmagick/
|
|
29
|
+
|
|
30
|
+
=== Step 2 - Initialize a Runo Directory
|
|
31
|
+
|
|
32
|
+
In a command line terminal, go to an empty directory where you want to build Runo projects.
|
|
33
|
+
Then type:
|
|
34
|
+
|
|
35
|
+
runo init
|
|
36
|
+
|
|
37
|
+
This will create a "runo" directory, which includes:
|
|
38
|
+
|
|
39
|
+
runo/
|
|
40
|
+
config.ru
|
|
41
|
+
skin/
|
|
42
|
+
|
|
43
|
+
=== Step 3 - Start a Test Server
|
|
44
|
+
|
|
45
|
+
In the terminal, change to the newly created "runo" directory.
|
|
46
|
+
Type:
|
|
47
|
+
|
|
48
|
+
runo run
|
|
49
|
+
|
|
50
|
+
=== Step 4 - Try some examples
|
|
51
|
+
|
|
52
|
+
Now open this URL with your browser.
|
|
53
|
+
|
|
54
|
+
http://localhost:9292/
|
|
55
|
+
|
|
56
|
+
You will see the default homepage of Runo.
|
|
57
|
+
There is some links to examples such like Blog, Contact Form, Forum, etc. Just see what can be done by plain HTML files.
|
|
58
|
+
|
|
59
|
+
=== Step 5 - Create Your Own App
|
|
60
|
+
|
|
61
|
+
Let's call our app "fab".
|
|
62
|
+
It is a web-based forum where logged in users can submit their own articles, and everybody can read them.
|
|
63
|
+
We put links to signup / login at bottom of the app.
|
|
64
|
+
|
|
65
|
+
Create a new directory under runo/skin/:
|
|
66
|
+
|
|
67
|
+
mkdir skin/fab/
|
|
68
|
+
|
|
69
|
+
Then create a new HTML file with your favorite editor:
|
|
70
|
+
|
|
71
|
+
edit skin/fab/index.html
|
|
72
|
+
|
|
73
|
+
The content is: (You can just copy & paste, of course)
|
|
74
|
+
|
|
75
|
+
<html>
|
|
76
|
+
<head>
|
|
77
|
+
<title>fab forum</title>
|
|
78
|
+
<link rel="stylesheet" href="/css/base.css" type="text/css" media="screen" />
|
|
79
|
+
</head>
|
|
80
|
+
|
|
81
|
+
<body>
|
|
82
|
+
<h1><a href=".">fab forum</a></h1>
|
|
83
|
+
|
|
84
|
+
<ul id="main" class="runo-forum">
|
|
85
|
+
<!-- 1..5 desc may_preview -->
|
|
86
|
+
<li>
|
|
87
|
+
<h2>$(title = text 32 1..32)</h2>
|
|
88
|
+
<div>
|
|
89
|
+
$(content = textarea-pre 60*10 1..)
|
|
90
|
+
<div>by $(_owner) @ $(_timestamp)</div>
|
|
91
|
+
</div>
|
|
92
|
+
</li>
|
|
93
|
+
</ul>
|
|
94
|
+
|
|
95
|
+
<p>$(.action_signup)$(.me)</p>
|
|
96
|
+
</body>
|
|
97
|
+
</html>
|
|
98
|
+
|
|
99
|
+
=== Step 6 - That's it!
|
|
100
|
+
|
|
101
|
+
See the URL:
|
|
102
|
+
|
|
103
|
+
http://localhost:9292/fab/
|
|
104
|
+
|
|
105
|
+
You have just created your first app. Open a bottle of your favorite drink and make yourself comfortable.
|
|
106
|
+
When you need more complicated tricks, HTMLs under skin/examples/ will be your help. More detailed documents are on the way.
|
|
107
|
+
|
|
108
|
+
== Note on Patches/Pull Requests
|
|
109
|
+
|
|
110
|
+
* Fork the project.
|
|
111
|
+
* Make your feature addition or bug fix.
|
|
112
|
+
* Add tests for it. This is important so I don't break it in a
|
|
113
|
+
future version unintentionally.
|
|
114
|
+
* Commit, do not mess with rakefile, version, or history.
|
|
115
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
|
116
|
+
* Send me a pull request. Bonus points for topic branches.
|
|
117
|
+
|
|
118
|
+
== Copyright
|
|
119
|
+
|
|
120
|
+
Copyright (c) 2010 Akira FUNAI <akira -at- funai -dot- com>. See LICENSE for details.
|
data/bin/runo
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# encoding: UTF-8
|
|
3
|
+
|
|
4
|
+
# Author:: Akira FUNAI
|
|
5
|
+
# Copyright:: Copyright (c) 2009-2010 Akira FUNAI
|
|
6
|
+
|
|
7
|
+
require 'rubygems'
|
|
8
|
+
|
|
9
|
+
$LOAD_PATH.unshift(::File.expand_path('../lib',::File.dirname(__FILE__)))
|
|
10
|
+
require 'runo'
|
|
11
|
+
|
|
12
|
+
case ARGV.shift
|
|
13
|
+
when 'init'
|
|
14
|
+
runo_dir = ::File.expand_path './runo'
|
|
15
|
+
|
|
16
|
+
if ::File.exists? runo_dir
|
|
17
|
+
$stderr.puts "#{runo_dir} already exists."
|
|
18
|
+
exit 1
|
|
19
|
+
else
|
|
20
|
+
$stderr.puts "Setting up Runo files in #{runo_dir}..."
|
|
21
|
+
::FileUtils.cp_r(
|
|
22
|
+
::File.expand_path('../skel',Runo.libdir),
|
|
23
|
+
'./runo',
|
|
24
|
+
:verbose => :true
|
|
25
|
+
)
|
|
26
|
+
end
|
|
27
|
+
when 'run'
|
|
28
|
+
::Dir.chdir(File.exists?('./config.ru') ? '.' : './runo') {
|
|
29
|
+
$stderr.puts "Starting a server with Runo files in #{::File.expand_path '.'}..."
|
|
30
|
+
system('rackup',*ARGV)
|
|
31
|
+
}
|
|
32
|
+
else
|
|
33
|
+
$stderr.puts 'Usage: runo {init|run [Rack options]}'
|
|
34
|
+
exit 1
|
|
35
|
+
end
|
data/lib/_error.rb
ADDED
data/lib/_field.rb
ADDED
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
3
|
+
# Author:: Akira FUNAI
|
|
4
|
+
# Copyright:: Copyright (c) 2009 Akira FUNAI
|
|
5
|
+
|
|
6
|
+
require 'rubygems'
|
|
7
|
+
require 'rack/utils'
|
|
8
|
+
|
|
9
|
+
$KCODE = 'UTF8'
|
|
10
|
+
|
|
11
|
+
class Runo::Field
|
|
12
|
+
|
|
13
|
+
include Runo::I18n
|
|
14
|
+
|
|
15
|
+
DEFAULT_META = {}
|
|
16
|
+
|
|
17
|
+
def self.instance(meta = {})
|
|
18
|
+
k = meta[:klass].to_s.split(/-/).inject(Runo) {|c, name|
|
|
19
|
+
name = name.capitalize
|
|
20
|
+
c.const_get(name)
|
|
21
|
+
}
|
|
22
|
+
k.new(meta) if k < self
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def self.h(val)
|
|
26
|
+
Rack::Utils.escape_html val.to_s
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
attr_reader :action, :result
|
|
30
|
+
|
|
31
|
+
def initialize(meta = {})
|
|
32
|
+
@meta = self.class.const_get(:DEFAULT_META).merge meta
|
|
33
|
+
@val = val_cast(nil)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def inspect
|
|
37
|
+
caller.grep(/`inspect'/).empty? ? super : "<#{self.class} name=\"#{my[:name]}\">"
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def [](id, *arg)
|
|
41
|
+
respond_to?("meta_#{id}") ? __send__("meta_#{id}", *arg) : @meta[id]
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def []=(id, v)
|
|
45
|
+
@meta[id] = v
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def val
|
|
49
|
+
@val
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def item(*item_steps)
|
|
53
|
+
item_steps = item_steps.first if item_steps.first.is_a? ::Array
|
|
54
|
+
item_steps.empty? ? self : nil # scalar has no item
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def find_ancestor(&block)
|
|
58
|
+
f = self
|
|
59
|
+
block.call(f) ? (return f) : (f = f[:parent]) until f.nil?
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def meta_name
|
|
63
|
+
my[:parent] && !my[:parent].is_a?(Runo::Set::Static::Folder) ?
|
|
64
|
+
"#{my[:parent][:name]}-#{my[:id]}" : my[:id]
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def meta_full_name
|
|
68
|
+
my[:parent] ? "#{my[:parent][:full_name]}-#{my[:id]}" : my[:id]
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def meta_short_name
|
|
72
|
+
return '' if Runo.base && my[:full_name] == Runo.base[:full_name]
|
|
73
|
+
my[:parent] && Runo.base && my[:parent][:full_name] != Runo.base[:full_name] ?
|
|
74
|
+
"#{my[:parent][:short_name]}-#{my[:id]}" : my[:id]
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def meta_folder
|
|
78
|
+
find_ancestor {|f| f.is_a? Runo::Set::Static::Folder }
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def meta_sd
|
|
82
|
+
find_ancestor {|f| f.is_a? Runo::Set::Dynamic }
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def meta_client
|
|
86
|
+
Runo.client
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def meta_owner
|
|
90
|
+
@meta[:owner] || (my[:parent] ? my[:parent][:owner] : 'root')
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def meta_owners
|
|
94
|
+
(my[:parent] ? my[:parent][:owners] : ['root']) | @meta[:owner].to_a
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def meta_admins
|
|
98
|
+
(my[:parent] ? my[:parent][:admins] : ['root']) | @meta[:admin].to_a
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def meta_group
|
|
102
|
+
@meta[:group] || (my[:parent] ? my[:parent][:group] : [])
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def meta_roles
|
|
106
|
+
roles = 0
|
|
107
|
+
roles |= Runo::Workflow::ROLE_ADMIN if my[:admins].include? my[:client]
|
|
108
|
+
roles |= Runo::Workflow::ROLE_GROUP if my[:group].include? my[:client]
|
|
109
|
+
roles |= Runo::Workflow::ROLE_OWNER if my[:owner] == my[:client]
|
|
110
|
+
roles |= (Runo.client == 'nobody') ? Runo::Workflow::ROLE_NONE : Runo::Workflow::ROLE_USER
|
|
111
|
+
roles
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def permit?(action)
|
|
115
|
+
return false if action == :create && @result == :load
|
|
116
|
+
return true unless my[:sd]
|
|
117
|
+
return true if my[:sd].workflow.permit?(my[:roles], action)
|
|
118
|
+
return true if find_ancestor {|f| f[:id] =~ Runo::REX::ID_NEW } # descendant of a new item
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def default_action
|
|
122
|
+
return :read unless my[:sd]
|
|
123
|
+
actions = my[:sd].workflow.class.const_get(:PERM).keys - [:read, :create, :update]
|
|
124
|
+
([:read, :create, :update] + actions).find {|action| permit? action }
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def get(arg = {})
|
|
128
|
+
if permit_get? arg
|
|
129
|
+
_get(arg)
|
|
130
|
+
else
|
|
131
|
+
if arg[:action]
|
|
132
|
+
raise Runo::Error::Forbidden
|
|
133
|
+
else
|
|
134
|
+
arg[:action] = default_action
|
|
135
|
+
end
|
|
136
|
+
arg[:action] ? _get(arg) : 'xxx'
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def load_default
|
|
141
|
+
post :load_default
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def load(v = nil)
|
|
145
|
+
post :load, v
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def create(v = nil)
|
|
149
|
+
post :create, v
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def update(v = nil)
|
|
153
|
+
post :update, v
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def delete
|
|
157
|
+
post :delete
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def post(action, v = nil)
|
|
161
|
+
raise Runo::Error::Forbidden unless permit_post?(action, v)
|
|
162
|
+
|
|
163
|
+
if _post action, val_cast(v)
|
|
164
|
+
@result = (action == :load || action == :load_default) ? action : nil
|
|
165
|
+
@action = (action == :load || action == :load_default) ? nil : action
|
|
166
|
+
else
|
|
167
|
+
@result = nil
|
|
168
|
+
end
|
|
169
|
+
self
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def commit(type = :temp)
|
|
173
|
+
if valid?
|
|
174
|
+
@result = @action
|
|
175
|
+
@action = nil if type == :persistent
|
|
176
|
+
self
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def pending?
|
|
181
|
+
@action ? true : false
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def valid?
|
|
185
|
+
errors.empty?
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def empty?
|
|
189
|
+
val.to_s == ''
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def errors
|
|
193
|
+
[]
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
private
|
|
197
|
+
|
|
198
|
+
def my
|
|
199
|
+
self
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
def _get(arg)
|
|
203
|
+
_get_by_method arg
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
def _get_by_method(arg)
|
|
207
|
+
m = "_g_#{arg[:action]}"
|
|
208
|
+
respond_to?(m, true) ? __send__(m, arg) : _g_default(arg)
|
|
209
|
+
end
|
|
210
|
+
alias :_get_by_self_reference :_get_by_method
|
|
211
|
+
|
|
212
|
+
def _g_empty(arg)
|
|
213
|
+
end
|
|
214
|
+
alias :_g_login :_g_empty
|
|
215
|
+
alias :_g_done :_g_empty
|
|
216
|
+
alias :_g_message :_g_empty
|
|
217
|
+
|
|
218
|
+
def _g_default(arg)
|
|
219
|
+
Runo::Field.h val
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
def _g_errors(arg)
|
|
223
|
+
<<_html unless _g_valid? arg
|
|
224
|
+
<span class="error_message">#{errors.join "<br/>\n"}</span>
|
|
225
|
+
_html
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
def _g_class(arg)
|
|
229
|
+
c = self.class.to_s.sub('Runo::', '').gsub('::', '-').downcase
|
|
230
|
+
_g_valid?(arg) ? c : "#{c} error"
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
def _g_valid?(arg)
|
|
234
|
+
valid? || (arg[:action] == :create && !item.pending?)
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
def _post(action, v)
|
|
238
|
+
case action
|
|
239
|
+
when :load_default
|
|
240
|
+
@val = val_cast(my[:defaults] || my[:default])
|
|
241
|
+
when :load, :create, :update
|
|
242
|
+
@val = v if @val != v
|
|
243
|
+
when :delete
|
|
244
|
+
true
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
def permit_get?(arg)
|
|
249
|
+
permit? arg[:action]
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
def permit_post?(action, v)
|
|
253
|
+
action == :load || action == :load_default || permit?(action)
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
def val_cast(v)
|
|
257
|
+
v
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
end
|