viu 0.0.0 → 0.0.5

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: 3f214b4ad59e98f74c0fdb8f8417d407d6a6a0984836fe5707d7d65eef4273e0
4
- data.tar.gz: c4b00a30be63eec767680ae34fe7c360ad35b37f570f45473e576753a69a8b18
3
+ metadata.gz: 17de95e5852c60464030292d611b3baa74bc9e5b72de1dab5cc6f820241b35cb
4
+ data.tar.gz: 1c04d6ee4f5ecb39bd846a7673bb542a2f1c34aacafa1acdf84cabeb799ffedb
5
5
  SHA512:
6
- metadata.gz: b35fee48fbfdeb0396e85bdc230743c35df5580d604cd278e5710936111e1eb84f578536d73165ef079b143a47dc7e70738064f1d7953c22b697061979833e62
7
- data.tar.gz: d5df5e9a68a80990a1b4d242067c15f39ecad3b42004767b5fc3488b8d6a0baf1928473a7a57ee73d7b9e892439b3830e0947fa31a674b3bd5484e9faa33df04
6
+ metadata.gz: c4a88a1afc091b1a1840bdc07bbc69d3c12b0ed2725875cc7d457bd12928188dd514c0aa27e538cee12d092eedff4346c15f76ee7ee47f00cc0880645165b48f
7
+ data.tar.gz: '099c2aa54ac9281b47a0cc777927b4076265bedbd873c39cc03b1c23a8adcfa1d714036976ee961b3a707d69565cdd3ba75e3b440c5faa46061228996d8ab802'
@@ -0,0 +1,13 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ /test/support/dummy/tmp
10
+ /test/support/dummy/log
11
+ *.gem
12
+
13
+ /gemfiles/*.gemfile.lock
@@ -0,0 +1,7 @@
1
+ ---
2
+ sudo: false
3
+ language: ruby
4
+ cache: bundler
5
+ rvm:
6
+ - 2.6.3
7
+ before_install: gem install bundler -v 1.17.2
@@ -0,0 +1,15 @@
1
+ # appraise "rails-5-0" do
2
+ # gem "rails", "~> 5.0.0"
3
+ # end
4
+
5
+ # appraise "rails-5-1" do
6
+ # gem "rails", "~> 5.1.0"
7
+ # end
8
+
9
+ appraise "rails-5-2" do
10
+ gem "rails", "~> 5.2.0"
11
+ end
12
+
13
+ appraise "rails-6-0" do
14
+ gem "rails", "~> 6.0.0"
15
+ end
@@ -0,0 +1,28 @@
1
+ ## 0.0.5 2020-12-01
2
+
3
+ - Added support for Rails 6.1.0.rc1
4
+ - Fixed bug with views not having access to compiled template methods (using #compiled_method_container)
5
+
6
+ ## 0.0.4 2020-11-29
7
+
8
+ - Added support for Rails ~> 6.0.0
9
+
10
+ ## 0.0.3 2020-09-02
11
+
12
+ - Added Viu::Json
13
+ - Added Viu::Xml
14
+ - Allow Viu::Html template! to receive a proc
15
+
16
+ ## 0.0.2 2020-08-16
17
+
18
+ ### Added
19
+
20
+ - Improve test helpers
21
+
22
+ ### Fixed
23
+
24
+ - Viu::Html#controller should be public
25
+
26
+ ## 0.0.1 2020-08-10
27
+
28
+ First public release
@@ -0,0 +1,74 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project team at mrbongiolo@hey.com. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
+ available at [http://contributor-covenant.org/version/1/4][version]
72
+
73
+ [homepage]: http://contributor-covenant.org
74
+ [version]: http://contributor-covenant.org/version/1/4/
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ gemspec
6
+
7
+ gem "rails", github: "rails/rails"
8
+ gem "oj"
@@ -0,0 +1,177 @@
1
+ GIT
2
+ remote: https://github.com/rails/rails
3
+ revision: 7503ef9490583f7b2c3a475edd2bb1b7de0afcac
4
+ specs:
5
+ actioncable (6.1.0.rc1)
6
+ actionpack (= 6.1.0.rc1)
7
+ activesupport (= 6.1.0.rc1)
8
+ nio4r (~> 2.0)
9
+ websocket-driver (>= 0.6.1)
10
+ actionmailbox (6.1.0.rc1)
11
+ actionpack (= 6.1.0.rc1)
12
+ activejob (= 6.1.0.rc1)
13
+ activerecord (= 6.1.0.rc1)
14
+ activestorage (= 6.1.0.rc1)
15
+ activesupport (= 6.1.0.rc1)
16
+ mail (>= 2.7.1)
17
+ actionmailer (6.1.0.rc1)
18
+ actionpack (= 6.1.0.rc1)
19
+ actionview (= 6.1.0.rc1)
20
+ activejob (= 6.1.0.rc1)
21
+ activesupport (= 6.1.0.rc1)
22
+ mail (~> 2.5, >= 2.5.4)
23
+ rails-dom-testing (~> 2.0)
24
+ actionpack (6.1.0.rc1)
25
+ actionview (= 6.1.0.rc1)
26
+ activesupport (= 6.1.0.rc1)
27
+ rack (~> 2.0, >= 2.0.9)
28
+ rack-test (>= 0.6.3)
29
+ rails-dom-testing (~> 2.0)
30
+ rails-html-sanitizer (~> 1.0, >= 1.2.0)
31
+ actiontext (6.1.0.rc1)
32
+ actionpack (= 6.1.0.rc1)
33
+ activerecord (= 6.1.0.rc1)
34
+ activestorage (= 6.1.0.rc1)
35
+ activesupport (= 6.1.0.rc1)
36
+ nokogiri (>= 1.8.5)
37
+ actionview (6.1.0.rc1)
38
+ activesupport (= 6.1.0.rc1)
39
+ builder (~> 3.1)
40
+ erubi (~> 1.4)
41
+ rails-dom-testing (~> 2.0)
42
+ rails-html-sanitizer (~> 1.1, >= 1.2.0)
43
+ activejob (6.1.0.rc1)
44
+ activesupport (= 6.1.0.rc1)
45
+ globalid (>= 0.3.6)
46
+ activemodel (6.1.0.rc1)
47
+ activesupport (= 6.1.0.rc1)
48
+ activerecord (6.1.0.rc1)
49
+ activemodel (= 6.1.0.rc1)
50
+ activesupport (= 6.1.0.rc1)
51
+ activestorage (6.1.0.rc1)
52
+ actionpack (= 6.1.0.rc1)
53
+ activejob (= 6.1.0.rc1)
54
+ activerecord (= 6.1.0.rc1)
55
+ activesupport (= 6.1.0.rc1)
56
+ marcel (~> 0.3.1)
57
+ mimemagic (~> 0.3.2)
58
+ activesupport (6.1.0.rc1)
59
+ concurrent-ruby (~> 1.0, >= 1.0.2)
60
+ i18n (>= 1.6, < 2)
61
+ minitest (>= 5.1)
62
+ tzinfo (~> 2.0)
63
+ zeitwerk (~> 2.3)
64
+ rails (6.1.0.rc1)
65
+ actioncable (= 6.1.0.rc1)
66
+ actionmailbox (= 6.1.0.rc1)
67
+ actionmailer (= 6.1.0.rc1)
68
+ actionpack (= 6.1.0.rc1)
69
+ actiontext (= 6.1.0.rc1)
70
+ actionview (= 6.1.0.rc1)
71
+ activejob (= 6.1.0.rc1)
72
+ activemodel (= 6.1.0.rc1)
73
+ activerecord (= 6.1.0.rc1)
74
+ activestorage (= 6.1.0.rc1)
75
+ activesupport (= 6.1.0.rc1)
76
+ bundler (>= 1.15.0)
77
+ railties (= 6.1.0.rc1)
78
+ sprockets-rails (>= 2.0.0)
79
+ railties (6.1.0.rc1)
80
+ actionpack (= 6.1.0.rc1)
81
+ activesupport (= 6.1.0.rc1)
82
+ method_source
83
+ rake (>= 0.8.7)
84
+ thor (~> 1.0)
85
+
86
+ PATH
87
+ remote: .
88
+ specs:
89
+ viu (0.0.5)
90
+
91
+ GEM
92
+ remote: https://rubygems.org/
93
+ specs:
94
+ appraisal (2.3.0)
95
+ bundler
96
+ rake
97
+ thor (>= 0.14.0)
98
+ bigdecimal (2.0.0)
99
+ builder (3.2.4)
100
+ concurrent-ruby (1.1.7)
101
+ crass (1.0.6)
102
+ docile (1.3.2)
103
+ erubi (1.10.0)
104
+ globalid (0.4.2)
105
+ activesupport (>= 4.2.0)
106
+ haml (5.1.2)
107
+ temple (>= 0.8.0)
108
+ tilt
109
+ i18n (1.8.5)
110
+ concurrent-ruby (~> 1.0)
111
+ loofah (2.8.0)
112
+ crass (~> 1.0.2)
113
+ nokogiri (>= 1.5.9)
114
+ mail (2.7.1)
115
+ mini_mime (>= 0.1.1)
116
+ marcel (0.3.3)
117
+ mimemagic (~> 0.3.2)
118
+ method_source (1.0.0)
119
+ mimemagic (0.3.5)
120
+ mini_mime (1.0.2)
121
+ mini_portile2 (2.4.0)
122
+ minitest (5.14.1)
123
+ nio4r (2.5.4)
124
+ nokogiri (1.10.10)
125
+ mini_portile2 (~> 2.4.0)
126
+ oj (3.10.12)
127
+ bigdecimal (>= 1.0, < 3)
128
+ rack (2.2.3)
129
+ rack-test (1.1.0)
130
+ rack (>= 1.0, < 3)
131
+ rails-dom-testing (2.0.3)
132
+ activesupport (>= 4.2.0)
133
+ nokogiri (>= 1.6)
134
+ rails-html-sanitizer (1.3.0)
135
+ loofah (~> 2.3)
136
+ rake (12.3.3)
137
+ simplecov (0.18.5)
138
+ docile (~> 1.1)
139
+ simplecov-html (~> 0.11)
140
+ simplecov-html (0.12.2)
141
+ slim (4.1.0)
142
+ temple (>= 0.7.6, < 0.9)
143
+ tilt (>= 2.0.6, < 2.1)
144
+ sprockets (4.0.2)
145
+ concurrent-ruby (~> 1.0)
146
+ rack (> 1, < 3)
147
+ sprockets-rails (3.2.2)
148
+ actionpack (>= 4.0)
149
+ activesupport (>= 4.0)
150
+ sprockets (>= 3.0.0)
151
+ temple (0.8.2)
152
+ thor (1.0.1)
153
+ tilt (2.0.10)
154
+ tzinfo (2.0.3)
155
+ concurrent-ruby (~> 1.0)
156
+ websocket-driver (0.7.3)
157
+ websocket-extensions (>= 0.1.0)
158
+ websocket-extensions (0.1.5)
159
+ zeitwerk (2.4.2)
160
+
161
+ PLATFORMS
162
+ ruby
163
+
164
+ DEPENDENCIES
165
+ appraisal (~> 2.3)
166
+ bundler (~> 1.17)
167
+ haml (~> 5)
168
+ minitest (~> 5.0)
169
+ oj
170
+ rails!
171
+ rake (~> 12.3)
172
+ simplecov (~> 0.18.0)
173
+ slim (~> 4)
174
+ viu!
175
+
176
+ BUNDLED WITH
177
+ 1.17.2
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2020 Ralf Schmitz Bongiolo
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,402 @@
1
+ # Viu
2
+
3
+ Rails' missing View layer.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem "viu"
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ ```bash
16
+ $ bundle install
17
+ ```
18
+
19
+ Or install it yourself as:
20
+
21
+ ```bash
22
+ $ gem install viu
23
+ ```
24
+
25
+ ## Rails Setup
26
+
27
+ Add this to your `config/application.rb` file:
28
+
29
+ ```ruby
30
+ config.eager_load_paths << Rails.root.join("app/views")
31
+ ```
32
+
33
+ This will add the `app/views` folder to the eager load paths, as it is not loaded there by default.
34
+
35
+ ## Viu::Html
36
+
37
+ Probably the most common view type of the wild web lands.
38
+
39
+ ### Usage
40
+
41
+ `app/views/awesome_view.rb`:
42
+ ```ruby
43
+ class AwesomeView < Viu::Html
44
+
45
+ layout! Layouts::ApplicationLayout
46
+
47
+ def initialize(posts:)
48
+ @posts = posts
49
+ end
50
+
51
+ private
52
+
53
+ def power_level_class(power)
54
+ return "over-9000" if power > 9000
55
+
56
+ "not-awesome-enough"
57
+ end
58
+ end
59
+ ```
60
+
61
+ `app/views/awesome_view.html.erb`:
62
+ ```erb
63
+ <h1>Awesomesauce</h1>
64
+ <%- @posts.each do |post| %>
65
+ <article class="<%= power_level_class(post.awesomeness) %>">
66
+ <h1><%= link_to post.title, post, class: "awesome-title" %></h1>
67
+ <p><%= post.summary %></p>
68
+ </article>
69
+ <%- end %>
70
+ ```
71
+
72
+ `app/controllers/home_controller.rb`:
73
+ ```ruby
74
+ # GET /awesome
75
+ def awesome
76
+ posts = Post.order(awesomeness: :desc)
77
+ render_view AwesomeView.new(posts: posts)
78
+ end
79
+ ```
80
+
81
+ Unless a template is given directly (using the `template! "file"` option inside the view), a view will try to find a
82
+ template with it's name.
83
+
84
+ As seen in the example above a view's template has access to all instance variables, public and private methods defined
85
+ in the view, as well as all `ActionView` helpers.
86
+
87
+ Also, the view won't have access to any variables or instance variables defined in the controller, those have to be
88
+ passed in directly, as shown in `AwesomeView.new(posts: posts)`.
89
+
90
+ ### ApplicationView
91
+
92
+ Usually it's a common practice in rails projects to define an `ApplicationController` or `ApplicationRecord` base class
93
+ that can be inherited from. The same can be done with views, an `ApplicationView` class is a good place to put some
94
+ basic functionalities that should be available to all views.
95
+
96
+ ### Callable templates
97
+
98
+ A view's template can be overridden with a `proc`. __Attention:__ currently using a callable template doesn't work with
99
+ layouts, they will be ignored.
100
+
101
+ ```ruby
102
+ # defining the view
103
+ class HeaderView < ApplicationView
104
+
105
+ template! proc { tag.h1 @title }
106
+
107
+ def initialize(title:)
108
+ @title = title
109
+ end
110
+ end
111
+
112
+ # rendering the view
113
+ render_view HeaderView.new(title: "Mas Gente!") # => "<h1>Mas Gente!</h1>"
114
+ ```
115
+
116
+ ### Layouts
117
+
118
+ By default a view won't be rendered inside a layout. To use a layout, one has to be declared, either directly on the
119
+ view or passed to the `render_view` method.
120
+
121
+ #### Defining a layout template
122
+
123
+ `app/views/my_view.rb`:
124
+ ```ruby
125
+ class MyView < ApplicationView
126
+ # This will look for an application template inside app/views/layouts,
127
+ # it can be a html.erb or any other template language defined in your application.
128
+ layout! 'layouts/application'
129
+ end
130
+ ```
131
+
132
+ `app/views/layouts/application.html.erb`:
133
+ ```erb
134
+ <html>
135
+ <head>
136
+ <title>A view view a Layout</title>
137
+ <%= stylesheet_link_tag "application" %>
138
+ <%= javascript_include_tag "application" %>
139
+ </head>
140
+ <body>
141
+ <header>Header from the layout</header>
142
+ <%= yield %>
143
+ </body>
144
+ </html>
145
+ ```
146
+
147
+ #### Defining a layout view
148
+
149
+ A layout can also be a `Viu::Layout` class, in this case it will work pretty much like a `Viu::Html`.
150
+
151
+ `app/views/my_view.rb`:
152
+ ```ruby
153
+ class MyView < ApplicationView
154
+ layout! Layouts::ApplicationLayout
155
+ end
156
+ ```
157
+
158
+ `app/views/layouts/application_layout.rb`:
159
+ ```ruby
160
+ module Layouts
161
+
162
+ # a layout needs to inherit from Viu::Layout
163
+ class ApplicationLayout < Viu::Layout
164
+
165
+ def header_text
166
+ "This is a Viu::Layout"
167
+ end
168
+ end
169
+ end
170
+ ```
171
+
172
+ `app/views/layouts/application_layout.html.erb`:
173
+ ```erb
174
+ <html>
175
+ <head>
176
+ <title>A Viu::Layout</title>
177
+ <%= stylesheet_link_tag "application" %>
178
+ <%= javascript_include_tag "application" %>
179
+ </head>
180
+ <body>
181
+ <header><%= header_text %></header>
182
+ <%= yield %>
183
+ </body>
184
+ </html>
185
+ ```
186
+
187
+ Similar as the `Viu::Html` a layout will search for a template with it's name, if none is given directly.
188
+
189
+ #### Defining a layout `proc`
190
+
191
+ A layout can also be declared as a `proc`, this is useful when the view wants to override the layout parameters.
192
+ The `proc` will be executed in the context of the view and the result must respond to `render_in`.
193
+
194
+ `app/views/my_view.rb`:
195
+ ```ruby
196
+ class MyView < ApplicationView
197
+
198
+ layout! proc { Layouts::ApplicationLayout.new(header_text: text) }
199
+
200
+ private
201
+
202
+ def text
203
+ "Text from the view"
204
+ end
205
+ end
206
+ ```
207
+
208
+ `app/views/layouts/application_layout.rb`:
209
+ ```ruby
210
+ module Layouts
211
+ class ApplicationLayout < Viu::Layout
212
+
213
+ attr_reader :header_text
214
+
215
+ def initialize(header_text: 'The header text')
216
+ @header_text = header_text
217
+ end
218
+ end
219
+ end
220
+ ```
221
+
222
+ `app/views/layouts/application_layout.html.erb`:
223
+ ```erb
224
+ <html>
225
+ <head>
226
+ <title>A Viu::Layout</title>
227
+ <%= stylesheet_link_tag "application" %>
228
+ <%= javascript_include_tag "application" %>
229
+ </head>
230
+ <body>
231
+ <header>
232
+ <!-- it will render "Text from the view" here -->
233
+ <%= header_text %>
234
+ </header>
235
+ <%= yield %>
236
+ </body>
237
+ </html>
238
+ ```
239
+
240
+ #### Overriding layout on `render_view`
241
+
242
+ Usually a `layout` is defined directly in the view, as most of the times a view will be used in a single "context",
243
+ but if needed it can be overridden on the `render_view` with the `layout:` option, like so:
244
+
245
+ ```ruby
246
+ # it accepts a template
247
+ render_view MyView.new, layout: 'layouts/admin'
248
+
249
+ # a Viu::Layout
250
+ render_view MyView.new, layout: Layouts::OtherLayout
251
+
252
+ # or a proc
253
+ render_view MyView.new, layout: proc { Layouts::OtherLayout.new(title: 'Dashboard') }
254
+ ```
255
+
256
+ ## Viu::Json
257
+
258
+ This is a simple module that can be included in your views, it will add a `to_json` method, this is called by default
259
+ when rendering in a Rails env. The value returned from `json_output` will be the output of the view.
260
+
261
+ `app/views/api/posts/resource_view.rb`:
262
+ ```ruby
263
+ module Api
264
+ module Posts
265
+ class ResourceView
266
+ include Viu::Json
267
+
268
+ def initialize(post:)
269
+ @post = post
270
+ end
271
+
272
+ private
273
+
274
+ def author
275
+ @author ||= @post.author
276
+ end
277
+
278
+ def json_output
279
+ {
280
+ title: @post.title,
281
+ published_on: @post.published_on.to_s(:iso8601),
282
+ author: {
283
+ name: author.name,
284
+ avatar: author.avatar.url
285
+ }
286
+ }
287
+ end
288
+ end
289
+ end
290
+ end
291
+ ```
292
+
293
+ `app/controllers/api/posts_controller.rb`:
294
+ ```ruby
295
+ def show
296
+ post = Post.find(params[:id])
297
+ render json: Api::Posts::ResourceView.new(post: post)
298
+ end
299
+ ```
300
+
301
+ The default `JSON` encoder can be overridden like so:
302
+
303
+ ```ruby
304
+ class MyJsonView
305
+ include Viu::Json
306
+
307
+ json_encoder ->(input) { Oj.dump(input) }
308
+
309
+ end
310
+ ```
311
+
312
+ ## Viu::Xml
313
+
314
+ Similar to `Viu::Json` this is a simple module that can be included in your views, it will add a `to_xml` method,
315
+ this is called by default when rendering in a Rails env. The value returned from `xml_output` will be the output
316
+ of the view.
317
+
318
+ `app/views/api/posts/resource_view.rb`:
319
+ ```ruby
320
+ module Api
321
+ module Posts
322
+ class ResourceView
323
+ include Viu::Xml
324
+
325
+ def initialize(post:)
326
+ @post = post
327
+ end
328
+
329
+ private
330
+
331
+ def author
332
+ @author ||= @post.author
333
+ end
334
+
335
+ def xml_output
336
+ {
337
+ title: @post.title,
338
+ published_on: @post.published_on.to_s(:iso8601),
339
+ author: {
340
+ name: author.name,
341
+ avatar: author.avatar.url
342
+ }
343
+ }
344
+ end
345
+ end
346
+ end
347
+ end
348
+ ```
349
+
350
+ `app/controllers/api/posts_controller.rb`:
351
+ ```ruby
352
+ def show
353
+ post = Post.find(params[:id])
354
+ render xml Api::Posts::ResourceView.new(post: post)
355
+ end
356
+ ```
357
+
358
+ The default `XML` encoder can be overridden like so:
359
+
360
+ ```ruby
361
+ class MyXmlView
362
+ include Viu::Xml
363
+
364
+ xml_encoder ->(input) { Ox.dump(input) }
365
+
366
+ end
367
+ ```
368
+
369
+ ## Known Issues
370
+
371
+ * A `Viu::Layout` doesn't work with `content_for` blocks, it's only available on a regular layout template for now;
372
+ * Templates and partials require the "full" path, eg: `layouts/application` or `posts/index`;
373
+ * Currently layout inheritance isn't working correctly.
374
+
375
+ ## About
376
+
377
+ Inspired by `view_component`, `cells` and others, currently this is a POC (proof of concept) to create a View layer
378
+ for Rails, it uses `ActionView` as the base for HTML views and it aims to work with the least amount of surprises on a
379
+ Rails application, but with a few boundaries, like a View won't be able to automatically access `@ivars` defined
380
+ in a controller, those have to explicitly be passed to them.
381
+
382
+ The project is already been tested on a small scale in our production environment.
383
+
384
+ ## Development
385
+
386
+ ```ruby
387
+ # install dependencies
388
+ bin/setup install
389
+
390
+ # running tests
391
+ bundle exec rake test
392
+
393
+ # running tests for all rails versions
394
+ bundle exec appraisal rake test
395
+
396
+ # releasing a new version:
397
+ # update changelog
398
+ # update VERSION on lib/viu/version.rb
399
+ # run bundle exec rake release
400
+ # create a Bump to version x.x.x commit
401
+ # run bundle exec rake release
402
+ ```