shaf 0.1.0.beta
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 +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
|