media_types-serialization 1.4.0 → 2.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '096826bd7e4a4be4fcd147fec07f26d05aec0101b8651ae63ed376a7a2388077'
4
- data.tar.gz: 2f783986be7ca3eff779e10a2ace5338d9ab7dbb755334ae79d01d7b422a77c9
3
+ metadata.gz: 693624dcfef405aa51599edfecb2eb6d355d4e33b2ed862cae84da2ba38d1184
4
+ data.tar.gz: c6ef94f5cf139da3c4699fd15f4322b5417ca2840b62038b0c96580d6b3afed4
5
5
  SHA512:
6
- metadata.gz: f0b58cdb8eb8e4f8c0c8ad73cc607673768cba38399cf9c804db16a54198b3fe0799a18c641e7c05d10e03c2936fc96a416b80ff51ff4bd5e6d570b10a47e712
7
- data.tar.gz: e82051321d55df89abe34c6d43e62a0158245c4fb9ae60060fc3e939df854626b3014285f2ac277f7632f6c3cd099ef349265bdfffbf7b7b226f76287bb53147
6
+ metadata.gz: 42cf5ba3382bb5863312d39c15cb5fb2565ef27ace28a06b6dfc565d766963649560501b1744e602e88d4c4d5d845c3b7c77a3d4640b2ddb5f17f7684da0f9de
7
+ data.tar.gz: 165bce5942688047c65b6d01c4c0657e8d311ad788456be0f6f84fd2536152a486d3e53a45f266cf8b357e4bc993d3832dcd52d61d48701c1a3de348736d7c9d
@@ -0,0 +1,34 @@
1
+ name: Publish debian bookworm packages
2
+
3
+ on:
4
+ - workflow_dispatch
5
+
6
+ jobs:
7
+ publish-bookworm:
8
+ runs-on: ubuntu-latest
9
+ container:
10
+ image: debian:bookworm
11
+ steps:
12
+ - name: Install repo
13
+ run: apt-get update && DEBIAN_FRONTEND=noninteractive apt-get --yes install wget && wget -O key.deb https://deb1.ws.maxmaton.nl/key.deb && DEBIAN_FRONTEND=noninteractive apt-get --yes install ./key.deb && echo "deb [signed-by=/usr/share/keyrings/maxmaton.gpg] http://deb.maxmaton.nl/debian bookworm main non-free" > /etc/apt/sources.list.d/maxmaton.list
14
+ - name: Install dependencies
15
+ run: apt-get update && DEBIAN_FRONTEND=noninteractive apt-get --yes install git build-essential gem scrypt sshpass gem2deb ruby-actionpack ruby-activesupport ruby-media-types
16
+ - uses: actions/checkout@v3
17
+ name: Check out repository
18
+ - name: Build gem
19
+ run: |
20
+ git config --global --add safe.directory "$(pwd)"
21
+ sed -i -re "s/VERSION\s+=\s+'([0-9]+.[0-9]+.[0-9]+)'/VERSION = '\1.bookworm'/g" lib/media_types/serialization/version.rb
22
+ gem build media_types-serialization.gemspec
23
+ - name: Build deb
24
+ run: DEBEMAIL=info@delftsolutions.nl gem2deb media_types-serialization-*.gem && ls -hal
25
+ - name: Publish
26
+ env:
27
+ PUBLISH_SIGNING_KEY: ${{ secrets.PUBLISH_SIGNING_KEY }}
28
+ SSHPASS: ${{ secrets.SSHPASS }}
29
+ run: |
30
+ echo "deb1.ws.maxmaton.nl ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDgN3TiyKvRTj4xBSyQtYz0OuHZYv2i+x3NL+svh2k0SgPr0Xms4Vu+g3AXntXUQGRM0W9zbcZSHiBIWbliv3Y+20f7lKlj9uXUEMHDuiB7Fu7dXObfHswIvTX3XWiPdDeG1jYQbGM3tENX/wtEoixyL++33O69t2SFR5MkPk+/j+zlGLCFf0ypTAMb7bT5NjRNM3+v0LT2WVSZuawA7Fl8WBVTq7MSSuCZIxHIv1kEq6AWpOjWZHNVZrijs+uRTIPcrZ47wSt6tanjAnWT9sAzu8KqcvQsPw9IQwqV1nfQWz0wMit7ijn9B3MrkNHXP5PaNiZQCezsbrh9glhShz0z" > known_hosts
31
+ echo "deb1.ws.maxmaton.nl ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMr5uAraiRj0pQ9Q9dQO0xMosTzFUAe+VjtMclIUbdJ7r7XMUa3etxh3BfBlW4nq3ZdIFCsV2zwzTaYSmfh95Xs=" >> known_hosts
32
+ echo "deb1.ws.maxmaton.nl ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPhQl7Ik6h7hSQbdo9ZfF78WYFCzch8SAOXFBxxAZH06" >> known_hosts
33
+ echo "Uploading :" ruby-media-types-serialization_*.deb
34
+ scrypt enc --passphrase "env:PUBLISH_SIGNING_KEY" ruby-media-types-serialization_*.deb | sshpass -e ssh -o "UserKnownHostsFile=known_hosts" publish@deb1.ws.maxmaton.nl "echo 'uploading bookworm' && sudo /opt/max/publish-deb ruby-media-types-serialization bookworm main && echo 'bookworm done'"
@@ -0,0 +1,34 @@
1
+ name: Publish debian sid packages
2
+
3
+ on:
4
+ - workflow_dispatch
5
+
6
+ jobs:
7
+ publish-sid:
8
+ runs-on: ubuntu-latest
9
+ container:
10
+ image: debian:sid
11
+ steps:
12
+ - name: Install repo
13
+ run: apt-get update && DEBIAN_FRONTEND=noninteractive apt-get --yes install wget && wget -O key.deb https://deb1.ws.maxmaton.nl/key.deb && DEBIAN_FRONTEND=noninteractive apt-get --yes install ./key.deb && echo "deb [signed-by=/usr/share/keyrings/maxmaton.gpg] http://deb.maxmaton.nl/debian sid main non-free" > /etc/apt/sources.list.d/maxmaton.list
14
+ - name: Install dependencies
15
+ run: apt-get update && DEBIAN_FRONTEND=noninteractive apt-get --yes install git build-essential gem scrypt sshpass gem2deb ruby-actionpack ruby-activesupport ruby-media-types
16
+ - uses: actions/checkout@v3
17
+ name: Check out repository
18
+ - name: Build gem
19
+ run: |
20
+ git config --global --add safe.directory "$(pwd)"
21
+ sed -i -re "s/VERSION\s+=\s+'([0-9]+.[0-9]+.[0-9]+)'/VERSION = '\1.sid'/g" lib/media_types/serialization/version.rb
22
+ gem build media_types-serialization.gemspec
23
+ - name: Build deb
24
+ run: DEBEMAIL=info@delftsolutions.nl gem2deb media_types-serialization-*.gem && ls -hal
25
+ - name: Publish
26
+ env:
27
+ PUBLISH_SIGNING_KEY: ${{ secrets.PUBLISH_SIGNING_KEY }}
28
+ SSHPASS: ${{ secrets.SSHPASS }}
29
+ run: |
30
+ echo "deb1.ws.maxmaton.nl ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDgN3TiyKvRTj4xBSyQtYz0OuHZYv2i+x3NL+svh2k0SgPr0Xms4Vu+g3AXntXUQGRM0W9zbcZSHiBIWbliv3Y+20f7lKlj9uXUEMHDuiB7Fu7dXObfHswIvTX3XWiPdDeG1jYQbGM3tENX/wtEoixyL++33O69t2SFR5MkPk+/j+zlGLCFf0ypTAMb7bT5NjRNM3+v0LT2WVSZuawA7Fl8WBVTq7MSSuCZIxHIv1kEq6AWpOjWZHNVZrijs+uRTIPcrZ47wSt6tanjAnWT9sAzu8KqcvQsPw9IQwqV1nfQWz0wMit7ijn9B3MrkNHXP5PaNiZQCezsbrh9glhShz0z" > known_hosts
31
+ echo "deb1.ws.maxmaton.nl ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMr5uAraiRj0pQ9Q9dQO0xMosTzFUAe+VjtMclIUbdJ7r7XMUa3etxh3BfBlW4nq3ZdIFCsV2zwzTaYSmfh95Xs=" >> known_hosts
32
+ echo "deb1.ws.maxmaton.nl ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPhQl7Ik6h7hSQbdo9ZfF78WYFCzch8SAOXFBxxAZH06" >> known_hosts
33
+ echo "Uploading :" ruby-media-types-serialization_*.deb
34
+ scrypt enc --passphrase "env:PUBLISH_SIGNING_KEY" ruby-media-types-serialization_*.deb | sshpass -e ssh -o "UserKnownHostsFile=known_hosts" publish@deb1.ws.maxmaton.nl "echo 'uploading sid' && sudo /opt/max/publish-deb ruby-media-types-serialization sid main && echo 'sid done'"
data/.gitignore CHANGED
@@ -11,4 +11,12 @@
11
11
  .idea/usage.statistics.xml
12
12
  .idea/tasks.xml
13
13
 
14
- /media_types-serialization*.gem
14
+ /media_types-serialization-*.gem
15
+ /ruby-media-types-serialization-*
16
+ /media-types-serialization-*.tar.gz
17
+ /ruby-media-types-serialization_*.deb
18
+ /ruby-media-types-serialization_*.buildinfo
19
+ /ruby-media-types-serialization_*.changes
20
+ /ruby-media-types-serialization_*.debian.tar.xz
21
+ /ruby-media-types-serialization_*.dsc
22
+ /ruby-media-types-serialization_*.orig.tar.gz
data/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.0.4
4
+
5
+ - ✨ Add more loose tests
6
+ - 🐛 Fix `locals` passing for HTML serialization
7
+ - 🐛 Fix for status passing in rack-like environments
8
+
9
+ ## 2.0.3
10
+
11
+ - 🐛 Fix debian packages not containing files
12
+
13
+ ## 2.0.0
14
+
15
+ - ✨ Add support for loose input validation
16
+ - ✨ Add inline api call functionality to api_viewer
17
+ - ✨ `allow_html_output` will now get the object in the `media` variable and if it is a hash, elements will be assigned as locals
18
+ - 🐛 Fix wildcards not showing up for non-nil views
19
+ - 🐛 Sending invalid content returned a 422 status code, changed to 400
20
+
3
21
  ## 1.4.0
4
22
 
5
23
  - ✨ Add support for redirecting in serializers
data/Gemfile.lock CHANGED
@@ -1,167 +1,169 @@
1
- PATH
2
- remote: .
3
- specs:
4
- media_types-serialization (1.4.0)
5
- actionpack (>= 6.0.0)
6
- activesupport (>= 6.0.0)
7
- media_types (>= 2.2.0, < 3.0.0)
8
-
9
- GEM
10
- remote: https://rubygems.org/
11
- specs:
12
- actioncable (6.1.7.3)
13
- actionpack (= 6.1.7.3)
14
- activesupport (= 6.1.7.3)
15
- nio4r (~> 2.0)
16
- websocket-driver (>= 0.6.1)
17
- actionmailbox (6.1.7.3)
18
- actionpack (= 6.1.7.3)
19
- activejob (= 6.1.7.3)
20
- activerecord (= 6.1.7.3)
21
- activestorage (= 6.1.7.3)
22
- activesupport (= 6.1.7.3)
23
- mail (>= 2.7.1)
24
- actionmailer (6.1.7.3)
25
- actionpack (= 6.1.7.3)
26
- actionview (= 6.1.7.3)
27
- activejob (= 6.1.7.3)
28
- activesupport (= 6.1.7.3)
29
- mail (~> 2.5, >= 2.5.4)
30
- rails-dom-testing (~> 2.0)
31
- actionpack (6.1.7.3)
32
- actionview (= 6.1.7.3)
33
- activesupport (= 6.1.7.3)
34
- rack (~> 2.0, >= 2.0.9)
35
- rack-test (>= 0.6.3)
36
- rails-dom-testing (~> 2.0)
37
- rails-html-sanitizer (~> 1.0, >= 1.2.0)
38
- actiontext (6.1.7.3)
39
- actionpack (= 6.1.7.3)
40
- activerecord (= 6.1.7.3)
41
- activestorage (= 6.1.7.3)
42
- activesupport (= 6.1.7.3)
43
- nokogiri (>= 1.8.5)
44
- actionview (6.1.7.3)
45
- activesupport (= 6.1.7.3)
46
- builder (~> 3.1)
47
- erubi (~> 1.4)
48
- rails-dom-testing (~> 2.0)
49
- rails-html-sanitizer (~> 1.1, >= 1.2.0)
50
- activejob (6.1.7.3)
51
- activesupport (= 6.1.7.3)
52
- globalid (>= 0.3.6)
53
- activemodel (6.1.7.3)
54
- activesupport (= 6.1.7.3)
55
- activerecord (6.1.7.3)
56
- activemodel (= 6.1.7.3)
57
- activesupport (= 6.1.7.3)
58
- activestorage (6.1.7.3)
59
- actionpack (= 6.1.7.3)
60
- activejob (= 6.1.7.3)
61
- activerecord (= 6.1.7.3)
62
- activesupport (= 6.1.7.3)
63
- marcel (~> 1.0)
64
- mini_mime (>= 1.1.0)
65
- activesupport (6.1.7.3)
66
- concurrent-ruby (~> 1.0, >= 1.0.2)
67
- i18n (>= 1.6, < 2)
68
- minitest (>= 5.1)
69
- tzinfo (~> 2.0)
70
- zeitwerk (~> 2.3)
71
- awesome_print (1.9.2)
72
- builder (3.2.4)
73
- concurrent-ruby (1.2.2)
74
- crass (1.0.6)
75
- date (3.3.3)
76
- erubi (1.12.0)
77
- globalid (1.1.0)
78
- activesupport (>= 5.0)
79
- i18n (1.12.0)
80
- concurrent-ruby (~> 1.0)
81
- loofah (2.19.1)
82
- crass (~> 1.0.2)
83
- nokogiri (>= 1.5.9)
84
- mail (2.8.1)
85
- mini_mime (>= 0.1.1)
86
- net-imap
87
- net-pop
88
- net-smtp
89
- marcel (1.0.2)
90
- media_types (2.2.0)
91
- method_source (1.0.0)
92
- mini_mime (1.1.2)
93
- minitest (5.18.0)
94
- net-imap (0.3.4)
95
- date
96
- net-protocol
97
- net-pop (0.1.2)
98
- net-protocol
99
- net-protocol (0.2.1)
100
- timeout
101
- net-smtp (0.3.3)
102
- net-protocol
103
- nio4r (2.5.8)
104
- nokogiri (1.14.2-x64-mingw32)
105
- racc (~> 1.4)
106
- oj (3.14.2)
107
- racc (1.6.2)
108
- rack (2.2.6.4)
109
- rack-test (2.1.0)
110
- rack (>= 1.3)
111
- rails (6.1.7.3)
112
- actioncable (= 6.1.7.3)
113
- actionmailbox (= 6.1.7.3)
114
- actionmailer (= 6.1.7.3)
115
- actionpack (= 6.1.7.3)
116
- actiontext (= 6.1.7.3)
117
- actionview (= 6.1.7.3)
118
- activejob (= 6.1.7.3)
119
- activemodel (= 6.1.7.3)
120
- activerecord (= 6.1.7.3)
121
- activestorage (= 6.1.7.3)
122
- activesupport (= 6.1.7.3)
123
- bundler (>= 1.15.0)
124
- railties (= 6.1.7.3)
125
- sprockets-rails (>= 2.0.0)
126
- rails-dom-testing (2.0.3)
127
- activesupport (>= 4.2.0)
128
- nokogiri (>= 1.6)
129
- rails-html-sanitizer (1.5.0)
130
- loofah (~> 2.19, >= 2.19.1)
131
- railties (6.1.7.3)
132
- actionpack (= 6.1.7.3)
133
- activesupport (= 6.1.7.3)
134
- method_source
135
- rake (>= 12.2)
136
- thor (~> 1.0)
137
- rake (13.0.6)
138
- sprockets (4.2.0)
139
- concurrent-ruby (~> 1.0)
140
- rack (>= 2.2.4, < 4)
141
- sprockets-rails (3.4.2)
142
- actionpack (>= 5.2)
143
- activesupport (>= 5.2)
144
- sprockets (>= 3.0.0)
145
- thor (1.2.1)
146
- timeout (0.3.2)
147
- tzinfo (2.0.6)
148
- concurrent-ruby (~> 1.0)
149
- websocket-driver (0.7.5)
150
- websocket-extensions (>= 0.1.0)
151
- websocket-extensions (0.1.5)
152
- zeitwerk (2.6.7)
153
-
154
- PLATFORMS
155
- x64-mingw32
156
-
157
- DEPENDENCIES
158
- awesome_print
159
- bundler
160
- media_types-serialization!
161
- minitest (~> 5.0)
162
- oj
163
- rails (~> 6.0)
164
- rake (~> 13.0)
165
-
166
- BUNDLED WITH
167
- 2.1.4
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ media_types-serialization (2.0.4)
5
+ actionpack (>= 6.0.0)
6
+ activesupport (>= 6.0.0)
7
+ media_types (>= 2.2.3, < 3.0.0)
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ actioncable (6.1.7.4)
13
+ actionpack (= 6.1.7.4)
14
+ activesupport (= 6.1.7.4)
15
+ nio4r (~> 2.0)
16
+ websocket-driver (>= 0.6.1)
17
+ actionmailbox (6.1.7.4)
18
+ actionpack (= 6.1.7.4)
19
+ activejob (= 6.1.7.4)
20
+ activerecord (= 6.1.7.4)
21
+ activestorage (= 6.1.7.4)
22
+ activesupport (= 6.1.7.4)
23
+ mail (>= 2.7.1)
24
+ actionmailer (6.1.7.4)
25
+ actionpack (= 6.1.7.4)
26
+ actionview (= 6.1.7.4)
27
+ activejob (= 6.1.7.4)
28
+ activesupport (= 6.1.7.4)
29
+ mail (~> 2.5, >= 2.5.4)
30
+ rails-dom-testing (~> 2.0)
31
+ actionpack (6.1.7.4)
32
+ actionview (= 6.1.7.4)
33
+ activesupport (= 6.1.7.4)
34
+ rack (~> 2.0, >= 2.0.9)
35
+ rack-test (>= 0.6.3)
36
+ rails-dom-testing (~> 2.0)
37
+ rails-html-sanitizer (~> 1.0, >= 1.2.0)
38
+ actiontext (6.1.7.4)
39
+ actionpack (= 6.1.7.4)
40
+ activerecord (= 6.1.7.4)
41
+ activestorage (= 6.1.7.4)
42
+ activesupport (= 6.1.7.4)
43
+ nokogiri (>= 1.8.5)
44
+ actionview (6.1.7.4)
45
+ activesupport (= 6.1.7.4)
46
+ builder (~> 3.1)
47
+ erubi (~> 1.4)
48
+ rails-dom-testing (~> 2.0)
49
+ rails-html-sanitizer (~> 1.1, >= 1.2.0)
50
+ activejob (6.1.7.4)
51
+ activesupport (= 6.1.7.4)
52
+ globalid (>= 0.3.6)
53
+ activemodel (6.1.7.4)
54
+ activesupport (= 6.1.7.4)
55
+ activerecord (6.1.7.4)
56
+ activemodel (= 6.1.7.4)
57
+ activesupport (= 6.1.7.4)
58
+ activestorage (6.1.7.4)
59
+ actionpack (= 6.1.7.4)
60
+ activejob (= 6.1.7.4)
61
+ activerecord (= 6.1.7.4)
62
+ activesupport (= 6.1.7.4)
63
+ marcel (~> 1.0)
64
+ mini_mime (>= 1.1.0)
65
+ activesupport (6.1.7.4)
66
+ concurrent-ruby (~> 1.0, >= 1.0.2)
67
+ i18n (>= 1.6, < 2)
68
+ minitest (>= 5.1)
69
+ tzinfo (~> 2.0)
70
+ zeitwerk (~> 2.3)
71
+ awesome_print (1.9.2)
72
+ builder (3.2.4)
73
+ concurrent-ruby (1.2.2)
74
+ crass (1.0.6)
75
+ date (3.3.3)
76
+ erubi (1.12.0)
77
+ globalid (1.1.0)
78
+ activesupport (>= 5.0)
79
+ i18n (1.14.1)
80
+ concurrent-ruby (~> 1.0)
81
+ loofah (2.21.3)
82
+ crass (~> 1.0.2)
83
+ nokogiri (>= 1.12.0)
84
+ mail (2.8.1)
85
+ mini_mime (>= 0.1.1)
86
+ net-imap
87
+ net-pop
88
+ net-smtp
89
+ marcel (1.0.2)
90
+ media_types (2.3.2)
91
+ method_source (1.0.0)
92
+ mini_mime (1.1.5)
93
+ minitest (5.19.0)
94
+ net-imap (0.3.7)
95
+ date
96
+ net-protocol
97
+ net-pop (0.1.2)
98
+ net-protocol
99
+ net-protocol (0.2.1)
100
+ timeout
101
+ net-smtp (0.3.3)
102
+ net-protocol
103
+ nio4r (2.5.9)
104
+ nokogiri (1.15.4-x64-mingw32)
105
+ racc (~> 1.4)
106
+ oj (3.16.0)
107
+ racc (1.7.1)
108
+ rack (2.2.8)
109
+ rack-test (2.1.0)
110
+ rack (>= 1.3)
111
+ rails (6.1.7.4)
112
+ actioncable (= 6.1.7.4)
113
+ actionmailbox (= 6.1.7.4)
114
+ actionmailer (= 6.1.7.4)
115
+ actionpack (= 6.1.7.4)
116
+ actiontext (= 6.1.7.4)
117
+ actionview (= 6.1.7.4)
118
+ activejob (= 6.1.7.4)
119
+ activemodel (= 6.1.7.4)
120
+ activerecord (= 6.1.7.4)
121
+ activestorage (= 6.1.7.4)
122
+ activesupport (= 6.1.7.4)
123
+ bundler (>= 1.15.0)
124
+ railties (= 6.1.7.4)
125
+ sprockets-rails (>= 2.0.0)
126
+ rails-dom-testing (2.2.0)
127
+ activesupport (>= 5.0.0)
128
+ minitest
129
+ nokogiri (>= 1.6)
130
+ rails-html-sanitizer (1.6.0)
131
+ loofah (~> 2.21)
132
+ nokogiri (~> 1.14)
133
+ railties (6.1.7.4)
134
+ actionpack (= 6.1.7.4)
135
+ activesupport (= 6.1.7.4)
136
+ method_source
137
+ rake (>= 12.2)
138
+ thor (~> 1.0)
139
+ rake (13.0.6)
140
+ sprockets (4.2.0)
141
+ concurrent-ruby (~> 1.0)
142
+ rack (>= 2.2.4, < 4)
143
+ sprockets-rails (3.4.2)
144
+ actionpack (>= 5.2)
145
+ activesupport (>= 5.2)
146
+ sprockets (>= 3.0.0)
147
+ thor (1.2.2)
148
+ timeout (0.4.0)
149
+ tzinfo (2.0.6)
150
+ concurrent-ruby (~> 1.0)
151
+ websocket-driver (0.7.6)
152
+ websocket-extensions (>= 0.1.0)
153
+ websocket-extensions (0.1.5)
154
+ zeitwerk (2.6.11)
155
+
156
+ PLATFORMS
157
+ x64-mingw32
158
+
159
+ DEPENDENCIES
160
+ awesome_print
161
+ bundler
162
+ media_types-serialization!
163
+ minitest (~> 5.0)
164
+ oj
165
+ rails (~> 6.0)
166
+ rake (~> 13.0)
167
+
168
+ BUNDLED WITH
169
+ 2.1.4
data/README.md CHANGED
@@ -471,7 +471,7 @@ class BookController < ActionController::API
471
471
  book = Book.new
472
472
  book.title = 'Everything, abridged'
473
473
 
474
- render_media serialize_media(book)
474
+ render_media book
475
475
  end
476
476
 
477
477
  def create
@@ -517,14 +517,14 @@ class BookController < ActionController::API
517
517
  book = Book.new
518
518
  book.title = 'Everything, abridged'
519
519
 
520
- render_media serialize_media(book)
520
+ render_media book
521
521
  end
522
522
 
523
523
  def create
524
524
  book = deserialize(request)
525
525
  book.save!
526
526
 
527
- render_media serialize_media(book)
527
+ render_media book
528
528
  end
529
529
  end
530
530
  ```
@@ -648,7 +648,7 @@ class BookController < ActionController::API
648
648
  book = Book.new
649
649
  book.title = 'Everything, abridged'
650
650
 
651
- render_media serialize_media(book)
651
+ render_media book
652
652
  end
653
653
 
654
654
  def create
@@ -12,8 +12,8 @@ module MediaTypes
12
12
  def unvalidated(prefix)
13
13
  self.serializer_validated = false
14
14
  self.serializer_validator = FakeValidator.new(prefix)
15
- self.serializer_input_registration = SerializationRegistration.new(:input)
16
- self.serializer_output_registration = SerializationRegistration.new(:output)
15
+ self.serializer_input_registrations = {}
16
+ self.serializer_output_registrations = {}
17
17
  end
18
18
 
19
19
  def validator(validator = nil)
@@ -22,8 +22,8 @@ module MediaTypes
22
22
 
23
23
  self.serializer_validated = true
24
24
  self.serializer_validator = validator
25
- self.serializer_input_registration = SerializationRegistration.new(:input)
26
- self.serializer_output_registration = SerializationRegistration.new(:output)
25
+ self.serializer_input_registrations = {}
26
+ self.serializer_output_registrations = {}
27
27
  end
28
28
 
29
29
  def disable_wildcards
@@ -40,11 +40,15 @@ module MediaTypes
40
40
 
41
41
  raise ValidatorNotSpecifiedError, :output if serializer_validator.nil?
42
42
 
43
+ unless serializer_output_registrations.has_key? view
44
+ serializer_output_registrations[view] = SerializationRegistration.new(:output)
45
+ end
46
+
43
47
  versions.each do |v|
44
48
  validator = serializer_validator.view(view).version(v)
45
49
  validator.override_suffix(:json) unless serializer_validated
46
50
 
47
- serializer_output_registration.register_block(
51
+ serializer_output_registrations[view].register_block(
48
52
  self,
49
53
  validator,
50
54
  v,
@@ -62,12 +66,16 @@ module MediaTypes
62
66
 
63
67
  raise ValidatorNotSpecifiedError, :output if serializer_validator.nil?
64
68
 
69
+ unless serializer_output_registrations.has_key? view
70
+ serializer_output_registrations[view] = SerializationRegistration.new(:output)
71
+ end
72
+
65
73
  versions.each do |v|
66
74
  validator = serializer_validator.view(view)
67
75
  .version(v)
68
76
  .override_suffix(suffix)
69
77
 
70
- serializer_output_registration.register_block(
78
+ serializer_output_registrations[view].register_block(
71
79
  self,
72
80
  validator,
73
81
  v,
@@ -87,7 +95,11 @@ module MediaTypes
87
95
  validator = serializer_validator.view(view).override_suffix(suffix)
88
96
  victim_identifier = validator.identifier
89
97
 
90
- serializer_output_registration.register_alias(
98
+ unless serializer_output_registrations.has_key? view
99
+ serializer_output_registrations[view] = SerializationRegistration.new(:output)
100
+ end
101
+
102
+ serializer_output_registrations[view].register_alias(
91
103
  self,
92
104
  media_type_identifier,
93
105
  victim_identifier,
@@ -106,7 +118,11 @@ module MediaTypes
106
118
  validator = serializer_validator.view(view).override_suffix(suffix)
107
119
  victim_identifier = validator.identifier
108
120
 
109
- serializer_output_registration.register_alias(
121
+ unless serializer_output_registrations.has_key? view
122
+ serializer_output_registrations[view] = SerializationRegistration.new(:output)
123
+ end
124
+
125
+ serializer_output_registrations[view].register_alias(
110
126
  self,
111
127
  media_type_identifier,
112
128
  victim_identifier,
@@ -122,11 +138,15 @@ module MediaTypes
122
138
 
123
139
  raise ValidatorNotSpecifiedError, :input if serializer_validator.nil?
124
140
 
141
+ unless serializer_input_registrations.has_key? view
142
+ serializer_input_registrations[view] = SerializationRegistration.new(:input)
143
+ end
144
+
125
145
  versions.each do |v|
126
146
  validator = serializer_validator.view(view).version(v)
127
147
  validator.override_suffix(:json) unless serializer_validated
128
148
 
129
- serializer_input_registration.register_block(self, validator, v, block, false)
149
+ serializer_input_registrations[view].register_block(self, validator, v, block, false)
130
150
  end
131
151
  end
132
152
 
@@ -136,10 +156,14 @@ module MediaTypes
136
156
 
137
157
  raise ValidatorNotSpecifiedError, :input if serializer_validator.nil?
138
158
 
159
+ unless serializer_input_registrations.has_key? view
160
+ serializer_input_registrations[view] = SerializationRegistration.new(:input)
161
+ end
162
+
139
163
  versions.each do |v|
140
164
  validator = serializer_validator.view(view).version(v).override_suffix(suffix)
141
165
 
142
- serializer_input_registration.register_block(self, validator, v, block, true)
166
+ serializer_input_registrations[view].register_block(self, validator, v, block, true)
143
167
  end
144
168
  end
145
169
 
@@ -151,7 +175,11 @@ module MediaTypes
151
175
  validator = serializer_validator.view(view).override_suffix(suffix)
152
176
  victim_identifier = validator.identifier
153
177
 
154
- serializer_input_registration.register_alias(
178
+ unless serializer_input_registrations.has_key? view
179
+ serializer_input_registrations[view] = SerializationRegistration.new(:input)
180
+ end
181
+
182
+ serializer_input_registrations[view].register_alias(
155
183
  self,
156
184
  media_type_identifier,
157
185
  victim_identifier,
@@ -169,7 +197,11 @@ module MediaTypes
169
197
  validator = serializer_validator.view(view).override_suffix(suffix)
170
198
  victim_identifier = validator.identifier
171
199
 
172
- serializer_input_registration.register_alias(
200
+ unless serializer_input_registrations.has_key? view
201
+ serializer_input_registrations[view] = SerializationRegistration.new(:input)
202
+ end
203
+
204
+ serializer_input_registrations[view].register_alias(
173
205
  self,
174
206
  media_type_identifier,
175
207
  victim_identifier,
@@ -181,19 +213,40 @@ module MediaTypes
181
213
 
182
214
  def serialize(victim, media_type_identifier, context:, dsl: nil, raw: nil)
183
215
  dsl ||= SerializationDSL.new(self, context: context)
184
- serializer_output_registration.call(victim, media_type_identifier.to_s, context, dsl: dsl, raw: raw)
216
+
217
+ merged_output_registrations = SerializationRegistration.new(:output)
218
+ serializer_output_registrations.keys.each do |k|
219
+ merged_output_registrations = merged_output_registrations.merge(serializer_output_registrations[k])
220
+ end
221
+
222
+ merged_output_registrations.call(victim, media_type_identifier.to_s, context, dsl: dsl, raw: raw)
185
223
  end
186
224
 
187
225
  def deserialize(victim, media_type_identifier, context:)
188
- serializer_input_registration.call(victim, media_type_identifier, context)
226
+ merged_input_registrations = SerializationRegistration.new(:input)
227
+ serializer_input_registrations.keys.each do |k|
228
+ merged_input_registrations = merged_input_registrations.merge(serializer_input_registrations[k])
229
+ end
230
+
231
+ merged_input_registrations.call(victim, media_type_identifier, context)
189
232
  end
190
233
 
191
234
  def outputs_for(views:)
192
- serializer_output_registration.filter(views: views)
235
+ merged_output_registrations = SerializationRegistration.new(:output)
236
+ views.each do |k|
237
+ merged_output_registrations = merged_output_registrations.merge(serializer_output_registrations[k]) if serializer_output_registrations.has_key?(k)
238
+ end
239
+
240
+ merged_output_registrations
193
241
  end
194
242
 
195
243
  def inputs_for(views:)
196
- serializer_input_registration.filter(views: views)
244
+ merged_input_registrations = SerializationRegistration.new(:input)
245
+ views.each do |k|
246
+ merged_input_registrations = merged_input_registrations.merge(serializer_input_registrations[k]) if serializer_input_registrations.has_key?(k)
247
+ end
248
+
249
+ merged_input_registrations
197
250
  end
198
251
  end
199
252
 
@@ -205,8 +258,8 @@ module MediaTypes
205
258
  class << self
206
259
  attr_accessor :serializer_validated
207
260
  attr_accessor :serializer_validator
208
- attr_accessor :serializer_input_registration
209
- attr_accessor :serializer_output_registration
261
+ attr_accessor :serializer_input_registrations
262
+ attr_accessor :serializer_output_registrations
210
263
  attr_accessor :serializer_disable_wildcards
211
264
  end
212
265
  end
@@ -168,14 +168,14 @@ module MediaTypes
168
168
  if defined? Oj::ParseError
169
169
  begin
170
170
  victim = MediaTypes::Serialization.json_decoder.call(victim)
171
- validator.validate!(victim)
171
+ validator.validate!(victim, loose: true)
172
172
  rescue MediaTypes::Scheme::ValidationError, Oj::ParseError, JSON::ParserError, EncodingError => inner
173
173
  raise InputValidationFailedError, inner
174
174
  end
175
175
  else
176
176
  begin
177
177
  victim = MediaTypes::Serialization.json_decoder.call(victim)
178
- validator.validate!(victim)
178
+ validator.validate!(victim, loose: true)
179
179
  rescue MediaTypes::Scheme::ValidationError, JSON::ParserError, EncodingError => inner
180
180
  raise InputValidationFailedError, inner
181
181
  end
@@ -22,6 +22,81 @@ module MediaTypes
22
22
  viewer.to_s
23
23
  end
24
24
 
25
+ def self.to_input_identifiers(serializers)
26
+ serializers.flat_map do |s|
27
+ s[:serializer].inputs_for(views: [s[:view]]).registrations.keys
28
+ end
29
+ end
30
+ def self.to_output_identifiers(serializers)
31
+ serializers.flat_map do |s|
32
+ s[:serializer].outputs_for(views: [s[:view]]).registrations.keys
33
+ end
34
+ end
35
+
36
+ def self.allowed_replies(context, actions)
37
+ request_path = context.request.original_fullpath.split('?')[0]
38
+
39
+ path_prefix = ENV.fetch('RAILS_RELATIVE_URL_ROOT') { '' }
40
+ request_path = request_path.sub(path_prefix, '')
41
+
42
+ my_controller = Rails.application.routes.recognize_path request_path
43
+ possible_replies = ['POST', 'PUT', 'DELETE']
44
+ enabled_replies = {}
45
+ possible_replies.each do |m|
46
+ begin
47
+ found_controller = Rails.application.routes.recognize_path request_path, method: m
48
+ if found_controller[:controller] == my_controller[:controller]
49
+ enabled_replies[m] = found_controller[:action]
50
+ end
51
+ rescue ActionController::RoutingError
52
+ # not available
53
+ end
54
+ end
55
+
56
+ input_definitions = actions[:input] || {}
57
+ output_definitions = actions[:output] || {}
58
+
59
+ result = {}
60
+ global_in = input_definitions['all_actions'] || []
61
+ global_out = output_definitions['all_actions'] || []
62
+
63
+ viewer_uri = URI.parse(context.request.original_url)
64
+ query_parts = viewer_uri.query&.split('&') || []
65
+ query_parts = query_parts.select { |q| !q.start_with? 'api_viewer=' }
66
+ viewer_uri.query = (query_parts + ["api_viewer=last"]).join('&')
67
+
68
+ enabled_replies.each do |method, action|
69
+ input_serializers = global_in + (input_definitions[action] || [])
70
+ output_serializers = global_out + (output_definitions[action] || [])
71
+ result[method] = {
72
+ input: to_input_identifiers(input_serializers),
73
+ output: to_output_identifiers(output_serializers),
74
+ }
75
+ end
76
+
77
+ result
78
+ end
79
+
80
+ def self.escape_javascript(value)
81
+ escape_map = {
82
+ "\\" => "\\\\",
83
+ "</" => '<\/',
84
+ "\r\n" => '\n',
85
+ "\n" => '\n',
86
+ "\r" => '\n',
87
+ '"' => '\\"',
88
+ "'" => "\\'",
89
+ "`" => "\\`",
90
+ "$" => "\\$"
91
+ }
92
+ escape_map[(+"\342\200\250").force_encoding(Encoding::UTF_8).encode!] = "&#x2028;"
93
+ escape_map[(+"\342\200\251").force_encoding(Encoding::UTF_8).encode!] = "&#x2029;"
94
+
95
+ value ||= ""
96
+
97
+ return value.gsub(/(\\|<\/|\r\n|\342\200\250|\342\200\251|[\n\r"']|[`]|[$])/u, escape_map).html_safe
98
+ end
99
+
25
100
  output_raw do |obj, version, context|
26
101
  original_identifier = obj[:identifier]
27
102
  registrations = obj[:registrations]
@@ -71,15 +146,25 @@ module MediaTypes
71
146
  end
72
147
  &.join("<br>\n")
73
148
 
149
+ unviewered_uri = URI.parse(context.request.original_url)
150
+ query_parts = unviewered_uri.query&.split('&') || []
151
+ query_parts = query_parts.select { |q| !q.start_with? 'api_viewer=' }
152
+ unviewered_uri.query = query_parts.join('&')
153
+
74
154
  input = OpenStruct.new(
75
155
  original_identifier: original_identifier,
76
156
  escaped_output: escaped_output,
77
157
  api_fied_links: api_fied_links,
78
158
  media_types: media_types,
79
- css: CommonCSS.css
159
+ css: CommonCSS.css,
160
+ etag: obj[:etag],
161
+ allowed_replies: allowed_replies(context, obj[:actions]),
162
+ escape_javascript: method(:escape_javascript),
163
+ unviewered_uri: unviewered_uri
80
164
  )
81
165
 
82
166
  template = ERB.new <<-TEMPLATE
167
+ <!DOCTYPE html>
83
168
  <html lang="en">
84
169
  <head>
85
170
  <meta content="width=device-width, initial-scale=1" name="viewport">
@@ -118,6 +203,168 @@ module MediaTypes
118
203
  </ul>
119
204
  </section>
120
205
  </nav>
206
+ <% if allowed_replies.any? %>
207
+ <section id="reply">
208
+ <details>
209
+ <summary>Reply</summary>
210
+ <div class="reply-indent">
211
+ <noscript>Javascript is required to submit custom responses back to the server</noscript>
212
+ <form id="reply-form" hidden>
213
+ <div class="form-table">
214
+ <label class="form-row">
215
+ <div class="cell label">Method:</div>
216
+ <% if allowed_replies.keys.count == 1 %>
217
+ <input type="hidden" name="method" value="<%= allowed_replies.keys[0] %>">
218
+ <div class="cell"><%= allowed_replies.keys[0] %></div>
219
+ <% else %>
220
+ <select class="cell" name="method">
221
+ <% allowed_replies.keys.each do |method| %>
222
+ <option value="<%= method %>"><%= method %></option>
223
+ <% end %>
224
+ </select>
225
+ <% end %>
226
+ </label>
227
+ <label class="form-row"><div class="cell label">Send:</div> <select class="cell" name="request-content-type"></select></label>
228
+ <label class="form-row"><div class="cell label">Receive:</div> <select class="cell" name="response-content-type"></select></label>
229
+ </div>
230
+ <textarea name="request-content"></textarea>
231
+ <input type="button" name="submit" value="Reply"><span id="reply-status-code" hidden> - sending...</span>
232
+ <hr>
233
+ <code id="reply-response" hidden>
234
+ </code>
235
+ </form>
236
+ <script>
237
+ {
238
+ let form = document.getElementById("reply-form")
239
+ form.removeAttribute('hidden')
240
+
241
+ let action_data = JSON.parse("<%= escape_javascript.call(allowed_replies.to_json) %>")
242
+
243
+ let methodElem = form.elements["method"]
244
+ let requestTypeElem = form.elements["request-content-type"]
245
+ let responseTypeElem = form.elements["response-content-type"]
246
+ let contentElem = form.elements["request-content"]
247
+ let submitElem = form.elements["submit"]
248
+ let replyResponseElem = document.getElementById("reply-response")
249
+ let replyStatusCodeElem = document.getElementById("reply-status-code")
250
+ let selectRequestType = function() {
251
+ let selected = requestTypeElem.value
252
+
253
+ if (selected == "")
254
+ contentElem.setAttribute("hidden", "")
255
+ else
256
+ contentElem.removeAttribute("hidden")
257
+
258
+ if (methodElem.value == "PUT" && contentElem.value.trim() == "") {
259
+ let currentRequestType = document.querySelector("#representations .active").textContent.trim()
260
+ if (currentRequestType == requestTypeElem.value) {
261
+ let outputElem = document.getElementById("output")
262
+ contentElem.value = outputElem.
263
+ textContent.
264
+ trim().
265
+ replaceAll(String.fromCharCode(160), " ")
266
+ }
267
+ }
268
+ }
269
+
270
+ let selectMethod = function() {
271
+ let selected = methodElem.value
272
+ submitElem.setAttribute("value", selected)
273
+
274
+ let mediatypes = action_data[selected]
275
+
276
+ while(requestTypeElem.firstChild)
277
+ requestTypeElem.removeChild(requestTypeElem.lastChild)
278
+ mediatypes["input"].forEach(mediatype => {
279
+ let option = document.createElement("option")
280
+ option.setAttribute("value", mediatype)
281
+ option.textContent = mediatype
282
+ requestTypeElem.appendChild(option)
283
+ })
284
+ let noneOption = document.createElement("option")
285
+ noneOption.setAttribute("value", "")
286
+ noneOption.textContent = "None"
287
+ requestTypeElem.appendChild(noneOption)
288
+
289
+ while(responseTypeElem.firstChild)
290
+ responseTypeElem.removeChild(responseTypeElem.lastChild)
291
+ mediatypes["output"].forEach(mediatype => {
292
+ let option = document.createElement("option")
293
+ option.setAttribute("value", mediatype)
294
+ option.textContent = mediatype
295
+ responseTypeElem.appendChild(option)
296
+ })
297
+ let anyOption = document.createElement("option")
298
+ anyOption.setAttribute("value", "")
299
+ anyOption.textContent = "Any"
300
+ responseTypeElem.appendChild(anyOption)
301
+
302
+ selectRequestType()
303
+ }
304
+
305
+ let onSubmit = async function() {
306
+ submitElem.setAttribute("disabled", "")
307
+ let method = methodElem.value
308
+ let requestContentType = requestTypeElem.value
309
+ let requestContent = contentElem.value
310
+ var responseAccept = responseTypeElem.value + ", application/problem+json; q=0.2, */*; q=0.1"
311
+ if (responseTypeElem.value == "")
312
+ responseAccept = "application/problem+json, */*; q=0.1"
313
+
314
+ let headers = {
315
+ Accept: responseAccept,
316
+ }
317
+ if (method == "PUT") {
318
+ let etag = "<%= escape_javascript.call(etag) %>"
319
+ if (etag != "") {
320
+ headers['If-Match'] = etag
321
+ }
322
+ }
323
+ let body = undefined
324
+ if (requestContentType != "") {
325
+ headers["Content-Type"] = requestContentType
326
+ body = requestContent
327
+ }
328
+
329
+ replyResponseElem.textContent = ""
330
+ replyStatusCodeElem.textContent = " - sending..."
331
+ replyStatusCodeElem.removeAttribute("hidden")
332
+
333
+ try {
334
+ let response = await fetch("<%= escape_javascript.call(unviewered_uri.to_s) %>", {
335
+ method: method,
336
+ mode: "same-origin",
337
+ credentials: "same-origin",
338
+ redirect: "follow",
339
+ headers: headers,
340
+ body: body
341
+ })
342
+
343
+ replyStatusCodeElem.textContent = " - Status " + response.status + " " + response.statusText
344
+ replyResponseElem.removeAttribute("hidden")
345
+ replyResponseElem.textContent = await response.text()
346
+ replyResponseElem.innerHTML = replyResponseElem.
347
+ innerHTML.
348
+ replaceAll("\\n", "<br>\\n").
349
+ replaceAll(" ", "&nbsp; ")
350
+ } catch (error) {
351
+ replyStatusCodeElem.textContent = " - Failed: " + error.message
352
+ } finally {
353
+ submitElem.removeAttribute("disabled")
354
+ }
355
+ }
356
+
357
+ requestTypeElem.addEventListener("change", (e) => selectRequestType())
358
+ methodElem.addEventListener("change", (e) => selectMethod())
359
+ submitElem.addEventListener("click", (e) => onSubmit())
360
+
361
+ addEventListener("DOMContentLoaded", (event) => selectMethod());
362
+ }
363
+ </script>
364
+ </div>
365
+ </details>
366
+ </section>
367
+ <% end %>
121
368
  <main>
