templet_rails 0.1.0
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 +7 -0
- data/.gitignore +8 -0
- data/.travis.yml +5 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +21 -0
- data/README.md +1059 -0
- data/Rakefile +10 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/generators/templet/controller/USAGE +13 -0
- data/lib/generators/templet/controller/controller_generator.rb +106 -0
- data/lib/generators/templet/core/USAGE +23 -0
- data/lib/generators/templet/core/core_generator.rb +128 -0
- data/lib/generators/templet/core_rspec/USAGE +16 -0
- data/lib/generators/templet/core_rspec/core_rspec_generator.rb +65 -0
- data/lib/generators/templet/destroy/USAGE +19 -0
- data/lib/generators/templet/destroy/destroy_generator.rb +126 -0
- data/lib/generators/templet/routes/USAGE +14 -0
- data/lib/generators/templet/routes/routes_generator.rb +64 -0
- data/lib/generators/templet/rspec/USAGE +10 -0
- data/lib/generators/templet/rspec/rspec_generator.rb +124 -0
- data/lib/generators/templet/scaffold/USAGE +22 -0
- data/lib/generators/templet/scaffold/scaffold_generator.rb +75 -0
- data/lib/generators/templet/shared/actions_option.rb +24 -0
- data/lib/generators/templet/shared/add_routes_option.rb +19 -0
- data/lib/generators/templet/shared/child_option.rb +23 -0
- data/lib/generators/templet/shared/comment_tests_option.rb +19 -0
- data/lib/generators/templet/shared/core_helpers.rb +48 -0
- data/lib/generators/templet/shared/grand_parent_option.rb +20 -0
- data/lib/generators/templet/shared/model_fields.rb +55 -0
- data/lib/generators/templet/shared/model_option.rb +25 -0
- data/lib/generators/templet/shared/parent_option.rb +20 -0
- data/lib/generators/templet/templates/controller.rb.erb +108 -0
- data/lib/generators/templet/templates/core/app/base_viewer.rb +7 -0
- data/lib/generators/templet/templates/core/app/link_sets/navbar.rb +12 -0
- data/lib/generators/templet/templates/core/app/panel/flash_messages.rb +33 -0
- data/lib/generators/templet/templates/core/app/panel/layout_base.rb +40 -0
- data/lib/generators/templet/templates/core/app/panel/layout_header.rb +22 -0
- data/lib/generators/templet/templates/core/app/panel/layout_header_sidebar.rb +18 -0
- data/lib/generators/templet/templates/core/app/panel/nav.rb +55 -0
- data/lib/generators/templet/templates/core/app/panel/nav_args_option.rb +30 -0
- data/lib/generators/templet/templates/core/app/panel/options_config.rb +19 -0
- data/lib/generators/templet/templates/core/app/panel/show_parents_option.rb +22 -0
- data/lib/generators/templet/templates/core/app/panel/sidebar_links_option.rb +24 -0
- data/lib/generators/templet/templates/core/controllers/.keep +0 -0
- data/lib/generators/templet/templates/core/controllers/json_rendering_helpers.rb +12 -0
- data/lib/generators/templet/templates/core/controllers/rendering_helpers.rb +53 -0
- data/lib/generators/templet/templates/core/controllers/viewer_call_string.rb +144 -0
- data/lib/generators/templet/templates/core/controllers/viewer_call_string_class.rb +65 -0
- data/lib/generators/templet/templates/core/controllers/viewer_responders.rb +121 -0
- data/lib/generators/templet/templates/core/helpers/app.rb +4 -0
- data/lib/generators/templet/templates/core/helpers/templet_helper.rb +10 -0
- data/lib/generators/templet/templates/core/spec/support/apis/api_helper.rb +13 -0
- data/lib/generators/templet/templates/core/spec/support/apis/shared_examples_a_json_controller.rb +196 -0
- data/lib/generators/templet/templates/core/spec/support/core/model_parent_helpers.rb +36 -0
- data/lib/generators/templet/templates/core/spec/support/core/rest_link_procs_assignments.rb +43 -0
- data/lib/generators/templet/templates/core/spec/support/core/rest_link_procs_helpers.rb +15 -0
- data/lib/generators/templet/templates/core/spec/support/viewer/partial_test_helpers.rb +32 -0
- data/lib/generators/templet/templates/core/spec/support/viewer/shared_examples_a_viewer.rb +105 -0
- data/lib/generators/templet/templates/core/spec/templet/forms/bs_form_errors_spec.rb +18 -0
- data/lib/generators/templet/templates/core/spec/templet/forms/bs_form_spec.rb +58 -0
- data/lib/generators/templet/templates/core/spec/templet/layout/html_rails_spec.rb +64 -0
- data/lib/generators/templet/templates/core/spec/templet/links/bs_link_set_collection_spec.rb +79 -0
- data/lib/generators/templet/templates/core/spec/templet/links/rest_link_procs_params_spec.rb +68 -0
- data/lib/generators/templet/templates/core/spec/templet/links/rest_link_procs_parents_spec.rb +78 -0
- data/lib/generators/templet/templates/core/spec/templet/links/rest_link_procs_spec.rb +140 -0
- data/lib/generators/templet/templates/core/templet/constants.rb +54 -0
- data/lib/generators/templet/templates/core/templet/forms/bs_form.rb +73 -0
- data/lib/generators/templet/templates/core/templet/forms/bs_form_errors.rb +38 -0
- data/lib/generators/templet/templates/core/templet/forms/bs_form_field.rb +114 -0
- data/lib/generators/templet/templates/core/templet/forms/bs_form_group.rb +115 -0
- data/lib/generators/templet/templates/core/templet/layouts/html_rails.rb +36 -0
- data/lib/generators/templet/templates/core/templet/links.rb +28 -0
- data/lib/generators/templet/templates/core/templet/links/bs_btn_class.rb +61 -0
- data/lib/generators/templet/templates/core/templet/links/bs_link_set_base.rb +168 -0
- data/lib/generators/templet/templates/core/templet/links/bs_link_set_collection.rb +21 -0
- data/lib/generators/templet/templates/core/templet/links/bs_link_set_navigation.rb +62 -0
- data/lib/generators/templet/templates/core/templet/links/rest_link_procs.rb +163 -0
- data/lib/generators/templet/templates/core/templet/links/rest_link_procs_parent.rb +39 -0
- data/lib/generators/templet/templates/core/templet/links/rest_link_procs_sets.rb +30 -0
- data/lib/generators/templet/templates/core/templet/links/rest_link_text.rb +102 -0
- data/lib/generators/templet/templates/core/templet/links/rest_path.rb +90 -0
- data/lib/generators/templet/templates/core/templet/mixins.rb +9 -0
- data/lib/generators/templet/templates/core/templet/mixins/bs.rb +11 -0
- data/lib/generators/templet/templates/core/templet/mixins/bs/grid.rb +53 -0
- data/lib/generators/templet/templates/core/templet/mixins/bs/lists.rb +77 -0
- data/lib/generators/templet/templates/core/templet/mixins/field_procs.rb +140 -0
- data/lib/generators/templet/templates/core/templet/mixins/html_presenters.rb +82 -0
- data/lib/generators/templet/templates/core/templet/require_all.rb +45 -0
- data/lib/generators/templet/templates/core/templet/utils/html_search_form.rb +53 -0
- data/lib/generators/templet/templates/core/templet/utils/link_set_factory.rb +46 -0
- data/lib/generators/templet/templates/core/templet/utils/link_set_factory_wrapper.rb +53 -0
- data/lib/generators/templet/templates/core/templet/utils/list_model_parents.rb +27 -0
- data/lib/generators/templet/templates/core/templet/utils/navbar_form.rb +26 -0
- data/lib/generators/templet/templates/core/templet/utils/selected_wrapper.rb +40 -0
- data/lib/generators/templet/templates/core/templet/viewer.rb +11 -0
- data/lib/generators/templet/templates/core/templet/viewer/meta_model.rb +66 -0
- data/lib/generators/templet/templates/core/templet/viewer/meta_model_defaults.rb +56 -0
- data/lib/generators/templet/templates/core/templet/viewer/presenters.rb +44 -0
- data/lib/generators/templet/templates/core/templet/viewer/rest_actions.rb +24 -0
- data/lib/generators/templet/templates/core/templet/viewer_base.rb +111 -0
- data/lib/generators/templet/templates/core/templet/viewer_rest.rb +144 -0
- data/lib/generators/templet/viewer/USAGE +10 -0
- data/lib/generators/templet/viewer/viewer_generator.rb +86 -0
- data/lib/templet_rails.rb +5 -0
- data/lib/templet_rails/version.rb +3 -0
- data/templet_rails.gemspec +36 -0
- metadata +178 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: e7deaf8989e6c551f2a2a43643b4a9cf0cc869f6
|
4
|
+
data.tar.gz: d36afba37dfd38b61d462d812df24ec821413265
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f717307ac491b39041177dcaa47bc3939e7bfa746829759f77a2963ac1a58263a521fca4e7a537e482fa3f7278b7d4526afe18bec17490681978f1414f8fd4e9
|
7
|
+
data.tar.gz: 5144a6c2c625b587c55c263a42943503f6c1ac01ced1220aa833aa6c6fca5129a936c6fab38c14c7c9b7668b23cbedc70d926e5ef169ca89d982822dcbe3cab3
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2018 TODO: Write your name
|
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.
|
data/README.md
ADDED
@@ -0,0 +1,1059 @@
|
|
1
|
+
# Templet
|
2
|
+
|
3
|
+
## Sections
|
4
|
+
|
5
|
+
[Forward](#forward)
|
6
|
+
a quick run through and info on learning resources.
|
7
|
+
|
8
|
+
[Introduction](#intro)
|
9
|
+
a short summary.
|
10
|
+
|
11
|
+
[FAQ](#faq)
|
12
|
+
frequently asked questions.
|
13
|
+
|
14
|
+
[Generators](#gen)
|
15
|
+
where you get started.
|
16
|
+
|
17
|
+
[Notes](#notes)
|
18
|
+
a wider summary.
|
19
|
+
|
20
|
+
<a name="forward"></a>
|
21
|
+
## Forward
|
22
|
+
|
23
|
+
### Outline
|
24
|
+
|
25
|
+
This is a framework to render views in Rails.
|
26
|
+
|
27
|
+
It replaces ERb (or HAML, etc.) scripts with a single class
|
28
|
+
that, by default, renders (Bootstrap) HTML for the standard REST actions.
|
29
|
+
|
30
|
+
It facilitates a more object oriented approach to coding up views,
|
31
|
+
yet remains compatible with existing view scripts and Helper methods.
|
32
|
+
|
33
|
+
If you're familiar with Rails,
|
34
|
+
getting to grips with this framework should cause little difficulty,
|
35
|
+
or take much time.
|
36
|
+
|
37
|
+
### Example Application
|
38
|
+
|
39
|
+
To learn it practically, there is an example Rails app,
|
40
|
+
[questionable](https://github.com/srycyk/questionable),
|
41
|
+
which is a small administrative front-end of just three models.
|
42
|
+
|
43
|
+
This small app has lots of examples that illustrate
|
44
|
+
how to customise views using the framework.
|
45
|
+
|
46
|
+
By itself, this app should provide enough information
|
47
|
+
for you to write code in the framework effectively.
|
48
|
+
It demonstrates most of the finer points involved in
|
49
|
+
adapting it for particular requirements.
|
50
|
+
|
51
|
+
### Documentation Sources
|
52
|
+
|
53
|
+
For a broad, more theoretical, overview of the framework,
|
54
|
+
there is this guide.
|
55
|
+
|
56
|
+
Although it's quite wordy, short of examples, not exhaustive,
|
57
|
+
and a lot to take in at one sitting,
|
58
|
+
nevertheless, it does explain why you may want to use it,
|
59
|
+
where you begin,
|
60
|
+
how it works,
|
61
|
+
what it contains,
|
62
|
+
and its internal organisation.
|
63
|
+
|
64
|
+
In addition, there is another guide found at,
|
65
|
+
[templet](https://github.com/srycyk/templet),
|
66
|
+
that describes the DSL that renders HTML tags.
|
67
|
+
This DSL, which is heavily used by the higher-level framework,
|
68
|
+
is so straightforward and succinct
|
69
|
+
that you may only need a passing acquaintance with it.
|
70
|
+
_You may well pick it up as you go along._
|
71
|
+
|
72
|
+
For hard-core punishment gluttons, there is yet more documentation -
|
73
|
+
the source code carries comments in the harder bits,
|
74
|
+
and the purpose of each class is spelled out.
|
75
|
+
|
76
|
+
<a name="intro"></a>
|
77
|
+
## Introduction
|
78
|
+
|
79
|
+
### Packaging
|
80
|
+
|
81
|
+
These facilities come in two gems,
|
82
|
+
[templet](https://github.com/srycyk/templet)
|
83
|
+
and
|
84
|
+
[templet\_rails](https://github.com/srycyk/templet_rails).
|
85
|
+
|
86
|
+
The first is a self-contained DSL for rendering markup, i.e. HTML pages.
|
87
|
+
|
88
|
+
The second, which relies on the first,
|
89
|
+
is a Rails framework that has similar functionality to
|
90
|
+
the the Rails scaffold generator.
|
91
|
+
And it is as easy to get working, but more modular and extensible.
|
92
|
+
|
93
|
+
> Naturally, these gems need to be declared in your *Gemfile*.
|
94
|
+
> Please see the *Configuration* section below for further details.
|
95
|
+
|
96
|
+
### Basic Design
|
97
|
+
|
98
|
+
The framework is small and simple.
|
99
|
+
So much so that *framework* may be too grand a term,
|
100
|
+
as it could equally be described as a pattern,
|
101
|
+
with an attached API.
|
102
|
+
|
103
|
+
The framework follows many of Rails' conventions,
|
104
|
+
notably it provides default behaviour
|
105
|
+
that can be easily overridden or supplanted.
|
106
|
+
|
107
|
+
### Benefits
|
108
|
+
|
109
|
+
It allows the DRY principle to be more easily applied to the views
|
110
|
+
than with the usual templates, (like ERb & HAML),
|
111
|
+
which are essentially a single block of in-line code,
|
112
|
+
which can quickly become long and repetitive.
|
113
|
+
|
114
|
+
The framework promotes productivity
|
115
|
+
as the views can be written in idiomatic Ruby,
|
116
|
+
thus allowing more standardisation, concision and encapsulation.
|
117
|
+
|
118
|
+
The framework does *not*, in any way, *monkey-patch* the Rails core,
|
119
|
+
and should work with just about any version of Rails, even future ones!
|
120
|
+
Though it requires a fairly recent (i.e. supported) version of Ruby.
|
121
|
+
|
122
|
+
### Installing
|
123
|
+
|
124
|
+
An installation involves issuing a few commands, and, almost certainly,
|
125
|
+
will have no knock-on effects elsewhere.
|
126
|
+
Likewise, a de-installation is even less trouble.
|
127
|
+
|
128
|
+
### Twitter Bootstrap Dependency
|
129
|
+
|
130
|
+
In the framework, as it stands,
|
131
|
+
you do really need to use *Twitter Bootstrap 3.3*.
|
132
|
+
_Without it, the HTML will look awful!_
|
133
|
+
|
134
|
+
If you don't currently use this particular Bootstrap (3.3) version,
|
135
|
+
it won't be difficult, or take too long, to update the source yourself.
|
136
|
+
|
137
|
+
But if you don't use Bootstrap, it'll take some time
|
138
|
+
to modify the source to accommodate some other CSS library.
|
139
|
+
|
140
|
+
### Main Sections
|
141
|
+
|
142
|
+
The framework introduces the following code divisions:
|
143
|
+
|
144
|
+
1. The framework's core code,
|
145
|
+
which is directly copied into your application's file system,
|
146
|
+
in a few separate sub-directories.
|
147
|
+
This shouldn't need much changing - if any.
|
148
|
+
|
149
|
+
2. Application code, consisting of your own
|
150
|
+
modules that cater for specific use-cases.
|
151
|
+
_As a part of the initial installation,
|
152
|
+
there are general-purpose classes pre-installed in this area,
|
153
|
+
most of which are for a prototype layout._
|
154
|
+
|
155
|
+
3. A declarative testing sub-system in Rspec, which is optional.
|
156
|
+
|
157
|
+
### Usage
|
158
|
+
|
159
|
+
#### Two Basic Steps
|
160
|
+
|
161
|
+
To build individual application modules with the framework,
|
162
|
+
you create a controller and a *Viewer* class,
|
163
|
+
both of which can be generated.
|
164
|
+
|
165
|
+
##### The Controller
|
166
|
+
|
167
|
+
The controller looks pretty much the same as usual,
|
168
|
+
except for the way the view is invoked.
|
169
|
+
|
170
|
+
You render a view by calling, from the controller,
|
171
|
+
a method on an instance of a *Viewer* class.
|
172
|
+
|
173
|
+
However, you shouldn't need to refer to this *Viewer* class directly,
|
174
|
+
as there are controller utilities that provide shortcuts
|
175
|
+
to launch the view rendering.
|
176
|
+
|
177
|
+
##### The Viewer
|
178
|
+
|
179
|
+
This *Viewer* class carries out all of the HTML rendering,
|
180
|
+
letting you diverge from default functionality
|
181
|
+
that is provided by its superclasses.
|
182
|
+
|
183
|
+
Normally, there is just one of these classes per controller,
|
184
|
+
and they have (public) method names in common.
|
185
|
+
|
186
|
+
Inside this *Viewer* class, you're able to override a hatful of methods,
|
187
|
+
for either fine, or coarse, grained modifications.
|
188
|
+
|
189
|
+
Among other things, this class offers the following features:
|
190
|
+
|
191
|
+
1. Adding, or excluding, one or two surrounding Layouts which are
|
192
|
+
shared by a group of pages.
|
193
|
+
|
194
|
+
2. An ability to use Partials that let you split the whole
|
195
|
+
into discrete parts.
|
196
|
+
Like the Layouts above, they are similar (in intent) to
|
197
|
+
their correlates in Rails, but here they are Ruby subclasses
|
198
|
+
that render HTML by means of a rudimentary DSL.
|
199
|
+
|
200
|
+
3. An API to render composite HTML components,
|
201
|
+
like forms, tables and lists.
|
202
|
+
|
203
|
+
4. Utility classes that build collections of REST links for actions
|
204
|
+
on any type of model - with or without a corresponding parent model.
|
205
|
+
These links can be wrapped in HTML lists, or in any markup you like.
|
206
|
+
By subclaassing, you can add extra links to these menus.
|
207
|
+
|
208
|
+
5. Access all of the Rails *ActionView* methods,
|
209
|
+
such as *link_to*, *text\_field\_tag* & *render*,
|
210
|
+
as well as those you may have added yourself in the traditional
|
211
|
+
Rails-generated Helper modules -
|
212
|
+
but with this framework, you won't need these anymore!
|
213
|
+
|
214
|
+
### Getting Started
|
215
|
+
|
216
|
+
#### Generators
|
217
|
+
|
218
|
+
The gem for the framework consists of several generators,
|
219
|
+
which are your starting point.
|
220
|
+
|
221
|
+
A few are to do with the installation of the framework,
|
222
|
+
and are to be run just once.
|
223
|
+
|
224
|
+
The others are for producing application code,
|
225
|
+
and are to be run multiple times with varying arguments.
|
226
|
+
|
227
|
+
Principally, there is a scaffold generator that creates, at once,
|
228
|
+
a controller, a *Viewer* class to customise the HTML output,
|
229
|
+
some RSpec tests, and a Rails routing entry.
|
230
|
+
|
231
|
+
The generated code code should work without intervention,
|
232
|
+
providing default behaviour that can be easily modified,
|
233
|
+
|
234
|
+
More information on using the generators is given below.
|
235
|
+
|
236
|
+
#### Environment Setup
|
237
|
+
|
238
|
+
Be aware that you'll need to add some simple configuration directives,
|
239
|
+
which are mentioned in the *Configuration* section at the end.
|
240
|
+
|
241
|
+
<a name="faq"></a>
|
242
|
+
## Frequently Asked Questions
|
243
|
+
|
244
|
+
### What is it?
|
245
|
+
|
246
|
+
It is a Ruby framework, with associated libraries,
|
247
|
+
that provide an object oriented (pure Ruby) approach to
|
248
|
+
the rendering of markup, i.e. HTML and XML.
|
249
|
+
|
250
|
+
The framework is sparse, has few dependencies
|
251
|
+
and is not particularly complicated.
|
252
|
+
|
253
|
+
### Why use it?
|
254
|
+
|
255
|
+
Primarily, it's to boost development efficiency.
|
256
|
+
|
257
|
+
But you may also find it more comfortable to code in,
|
258
|
+
as it gives you more of a free rein than, say, ERb scripts.
|
259
|
+
|
260
|
+
#### *It's quick*
|
261
|
+
|
262
|
+
Using the supplied generators,
|
263
|
+
(which work like Rails' scaffolding),
|
264
|
+
you can have a viable fully-functional REST interface up and running
|
265
|
+
in next to no time.
|
266
|
+
|
267
|
+
And when you need to augment or alter the default functionality,
|
268
|
+
it lets you do so easily and briefly.
|
269
|
+
|
270
|
+
#### *It's flexible*
|
271
|
+
|
272
|
+
In Rails, object oriented support stops at the view stage.
|
273
|
+
|
274
|
+
When you use scripts like ERb or HAML or SLIM,
|
275
|
+
you're constrained by their in-line procedural design.
|
276
|
+
|
277
|
+
These scripts often end up being monolithic and painful to maintain.
|
278
|
+
Code sharing is too verbose,
|
279
|
+
as it usually results in a proliferation of tiny files and
|
280
|
+
complex helper methods, which, since they are global in scope,
|
281
|
+
need to be named with care.
|
282
|
+
|
283
|
+
In contrast, within this framework everything can be written in
|
284
|
+
pure unrestrained Ruby,
|
285
|
+
allowing you to use the language's object oriented (and functional)
|
286
|
+
features as you see fit.
|
287
|
+
|
288
|
+
For example, using this framework, it's much easier
|
289
|
+
to implement general-purpose components,
|
290
|
+
to fine-tune small variations,
|
291
|
+
to enforce site-wide uniformity in presentation,
|
292
|
+
and to rearrange the page sections.
|
293
|
+
|
294
|
+
### How easy is to learn?
|
295
|
+
|
296
|
+
For a Rails developer its workings should be intuitive.
|
297
|
+
Also, the API is relatively small, and what you need to know
|
298
|
+
to get started is even smaller.
|
299
|
+
|
300
|
+
### Is it compatible with traditional view rendering?
|
301
|
+
|
302
|
+
In this framework, you're still able to use the
|
303
|
+
(convenient and well known) Rails helper methods,
|
304
|
+
like *render*, *link\_to* and *options\_from\_collection\_for\_select*.
|
305
|
+
|
306
|
+
This allows you to *mix 'n' match* the two approaches,
|
307
|
+
which lays out a path should you require to switch
|
308
|
+
from from one methodology to the other.
|
309
|
+
|
310
|
+
### How is this facility used?
|
311
|
+
|
312
|
+
You can use it as a framework
|
313
|
+
that performs the entire view rendering process,
|
314
|
+
or you can just use it as a library (toolkit) to render view segments.
|
315
|
+
|
316
|
+
#### *As a framework*
|
317
|
+
|
318
|
+
To use it as a framework there are generally just two classes to create,
|
319
|
+
(though in the very simplest cases there is only one).
|
320
|
+
|
321
|
+
1. A *Controller* class, which is almost the same as usual,
|
322
|
+
the only major difference is in the way the view handling is executed,
|
323
|
+
which is by the class described directly below.
|
324
|
+
|
325
|
+
2. A *Viewer* class, which renders complete HTML pages
|
326
|
+
for (the actions of) its corresponding controller,
|
327
|
+
with which it has a similarly named public API.
|
328
|
+
For example, both may share the public method names, *index* and *show*.
|
329
|
+
|
330
|
+
#### *As a library*
|
331
|
+
|
332
|
+
If, instead, you want to use it as library for rendering components such
|
333
|
+
as forms, tables, lists, navigation buttons, Bootstrap menus, etc..
|
334
|
+
There are a several *mixin* Ruby modules, and utility classes,
|
335
|
+
included that facilitate this.
|
336
|
+
|
337
|
+
At present, you'll have to dip into the source yourself to learn this API,
|
338
|
+
though it is covered briefly later on.
|
339
|
+
|
340
|
+
### Will using it have any unwanted side-effects?
|
341
|
+
|
342
|
+
Highly unlikely, as it doesn't alter anything in any existing classes,
|
343
|
+
and there aren't too many calls to the Rails API.
|
344
|
+
|
345
|
+
It has only one run-time dependency on a third-party gem,
|
346
|
+
as it uses *Twitter Bootstrap 3.3*, (for the HTML presentation).
|
347
|
+
|
348
|
+
### What does it contain?
|
349
|
+
|
350
|
+
The package consists of two relatively small gems,
|
351
|
+
firstly, a rendering DSL,
|
352
|
+
and secondly, a gem that is for use with Rails and Bootstrap (3.3).
|
353
|
+
|
354
|
+
The first is a run-time dependency.
|
355
|
+
The second contains several generators
|
356
|
+
that add files in your application's file system.
|
357
|
+
|
358
|
+
### Where does it add its code?
|
359
|
+
|
360
|
+
The framework, by default, is copied into two
|
361
|
+
directories: *app/helpers/templet/* and *app/controllers/templet/*,
|
362
|
+
and two Ruby modules in *app/helpers/*.
|
363
|
+
|
364
|
+
Your application view's code is put under *app/helpers/app/*.
|
365
|
+
|
366
|
+
### Is it easy to deinstall?
|
367
|
+
|
368
|
+
If you try it out, and then decide to ditch it,
|
369
|
+
a rollback will almost certainly be effortless.
|
370
|
+
|
371
|
+
It will just involve deleting a number of files,
|
372
|
+
for which there's a generator, *templet:destroy*.
|
373
|
+
|
374
|
+
This generator deletes all of the framework
|
375
|
+
and the nearly all of the application files,
|
376
|
+
apart from any controllers that you may have generated,
|
377
|
+
and entries in *config/routes.rb*.
|
378
|
+
|
379
|
+
### What does it depend on?
|
380
|
+
|
381
|
+
Apart from Rails itself, there is a dependency on *Twitter Bootstrap 3.3*.
|
382
|
+
|
383
|
+
This is not strictly compulsory, (it'll spit out the HTML regardless)
|
384
|
+
but, right now, you'll have to change the source code yourself
|
385
|
+
to disentangle this dependency,
|
386
|
+
|
387
|
+
It's currently for Bootstrap 3.3, but if you
|
388
|
+
fork the code for compatibility with, say, Bootstrap 4,
|
389
|
+
you should only be occupied for a few hours,
|
390
|
+
and you'll only need to edit a half-dozen files at most.
|
391
|
+
|
392
|
+
However, if you don't use Bootstrap,
|
393
|
+
and you choose to adapt this framework
|
394
|
+
to work with some other styling (CSS) API,
|
395
|
+
it'll likely take you a good while.
|
396
|
+
|
397
|
+
### Will it be supported?
|
398
|
+
|
399
|
+
No guarantee!
|
400
|
+
But will you need long-term external support? Probably not.
|
401
|
+
|
402
|
+
The code-base so small that taking responsibility
|
403
|
+
for its upkeep should not be too onerous.
|
404
|
+
There is little to go wrong.
|
405
|
+
|
406
|
+
### Are there tests?
|
407
|
+
|
408
|
+
It comes supplied with a rudimentary testing system.
|
409
|
+
|
410
|
+
This consists of Rspec *shared\_examples* that
|
411
|
+
test the controller's JSON output,
|
412
|
+
and other *shared\_examples* that test the output of the *Viewer* classes,
|
413
|
+
using (Nokogiri) CSS selectors on the resultant HTML.
|
414
|
+
|
415
|
+
Although limited in scope, these tests can be written in
|
416
|
+
a very small chunk of declarative code.
|
417
|
+
Nonetheless, in their present form, they are not a viable substitute
|
418
|
+
for the usual model and feature tests.
|
419
|
+
|
420
|
+
When running the tests, it needs the gems:
|
421
|
+
*rspec*, *nokogiri* and *factory_bot*,
|
422
|
+
for which (model) factories have already been defined.
|
423
|
+
|
424
|
+
### What sort of applications is it most suited for?
|
425
|
+
|
426
|
+
1. It's ideal for REST-based apps, especially administrative dashboards.
|
427
|
+
|
428
|
+
2. Experimental or MVP sites, where it can quickly plug holes.
|
429
|
+
The framework reduces development time because most modifications
|
430
|
+
can be written in compact sections of (structured) code.
|
431
|
+
|
432
|
+
3. In general, it's for data-base driven sites -
|
433
|
+
not so much for fancy (HTML/JS-heavy) sites
|
434
|
+
where data is passively consumed.
|
435
|
+
|
436
|
+
### What are its advantages?
|
437
|
+
|
438
|
+
1. As well as being quicker to develop in, it seems to run a bit faster
|
439
|
+
than the conventional Rails ERb rendering.
|
440
|
+
|
441
|
+
2. Presentational changes can be made from a single place,
|
442
|
+
and then propagate immediately throughout the whole site.
|
443
|
+
For example, all textual HTML links can be changed to iconic
|
444
|
+
in a single line of code.
|
445
|
+
|
446
|
+
3. It lets you do things like putting view segments
|
447
|
+
into variables that you can pass around for, say,
|
448
|
+
later rendition within another nested component.
|
449
|
+
|
450
|
+
4. It can be used alongside existing views scripts and Helper methods.
|
451
|
+
|
452
|
+
5. Testing view components is made easier, as they can be implemented
|
453
|
+
in separate stand-alone classes.
|
454
|
+
|
455
|
+
### What are its disadvantages?
|
456
|
+
|
457
|
+
1. The bare Bootstrap styling is characterless,
|
458
|
+
and the HTML will be difficult for designers to modify.
|
459
|
+
|
460
|
+
2. The way in which this framework is structured may rub against your
|
461
|
+
existing practices.
|
462
|
+
|
463
|
+
3. Some functionality, provided by Rails, for view rendering
|
464
|
+
is now not available. These are things like: view path look-ups,
|
465
|
+
Turbolinks support, and an inability to *yield* additional content
|
466
|
+
at arbitrary positions on the page.
|
467
|
+
|
468
|
+
4. Similarly, caching view segments may be more difficult than usual.
|
469
|
+
You should still be able to use Rails' low-level fragment caching,
|
470
|
+
but partial caching is impossible.
|
471
|
+
|
472
|
+
5. Having to learn how to use the caboodle in the first place.
|
473
|
+
But since you've ploughed through this far, you're getting there,
|
474
|
+
and I congratulate your endurance!
|
475
|
+
|
476
|
+
6. But seriously, there may be possible security issues with
|
477
|
+
code injection attacks.
|
478
|
+
This is because the whole page is made *html_safe*.
|
479
|
+
Probably the best way of safeguarding against this is by adding model
|
480
|
+
validations to ensure that malicious snippets of code cannot be saved
|
481
|
+
to begin with.
|
482
|
+
There is a validator module,
|
483
|
+
(*app/models/concerns/nasty_char_validator.rb*, in *questionable*)
|
484
|
+
which can be added to model classes to prevent users from saving
|
485
|
+
records containing field values with non-standard punctuation.
|
486
|
+
Alternatively, you could *sanitize* input fields
|
487
|
+
in a *before_validation* callback.
|
488
|
+
|
489
|
+
### How does it compare to similar offerings?
|
490
|
+
|
491
|
+
Although the following claims do present
|
492
|
+
the framework in its *best light*,
|
493
|
+
they, nevertheless, hold good, arguably.
|
494
|
+
|
495
|
+
1. It is similar in function to data-base maintenance gems,
|
496
|
+
(like *active_admin*),
|
497
|
+
but while such like provide a finished application,
|
498
|
+
(which can only be modified via a restrictive DSL),
|
499
|
+
this framework provides a prototype (preliminary) application,
|
500
|
+
(which can be modified in any way you wish).
|
501
|
+
|
502
|
+
2. It has the modularity of say, *cells*, but does not rely on
|
503
|
+
scripts behind the scenes, which add a layer of complexity,
|
504
|
+
requiring you, for one, to flit between multiple file edits.
|
505
|
+
|
506
|
+
3. It has the *kick-start* convenience of Rails's scaffolding.
|
507
|
+
|
508
|
+
4. You can write HTML with the economy of HAML or SLIM,
|
509
|
+
and be assured that it's well-formed.
|
510
|
+
|
511
|
+
5. The *Viewer* classes, in themselves, have the simplicity of Sinatra.
|
512
|
+
|
513
|
+
<a name="gen"></a>
|
514
|
+
## Generators
|
515
|
+
|
516
|
+
The generators are your first port of call.
|
517
|
+
One is invoked to install the framework's core code.
|
518
|
+
Others are invoked as an initial step in developing application modules.
|
519
|
+
|
520
|
+
The generators are contained in the gem, *templet_rails*.
|
521
|
+
Apart from documentation, this gem contains nothing else of interest,
|
522
|
+
and it's only for use in the development environment.
|
523
|
+
|
524
|
+
These generators are listed as follows:
|
525
|
+
|
526
|
+
```
|
527
|
+
$ rails g
|
528
|
+
...
|
529
|
+
Templet:
|
530
|
+
templet:controller
|
531
|
+
templet:core
|
532
|
+
templet:core_rspec
|
533
|
+
templet:destroy
|
534
|
+
templet:routes
|
535
|
+
templet:rspec
|
536
|
+
templet:scaffold
|
537
|
+
templet:viewer
|
538
|
+
...
|
539
|
+
```
|
540
|
+
|
541
|
+
> *Troubleshooting tip.* If you're unable to see these generators as listed,
|
542
|
+
> from the command-line, try this: `$ mkdir lib/generators`.
|
543
|
+
|
544
|
+
### Framework Installation
|
545
|
+
|
546
|
+
The first generator to run is *templet:core*,
|
547
|
+
which copies the complete source code of the framework into
|
548
|
+
your local file system - once and for all.
|
549
|
+
|
550
|
+
To install the framework, from the command line, key in:
|
551
|
+
|
552
|
+
````
|
553
|
+
$ rails generator templet:core
|
554
|
+
````
|
555
|
+
|
556
|
+
#### Testing the Framework Internally
|
557
|
+
|
558
|
+
If you wish to add some tests for the framework itself,
|
559
|
+
then you can run the generator *templet:core_rspec*.
|
560
|
+
This generator copies files into your *spec/helpers/* directory tree,
|
561
|
+
(inside the sub-directories: *app/* and *templet/*).
|
562
|
+
|
563
|
+
This part is best left out at first, as it adds clutter,
|
564
|
+
slowing down your test suite without any real pay back.
|
565
|
+
However, if you modify the framework for yourself
|
566
|
+
then these tests may be useful.
|
567
|
+
|
568
|
+
#### Deinstallation
|
569
|
+
|
570
|
+
If you decide to remove the framework,
|
571
|
+
you can run the generator *templet:destroy*.
|
572
|
+
This deletes __all__ associated files, apart from the controllers.
|
573
|
+
You do this with:
|
574
|
+
|
575
|
+
```
|
576
|
+
$ rails generator templet:destroy --all
|
577
|
+
```
|
578
|
+
|
579
|
+
### Generating Application Code
|
580
|
+
|
581
|
+
The remaining generators are for use when
|
582
|
+
you begin to write your own application modules.
|
583
|
+
|
584
|
+
But prior to using these generators, you need a model already in place,
|
585
|
+
which you can create using the standard Rails (model) generator.
|
586
|
+
|
587
|
+
These generators replace Rails' controller and view generators,
|
588
|
+
with which they have a lot in common.
|
589
|
+
That is, they provide basic REST functionality,
|
590
|
+
(i.e. a data-base administration interface),
|
591
|
+
that should run without error straight off,
|
592
|
+
and is ready for you to change.
|
593
|
+
|
594
|
+
#### Scaffold Generator
|
595
|
+
|
596
|
+
The quickest way to start is by using the *templet:scaffold* generator,
|
597
|
+
which creates the following:
|
598
|
+
|
599
|
+
1. A controller that is similar to a regular REST controller, which:
|
600
|
+
* Handles the HTTP request formats: HTML, JS & JSON
|
601
|
+
* Can be namespaced, i.e. nested within a Ruby module
|
602
|
+
* Allows you to restrict the supported REST actions
|
603
|
+
* Allows you to declare a parent (and grand-parent)
|
604
|
+
for the main model, which can have any name you like
|
605
|
+
|
606
|
+
2. A *Viewer* subclass that renders all of the HTML
|
607
|
+
for each controller action.
|
608
|
+
It's usually generated with little in its body,
|
609
|
+
as it's for you to change.
|
610
|
+
|
611
|
+
3. Some Rspec tests for the controller and *Viewer* classes.
|
612
|
+
|
613
|
+
4. REST routing entries, which are written to *config/routes.rb*.
|
614
|
+
|
615
|
+
In turn, it runs the four generators:
|
616
|
+
|
617
|
+
1. templet:controller
|
618
|
+
3. templet:viewer
|
619
|
+
2. templet:rspec
|
620
|
+
4. templet:routes
|
621
|
+
|
622
|
+
Each of these generators can be invoked singly,
|
623
|
+
which is useful, if, say, you don't want Rspec tests installed.
|
624
|
+
|
625
|
+
#### Generator Remarks
|
626
|
+
|
627
|
+
There are several options available which let you specify the names of
|
628
|
+
controllers, models, installation directories, etc..
|
629
|
+
For full information on usage, call any of them with the *--help* option.
|
630
|
+
For example, `rails g templet:core --help`
|
631
|
+
The scaffold generator lists all of the options concerned with
|
632
|
+
producing application code.
|
633
|
+
|
634
|
+
Like in Rails, the generators only provide support for REST functionality.
|
635
|
+
If your requirements diverge from this,
|
636
|
+
and you're forced to write code from scratch,
|
637
|
+
then these generators probably won't be a great deal of use.
|
638
|
+
_In such cases, you should find the framework no more difficult
|
639
|
+
to code in than traditional view scripts - and maybe it'll be easier._
|
640
|
+
|
641
|
+
> Once you're over and done with the generators, you can remove this gem.
|
642
|
+
> Note that the other gem, *templet*, is a run-time dependency,
|
643
|
+
> so needs to be present in all environments.
|
644
|
+
|
645
|
+
<a name="notes"></a>
|
646
|
+
## Notes
|
647
|
+
|
648
|
+
This part recaps some of what was said before, but in a bit more depth.
|
649
|
+
|
650
|
+
### Overall (Onion) Structure
|
651
|
+
|
652
|
+
The framework has a strict hierarchy,
|
653
|
+
in which the higher layers depend on those below.
|
654
|
+
Starting at the bottom, there are the four layers:
|
655
|
+
|
656
|
+
1. A bare-boned DSL that renders markup tags. You pass in a number of
|
657
|
+
method look-up contexts into this API,
|
658
|
+
as well as local variables.
|
659
|
+
|
660
|
+
2. Support for components (as Ruby classes) that render
|
661
|
+
(encapsulated) view segments.
|
662
|
+
|
663
|
+
3. A Rails-like micro-framework that stands in for the usual
|
664
|
+
view handling mechanism, (i.e. ERb scripts),
|
665
|
+
providing default functionality, ready to be changed.
|
666
|
+
|
667
|
+
4. A Rails scaffolding substitute, that generates a REST administrative
|
668
|
+
interface. This includes a controller and a *Viewer* class.
|
669
|
+
|
670
|
+
This is a rather abstract refined description -
|
671
|
+
so don't linger as more concrete details come next.
|
672
|
+
|
673
|
+
### The Framework
|
674
|
+
|
675
|
+
#### Prerequisites
|
676
|
+
|
677
|
+
At run-time, the framework has a single dependent gem, *templet*.
|
678
|
+
|
679
|
+
For testing, it requires *rspec*, *nokogiri* and *factory_bot*.
|
680
|
+
And it needs *factory_bot* factories for the models being tested.
|
681
|
+
|
682
|
+
#### Framework Code Locations
|
683
|
+
|
684
|
+
The core code, which is installed by the generator, *templet:core*,
|
685
|
+
is placed in two directories:
|
686
|
+
|
687
|
+
1. In *app/helpers/templet/*, which is a tree (of several branches)
|
688
|
+
that contains the bulk of the code.
|
689
|
+
It contains the run-time framework and libraries.
|
690
|
+
_Incidentally, there is a generator option to relocate this directory._
|
691
|
+
|
692
|
+
2. In *app/controllers/templet/*, which contains a few controller modules
|
693
|
+
of helper methods that simplify the process of invoking the view.
|
694
|
+
|
695
|
+
Also, there are another two files, *app/helpers/templet_helper.rb*
|
696
|
+
and *app/helpers/app.rb*, which, for now, can be safely deleted.
|
697
|
+
They are reserved for global settings, the former for the framework,
|
698
|
+
the latter for the application.
|
699
|
+
|
700
|
+
### Writing Applications
|
701
|
+
|
702
|
+
As usual, it's assumed that your applications will, for the most part,
|
703
|
+
be made up of a series of REST interfaces,
|
704
|
+
which have one or more models that are fetched from a data-base.
|
705
|
+
|
706
|
+
If your requirements don't square with this methodology,
|
707
|
+
then the framework may only be of limited assistance,
|
708
|
+
but this much is also true of Rails.
|
709
|
+
|
710
|
+
#### Application Code Locations
|
711
|
+
|
712
|
+
In addition to the core code, (mentioned in the preceding section),
|
713
|
+
the generator, *templet:core*, also creates another directory tree
|
714
|
+
for view-specific application code.
|
715
|
+
|
716
|
+
The generator installs a skeletal application area,
|
717
|
+
(under the directory, *app/helpers/app/*),
|
718
|
+
which is where your own application code goes.
|
719
|
+
_At present, relocating this directory might cause issues._
|
720
|
+
|
721
|
+
The generator also installs (in this area) some place-holder
|
722
|
+
classes for the HTML layouts and REST link menus.
|
723
|
+
These are put in the two sub-directories, *panel/* and *link_sets/*.
|
724
|
+
The code placed here is only a suggestion to give you an idea
|
725
|
+
of how the various elements fit together.
|
726
|
+
|
727
|
+
> By the way, no files are needed in the view's usual directory tree,
|
728
|
+
> i.e. *app/views/*, except mailers, of course.
|
729
|
+
> Nor are (the Rails generated) Helper modules needed,
|
730
|
+
> but their base directory (*app/helpers/*) is still used.
|
731
|
+
|
732
|
+
#### Application Modules
|
733
|
+
|
734
|
+
As said, to hook into the framework,
|
735
|
+
you build individual application modules with a *Controller* and,
|
736
|
+
nearly always, a *Viewer* class.
|
737
|
+
As said, both of these can be generated.
|
738
|
+
|
739
|
+
#### The Controller
|
740
|
+
|
741
|
+
The controller is put in its usual directory and will look familiar.
|
742
|
+
It carries out its usual tasks in the usual way - for example,
|
743
|
+
you still apply filters and define instance variables for use in the view.
|
744
|
+
The only substantial difference is in the view dispatching.
|
745
|
+
|
746
|
+
For brevity, helper methods are provided that reduce the
|
747
|
+
view dispatching to a line, or two, of code.
|
748
|
+
|
749
|
+
#### Invoking the View from the Controller
|
750
|
+
|
751
|
+
To render a view, the controller calls a method
|
752
|
+
on an instance of a *Viewer* class,
|
753
|
+
which, by convention, shares the name of the controller's calling method.
|
754
|
+
|
755
|
+
To save you from having to construct (and execute)
|
756
|
+
a *Viewer* class explicitly,
|
757
|
+
there are several controller helper methods,
|
758
|
+
(kept in Ruby modules in *app/controllers/templet/*),
|
759
|
+
that simplify the process of dealing with this *Viewer* class,
|
760
|
+
which can, sometimes, require a fair few input parameters.
|
761
|
+
|
762
|
+
These helper methods cater for the output formats: *html, js & json*.
|
763
|
+
And should be useful if you write controller code by hand.
|
764
|
+
|
765
|
+
The *Viewer* is actually called from the controller's
|
766
|
+
built-in *render* helper method, as an *inline* template.
|
767
|
+
Eventually, it's a line of code (in the controller) resembling something
|
768
|
+
like: `render inline: 'ViewerClass.new.index'`.
|
769
|
+
|
770
|
+
However, in the current implementation,
|
771
|
+
this *inline* template does not call the *Viewer* class directly,
|
772
|
+
but instead uses the bridging class, *ViewerCallString*.
|
773
|
+
This class compiles a string of executable Ruby that makes the
|
774
|
+
actual call to the *Viewer* that fires up the view rendering.
|
775
|
+
This round about path is taken so to pass in (implicitly)
|
776
|
+
various variables for accessing within the view context.
|
777
|
+
_This source of this class, *ViewerCallString* is quite well documented._
|
778
|
+
|
779
|
+
#### The Viewer Class
|
780
|
+
|
781
|
+
This class, which is placed under the directory, *app/helpers/app/*,
|
782
|
+
(or sub-directory thereof),
|
783
|
+
performs the functions of the usual view templates, such as ERb scripts.
|
784
|
+
It renders the entire HTML page for each appropriate controller action.
|
785
|
+
|
786
|
+
It inherits from a few superclasses,
|
787
|
+
(e.g. *Templet::ViewerRest*),
|
788
|
+
that provide very basic behaviour that you'll,
|
789
|
+
inevitably, need to extend or replace.
|
790
|
+
You can do this at any granularity.
|
791
|
+
|
792
|
+
* For small changes, like specifying the fields
|
793
|
+
to display on the *index* or *show* pages.
|
794
|
+
|
795
|
+
* For medium-sized changes, like adding pagination, images,
|
796
|
+
supplementary (contextual) text, link sets, etc..
|
797
|
+
|
798
|
+
* For very large changes, like writing all of the HTML yourself or
|
799
|
+
calling ERb templates (via the built-in view helper method *render*).
|
800
|
+
|
801
|
+
Broadly speaking, such changes are made by overriding methods.
|
802
|
+
|
803
|
+
The superclass naming convention, where you append the substring *Viewer*
|
804
|
+
onto a singular declension of the controller's (camel-cased) name,
|
805
|
+
saves you from having to explicitly state
|
806
|
+
the fully qualified class name when you call instances
|
807
|
+
of this *Viewer* class from the controller.
|
808
|
+
For example, this (derived) class may be called something
|
809
|
+
like *App::UserViewer* or,
|
810
|
+
if it's namespaced, *App::Admin::UserViewer*.
|
811
|
+
|
812
|
+
#### The Viewer Subclass
|
813
|
+
|
814
|
+
As said, the *Viewer* class inherits from a number of superclasses.
|
815
|
+
These are: *App::BaseViewer*, (for site-wide settings), which inherits
|
816
|
+
a non-abstract base class, *Templet::ViewerRest*,
|
817
|
+
which itself inherits from the abstract class, *Templet::ViewerBase*.
|
818
|
+
|
819
|
+
The purpose of these subclasses are to render markup (HTML)
|
820
|
+
for each of the relevant controller actions.
|
821
|
+
To expedite this, it has the following functionality:
|
822
|
+
|
823
|
+
1. Handles shared layouts, which can be varied per controller,
|
824
|
+
via the *Viewer*.
|
825
|
+
|
826
|
+
2. Provides ready access to the underlying API.
|
827
|
+
|
828
|
+
3. Exposes a number of named data items for use in the view.
|
829
|
+
Most of these are set up in the call from the controller.
|
830
|
+
|
831
|
+
In very simple cases, you can use an instance
|
832
|
+
of *Templet::ViewerRest*, or *App::BaseViewer*, directly,
|
833
|
+
whereupon a REST interface should still be fully operational.
|
834
|
+
_Your own subclasses let you deviate from the *no-frills* functionality._
|
835
|
+
|
836
|
+
#### HTML Layouts
|
837
|
+
|
838
|
+
As in Rails, you can specify layouts which are used by all
|
839
|
+
(or a circumscribed group of) controllers.
|
840
|
+
|
841
|
+
But in this framework there are two layouts, an inner and outer.
|
842
|
+
|
843
|
+
These are specified by class names returned by the *Viewer*
|
844
|
+
instance methods, *layout_class* and *panel_class*.
|
845
|
+
The former is for the outer layout, the latter for the inner.
|
846
|
+
|
847
|
+
##### The Outer Layout
|
848
|
+
|
849
|
+
This is equivalent to the layout that comes with Rails.
|
850
|
+
It contains everything except for the HTML *body* tag,
|
851
|
+
that is, it fills in the *head* tag,
|
852
|
+
pulling in assets, such as the *Bootstrap* CSS and JS libraries.
|
853
|
+
|
854
|
+
This layout is specified in a class kept inside of the framework's
|
855
|
+
directory tree, namely, *app/helpers/templet/layouts/html.rb*
|
856
|
+
If you want to use something else instead,
|
857
|
+
you should put a new version in your application area.
|
858
|
+
|
859
|
+
If the HTTP request is for the JS output format (i.e. remote, AJAX)
|
860
|
+
then this (outer) layout is omitted - as you'd expect!
|
861
|
+
|
862
|
+
##### The Inner Layout
|
863
|
+
|
864
|
+
As said, you can also specify a further inner layout,
|
865
|
+
(that is rendered within the *body* HTML tag),
|
866
|
+
which allows you to display supplementary markup,
|
867
|
+
like menus and headings.
|
868
|
+
|
869
|
+
These layout classes are found in the directory, *app/helpers/app/panel/*.
|
870
|
+
|
871
|
+
As noted, you'll want to change this inner layout,
|
872
|
+
as it generated for you with pre-written sample code,
|
873
|
+
intended to be illustrative.
|
874
|
+
|
875
|
+
This sample code is nested via inheritance chains,
|
876
|
+
whose participant classes have names that are prefixed with *Layout*.
|
877
|
+
|
878
|
+
In this directory, there are also sample classes,
|
879
|
+
suffixed with *Option*,
|
880
|
+
that provide custom functionality for various page sections.
|
881
|
+
They are set up in the class, *OptionsConfig*.
|
882
|
+
You may possibly adopt this pattern in your own code,
|
883
|
+
or just get shot of it.
|
884
|
+
|
885
|
+
#### REST Link Menus
|
886
|
+
|
887
|
+
There are general-purpose classes to render lists of HTML links that
|
888
|
+
point to actions in REST controllers, e.g. index, show & edit.
|
889
|
+
These classes are in the directory, *app/helpers/templet/links/*.
|
890
|
+
|
891
|
+
They are for use with any type of *ActiveRecord* model,
|
892
|
+
combined with, if need be, a model's parent and grand-parent.
|
893
|
+
And even a dependent's name, (i.e. a model's children),
|
894
|
+
which is used to dispay a forward HTML link.
|
895
|
+
|
896
|
+
There are, primarily, two template classes
|
897
|
+
that render a list of HTML links for REST actions.
|
898
|
+
These two are *Templet::Links::BsLinkSetNavigation*
|
899
|
+
and *Templet::Links::BsLinkSetCollection*.
|
900
|
+
The former is given a model *instance* (for the actions: edit show etc.),
|
901
|
+
the latter is given a model's *name* (for the actions: index new etc.).
|
902
|
+
|
903
|
+
You can add arbitrary links (at certain spots) to these lists of HTML links
|
904
|
+
by subclassing one of the two above classes.
|
905
|
+
|
906
|
+
These classes inherit from *Templet::Links::BsLinkSetBase*,
|
907
|
+
which have utility methods to render individual HTML links.
|
908
|
+
|
909
|
+
The directory, *app/helpers/app/link_sets/*, is reserved for
|
910
|
+
your own classes that render HTML link menus.
|
911
|
+
Your own classes should inherit from one of the three classes above.
|
912
|
+
|
913
|
+
The (list of) links can be presented in HTML containers,
|
914
|
+
such as the various *Bootstrap* Button Groups and Navbars.
|
915
|
+
There are some factories (in *app/helpers/templet/utils/*)
|
916
|
+
that do this for you.
|
917
|
+
|
918
|
+
This part has, perhaps, the most intricate functionality,
|
919
|
+
and is best learned by looking at sample code in the example app,
|
920
|
+
[questionable](https://github.com/srycyk/questionable).
|
921
|
+
|
922
|
+
> Do note that this example app has many other examples of API usage,
|
923
|
+
> and is complementary to this guide,
|
924
|
+
> as it has the examples that are absent here.
|
925
|
+
|
926
|
+
#### HTML Components
|
927
|
+
|
928
|
+
The API has utility mixin methods to render the standard
|
929
|
+
HTML lists and tables - to which CSS class names can be passed.
|
930
|
+
|
931
|
+
1. The lists (HTML tag *ul*) take as input a Ruby Array of list items.
|
932
|
+
|
933
|
+
2. The tables take as input a Ruby Hash, where the key is the heading,
|
934
|
+
and the value is, usually, a Ruby Proc, to which individual models
|
935
|
+
are passed, taken one-by-one from a given Array of models.
|
936
|
+
|
937
|
+
2. Definition (HTML tag *dl*) lists take as input
|
938
|
+
a similar kind of Hash as the tables (i.e. item *2*).
|
939
|
+
If this Hash has lambdas as values,
|
940
|
+
a single model should be passed to this method as well.
|
941
|
+
|
942
|
+
There are other API facilities including:
|
943
|
+
|
944
|
+
1. Mixin methods to render Bootstrap components,
|
945
|
+
e.g. for the grid system and button groups.
|
946
|
+
|
947
|
+
2. Mixin methods that return various lambdas
|
948
|
+
that are used by the generic components.
|
949
|
+
A model instance is often passed to these lambdas.
|
950
|
+
|
951
|
+
3. Classes to let you render HTML input forms in a short block of code.
|
952
|
+
The outputted HTML will be adorned with Bootstrap's regalia,
|
953
|
+
i.e. in a *form-group*, with optional help text, etc..
|
954
|
+
The main HTML input types are supported.
|
955
|
+
|
956
|
+
4. Classes to render composite view segments, like a search form.
|
957
|
+
|
958
|
+
These facilities are in sub-directories below *app/helpers/templet/*,
|
959
|
+
and are *mixins/ (1 & 2)*, *forms/ (2)*, and *utils/ (3)*.
|
960
|
+
|
961
|
+
### System Variables
|
962
|
+
|
963
|
+
Within the viewer class there are a number of objects made available
|
964
|
+
that you can reference in your own custom view code.
|
965
|
+
|
966
|
+
The principal object is *renderer*, and is used to render markup using
|
967
|
+
the DSL that is mentioned many times above.
|
968
|
+
This object is an instance of *Templet::Renderer* (in the gem *templet*),
|
969
|
+
and can be used in two ways:
|
970
|
+
|
971
|
+
1. To render HTML snippets by means of its *call* method,
|
972
|
+
to which a block is passed, as in:
|
973
|
+
`renderer.call { span 'Goodbye cruel world' }`.
|
974
|
+
|
975
|
+
2. Directly, as in `renderer.root_path`. but this has limited usefulness.
|
976
|
+
|
977
|
+
For REST controllers there are the objects *model*, *parent*, and
|
978
|
+
perhaps *grand\_parent*, as well as a few others.
|
979
|
+
These are used for generic components,
|
980
|
+
such as REST link menus and headings.
|
981
|
+
|
982
|
+
If you prefer more natural names than *model* or *parent*,
|
983
|
+
(or if you require extra input for the view),
|
984
|
+
you can define instance variables in the controller
|
985
|
+
and then pass their names into the *Viewer* class,
|
986
|
+
whereupon they will become accessible (by name) in the view code.
|
987
|
+
|
988
|
+
### Configuration
|
989
|
+
|
990
|
+
The example application,
|
991
|
+
[questionable](https://github.com/srycyk/questionable),
|
992
|
+
has all of these configuration settings in place,
|
993
|
+
so may be worth looking at if anything goes wrong in your app.
|
994
|
+
|
995
|
+
#### Adding Gems
|
996
|
+
|
997
|
+
There are two necessary lines to add to your *Gemfile*:
|
998
|
+
|
999
|
+
```
|
1000
|
+
gem 'templet', git: 'https://github.com/srycyk/templet'
|
1001
|
+
|
1002
|
+
gem 'templet_rails', git: 'https://github.com/srycyk/templet_rails', group: :development
|
1003
|
+
```
|
1004
|
+
|
1005
|
+
You can, instead, leave the *git* address out,
|
1006
|
+
and fetch the gems in the usual way, i.e. from *rubygems.org*.
|
1007
|
+
Fetching from *github*, however, will give you the most recent version.
|
1008
|
+
|
1009
|
+
In addition, there are following gems:
|
1010
|
+
|
1011
|
+
```
|
1012
|
+
gem 'bootstrap-sass', '~> 3.3.7'
|
1013
|
+
|
1014
|
+
group :development, :test do
|
1015
|
+
gem 'factory_bot_rails'
|
1016
|
+
end
|
1017
|
+
|
1018
|
+
# These are optional
|
1019
|
+
gem 'sqlite3' # or some other DB gem
|
1020
|
+
gem 'kaminari' # if you want to use paging
|
1021
|
+
```
|
1022
|
+
|
1023
|
+
#### Rspec Support
|
1024
|
+
|
1025
|
+
If running tests, add these lines to *spec/spec_helper.rb*:
|
1026
|
+
|
1027
|
+
```
|
1028
|
+
require 'factory_bot'
|
1029
|
+
|
1030
|
+
Dir["./spec/support/**/*.rb"].each {|file| require file }
|
1031
|
+
```
|
1032
|
+
|
1033
|
+
The testing suites require that you have *factory\_bot* factories
|
1034
|
+
set up for the models that are to be the subject of the tests.
|
1035
|
+
|
1036
|
+
The framework installation will add a number of configuration files
|
1037
|
+
in *spec/support/apis/* and *spec/support/templet/*.
|
1038
|
+
|
1039
|
+
## Licence
|
1040
|
+
|
1041
|
+
The gem is available as open source under the terms
|
1042
|
+
of the [MIT License](https://opensource.org/licenses/MIT).
|
1043
|
+
|
1044
|
+
### Contact
|
1045
|
+
|
1046
|
+
If you have any queries or suggestions,
|
1047
|
+
mail me at stephen.rycyk@googlemail.com
|
1048
|
+
|
1049
|
+
### To Do
|
1050
|
+
|
1051
|
+
1. Upgrade support for installing a new version of the framework,
|
1052
|
+
without affecting application code.
|
1053
|
+
2. Add two global config files for handling variation.
|
1054
|
+
One for the framework, another for the application.
|
1055
|
+
3. Allow more flexibility about where the directory trees are to be located.
|
1056
|
+
4. Remove all files to do with Rspec support unless this is explicitly requested.
|
1057
|
+
5. Add support for mailer templates, so that HTML and plain-text formatted
|
1058
|
+
mails are both rendered from a single source of text.
|
1059
|
+
6. Refactor the classes producing REST link menus.
|