guide-kemal-clone-of-rails-guide
Suffragist
this repo takes the documentation from the Rails-Girls guides to implement it in crystal-lang
Guide
Project initialize
crystal init app suffragist
cd suffragist
Install Kemal
Add to shard.yml
dependencies:
kemal:
github: kemalcr/kemal
Create your first Kemal app
In the file src/suffragist.cr
require "kemal"
get "/" do
"Hello, voter!"
end
Kemal.run
Run your app
in the project directory, run crystal src/suffragist.cr
. Wait for the message [development] Kemal is ready to lead at http://0.0.0.0:3000
and visit localhost:3000. You should see a "Hello, voter!" page. Hit Ctrl+C in the terminal to shut down the server.
Add the index view
To keep everything in order let's make a directory for our views (and name it views
).
Put this code into an index.ecr
file in the views
directory:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Suffragist</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<p>What's for dinner?</p>
<form action="cast" method="post">
<div class="mb-3">
<%- Choices.each do |id, text| -%>
<div class="form-check">
<input type="radio" name="vote" value="<%= id %>" class="form-check-input" id="vote_<%= id %>" />
<label class="form-check-label" for="vote_<%= id %>">
<%= text %>
</label>
</div>
<%- end -%>
</div>
<button type="submit" class="btn btn-primary">Cast this vote!</button>
</form>
</div>
</body>
</html>
And into suffragist.cr
:
require "kemal"
require "ecr"
Choices = {
"HAM" => "Hamburger",
"PIZ" => "Pizza",
"CUR" => "Curry",
"NOO" => "Noodles",
}
get "/" do
render "src/views/index.ecr
end
Kemal.run
Run crystal src/suffragist.cr
, check your results and shut down the server with Ctrl+C.
Templates
Adjust the index.ecr
file in the views
directory and add the <h1>…</h1>
line:
<body>
<div class="container">
<h1><%= @title %></h1>
<p>What's for dinner?</p>
Change the get
action:
get "/" do
title = "Welcome to the Suffragist!"
render "src/views/index.ecr"
end
Add the ability to POST results
Put this into src/suffragist.cr
:
post "/cast" do |env|
title = "Thanks for casting your vote!"
vote = env.params.body["vote"].as(UInt32)
render "src/views/cast.ecr"
end
Create a new file in the views
directory, cast.ecr
, and put there some HTML with embedded Crystal code:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Suffragist</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<h1><%= title %></h1>
<p>You cast: <%= Choices[vote] %></p>
<p><a href="/results">See the results!</a></p>
</div>
</body>
</html>
Factor out a common layout
Create a layout.ecr
file in the views
directory. Put the following in there:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Suffragist</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<h1><%= title %></h1>
<%= content %>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
in src/suffragist.cr
, add a macro to call this layout
macro my_renderer(filename)
render "src/views/#{ {{filename}} }.ecr", "src/views/layout.ecr"
end
and now, you can use your new renderer in all actions :
require "kemal"
require "ecr"
Choices = {
"HAM" => "Hamburger",
"PIZ" => "Pizza",
"CUR" => "Curry",
"NOO" => "Noodles",
}
macro my_renderer(filename)
render "src/views/#{ {{filename}} }.ecr", "src/views/layout.ecr"
end
get "/" do
title = "Welcome to the Suffragist!"
my_renderer "index"
end
post "/cast" do |env|
title = "Thanks for casting your vote!"
vote = env.params.body["vote"].as(String)
my_renderer "cast"
end
Kemal.run
Remove the above part from the other two templates (index.ecr
and cast.ecr
in the views
directory).
Add the results route and the results view
Paste the following code into src/suffragist.cr
:
get "/results" do
title = "Results"
votes = { "HAM" => 7, "PIZ" => 5, "CUR" => 3 }
my_renderer "results"
end
Create a new file in the views
directory, called results.ecr
.
<table class="table table-hover table-striped">
<%- Choices.each do |id, text| -%>
<tr>
<th><%= text %></th>
<%- if votes.has_key? id -%>
<td><%= votes[id] %></td>
<td><%= "#" * (votes[id]) %></td>
<%- else -%>
<td>0</td>
<td></td>
<%- end -%>
</tr>
<% end %>
</table>
<p><a href="/">Cast more votes!</a></p>
Run src/suffragist.cr
, check your results and shut down the server with Ctrl+C.
Contributors
- Jade D. Kharats - creator and maintainer
guide-kemal-clone-of-rails-guide
- 0
- 0
- 0
- 0
- 1
- about 1 year ago
- September 7, 2023
MIT License
Fri, 22 Nov 2024 09:41:49 GMT