ttl2html 1.0.0 → 1.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 +4 -4
- data/lib/ttl2html/template.rb +18 -3
- data/lib/ttl2html/version.rb +1 -1
- data/lib/ttl2html.rb +67 -33
- data/locales/en.yml +26 -0
- data/locales/ja.yml +25 -0
- data/templates/about.html.erb +5 -4
- data/templates/default.html.erb +2 -2
- data/templates/index.html.erb +1 -1
- data/templates/layout.html.erb +1 -1
- data/templates/shape-table.html.erb +14 -9
- metadata +18 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2d481c51d33a3f278444c1029dc50602c11d2b4d3e494e78884d4feabada2059
|
4
|
+
data.tar.gz: c0402991e0ac87f10aa4afc09a89c53ab7aa1103cd4a6f8d7cd42601f3e7cec4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aecbba96f8160b240d653eca3d41e5e6370f39b5805e96d07cbaafae5345e411950de991d053db5a0fbf5bdee1293e474035991968af39f751361cb272013c48
|
7
|
+
data.tar.gz: 0d9992e7381665ef9b137473c46ac3a381674cc6d899ef2a4a16a18853437381eb78362cacef3b59850f29db5820242563c972842eb34cc5f4f5942f3f668120
|
data/lib/ttl2html/template.rb
CHANGED
@@ -3,16 +3,20 @@
|
|
3
3
|
require "fileutils"
|
4
4
|
require "pathname"
|
5
5
|
require "erb"
|
6
|
+
require "i18n"
|
6
7
|
|
7
8
|
module TTL2HTML
|
8
9
|
class Template
|
9
10
|
attr_reader :param
|
10
11
|
include ERB::Util
|
12
|
+
include I18n::Base
|
11
13
|
def initialize(template, param = {})
|
12
14
|
@template = template
|
13
15
|
@param = param
|
14
16
|
@template_path = [ Dir.pwd, File.join(Dir.pwd, "templates") ]
|
15
17
|
@template_path << File.join(File.dirname(__FILE__), "..", "..", "templates")
|
18
|
+
I18n.load_path << Dir[File.expand_path("locales") + "/*.yml"]
|
19
|
+
I18n.locale = @param[:locale] if @param[:locale]
|
16
20
|
end
|
17
21
|
def output_to(file, param = {})
|
18
22
|
@param.update(param)
|
@@ -92,9 +96,9 @@ module TTL2HTML
|
|
92
96
|
{
|
93
97
|
path: path,
|
94
98
|
shorten_path: shorten_path,
|
95
|
-
name: data[property]["http://www.w3.org/ns/shacl#name"]
|
99
|
+
name: get_language_literal(data[property]["http://www.w3.org/ns/shacl#name"]),
|
96
100
|
example: data[property]["http://www.w3.org/2004/02/skos/core#example"] ? data[property]["http://www.w3.org/2004/02/skos/core#example"].first : nil,
|
97
|
-
description: data[property]["http://www.w3.org/ns/shacl#description"]
|
101
|
+
description: get_language_literal(data[property]["http://www.w3.org/ns/shacl#description"]),
|
98
102
|
required: data[property]["http://www.w3.org/ns/shacl#minCount"] ? data[property]["http://www.w3.org/ns/shacl#minCount"].first.to_i > 0 : false,
|
99
103
|
repeatable: repeatable,
|
100
104
|
nodeKind: data[property]["http://www.w3.org/ns/shacl#nodeKind"] ? data[property]["http://www.w3.org/ns/shacl#nodeKind"].first : nil,
|
@@ -124,6 +128,13 @@ module TTL2HTML
|
|
124
128
|
end
|
125
129
|
end
|
126
130
|
def get_title(data, default_title = "no title")
|
131
|
+
if @param[:title_property_perclass] and data["http://www.w3.org/1999/02/22-rdf-syntax-ns#type"]
|
132
|
+
@param[:title_property_perclass].each do |klass, property|
|
133
|
+
if data["http://www.w3.org/1999/02/22-rdf-syntax-ns#type"].include?(klass) and data[property]
|
134
|
+
return get_language_literal(data[property])
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
127
138
|
if @param[:title_property] and data[@param[:title_property]]
|
128
139
|
return get_language_literal(data[@param[:title_property]])
|
129
140
|
end
|
@@ -140,7 +151,11 @@ module TTL2HTML
|
|
140
151
|
end
|
141
152
|
def get_language_literal(object)
|
142
153
|
if object.respond_to? :has_key?
|
143
|
-
object.
|
154
|
+
if object.has_key?(I18n.locale)
|
155
|
+
object[I18n.locale]
|
156
|
+
else
|
157
|
+
object.values.first
|
158
|
+
end
|
144
159
|
elsif object.is_a? Array
|
145
160
|
object.first
|
146
161
|
else
|
data/lib/ttl2html/version.rb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
TTL2HTML::VERSION = "1.
|
1
|
+
TTL2HTML::VERSION = "1.1.0"
|
data/lib/ttl2html.rb
CHANGED
@@ -110,6 +110,7 @@ module TTL2HTML
|
|
110
110
|
@graph.query([nil, nil, object]).statements.sort_by do |e|
|
111
111
|
[ e.subject, e.predicate, object ]
|
112
112
|
end.map do |e|
|
113
|
+
next if e.subject.node?
|
113
114
|
result << "<#{e.subject}> <#{e.predicate}> <#{object}>.\n"
|
114
115
|
end
|
115
116
|
result
|
@@ -122,6 +123,22 @@ module TTL2HTML
|
|
122
123
|
end
|
123
124
|
end
|
124
125
|
def output_html_files
|
126
|
+
template = Template.new("")
|
127
|
+
shapes = @graph.query([nil,
|
128
|
+
RDF::URI("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"),
|
129
|
+
RDF::URI("http://www.w3.org/ns/shacl#NodeShape")])
|
130
|
+
labels = shapes2labels(shapes)
|
131
|
+
@config[:labels_with_class] ||= {}
|
132
|
+
labels.each do |klass, props|
|
133
|
+
props.each do |property, label|
|
134
|
+
@config[:labels_with_class][klass] ||= {}
|
135
|
+
if @config[:labels_with_class][klass][property]
|
136
|
+
next
|
137
|
+
else
|
138
|
+
@config[:labels_with_class][klass][property] = template.get_language_literal(label)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
125
142
|
each_data do |uri, v|
|
126
143
|
template = Template.new("default.html.erb", @config)
|
127
144
|
param = @config.dup
|
@@ -130,26 +147,7 @@ module TTL2HTML
|
|
130
147
|
param[:data_inverse] = @data_inverse[uri]
|
131
148
|
param[:data_global] = @data
|
132
149
|
param[:title] = template.get_title(v)
|
133
|
-
file =
|
134
|
-
if @config[:uri_mappings]
|
135
|
-
@config[:uri_mappings].each do |mapping|
|
136
|
-
local_file = uri.sub(@config[:base_uri], "")
|
137
|
-
if mapping["regexp"] =~ local_file
|
138
|
-
file = local_file.sub(mapping["regexp"], mapping["path"])
|
139
|
-
end
|
140
|
-
end
|
141
|
-
end
|
142
|
-
if file.nil?
|
143
|
-
if @data.keys.find{|e| e.start_with?(uri + "/") }
|
144
|
-
file = uri + "/index.html"
|
145
|
-
elsif uri.end_with?("/")
|
146
|
-
file = uri + "index.html"
|
147
|
-
else
|
148
|
-
file = uri + ".html"
|
149
|
-
end
|
150
|
-
end
|
151
|
-
#p uri, param
|
152
|
-
file = file.sub(@config[:base_uri], "")
|
150
|
+
file = uri_mapping_to_path(uri, ".html")
|
153
151
|
if @config[:output_dir]
|
154
152
|
Dir.mkdir @config[:output_dir] if not File.exist? @config[:output_dir]
|
155
153
|
file = File.join(@config[:output_dir], file)
|
@@ -176,9 +174,6 @@ module TTL2HTML
|
|
176
174
|
template.output_to(index_html, param)
|
177
175
|
end
|
178
176
|
end
|
179
|
-
shapes = @graph.query([nil,
|
180
|
-
RDF::URI("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"),
|
181
|
-
RDF::URI("http://www.w3.org/ns/shacl#NodeShape")])
|
182
177
|
if shapes.size > 0
|
183
178
|
about_html = @config[:about_file] || "about.html"
|
184
179
|
about_html = File.join(@config[:output_dir], about_html) if @config[:output_dir]
|
@@ -203,10 +198,26 @@ module TTL2HTML
|
|
203
198
|
template.output_to(about_html, param)
|
204
199
|
end
|
205
200
|
end
|
201
|
+
|
202
|
+
def shapes2labels(shapes)
|
203
|
+
labels = {}
|
204
|
+
shapes.subjects.each do |shape|
|
205
|
+
target_class = @data[shape.to_s]["http://www.w3.org/ns/shacl#targetClass"]&.first
|
206
|
+
if target_class
|
207
|
+
@data[shape.to_s]["http://www.w3.org/ns/shacl#property"].each do |property|
|
208
|
+
path = @data[property]["http://www.w3.org/ns/shacl#path"].first
|
209
|
+
name = @data[property]["http://www.w3.org/ns/shacl#name"]
|
210
|
+
labels[target_class] ||= {}
|
211
|
+
labels[target_class][path] = name
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
labels
|
216
|
+
end
|
217
|
+
|
206
218
|
def output_turtle_files
|
207
219
|
each_data do |uri, v|
|
208
|
-
file = uri
|
209
|
-
file << ".ttl"
|
220
|
+
file = uri_mapping_to_path(uri, ".ttl")
|
210
221
|
if @config[:output_dir]
|
211
222
|
Dir.mkdir @config[:output_dir] if not File.exist? @config[:output_dir]
|
212
223
|
file = File.join(@config[:output_dir], file)
|
@@ -218,21 +229,44 @@ module TTL2HTML
|
|
218
229
|
end
|
219
230
|
end
|
220
231
|
end
|
232
|
+
def uri_mapping_to_path(uri, suffix = ".html")
|
233
|
+
path = nil
|
234
|
+
if @config[:uri_mappings]
|
235
|
+
@config[:uri_mappings].each do |mapping|
|
236
|
+
local_file = uri.sub(@config[:base_uri], "")
|
237
|
+
if mapping["regexp"] =~ local_file
|
238
|
+
path = local_file.sub(mapping["regexp"], mapping["path"])
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|
242
|
+
if path.nil?
|
243
|
+
if suffix == ".html"
|
244
|
+
if @data.keys.find{|e| e.start_with?(uri + "/") }
|
245
|
+
path = uri + "/index"
|
246
|
+
elsif uri.end_with?("/")
|
247
|
+
path = uri + "index"
|
248
|
+
else
|
249
|
+
path = uri
|
250
|
+
end
|
251
|
+
else
|
252
|
+
path = uri
|
253
|
+
end
|
254
|
+
end
|
255
|
+
path = path.sub(@config[:base_uri], "")
|
256
|
+
path << suffix
|
257
|
+
#p [uri, path]
|
258
|
+
path
|
259
|
+
end
|
221
260
|
def cleanup
|
222
261
|
@data.select do |uri, v|
|
223
262
|
uri.start_with? @config[:base_uri]
|
224
263
|
end.sort_by do |uri, v|
|
225
264
|
-(uri.size)
|
226
265
|
end.each do |uri, v|
|
227
|
-
|
228
|
-
file = uri + "/index.html"
|
229
|
-
else
|
230
|
-
file = uri + ".html"
|
231
|
-
end
|
232
|
-
html_file = file.sub(@config[:base_uri], "")
|
266
|
+
html_file = uri_mapping_to_path(uri, ".html")
|
233
267
|
html_file = File.join(@config[:output_dir], html_file) if @config[:output_dir]
|
234
268
|
File.unlink html_file
|
235
|
-
ttl_file = uri
|
269
|
+
ttl_file = uri_mapping_to_path(uri, ".ttl")
|
236
270
|
ttl_file = File.join(@config[:output_dir], ttl_file) if @config[:output_dir]
|
237
271
|
File.unlink ttl_file
|
238
272
|
dir = uri.sub(@config[:base_uri], "")
|
@@ -259,4 +293,4 @@ module TTL2HTML
|
|
259
293
|
file
|
260
294
|
end
|
261
295
|
end
|
262
|
-
end
|
296
|
+
end
|
data/locales/en.yml
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
en:
|
2
|
+
about:
|
3
|
+
title: "About %{title}"
|
4
|
+
The properties for the textbook resources are as follows:
|
5
|
+
shape-note: "The properties for the %{resource} resources are as follows:"
|
6
|
+
default:
|
7
|
+
details: Details
|
8
|
+
inverse_data: Referred resources
|
9
|
+
index:
|
10
|
+
list: "List of %{resource}"
|
11
|
+
layout:
|
12
|
+
rdf-data: RDF data
|
13
|
+
shape-table:
|
14
|
+
header:
|
15
|
+
property-name: "Property name"
|
16
|
+
description: "Description"
|
17
|
+
example: "Example of the property value(s)"
|
18
|
+
required: "Required?"
|
19
|
+
repeatable: "Repeatable?"
|
20
|
+
note: "Notes"
|
21
|
+
required: "Required"
|
22
|
+
repeatable: "Repeatable"
|
23
|
+
optional: "Optional"
|
24
|
+
non-repeatable: "Non repeatable"
|
25
|
+
blank-node-structure: "The structural contents of a blank node are as follows:"
|
26
|
+
blank-node-or-structure: "The structural contents of a blank node are either of the followings:"
|
data/locales/ja.yml
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
ja:
|
2
|
+
about:
|
3
|
+
title: "%{title}について"
|
4
|
+
shape-note: "%{resource}リソースが持つプロパティを下表に示します"
|
5
|
+
default:
|
6
|
+
details: 詳細情報
|
7
|
+
inverse_data: 被参照情報
|
8
|
+
index:
|
9
|
+
list: "%{resource} 一覧"
|
10
|
+
layout:
|
11
|
+
rdf-data: RDFデータ
|
12
|
+
shape-table:
|
13
|
+
header:
|
14
|
+
property-name: プロパティ名
|
15
|
+
description: 説明
|
16
|
+
example: プロパティ値の例
|
17
|
+
required: 必須・省略の別
|
18
|
+
repeatable: 繰り返しの有無
|
19
|
+
note: 備考
|
20
|
+
required: 必須
|
21
|
+
repeatable: 繰り返し有り
|
22
|
+
optional: 省略可能
|
23
|
+
non-repeatable: 繰り返し無し
|
24
|
+
blank-node-structure: ブランクノードの内容は以下の内容からなる構造を持ちます。
|
25
|
+
blank-node-or-structure: ブランクノードの内容は以下のいずれかの内容からなる構造を持ちます。
|
data/templates/about.html.erb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
<div class="jumbotron">
|
2
2
|
<div class="container">
|
3
|
-
<h1><%=h param[:site_title]
|
3
|
+
<h1><%=h t("about.title", title: param[:site_title]) %></h1>
|
4
4
|
</div>
|
5
5
|
</div>
|
6
6
|
<div class="container">
|
@@ -8,7 +8,7 @@
|
|
8
8
|
<div class="col-md-12">
|
9
9
|
<ol class="breadcrumb">
|
10
10
|
<li><a href="./"><span class="glyphicon glyphicon-home" aria-hidden="true"></span> Home</a></li>
|
11
|
-
<li class="active"><%=h param[:site_title]
|
11
|
+
<li class="active"><%=h t("about.title", title: param[:site_title]) %></li>
|
12
12
|
</ol>
|
13
13
|
</div>
|
14
14
|
</div>
|
@@ -16,8 +16,9 @@
|
|
16
16
|
<div class="row">
|
17
17
|
<div class="col-md-10">
|
18
18
|
<%- param[:content].keys.sort.each do |shape| -%>
|
19
|
-
<h3><%=h param[:content][shape][:label]
|
20
|
-
<p><%=
|
19
|
+
<h3><%=h param[:content][shape][:label] %></h3>
|
20
|
+
<p><%= param[:content][shape][:comment] %></p>
|
21
|
+
<p><%=h t("about.shape-note", resource: param[:content][shape][:label]) %></p>
|
21
22
|
<%= param[:content][shape][:html] -%>
|
22
23
|
<%- end -%>
|
23
24
|
</div>
|
data/templates/default.html.erb
CHANGED
@@ -7,14 +7,14 @@
|
|
7
7
|
<div class="container">
|
8
8
|
<div class="row">
|
9
9
|
<div class="col-md-12">
|
10
|
-
<h2
|
10
|
+
<h2><%=h t("default.details") %></h2>
|
11
11
|
<%= format_triples(param[:data]) %>
|
12
12
|
</div>
|
13
13
|
</div>
|
14
14
|
<% if param[:data_inverse] %>
|
15
15
|
<div class="row inverse">
|
16
16
|
<div class="col-md-12">
|
17
|
-
<h2
|
17
|
+
<h2><%=h t("default.inverse_data") %></h2>
|
18
18
|
<%= format_triples(param[:data_inverse]) %>
|
19
19
|
</div>
|
20
20
|
</div>
|
data/templates/index.html.erb
CHANGED
@@ -7,7 +7,7 @@
|
|
7
7
|
<div class="container">
|
8
8
|
<div class="row">
|
9
9
|
<div class="col-md-12">
|
10
|
-
<h2><%=h param[:class_label]
|
10
|
+
<h2><%=h t("index.list", resource: param[:class_label]) %></h2>
|
11
11
|
<ul>
|
12
12
|
<% param[:index_data].each do |e| %>
|
13
13
|
<li><%= format_object(e, param[:data_global]) %></li>
|
data/templates/layout.html.erb
CHANGED
@@ -22,7 +22,7 @@
|
|
22
22
|
<hr>
|
23
23
|
<footer>
|
24
24
|
<%- if param[:uri] -%>
|
25
|
-
<p class="pull-right"><a href="<%=h param[:uri] %>.ttl"><img src="https://www.w3.org/RDF/icons/rdf_flyer.24" alt="
|
25
|
+
<p class="pull-right"><a href="<%=h param[:uri] %>.ttl"><img src="https://www.w3.org/RDF/icons/rdf_flyer.24" alt="<%=h t("layout.rdf_data") %>"></a></p>
|
26
26
|
<%- end -%>
|
27
27
|
</footer>
|
28
28
|
|
@@ -1,6 +1,11 @@
|
|
1
1
|
<table class="table table-condensed">
|
2
2
|
<tr>
|
3
|
-
<th
|
3
|
+
<th><%=h t('shape-table.header.property-name') %></th>
|
4
|
+
<th><%=h t('shape-table.header.description') %></th>
|
5
|
+
<th><%=h t('shape-table.header.example') %></th>
|
6
|
+
<th><%=h t('shape-table.header.required') %><br>
|
7
|
+
<%=h t('shape-table.header.repeatable') %></th>
|
8
|
+
<th><%=h t('shape-table.header.note') %></th>
|
4
9
|
</tr>
|
5
10
|
<tbody>
|
6
11
|
<%- param[:properties].each do |property| -%>
|
@@ -10,7 +15,7 @@
|
|
10
15
|
<%- else -%>
|
11
16
|
<td><code><%=h property[:shorten_path] %></code></td>
|
12
17
|
<%- end -%>
|
13
|
-
<td><%= property[:
|
18
|
+
<td><%= property[:name] %></td>
|
14
19
|
<%- if property[:nodeKind] == "http://www.w3.org/ns/shacl#IRI" -%>
|
15
20
|
<td class="url"><%= property[:example] %></td>
|
16
21
|
<%- else -%>
|
@@ -19,31 +24,31 @@
|
|
19
24
|
<td>
|
20
25
|
<div>
|
21
26
|
<%- if property[:required] -%>
|
22
|
-
<strong
|
27
|
+
<strong><%=h t('shape-table.required') %></strong>
|
23
28
|
<%- else -%>
|
24
|
-
|
29
|
+
<%=h t('shape-table.optional') %>
|
25
30
|
<%- end -%>
|
26
31
|
</div>
|
27
32
|
<div>
|
28
33
|
<%- if property[:repeatable] -%>
|
29
|
-
|
34
|
+
<%=h t('shape-table.repeatable') %>
|
30
35
|
<%- else -%>
|
31
|
-
|
36
|
+
<%=h t('shape-table.non-repeatable') %>
|
32
37
|
<%- end -%>
|
33
38
|
</div>
|
34
39
|
</td>
|
35
|
-
<td><%= property[:
|
40
|
+
<td><%= property[:description] %></td>
|
36
41
|
</tr>
|
37
42
|
<%- if property[:nodeKind] == "http://www.w3.org/ns/shacl#BlankNode" -%>
|
38
43
|
<tr>
|
39
44
|
<td colspan="4">
|
40
45
|
<%- if property[:node_mode] == :or -%>
|
41
|
-
|
46
|
+
<%=h t("shape-table.blank-node-or-structure") %>
|
42
47
|
<%- property[:nodes].each do |e| -%>
|
43
48
|
<div class="blank_node"><%= e.sub(/class="table"/, 'class="table table-condensed"') %></div>
|
44
49
|
<%- end -%>
|
45
50
|
<%- else -%>
|
46
|
-
|
51
|
+
<%=h t("shape-table.blank-node-structure") %>
|
47
52
|
<div class="blank_node"><%= property[:nodes].sub(/class="table"/, 'class="table table-condensed"') %></div>
|
48
53
|
<%- end -%>
|
49
54
|
</td>
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ttl2html
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Masao Takaku
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-11-
|
11
|
+
date: 2021-11-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: i18n
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: ruby-progressbar
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -124,6 +138,8 @@ files:
|
|
124
138
|
- lib/ttl2html/template.rb
|
125
139
|
- lib/ttl2html/version.rb
|
126
140
|
- lib/xlsx2shape.rb
|
141
|
+
- locales/en.yml
|
142
|
+
- locales/ja.yml
|
127
143
|
- templates/about.html.erb
|
128
144
|
- templates/default.html.erb
|
129
145
|
- templates/index.html.erb
|