122
369
  <code id="output">
123
370
  <%= escaped_output %>
@@ -49,65 +49,76 @@ module MediaTypes
49
49
  min-height: 100%;
50
50
  background: <%= background %>;
51
51
  }
52
-
52
+
53
53
  body {
54
54
  color: #fff;
55
- margin-left: 10em;
56
- margin-right: 10em;
55
+ margin-left: 2em;
56
+ margin-right: 2em;
57
57
  margin-top: 1em;
58
-
58
+ max-width: 1200px;
59
+
59
60
  font-family: -apple-system, ".SFNSText-Regular", "San Francisco", "Roboto", "Segoe UI", "Helvetica Neue", "Lucida Grande", sans-serif;
60
- font-size: 16px;
61
- line-height: 1.6;
62
- -webkit-font-feature-settings: "kern","liga","clig","calt";
63
- font-feature-settings: "kern","liga","clig","calt";
64
- -webkit-font-smoothing: antialiased;
65
- -moz-osx-font-smoothing: grayscale
66
- }
67
-
61
+ font-size: 16px;
62
+ line-height: 1.6;
63
+ -webkit-font-feature-settings: "kern","liga","clig","calt";
64
+ font-feature-settings: "kern","liga","clig","calt";
65
+ -webkit-font-smoothing: antialiased;
66
+ -moz-osx-font-smoothing: grayscale
67
+ overflow-x: hidden;
68
+ }
69
+
70
+ main {
71
+ max-width: 100%;
72
+ }
73
+
68
74
  header {
69
75
  display: inline-block;
76
+ max-width: 100%;
70
77
  }
71
-
78
+
72
79
  a:link {
73
- color: #293590;
80
+ color: #007bff;
74
81
  }
75
82
  a:visited {
76
- color: #080F43;
83
+ color: #9c27b0;
77
84
  }
78
85
  a:hover {
79
- color: #5E7EFF;
86
+ color: #00bcd4;
80
87
  }
81
-
88
+
82
89
  #logo {
83
90
  width: <%= logo_width %>em;
84
- height: 6em;
85
- background-repeat: no-repeat;
86
- background-position-x: right;
87
- background-position-y: center;
91
+ height: 5em;
92
+ background-repeat: no-repeat;
93
+ background-position-x: right;
94
+ background-position-y: center;
88
95
  background-image: url(<%= logo_url %>);
89
96
  float: left;
90
- margin-right: 0.75em;
97
+ margin-right: 2em;
91
98
  }
92
-
99
+
93
100
  header h1 {
94
101
  clear: right;
95
102
  text-overflow: ellipsis;
96
103
  white-space: nowrap;
97
104
  overflow: hidden;
105
+
106
+ font-size: 1.5em;
107
+ line-height: 2em;
98
108
  }
99
-
109
+
100
110
  #content {
101
111
  margin-top: 1em;
102
- padding-left: 3em;
103
- padding-right: 3em;
104
- padding-bottom: 3em;
112
+ padding-left: 1em;
113
+ padding-right: 1em;
114
+ padding-bottom: 1em;
105
115
  color: #060B34;
106
116
  background-color: #fff;
107
117
  border-radius: 1em;
108
118
  border: 1px solid #E0E1E4;
119
+ overflow: auto;
109
120
  }
110
-
121
+
111
122
  nav h2 {
112
123
  font-size: 1em;
113
124
  line-height: 1.25em;
@@ -116,7 +127,7 @@ module MediaTypes
116
127
  nav .label {
117
128
  float: left;
118
129
  }
119
-
130
+
120
131
  nav ul {
121
132
  clear: right;
122
133
  display: inline-block;
@@ -138,17 +149,15 @@ module MediaTypes
138
149
  content: "|";
139
150
  margin-right: 0.3em;
140
151
  }
141
-
152
+
142
153
  nav #representations {
143
- margin-left: -2em;
144
- margin-right: -2em;
145
- margin-bottom: 2em;
154
+ margin-bottom: 1em;
146
155
  }
