別サイト
に書いていたのだけどサ終してしまったので移行した記事その2
2019/03/06のもの
Julia
Juiliaという言語があるのを最近知ったのでサンプルに従って書いてみる
Genie
Julia向けにGenieというwebフレームワークがあったのでそれを使ってDB接続するところまでをやっていく
環境構築
https://julialang.org/downloads/
からJuliaをダウンロード、インストール
$ julia --version
julia version 1.1.0
自分が入れた段階では1.1.0だった
Genieインストール、アプリ作成
$ julia
julia> using Pkg
julia> Pkg.clone("https://github.com/essenciary/Genie.jl")
julia> using Genie
julia> Genie.REPL.new_app("app")
julia> ] ## ]をいれるとパッケージモードになる
pkg> add https://github.com/essenciary/SearchLight.jl ##DB接続用にSearchLightをいれる
これで基本は完了。
./bin/serverなどで起動すると
http://localhost:8000/
でトップページが表示できました
実装
https://github.com/essenciary/Genie.jl
Julia web frameworkのGenieでTODOリストを作る
公式ドキュメントや他の方がやられていたのを参考に実装していく
app/resources配下にコントローラやビューを作成する作法らしい
今回作成したファイル
- app/resources/tests/Tests.jl(生成は自動)
- app/resources/tests/TestsController.jl
- app/resources/tests/TestsValidator.jl(生成は自動)
- app/resources/tests/views/new.jl.html
- app/resources/tests/views/tests.jl.html
修正したファイル
- config/database.yml
- config/routes.jl
ソースは後述
database設定
config/initializers/searchlight.jlのコメントを外す
using SearchLight, SearchLight.QueryBuilder
Core.eval(SearchLight, :(config.db_config_settings = SearchLight.Configuration.load_db_connection()))
SearchLight.Loggers.empty_log_queue()
if SearchLight.config.db_config_settings["adapter"] != nothing
SearchLight.Database.setup_adapter()
SearchLight.Database.connect()
SearchLight.load_resources()
end
database.ymlに設定追加
env: dev
dev:
adapter: SQLite
database: db/tests.sqlite
host:
username:
password:
port:
config:
DB接続、モデル作成
julia> SearchLight.Configuration.load_db_connection()
julia> SearchLight.Configuration.load_db_connection() |> SearchLight.Database.connect!
julia> SearchLight.db_init()
julia> SearchLight.Generator.new_resource("Test")
作成されたマイグレーションファイルに適当にカラムを設定
module CreateTableTests
import SearchLight.Migrations: create_table, column, primary_key, add_index, drop_table
function up()
create_table(:tests) do
[
primary_key()
column(:content, :string)
column(:done, :bool)
]
end
add_index(:tests, :content)
end
function down()
drop_table(:tests)
end
end
テーブル作成
julia> SearchLight.Migration.last_up()
モデルファイルもマイグレーションファイルと同様にカラム設定をいれる
seedファンクションにて初期データ用の処理も追加
mutable struct Test <: AbstractModel
### INTERNALS
_table_name::String
_id::String
_serializable::Vector{Symbol}
### FIELDS
id::DbId
content::String
done::Bool
### constructor
Test(;
### FIELDS
id = DbId(),
content = "",
done = false
) = new("tests", "id", Symbol[], ### INTERNALS
id, content, done ### FIELDS
)
end
function seed()
SampleTests = [
("ほげ", true),
("ほげほげ", false),
("げほげほ", false)
]
for test in SampleTests
Test(content = test[1], done = test[2]) |> SearchLight.save!
end
end
初期データ投入
julia> ]
pkg> activate .
pkg> # Ctrl-C
julia> using Genie
julia> Genie.REPL.load_app()
julia> using Tests
julia> Tests.seed()
コントローラ、ビュー、ルートの修正
コントローラ作成->ビュー作成->ルート作成
みたいな感じで作成していきました
動かすたびにエラーでたり試行錯誤が多かったけど最終的に
- DBからselectしたものを表示
- DBにデータをinsert
- DBのデータをupdate
といったところができた
コントローラ
module TestsController
using Genie.Renderer
using Genie.Router
using SearchLight
using Tests
# トップ
function index()
html!(:tests, :tests, tests = SearchLight.all(Tests.Test))
end
# 新規作成
function new()
html!(:tests, :new)
end
# 新規登録
function create()
# 作成
Tests.Test(content = @params(:test_content), done = false) |> save
redirect_to(:get_tests)
end
# 更新
function update()
# 既存データのselect
test = SearchLight.find_one_by!!(Tests.Test, :id, @params(:test_id))
# リクエストパラメータ(なんかstringで受けるのでそのままbool判定できなかった)
in_done = ifelse(@params(:test_done) == "true", true, false)
# 更新処理
Tests.Test(id = @params(:test_id), content = test.content, done = in_done) |> save!
# トップにリダイレクト
redirect_to(:get_tests)
end
end
ビュー
<form action="$(Genie.Router.link_to(:create_test))">
内容:<input type="text" name="test_content" /></br>
<input type="submit" value="作成" />
</form>
velocityみたいな感じで書ける
<a href="$(Genie.Router.link_to(:new_test))">作成</a>
<ul>
<%
if length(@vars(:tests)) == 0
"データがありません。"
else
@foreach(@vars(:tests)) do test
if test.done
"<li><s>$(test.content)</s><a href=" * Genie.Router.link_to(:update_test) * "?test_id=" * string(get(test.id)) * "&test_done=false" * ">  falseに戻す</a></li>"
else
"<li>$(test.content)<a href=" * Genie.Router.link_to(:update_test) * "?test_id=" * string(get(test.id)) * "&test_done=true" * ">  trueにする</a></li>"
end
end
end
%>
</ul>
ルート
using Genie.Router
using TestsController
route("/") do
serve_static_file("/welcome.html")
end
# トップページ
route("/tests", TestsController.index, named = :get_tests)
# 新規登録画面
route("/tests/new", TestsController.new, named = :new_test)
# 登録処理
route("/tests/create", TestsController.create, method = GET, named = :create_test)
# 更新処理
route("/tests/update", TestsController.update, method = GET, named = :update_test)
感想
コードは見やすく短くかけていい感じだと思う
ただまだよくわからないところも多く(サンプルの通りでも怪しいところがあったり)
エラーが起きたときにどう対処すればいいかがわからないことが多かった
同じソースでも起動し直したら動いたりするのも何故なのかもよくわからない
POSTメソッドでもなぜかエラーが出たり。。。