viu 0.0.2 → 0.0.7

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: 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: