2014年4月26日土曜日

Play FrameworkのSlickでevolutionを使ったテーブル管理をしてみた

今回はPlay FrameworkにSlickを入れて、evolutionを使ったテーブル管理をやってみました。

バージョン
Play Framework 2.2.2
slick 2.0.1
play-slick 0.6.0.1

build.sbtに下記を追加する。
  "com.typesafe.slick" %% "slick" % "2.0.1",
  "org.slf4j" % "slf4j-nop" % "1.7.6",
  "com.typesafe.play" % "play-slick_2.10" % "0.6.0.1"

application.confでevolutionを有効にし、slickでテーブルを作る対象をmodels.*で指定する。
evolutionplugin=enabled
slick.default="models.*"

上で指定したパッケージ配下にmodelを作成
package models
 
import play.api.db.slick.Config.driver.simple._
import java.sql.Date
import models.dao.DAO
 
case class Twitter(id: Int, word: String, ins_date: Date, upd_date: Date, ng_flg : Boolean)
  
class Twitters(tag: Tag) extends Table[Twitter](tag,"twitter"){
 
  def id = column[Int]("id",O.PrimaryKey,O.AutoInc)
  def word = column[String]("word",O.NotNull)
  def ins_date = column[Date]("ins_date",O.NotNull)
  def * = (id,word,ins_date) <> (Twitter.tupled,Twitter.unapply)
}
 
object Twitters extends DAO{
    
  def insert(word:String,ins_date:Date)(implicit s: Session) = {
    Twitters map{
      r => (r.word,r.ins_date)
    } +=(word,ins_date)
  }
  
  def findByWord(word:String)(implicit s: Session):List[Int] = {
    Twitters filter {
      _.word === word
    } map {
     _.id
    } list()
  }
}

DAOは分けてこう書いておくとよいと見かけたので、この形で作成。
ちなみにTableを継承してないclassがslickの対象パッケージにいるとエラー出るので別の階層にしないといけない。
package models.dao
 
import models.h2.Twitters
import scala.slick.lifted.TableQuery
 
private[models] trait DAO{
  val Twitters = TableQuery[Twitters]
}

ひととおり揃えたのでplay runして実行させるとエラーが出た。。。
エラーメッセージ
Found a matching object: modules.Twitter for modules.Twitter but it is not a Slick Table and a wildcard was not specified"

テーブルとして見てもらえてないようなメッセージ。
application.confの指定を*でなく指定する形の以下にしてみたもののだめ。
slick.default="models.Twitters"

結局、この形で記述してみたらうまくいきました。(h2はDBにh2database使ってるため)
最初のだとdaoとTwitter.scalaが同一ディレクトリにいるのがだめなようで、
指定した場所にTable以外のものが入ってないようにしないといけないようです。
slick.default="models.h2.*"


参考URL
http://akiomik.hatenablog.jp/entry/2014/02/23/033444
http://windymelt.hatenablog.com/entry/2014/03/30/191152
https://github.com/freekh/play-slick/blob/6b49ec019e00158c96df12d673856c53830ed1e6/code/src/main/scala/play/api/db/slick/ddl/TableScanner.scala
http://nilfigo.hatenablog.com/entry/2013/09/10/173552

2014年4月24日木曜日

Play FrameworkのAkkaでスケジューラ処理

Play FrameworkのAkkaでスケジューラ処理をさせました。
バージョン
Play Framework 2.2.2

GlobalSettingsを継承して、onStartをoverrideさせることで実現できました。
package common

import akka.actor._
import scala.concurrent.duration._
import play.api._
import play.api.libs.json._
import play.api.libs.concurrent._
import play.api.Play.current
import play.api.libs.concurrent.Execution.Implicits._
import service.TwitterService
import play.Logger
 
object Global extends GlobalSettings {
  
  override def onStart(app: Application){
   val actor = Akka.system.actorOf(Props(new TwitterService), "twitterservice")    
    Akka.system.scheduler.schedule(0.milliseconds, 1.minutes, actor, "tick")
  }  
}
TwitterServiceは↓に載せてあります。twitter4jを使って現在のtrendを取得する処理です。
Akkaに処理を渡す形になるのでActorを継承する必要があります。
Akka.system.scheduler.schedule(0.milliseconds, 1.minutes, actor, "tick")
は起動して0ミリ秒から1分置きにactorを動かして、actorに"tick"を送ります。
package service
 
import twitter4j.Twitter
import twitter4j.TwitterFactory
import twitter4j.Trend
import play.api.libs.concurrent.Akka
import akka.actor._
import akka.actor.Actor._
import org.slf4j.LoggerFactory
import play.Logger
import twitter4j.conf.ConfigurationBuilder
 
class TwitterService extends Actor{
   
  def receive = {
    case i:Int => {
      Logger.error("aa")
      println("aa")
    }
    case msg:String => {
      Logger.error(msg)
      println(msg)
      getTrend(23424856)
    }
    case _ => {
      Logger.error("tetete")
      println("tetete")
      getTrend(23424856)
    }
  }
  
  def getTrend(place:Int):Array[Trend] = {
    
    var twitter = twitterFactory.getInstance()
    var trendsResources = twitter.trends()
    var trends = trendsResources.getPlaceTrends(place)
    
    for(trend:Trend <- trends.getTrends()){
     println(trend.getName())
    }
  }  
}
def receiveにcase文で3つ処理を書きましたが、
"tick"を送っているので、case msg:Stringの処理が実行されます。

application.confのapplication.globalでGlobal.scalaの配置位置を指定できます
# Global object class
# ~~~~~
# Define the Global object class for this application.
# Default to Global in the root package.
# application.global=Global
application.global=common.Global

これでplay runで実行すると、1分置きにtwitterのtrendを取得しに行く処理が動きます。

参考URL
http://www.playframework.com/documentation/2.2.x/ScalaGlobal
http://stackoverflow.com/questions/20924195/play-framework-2-2-scala-onstart-doesnt-work

2014年4月22日火曜日

Play Frameworkで外部のライブラリを使えるようにする。

ScalaのPlay FrameworkではJavaのライブラリが使えるので、使えるようにしたい。
今回はtwitter4jのライブラリを追加します。

build.sbtに追加する
libraryDependencies ++= Seq(
  jdbc,
  anorm,
  cache,
  "org.twitter4j" % "twitter4j-core" % "4.0.1"
)     

使いたいライブラリはここで探すとよい
http://mvnrepository.com/
検索してライブラリを選択するとMavenなどの記述方法が出るので、
SBTのタブを選択して、そこの内容を元に追加する。

追加をしたらplayに反映させます。
$ play update
[info] Loading project definition from /Users/xxxx/play/sample/project
[info] Set current project to sample (in build file:/Users/xxxx/play/sample/)
[info] Updating {file:/Users/xxxx/play/sample/}sample...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] downloading file:/Users/xxxx/.m2/repository/org/twitter4j/twitter4j-core/4.0.1/twitter4j-core-4.0.1.jar ...
[info]  [SUCCESSFUL ] org.twitter4j#twitter4j-core;4.0.1!twitter4j-core.jar (13ms)
[info] Done updating.
[success] Total time: 4 s, completed 2014/04/15 14:54:05

playに反映させたら、eclipseからも読めるようにします。
$ play eclipse
[info] Loading project definition from /Users/xxxx/play/sample/project
[info] Set current project to sample (in build file:/Users/xxxx/play/sample/)
[info] About to create Eclipse project files for your project(s).
[info] Successfully created Eclipse project files for project(s):
[info] sample
eclipseで該当プロジェクトをrefresh(F5)すると、twitter4jのjarが現れます。


参考URL
http://qiita.com/p07025/items/b1be18f1c0db3b8fa3af
http://kagamihoge.hatenablog.com/entry/20130430/1367310191

2014年4月21日月曜日

Mac MavericksにPlay Frameworkをインストール

Mac MavericksにPlay Frameworkをインストールしました。

バージョン
Mac OS X 10.9.2
Play Framework2.2.2
Java 1.7.0_51
Eclipse 4.3

Macにはhomebrewでインストールできます。便利!
$ brew install play
==> Downloading http://downloads.typesafe.com/play/2.2.2/play-2.2.2.zip
######################################################################## 100.0%
🍺  /usr/local/Cellar/play/2.2.2: 2184 files, 130M, built in 37 seconds
インストールが完了したのでplayを起動
$ play
Getting com.typesafe.play console_2.10 2.2.2 ...
:: retrieving :: org.scala-sbt#boot-app
 confs: [default]
 6 artifacts copied, 0 already retrieved (2012kB/30ms)
Getting Scala 2.10.3 (for console)...
:: retrieving :: org.scala-sbt#boot-scala
 confs: [default]
 5 artifacts copied, 0 already retrieved (24447kB/145ms)
       _
 _ __ | | __ _ _  _
| '_ \| |/ _' | || |
|  __/|_|\____|\__ /
|_|            |__/
 
play 2.2.2 built with Scala 2.10.3 (running Java 1.7.0_51), http://www.playframework.com
 
This is not a play application!
 
Use `play new` to create a new Play application in the current directory,
or go to an existing application and launch the development console using `play`.
 
You can also browse the complete documentation at http://www.playframework.com.


無事に起動したので早速プロジェクトを作成
途中プロジェクト名聞かれるのでそのままEnterを押す
ScalaとJavaどちらにするか聞かれるので、今回はScalaで。
$ play new sample
       _
 _ __ | | __ _ _  _
| '_ \| |/ _' | || |
|  __/|_|\____|\__ /
|_|            |__/
 
play 2.2.2 built with Scala 2.10.3 (running Java 1.7.0_51), http://www.playframework.com
 
The new application will be created in /Users/xxxx/play/sample
 
What is the application name? [sample]
そのままEnter
 
Which template do you want to use for this new application? 
 
  1             - Create a simple Scala application
  2             - Create a simple Java application
 
> 1
OK, application sample is created.
 
Have fun!


プロジェクトを作成したので、とりあえず起動。
$ cd sample/
$ play run
Getting org.scala-sbt sbt 0.13.0 ...
:: retrieving :: org.scala-sbt#boot-app
 confs: [default]
 43 artifacts copied, 0 already retrieved (12440kB/196ms)
[info] Loading project definition from /Users/xxxx/play/sample/project
[info] Set current project to sample (in build file:/Users/xxxx/play/sample/)
[info] Updating {file:/Users/xxxx/play/sample/}sample...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
 
--- (Running the application from SBT, auto-reloading is enabled) ---
 
[info] play - Listening for HTTP on /0:0:0:0:0:0:0:0:9000
 
(Server started, use Ctrl+D to stop and go back to the console...)
http://localhost:9000 にアクセスしてYour new application is readyのページが出ればOK
アクセスするとコンソールに以下がでる
[info] Compiling 5 Scala sources and 1 Java source to /Users/xxxx/play/sample/target/scala-2.10/classes...
[info] 'compiler-interface' not yet compiled for Scala 2.10.3. Compiling...
[info]   Compilation completed in 11.059 s
[info] play - Application started (Dev)
最初はdevモードで起動するので、起動しただけだとコンパイルはされずに、
初めてアクセスをしたタイミングでコンパイルが走る。

Ctrl+Dで停止すると以下が出て終了
[success] Total time: 155 s, completed 2014/04/15 12:10:15

次にEclipseで開発できるように以下を実行
$ play eclipse
[info] Loading project definition from /Users/xxxx/play/sample/project
[info] Set current project to sample (in build file:/Users/xxxx/play/sample/)
[info] About to create Eclipse project files for your project(s).
[info] Successfully created Eclipse project files for project(s):
[info] sample

Eclipse側の対応もやっていく。
eclipseにScala IDEをインストール
eclipseはeclipse-jee-kepler-SR2-macosx-cocoa-x86_64.tar.gzをダウンロードしてきて使用。
ソフトウエアを追加する。
Help → Install New Software
Addで以下を追加
Name:Scala IDE for Eclipse
Location:http://download.scala-ide.org/sdk/e38/scala210/dev/site/

Scala IDE for Eclipse
Scala IDE for Eclipse development support
Scala IDE for Eclipse Source Feature
Scala IDE plugins(incubation)
Sources
の5つが表示されるのですべてチェックしてNext

Will not be installedに以下が表示されていたけど、
InSynth Feature
keep my installation the same and modify the items being installed tobe compatible
を選択してNext。
もう一回Next。
Review Licensesの画面になるのでI accept〜を選択してFinish

Security Warningが出るけどOK
再起動するか聞かれるのでOK

再起動すると
Upgrade of Scala plugin detected.
Run setup diagnostics to ensure correct plugin settings?
と聞かれるのでYesとして、内容を確認してOKする

File-Import-General-Existing Projects into Workspace
Select root directory:に先ほど作ったplayのプロジェクトのディレクトリを指定してFinish
これでEclipseからPlayのプロジェクトを開発できます。

2014年4月16日水曜日

Mac MavericksにhomebrewでVirtualBoxをインストール

Macの環境を整えていくってことで、今回はVirtualBoxをhomebrewでインストール

