viu 0.0.2 → 0.0.7

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: 2f24b77a5e5a5ada196406705ac4ff02102f7915321f0b22cc946f8a9fc27040
4
- data.tar.gz: 2648be1eec444b862d8c7c40f4ccf557011be42784a9ab29b0944f8251d8fff7
3
+ metadata.gz: 9edfbe265c55fd9fc3a3577ebdb1e4861188565d75ee30bd48d55266f0fa53d2
4
+ data.tar.gz: 718f552c4b1e9b28b93aeb2dea02aae4a147ff6b4d7b15203dd1da51b963f0c4
5
5
  SHA512:
6
- metadata.gz: fb6709c1bf1b41bf7cd451fc20683fcb6e98e7aa4bfe107a21bea21e8a0d0ece7277f6de65e75c385eb545498306bd75a148e497ce5e3799d6d8f875238ed6ce
7
- data.tar.gz: 6b75da7d7c59928851d230ed0b1f4dcb527cf3f0d8b3bbef93c6c87d1ecd8f023155d1ab5026b75b64223c45301c6e7b8fbc70c415401ecfb4ab2984401a323f
6
+ metadata.gz: 1580d4292754df11655385b8358e9eb79706968d814f5b8182abbdf94cb989f40d9a4fc68fc2848fe2e12e2906a764470c30f95ac933f7e47d5b38142789f304
7
+ data.tar.gz: 0f956d9168108108cad578b21d1078c374b85736d836fb8c443189fa08735e01028aaf727456e4cb5c65a3b384ad230048b6a8980027916aab5132f9cfb392d0
data/.gitignore CHANGED
@@ -9,3 +9,5 @@
9
9
  /test/support/dummy/tmp
10
10
  /test/support/dummy/log
11
11
  *.gem
