1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

JuliaのGenieを使ってDB操作をするところまで

Posted at

別サイト

に書いていたのだけどサ終してしまったので移行した記事その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のコメントを外す

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に設定追加

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")

作成されたマイグレーションファイルに適当にカラムを設定

db/migrations/xxxxx_create_table_tests.jl
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ファンクションにて初期データ用の処理も追加

app/resources/tests/Tests.jl
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

といったところができた

コントローラ

app/resources/tests/TestsController.jl
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

ビュー

app/resources/tests/views/new.jl.html
<form action="$(Genie.Router.link_to(:create_test))">
  内容:<input type="text" name="test_content" /></br>
  <input type="submit" value="作成" />
</form>

velocityみたいな感じで書ける

app/resources/tests/views/tests.jl.html
<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" * ">&nbsp falseに戻す</a></li>"
      else
      "<li>$(test.content)<a href=" * Genie.Router.link_to(:update_test) * "?test_id=" * string(get(test.id)) * "&test_done=true" * ">&nbsp trueにする</a></li>"
      end
    end
  end
 %>
</ul>

ルート

config/routes.jl
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メソッドでもなぜかエラーが出たり。。。

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?