lipa-web 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/NEWS.md +24 -0
- data/README.md +107 -43
- data/examples/many_objects.rb +33 -0
- data/lib/lipa/web.rb +3 -1
- data/lib/lipa/web/application.rb +12 -7
- data/lib/lipa/web/helpers.rb +3 -3
- data/lib/lipa/web/helpers/html.rb +40 -0
- data/lib/lipa/web/helpers/node.rb +120 -0
- data/lib/lipa/web/helpers/{html_helper.rb → response.rb} +6 -7
- data/lib/lipa/web/response.rb +49 -0
- data/lib/lipa/web/response/html.rb +90 -0
- data/lib/lipa/web/{helpers/node_helper.rb → response/json.rb} +27 -45
- data/lib/lipa/web/response/xml.rb +68 -0
- data/lib/lipa/web/version.rb +1 -1
- data/spec/application_spec.rb +6 -59
- data/spec/formats/html_spec.rb +62 -0
- data/spec/formats/json_spec.rb +36 -0
- data/spec/formats/xml_spec.rb +48 -0
- data/spec/server_spec.rb +4 -1
- data/spec/spec_helper.rb +26 -0
- metadata +50 -30
- data/lib/lipa/web/helpers/response_helper.rb +0 -128
@@ -25,14 +25,13 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
25
25
|
|
26
26
|
module Lipa
|
27
27
|
module Web
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
def link_to(node)
|
34
|
-
%(<a href="#{node.full_name}">#{node.name}</a>)
|
28
|
+
module Helpers
|
29
|
+
module Response
|
30
|
+
def read_template(path)
|
31
|
+
File.open(path).read
|
32
|
+
end
|
35
33
|
end
|
36
34
|
end
|
37
35
|
end
|
38
36
|
end
|
37
|
+
|
@@ -0,0 +1,49 @@
|
|
1
|
+
=begin
|
2
|
+
Web access to Lipa
|
3
|
+
|
4
|
+
Copyright (c) 2011 Aleksey Timin
|
5
|
+
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
7
|
+
a copy of this software and associated documentation files (the
|
8
|
+
'Software'), to deal in the Software without restriction, including
|
9
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
10
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
11
|
+
permit persons to whom the Software is furnished to do so, subject to
|
12
|
+
the following conditions:
|
13
|
+
|
14
|
+
The above copyright notice and this permission notice shall be
|
15
|
+
included in all copies or substantial portions of the Software.
|
16
|
+
|
17
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
18
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
19
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
20
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
21
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
22
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
23
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
24
|
+
=end
|
25
|
+
|
26
|
+
require "lipa/web/response/html"
|
27
|
+
require "lipa/web/response/json"
|
28
|
+
require "lipa/web/response/xml"
|
29
|
+
|
30
|
+
module Lipa
|
31
|
+
module Web
|
32
|
+
module Response
|
33
|
+
# Rendering node data in format
|
34
|
+
#
|
35
|
+
# @param node [Lipa::Node] node for rendering
|
36
|
+
# @param format of rendering
|
37
|
+
def respond(node, format)
|
38
|
+
case format.to_s
|
39
|
+
when "json"
|
40
|
+
JSON::response(node)
|
41
|
+
when "xml"
|
42
|
+
XML::response(node)
|
43
|
+
else
|
44
|
+
HTML::response(node)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
=begin
|
2
|
+
Web access to Lipa
|
3
|
+
|
4
|
+
Copyright (c) 2011 Aleksey Timin
|
5
|
+
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
7
|
+
a copy of this software and associated documentation files (the
|
8
|
+
'Software'), to deal in the Software without restriction, including
|
9
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
10
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
11
|
+
permit persons to whom the Software is furnished to do so, subject to
|
12
|
+
the following conditions:
|
13
|
+
|
14
|
+
The above copyright notice and this permission notice shall be
|
15
|
+
included in all copies or substantial portions of the Software.
|
16
|
+
|
17
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
18
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
19
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
20
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
21
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
22
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
23
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
24
|
+
=end
|
25
|
+
|
26
|
+
module Lipa
|
27
|
+
module Web
|
28
|
+
module Response
|
29
|
+
module HTML
|
30
|
+
extend Helpers::Response
|
31
|
+
|
32
|
+
def self.response(node)
|
33
|
+
header = {}
|
34
|
+
|
35
|
+
html = node.html
|
36
|
+
if html
|
37
|
+
if html[:block]
|
38
|
+
body = html[:block].call
|
39
|
+
else
|
40
|
+
case html[:render]
|
41
|
+
when :erb
|
42
|
+
body = render_erb(node)
|
43
|
+
header["Content-Type"] = "text/html"
|
44
|
+
when :text
|
45
|
+
body = html[:msg]
|
46
|
+
header["Content-Type"] = "text/plain"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
else
|
50
|
+
body = render_default_template(node)
|
51
|
+
end
|
52
|
+
[ 200, header, [body]]
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
def self.context(node)
|
57
|
+
node.instance_eval("def binding_for(#{node.attrs.keys.join(",")}) binding; end")
|
58
|
+
node.extend(Helpers::HTML)
|
59
|
+
block = block_given? ? Proc.new : nil
|
60
|
+
node.binding_for(*node.eval_attrs.values, &block)
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.render_default_template(node)
|
64
|
+
path = File.join(File.dirname(__FILE__), '..', 'views', 'node.html.erb') # default path
|
65
|
+
default_template = read_template(path)
|
66
|
+
|
67
|
+
path = File.join(File.dirname(__FILE__), '..', 'views', 'layout.html.erb') # default path
|
68
|
+
default_layout = read_template(path)
|
69
|
+
|
70
|
+
ERB.new(default_layout).result(
|
71
|
+
context(node) do
|
72
|
+
ERB.new(default_template).result(context(node))
|
73
|
+
end
|
74
|
+
)
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.render_erb(node)
|
78
|
+
template = read_template(node.html[:template])
|
79
|
+
root = node.root
|
80
|
+
if root.layout
|
81
|
+
layout = read_template(File.join(root.views, root.layout))
|
82
|
+
ERB.new(layout).result(context(node) { ERB.new(template).result(context(node)) })
|
83
|
+
else
|
84
|
+
ERB.new(template).result(context(node))
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -23,58 +23,40 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
23
23
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
24
24
|
=end
|
25
25
|
|
26
|
+
require "json"
|
26
27
|
module Lipa
|
27
28
|
module Web
|
28
|
-
module
|
29
|
+
module Response
|
30
|
+
module JSON
|
31
|
+
def self.response(node)
|
32
|
+
body = if node.json
|
33
|
+
j = {}
|
34
|
+
node.json[:block].call(j)
|
35
|
+
j.to_json
|
36
|
+
else
|
37
|
+
render_default_json(node)
|
38
|
+
end
|
29
39
|
|
30
|
-
|
31
|
-
|
32
|
-
# @param path [String] path about views directory
|
33
|
-
#
|
34
|
-
# @examnple
|
35
|
-
# node :page_1 do
|
36
|
-
# html erb("page.html.erb")
|
37
|
-
# end
|
38
|
-
def erb(path)
|
39
|
-
{ :render => :erb, :template => File.join(root.attrs[:views], path) }
|
40
|
-
end
|
40
|
+
[ 200, { "Content-Type" => "application/json" }, [body]]
|
41
|
+
end
|
41
42
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
# end
|
50
|
-
def text(msg)
|
51
|
-
{ :render => :text, :msg => msg }
|
52
|
-
end
|
43
|
+
private
|
44
|
+
def self.render_default_json(node)
|
45
|
+
j = {}
|
46
|
+
j[:name] = node.name
|
47
|
+
j[:full_name] = node.full_name
|
48
|
+
j[:parent] = json_link_to(node.parent)
|
49
|
+
j[:children] = node.children.values.each.map {|ch| json_link_to(ch) }
|
53
50
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
if opts.nil?
|
60
|
-
@html
|
61
|
-
else
|
62
|
-
@html = opts
|
51
|
+
node.eval_attrs.each_pair do |k,v|
|
52
|
+
j[k] = v.kind_of?(Lipa::Node) ? json_link_to(v) : v
|
53
|
+
end
|
54
|
+
|
55
|
+
j.to_json
|
63
56
|
end
|
64
|
-
end
|
65
57
|
|
66
|
-
|
67
|
-
|
68
|
-
# @example
|
69
|
-
# node :josn_1 do
|
70
|
-
# json { |j| j[:name] = name }
|
71
|
-
# end
|
72
|
-
# # => { "name":"json_1" }
|
73
|
-
def json(&block)
|
74
|
-
if block_given?
|
75
|
-
@json = {:block => block}
|
76
|
-
else
|
77
|
-
@json
|
58
|
+
def self.json_link_to(node)
|
59
|
+
{ :name => node.name, :full_name => node.full_name }
|
78
60
|
end
|
79
61
|
end
|
80
62
|
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
=begin
|
2
|
+
Web access to Lipa
|
3
|
+
|
4
|
+
Copyright (c) 2011 Aleksey Timin
|
5
|
+
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
7
|
+
a copy of this software and associated documentation files (the
|
8
|
+
'Software'), to deal in the Software without restriction, including
|
9
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
10
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
11
|
+
permit persons to whom the Software is furnished to do so, subject to
|
12
|
+
the following conditions:
|
13
|
+
|
14
|
+
The above copyright notice and this permission notice shall be
|
15
|
+
included in all copies or substantial portions of the Software.
|
16
|
+
|
17
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
18
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
19
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
20
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
21
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
22
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
23
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
24
|
+
=end
|
25
|
+
|
26
|
+
require "builder"
|
27
|
+
|
28
|
+
module Lipa
|
29
|
+
module Web
|
30
|
+
module Response
|
31
|
+
module XML
|
32
|
+
extend Helpers::Response
|
33
|
+
|
34
|
+
def self.response(node)
|
35
|
+
xml = Builder::XmlMarkup.new
|
36
|
+
if node.xml
|
37
|
+
if node.xml[:block]
|
38
|
+
node.xml[:block].call(xml)
|
39
|
+
else
|
40
|
+
case node.xml[:render]
|
41
|
+
when :builder
|
42
|
+
template = read_template(node.xml[:template])
|
43
|
+
end
|
44
|
+
eval(template, context(node,xml))
|
45
|
+
end
|
46
|
+
else
|
47
|
+
eval(default_template, context(node,xml))
|
48
|
+
end
|
49
|
+
|
50
|
+
[200, {"Content-Type" => "application/xml"}, [ xml.target!]]
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
def self.context(node,xml)
|
55
|
+
node.instance_eval("def binding_for(#{(node.attrs.keys << "xml").join(",")}) binding; end")
|
56
|
+
block = block_given? ? Proc.new : nil
|
57
|
+
node.binding_for(*(node.eval_attrs.values << xml), &block)
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.default_template
|
61
|
+
path = File.join(File.dirname(__FILE__), '..', 'views', 'node.builder') # default path
|
62
|
+
template = read_template(path)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
data/lib/lipa/web/version.rb
CHANGED
data/spec/application_spec.rb
CHANGED
@@ -1,36 +1,17 @@
|
|
1
|
-
require "
|
2
|
-
require "rack/test"
|
1
|
+
require File.join(File.dirname(__FILE__), "spec_helper")
|
3
2
|
|
4
3
|
describe Lipa::Web::Application do
|
5
4
|
include Rack::Test::Methods
|
6
5
|
|
7
6
|
before :each do
|
8
7
|
@srv = root :srv do
|
9
|
-
|
10
|
-
layout "layout.html.erb"
|
8
|
+
static_folder File.join(File.dirname(__FILE__), "public")
|
11
9
|
|
12
10
|
node :group do
|
13
11
|
node :test_node do
|
14
|
-
param_int 20
|
15
|
-
param_bool false
|
16
|
-
param_float 32.2
|
17
|
-
param_string "Hello"
|
18
|
-
param_time Time.new(2000,"jan",1,20,15,1,0)
|
19
|
-
param_proc run{5+3}
|
20
|
-
param_ref ref("../node_with_template")
|
21
|
-
|
22
12
|
node :child_1
|
23
13
|
node :child_2
|
24
14
|
end
|
25
|
-
|
26
|
-
node :node_with_template do
|
27
|
-
html erb("./my_template.html.erb")
|
28
|
-
json { |j| j[:name] = name }
|
29
|
-
end
|
30
|
-
|
31
|
-
node :node_greater do
|
32
|
-
html text("Hello world!")
|
33
|
-
end
|
34
15
|
end
|
35
16
|
end
|
36
17
|
end
|
@@ -56,44 +37,10 @@ describe Lipa::Web::Application do
|
|
56
37
|
last_response.body.should eql("Node is not existence")
|
57
38
|
end
|
58
39
|
|
59
|
-
it 'should
|
60
|
-
get "/
|
61
|
-
|
62
|
-
last_response.
|
63
|
-
last_response.body.gsub(/^\s*\n/, '').should == fixture("node.html")
|
64
|
-
end
|
65
|
-
|
66
|
-
it 'should render user html template' do
|
67
|
-
get "/group/node_with_template"
|
68
|
-
|
69
|
-
last_response.header['Content-Type'].should eql("text/html")
|
70
|
-
last_response.body.gsub(/^\s*\n/, '').should == fixture("node_with_template.html")
|
71
|
-
end
|
72
|
-
|
73
|
-
it 'should render text' do
|
74
|
-
get "/group/node_greater"
|
75
|
-
|
76
|
-
last_response.header['Content-Type'].should eql("text/plain")
|
77
|
-
last_response.body.should == "Hello world!"
|
78
|
-
end
|
79
|
-
|
80
|
-
it 'should response in default json format' do
|
81
|
-
get "group/test_node.json"
|
82
|
-
|
83
|
-
last_response.header['Content-Type'].should eql("application/json")
|
84
|
-
last_response.body.gsub(/\s*/,'').should == fixture("node.json").gsub(/\s*/,'')
|
85
|
-
end
|
86
|
-
|
87
|
-
it 'should response in default json format' do
|
88
|
-
get "group/node_with_template.json"
|
89
|
-
|
90
|
-
last_response.header['Content-Type'].should eql("application/json")
|
91
|
-
last_response.body.should == '{"name":"node_with_template"}'
|
92
|
-
end
|
93
|
-
|
94
|
-
def fixture(name)
|
95
|
-
path = File.join(File.dirname(__FILE__), "fixtures", name)
|
96
|
-
File.open(path).read.gsub(/^\s*\n/,'')
|
40
|
+
it 'should serve statics files in public folder' do
|
41
|
+
get "/css/style.css"
|
42
|
+
last_response.header["Content-Type"].should eql("text/css")
|
43
|
+
last_response.body.should eql(".h1 { color: #fff; }\n")
|
97
44
|
end
|
98
45
|
end
|
99
46
|
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "..", "spec_helper")
|
2
|
+
|
3
|
+
describe Lipa::Web::Application do
|
4
|
+
include Rack::Test::Methods
|
5
|
+
|
6
|
+
before :each do
|
7
|
+
@srv = root :srv do
|
8
|
+
views File.join(File.dirname(__FILE__), "views")
|
9
|
+
layout "layout.html.erb"
|
10
|
+
|
11
|
+
example_node
|
12
|
+
|
13
|
+
node :node_with_template do
|
14
|
+
html erb("./my_template.html.erb")
|
15
|
+
end
|
16
|
+
|
17
|
+
node :node_greater do
|
18
|
+
html text("Hello world!")
|
19
|
+
end
|
20
|
+
|
21
|
+
node :node_man_html do
|
22
|
+
say "Hello"
|
23
|
+
html { "<h1>#{say}</h1>" }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def app
|
29
|
+
Lipa::Web::Application.new(@srv)
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'should render default html template' do
|
33
|
+
get "/group/test_node"
|
34
|
+
|
35
|
+
last_response.header['Content-Type'].should eql( "text/html")
|
36
|
+
last_response.body.gsub(/^\s*\n/, '').should == fixture("node.html")
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should render custom html template' do
|
40
|
+
get "/node_with_template"
|
41
|
+
|
42
|
+
last_response.header['Content-Type'].should eql("text/html")
|
43
|
+
last_response.body.gsub(/^\s*\n/, '').should == fixture("node_with_template.html")
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should render text' do
|
47
|
+
get "/node_greater"
|
48
|
+
|
49
|
+
last_response.header['Content-Type'].should eql("text/plain")
|
50
|
+
last_response.body.should == "Hello world!"
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
it 'should have custom html response' do
|
55
|
+
get "/node_man_html"
|
56
|
+
|
57
|
+
last_response.header['Content-Type'].should eql("text/html")
|
58
|
+
last_response.body.should == '<h1>Hello</h1>'
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
|