viu 0.0.0 → 0.0.5

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 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
+ ```