まずはbrewで入れられるかsearchしてみる。
$ brew search virtualbox
No formula found for "virtualbox".
Searching pull requests...
Closed pull requests:
libvirt: Enabled Support for VirtualBox by Default, Removed QEMU (https://github.com/Homebrew/homebrew/pull/6821)
検索してもひっかからない。。

$ brew tap phinze/homebrew-cask
$ brew install brew-cask
「tap」コマンドはphinzeというアカウントのhomebrew-caskを追加するという意味らしい。

$ brew cask search virtualbox
==> Exact match
virtualbox
検索でvirtualboxがひっかかるようになった。
$ brew cask install virtualbox
==> Downloading http://download.virtualbox.org/virtualbox/4.3.10/VirtualBox-4.3.10-93012-OSX.dmg
######################################################################## 100.0%
==> Running installer for virtualbox; your password may be necessary.
Password:
==> installer: Package name is Oracle VM VirtualBox
==> installer: Installing at base path /
==> installer: The install was successful.
🍺  virtualbox installed to '/opt/homebrew-cask/Caskroom/virtualbox/4.3.10-93012' (4 files, 115M)
インストールを完了するとアプリケーションにVirtualBox.appが追加されます。
簡単に入れられてよいですね。

2014年4月15日火曜日

Mac Mavericksにhomebrewをインストール

せっかくのMacなのでパッケージ管理システムでいろいろ管理したいなということで、
homebrewを入れてみました。
1.Javaのインストール
jdk8をoracleのサイトからダウンロードしてインストール
http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html

$ java -version
java version "1.8.0"
Java(TM) SE Runtime Environment (build 1.8.0-b132)
Java HotSpot(TM) 64-Bit Server VM (build 25.0-b70, mixed mode)

2.Xcodeのインストール
App Storeから入れられます。

3.homebrewのインストール
homebrewのサイト(http://brew.sh/index_ja.html)にある
インストール用のコマンドを実行する。

$ ruby -e "$(curl -fsSL https://raw.github.com/Homebrew/homebrew/go/install)"
==> /usr/bin/sudo /usr/bin/xcode-select --install
xcode-select: note: install requested for command line developer tools
Press any key when the installation has completed.
ポップアップが出てcommand line toolsを入れるか聞かれるのでインストール

$ brew doctor
Your system is ready to brew.

$ brew update
とりあえずhomebrewの導入はこれで完了。

2014年4月5日土曜日

テストから見えてくる グーグルのソフトウェア開発を読了

テストから見えてくる グーグルのソフトウェア開発を読了。 

テストから見えてくる グーグルのソフトウェア開発

テストから見えてくる グーグルのソフトウェア開発

  • 作者: ジェームズ・ウィテカー,ジェーソン・アーボン,ジェフ・キャローロ,長尾高弘
  • 出版社/メーカー: 日経BP社
  • 発売日: 2013/05/23
  • メディア: 単行本

インタビューが割と多くて少し読みづらかったけど、

興味深いところもあった。

ユースケースの20%が利用の80%を占める。その20%だけを自動化し、ほかのものには手を付けるな。その他は手動テストパスに残しておけばよい。

心に一番残ったのはこれ。
理想論を言えば、すべてのテストが自動化されてた方がよいし、新規で開発するときなんかはそこを目指すべきだと思います。
ただ、既存のシステムなんかで、テストの自動化がまだできてないところなんかは、これを基準にして少しずつ自動化を進めていくのがよいのだろうなと思いました。

2014年4月3日木曜日

html内のリンクURLは絶対パスで書いた方がよい

html内にリンク貼るときには絶対パスで書いた方がよいです。
例えばユーザーが自由にhtmlタグを入力できるようなサイトの場合、
タグ内に<base>タグを入れると、
そのページ内の相対パスがすべて<base>タグで
指定されたドメインのものになってしまいます。

<a href="http://www.google.co.jp/test.html">link 01</a><br/>
<a href="https://www.google.co.jp/hoge.html">link 02</a><br/>
<a href="test.html">link 11</a><br/>
<a href="hoge.html">link 12</a><br/>
<base href="http://yahoo.co.jp"/>
<a href="test.html">link 21</a><br/>
<a href="hoge.html">link 22</a><br/>
こういうページがあったとき、
link01とlink02はそのまま指定されたドメインのURLになりますが、
それ以外の4つは<base>タグで指定したドメインのURLのリンクになってしまいます。
なので、普段から絶対パスで書くようにしといた方がよいです。


サンプルソースgithubにあげました
https://github.com/syakasyaka/html/blob/master/base-tag.html