casual-api 3.0.2 → 3.0.3
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.
- checksums.yaml +4 -4
- data/lib/casual-api.rb +1 -0
- data/lib/casual.rb +108 -85
- data/lib/config.ru +1 -2
- data/lib/dsl.rb +238 -189
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 45222dcf0822e0dd2a5435627f91147a2bc4a78e
|
4
|
+
data.tar.gz: 8ee0ef74b92e226dec8e3a307ffd23a9bc297e01
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 09d85af70129a29def81eb53d2a16dd106ede9e2470b7b84aca70effc69747bfb22f45012ffb95c7868d6c7476581821cd46ec3046c74554f1d6564903c785c2
|
7
|
+
data.tar.gz: 8a25f7ee7cf1a01882557418dcc3259b21a8aefe1582fb59dc481246e57cff7908fa29ef4cb2c6d53a000c771732678e9dda39a372384f5c24b8babda5ffb6b7
|
data/lib/casual-api.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require_relative './dsl.rb'
|
data/lib/casual.rb
CHANGED
@@ -1,102 +1,125 @@
|
|
1
1
|
require 'rack'
|
2
|
+
require 'tempfile'
|
2
3
|
require_relative './dsl.rb'
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
5
|
+
module CasualAPI
|
6
|
+
class ChildProcess
|
7
|
+
def initialize(action, parameters, session)
|
8
|
+
@action = action
|
9
|
+
@params = parameters
|
10
|
+
@session = session
|
11
|
+
end
|
12
|
+
|
13
|
+
def execute
|
14
|
+
check_parameter
|
15
|
+
obj = Action.fire @action, @params, @session
|
16
|
+
{
|
17
|
+
session: obj.session,
|
18
|
+
status_code: obj.status_code,
|
19
|
+
content_type: obj.content_type,
|
20
|
+
body: obj.body,
|
21
|
+
}
|
22
|
+
end
|
11
23
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
24
|
+
private
|
25
|
+
def check_parameter
|
26
|
+
check_satisfy_required_parameters
|
27
|
+
check_upload_file
|
28
|
+
end
|
29
|
+
def check_satisfy_required_parameters
|
30
|
+
unless @action[:parameters].all?{|k,v|@params[k] || !v[:required]}
|
31
|
+
raise InvalidParameterError, "Invalid parameter(s)"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
def check_upload_file
|
35
|
+
unless @action[:parameters].all?{|k,v|
|
36
|
+
next false if v[:is_file] ^ @params[k].is_a?(Hash)
|
37
|
+
next false if v[:as_file] && @params[k].is_a?(Hash)
|
38
|
+
true
|
39
|
+
}
|
40
|
+
raise InvalidParameterError, "Invalid parameter(s)"
|
41
|
+
end
|
42
|
+
end
|
20
43
|
end
|
21
|
-
end
|
22
44
|
|
23
45
|
|
24
|
-
# RackApp
|
25
|
-
class Casual
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
46
|
+
# RackApp
|
47
|
+
class Casual
|
48
|
+
def initialize(prefix, file, mode)
|
49
|
+
@prefix = prefix
|
50
|
+
@file = file
|
51
|
+
@mode = mode
|
52
|
+
end
|
31
53
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
54
|
+
def call(env)
|
55
|
+
@env = env
|
56
|
+
@req = Rack::Request.new(env)
|
57
|
+
fire_action
|
58
|
+
end
|
37
59
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
60
|
+
private
|
61
|
+
def fire_action
|
62
|
+
actions = parse_actions
|
63
|
+
action = detect_action actions
|
64
|
+
if action
|
65
|
+
begin
|
66
|
+
cp = ChildProcess.new(action, parameters, session)
|
67
|
+
result = cp.execute
|
68
|
+
@req.session['casual.session'] = result[:session]
|
69
|
+
res = Rack::Response.new(){|r|
|
70
|
+
r.status = result[:status_code]
|
71
|
+
r.write result[:body]
|
72
|
+
r['Content-Type'] = map_content_type(result[:content_type])
|
73
|
+
}
|
74
|
+
res.finish
|
75
|
+
rescue CommandError => ex
|
76
|
+
return [ex.status_code,
|
77
|
+
{ 'Content-Type' => map_content_type(ex.content_type) },
|
78
|
+
[ex.message]]
|
79
|
+
rescue => ex
|
80
|
+
[500, {}, ["Server Error"]]
|
81
|
+
end
|
82
|
+
else
|
83
|
+
[404, {}, []]
|
59
84
|
end
|
60
|
-
else
|
61
|
-
[404, {}, []]
|
62
85
|
end
|
63
|
-
end
|
64
86
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
87
|
+
def map_content_type(c)
|
88
|
+
{
|
89
|
+
txt: "text/plain;charset=utf-8",
|
90
|
+
html: "text/html;charset=utf-8",
|
91
|
+
}[c.to_sym] || c
|
92
|
+
end
|
71
93
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
94
|
+
def parse_actions
|
95
|
+
if @mode == "development" || !@actions
|
96
|
+
@actions = DSL.parse @file
|
97
|
+
else
|
98
|
+
@actions
|
99
|
+
end
|
77
100
|
end
|
78
|
-
end
|
79
101
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
102
|
+
def detect_action actions
|
103
|
+
path = request_path
|
104
|
+
_method = request_method
|
105
|
+
actions.detect{|act|
|
106
|
+
act[:method] == _method && make_path(act) == path
|
107
|
+
}
|
108
|
+
end
|
109
|
+
def make_path action
|
110
|
+
@prefix + (action[:domain] + action[:names]).compact.map{|p|p.to_s}.join('/')
|
111
|
+
end
|
112
|
+
def parameters
|
113
|
+
@req.params.map{|k,v| {k.to_sym => v} }.inject({}, :merge)
|
114
|
+
end
|
115
|
+
def session
|
116
|
+
@req.session['casual.session'] || {}
|
117
|
+
end
|
118
|
+
def request_method
|
119
|
+
@req.request_method.downcase.to_sym
|
120
|
+
end
|
121
|
+
def request_path
|
122
|
+
@req.path
|
123
|
+
end
|
101
124
|
end
|
102
125
|
end
|
data/lib/config.ru
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
require 'rack'
|
2
2
|
require 'yaml'
|
3
|
-
|
4
3
|
require_relative './casual.rb'
|
5
4
|
|
6
5
|
config = open("config.yaml"){|f|
|
@@ -17,7 +16,7 @@ use Rack::Session::Pool,
|
|
17
16
|
(config["routes"] || {}).each{|k,v|
|
18
17
|
map(k)do
|
19
18
|
run Rack::Cascade.new [
|
20
|
-
Casual.new(k, v, config["mode"])
|
19
|
+
CasualAPI::Casual.new(k, v, config["mode"])
|
21
20
|
]
|
22
21
|
end
|
23
22
|
}
|
data/lib/dsl.rb
CHANGED
@@ -1,228 +1,277 @@
|
|
1
1
|
require 'pp'
|
2
2
|
require 'securerandom'
|
3
|
+
require 'tempfile'
|
3
4
|
|
4
|
-
module
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
5
|
+
module CasualAPI
|
6
|
+
module BodyWriter
|
7
|
+
def self.extended obj
|
8
|
+
obj.instance_variable_set(:@body, "")
|
9
|
+
end
|
10
|
+
def write str
|
11
|
+
@body << str.to_s
|
12
|
+
end
|
13
|
+
def print str
|
14
|
+
@body << str.to_s
|
15
|
+
end
|
16
|
+
def puts str
|
17
|
+
@body << str.to_s << "\n"
|
18
|
+
end
|
19
|
+
def printf *p
|
20
|
+
@body << (sprintf *p)
|
21
|
+
end
|
22
|
+
def command cmd
|
23
|
+
write `#{cmd.to_s}`
|
24
|
+
end
|
25
|
+
def body
|
26
|
+
@body
|
27
|
+
end
|
28
|
+
def body=(value)
|
29
|
+
@body = value
|
30
|
+
end
|
22
31
|
end
|
23
|
-
|
24
|
-
|
32
|
+
|
33
|
+
class CommandError < StandardError
|
34
|
+
def content_type; :txt; end
|
35
|
+
def status_code; 400; end
|
25
36
|
end
|
26
|
-
|
27
|
-
@body = value
|
37
|
+
class InvalidParameterError < CommandError
|
28
38
|
end
|
29
|
-
end
|
30
39
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
40
|
+
module Action
|
41
|
+
def self.extended obj
|
42
|
+
obj.instance_variable_set(:@session, {})
|
43
|
+
obj.instance_variable_set(:@content_type, nil)
|
44
|
+
obj.instance_variable_set(:@status_code, 200)
|
45
|
+
obj.instance_variable_set(:@tempfiles, [])
|
46
|
+
end
|
37
47
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
obj.instance_variable_set(:@content_type, nil)
|
42
|
-
obj.instance_variable_set(:@status_code, 200)
|
43
|
-
obj.instance_variable_set(:@tempfiles, [])
|
44
|
-
end
|
48
|
+
def invalid_parameter *params
|
49
|
+
raise InvalidParameterError, "Invalid parameter(s): #{params.map{|p|p.to_s}.join(',')}"
|
50
|
+
end
|
45
51
|
|
46
|
-
|
47
|
-
|
48
|
-
|
52
|
+
def file? file
|
53
|
+
file.is_a? Hash
|
54
|
+
end
|
49
55
|
|
50
|
-
|
51
|
-
|
52
|
-
|
56
|
+
def tempfile file
|
57
|
+
Action.tempfile self, file
|
58
|
+
end
|
53
59
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
else
|
58
|
-
f = Tempfile.open(SecureRandom.hex(4))
|
59
|
-
f.write file
|
60
|
-
f.flush
|
61
|
-
@tempfiles.push f
|
62
|
-
f.path
|
60
|
+
def session_clear
|
61
|
+
session.clear
|
62
|
+
session = nil
|
63
63
|
end
|
64
|
-
end
|
65
64
|
|
66
|
-
|
67
|
-
session
|
68
|
-
|
69
|
-
|
65
|
+
def session; @session; end
|
66
|
+
def session=(value); @session = value; end
|
67
|
+
def content_type; @content_type; end
|
68
|
+
def tempfiles; @tempfiles; end
|
69
|
+
def status_code; @status_code; end
|
70
|
+
def content_type=(type); @content_type = type; end
|
71
|
+
def status_code=(code); @status_code = code; end
|
70
72
|
|
71
|
-
def session; @session; end
|
72
|
-
def session=(value); @session = value; end
|
73
|
-
def content_type; @content_type; end
|
74
|
-
def tempfiles; @tempfiles; end
|
75
|
-
def status_code; @status_code; end
|
76
|
-
def content_type=(type); @content_type = type; end
|
77
|
-
def status_code=(code); @status_code = code; end
|
78
|
-
|
79
|
-
|
80
|
-
def self.fire(action, params, session)
|
81
|
-
obj = Object
|
82
|
-
obj.extend Action
|
83
|
-
obj.extend BodyWriter
|
84
|
-
obj.content_type = action[:content_type] || :txt
|
85
|
-
obj.session = session
|
86
|
-
ps = action[:action].parameters.map{|_, name|
|
87
|
-
{name => params[name]}
|
88
|
-
}.inject({}, :merge)
|
89
|
-
result = execute(obj, ps, action[:action])
|
90
|
-
unless result[:executed]
|
91
|
-
raise InvalidParameterError, "Not given required parameter(s)"
|
92
|
-
end
|
93
|
-
obj.tempfiles.each{|f| f.close }
|
94
|
-
obj
|
95
|
-
end
|
96
73
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
74
|
+
def self.fire(action, params, session)
|
75
|
+
obj = Object
|
76
|
+
obj.extend Action
|
77
|
+
obj.extend BodyWriter
|
78
|
+
obj.content_type = action[:content_type] || :txt
|
79
|
+
obj.session = session
|
80
|
+
ps = action[:action].parameters.map{|_, name|
|
81
|
+
{name => params[name]}
|
82
|
+
}.inject({}, :merge)
|
83
|
+
execute(obj, ps, action)
|
84
|
+
obj.tempfiles.each{|f| f.close }
|
85
|
+
obj
|
107
86
|
end
|
108
|
-
end
|
109
87
|
|
110
|
-
|
88
|
+
private
|
89
|
+
def self.execute(obj, ps, action)
|
90
|
+
ps = to_as_file(obj, ps, action)
|
91
|
+
ps = to_tempfile(obj, ps, action)
|
92
|
+
vs = action[:parameters].map{|k,v|ps[k]}
|
93
|
+
obj.instance_exec(*vs, &(action[:action]))
|
94
|
+
end
|
111
95
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
96
|
+
def self.to_as_file(obj, ps, action)
|
97
|
+
action[:parameters].select{|_,v|v[:as_file]}.each{|k,_|
|
98
|
+
f = Tempfile.open(k.to_s)
|
99
|
+
f.write ps[k]
|
100
|
+
f.close
|
101
|
+
f.open
|
102
|
+
obj.tempfiles.push f
|
103
|
+
ps[k] = {tempfile: f}
|
104
|
+
}
|
105
|
+
ps
|
106
|
+
end
|
107
|
+
def self.to_tempfile(obj, ps, action)
|
108
|
+
action[:parameters].select{|_,v|v[:tempfile]}.each{|k,_|
|
109
|
+
ps[k] = tempfile obj, ps[k]
|
110
|
+
}
|
111
|
+
ps
|
112
|
+
end
|
113
|
+
def self.tempfile(obj,file)
|
114
|
+
if file.is_a? Hash
|
115
|
+
file[:tempfile].path
|
116
|
+
else
|
117
|
+
f = Tempfile.open(SecureRandom.hex(4))
|
118
|
+
f.write file
|
119
|
+
f.flush
|
120
|
+
f.close
|
121
|
+
f.open
|
122
|
+
obj.tempfiles.push f
|
123
|
+
f.path
|
124
|
+
end
|
124
125
|
end
|
125
126
|
end
|
126
|
-
def clear_annotaion
|
127
|
-
@context_stack.last.delete(:files)
|
128
|
-
@context_stack.last.delete(:description)
|
129
|
-
end
|
130
|
-
end
|
131
127
|
|
132
|
-
module
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
end
|
128
|
+
module Annotation
|
129
|
+
def is_file *files
|
130
|
+
@context_stack.last[:is_file] ||= []
|
131
|
+
@context_stack.last[:is_file].push(*files)
|
132
|
+
end
|
133
|
+
def as_file *files
|
134
|
+
@context_stack.last[:as_file] ||= []
|
135
|
+
@context_stack.last[:as_file].push(*files)
|
136
|
+
end
|
137
|
+
def tempfile *files
|
138
|
+
@context_stack.last[:tempfile] ||= []
|
139
|
+
@context_stack.last[:tempfile].push(*files)
|
140
|
+
end
|
137
141
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
142
|
+
def description(param1, param2=nil)
|
143
|
+
@context_stack.last[:description] ||= {}
|
144
|
+
if param2
|
145
|
+
@context_stack.last[:description][:params] ||= {}
|
146
|
+
@context_stack.last[:description][:params][param1] = param2
|
147
|
+
else
|
148
|
+
@context_stack.last[:description][:path] = param1
|
149
|
+
end
|
150
|
+
end
|
151
|
+
def clear_annotaion
|
152
|
+
@context_stack.last.delete(:is_file)
|
153
|
+
@context_stack.last.delete(:as_file)
|
154
|
+
@context_stack.last.delete(:tempfile)
|
155
|
+
@context_stack.last.delete(:description)
|
156
|
+
end
|
144
157
|
end
|
145
158
|
|
146
|
-
|
147
|
-
|
159
|
+
module ExtExpression
|
160
|
+
def content_type type
|
161
|
+
@context_stack.last[:content_type] = type
|
162
|
+
end
|
148
163
|
end
|
149
164
|
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
165
|
+
module SyntaxSugar
|
166
|
+
def get(*names, &block); path(:get, *names, &block); end
|
167
|
+
def post(*names, &block); path(:post, *names, &block); end
|
168
|
+
|
169
|
+
def command(*names, cmd)
|
170
|
+
eval(replace :get, names, "write `#{cmd}`")
|
171
|
+
end
|
154
172
|
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
173
|
+
def text(*names, text)
|
174
|
+
eval(replace :get, names, "write \"#{text}\"")
|
175
|
+
end
|
176
|
+
|
177
|
+
def get_command(*names, cmd); command(*names, cmd); end
|
178
|
+
def post_command(*names, cmd)
|
179
|
+
eval(replace :post, names, "write `#{cmd}`")
|
180
|
+
end
|
159
181
|
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
182
|
+
def get_text(*names, text); text(*names, text); end
|
183
|
+
def post_text(*names, text)
|
184
|
+
eval(replace :post, names, "write \"#{text}\"")
|
185
|
+
end
|
186
|
+
|
187
|
+
private
|
188
|
+
def replace meth, names, cmd
|
189
|
+
ps = cmd.scan(/\$\{(?<p>[^:\}]*)\}/).flatten
|
190
|
+
fs = cmd.scan(/\$\{file:(?<p>[^:\}]*)\}/).flatten
|
191
|
+
c = ps.inject(cmd){|acc,c|
|
192
|
+
acc.gsub /\$\{#{c}\}/, "\#{#{c}}"
|
193
|
+
}
|
194
|
+
c = fs.inject(c){|acc,c|
|
195
|
+
acc.gsub /\$\{file:#{c}\}/, "\#{#{c}}"
|
196
|
+
}
|
197
|
+
is_file_annotation = "is_file " + fs.map{|f|":#{f}"}.join(',')
|
198
|
+
tempfile_annotation = "tempfile " + fs.map{|f|":#{f}"}.join(',')
|
199
|
+
args = (ps + fs).join(',')
|
175
200
|
<<PROC
|
201
|
+
#{is_file_annotation}
|
202
|
+
#{tempfile_annotation}
|
176
203
|
#{meth.to_s}(#{names.map{|n|":#{n.to_s}"}.join(',')}) do | #{args} |
|
177
|
-
#{
|
204
|
+
#{c}
|
178
205
|
end
|
179
206
|
PROC
|
207
|
+
end
|
180
208
|
end
|
181
|
-
end
|
182
209
|
|
183
210
|
|
184
|
-
module DSL
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
211
|
+
module DSL
|
212
|
+
def self.extended obj
|
213
|
+
# add stacks and a context to an extended object.
|
214
|
+
obj.instance_variable_set(:@action_stack, [])
|
215
|
+
obj.instance_variable_set(:@domain_stack, [])
|
216
|
+
obj.instance_variable_set(:@context_stack, [{}])
|
217
|
+
obj.extend Action
|
218
|
+
obj.extend Annotation
|
219
|
+
obj.extend ExtExpression
|
220
|
+
obj.extend SyntaxSugar
|
221
|
+
end
|
222
|
+
def action_stack
|
223
|
+
@action_stack
|
224
|
+
end
|
198
225
|
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
226
|
+
def domain(*path , &block)
|
227
|
+
# annotations don't effect over domain
|
228
|
+
clear_annotaion
|
229
|
+
@domain_stack.push *path
|
230
|
+
@context_stack.push(@context_stack.last.clone)
|
231
|
+
block.call
|
232
|
+
@context_stack.pop
|
233
|
+
@domain_stack.pop path.length
|
234
|
+
# annotations don't effect over domain
|
235
|
+
clear_annotaion
|
236
|
+
end
|
210
237
|
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
238
|
+
def path(method, *names, &block)
|
239
|
+
meta = @context_stack.last.clone
|
240
|
+
meta[:method] = method
|
241
|
+
meta[:names] = names
|
242
|
+
meta[:domain] = @domain_stack.clone
|
243
|
+
meta[:action] = block
|
244
|
+
clear_annotaion # annotations effect only a path.
|
245
|
+
@action_stack.push meta
|
246
|
+
end
|
247
|
+
|
248
|
+
def self.parse(file)
|
249
|
+
obj = Object.new
|
250
|
+
obj.extend DSL
|
251
|
+
obj.instance_eval(open(file){|f|f.read})
|
252
|
+
obj.action_stack.map{|x| normalize x }
|
253
|
+
end
|
227
254
|
|
255
|
+
def self.normalize hs
|
256
|
+
description = hs[:description] || {}
|
257
|
+
description[:params] ||= {}
|
258
|
+
parameters = hs[:action].parameters.map.with_index{|(_,n),i|
|
259
|
+
{ n => {
|
260
|
+
required: i < hs[:action].arity,
|
261
|
+
is_file: (hs[:is_file]||[]).include?(n),
|
262
|
+
as_file: (hs[:as_file]||[]).include?(n),
|
263
|
+
tempfile: (hs[:tempfile]||[]).include?(n),
|
264
|
+
}
|
265
|
+
}
|
266
|
+
}.inject({}, :merge)
|
267
|
+
{
|
268
|
+
method: hs[:method],
|
269
|
+
names: hs[:names],
|
270
|
+
description: description,
|
271
|
+
domain: hs[:domain],
|
272
|
+
action: hs[:action],
|
273
|
+
parameters: parameters,
|
274
|
+
}
|
275
|
+
end
|
276
|
+
end
|
228
277
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: casual-api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0.
|
4
|
+
version: 3.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Takeshi Kojima
|
@@ -38,6 +38,7 @@ extensions: []
|
|
38
38
|
extra_rdoc_files: []
|
39
39
|
files:
|
40
40
|
- bin/casual-api
|
41
|
+
- lib/casual-api.rb
|
41
42
|
- lib/casual.rb
|
42
43
|
- lib/config.ru
|
43
44
|
- lib/dsl.rb
|