shaf 0.1.0.beta
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +1 -0
- data/bin/shaf +57 -0
- data/lib/shaf.rb +9 -0
- data/lib/shaf/api_doc.rb +124 -0
- data/lib/shaf/api_doc/comment.rb +27 -0
- data/lib/shaf/api_doc/document.rb +133 -0
- data/lib/shaf/app.rb +22 -0
- data/lib/shaf/command.rb +42 -0
- data/lib/shaf/command/console.rb +17 -0
- data/lib/shaf/command/generate.rb +19 -0
- data/lib/shaf/command/new.rb +79 -0
- data/lib/shaf/command/server.rb +15 -0
- data/lib/shaf/command/templates/Gemfile.erb +30 -0
- data/lib/shaf/doc_model.rb +54 -0
- data/lib/shaf/errors.rb +77 -0
- data/lib/shaf/extensions.rb +11 -0
- data/lib/shaf/extensions/authorize.rb +42 -0
- data/lib/shaf/extensions/resource_uris.rb +153 -0
- data/lib/shaf/formable.rb +188 -0
- data/lib/shaf/generator.rb +69 -0
- data/lib/shaf/generator/controller.rb +106 -0
- data/lib/shaf/generator/migration.rb +122 -0
- data/lib/shaf/generator/migration/add_column.rb +49 -0
- data/lib/shaf/generator/migration/create_table.rb +40 -0
- data/lib/shaf/generator/migration/drop_column.rb +45 -0
- data/lib/shaf/generator/migration/empty.rb +21 -0
- data/lib/shaf/generator/migration/rename_column.rb +48 -0
- data/lib/shaf/generator/model.rb +68 -0
- data/lib/shaf/generator/policy.rb +43 -0
- data/lib/shaf/generator/scaffold.rb +26 -0
- data/lib/shaf/generator/serializer.rb +258 -0
- data/lib/shaf/generator/templates/api/controller.rb.erb +62 -0
- data/lib/shaf/generator/templates/api/model.rb.erb +20 -0
- data/lib/shaf/generator/templates/api/policy.rb.erb +26 -0
- data/lib/shaf/generator/templates/api/serializer.rb.erb +24 -0
- data/lib/shaf/generator/templates/spec/integration_spec.rb.erb +98 -0
- data/lib/shaf/generator/templates/spec/model.rb.erb +40 -0
- data/lib/shaf/generator/templates/spec/serializer_spec.rb.erb +46 -0
- data/lib/shaf/helpers.rb +15 -0
- data/lib/shaf/helpers/json_html.rb +65 -0
- data/lib/shaf/helpers/paginate.rb +24 -0
- data/lib/shaf/helpers/payload.rb +115 -0
- data/lib/shaf/helpers/session.rb +53 -0
- data/lib/shaf/middleware.rb +1 -0
- data/lib/shaf/middleware/request_id.rb +16 -0
- data/lib/shaf/registrable_factory.rb +71 -0
- data/lib/shaf/settings.rb +33 -0
- data/lib/shaf/spec.rb +6 -0
- data/lib/shaf/spec/http_method_utils.rb +24 -0
- data/lib/shaf/spec/integration_spec.rb +53 -0
- data/lib/shaf/spec/model.rb +17 -0
- data/lib/shaf/spec/payload_test.rb +78 -0
- data/lib/shaf/spec/payload_utils.rb +176 -0
- data/lib/shaf/spec/serializer_spec.rb +24 -0
- data/lib/shaf/tasks.rb +4 -0
- data/lib/shaf/tasks/db.rb +61 -0
- data/lib/shaf/tasks/test.rb +43 -0
- data/lib/shaf/utils.rb +53 -0
- data/lib/shaf/version.rb +3 -0
- data/templates/Rakefile +13 -0
- data/templates/api/controllers/base_controller.rb +57 -0
- data/templates/api/controllers/docs_controller.rb +16 -0
- data/templates/api/controllers/root_controller.rb +8 -0
- data/templates/api/serializers/error_serializer.rb +10 -0
- data/templates/api/serializers/form_serializer.rb +42 -0
- data/templates/api/serializers/root_serializer.rb +16 -0
- data/templates/config.ru +4 -0
- data/templates/config/bootstrap.rb +12 -0
- data/templates/config/constants.rb +5 -0
- data/templates/config/customize.rb +3 -0
- data/templates/config/database.rb +40 -0
- data/templates/config/directories.rb +32 -0
- data/templates/config/helpers.rb +18 -0
- data/templates/config/initializers.rb +12 -0
- data/templates/config/initializers/db_migrations.rb +18 -0
- data/templates/config/initializers/hal_presenter.rb +6 -0
- data/templates/config/initializers/logging.rb +7 -0
- data/templates/config/initializers/sequel.rb +4 -0
- data/templates/config/settings.yml +19 -0
- data/templates/frontend/assets/css/main.css +70 -0
- data/templates/frontend/views/form.erb +16 -0
- data/templates/frontend/views/layout.erb +11 -0
- data/templates/frontend/views/payload.erb +8 -0
- data/templates/spec/integration/root_spec.rb +14 -0
- data/templates/spec/serializers/root_serializer_spec.rb +12 -0
- data/templates/spec/spec_helper.rb +4 -0
- metadata +348 -0
- metadata.gz.sig +0 -0
@@ -0,0 +1,62 @@
|
|
1
|
+
require '<%= policy_file %>'
|
2
|
+
|
3
|
+
class <%= controller_class_name %> < BaseController
|
4
|
+
|
5
|
+
resource_uris_for :<%= name %>
|
6
|
+
|
7
|
+
authorize_with <%= policy_class_name %>
|
8
|
+
|
9
|
+
get '/<%= plural_name %>/form' do
|
10
|
+
form = <%= model_class_name %>.create_form
|
11
|
+
form.self_link = new_<%= name %>_uri
|
12
|
+
form.href = <%= plural_name %>_uri
|
13
|
+
respond_with form
|
14
|
+
end
|
15
|
+
|
16
|
+
get '/<%= plural_name %>/:id/edit' do
|
17
|
+
form = <%= name %>.edit_form
|
18
|
+
form.self_link = edit_<%= name %>_uri(<%= name %>)
|
19
|
+
form.href = <%= name %>_uri(<%= name %>)
|
20
|
+
respond_with form
|
21
|
+
end
|
22
|
+
|
23
|
+
get '/<%= plural_name %>/:id' do
|
24
|
+
respond_with <%= name %>
|
25
|
+
end
|
26
|
+
|
27
|
+
put '/<%= plural_name %>/:id' do
|
28
|
+
authorize! :write
|
29
|
+
<%= name %>.update(<%= name %>_params)
|
30
|
+
respond_with <%= name %>
|
31
|
+
end
|
32
|
+
|
33
|
+
delete '/<%= plural_name %>/:id' do
|
34
|
+
authorize! :write
|
35
|
+
<%= name %>.destroy
|
36
|
+
status 204
|
37
|
+
end
|
38
|
+
|
39
|
+
get '/<%= plural_name %>' do
|
40
|
+
collection = paginate(<%= model_class_name %>.order(:created_at).reverse)
|
41
|
+
respond_with_collection collection, serializer: <%= serializer_class_name %>
|
42
|
+
end
|
43
|
+
|
44
|
+
post '/<%= plural_name %>' do
|
45
|
+
authorize! :write
|
46
|
+
<%= name %> = <%= model_class_name %>.create(<%= name %>_params)
|
47
|
+
headers({ "Location" => <%= name %>_uri(<%= name %>) })
|
48
|
+
respond_with <%= name %>, status: 201
|
49
|
+
end
|
50
|
+
|
51
|
+
def <%= name %>_params
|
52
|
+
# Generated method - TODO: Remove any params that should not be allowed!
|
53
|
+
safe_params(<%= params.map { |p| ":#{p[0]}" }.join(', ') %>)
|
54
|
+
end
|
55
|
+
|
56
|
+
def <%= name %>
|
57
|
+
<%= model_class_name %>[params['id']].tap do |<%= name %>|
|
58
|
+
raise NotFoundError.new(clazz: <%= model_class_name %>, id: params['id']) unless <%= name %>
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class <%= class_name %> < Sequel::Model
|
2
|
+
include Shaf::Formable
|
3
|
+
|
4
|
+
<% if form_fields.any? %>
|
5
|
+
form do
|
6
|
+
<%= form_fields.join("\n ") %>
|
7
|
+
|
8
|
+
create do
|
9
|
+
title 'Create <%= class_name %>'
|
10
|
+
name 'create-<%= model_name %>'
|
11
|
+
end
|
12
|
+
|
13
|
+
edit do
|
14
|
+
title 'Update <%= class_name %>'
|
15
|
+
name 'update-<%= model_name %>'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
<% end %>
|
19
|
+
end
|
20
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
class <%= policy_class_name %>
|
2
|
+
include HALPresenter::Policy::DSL
|
3
|
+
|
4
|
+
# Auto generated policy: Update this file to suite your API!
|
5
|
+
|
6
|
+
<%= attributes.join("\n ") %>
|
7
|
+
|
8
|
+
link :up
|
9
|
+
|
10
|
+
link :edit, :'create-form', :'edit-form', :delete do
|
11
|
+
write?
|
12
|
+
end
|
13
|
+
|
14
|
+
embed :'create-form', :'edit-form' do
|
15
|
+
write?
|
16
|
+
end
|
17
|
+
|
18
|
+
def read?
|
19
|
+
true
|
20
|
+
end
|
21
|
+
|
22
|
+
def write?
|
23
|
+
# !!current_user
|
24
|
+
true
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'policies/<%= policy_name %>'
|
2
|
+
|
3
|
+
class <%= class_name %>
|
4
|
+
extend HALPresenter
|
5
|
+
extend Shaf::UriHelper
|
6
|
+
|
7
|
+
model <%= model_class_name %>
|
8
|
+
policy <%= policy_class_name %>
|
9
|
+
<% attributes_with_doc.each do |attr| %>
|
10
|
+
<%= attr.join("\n ") %>
|
11
|
+
<% end %>
|
12
|
+
<% curies_with_doc.each do |curie| %>
|
13
|
+
<%= curie.join("\n ") %>
|
14
|
+
<% end %>
|
15
|
+
<% links_with_doc.each do |link| %>
|
16
|
+
<%= link.join("\n ") %>
|
17
|
+
<% end %>
|
18
|
+
<% embeds_with_doc.each do |embed| %>
|
19
|
+
<%= embed.join("\n ") %>
|
20
|
+
<% end %>
|
21
|
+
<% if collection_with_doc %>
|
22
|
+
<%= collection_with_doc.join("\n ") %>
|
23
|
+
<% end %>
|
24
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe <%= model_class_name %>, type: :integration do
|
4
|
+
|
5
|
+
it "returns a <%= name %>" do
|
6
|
+
<%= name %> = <%= model_class_name %>.create
|
7
|
+
get <%= name %>_uri(<%= name %>)
|
8
|
+
status.must_equal 200
|
9
|
+
link_rels.must_include(:self)
|
10
|
+
links[:self][:href].must_equal <%= name %>_uri(<%= name %>)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "lists all <%= plural_name %>" do
|
14
|
+
<%= model_class_name %>.create
|
15
|
+
<%= model_class_name %>.create
|
16
|
+
|
17
|
+
get <%= plural_name %>_uri
|
18
|
+
status.must_equal 200
|
19
|
+
link_rels.must_include(:self)
|
20
|
+
links[:self][:href].must_include <%= plural_name %>_uri
|
21
|
+
embedded :'<%= plural_name %>' do
|
22
|
+
<%= plural_name %> = last_payload
|
23
|
+
<%= plural_name %>.size.must_equal 2
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
it "can create <%= plural_name %>" do
|
28
|
+
get <%= plural_name %>_uri
|
29
|
+
|
30
|
+
embedded :'doc:create-form' do
|
31
|
+
links[:self][:href].must_equal new_<%= name %>_uri
|
32
|
+
attributes[:href].must_equal <%= plural_name %>_uri
|
33
|
+
attributes[:method].must_equal "POST"
|
34
|
+
attributes[:name].must_equal "create-<%= name %>"
|
35
|
+
attributes[:title].must_equal "Create <%= model_class_name %>"
|
36
|
+
attributes[:type].must_equal "application/json"
|
37
|
+
attributes[:fields].size.must_equal <%= params.size %>
|
38
|
+
|
39
|
+
payload = fill_form attributes[:fields]
|
40
|
+
post attributes[:href], payload
|
41
|
+
status.must_equal 201
|
42
|
+
link_rels.must_include(:self)
|
43
|
+
headers["Location"].must_equal links[:self][:href]
|
44
|
+
end
|
45
|
+
|
46
|
+
get <%= plural_name %>_uri
|
47
|
+
status.must_equal 200
|
48
|
+
links[:self][:href].must_include <%= plural_name %>_uri
|
49
|
+
embedded(:'<%= plural_name %>').size.must_equal 1
|
50
|
+
|
51
|
+
embedded :'<%= plural_name %>' do
|
52
|
+
<%= name %> = last_payload.first
|
53
|
+
<% params.each do |param| -%>
|
54
|
+
<% if param[1] == 'string' -%>
|
55
|
+
<%= name %>[:<%= param[0] %>].must_equal "value for <%= param[0] %>"
|
56
|
+
<% elsif param[1] == 'integer' -%>
|
57
|
+
<%= name %>[:<%= param[0] %>].must_equal "<%= param[0] %>".size
|
58
|
+
<% end -%>
|
59
|
+
<% end -%>
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
it "<%= plural_name %> can be updated" do
|
64
|
+
<%= name %> = <%= model_class_name %>.create
|
65
|
+
get <%= name %>_uri(<%= name %>)
|
66
|
+
status.must_equal 200
|
67
|
+
link_rels.must_include(:'doc:edit-form')
|
68
|
+
|
69
|
+
embedded :'doc:edit-form' do
|
70
|
+
links[:self][:href].must_equal edit_<%= name %>_uri(<%= name %>)
|
71
|
+
attributes[:href].must_equal <%= name %>_uri(<%= name %>)
|
72
|
+
attributes[:method].must_equal "PUT"
|
73
|
+
attributes[:name].must_equal "update-<%= name %>"
|
74
|
+
attributes[:title].must_equal "Update <%= model_class_name %>"
|
75
|
+
attributes[:type].must_equal "application/json"
|
76
|
+
attributes[:fields].size.must_equal <%= params.size %>
|
77
|
+
|
78
|
+
payload = fill_form attributes[:fields]
|
79
|
+
put attributes[:href], payload
|
80
|
+
status.must_equal 200
|
81
|
+
link_rels.must_include(:self)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
it "<%= plural_name %> can be deleted" do
|
86
|
+
<%= name %> = <%= model_class_name %>.create
|
87
|
+
get <%= name %>_uri(<%= name %>)
|
88
|
+
status.must_equal 200
|
89
|
+
link_rels.must_include(:'doc:delete')
|
90
|
+
|
91
|
+
follow_rel(:'doc:delete', method: :delete)
|
92
|
+
status.must_equal 204
|
93
|
+
|
94
|
+
get <%= name %>_uri(<%= name %>)
|
95
|
+
status.must_equal 404
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Model
|
4
|
+
class UserTest < TestCase
|
5
|
+
def setup
|
6
|
+
@user = User.create(
|
7
|
+
username: 'test_user',
|
8
|
+
password: 'hidden',
|
9
|
+
email: 'test@user.com',
|
10
|
+
)
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_create
|
14
|
+
assert @user
|
15
|
+
assert_equal @user.username, 'test_user'
|
16
|
+
assert_equal @user.email, 'test@user.com'
|
17
|
+
created = @user.created_at
|
18
|
+
assert (created..(created + 30)).include? Time.now
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_update_user
|
22
|
+
digest = @user.password_digest
|
23
|
+
@user.update(
|
24
|
+
username: 'test_User',
|
25
|
+
email: 'test@User.com',
|
26
|
+
password: 'hidden2'
|
27
|
+
)
|
28
|
+
assert @user.created_at < @user.updated_at
|
29
|
+
assert_equal 'test_User', @user.username
|
30
|
+
assert_equal 'test@User.com', @user.email
|
31
|
+
refute_equal digest, @user.password_digest
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_delete_user
|
35
|
+
@user.destroy
|
36
|
+
assert_nil User.where(username: @user.username).first
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe <%= class_name %> do
|
4
|
+
|
5
|
+
let(:resource) do
|
6
|
+
<%= model_class_name %>.new.
|
7
|
+
tap { |<%= name %>| <%= name %>.id = 5 }
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "when current_user is nil" do
|
11
|
+
before do
|
12
|
+
set_payload HALPresenter.to_hal(resource)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "serializes attributes" do
|
16
|
+
<% attributes.each do |attr| -%>
|
17
|
+
attributes.keys.must_include(<%= attr %>)
|
18
|
+
<% end -%>
|
19
|
+
end
|
20
|
+
|
21
|
+
it "serializes links" do
|
22
|
+
<% ['self', 'doc:up'].each do |rel| -%>
|
23
|
+
link_rels.must_include(:'<%= rel %>')
|
24
|
+
<% end -%>
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "when current_user is present" do
|
29
|
+
before do
|
30
|
+
set_payload HALPresenter.to_hal(resource, current_user: "Bengt")
|
31
|
+
end
|
32
|
+
|
33
|
+
it "serializes attributes" do
|
34
|
+
<% attributes.each do |attr| -%>
|
35
|
+
attributes.keys.must_include(<%= attr %>)
|
36
|
+
<% end -%>
|
37
|
+
end
|
38
|
+
|
39
|
+
it "serializes links" do
|
40
|
+
<% links.each do |rel| -%>
|
41
|
+
link_rels.must_include(:'<%= rel %>')
|
42
|
+
<% end -%>
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
data/lib/shaf/helpers.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
module Shaf
|
2
|
+
module JsonHtml
|
3
|
+
|
4
|
+
def json2html(json)
|
5
|
+
o = JSON.parse(json)
|
6
|
+
"<pre><code>#{to_html(o)}</code></pre>"
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def to_html(obj, indent: 0, pre_indent: "")
|
12
|
+
case obj
|
13
|
+
when Array
|
14
|
+
html_array(obj, indent, pre_indent)
|
15
|
+
when Hash
|
16
|
+
html_hash(obj, indent, pre_indent)
|
17
|
+
else
|
18
|
+
html_scalar(obj, indent, pre_indent)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def html_array(a, indent, pre_indent)
|
23
|
+
array_of_strings = a.map do |e|
|
24
|
+
to_html(e, indent: indent + 1, pre_indent: indentation(indent + 1))
|
25
|
+
end
|
26
|
+
|
27
|
+
<<~EOS.chomp
|
28
|
+
#{pre_indent}<span>[</span>
|
29
|
+
#{array_of_strings.join(",\n")}
|
30
|
+
#{indentation(indent)}<span>]</span>
|
31
|
+
EOS
|
32
|
+
end
|
33
|
+
|
34
|
+
def html_hash(h, indent, pre_indent)
|
35
|
+
<<~EOS.chomp
|
36
|
+
#{pre_indent}<span>{</span>
|
37
|
+
#{h.map { |k,v| sub_hash(k,v, indent + 1) }.join(",\n")},
|
38
|
+
#{indentation(indent)}<span>}</span>
|
39
|
+
EOS
|
40
|
+
end
|
41
|
+
|
42
|
+
def html_scalar(s, indent, pre_indent)
|
43
|
+
q = around(s)
|
44
|
+
format "%s%s%s%s", pre_indent, q, s, q
|
45
|
+
end
|
46
|
+
|
47
|
+
def sub_hash(key, value, indent)
|
48
|
+
if key == 'href'
|
49
|
+
%Q(#{indentation(indent)}"#{key}"<span>:</span> <a href="#{value}">#{value}</a>)
|
50
|
+
else
|
51
|
+
"#{indentation(indent)}\"#{key}\"<span>:</span> #{to_html(value, indent: indent) }"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def indentation(i)
|
56
|
+
" " * i
|
57
|
+
end
|
58
|
+
|
59
|
+
def around(obj)
|
60
|
+
return '"' if obj.is_a? String
|
61
|
+
""
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Shaf
|
2
|
+
module Paginate
|
3
|
+
|
4
|
+
def current_page
|
5
|
+
page = (params[:page] || 1).to_i
|
6
|
+
page == 0 ? 1 : page
|
7
|
+
end
|
8
|
+
|
9
|
+
def paginate!(collection, per_page = PAGINATION_PER_PAGE)
|
10
|
+
unless collection.respond_to? :paginate
|
11
|
+
log.warning "Trying to paginate a collection that doesn't " \
|
12
|
+
"support pagination: #{collection}"
|
13
|
+
return
|
14
|
+
end
|
15
|
+
|
16
|
+
per_page = params[:per_page].to_i if params[:per_page]
|
17
|
+
collection.paginate(current_page, per_page)
|
18
|
+
end
|
19
|
+
|
20
|
+
def paginate(collection, per_page = PAGINATION_PER_PAGE)
|
21
|
+
paginate!(collection.dup, per_page)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
module Shaf
|
2
|
+
module Payload
|
3
|
+
def supported_response_types(resource)
|
4
|
+
[
|
5
|
+
mime_type(:hal),
|
6
|
+
mime_type(:json),
|
7
|
+
mime_type(:html)
|
8
|
+
]
|
9
|
+
end
|
10
|
+
|
11
|
+
def preferred_response_type(resource)
|
12
|
+
supported_types = supported_response_types(resource)
|
13
|
+
request.preferred_type(supported_types)
|
14
|
+
end
|
15
|
+
|
16
|
+
def prefer_html?
|
17
|
+
request.preferred_type.to_s == mime_type(:html)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def payload
|
23
|
+
@@request_id ||= nil
|
24
|
+
@@payload ||= nil
|
25
|
+
|
26
|
+
if @@request_id != request.env["REQUEST_ID"]
|
27
|
+
@@request_id = request.env["REQUEST_ID"]
|
28
|
+
@@payload = parse_payload
|
29
|
+
end
|
30
|
+
@@payload
|
31
|
+
end
|
32
|
+
|
33
|
+
def read_input
|
34
|
+
request.body.rewind unless request.body.pos == 0
|
35
|
+
request.body.read
|
36
|
+
ensure
|
37
|
+
request.body.rewind
|
38
|
+
end
|
39
|
+
|
40
|
+
def parse_payload
|
41
|
+
if request.env['CONTENT_TYPE'] == 'application/x-www-form-urlencoded'
|
42
|
+
return params.reject { |key,_| ['captures', 'splat'].include? key }
|
43
|
+
end
|
44
|
+
|
45
|
+
input = read_input
|
46
|
+
return {} if input.empty?
|
47
|
+
|
48
|
+
if request.env['CONTENT_TYPE'] =~ %r(\Aapplication/json)
|
49
|
+
JSON.parse(input)
|
50
|
+
else
|
51
|
+
raise ::UnsupportedMediaTypeError.new(request: request)
|
52
|
+
end
|
53
|
+
rescue StandardError
|
54
|
+
raise ::BadRequestError.new
|
55
|
+
end
|
56
|
+
|
57
|
+
def safe_params(*fields)
|
58
|
+
return {} unless payload
|
59
|
+
{}.tap do |allowed|
|
60
|
+
fields.each do |field|
|
61
|
+
f = field.to_s.downcase
|
62
|
+
allowed[f.to_sym] = payload[f] if payload[f]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def ignore_form_input?(name)
|
68
|
+
return name == '_method'
|
69
|
+
end
|
70
|
+
|
71
|
+
def respond_with_collection(resource, status: 200, serializer: nil)
|
72
|
+
respond_with(resource, status: status, serializer: serializer, collection: true)
|
73
|
+
end
|
74
|
+
|
75
|
+
def respond_with(resource, status: 200, serializer: nil, collection: false)
|
76
|
+
status(status)
|
77
|
+
|
78
|
+
preferred_response = preferred_response_type(resource)
|
79
|
+
serialized = serialize(resource, serializer, collection)
|
80
|
+
|
81
|
+
if preferred_response == mime_type(:html)
|
82
|
+
respond_with_html(resource, serialized)
|
83
|
+
else
|
84
|
+
respond_with_hal(resource, serialized)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def serialize(resource, serializer, collection)
|
89
|
+
serializer ||= HALPresenter
|
90
|
+
if collection
|
91
|
+
serializer.to_collection(resource, current_user: current_user)
|
92
|
+
else
|
93
|
+
serializer.to_hal(resource, current_user: current_user)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def respond_with_hal(resource, serialized)
|
98
|
+
log.debug "Response payload (#{resource.class}): #{serialized}"
|
99
|
+
content_type :hal
|
100
|
+
body serialized
|
101
|
+
end
|
102
|
+
|
103
|
+
def respond_with_html(resource, serialized)
|
104
|
+
log.debug "Responding with html. Output payload (#{resource.class}): #{serialized}"
|
105
|
+
content_type :html
|
106
|
+
case resource
|
107
|
+
when Shaf::Formable::Form
|
108
|
+
body erb(:form, locals: {form: resource, serialized: serialized})
|
109
|
+
else
|
110
|
+
body erb(:payload, locals: {serialized: serialized})
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
end
|