12
+
13
+ /gemfiles/*.gemfile.lock
@@ -0,0 +1,19 @@
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
16
+
17
+ appraise "rails-6-1" do
18
+ gem "rails", "~> 6.1.0"
19
+ end
@@ -1,3 +1,26 @@
1
+ ### 0.0.7 2020-12-24
2
+
3
+ - Allow #render_view to accept a :format option
4
+
5
+ ## 0.0.6 2020-12-23
6
+
7
+ - Set content type as "text/html" when using #render_view
8
+
9
+ ## 0.0.5 2020-12-01
10
+
11
+ - Added support for Rails 6.1.0.rc1
12
+ - Fixed bug with views not having access to compiled template methods (using #compiled_method_container)
13
+
14
+ ## 0.0.4 2020-11-29
15
+
16
+ - Added support for Rails ~> 6.0.0
17
+
18
+ ## 0.0.3 2020-09-02
19
+
20
+ - Added Viu::Json
21
+ - Added Viu::Xml
22
+ - Allow Viu::Html template! to receive a proc
23
+
1
24
  ## 0.0.2 2020-08-16
2
25
 
3
26
  ### Added
data/Gemfile CHANGED
@@ -4,6 +4,5 @@ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
4
4
 
5
5
  gemspec
6
6
 
7
- rails_version = "#{ENV['RAILS_VERSION'] || '~> 5.2'}"
8
-
9
- gem "rails", rails_version == "master" ? { github: "rails/rails" } : rails_version
7
+ gem "rails", github: "rails/rails"
8
+ gem "oj"
@@ -1,66 +1,113 @@
1
- PATH
2
- remote: .
3
- specs:
4
- viu (0.0.2)
5
-
6
- GEM
7
- remote: https://rubygems.org/
1
+ GIT
2
+ remote: https://github.com/rails/rails
3
+ revision: 007a86506f02db265b6c8156575f29733931338e
8
4
  specs:
9
- actioncable (5.2.4.3)
10
- actionpack (= 5.2.4.3)
5
+ actioncable (6.2.0.alpha)
6
+ actionpack (= 6.2.0.alpha)
7
+ activesupport (= 6.2.0.alpha)
11
8
  nio4r (~> 2.0)
12
9
  websocket-driver (>= 0.6.1)
13
- actionmailer (5.2.4.3)
14
- actionpack (= 5.2.4.3)
15
- actionview (= 5.2.4.3)
16
- activejob (= 5.2.4.3)
10
+ actionmailbox (6.2.0.alpha)
11
+ actionpack (= 6.2.0.alpha)
12
+ activejob (= 6.2.0.alpha)
13
+ activerecord (= 6.2.0.alpha)
14
+ activestorage (= 6.2.0.alpha)
15
+ activesupport (= 6.2.0.alpha)
16
+ mail (>= 2.7.1)
17
+ actionmailer (6.2.0.alpha)
18
+ actionpack (= 6.2.0.alpha)
19
+ actionview (= 6.2.0.alpha)
20
+ activejob (= 6.2.0.alpha)
21
+ activesupport (= 6.2.0.alpha)
17
22
  mail (~> 2.5, >= 2.5.4)
18
23
  rails-dom-testing (~> 2.0)
19
- actionpack (5.2.4.3)
20
- actionview (= 5.2.4.3)
21
- activesupport (= 5.2.4.3)
22
- rack (~> 2.0, >= 2.0.8)
24
+ actionpack (6.2.0.alpha)
25
+ actionview (= 6.2.0.alpha)
26
+ activesupport (= 6.2.0.alpha)
27
+ rack (~> 2.0, >= 2.0.9)
23
28
  rack-test (>= 0.6.3)
24
29
  rails-dom-testing (~> 2.0)
25
- rails-html-sanitizer (~> 1.0, >= 1.0.2)
26
- actionview (5.2.4.3)
27
- activesupport (= 5.2.4.3)
30
+ rails-html-sanitizer (~> 1.0, >= 1.2.0)
31
+ actiontext (6.2.0.alpha)
32
+ actionpack (= 6.2.0.alpha)
33
+ activerecord (= 6.2.0.alpha)
34
+ activestorage (= 6.2.0.alpha)
35
+ activesupport (= 6.2.0.alpha)
36
+ nokogiri (>= 1.8.5)
37
+ actionview (6.2.0.alpha)
38
+ activesupport (= 6.2.0.alpha)
28
39
  builder (~> 3.1)
29
40
  erubi (~> 1.4)
30
41
  rails-dom-testing (~> 2.0)
31
- rails-html-sanitizer (~> 1.0, >= 1.0.3)
32
- activejob (5.2.4.3)
33
- activesupport (= 5.2.4.3)
42
+ rails-html-sanitizer (~> 1.1, >= 1.2.0)
43
+ activejob (6.2.0.alpha)
44
+ activesupport (= 6.2.0.alpha)
34
45
  globalid (>= 0.3.6)
35
- activemodel (5.2.4.3)
36
- activesupport (= 5.2.4.3)
37
- activerecord (5.2.4.3)
38
- activemodel (= 5.2.4.3)
39
- activesupport (= 5.2.4.3)
40
- arel (>= 9.0)
41
- activestorage (5.2.4.3)
42
- actionpack (= 5.2.4.3)
43
- activerecord (= 5.2.4.3)
46
+ activemodel (6.2.0.alpha)
47
+ activesupport (= 6.2.0.alpha)
48
+ activerecord (6.2.0.alpha)
49
+ activemodel (= 6.2.0.alpha)
50
+ activesupport (= 6.2.0.alpha)
51
+ activestorage (6.2.0.alpha)
52
+ actionpack (= 6.2.0.alpha)
53
+ activejob (= 6.2.0.alpha)
54
+ activerecord (= 6.2.0.alpha)
55
+ activesupport (= 6.2.0.alpha)
44
56
  marcel (~> 0.3.1)
45
- activesupport (5.2.4.3)
57
+ mimemagic (~> 0.3.2)
58
+ activesupport (6.2.0.alpha)
46
59
  concurrent-ruby (~> 1.0, >= 1.0.2)
47
- i18n (>= 0.7, < 2)
48
- minitest (~> 5.1)
49
- tzinfo (~> 1.1)
50
- arel (9.0.0)
60
+ i18n (>= 1.6, < 2)
61
+ minitest (>= 5.1)
62
+ tzinfo (~> 2.0)
63
+ zeitwerk (~> 2.3)
64
+ rails (6.2.0.alpha)
65
+ actioncable (= 6.2.0.alpha)
66
+ actionmailbox (= 6.2.0.alpha)
67
+ actionmailer (= 6.2.0.alpha)
68
+ actionpack (= 6.2.0.alpha)
69
+ actiontext (= 6.2.0.alpha)
70
+ actionview (= 6.2.0.alpha)
71
+ activejob (= 6.2.0.alpha)
72
+ activemodel (= 6.2.0.alpha)
73
+ activerecord (= 6.2.0.alpha)
74
+ activestorage (= 6.2.0.alpha)
75
+ activesupport (= 6.2.0.alpha)
76
+ bundler (>= 1.15.0)
77
+ railties (= 6.2.0.alpha)
78
+ sprockets-rails (>= 2.0.0)
79
+ railties (6.2.0.alpha)
80
+ actionpack (= 6.2.0.alpha)
81
+ activesupport (= 6.2.0.alpha)
82
+ method_source
83
+ rake (>= 0.8.7)
84
+ thor (~> 1.0)
85
+
86
+ PATH
87
+ remote: .
88
+ specs:
89
+ viu (0.0.7)
90
+
91
+ GEM
92
+ remote: https://rubygems.org/
93
+ specs:
94
+ appraisal (2.3.0)
95
+ bundler
96
+ rake
97
+ thor (>= 0.14.0)
51
98
  builder (3.2.4)
52
99
  concurrent-ruby (1.1.7)
53
100
  crass (1.0.6)
54
- docile (1.3.2)
55
- erubi (1.9.0)
101
+ docile (1.3.4)
102
+ erubi (1.10.0)
56
103
  globalid (0.4.2)
57
104
  activesupport (>= 4.2.0)
58
- haml (5.1.2)
105
+ haml (5.2.1)
59
106
  temple (>= 0.8.0)
60
107
  tilt
61
108
  i18n (1.8.5)
62
109
  concurrent-ruby (~> 1.0)
63
- loofah (2.6.0)
110
+ loofah (2.8.0)
64
111
  crass (~> 1.0.2)
65
112
  nokogiri (>= 1.5.9)
66
113
  mail (2.7.1)
@@ -71,70 +118,54 @@ GEM
71
118
  mimemagic (0.3.5)
72
119
  mini_mime (1.0.2)
73
120
  mini_portile2 (2.4.0)
74
- minitest (5.14.1)
75
- nio4r (2.5.2)
121
+ minitest (5.14.2)
122
+ nio4r (2.5.4)
76
123
  nokogiri (1.10.10)
77
124
  mini_portile2 (~> 2.4.0)
125
+ oj (3.10.17)
78
126
  rack (2.2.3)
79
127
  rack-test (1.1.0)
80
128
  rack (>= 1.0, < 3)
81
- rails (5.2.4.3)
82
- actioncable (= 5.2.4.3)
83
- actionmailer (= 5.2.4.3)
84
- actionpack (= 5.2.4.3)
85
- actionview (= 5.2.4.3)
86
- activejob (= 5.2.4.3)
87
- activemodel (= 5.2.4.3)
88
- activerecord (= 5.2.4.3)
89
- activestorage (= 5.2.4.3)
90
- activesupport (= 5.2.4.3)
91
- bundler (>= 1.3.0)
92
- railties (= 5.2.4.3)
93
- sprockets-rails (>= 2.0.0)
94
129
  rails-dom-testing (2.0.3)
95
130
  activesupport (>= 4.2.0)
96
131
  nokogiri (>= 1.6)
97
132
  rails-html-sanitizer (1.3.0)
98
133
  loofah (~> 2.3)
99
- railties (5.2.4.3)
100
- actionpack (= 5.2.4.3)
101
- activesupport (= 5.2.4.3)
102
- method_source
103
- rake (>= 0.8.7)
104
- thor (>= 0.19.0, < 2.0)
105
134
  rake (12.3.3)
106
135
  simplecov (0.18.5)
107
136
  docile (~> 1.1)
108
137
  simplecov-html (~> 0.11)
109
- simplecov-html (0.12.2)
138
+ simplecov-html (0.12.3)
110
139
  slim (4.1.0)
111
140
  temple (>= 0.7.6, < 0.9)
112
141
  tilt (>= 2.0.6, < 2.1)
113
142
  sprockets (4.0.2)
114
143
  concurrent-ruby (~> 1.0)
115
144
  rack (> 1, < 3)
116
- sprockets-rails (3.2.1)
145
+ sprockets-rails (3.2.2)
117
146
  actionpack (>= 4.0)
118
147
  activesupport (>= 4.0)
119
148
  sprockets (>= 3.0.0)
120
149
  temple (0.8.2)
121
150
  thor (1.0.1)
122
- thread_safe (0.3.6)
123
151
  tilt (2.0.10)
124
- tzinfo (1.2.7)
125
- thread_safe (~> 0.1)
152
+ tzinfo (2.0.4)
153
+ concurrent-ruby (~> 1.0)
126
154
  websocket-driver (0.7.3)
127
155
  websocket-extensions (>= 0.1.0)
128
156
  websocket-extensions (0.1.5)
157
+ zeitwerk (2.4.2)
129
158
 
130
159
  PLATFORMS
131
160
  ruby
132
161
 
133
162
  DEPENDENCIES
163
+ appraisal (~> 2.3)
134
164
  bundler (~> 1.17)
135
165
  haml (~> 5)
136
166
  minitest (~> 5.0)
137
- rails (~> 5.2)
167
+ oj
168
+ rails!
138
169
  rake (~> 12.3)
139
170
  simplecov (~> 0.18.0)
140
171
  slim (~> 4)
data/README.md CHANGED
@@ -1,26 +1,402 @@
1
1
  # Viu
2
2
 
3
- Currently this is a POC (proof of concept), on the usage of `ActionView` as a "real" view layer. Inspired on
4
- `view_component`, `cells` and others, `viu` is just a small wrapper around `AV`. It aims to work with the least amount
5
- of surprise with Rails, but with a few boundaries, like a View won't be able to automatically access `@ivars` defined
6
- in the controller, those have to explicitly be passed to them.
3
+ Rails' missing View layer.
7
4
 
8
- The project is already been tested on a small scale in our production environment.
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
+ ```
9
171
 
10
- ## Your first View
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`.
11
193
 
12
194
  `app/views/my_view.rb`:
13
195
  ```ruby
14
- class MyView < Viu::Html
15
- def initialize(name)
16
- @name = name
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
17
218
  end
18
219
  end
19
220
  ```
20
221
 
21
- `app/views/my_view.html.erb`:
222
+ `app/views/layouts/application_layout.html.erb`:
22
223
  ```erb
23
- <h1><%= @name %></h1>
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
24
356
  ```
25
357
 
26
- Unless a template is given directly, a view will try to find a template with it's name.
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
+ ```
@@ -0,0 +1,2 @@
1
+ ---
2
+ BUNDLE_RETRY: "1"
@@ -0,0 +1,8 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "~> 5.2.0"
6
+ gem "oj"
7
+
8
+ gemspec path: "../"
@@ -0,0 +1,8 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "~> 6.0.0"
6
+ gem "oj"
7
+
8
+ gemspec path: "../"
@@ -0,0 +1,8 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "~> 6.1.0"
6
+ gem "oj"
7
+
8
+ gemspec path: "../"
data/lib/viu.rb CHANGED
@@ -4,6 +4,8 @@ require "viu/version"
4
4
 
5
5
  require "viu/html"
6
6
  require "viu/layout"
7
+ require "viu/json"
8
+ require "viu/xml"
7
9
  require "viu/test_case"
8
10
 
9
11
  require 'viu/railtie' if defined?(Rails)
@@ -7,9 +7,17 @@ module Viu
7
7
 
8
8
  def initialize(*); end
9
9
 
10
+ module CompiledMethodContainer; end
11
+
12
+ def compiled_method_container
13
+ Viu::Html::CompiledMethodContainer
14
+ end
15
+
10
16
  def render_in(view_context, options = EMPTY_HASH)
11
17
  __setup!(view_context)
12
18
 
19
+ return __render_template_proc if __fetch_template!.is_a?(Proc)
20
+
13
21
  layout = options.fetch(:layout, self.class.layout)
14
22
 
15
23
  if layout.is_a?(Class)
@@ -48,6 +56,10 @@ module Viu
48
56
  self.class.template!(self.class.name.underscore)
49
57
  end
50
58
 
59
+ def __render_template_proc
60
+ self.instance_exec(&__fetch_template!)
61
+ end
62
+
51
63
  def __render_layout_class(layout)
52
64
  layout.new.render_in(@view_context) do
53
65
  @view_renderer.render(self, template: __fetch_template!, layout: nil)
@@ -63,8 +75,10 @@ module Viu
63
75
  class << self
64
76
 
65
77
  def inherited(child)
78
+ child.include(Viu::Html::CompiledMethodContainer)
79
+
66
80
  if defined?(Rails) && child != Viu::Layout
67
- child.include Rails.application.routes.url_helpers unless child < Rails.application.routes.url_helpers
81
+ child.include(Rails.application.routes.url_helpers) unless child < Rails.application.routes.url_helpers
68
82
  end
69
83
  end
70
84
 
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/concern'
4
+ require 'active_support/core_ext/class/attribute'
5
+
6
+ module Viu
7
+ module Json
8
+ extend ActiveSupport::Concern
9
+
10
+ DEFAULT_JSON_ENCODER = ->(input) { input.to_json }.freeze
11
+
12
+ included do
13
+ class_attribute :__json_encoder, instance_accessor: false, instance_predicate: false,
14
+ default: DEFAULT_JSON_ENCODER
15
+
16
+ attr_reader :rendering_options
17
+
18
+ def to_json(options = EMPTY_HASH)
19
+ @rendering_options = options
20
+ self.class.__json_encoder.call(json_output)
21
+ end
22
+ end
23
+
24
+ class_methods do
25
+
26
+ def json_encoder(value)
27
+ self.__json_encoder = value
28
+ end
29
+ end
30
+ end
31
+ end
@@ -15,10 +15,22 @@ module Viu
15
15
  end
16
16
  end
17
17
 
18
+ RAILS_6_0 = Gem::Version.new('6.0.0')
19
+ RAILS_6_1_WITH_PRERELEASES = Gem::Version.new('6.1.0.a')
20
+ private_constant :RAILS_6_0, :RAILS_6_1_WITH_PRERELEASES
21
+
18
22
  def render_in(view_context, &block)
19
23
  __setup!(view_context)
20
24
 
21
- Renderer.new(@lookup_context).render(self, { partial: __fetch_template!, layout: nil }, block)
25
+ rails_version = ::Rails.gem_version
26
+
27
+ if rails_version >= RAILS_6_1_WITH_PRERELEASES
28
+ Renderer.new(@lookup_context, layout: nil).render(__fetch_template!, self, block).body
29
+ elsif rails_version >= RAILS_6_0
30
+ Renderer.new(@lookup_context).render(self, { partial: __fetch_template!, layout: nil }, block).body
31
+ else
32
+ Renderer.new(@lookup_context).render(self, { partial: __fetch_template!, layout: nil }, block)
33
+ end
22
34
  end
23
35
  end
24
36
  end
@@ -10,7 +10,8 @@ module Viu
10
10
 
11
11
  module ActionControllerHelpers
12
12
  def render_view(view, options = EMPTY_HASH)
13
- self.response_body = view.render_in(view_context, options)
13
+ format = options.fetch(:format) { :html }
14
+ render(format => view.render_in(view_context, options))
14
15
  end
15
16
  end
16
17
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Viu
4
- VERSION = "0.0.2"
4
+ VERSION = "0.0.7"
5
5
  end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/concern'
4
+ require 'active_support/core_ext/class/attribute'
5
+
6
+ module Viu
7
+ module Xml
8
+ extend ActiveSupport::Concern
9
+
10
+ DEFAULT_XML_ENCODER = ->(input) { input.to_xml }.freeze
11
+
12
+ included do
13
+ class_attribute :__xml_encoder, instance_accessor: false, instance_predicate: false,
14
+ default: DEFAULT_XML_ENCODER
15
+
16
+ attr_reader :rendering_options
17
+
18
+ def to_xml(options = EMPTY_HASH)
19
+ @rendering_options = options
20
+ self.class.__xml_encoder.call(xml_output)
21
+ end
22
+ end
23
+
24
+ class_methods do
25
+
26
+ def xml_encoder(value)
27
+ self.__xml_encoder = value
28
+ end
29
+ end
30
+ end
31
+ end
@@ -40,4 +40,5 @@ Gem::Specification.new do |spec|
40
40
  spec.add_development_dependency "simplecov", "~> 0.18.0"
41
41
  spec.add_development_dependency "haml", "~> 5"
42
42
  spec.add_development_dependency "slim", "~> 4"
43
+ spec.add_development_dependency "appraisal", "~> 2.3"
43
44
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: viu
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ralf Schmitz Bongiolo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-08-16 00:00:00.000000000 Z
11
+ date: 2020-12-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -94,6 +94,20 @@ dependencies:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
96
  version: '4'
97
+ - !ruby/object:Gem::Dependency
98
+ name: appraisal
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '2.3'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '2.3'
97
111
  description: Rails' missing View layer.
98
112
  email:
99
113
  - mrbongiolo@hey.com
@@ -103,6 +117,7 @@ extra_rdoc_files: []
103
117
  files:
104
118
  - ".gitignore"
105
119
  - ".travis.yml"
120
+ - Appraisals
106
121
  - CHANGELOG.md
107
122
  - CODE_OF_CONDUCT.md
108
123
  - Gemfile
@@ -112,14 +127,20 @@ files:
112
127
  - Rakefile
113
128
  - bin/console
114
129
  - bin/setup
130
+ - gemfiles/.bundle/config
131
+ - gemfiles/rails_5_2.gemfile
132
+ - gemfiles/rails_6_0.gemfile
133
+ - gemfiles/rails_6_1.gemfile
115
134
  - lib/viu.rb
116
135
  - lib/viu/html.rb
136
+ - lib/viu/json.rb
117
137
  - lib/viu/layout.rb
118
138
  - lib/viu/railtie.rb
119
139
  - lib/viu/rendering_helpers.rb
120
140
  - lib/viu/test_case.rb
121
141
  - lib/viu/test_helpers.rb
122
142
  - lib/viu/version.rb
143
+ - lib/viu/xml.rb
123
144
  - viu.gemspec
124
145
  homepage: https://github.com/mrbongiolo/viu
125
146
  licenses: