Playãã¬ãŒã ã¯ãŒã¯ã¯éåžžã«æè»ãªããŒã«
ã§ãããã€ã³ã¿ãŒãããäžã®
ã«ãŒããã¡ã€ã«ã®åœ¢åŒãå€æŽããæ¹æ³ã«é¢ããæ
å ±ã¯ã»ãšãã©ãããŸããã ã«ãŒããã¡ã€ã«ã«åºã¥ãæšæºã®ã«ãŒãèšè¿°èšèªã
RAML圢åŒã®èª¬æã«
眮ãæããæ¹æ³ã«ã€ããŠèª¬æããŸãã ãã®ããã«
ãç¬èªã®SBTãã©ã°ã€ã³ãäœæããå¿
èŠããããŸãã
RAMLïŒRESTful API Modeling LanguageïŒã«é¢ããç°¡åãªèª¬æã§ãã ãããžã§ã¯ãã®ã¡ã€ã³ããŒãžã§éåžžã«æ£ç¢ºã«è¿°ã¹ãããŠããããã«ããã®èšèªã¯ã©ã€ããµã€ã¯ã«å
šäœãéããŠã¢ããªã±ãŒã·ã§ã³APIã®æäœã倧å¹
ã«ç°¡çŽ åããŸãã ç°¡æœã§ãåå©çšãç°¡åã§ãæãéèŠãªã®ã¯ãæ©æ¢°ãšäººãåãããã«èªã¿ãããããšã§ãã ã€ãŸãã1ã€ã®ã¢ãŒãã£ãã¡ã¯ãïŒRAMLã¹ã¯ãªããïŒãéçºããã»ã¹ã®ãã¹ãŠã®åå è
ïŒã¢ããªã¹ãããã¹ã¿ãŒãããã°ã©ããŒïŒã®ãšã³ããªãã€ã³ãã«ãªããšãã«ãããã¥ã¡ã³ããã³ãŒãã¢ãããŒããšããŠå®è£
ã§ããŸãã
åé¡ã®å£°æ
ç§ãã¡ã®ããŒã ã¯ã倧èŠæš¡ã§è€éãª
ãªã³ã©ã€ã³ãã³ãã³ã°ã·ã¹ãã ã«åãçµãã§ã
ãŸã ã ã€ã³ã¿ãŒãã§ã€ã¹ãšãã¹ãã®ããã¥ã¡ã³ãã«ç¹ã«æ³šæãæãããŸãã ãã¹ããããã¥ã¡ã³ããããã³ã³ãŒãçæãçµã¿åãããããšãã§ãããã©ããçåã«æããŸããã ããã¯ããçšåºŠãŸã§å¯èœã§ããããšãå€æããŸããã ããããæåã«ããªããããå¿
èŠãªã®ãã«ã€ããŠã®ããã€ãã®èšèã
倧èŠæš¡ãªãããžã§ã¯ãã§ã¯ãã€ã³ã¿ãŒãã§ã€ã¹ã®ããã¥ã¡ã³ãåãç¹ã«éèŠã§ãã ã¢ããªã¹ãããµãŒãã¹ãããã³ã¯ã©ã€ã¢ã³ãã¢ããªã±ãŒã·ã§ã³ã®éçºè
ã¯ãäœæ¥ããŠããAPIã·ã¹ãã ã®èª¬æãå¿
èŠã§ãã ã¢ããªã¹ãã¯ããã¥ã¡ã³ããèªã¿ãããæ¹æ³ã§æ±ããããã°ã©ããŒã¯æçµçã«ã€ã³ã¿ãŒãã§ã€ã¹ãã³ãŒãã§èšè¿°ããç°ãªãããŒã ã¯ç°ãªãèšèªã§ã³ãŒããèšè¿°ããŸãã æ
å ±ã¯äœåºŠãè€è£œããããããåæãé£ãããªããŸãã å€æ°ã®ã³ãã³ããããå Žåãç°ãªãAPI圢åŒã®äºææ§ãæåã§ä¿èšŒããããšã¯ã»ãšãã©äžå¯èœã§ãã ãã®ããããã®åé¡ã®è§£æ±ºã«åŸ¹åºçã«åãçµã¿ãŸããã
ãŸããAPIèšè¿°ã®ãã¹ãŠã®ããŒã ã«çµ±äžãããèšè¿°åœ¢åŒãéžæããŸããã RAMLã«ãªããŸããã 次ã«ããµãŒãã¹ã説æã©ããã§ãããã¯ã©ã€ã¢ã³ãã¢ããªã±ãŒã·ã§ã³ã説æãããŠãããµãŒãã¹ã§åäœããããšãïŒå¯èœãªéãïŒä¿èšŒããå¿
èŠããããŸãã ãããè¡ãã«ã¯ãå¥ã®èšäºã§èª¬æãããã¹ãããŒã«ã䜿çšããŸãã æåŸã®ã¹ãããã¯ãRAMLã®ããŒã¿ã«åºã¥ããŠã³ãŒããäœæããã³ãŒãçæã®å°å
¥ã§ããã ä»æ¥ã¯ããµãŒããŒãããžã§ã¯ãã§äœ¿çšãããã³ãŒãçæããŒã«ã«ã€ããŠèª¬æããŸãã
éåžžãããã¥ã¡ã³ãã«ã¯ãRESTãšã³ããã€ã³ãã«é¢ããæ
å ±ããªã¯ãšã¹ãã®ãã©ã¡ãŒã¿ãŒãšæ¬æã®èª¬æãHTTPã³ãŒããããã³å¿çã®èª¬æãå«ãŸããŠããŸãã åæã«ãå€ãã®å Žåãäžèšã®ãã¹ãŠã®èŠçŽ ã®äŸã瀺ãããŠããŸãã ãã®æ
å ±ã¯ããšã³ããã€ã³ãã®æäœæ§ããã¹ãããã®ã«ååã§ãããµã³ãã«ã®ãªã¯ãšã¹ããåãåã£ãŠãµãŒããŒã«éä¿¡ããã ãã§ãã ãšã³ããã€ã³ãã«ãã©ã¡ãŒã¿ãŒãããå Žåããããã®å€ãäŸããååŸããå¿
èŠããããŸãã åãåã£ãåçãåçã®äŸãšæ¯èŒããããããã¥ã¡ã³ãã«åºã¥ããŠJSONã¹ããŒã ãæ€èšŒããŸãã ãµã³ãã«ã®åçããµãŒããŒã®å¿çã«å¯Ÿå¿ããããã«ã¯ãããŒã¿ããŒã¹å
ã®æ£ããããŒã¿ãåŠçããå¿
èŠããããŸãã ãããã£ãŠããã¹ãããŒã¿ãšãå¿çã®èª¬æãšãªã¯ãšã¹ãã®äŸãèšèŒãããAPIãµãŒãã¹ã®ããã¥ã¡ã³ããå«ãããŒã¿ããŒã¹ãããå ŽåããµãŒãã¹ã®ç¶æ
ãç°¡åã«ãã¹ãã§ããŸãã å®å
šãæãããã«ãããã¥ã¡ã³ãããã¹ãã·ã¹ãã ãããã³ããŒã¿ããŒã¹ã«ã€ããŠã¯æ¢ã«èª¬æããŸãããããããã«ã€ããŠã¯ãŸãå¥ã®æ©äŒã«èª¬æããŸãã ããã§ã¯ããã®ãããªããã¥ã¡ã³ãã«åºã¥ããŠãã§ããã ãå€ãã®æçšãªãµãŒããŒã³ãŒããçæããæ¹æ³ã«ã€ããŠèª¬æããŸãã
ç§ãã¡ã®ãµãŒããŒã¯Play 2.5ã§æžãããŠããã顧客ã«REST APIãæäŸããŠããŸãã ããŒã¿äº€æ圢åŒã¯JSONã§ãã Playãã¬ãŒã ã¯ãŒã¯ã®æšæºAPIèšè¿°ã¯conf / routeãã¡ã€ã«ã«ãããŸãã ãã®èª¬æã®æ§æã¯åçŽã§ããšã³ããã€ã³ãã®ååãšãã®ãã©ã¡ãŒã¿ãŒã®èª¬æãããã³ã«ãŒããã¡ã€ã«å
ã®ã³ã³ãããŒã©ãŒã¡ãœãããžã®ãšã³ããã€ã³ãã®ãã€ã³ãã«éå®ãããŠããŸãã ç§ãã¡ã®ç®æšã¯ãæšæºæ§æãRAML圢åŒã®èª¬æã«çœ®ãæããããšã§ãã ããã«ã¯æ¬¡ã®ãã®ãå¿
èŠã§ãã
- Playã§ã®ã«ãŒãã£ã³ã°ã®ä»çµã¿ãšãã«ãŒããã¡ã€ã«ã®åŠçæ¹æ³ãç解ããŸãã
- RAMLã䜿çšããã¡ã«ããºã ã§æšæºã«ãŒãã£ã³ã°ã¡ã«ããºã ã眮ãæããŸãã
- çµæãèŠãŠãçµè«ãå°ããŸã:)
é çªã«ååŸããŸãããã
Playãã¬ãŒã ã¯ãŒã¯ã§ã®ã«ãŒãã£ã³ã°
Playãã¬ãŒã ã¯ãŒã¯ã¯ãScalaãšJavaã®2ã€ã®èšèªã§äœ¿çšããããã«èšèšãããŠããŸãã ãããã£ãŠãã«ãŒããèšè¿°ããããã«ããã¬ãŒã ã¯ãŒã¯ã®äœæè
ã¯ç¹å®ã®èšèªã«åºã¥ããDSLã䜿çšãããç¬èªã®èšèªãšãã®ã³ã³ãã€ã©ãäœæããŸããã 次ã«ãScalaã«ã€ããŠèª¬æããŸãããJavaã«ã€ããŠã¯ãã¹ãŠãçå®ã§ãã playã¢ããªã±ãŒã·ã§ã³ã¯
SBTã䜿çšããŠæ§ç¯ãããŠããŸãã ãããžã§ã¯ãã®ã¢ã»ã³ããªäžã«ãã«ãŒããã¡ã€ã«ãScalaãŸãã¯Javaã§ãã¡ã€ã«ã«ã³ã³ãã€ã«ãããã³ã³ãã€ã«çµæãã¢ã»ã³ããªäžã«äœ¿çšãããŸãã SBTãã©ã°ã€ã³com.typesafe.play.sbt-pluginã¯ãã«ãŒããã¡ã€ã«ã®åŠçãæ
åœããŸãã ä»çµã¿ãèŠãŠã¿ãŸãããã ããããæåã«ãSBTã«ã€ããŠäžèšã
SBTã®åºæ¬æŠå¿µãéèŠã§ãã ããŒã«ã¯ãTaskKeyãšSettingsKeyã®2ã€ã®ã¿ã€ãããããŸãã æåã®ã¿ã€ãã¯ãé¢æ°ãä¿åããããã«äœ¿çšãããŸãã ãã®ããŒãåŒã³åºããã³ã«ããã®é¢æ°ãåŒã³åºãããŸãã 2çªç®ã®ã¿ã€ãã®ããŒã¯å®æ°ãä¿åãã1åèšç®ãããŸãã ã³ã³ãã€ã«ã¯TaskKeyã§ãããå®è¡ã®éçšã§ãã³ãŒãçæãšãœãŒã¹ãã¡ã€ã«ã®äœæã®ããã«å¥ã®TaskKeyãsourceGeneratorsãåŒã³åºããŸãã å®éã«ãSBTãã©ã°ã€ã³ã¯source-Generatorsã«ã«ãŒããã¡ã€ã«åŠçæ©èœãè¿œå ããŸãã
éåžžãã«ãŒãã«åºã¥ããŠ2ã€ã®äž»èŠãªã¢ãŒãã£ãã¡ã¯ããäœæãããŸã-ãã¡ã€ã«target / scala-2.11 / routes / main / router / Routes.scalaããã³target / scala-2.11 / routes / main / controllers / ReverseRoutes.scalaã Routesã¯ã©ã¹ã¯ãçä¿¡èŠæ±ãã«ãŒãã£ã³ã°ããããã«äœ¿çšãããŸãã ReverseRoutesã¯ãã³ã³ãããŒã©ãŒã³ãŒããããšã³ããã€ã³ããåŒã³åºãããšã³ããã€ã³ãã®ååã§è¡šç€ºããããã«äœ¿çšãããŸãã äžèšãäŸã§èª¬æããŸãããã
conf /ã«ãŒãGET /test/:strParam @controllers.HomeController.index(strParam)
ããã§ããã©ã¡ãŒã¿ãŒåããããšã³ããã€ã³ãã宣èšããHomeController.indexã¡ãœããã«ãããããŸãã ãã®ãã¡ã€ã«ãã³ã³ãã€ã«ãããšã次ã®Scalaã³ãŒããçæãããŸãã
ã¿ãŒã²ãã/ scala-2.11 /ã«ãŒã/ã¡ã€ã³/ã«ãŒã¿ãŒ/ Routes.scala class Routes( override val errorHandler: play.api.http.HttpErrorHandler, HomeController_0: javax.inject.Provider[controllers.HomeController], val prefix: String ) extends GeneratedRouter { ... private[this] lazy val controllers_HomeController_index0_route = Route("GET", PathPattern(List( StaticPart(this.prefix), StaticPart(this.defaultPrefix), StaticPart("test/"), DynamicPart("strParam", """[^/]+""",true) )) ) private[this] lazy val controllers_HomeController_index0_invoker = createInvoker( HomeController_0.get.index(fakeValue[String]),HandlerDef( this.getClass.getClassLoader, "router","controllers.HomeController","index", Seq(classOf[String]),"GET","""""",this.prefix + """test/""" + "$" + """strParam<[^/]+>""") ) def routes: PartialFunction[RequestHeader, Handler] = { case controllers_HomeController_index0_route(params) => call(params.fromPath[String]("strParam", None)) { (strParam) => controllers_HomeController_index0_invoker.call(HomeController_0.get.index(strParam)) } } }
ãã®ã¯ã©ã¹ã¯ãçä¿¡èŠæ±ãã«ãŒãã£ã³ã°ããŸãã åŒæ°ãšããŠãã³ã³ãããŒã©ãŒïŒããæ£ç¢ºã«ã¯ã€ã³ãžã§ã¯ã¿ãŒã§ãããå¿
é ã§ã¯ãããŸããïŒãžã®åç
§ãšãæ§æãã¡ã€ã«ã§æ§æããããã¹URLãã¬ãã£ãã¯ã¹ãæž¡ãããŸãã ããã«ãã®ã¯ã©ã¹ã§ã¯ãã«ãŒãã£ã³ã°ãã¹ã¯
controllers_HomeController_index0_routeã宣èšãããŠããŸãã ãã¹ã¯ã¯ãHTTPåè©ãšã«ãŒããã¿ãŒã³ã§æ§æãããŸãã åŸè
ã¯ãããããããã¹URLèŠçŽ ã«å¯Ÿå¿ããéšåã§æ§æãããŸãã StaticPartã¯ãã¹ã®äžå€éšåã®ãã¹ã¯ãå®çŸ©ããDynamicPartã¯ãã©ã¡ãŒã¿ãŒURLã®ãã¿ãŒã³ãèšå®ããŸãã åçä¿¡ãªã¯ãšã¹ãã¯routesé¢æ°ã«åé¡ãããããã§äœ¿çšå¯èœãªãã¹ã¯ïŒãã®å Žåã¯1ã€ïŒã«ãããã³ã°ãããŸãã äžèŽãããã®ãèŠã€ãããªãå Žåãã¯ã©ã€ã¢ã³ãã¯404ãšã©ãŒãåãåããŸãããã以å€ã®å Žåã察å¿ãããã³ãã©ãŒãåŒã³åºãããŸãã ãã®äŸã§ã¯ã1ã€ã®ãã³ãã©ãŒã¯
controllers_HomeController_index0_invokerã§ãã ãã³ãã©ãŒã®åœ¹å²ã«ã¯ãç®çã®ãã©ã¡ãŒã¿ãŒã»ããã䜿çšããŠã³ã³ãããŒã©ãŒã¡ãœãããåŒã³åºãããã®åŒã³åºãã®çµæãå€æããããšãå«ãŸããŸãã
ã¿ãŒã²ãã/ scala-2.11 /ã«ãŒã/ã¡ã€ã³/ã³ã³ãããŒã©ãŒ/ ReverseRoutes.scala package controllers { class ReverseHomeController(_prefix: => String) { ... def index(strParam:String): Call = { import ReverseRouteContext.empty Call("GET", _prefix + { _defaultPrefix } + "test/" + implicitly[PathBindable[String]].unbind("strParam", dynamicString(strParam))) } } }
ãã®ã³ãŒãã«ããã察å¿ããé¢æ°ãä»ããŠãããšãã°ãã¥ãŒã§ãšã³ããã€ã³ãã«ã¢ã¯ã»ã¹ã§ããŸãã
ãã®ãããã«ãŒãèšè¿°ã®åœ¢åŒãå€æŽããã«ã¯ãRoutesãã¡ã€ã«ãžã§ãã¬ãŒã¿ãŒãäœæããã ãã§ãã ãµãŒãã¹ã¯JSONãæäŸãããã¥ãŒãæããªããããReverseRoutesã¯å¿
èŠãããŸããã ãžã§ãã¬ãŒã¿ãæ©èœãããã«ã¯ãé»æºããªã³ã«ããå¿
èŠããããŸãã ãžã§ãã¬ãŒã¿ã®ãœãŒã¹ã³ãŒããå¿
èŠãªåãããžã§ã¯ãã«ã³ããŒããŠãããbuild.sbtã«æ¥ç¶ã§ããŸãã ãã ãããžã§ãã¬ãŒã¿ãŒãSBTã®ãã©ã°ã€ã³ãšããŠèšèšããæ¹ãé©åã§ãã
SBTãã©ã°ã€ã³
SBTãã©ã°ã€ã³ã¯ãããã¥ã¡ã³ãã«åŸ¹åºçã«
èšè¿°ãããŠããŸãã ããã§ãç§ã®æèŠã§ã¯ãäž»èŠãªãã€ã³ãã«èšåããŸãã ãã©ã°ã€ã³ã¯è¿œå æ©èœã®ã»ããã§ãã éåžžããã©ã°ã€ã³ã¯ãããžã§ã¯ãã«æ°ããããŒãè¿œå ããæ¢åã®ããŒãå±éããŸãã ããšãã°ãsourceGeneratorsããŒãæ¡åŒµããå¿
èŠããããŸãã äžéšã®ãã©ã°ã€ã³ã¯ä»ã®ãã©ã°ã€ã³ã«äŸåããå ŽåããããŸããããšãã°ãcom.typesafe.play.sbt-pluginãã©ã°ã€ã³ãããŒã¹ãšããŠäœ¿çšããå¿
èŠãªãã®ã ããå€æŽã§ããŸãã ã€ãŸãããã©ã°ã€ã³ã¯com.typesafe.play.sbt-pluginã«äŸåããŠããŸãã SBTããã©ã°ã€ã³ã®ãã¹ãŠã®äŸåé¢ä¿ãèªåçã«æ¥ç¶ããã«ã¯ã
AutoPluginã§ããå¿
èŠããã
ãŸã ã æåŸã«ãäºææ§ã®åé¡ã®ããããã©ã°ã€ã³ã¯Scala 2.10ã§èšè¿°ãããŠããŸãã
ãã®ãããRAMLãã¡ã€ã«ã«åºã¥ããŠRoutes.scalaãçæããå¿
èŠããããŸãã ãã®ãã¡ã€ã«ãconf / api.ramlãšåŒã³ãŸãã RAML圢åŒã®ããã¥ã¡ã³ããã«ãŒãã£ã³ã°ã«äœ¿çšããã«ã¯ããªã¯ãšã¹ãã®åä¿¡æã«åŒã³åºãå¿
èŠãããã³ã³ãããŒã©ãŒã¡ãœããããšã³ããã€ã³ãããšã«äœããã®æ¹æ³ã§æå®ããå¿
èŠããããŸãã ç§ãã¡ã䜿çšããRAML 0.8ã«ã¯ããã®ãããªæ
å ±ã瀺ãæ段ããªããããããŒãã£ããã¯ãäœæããå¿
èŠããããŸãïŒRAML 1.0ã¯æ³šéã䜿çšããŠãã®åé¡ã解決ããŸãããå·çæç¹ã§ã¯ããã®ããŒãžã§ã³ã®æšæºã¯æªå å·¥ã§ãïŒã åŒã³åºãããã³ã³ãããŒã©ãŒã¡ãœããã«é¢ããæ
å ±ããåãšã³ããã€ã³ãã®æåã®èª¬æè¡ã«è¿œå ããŸãã åç« ã®RAML圢åŒã®äŸã¯æ¬¡ã®ããã«ãªããŸãã
/test/{strParam}: uriParameters: strParam: description: simple parameter type: string required: true example: "some value" get: description: | @controllers.HomeController.index(strParam) responses: 200: body: application/json: schema: !include ./schemas/statements/operations.json example: !include ./examples/statements/operations.json
RAML解æã®è©³çŽ°ã«ã€ããŠã¯èª¬æããŸãã
ãraml.orgã®
ããŒãµãŒã䜿çšã§ãããšããèšããŸãã
ã 解æã®çµæãã«ãŒã«ã®ãªã¹ããååŸããŸã-ãšã³ããã€ã³ãããšã«1ã€ã ã«ãŒã«ã¯ã次ã®ã¯ã©ã¹ã«ãã£ãŠå®çŸ©ãããŸãã
case class Rule(verb: HttpVerb, path: PathPattern, call: HandlerCall, comments: List[Comment] = List())
ãã£ãŒã«ãã®ååãšã¿ã€ãã¯ãããèªäœãç©èªã£ãŠããŸãã ããã§ãã«ãŒã«ããšã«ãRoutes.scalaãã¡ã€ã«ã®routeé¢æ°ã§ãã¹ã¯ããã³ãã©ãŒãããã³ã±ãŒã¹èŠçŽ ãäœæã§ããŸãã ãã®åé¡ã解決ããã«ã¯ãã«ãŒã«ã®ãªã¹ãã«åºã¥ããŠã³ãŒãRoutes.scalaãå«ãè¡ãæåã§çæãããããã¯ããé©çšããŸãã ãã ããPlayéçºè
ã奜ãäžéãªãã·ã§ã³ãéžæããæ¹ãè¯ãã§ãããããã³ãã¬ãŒããšã³ãžã³ã䜿çšããŠãã ããã PW Playã¯
twirl template
engineã䜿çšããŠãããããã䜿çšããŠããŸãã ã«ãŒãé¢æ°ãçæãããã©ã°ã€ã³ã®ãã³ãã¬ãŒãã¯æ¬¡ã®ãšããã§ãã
def routes: PartialFunction[RequestHeader, Handler] = @ob @if(rules.isEmpty) { Map.empty } else {@for((dep, index) <- rules.zipWithIndex){@dep.rule match { case route @ Rule(_, _, _, _) => { case @(routeIdentifier(route, index))(params) => call@(routeBinding(route)) @ob @tupleNames(route) @paramsChecker(route) @(invokerIdentifier(route, index)) .call(@injectedControllerMethodCall(route, dep.ident, x => safeKeyword(x.name)))@cb } }}}@cb
å°ãåããã«ããããã«èŠããŸãããããèŠããšãã¹ãŠãã¯ã£ããããŠããŸãã @ã§å§ãŸãåŒã¯ããã£ã¬ã¯ãã£ããšãã³ãã¬ãŒãå€æ°ã§ãã @obããã³@cbå€æ°ã¯ããããã{and}ã§å±éãããŸãã ãŸããããšãã°ã
@ïŒrouteIdentifierïŒã«ãŒããã€ã³ããã¯ã¹ïŒïŒã¯æ¬¡ã®èŠåã«åŸã£ãŠå±éãããŸãã
def routeIdentifier(route: Rule, index: Int): String = route.call.packageName.replace(".", "_") + "_" + route.call.controller.replace(".", "_") + "_" + route.call.method + index + "_route"
ããã§ãRAMLã«åºã¥ããŠRoutes.scalaãçæããã³ãŒãã®èšè¿°æ¹æ³ãšããããã¢ã»ã³ããªã«æ¥ç¶ããæ¹æ³ãæ確ã«ãªããŸããã ãã©ã°ã€ã³ã®ãœãŒã¹ã³ãŒãã¯
Githubã«ãããŸãã
ä»åŸã®èšç»
ãã©ã°ã€ã³ã«ãããããã¥ã¡ã³ãããµãŒããŒã®ãœãŒã¹ã³ãŒããšããŠäœ¿çšã§ããŸããã ãã ããã³ãŒãçæã§ã¯ãRAMLãã¡ã€ã«ããå
¥æå¯èœãªãã¹ãŠã®æ
å ±ã䜿çšããããã§ã¯ãããŸããã ã€ãŸãããªã¯ãšã¹ããšã¬ã¹ãã³ã¹ã®ã¿ã€ãã«é¢ããæ
å ±ã¯äœ¿çšããŸããã Playã§ã¯ãã³ã³ãããŒã©ãŒã¡ãœããã§ãªã¯ãšã¹ãã®è§£æãšå¿çã®çæãè¡ãããŸããããã®ã³ãŒããèªåçã«çæããå¿
èŠããããŸãã ããã«ãããŒãžã§ã³RAML 1.0ã䜿çšããäºå®ã§ãã
ä»æ¥ã¯ä»¥äžã§ããèŠãŠãããŠããããšãïŒ