ページ

2015年11月29日日曜日

Gradleをちゃんと使ってみる 1

AndroidStudioでお世話になっているGradleですが
一からちゃんと使った事がないので、ちゃんと使ってみます
そもそも・・・
Gradleとは
Gradleは、Groovyで書かれたビルドシステム
※Groovyは、Java VM上で動作する動的なスクリプト言語
とあります。

   インストール


Gradleのインストール方法が以下の2パターンある模様
  • 公式サイトからバイナリをダウンロードしてインストール
  • GVMを使用する
今回はGVM(Groovy enVironment Manager)を使ってみる
rubyのRVMみたいなもんで、複数バージョンのGradleを管理できる
以下コマンドでインストール
$ curl -s get.gvmtool.net | bash
現時点ではSDKMANというのに変更されているらしく、上のコマンドを実行すると
SDKMANがインストールされるが、gvmコマンドはsdkコマンドのエイリアスとして設定されます
$ which gvm
gvm: aliased to sdk
インストール可能なGradleの一覧を表示
$ gvm list gradle
とりあえず現時点で最新の2.9をインストール
$ gvm install gradle 2.9
動作確認
$ gradle -version

   とりあえず、Hello World


おきまりのHello WorldをGradleで書いてみたいと思います
build.gradle
task helloworld << {
  println "Hello World!"
}
gradle helloworldで実行してみる
:helloworld
Hello World!

BUILD SUCCESSFUL
上のように成功になれば準備はOK

   Javaクラスのコンパイル&実行


単純なJavaのクラスを作成
package sample;

public class Sample {

  public static void main(String[] args) {
    System.out.println("print from Sample class");
  }
}
build.gradleを以下に編集
apply plugin: "java"

repositories {
  mavenCentral()
}
この時のフォルダ構成は以下
.
├── build.gradle
└── src
    └── main
        └── java
            └── sample
                └── Sample.java

早速コンパイルしてみる
$ gradle compileJava
:compileJava

BUILD SUCCESSFUL

Total time: 5.966 secs
ビルドに成功するとbuildディレクトリが作成され、
build/classes/main/sampleにコンパイルされたSample.classが作成されている
.
├── build
│   ├── classes
│   │   └── main
│   │       └── sample
│   │           └── Sample.class ★
│   ├── dependency-cache
│   └── tmp
│       └── compileJava
├── build.gradle
└── src
    └── main
        └── java
            └── sample
                └── Sample.java
実行してみる
$ java -cp build/classes/main sample.Sample
print from Sample class
上のように表示されれば成功
作成されたbuildを消すには
$ gradle clean
で消えます

2015年11月25日水曜日

道の駅を巡ってみる 6 - 佐賀/長崎県境 -


今回は名前が特徴的な「桃山天下市」(ももやまてんかいち)と
「鷹ら島」(たからじま)に行ってきました。

1. 道の駅「桃山天下市」



呼子から少し行った所にあります。呼子だけあって道の駅内にはイカ焼きやイカ一夜干しなどイカづくしでした。






とりあえずイカは食べとかないと・・と思ってイカ焼きを買ってみました。
残念ながら焼きたてでは無かったんですが、冷めてても美味しかったです。

公式ページ


2. 道の駅「鷹ら島」

名前が良い響きな鷹ら島ですが、なんといっても道の駅に行く時に通る
鷹島肥前大橋が素晴らしかったです。



ちょっと分かりづらいですね・・・奥に写っているのが大橋です。
ちゃんとした大橋の写真は↓の公式ページを見てみてください^^;。




道の駅内の食事処には魚島来飯(おとこめし)なるものが!!
注文してみたら↑のようなすごく贅沢な海鮮丼でした。
鯛やハマチ?やイカなど具沢山、しかも付け合わせも美味しい。

↓TAKARAJIMA FOODで売っていたマグロバーガーも気になる・・・



公式ページ

2015年11月21日土曜日

Elixir/Phoenixで遊ぶ 15 - ElixirでGitHubリポジトリ同期ツールの作成 その4-


今回でリポジトリと同期する処理を実装し、とりあえず完成させる

   モジュールの分離


前回までリポジトリ一覧の処理をSynchubモジュール内に書いていましたが、 一覧表示の所を別モジュールに切り出したいと思います。

新規にlib/synchub/listrepos.exを以下内容で作成
defmodule Synchub.Listrepos do

@moduledoc """
The module of list github repos.
"""

@doc "put repos name."
def put_repo_name([info|tail]) do
  IO.puts info["name"]
  put_repo_name(tail)
end

def put_repo_name(info) do
end

end

lib/mix/tasks/list.github.repos.exを以下に編集
※少し名前を変更してます。(長かったので・・・)
defmodule Mix.Tasks.List.Github do
  use Mix.Task

  @shortdoc "Show github repos list"

  def run(args) do
    url = "users/" <> Application.get_env(:synchub, :userid) <> "/repos"
    Synchub.start
    repos = Synchub.get(url)
    Synchub.Listrepos.put_repo_name(repos)
  end
end
Synchub.get内で一覧表示させていた部分をSynchub.Listrepos.put_repo_name(repos)で実行しています。
$ mix list.githubで一覧表示されればOK


   リポジトリ同期モジュールの作成


上でモジュールを分離させたのは、リポジトリ同期モジュールの為になります。
Synchub.get(url)で取得したリポジトリ一覧に対して処理を行うモジュールを作成します。

lib/synchub/syncrepos.exを以下内容で作成
defmodule Synchub.Syncrepos do

@moduledoc """
The module of sync github repos.
"""

@rootdir "syncrepos"

@doc "check install git client"
def install_git?() do
  ret = System.find_executable("git") # [1]
  ret != nil
end

@doc "sync github repos."
def sync([info|tail]) do
  # create sync repos dir
  unless File.exists?(@rootdir) do
    IO.puts "create dir ==> " <> @rootdir
    File.mkdir(@rootdir)
  end
  File.cd(@rootdir)

  if File.exists?(info["name"]) do # [2]
    # git command
    File.cd(info["name"])
    IO.puts "exists repo dir " <> info["name"]
    case System.cmd("git", Application.get_env(:synchub, :exists_cmd)) do # [3]
      {err, code} -> IO.puts(err)
    end
    File.cd("../")
  else
    # clone repo
    clone_url = info["clone_url"]
    if clone_url do
      IO.puts "clone " <> clone_url
      case System.cmd("git", ["clone", clone_url]) do # [4]
        {err, code} -> IO.puts(err)
      end
    end
  end
  File.cd("../")
  sync(tail)
end

def sync([]), do: nil

end
やってる事のポイントとしては、
  • [1] gitインストールの確認
  • [2] 既にクローン済みか判定
  • [3] config.exsで設定されたgitコマンドを実行
  • [4] gitクローンを実行
になります。

   リポジトリ同期用のタスクを作成


一覧表示の時と同じようにカスタムのタスクを作成したいと思います。

最終的に
$ mix sync.github
としたら同期してくれるようにしたいと思います。

lib/mix/tasks/sync.github.exを以下内容で作成
defmodule Mix.Tasks.Sync.Github do
  use Mix.Task

  @shortdoc "Sync github repos"

  alias Synchub.Syncrepos

  def run(args) do
    IO.puts "start sync github repos..."
    unless Syncrepos.install_git? do # [1]
      IO.puts "not found git. please install"
    else
      url = "users/" <> Application.get_env(:synchub, :userid) <> "/repos"
      Synchub.start
      repos = Synchub.get(url)
      Syncrepos.sync(repos.body)
      IO.puts "success sync github repos"
    end
  end
end
[1] でgitがインストールされているか確認し、インストールされている場合のみ
同期を行うようにしています。

ここまで作成したらmix compileでコンパイルし、mix sync.githubで同期できれば成功です。

   まとめ


荒削りですが、とりあえず作成完了ということにします(笑)

プロジェクト自体はここに上げています。気ままに更新していこうかなと思ってるので良かったら使ってみてください。

2015年11月19日木曜日

Elixir/Phoenixで遊ぶ 14 - ElixirでGitHubリポジトリ同期ツールの作成 その3-

今回はテストの作成 & TravisCIで自動テストを行ってみます

   テストの作成


test/synchub_test.exsを修正していきます
プロジェクト作成したばかりは以下のようになっています。
defmodule SynchubTest do
  use ExUnit.Case

  test "the truth" do
    assert 1 + 1 == 2
  end
end
試しに実行してみます
$ mix test
==> poison
Compiled lib/poison.ex
Compiled lib/poison/decoder.ex
Compiled lib/poison/parser.ex
Compiled lib/poison/encoder.ex
Generated poison app
==> httpotion
Compiled lib/httpotion.ex
Generated httpotion app
==> ibrowse (compile)
==> synchub
Compiled lib/synchub.ex
Generated synchub app
.

Finished in 0.06 seconds (0.06s on load, 0.00s on tests)
1 tests, 0 failures

Randomized with seed 765702
依存関係が解決されテストが実行され成功しているのが分かります。
次は実際にsynchub.exのテストを書きたいと思います。
とりあえず今回はテストとして
  1. リクエストのヘッダのUser-Agentにconfig.exsusernameが設定されていること
  2. レスポンスが正常に帰ってくること
を確認するテストを書いてみます。
defmodule SynchubTest do
  use ExUnit.Case

  # 1. リクエストヘッダの確認
  test "user-agent" do
    headers = Synchub.process_request_headers(%{})
    agent = Map.fetch!(headers, :"User-Agent")
    assert agent == Application.get_env(:synchub, :username)
  end

  # 2. レスポンスの確認
  test "list.github.repos" do
    url = "users/" <> Application.get_env(:synchub, :userid) <> "/repos"
    Synchub.start
    assert_response Synchub.get(url)
  end

  defp assert_response(response) do
    assert HTTPotion.Response.success?(response, :extra)
  end

end
"user-agent"テストではprocess_request_headers内で設定された User-AgentがApplication.get_env(:synchub, :username)と等しいこと
を確認しています。
"list.github.repos"テストでは実際にGithubAPIを使ってリクエストを送り
レスポンスが正常に帰ってくるか確認しています。
defp assert_response(response) do
  assert HTTPotion.Response.success?(response, :extra)
end
ではHTTPotionのレスポンスチェック関数を使ってます
実際にテストを実行してみます。
$ mix test
.https://api.github.com/users/Slowhand0309/repos
.

Finished in 2.4 seconds (0.1s on load, 2.2s on tests)
2 tests, 0 failures

Randomized with seed 978629
0 failuresになればテスト成功です。

   TravisCIで自動テスト


TravisCIでプロジェクトを登録し、プロジェクト直下に
.travis.ymlを作成します。
  • .travis.yml
language: elixir
elixir:
  - 1.0.5
otp_release:
  - 18.0
sudo: false
↑環境に合わせて修正
これでGithubにpushして自動でテストが行われれば成功です

2015年11月14日土曜日

Elixir/Phoenixで遊ぶ 13 - ElixirでGitHubリポジトリ同期ツールの作成 その2-


前回に続いて同期ツールの作成

   config/config.exsの使用


前回GitHubApiを使ってリポジトリの一覧を取得した際にユーザー名や
リクエストURLをソースコード上に直で書いていましたが、今回はconfig/config.exs
を読み込んで使ってみたいと思います。
まずはconfig/config.exsに以下内容を追加
config :synchub,
  apiurl: "https://api.github.com/",
  userid: "{ユーザーID}",
  username: "{ユーザー名}"
※{ユーザーID}/{ユーザー名}は使用するアカウントのユーザー名、ユーザーIDを設定して下さい
lib/synchub.exを修正
defmodule Synchub do
  @moduledoc """
  The module of sync github repos.
  """
  use HTTPotion.Base

  @apiurl Application.get_env(:synchub, :apiurl) # (1)ここ!

  @doc "handle create url."
  def process_url(url) do
    @apiurl <> url
  end

  @doc "handle create request header."
  def process_request_headers(headers) do
    Dict.put headers, :"User-Agent", Application.get_env(:synchub, :username) # (2)ここ!
  end

  @doc "handle response of html body."
  def process_response_body(body) do
    body |> Poison.decode! |> put_repo_name
  end

  @doc "put repos name."
  def put_repo_name([info|tail]) do
    IO.puts info["name"]
    put_repo_name(tail)
  end

  def put_repo_name([]), do: nil
end
config/config.exsで設定した値を読み込む時はApplication.get_envを使う
↑では(1)と(2)でそれぞれapiurlusernameを読み込んでいる

   カスタムタスクの作成


前回は以下のように実行していましたが、
$ iex -S mix
iex(1)> Synchub.get("users/{ユーザーID}/repos")
一回一回iexを起動するのも面倒くさいので、mixのタスクを作成してみたいと思います。 作成したいタスクとしては・・・
$ mix list.github.repos
とすると、config/config.exsで設定されたユーザーのリポジトリ一覧を取得できたら良さげ
  • タスクファイルの作成
lib/mix/tasks/list.github.repos.exを作成し、以下内容に編集する
defmodule Mix.Tasks.List.Github.Repos do
  use Mix.Task

  @shortdoc "Show github repos list" # (1)

  def run(args) do
    url = "users/" <> Application.get_env(:synchub, :userid) <> "/repos" # (2)
    Synchub.start
    Synchub.get(url)
  end
end
モジュール名は作成したファイル名と対応する様な名前で作成
(1) @shortdocを書く事でmix helpの一覧に説明が表示される
(2) ここでconfig/config.exsからuseridを読み込みurlを作成
  • コンパイル
$ mix compile
mix helpで一覧に表示されているか確認してみる
$ mix help
・・・
mix list.github.repos # Show github repos list
・・・
↑の様に表示されればOK
  • 実行
$ mix list.github.repos
前回と同じ様にリポジトリの一覧が表示されればOKです