SORU
1 Aralık 2012, CUMARTESİ


Nasıl veritabanı-agnostik Oyun uygulama yazmak ve veritabanı başlatma gerçekleştirmek için?

2.1* *27 Slick kullanıyorum ve bazı sorunlarım var.

Aşağıdaki verilen varlık...

package models

import scala.slick.driver.PostgresDriver.simple._

case class Account(id: Option[Long], email: String, password: String)

object Accounts extends Table[Account]("account") {
  def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
  def email = column[String]("email")
  def password = column[String]("password")
  def * = id.? ~ email ~ password <> (Account, Account.unapply _)
}

...İçin bir paket almak zorunda kalıyorumözelveritabanı sürücüsü, ama kullanmak istiyorumH2içintestvePostgreSQLüretim. Peki ne yapmam gerekiyor?

Bu geçici çözüm başardıgeçersiz kılmasürücü ünitesi test ayarları:

package test

import org.specs2.mutable._

import play.api.test._
import play.api.test.Helpers._

import scala.slick.driver.H2Driver.simple._
import Database.threadLocalSession

import models.{Accounts, Account}

class AccountSpec extends Specification {

  "An Account" should {
    "be creatable" in {
      Database.forURL("jdbc:h2:mem:test1", driver = "org.h2.Driver") withSession {
        Accounts.ddl.create                                                                                                                                          
        Accounts.insert(Account(None, "user@gmail.com", "Password"))
        val account = for (account <- Accounts) yield account
        account.first.id.get mustEqual 1
      }
    }
  }
}

Bu çözüm sevmiyorum ve eğer iki farklı veritabanı motorları kullanılan test ve üretim başka bir var DB-agnostik kodu yazmak için zarif bir yolu varsa merak ediyorum?

Evrim kullanmak da istemiyorum, ve Kaygan benim için veritabanı tabloları oluşturmak için tercih:

import play.api.Application
import play.api.GlobalSettings
import play.api.Play.current
import play.api.db.DB

import scala.slick.driver.PostgresDriver.simple._
import Database.threadLocalSession

import models.Accounts

object Global extends GlobalSettings {

  override def onStart(app: Application) {
    lazy val database = Database.forDataSource(DB.getDataSource())

    database withSession {
      Accounts.ddl.create
    }
  }
}

Uygulamayı başlatmak ilk kez, her şey çok güzel... o zaman, tabii ki, ben PostgreSQL veritabanı tabloları zaten çünkü çöküyor uygulamayı başlatmak ikinci kez çalışır.

Bu, son iki soru var " dedi

  1. Nasıl veritabanı tablo zaten var olup olmadığını nasıl belirleyebilirim?
  2. Nasıl FakeApplication ile benim uygulama test edebilirsiniz böylece DB-agnostik yukarıda onStart yöntemi yapabilir miyim?

CEVAP
2 Aralık 2012, Pazar


Bağımlılık enjeksiyon / kek kalıbı veritabanı Erişim Katmanı Kaygan sürücüsü burada ayrıştır kullanmak için nasıl bir örnek bulabilirsiniz: https://github.com/slick/slick-examples.

Nasıl FakeApplication ile Kaygan sürücü ve test uygulama ayrıştır

Bir kaç gün önce uygulama için sürücü bağımlılık taşır oynamak için Kaygan entegrasyon kitaplık yazdım.Oyun proje conf: https://github.com/danieldietrich/slick-integration.

Bu kütüphane yardımı ile örnek aşağıdaki gibi uygulanacak

1) proje/bağımlılık Oluşturmak Ekleyin.scala

"net.danieldietrich" %% "slick-integration" % "1.0-SNAPSHOT"

Anlık depo Ekle

resolvers  = "Daniel's Repository" at "http://danieldietrich.net/repository/snapshots"

Veya kaygan entegrasyon yerel depo, yerel olarak yayımlanır

resolvers  = Resolver.mavenLocal

2) Kaygan sürücü/uygulama conf Ekleyin.conf

slick.default.driver=scala.slick.driver.H2Driver

3) Hesap/uygulama/modelleri Uygulamak.scala

Kaygan-bütünleşme durumunda, otomatik artan olan tip Uzun birincil anahtarları kullandığınız varsayılmaktadır. Pk adı''. ıd. Tablo/Eşleyici uygulama varsayılan yöntemleri (sil, findAll, findByİd, ınsert, update). Sizin varlıklar uygulamak zorunda 'gerekli olan' 'Ekle' yöntemi. withİd

package models

import scala.slick.integration._

case class Account(id: Option[Long], email: String, password: String)
    extends Entity[Account] {
  // currently needed by Mapper.create to set the auto generated id
  def withId(id: Long): Account = copy(id = Some(id))
}

// use cake pattern to 'inject' the Slick driver
trait AccountComponent extends _Component { self: Profile =>

  import profile.simple._

  object Accounts extends Mapper[Account]("account") {
    // def id is defined in Mapper
    def email = column[String]("email")
    def password = column[String]("password")
    def * = id.? ~ email ~ password <> (Account, Account.unapply _)
  }

}

4) app/models/DAL Uygulamak.scala

Bu veritabanına erişmek için kontrolörler tarafından kullanılan Veri Erişim Katmanı (DAL). İşlemleri ilgili Bileşen içinde/Eşleyici uygulama Tablo tarafından yönetilir.

package models

import scala.slick.integration.PlayProfile
import scala.slick.integration._DAL
import scala.slick.lifted.DDL

import play.api.Play.current

class DAL(dbName: String) extends _DAL with AccountComponent
    /* with FooBarBazComponent */ with PlayProfile {

  // trait Profile implementation
  val profile = loadProfile(dbName)
  def db = dbProvider(dbName)

  // _DAL.ddl implementation
  lazy val ddl: DDL = Accounts.ddl //    FooBarBazs.ddl

}

object DAL extends DAL("default")

5) test/test/AccountSpec Uygular.scala

package test

import models._
import models.DAL._
import org.specs2.mutable.Specification
import play.api.test.FakeApplication
import play.api.test.Helpers._
import scala.slick.session.Session

class AccountSpec extends Specification {

  def fakeApp[T](block: => T): T =
    running(FakeApplication(additionalConfiguration = inMemoryDatabase()   
        Map("slick.default.driver" -> "scala.slick.driver.H2Driver",
          "evolutionplugin" -> "disabled"))) {
      try {
        db.withSession { implicit s: Session =>
          try {
            create
            block
          } finally {
            drop
          }
        }
      }
    }

  "An Account" should {
    "be creatable" in fakeApp {
      val account = Accounts.insert(Account(None, "user@gmail.com", "Password"))
      val id = account.id
      id mustNotEqual None 
      Accounts.findById(id.get) mustEqual Some(account)
    }
  }

}

Nasıl veritabanı veya tablo zaten var olup olmadığını belirlemek için

Bu soru için yeterli bir cevap veremem...

... ama belki de bu gerçekten değil.th yapmak istiyorum. Eğer bir tablo için bir öznitelik eklemek, Account.active söyle? Eğer güvenli veri şu anda, tablolardaki saklı istiyorsanız, o zaman bir alter senaryo iş yapmaz. Şu anda, böyle bir alter script elle yazılmış olmalı. DAL.ddl.createStatements tablolar oluşturmak almak için kullanılabilir. Önceki sürümleri ile daha iyi karşılaştırılabilir olması sıralanması. Sonra bir diff (önceki sürüm ile) el ile alter komut dosyası oluşturmak için kullanılır. Burada, evrimler db şema değiştirmek için kullanılır.

İşte (ilk) evrim oluşturmak için nasıl bir örnek:

object EvolutionGenerator extends App {

  import models.DAL

  import play.api.test._
  import play.api.test.Helpers._

    running(FakeApplication(additionalConfiguration = inMemoryDatabase()   
        Map("slick.default.driver" -> "scala.slick.driver.PostgresDriver",
          "evolutionplugin" -> "disabled"))) {


    val evolution = (
      """|# --- !Ups
         |"""   DAL.ddl.createStatements.mkString("\n", ";\n\n", ";\n")  
      """|
         |# --- !Downs
         |"""   DAL.ddl.dropStatements.mkString("\n", ";\n\n", ";\n")).stripMargin

    println(evolution)

  }

}

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Andrew_Huang

    Andrew_Huang

    10 ŞUBAT 2006
  • We've moved!

    We've moved!

    7 Ocak 2008
  • USI Events

    USI Events

    6 AĞUSTOS 2013