Screaming Loud

日々是精進

2015年に読んだ本を振り返る

以下サイトを見てまとめて記録として残しておくのはいいなぁと思ったので、自分が読んだ本に関してもまとめてみます。
blog.kentarok.org

自分は読書メーターを利用して読書記録をつけているので、以下を見てもらえれば把握できるかと思います。
bookmeter.com


今年読んだ冊数は30冊でした。
去年読んだ冊数は41冊なので、結構減ってしまいました。

減った原因としては、以下のアプリに対してかなりの時間を費やしてしまったことが大きいかなと思っています。

Vainglory

Vainglory

  • Rogue Games
  • ゲーム
  • 無料

んーvaingloryはリアルタイムでのマッチングで3vs3の対戦です。
スプラトゥーンみたいな感じなのですが、iPhone,Androidでできるやつです。
ハマってしまいました。。

あとは、DeepLearingの勉強を2ヶ月くらいちょこちょこやっていて、その間はほとんど本を読まなかったのも大きかったかなーと思います。

良かった本

今年読んだ中でよかったと思った本は30冊だったので少ないですが、以下です。

bookmeter.com
bookmeter.com
bookmeter.com

結構、その時々のタイミングによって読む本とその本に対する感想は結構変わるので、なんともいえませんね。

slickのcase classをつくるのがめんどくさかったので、スクリプトで作った

slickのcase classをつくるのがめんどかったので、SQLを投げればcase classとTableを生成するスクリプト作りました。
(すでにslick-code-generatorとかある。車輪の再発明。。)
Schema code generation — Slick 2.0.0-RC1 documentation


作った経緯として、なんかslick-code-genが動かなくなって、原因追求の時間がなかったからさくっと作った感じです。

github.com

後悔はしていない。


実際、こんなcreate SQL文を投げると、

CREATE TABLE `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(100) DEFAULT NULL,
  `email` varchar(100) DEFAULT NULL,
  `password` varchar(100) DEFAULT NULL,
  `create_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `last_name` varchar(25) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1851 DEFAULT CHARSET=utf8;
case class usersDto(
  id: Int ,
  name: String ,
  email: String ,
  password: String ,
  createDate: DateTime ,
  lastName: String
)
class usersTable(tag: Tag) extends Table[usersDto](tag, "users") {
  def id: Column[Int] = column[Int]("id")
  def name: Column[String] = column[String]("name")
  def email: Column[String] = column[String]("email")
  def password: Column[String] = column[String]("password")
  def createDate: Column[DateTime] = column[DateTime]("create_date")
  def lastName: Column[String] = column[String]("last_name")
def * = (id,name,email,password,create_date,last_name)<>(usersDto.tuppled, usersDto.unapply)
}

こんなアウトプットになります。

新しいfirefoxのweb extensionsがChromeExtentionとの互換性そのままだった

今回、firefox dev conferenceに参加してきました。

www.mozilla.jp


そこで聞いてきた、webextensionsに関して試してみたので、ログっておきます。

firefoxはアドオンの機能に関して、Chrome拡張機能と同じ仕様を搭載することを発表しています。dev.mozilla.jp

実際、どのようにして作るのか紹介します。

WebExtensionsに関しては、WebExtensions - MozillaWikiに書いてあります。

環境構築

以下からFirefox Developer Editionをダウンロードします。
Firefox のダウンロード — 自由な Web ブラウザ — Mozilla
リンクのURLからしてバージョンが変わると見れなくなりそうなので、
リンクに飛べない場合は、「DeveloperEdition」で検索してダウンロードします。

  • DeveloperEditionを起動
  • about:configを開く
  • xpinstall.signatures.required = falseにする。(これは、署名されていないアドオンを利用できるようにするものです。)

これで環境構築は終了です!

拡張機能開発

今回は互換性がそのままだということを示すために、GoogleChrome拡張機能サンプルから作成します。
mdn/webextensions-examples · GitHubにMDNが作成したサンプルもあります。


以下から、PageRedderをダウンロードします。
Sample Extensions - Google Chrome
このアドオンは単純にバックグラウンドを赤くするアドオンですw

  • background.js
  • manifest.json

をダウンロードします。

manifest.jsonのルートに以下を追加します。

"applications": {
    "gecko": {
        "id": "borderify@mozilla.org"
    }
},

そして、以下で圧縮します。

zip -r ../redder.xpi *

これで出来たxpiファイルをDeveoperEditionブラウザにドラッグアンドドロップでインストールされます

作ったアドオンで画面はこんな感じになりますw
f:id:yuutookun:20151115165653p:plain

Firefoxのアドオンが更に充実していくといいですねb

参考にGistも貼っておきます。

slickにおける動的にwhere句を作る

Slickにおける動的where句の作り方

現在最新は3系ですが環境としては、Slick2.1での書き方での紹介です。
Documentation | Slick

Slickにおいて動的にwhere句を作るのは、案外Scalaを始めたばかりだとうまくいきません。

以下の様なクラスに対して複数の検索をかけるとき、

type Address = (Int,String,String)
class Addresses(tag: Tag) extends Table[Address](tag, "ADDRESS") {
  def id = column[Int]("ID", O.PrimaryKey, O.AutoInc)
  def street = column[String]("STREET")
  def city = column[String]("CITY")
  def * = (id,street,city)
}
lazy val addresses = TableQuery[Addresses]

多分一番最初に思い浮かぶ方法は以下だと思います。

def find(streetOp: Option[String], cityOp: Option[String])(implicit session: Session) = {
  val q = streetOp.map(s => addresses.filter(_.street === s).getOrElse(addresses)
  val q1 = cityOp.map(c => q.filter(_.city === c).getOrElse(q)
  q1.list
}

しかし、実はfilter()の中をColumn[Option[Boolean]]を返すことで条件として満たします。
なので、以下の様な書き方ができます。

def makeCondition(row: Addresses, streetOp: Option[String], cityOp: Option[String]): Column[Option[Boolean]] = {

    val True: Column[Option[Boolean]] = Some(true)
    val a: Option[Boolean] = (if (streetOp.nonEmpty) row.street === streetOp.get else True) &&
      (if (citiOp.isDefined) row.city === cityOp.get else True)
    a   
}
addresses.filter(q => makeCondition(q, Some("東海道"), None)).list

この書き方の場合、検索条件を関数化できるので、複数の部品による組み合わせができます。

例えば、

addresses.filter(q => makeCondition(q, Some("東海道"), None) || q.id === 1).list

みたいなことができます。

使う機会は多いのに、ドキュメントからではなかなかわからないのですが、ぜひ活用してみてください。