147
156
  nav hr {
148
157
  border: none;
149
158
  border-top: solid 1px #E0E1E4;
150
159
  }
151
-
160
+
152
161
  nav #links {
153
162
  display: inline-block;
154
163
  margin-bottom: 1em;
@@ -156,7 +165,42 @@ module MediaTypes
156
165
  nav #links ul {
157
166
  float: left;
158
167
  }
168
+
169
+ #output {
170
+ font-size: .9em;
171
+ }
172
+
173
+ #reply .reply-indent {
174
+ border-left: 0.5em solid lightgray;
175
+ padding-left: 1em;
176
+ }
177
+
178
+ #reply .form-table {
179
+ display: table;
180
+ border-spacing: 1em 0;
181
+ margin-left: -1em;
182
+ margin-bottom: 0.2em;
183
+ }
184
+
185
+ #reply .form-row {
186
+ display: table-row;
187
+ }
159
188
 
189
+ #reply .cell {
190
+ display: table-cell;
191
+ }
192
+
193
+ #reply textarea {
194
+ width: 100%;
195
+ height: 6em;
196
+ clear: both;
197
+ }
198
+
199
+ #reply #reply-status-code {
200
+ font-style: italic;
201
+ font-size: 80%;
202
+ }
203
+
160
204
  TEMPLATE
161
205
  template = ERB.new custom_css unless custom_css.nil?
162
206
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module MediaTypes
4
4
  module Serialization
5
- VERSION = '1.4.0'
5
+ VERSION = '2.0.4'
6
6
  end
7
7
  end
@@ -195,12 +195,14 @@ module MediaTypes
195
195
 
196
196
  validator = FakeValidator.new(as.nil? ? 'text/html' : as)
197
197
 
198
- block = lambda { |_, _, controller|
198
+ block = lambda { |victim, _, controller|
199
199
  options = {}
200
200
  options[:layout] = layout unless layout.nil?
201
201
  options[:template] = view unless view.nil?
202
202
  options[:formats] = formats unless formats.nil?
203
203
  options[:variants] = variants unless variants.nil?
204
+ options[:locals] = victim if victim.is_a?(::Hash)
205
+ options[:assigns] = { media: victim }
204
206
 
205
207
  controller.render_to_string(**options)
206
208
  }
@@ -445,9 +447,12 @@ module MediaTypes
445
447
  @serialization_override_accept = registration.registrations.keys.last
446
448
  end
447
449
 
448
- return nil unless registration.has? @serialization_override_accept
450
+ return @serialization_override_accept if registration.has? @serialization_override_accept
449
451
 
450
- return @serialization_override_accept
452
+ # Always render problems in api viewer if we can't show chosen override
453
+ return 'application/problem+json' if registration.has? 'application/problem+json'
454
+
455
+ return nil
451
456
  end
452
457
 
453
458
  # Ruby negotiation
@@ -536,10 +541,14 @@ module MediaTypes
536
541
  self
537
542
  )
538
543
  rescue InputValidationFailedError => e
539
- serializers = @serialization_input_validation_failed_serializer || [
540
- MediaTypes::Serialization::Serializers::ProblemSerializer,
541
- MediaTypes::Serialization::Serializers::InputValidationErrorSerializer
542
- ]
544
+ serializers = if defined?(@serialization_input_validation_failed_serializer)
545
+ @serialization_input_validation_failed_serializer
546
+ else
547
+ [
548
+ MediaTypes::Serialization::Serializers::ProblemSerializer,
549
+ MediaTypes::Serialization::Serializers::InputValidationErrorSerializer
550
+ ]
551
+ end
543
552
  registrations = SerializationRegistration.new(:output)
544
553
  serializers.each do |s|
545
554
  registrations = registrations.merge(s.outputs_for(views: [nil, :html]))
@@ -551,7 +560,7 @@ module MediaTypes
551
560
  error: e
552
561
  }
553
562
 
554
- render_media nil, serializers: [registrations], status: :unprocessable_entity do
563
+ render_media nil, serializers: [registrations], status: :bad_request do
555
564
  serializer MediaTypes::Serialization::Serializers::InputValidationErrorSerializer, input
556
565
  serializer MediaTypes::Serialization::Serializers::ProblemSerializer do
557
566
  problem = Problem.new(e)
@@ -577,7 +586,7 @@ module MediaTypes
577
586
 
578
587
  endpoint_matched_identifier = resolve_media_type(
579
588
  request,
580
- description_serializer.serializer_output_registration,
589
+ description_serializer.serializer_output_registrations[nil],
581
590
  allow_last: false
582
591
  )
583
592
 
@@ -654,7 +663,9 @@ module MediaTypes
654
663
  identifier: identifier,
655
664
  registrations: registrations,
656
665
  output: result,
657
- links: links
666
+ links: links,
667
+ etag: response.get_header('ETag'),
668
+ actions: @serialization_available_serializers
658
669
  }
659
670
  wrapped = @serialization_wrapping_renderer.serialize input, '*/*', context: self
660
671
  render body: wrapped
@@ -664,6 +675,9 @@ module MediaTypes
664
675
  end
665
676
 
666
677
  if context.serialization_custom_render.nil?
678
+ status = options.delete(:status)
679
+ response.status = status if status
680
+
667
681
  render body: result, **options
668
682
 
669
683
  response.content_type = registrations.identifier_for(identifier)
@@ -37,7 +37,7 @@ Gem::Specification.new do |spec|
37
37
 
38
38
  spec.add_dependency 'actionpack', '>= 6.0.0'
39
39
  spec.add_dependency 'activesupport', '>= 6.0.0'
40
- spec.add_dependency 'media_types', '>= 2.2.0', '< 3.0.0'
40
+ spec.add_dependency 'media_types', '>= 2.2.3', '< 3.0.0'
41
41
 
42
42
  spec.add_development_dependency 'awesome_print'
43
43
  spec.add_development_dependency 'bundler'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: media_types-serialization
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ version: 2.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Derk-Jan Karrenbeld
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2023-03-24 00:00:00.000000000 Z
12
+ date: 2023-08-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: actionpack
@@ -45,7 +45,7 @@ dependencies:
45
45
  requirements:
46
46
  - - ">="
47
47
  - !ruby/object:Gem::Version
48
- version: 2.2.0
48
+ version: 2.2.3
49
49
  - - "<"
50
50
  - !ruby/object:Gem::Version
51
51
  version: 3.0.0
@@ -55,7 +55,7 @@ dependencies:
55
55
  requirements:
56
56
  - - ">="
57
57
  - !ruby/object:Gem::Version
58
- version: 2.2.0
58
+ version: 2.2.3
59
59
  - - "<"
60
60
  - !ruby/object:Gem::Version
61
61
  version: 3.0.0
@@ -152,6 +152,8 @@ extensions: []
152
152
  extra_rdoc_files: []
153
153
  files:
154
154
  - ".github/workflows/ci.yml"
155
+ - ".github/workflows/publish-bookworm.yml"
156
+ - ".github/workflows/publish-sid.yml"
155
157
  - ".gitignore"
156
158
  - ".idea/.rakeTasks"
157
159
  - ".idea/dictionaries/Derk_Jan.xml"