Skip to content

Instantly share code, notes, and snippets.

@gakuzzzz
Last active June 30, 2016 21:58
Show Gist options
  • Save gakuzzzz/10460232 to your computer and use it in GitHub Desktop.
Save gakuzzzz/10460232 to your computer and use it in GitHub Desktop.
Skinny Framework ハンズオン Q&A

Skinny Framework ハンズオンで出た質問と回答

IDE の Debugger どうやったら使えるの?

ハンズオン中はごめんなさいをするしかなかったのですが、 Skinny Framework 1.0.6 から使えるようになりました!

$ ./skinny debug [port]

とすると、リモートデバッグを有効にしてアプリが起動します。 後はお使いのIDEのDebuggerから指定したポートに接続すれば、 Break Pointなど自由に貼ることができます。

port番号を省略した場合はデフォルトで 5005 ポートを使用します。

Skinny ORM の Associations で、DB上でも NOT NULL だし、byDefault で必ず join するのに、フィールドを Option 型で宣言しなきゃいけないのがキモいんだけど?

2014-04-12 00:27 追記

innerJoinWithDefaults もしくは innerJoin を使用して、extract 中から関連の apply を呼んで Option を回避できるようです。> ありがとうございます @seratch

case class Employee private (
  id: EmployeeId,
  name: String,
  companyId: CompanyId,
  company: Company
)

object Employee extends SkinnyCRUDMapper[Employee] {

  innerJoinWithDefaults(Company, (e, c) => sqls.eq(e.companyId, c.id)).byDefault

  override def extract(rs: WrappedResultSet, rn: ResultName[Employee]): Employee = new Employee(
    id = rs.get(rn.id),
    name = rs.get(rn.name),
    companyId = rs.get(rn.companyId),
    company = Company(rs)
  )

}

2014-04-12 00:27 削除

気持ちは痛いほどわかります。

とは言え、逆からの関連を辿る場合など、join しないケースが実際にはありえるので、型としては Option にしておく方が望ましいと思います。

ただ、アプリケーションの殆どで join するケースしかあり得ないと想定できるのであれば、確かに毎回 Option を剥がすのも面倒なので、下記のように直接アクセスできるようなアクセサを提供するのも検討できます。

case class Employee private (
  id: EmployeeId,
  name: String,
  companyId: CompanyId,
  private val companyOpt: Option[Company] = None
) {

  lazy val company: Company = companyOpt.get // 常にjoinして取得する前提なのでここで例外でたら
                                             // データがおかしいかコードにバグがある
}

object Employee extends SkinnyCRUDMapper[Employee] {

  belongsTo[Company](Company, (e, c) => e.copy(companyOpt = c)).byDefault

  override def extract(rs: WrappedResultSet, rn: ResultName[Employee]): Employee = new Employee(
    id = rs.get(rn.id),
    name = rs.get(rn.name),
    companyId = rs.get(rn.companyId)
  )

}

画面の左上に Some(Some( っていう謎の表示があるんだけど?

以下のようなコードで画面上に奇妙な Some(Some( という表示がされていました。

class EmployeesController extends ApplicationController {

  def show = params.getAs[EmployeeId]("id").map { id =>
    Employee.findById(id).map { emp =>
      set("employee", emp)
      render("/employees/show")
    }
  }

  ...snip

}

params.getAs[EmployeeId]Option[EmployeeId] を返します。 そして Employee.findById(id)Option[Employee] を返します。 したがって、この show メソッドは Option[Option[String]] を返す事になっていました。

このコードは本来下記のようにする必要があったのです。

class EmployeesController extends ApplicationController {

  def show = params.getAs[EmployeeId]("id").flatMap { id =>
    Employee.findById(id).map { emp =>
      set("employee", emp)
      render("/employees/show")
    }
  } getOrElse halt(404)

  ...snip

}

これはなかなか検出しづらいですね。

render を使うような場合は、戻り値の型アノテーションを省略せずに

  def show: String = ...

のようにしておくと、うっかり Option を返すコードを書いてしまった時にコンパイラが型チェックで検出してくれるので、慣れないうちは上記のようにしておくのもありかもしれません。

余談ですが、今回の様な Option がネストする場合というのは結構多発します。 そういった場合はfor式を使うとすっきり書けるケースがあります。

  def show = (for {
    id  <- params.getAs[EmployeeId]("id")
    emp <- Employee.findById(id)
  } yield {
    set("employee", emp)
    render("/employees/show")
  }) getOrElse halt(404)

Assets Pipeline を使わない静的リソースはどこに置けばいいの?

${application_root}/src/main/webapp/

以下にファイルを置くと、contextPath 以下から参照できます。

IntelliJ IDEA の日本語化できないの?

株式会社サムライズム さんの動きに期待しましょう!

現在日本語化に向けてのアンケート を行っているようです。

skinny run で起動するポートを変更できないの?

Skinny Framework 1.0.6 から簡単に変更できるようになりました。

${application_root}/project/Build.scala

を開いて

port in container.Configuration := 8080

の行を好きなポート番号に変更すればOKです。

@seratch
Copy link

seratch commented Apr 11, 2014

Skinny ORM の Associations で、DB上でも NOT NULL だし、byDefault で必ず join するのに、フィールドを Option 型で宣言しなきゃいけないのがキモいんだけど?

extract で必ず join されているものをとる手段はあります。どうしても Option を回避したいならこれですね。

https://github.com/skinny-framework/skinny-framework/blob/1.0.6/orm/src/test/scala/skinny/orm/models.scala#L30

https://github.com/skinny-framework/skinny-framework/blob/1.0.6/orm/src/test/scala/skinny/orm/models.scala#L70

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment