我希望我的Play应用程序使用不同的数据库进行测试,本地和生产(生产是Heroku)环境。
在application.conf
我有:
db.default.driver=org.postgresql.Driver
%dev.db.default.url="jdbc:postgresql://localhost/foobar"
%test.db.default.url="jdbc:postgresql://localhost/foobar-test"
%prod.db.default.url=${DATABASE_URL}
这似乎不起作用。当我运行play test
或play run
时,
所有数据库访问都失败了:
Configuration error [Missing configuration [db.default.url]] (Configuration.scala:258)
我对此有几个问题:
一般来说,我对数据库的配置方式有点困惑
在Play中:它看起来像普通db
,db.[DBNAME]
和db.
[DBNAME].url
,不同的教程做出了不同的选择
那些。某些似乎应该起作用的表达式(例如db.default.url = "jdbc:..."
失败,并且在预期对象的位置提供了字符串错误。)
我见过其他人建议我创建单独的prod.conf
,dev.conf
和test.conf
文件,每个文件都包含application.conf
,然后包含特定于数据库的配置。但在这种情况下,如何从Play控制台运行test
时指定要使用的数据库?
%env
语法是否适用于Play 2?
指定play test
使用的环境的正确方法是什么?
答案 0 :(得分:21)
在Play 2中,没有不同的配置环境。相反,您只需设置或覆盖conf/application.conf
文件中的配置参数。一种方法是在play
命令行上,例如:
play -Ddb.default.driver=org.postgresql.Driver -Ddb.default.url=$DATABASE_URL ~run
您还可以告诉Play使用其他配置文件:
play -Dconfig.file=conf/prod.conf ~run
有关Heroku的示例Procfile,请参阅:
https://github.com/jamesward/play2bars/blob/scala-anorm/Procfile
Play文档中的更多详细信息:
http://www.playframework.org/documentation/2.0/Configuration
答案 1 :(得分:11)
至少在Play 2.1.1中,如果设置了环境变量,可能会覆盖配置值。 (详见:http://www.playframework.com/documentation/2.1.1/ProductionConfiguration)
因此,您可以在conf/application.conf
中设置以下内容:
db.default.url="jdbc:mysql://localhost:3306/my-db-name"
db.default.url=${?DATABASE_URL_DB}
默认情况下,它将使用定义的JDBC-URL,除非环境变量DATABASE_URL_DB
为其定义了值。
因此,您只需在配置中设置开发数据库,并为生产或阶段设置环境变量。
但要注意,如果将变量引用放在带引号的字符串中,则此替换不起作用:
db.default.url="jdbc:${?DATABASE_URL_DB}"
相反,只是取消引用要替换的部分,例如。
database_host = "localhost"
database_host = ${?ENV_DATABASE_HOST}
db.default.url="jdbc:mysql://"${?database_host}":3306/my-db-name"
在此示例中,如果未设置环境变量ENV_DATABASE_HOST
,则默认情况下将使用localhost。 (详见:https://www.playframework.com/documentation/2.5.x/ConfigFile#substitutions)
答案 2 :(得分:2)
如果您在加载配置值时检查Play.isTest
,然后在加载的属性前加上'test',则实际上您仍然可以在Play 2中使用Play 1.0配置值命名方法。这是一个剪辑:
def configPrefix = if (play.api.Play.isTest) "test." else ""
def configStr(path: String) =
Play.configuration.getString(configPrefix + path) getOrElse
die(s"Config value missing: $configPrefix$path")
new RelDb(
server = configStr("pgsql.server"),
port = configStr("pgsql.port"),
database = configStr("pgsql.database"),
user = ...,
password = ...)
相关的配置代码段:
pgsql.server="192.168.0.123"
pgsql.port="5432"
pgsql.database="prod"
...
test.pgsql.server="192.168.0.123"
test.pgsql.port="5432"
test.pgsql.database="test"
...
现在,您无需记住在运行e2e测试套件时设置任何系统属性,并且您不会意外连接到prod数据库。
我想您可以选择将test.
值放在一个单独的文件中,然后将其包含在我认为的主配置文件的末尾。
答案 3 :(得分:0)
还有另一种方法是覆盖Global / GlobalSettings方法 onLoadConfig ,然后您可以使用通用配置和特定环境配置设置应用程序配置,如下所示......
conf/application.conf --> configurations common for all environment
conf/dev/application.conf --> configurations for development environment
conf/test/application.conf --> configurations for testing environment
conf/prod/application.conf --> configurations for production environment
您可以查看http://bit.ly/1AiZvX5我的示例实施。
希望这有帮助。
答案 4 :(得分:0)
偏离主题,但是如果你遵循12-factor-app,那么以环境命名的单独配置是不好的:
Another aspect of config management is grouping. Sometimes apps batch config into named groups (often called “environments”) named after specific deploys, such as the development, test, and production environments in Rails. This method does not scale cleanly: as more deploys of the app are created, new environment names are necessary, such as staging or qa. As the project grows further, developers may add their own special environments like joes-staging, resulting in a combinatorial explosion of config which makes managing deploys of the app very brittle