If you get in Homebrew:
Error: An unexpected error occurred during the `brew link` step
The formula built, but is not symlinked into /usr/local
Permission denied @ dir_s_mkdir - /usr/local/XXX
Then run the following to resolve:
sudo chown -R $(whoami) $(brew --prefix)/*
sudo install -d -o $(whoami) -g admin /usr/local/XXX
And either run brew again to install or brew link (whatever package that had the problem)
COMPUTERPUNC
Technology, Entrepreneurship, Craftsmanship and Fun.
Tuesday, November 13, 2018
Tuesday, August 30, 2016
Dependancy Injection and Anorm
Moving from Play Framework 2.4.x to 2.5.x requires to drop global variables. Specifically in this case play.api.Play.current and play.api.db.DB.
Most of my models using Anorm have a simple form:
case class Model(id:Long, name:String, …)
case object Model {
val model=get[Long]("id")~get[String]("name")~ … map {
case id~name~ … => Model(id, name, …)
}
def findById(id:Long):Option[Model]=DB.withConnection { implicit c=>
SQL"SELECT * FROM models WHERE modelId=$id".as(model*).headOption
}
}
In 2.5.x, DB is now deprecated. It is recommended to use dependancy injection.
Here's a minimum to support 2.5.x:
1. Instead of changing much (such as not using a case object), change DB to implicit.
def findById(id:Long)(implicit db:Database):Option[Model]=db.withConnection { implicit c=>
SQL"SELECT * FROM models WHERE modelId=$id".as(model*).headOption
}
2. For every controller using models, add @Inject()(db: Database), e.g.,
class Application @Inject()(db: Database) extends Controller {
implicit val dbImplicitVal=db
3. For every AKKA actor using models, add (db:Database), e.g.,
class Logger(db:Database) extends Actor {
and by calling props with a valid database when requesting an actor, e.g.,
val logger=actorSystem.actorOf(Props(new Logger(db)))
Simple and minimal.
Sunday, December 27, 2015
Simulate location routes when debugging in Xcode
If you want to simulate a route when debugging in Xcode, you'll need to create a gpx file add it to your Xcode project and then choose it when you run your app.
The hardest part is to create a gpx file. Xcode requires gpx files to be in a specific format.
So first create a gpx format by one of the available online map services. I used Graphhopper with satisfactory results (https://graphhopper.com/maps/).
Next, translate the resulting file to a format that Xcode will understand using the tool gpsbabel (on the Mac gpsbabel can be easily installed using homebrew).
The hardest part is to create a gpx file. Xcode requires gpx files to be in a specific format.
So first create a gpx format by one of the available online map services. I used Graphhopper with satisfactory results (https://graphhopper.com/maps/).
Next, translate the resulting file to a format that Xcode will understand using the tool gpsbabel (on the Mac gpsbabel can be easily installed using homebrew).
gpsbabel -i gpx -f input.gpx -x transform,wpt=trk -o gpx -F output.gpx
And that's it.
Friday, August 7, 2015
Some tips and tricks when doing TDD with SBT (and Play Framework)
If you are doing any TDD with SBT or Play Framework, here are a few tips and tricks to make you happy.
- Choose the right command tool to run your tests:
- test - runs all tests.
- testOnly - runs only one test (e.g. testOnly test1) or wild card specific tests (e.g. testOnly test1*).
- testQuick - runs only the tests that haven't run yet or failed ones. Can be limited to a specific test scope with a wild card (e.g. testQuick test1*).
- Since you are going run these command many many times, add the following shortcuts in build.sbt:
- to for testOnly - addCommandAlias("to", "testOnly")
- tq for testQuick - addCommandAlias("tq", "testQuick")
- Divide your tests into groups/folders. E.g., have a folder for unit tests in folder "unit" and run those test with to unit.* .
Saturday, July 4, 2015
Want to have different Java versions on the same Mac: jenv to the rescue
With the introduction of Play Framework 2.4.x, Play doesn't support Java 1.6 anymore. Because some applications running on the Mac require to run only with Java 1.6, there need to be some kind of a hybrid environment. jenv configuration utility to the rescue.
- Prerequisites - Apple's Java (https://support.apple.com/downloads/java), brew (http://brew.sh/) and brew-cask (http://caskroom.io/)
- Install Java - brew cask install java
- Install jenv - brew install jenv & echo 'if which jenv > /dev/null; then eval "$(jenv init -)"; fi' >> ~/.bash_profile
- Configure jenv - jenv add [JDK Folder], e.g., jenv add /Library/Java/JavaVirtualMachines/jdk1.8.0_45.jdk/Contents/Home
- Configure per Folder - jenv local [Java Version], e.g., jenv local oracle64-1.8.0.45
Monday, April 6, 2015
Play Framework, Anorm, Postgres and JSON
With the release of Postgres 9.4, JSON has become a first class citizen. JSON objects inside the DB can be indexed and searched as can regular columns in a relational DB.
If you are using Play Framework with Anorm then JSON with Postgres support doesn't come out of the box. On the bright side, it doesn't take much to make it work.
The examples below have been tested with Play Framework 2.3.7, Postgres 9.4.1 and Postgres JDBC Driver 9.4-1201.
Let's say we have a table in the DB of the following:
CREATE TABLE json_store (
id serial PRIMARY KEY,
data json
);
And here's some regular Scala code with Anorm:
import anorm.SqlParser._
import anorm._
import play.api.db.DB
import play.api.libs.json.JsValue
import play.api.Play.current
case class JsonData(id:Long, data:JsValue)
object JsonData {
val jsonData=get[Long]("id")~get[JsValue]("data") map {
case id~data=> JsonData(id, data)
}
def insert(data:JsValue):Option[Long]=DB.withConnection { implicit c=>
SQL"INSERT INTO json_store (data) VALUES ($data)".executeInsert()
}
def findById(jsonId:Long):Option[JsonData]=DB.withConnection { implicit c=>
SQL"SELECT * FROM object_store WHERE id=$jsonId".as(jsonData*).headOption
}
}
This doesn't compile with 2 errors:
[error] could not find implicit value for parameter extractor: anorm.Column[play.api.libs.json.JsValue]
[error] val jsonData=get[Long]("id")~get[JsValue]("data") map {
[error] ^
and
[error] type mismatch;
[error] found : play.api.libs.json.JsValue
[error] required: anorm.ParameterValue
[error] SQL"INSERT INTO json_store (data) VALUES ($data)".executeInsert()
To fix the 1st error, we'll add an implicit that will transform a json into a string and inject it into the SQL statement:
def set(s: PreparedStatement, i: Int, json: JsValue):Unit=s.setString(i, Json.stringify(json))
}
implicit object jsonToStatement extends ToStatement[JsValue] {
def set(s: PreparedStatement, i: Int, json: JsValue):Unit={
val jsonObject=new org.postgresql.util.PGobject()
jsonObject.setType("json")
jsonObject.setValue(Json.stringify(json))
s.setObject(i, jsonObject)
}
}
And for the 2nd error, we'll add an implicit that will transform a PGobject into JsValue:
implicit val columnToJsValue:Column[JsValue]=anorm.Column.nonNull[JsValue] { (value, meta) =>
val MetaDataItem(qualified, nullable, clazz)=meta
value match {
case json:org.postgresql.util.PGobject=> Right(Json.parse(json.getValue))
case _=> Left(TypeDoesNotMatch(s"Cannot convert $value: ${value.asInstanceOf[AnyRef].getClass} to Json for column $qualified"))
}
}
To overcome, we'll add the following cast:
And that's all you need for adding JSON support in Play Framework with Anorm.
Subscribe to:
Posts (Atom)