
è¯ãäžæ¥ã芪æãªãããã©ããã¢ã³ã
ç§ãã¡ã
pogromããã°ã©ããŒã¯ãæ°ããèšèªXãŸãã¯ãã¬ãŒã ã¯ãŒã¯YãåŠç¿ãããšãã«ãåãåé¡ã«ééããããšãéåžžã«å€ããããŸãã X / Yã®é·æãšçæã瀺ãããšãã§ããŸãããããã»ã©æéã¯ããããŸããã
ç§ã®ä»²éã¯ãã䌌ã質åãããŸããã ãã®çµæãRSSãªãŒããŒãäœæãããšããç°¡åãªèããçãŸããŸããã ããã§ããããã¯ãŒã¯ãXMLããŒãµãŒãããã³ããŒã¿ããŒã¹ãæäœã§ããŸãããã³ãã¬ãŒããšã³ãžã³ãèŠãŠãã ããã ã¯ããããªãã¯æ±ºããŠç¥ããŸããã
ãããã£ãŠãããããã¯ãããã¯ãšã³ãã®
Play Framework 2.2 + Scala + MongoDBã¹ã¿ãã¯ãšãããã³ããšã³ãã®
AngularJS + CoffeeScriptãžã®ãšããµã€ãã£ã³ã°ãªæ
ãå§ãŸããŸãã
TL; DRãããžã§ã¯ãå
šäœã¯ãScalaã§ã¯250ã300è¡ãCSã§ã¯150è¡ã«é
眮ãããŸããã ãŸããããã€ãã®HTMLã
Bitbucketã§å©çšå¯èœãªã³ãŒã
ãããŠãæåã®ç®çã¯è³ªåã§ãããªãJavaã§ã¯ãªãScalaãªã®ã§ããããã ãããŠããªãåãPlayã§ã¯ãªãPlayãªã®ã§ããããïŒ
çãã¯éåžžã«ã·ã³ãã«ã§äž»èгçã§ãã
Scalaã¯ãã³ãŒãã®ããã«ãããé«ãã¬ãã«ã®æœè±¡åãšããå°ãªãã³ãŒããæäŸããŸãã ããããå Žé¢ã§200ã®ã¡ãœãããåããæšæº
ãªã¹ãã®ããã¥ã¡ã³ããèŠããšã...çå£ã«ãèªåã§è©ŠããŠãã ããã
ãã¬ãŒã ã¯ãŒã¯ã®éžæã«é¢ããŠã¯ãLiftã®ç°¡åãªäŸã§ã¯ãlocalhostã§
ã150ããªç§ã®éããŒãžã衚瀺ãããŸããããããã¯ããŒã¿ããŒã¹ã䜿çšããŠããŸããã åæã«ãåããã·ã³ãšåãJVMãã¬ã€ã§ã¯ãçŽ5ã10ããªç§ããããŸããã ããããªããå€åæã¯ããã ãã
ãããŠããã¬ã€ã³ã³ãœãŒã«ã§ããããã
Playãã€ã³ã¹ããŒã«ããŠéå§ããæ¹æ³ã«ã€ããŠã¯ãå
¬åŒããã¥ã¡ã³ãïŒãã¹ãŠã
ãæ°ã«å
¥ãã®IDEã®ãããžã§ã¯ããçæãããŸã§ïŒã«ãã¹ãŠã
å®å
šã«çã蟌ãŸããŠãããããäžéšãèŠéããŠããŸããŸãã
ãªã¯ãšã¹ããã¹
ã¢ããªã±ãŒã·ã§ã³ãè§£æããæãæçœãªæ¹æ³ã¯ãã¯ã©ã€ã¢ã³ãã®èŠæ±ã«åŸãããšã§ãã
ç¹ã«Nettyäžã«æ§ç¯ãããŠããããããã¬ãŒã ã¯ãŒã¯èªäœã«ãããªã¯ãšã¹ãåŠçã®ãã©ãã¯ããã¯ã¹ãã¹ãããããæ¹ãè¯ãã§ãããã ãã¶ãäžåœãžã
åå·ã¯å°å·ã§å§ãŸããããPlayã®ã¢ããªã±ãŒã·ã§ã³ã¯ã«ãŒãã£ã³ã°ã§å§ãŸããŸããããã¯ã
conf /ã«ãŒã ïŒã«ãŒã
ïŒãã®ãã¡ã€ã«ã¯ããã¹ãŠã®ã¢ããªã±ãŒã·ã§ã³ã«ãŒããå®çŸ©ããŸãïŒåªå
é äœã®é«ãã«ãŒããæåïŒ
ïŒ~~~~
ïŒãã¥ãŒã¹ãå
¥æ
GET / news controllers.NewsController.newsïŒtagïŒStringïŒ= ""ãPubDateïŒIntïŒ=ïŒSystem.currentTimeMillisïŒïŒ/ 1000ïŒ.toIntïŒ
ïŒè§£æãã¥ãŒã¹
GET / parse controllers.NewsController.parseRSS
ïŒã¿ã°ãååŸ
GET / tags controllers.TagsController.tags
ïŒéçãªãœãŒã¹ã/ãããªãã¯ãã©ã«ããŒãã/ã¢ã»ããã®URLãã¹ã«ãããããŸã
GET / asset / * file controllers.Assets.atïŒpath = "/ public"ãfileïŒ
ïŒããŒã ããŒãž
GET / controllers.Application.index
ããŒãžã³ã®ããŒãžã³ïŒ
æå®ãããã¡ãœããã«æž¡ãããåŒæ°ã«ããã©ã«ãå€ãèšå®ããå¯èœæ§ã«å ããŠãåŒãæå®ã§ããããšãå¥ã«åŒ·èª¿ããããšæããŸãã ããšãã°ãçŸåšã®ã¿ã€ã ã¹ã¿ã³ããååŸããŸãã
ã¡ãªã¿ã«ãPlayã®ã«ãŒãã£ã³ã°ã¯éåžžã«æ©èœçã§ããªã¯ãšã¹ããåŠçãããšãã®æ£èŠè¡šçŸãŸã§ã§ãã
ãã±ããããã¬ãŒã³ãïŒ
ã¿ã€ãã«ããæšæž¬ã§ããããã«ãã¹ããŒãªãŒã¯ã³ã³ãããŒã©ãŒã§ç¶ããŸãã Playã§ã¯ããŠãŒã¶ãŒã³ã³ãããŒã©ãŒã¯
controllers
ããã±ãŒãžã«å«ãŸãã
Controller
ãã¬ã€ãã䜿çšããã«ãŒãã£ã³ã°ã«åŸã£ãŠãŠãŒã¶ãŒãªã¯ãšã¹ããåãå
¥ããŠå¿çããã¡ãœãããæã€ãªããžã§ã¯ãã§ãã
ã¢ããªã±ãŒã·ã§ã³ã¯AJAXãä»ããŠãµãŒããŒããããŒã¿ãåä¿¡ãããããã¡ã€ã³ããŒãžãã¬ã³ããªã³ã°ããããã®ã³ã³ãããŒã©ãŒã¯æ£æ¹åœ¢ãšããŠç°¡åã§ãããHTML / CS / JSã¹ã¯ãªããã®èªã¿èŸŒã¿ã«ã®ã¿å¿
èŠã§ãã
å
¥åããã«20è¡ package controllers import play.api.mvc._ object Application extends Controller { def index = Action { Ok(views.html.index()) } }
Ok
ã¯ãããŒãžã®ããããŒã𿬿ãå«ã
play.api.mvc.SimpleResult
ã€ã³ã¹ã¿ã³ã¹ãè¿ããŸãã æãæ³šææ·±ãäººãæšæž¬ããããã«ããµãŒããŒããã®å¿çã¯200
OK
ãŸãã
ããã
ã¢ããªã±ãŒã·ã§ã³å
šäœã®å®å
šãªã³ã³ãããŒã©ãŒã20è¡ã«åãŸãå Žåãã«ãŒãã«ã§æžããŠããå¯èœæ§ãéåžžã«é«ããªããŸãã
ããã§ã¯ãAJAXã¯ã©ã€ã¢ã³ãã«ãã¥ãŒã¹ãåä¿¡ãããªã¯ãšã¹ããäžããæè¯ã®æ¹æ³ã¯äœã§ããïŒ ãããJSONã
NewsController
ã
NewsController
ãªããžã§ã¯ãNewsController package controllers import play.api.mvc._ import scala.concurrent._ import models.News import play.api.libs.concurrent.Execution.Implicits.defaultContext import models.parsers.Parser import com.mongodb.casbah.Imports._ object NewsController extends Controller { def news(tag: String, pubDate: Int) = Action.async { val futureNews = Future { try { News asJson News.allNews(tag, pubDate) } catch { case e: MongoException => throw e } } futureNews.map { news => Ok(news).as("application/json") }.recover { case e: MongoException => InternalServerError("{error: 'DB Error: " + e.getMessage + "'}").as("application/json") } } def parseRSS = Action.async { val futureParse = scala.concurrent.Future { try { Parser.downloadItems(News.addNews(_)) News asJson News.allNews() } catch { case e: Exception => throw e } } futureParse.map(newsJson => Ok(newsJson).as("application/json")).recover { case e: MongoException => InternalServerError("{error: 'DB Error: " + e.getMessage + "'}").as("application/json") case e: Exception => InternalServerError("{error: 'Parse Error: " + e.getMessage + "'}").as("application/json") } } }
Future
Async
ã ããã§åããŠè峿·±ããã®ã«ãªããŸãã
ãŸããPlayã¯éåæã§ãããååãšããŠãã¹ããªãŒã ãæäœããå¿
èŠã¯ãŸã£ãããããŸããã ããããããŒã¿ããŒã¹ãžã®ã¢ã¯ã»ã¹ããã¡ã€ã«ããã®ããŒã¿ã®èªã¿åãããŸãã¯å¥ã®é
ãI / Oæé ãå®è¡
ããããã«æ°å€Ïã
ç·æ¥ã«èšç®ããå¿
èŠ
ãããå Žåã
Future
ãå©ãã«ãªããŸããããã«ãããã¡ã€ã³ã¹ããªãŒã ããããã¯ããã«éåæã§æäœãå®è¡ã§ããŸãã
Future
ã¯å®è¡ã«å¥ã®ã³ã³ããã¹ãã䜿çšãããããã¹ã¬ããã«ã€ããŠå¿é
ããå¿
èŠã¯ãããŸããã
颿°ã¯
Future[SimpleResult]
ã§ã¯ãªã
Future[SimpleResult]
è¿ãããã«ãªã£ãããã
ActionBuilder
ãã¬ã€ãã®
async
ã¡ãœããã
ActionBuilder
ïŒããã¯
Action
ãªããžã§ã¯ãã䜿çšããŸãïŒ
颚æ¯
ãã®éåæã®æªå€¢ããããŠãç§ãã¡ã®ç®ãåŒããã³ãã¬ãŒããèŠãŠã¿ãŸãããã Playã¯éåžžã®HTMLã§åäœããæ©èœãæäŸããŸãã Scalaã³ãŒããæ¿å
¥ããéåžžã®HTMLã ãã³ãã¬ãŒãã¯èªåçã«ãœãŒã¹ãã¡ã€ã«ã«ã³ã³ãã€ã«ããããã©ã¡ãŒã¿ãæž¡ããããä»ã®ãã³ãã¬ãŒããæ¥ç¶ïŒåŒã³åºãïŒã§ããéåžžã®æ©èœã§ãã ãšããã§ãå€ãã®äººã¯ãéåžžã«HTMLãã³ãŒãã«ã³ã³ãã€ã«ããæéãæ¯èŒçé
ããããæ°ãããã³ãã¬ãŒããšã³ãžã³ãå«ã£ãŠããŸããã å
æ°ã§ãã
index.scala.html <!DOCTYPE html> <html> <head> <title> playRSS </title> <link rel="shortcut icon" href='@routes.Assets.at("images/favicon.png")' type="image/png"> <link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css"/> <link rel="stylesheet" href='@routes.Assets.at("stylesheets/main.css")'> @helper.requireJs(core = routes.Assets.at("javascripts/require.js").url, module = routes.Assets.at("javascripts/main").url) </head> <body> <div class="container" id="container" ng-controller="MainCtrl"> <a href="/"><h1>playRSS</h1></a> @control() <div class="row"> <div class="col-lg-12"> @news() </div> </div> </div> </body> </html>
ãœãŒã¹ãããããããã«ãã¡ãã£ãšããéæ³ã§ãã
@helper
ã¯ããã¬ãŒã ã¯ãŒã¯èªäœãæäŸãã
@helper
æ¥ç¶ããããã³ããšã³ããåæåãããmain.jsãžã®ãã¹ã瀺ããŸãã
@news()
ããã³
@control()
ã¯ãããããnews.scala.htmlããã³control.scala.htmlãã³ãã¬ãŒãã§ãã 颿°ãå®è¡ããçŸåšã®ãã³ãã¬ãŒãå
ã«çµæã衚瀺ããŸãã ããã
ãããŠãŸã
if / elseãªã©ã®ã«ãŒãã䜿çšã§ããŸãã 詳现ãªããã¥ã¡ã³ãããããŸã
ã«ã¹ãå±±
ããŒã¿ããŒã¹ã§ã®äœæ¥ãç¶ããŸãããã ç§ã®å ŽåãMongoãéžæãããŸããã
ç§ã¯ããŒãã«ãäœæããã®ãé¢åã ãã:)Casbahã¯ã麺æ£ã§MongoDBãæäœããããã®
å
¬åŒãã©ã€ããŒã§ãã ãã®å©ç¹ã¯ãã·ã³ãã«ããšæ©èœæ§ãåæã«åããŠããããšã§ãã ãããŠãäž»ãªæ¬ ç¹ã¯æåŸã«èæ
®ãããŸãã
ãã©ã€ããŒã¯ããªãåçŽã«æ¥ç¶ãããŠããŸãã
libraryDependencies
å
ã®libraryDependenciesã«æ¬¡ã®è¡ã远å ããŸãã
"org.mongodb" %% "casbah" % "2.6.3"
- ã³ãŒãã«è¿œå ããŸãã
import com.mongodb.casbah.Imports._
- ãããžã§ã¯ãèªäœã®èµ·åæã«åçãããšãåçž®ããŸã
- ???
- å©ç
ãããŠãã³ãŒãã«ã€ããŠå°ãã ãªãŒããŒã¯è€éã§ã¯ãªãã®ã§ãMongoDBããè²§ãã人ã
ã®ã³ã¬ã¯ã·ã§ã³ã«é
åžãããªããžã§ã¯ããäœæãããŸããã ãããŸã§ã®ãšãããDAOãŸãã¯DIããã§ã³ã¹ããæ£ããèšèã¯åã«äžèŠã§ãã
ãªããžã§ã¯ãããŒã¿ããŒã¹ package models import com.mongodb.casbah.Imports._ import play.api.Play object Database { private val db = MongoClient( Play.current.configuration.getString("mongo.host").get, Play.current.configuration.getInt("mongo.port").get). getDB(Play.current.configuration.getString("mongo.db").get) def collection(collectionName:String) = db(collectionName) def clearCollection(collectionName:String) = db(collectionName).remove(MongoDBObject()) }
ããŒãžã³ã®ããŒãžã³ïŒ
Scalaã§ã¯ããªããžã§ã¯ãã¯å®éã«ã¯ã·ã³ã°ã«ããŒã³ã§ãã éå±ã¢ãŒããæå¹ã«ãããšãéçã¡ãœãããæã€å¿åã¯ã©ã¹ãäœæãããã€ã³ã¹ã¿ã³ã¹åãããŸãïŒJava / JVMãã¥ãŒã§ïŒã ãã®ããããªããžã§ã¯ããäœæããããšæ¥ç¶ã確ç«ãããã¢ããªã±ãŒã·ã§ã³ã®äœæ¥ãµã€ã¯ã«å
šäœã§å©çšå¯èœã«ãªããŸãã
ä»ãããScalaãšCasbahã®ããŒã¹ãšã®é£æºãå®èšŒãããšãã§ãã
ãªããžã§ã¯ããã¥ãŒã¹ case class News(val id: String = "0", val title: String, val link: String, val content: String, val tags: Seq[String], val pubDate: Long) /** * News object allows to operate with news in database. Companion object for News class */ object News { .... def addNews(news: News) = { val toInsert = MongoDBObject("title" -> news.title, "content" -> news.content, "link" -> news.link, "tags" -> news.tags, "pubDate" -> news.pubDate) try { col.insert(toInsert) } catch { case e: Exception => } } .... def getNews(filter: MongoDBObject, sort: MongoDBObject = MongoDBObject("pubDate" -> -1), limit: Int = newsLimit): Array[News] = { try { col.find(filter). sort(sort). limit(limit). map((o: DBObject) => { new News( id = o.as[ObjectId]("_id").toString, title = o.as[String]("title"), link = o.as[String]("link"), content = o.as[String]("content"), tags = o.as[MongoDBList]("tags").map(_.toString), pubDate = o.as[Long]("pubDate")) }).toArray } catch { case e: MongoException => throw e } } }
MongoDBãAPIãããã³ã±ãŒã¹ã¯ã©ã¹ã®Newsã€ã³ã¹ã¿ã³ã¹ã®ã€ã³ã¹ã¿ã³ã¹ã®ç°¡åãªå
å¡«ãæ±ã£ããã¹ãŠã®äººã«ç²ŸéããŠããŸãã ãããŸã§ã®ãšããããã¹ãŠãåºæ¬ã§ãã ã§ãå€ãããã
ãã£ãšé¢çœããã®ãå¿
èŠã§ãã
éçŽã¯ã©ãã§ããïŒ
ã¿ã°ãåŒãåºã case class Tags(name: String, total: Int) /** * Tags object allows to operate with tags in DB */ object Tags { private val col: MongoCollection = Database.collection("news") def allTags: Array[Tags] = { val group = MongoDBObject("$group" -> MongoDBObject( "_id" -> "$tags", "total" -> MongoDBObject("$sum" -> 1) )) val sort = MongoDBObject("$sort" -> MongoDBObject("total"-> -1)) try { col.aggregate(group,sort).results.map((o: DBObject) => { val name = o.as[MongoDBList]("_id").toSeq.mkString(", ") val total = o.as[Int]("total") Tags(name, total) }).toArray } catch { case e: MongoException => throw e } } }
.aggregate
䜿çšãããšã
.aggregate
ãªãã§äžæè°ãªããšãã§ããŸãã ãŸããScalaã§ã®äœæ¥ã®ååã¯ãã³ã³ãœãŒã«ã®å Žåãšåãã§ãã ã³ã³ãã ãã§åºåãããäžçš®ã®ãã€ãã©ã€ã³ã ã¿ã°ã§ã°ã«ãŒãåãããåèšã§åãåèšããå
šäœããœãŒãããŸããã çŽ æŽãããã
ãšããã§ã
ã«ã¹ãã¯èŠå¡ã§ãJSON-XMLã䜿çšããŠããŸã
決ããŠãããããªã
ããªãã倱æãããªã
éçã«åä»ããããèšèªã®å Žåããã®å Žåã®XML / JSONã®æäœã¯ããã®ããã«èŠããããã§ãã çãããã»ã©çãã
å®éãScalaã§ã®XMLè§£æã¯ïŒJavaã®å€§èŠæš¡ãªãã¡ã¯ããªãŒã®åŸã®ïŒç§ã®ç®ã楜ããŸããŠããŸãã
XMLããŒãµãŒ package models.parsers import scala.xml._ import models.News import java.util.Locale import java.text.{SimpleDateFormat, ParseException} import java.text._ import play.api.Play import collection.JavaConversions._ object Parser { val urls = try { Play.current.configuration.getStringList("rss.urls").map(_.toList).getOrElse(List()) } catch { case e: Throwable => List() } def downloadItems(cb: (News) => Unit) = { urls.foreach { (url: String) => try { parseItem(XML.load(url)).foreach(cb(_)) } catch { case e: Exception => throw e } } } def parseDateTime(s: String): Long = { try { new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.ENGLISH).parse(s).getTime / 1000 } catch { case e: ParseException => 0 } } def parseItem(xml: Elem): List[News] = (xml \\ "item").map(buildNews(_)).toList def buildNews(node: Node) = new News( title = (node \\ "title").text, link = (node \\ "link").text, content = (node \\ "description").text, pubDate = parseDateTime((node \\ "pubDate").text), tags = Seq((node \\ "category").text)) }
åæãã
æåã«ã\ãŸãã¯\\ãšãã圢åŒã®ååã®ã¡ãœããã¯ãæ··ä¹±ç¶æ
ã«é¥ããŸãã ãã ããJavaããBigIntegerãåŒã³åºãå Žåãããã¯ããçšåºŠæå³ããããŸãã
JSONã¯ã©ãã§ããïŒ Scalaã®ãã€ãã£ãJSONã¯ããããŸã§ã®ãšãã䞻芳çãªãã®ã§ã¯ãããŸããã é
ããŠæãã
å°é£ãªææã«ã¯ãPlayãš
play.api.libs.json
ããã±ãŒãžããã®ãã®æžã蟌ã¿/èªã¿åãã
play.api.libs.json
ãŸãã PHP 5.4ã®
JsonSerializable
ã€ã³ã¿ãŒãã§ã€ã¹ãç¥ã£ãŠãã
JsonSerializable
ãŸããïŒ Playã®æ¹ãç°¡åã§ãïŒ
JSONæžã蟌㿠case class News(val id: String = "0", val title: String, val link: String, val content: String, val tags: Seq[String], val pubDate: Long) /** * News object allows to operate with news in database. Companion object for News class */ object News { implicit def newsWrites = Json.writes[News] def asJson(src: Array[News]) = { Json.stringify(Json.toJson(src)) } }
åçŽãªã·ãªã¢ã«åã®å Žåã®1è¡ã®ã¡ãœãã
someObjectWrites
ã¯ããã¹ãŠã®åé¡ãåãé€ããŸãã Scalaã®æé»çãªå€æã¯ãå®éã«äœ¿çšããã匷åã§äŸ¿å©ãªããŒã«ã§ãã
ããããããã¯éåžžã«å¹³å¡ãªã±ãŒã¹ã§ãã ç¹å¥ãªãã®ãè€éãªãã®ãå¿
èŠãªå Žåã¯ã
æ©èœäž»çŸ©ãšçµã¿åããã圹ç«ã¡ãŸãã
ãšããéããŠæãž
ãŠãŒã¶ãŒãéå±ããã¹ã¯ãªããã«ãã£ãŠãµãŒããŒã«éä¿¡ãããèŠæ±ãžã®å¿çãåŸ
ã£ãŠããé...åŸ
ã£ãŠãã ããã å¥ã®ããã³ããšã³ãã
çŽæã©ãããCoffeeScriptãšAngularJSã䜿çšãããŸããã å®çšŒåç°å¢ã§ãã®ãã³ãã«ã®äœ¿çšãéå§ããåŸããŠãŒã¶ãŒã€ã³ã¿ãŒãã§ã€ã¹ãéçºããéã®èŠçã®æ°ã¯78.5ïŒ
æžå°ããŸããã ã³ãŒãã®éã奜ãã§ãã
ãã®çç±ããããããã®ã¹ã¿ã€ãªãã·ã¥ã§ãã¡ãã·ã§ããã«ãªè¥è
åããã¯ãããžãŒãèªè
ã«äœ¿çšããããšã«ããŸããã ãŸããç§ã®éžæãããã¬ãŒã ã¯ãŒã¯ã«ã¯CoffeeScriptãšLESSã³ã³ãã€ã©ãæèŒãããŠããããã§ãã
å®éãçµéšè±å¯ãªéçºè
ã¯æ°ããè峿·±ãããšãäœãåŠã°ãªãã®ã§ãè峿·±ãããªãã¯ãããã€ã玹ä»ããŸãã
å€ãã®å Žåãè§åºŠã³ã³ãããŒã©ãŒéã§ããŒã¿ã亀æããå¿
èŠããããŸãã ãããŠãæŽç·Žããã玳士ã ããè¡ããªããã®ïŒlocalStorageãžã®æžã蟌ã¿ãªã©ïŒ...
ãããŠããéããŸãã
ãµãŒãã¹ãäœæããå¿
èŠãªã³ã³ãããŒã©ãŒã«å®è£
ããã ãã§ååã§ãçºè¡šãã define ["angular","ngInfinite"],(angular,infiniteScroll) -> newsModule = angular.module("News", ['infinite-scroll']) newsModule.factory 'broadcastService', ["$rootScope", ($rootScope) -> broadcastService = message: {}, broadcast: (sub, msg)-> if typeof msg == "number" then msg = {} this.message[sub] = angular.copy msg $rootScope.$broadcast(sub) ] newsModule
éããŸã define ["app/NewsModule"], (newsModule)-> newsModule.controller "PanelCtrl", ["$scope", "$http", "broadcastService", ($scope, $http, broadcastService)-> $scope.loadByTag = (tag) -> if tag.active tag.active = false broadcastService.broadcast("loadAll",0) else broadcastService.broadcast("loadByTag",tag.name) ]
ååŸããŸã define ["app/NewsModule","url"], (newsModule,urlParser)-> newsModule.controller "NewsCtrl", ["$scope", "$http", "broadcastService", ($scope, $http, broadcastService)->
è§åºŠã§
ãµãŒãã¹ã¯ã·ã³ã°ã«ãã³ã§ãã ãããã£ãŠãã€ã³ã¹ã¿ã³ã¹ãäœæããã«ã¡ãã»ãŒãžãããåãã§ããŸãã
ãã¹ãŠæ¥ã
ãã®ãããªæ··intoãšããè
žå
ãžã®è¡ãåž°ãã®æ
ã®åŸãèŠçŽãã䟡å€ããããŸãã
é·æãšçæãèŽåœçã§ã¯ãªãã誰ããèªåã§éžæããå¿
èŠããããŸãã 貚ç©ãæ œå¹ããã®ã§ã¯ãªããé©åãªå Žæã§ããŒã«ã䜿çšããŸããïŒ
奜ãã ã£ãïŒ- Javaã®åã®ç°¡æœãªScalaã éçã«åä»ããããèšèªã®å Žåãã³ãŒããå°ããããªããã³ã³ãã€ã«æã«ãšã©ãŒããã£ãããããŸãã ãã¹ããªã©ã«ã€ããŠè¿°ã¹ãŠããããšãããã³åçåä»ãèšèªã¯ããã®ç¹ã§å£ã£ãŠããŸãã
- ãã¬ãŒã ã¯ãŒã¯èªäœã®æ©èœãå€ãã®ãœãªã¥ãŒã·ã§ã³ãæäŸããŸãããç¹å®ã®æ§é ãã³ãŒãã®èšè¿°æ¹æ³ã匷å¶ããŸããã
æ°ã«å
¥ããªãã£ãïŒ- ããã«ããããããã倿ŽããããœãŒã¹ãçµ¶ããåã³ã³ãã€ã«ãããããããããæŽæ°ã¯ãŒã¯ãããŒã¯ãã¡ããšæ©èœããŸãã èŽåœçã§ã¯ãªãããæèã®é£è¡ãé
ããã
- ãã¬ãŒã ã¯ãŒã¯ã®é¢šã®åé¡ïŒ\\ vs /ïŒãšJVMã¯ãWinã·ã¹ãã ã§ã³ã³ãã€ã«ããã³å®è¡äžã®ã¢ããªã±ãŒã·ã§ã³ãå®å
šã«å®è¡ããããšãèš±å¯ããŸããã éçºã¢ãŒãã§ã®ã¿ã ãããŠãããã§ã¯ç¹ã«ããã©ãŒãã³ã¹ã¯æž¬å®ãããŸããã 幞ããªããšã«ãããã€ãã®nixãµãŒããŒãæå
ã«ãããŸã
- ãã¹ãã«ãã°ã€ã³ããŸããã ãã¬ãŒã§ã®ã¯ã€ã«ãã¡ã¢ãªãŒãªãŒã¯ãåå ãšãããŠããŸãã ãŸããç§ã¯ãã§ã«ãããéžãã§ããŸãã
ãŸããéçºæã«ã¯ãFutureã䜿çšããŠãããã¯æäœãæäœããéã«æ³šæããå¿
èŠããããŸãã ãã ãã1ã€ã ããããŸãã ã¡ã€ã³ã®å®è¡ã¹ã¬ããããããã¯ãããªããšããäºå®ã«ãããããããå¥ã®ã¹ã¬ããã¯ãããã¯ãããŸãã ã¹ã¬ãããååã«ãããç«¶åãããªã¯ãšã¹ããããŸãå€ããªãå Žåã¯è¯ãããšã§ãã ããããïŒ ãã®å ŽåãPlayéçºè
ã¯ãåãããŒã¿ããŒã¹ã«å¯ŸããŠéåæãã©ã€ããŒã䜿çšããããšããå§ãããŸãã ããšãã°ãCasbahã§ã¯ãªãReactiveMongoã ãŸãã¯ãå°ãªããšãã¢ã¯ã¿ãŒãšã¹ã¬ããããŒã«ãæ§æããŸãã ããããããã¯å
šãç°ãªã話ã§ã...
ãæž
èŽããããšãããããŸããã
PS
ãã®èœæžããå°ãèŠããå Žåããã
ã«Bitbucketã®
ãªããžããªããã
ãŸã ã