SlideShare una empresa de Scribd logo
1 de 36
Descargar para leer sin conexión
Ruby
Play
2.0
       X    On
           Rails

               by @danicuki
Documentation
http://www.playframework.com/documentation/   http://guides.rubyonrails.org/
Installing

$   apt-get install java         $	
  apt-­‐get	
  install	
  ruby
$   wget play-2.1.0.zip          $	
  apt-­‐get	
  install	
  rubygems
$   unzip play-2.1.0.zip         $	
  gem	
  install	
  rails
$   export
    PATH=$PATH:/pathToPlay



http://www.playframework.com/
documentation/2.1.0/Installing
First App


$ play new myapp     $	
  rails	
  new	
  myapp
Project Structure
app/                      app/
 ! assets                  ! assets
     ! stylesheets             ! stylesheets
     ! javascripts             ! javascripts
 ! controllers             ! controllers
 ! models                  ! helpers
 ! views                   ! mailers
conf/                      ! models
 ! application.conf        ! views
 ! routes                 config/
public/                    ! application.rb
project                    ! routes.rb
 ! build.properties        ! database.yml
 ! Build.scala            config.ru
 ! plugins.sbt            db
lib/                      GemFile
logs/                     lib/
target/                   log/
                          public/
 ! scala-2.10.0           script/
test/                     test/
                          tmp/
                          vendor/
Console
Dependencies
Maven
project/Build.scala
val appDependencies = Seq(
  "postgresql" % "postgresql" % "8.4-702.jdbc4"
  "org.mockito" % "mockito-all" % "1.8.5" % "test"
)

RubyGems
Gemfile
gem "mysql2"
group :test do
  gem "webmock"
end
Dependencies Support
       429.000 jars
     mvnrepository.com




       52,468 gems
      rubygems.org
Views Templates
STE    (Scala Template Engine)

@(title: String)(content: Html)
<title>
  @Messages("site.title") - @title
</title>
@{(video  "title")(0).text}


ERB      (Embedded Ruby)

<title>
	
  	
  <%=	
  t("site.title")	
  %>	
  -­‐	
  <%=	
  yield(:title)	
  %>
</title>
<%=	
  video['title']	
  %>
js / css
<link rel="stylesheet" href="@routes.Assets.at("stylesheets/grid.css")">
<link rel="stylesheet" href="@routes.Assets.at("stylesheets/style.css")">
<link rel="stylesheet" href="@routes.Assets.at("stylesheets/galleriffic.css")">
<script src="@routes.Assets.at("javascripts/applicaton.js")" type="text/javascript" />
<script src="@routes.Assets.at("javascripts/jquery.js")" type="text/javascript" />




 <%=	
  javascript_include_tag	
  :all,	
  :cache	
  =>	
  true	
  %>	
  
 <%=	
  stylesheet_link_tag	
  :all,	
  :cache	
  =>	
  true	
  %>
Links
<li class="menu">
  <a href="@routes.Application.cantora">@Messages("site.singer")</a>
</li>




 <li	
  class="menu">
 	
  	
  <%=	
  link_to	
  "#{t('site.singer')}",	
  {:controller	
  =>	
  "cantora"}	
  %>
 </li>
Routes
GET     /cantora         controllers.Application.cantora
GET     /musicas         controllers.Application.music
GET     /agenda          controllers.Application.shows
GET     /novidades       controllers.Application.news

GET   /clients/:id         controllers.Clients.show(id: Long)




map.connect	
  ':controller/:action/:id'
Controllers
def   cantora = Action { implicit request =>; Ok(views.html.cantora()) }
def   music = Action { implicit request =>; Ok(views.html.music()) }
def   shows = Action { implicit request => Ok(views.html.shows()) }
def   news = Action { implicit request => Ok(views.html.news()) }

/app/views/[method_name].scala.html



class	
  CantoraController	
  <	
  ApplicationController
        def	
  index
	
  	
  end
end
class	
  NewsController	
  <	
  ApplicationController
	
   def	
  index
	
   end
end
/app/views/[controller_name]/index.erb.html
Databases
conf/application.conf:

db.default.driver=com.mysql.jdbc.Driver
db.default.url="jdbc:mysql://localhost/playdb"
db.default.user=playdbuser
db.default.pass="a strong password"




config/database.yml:

development:
	
  	
  adapter:	
  mysql2
	
  	
  database:	
  blog_development
	
  	
  username:	
  root
	
  	
  password:
SQL API:                          Databases
val countries = SQL("Select name,population from Country")().collect {
  case Row("France", _) => France()
  case Row(name:String, pop:Int) if(pop > 1000000) => BigCountry(name)
  case Row(name:String, _) => SmallCountry(name)
}

val result: Int =
  SQL("delete from City where id = {id}").on(“id” -> 99).executeUpdate()

Active	
  Record:

Country.all.map	
  do	
  |c|
	
  	
  if	
  (c.name	
  ==	
  “France”)
	
  	
  	
  	
  France.new
	
  	
  else	
  if	
  (c.pop	
  >	
  1000000)    Country.delete(99)
	
  	
  	
  	
  BigCountry.new(c.name)
	
  	
  else
	
  	
  	
  	
  SmallCountry.new(c.name)
	
  	
  end
end
Databases
                                                OGH
                              (Old Good Hibernate)


Active	
  Record:

Country.all.map	
  do	
  |c|
	
  	
  if	
  (c.name	
  ==	
  “France”)
	
  	
  	
  	
  France.new
	
  	
  else	
  if	
  (c.pop	
  >	
  1000000)         Country.delete(99)
	
  	
  	
  	
  BigCountry.new(c.name)
	
  	
  else
	
  	
  	
  	
  SmallCountry.new(c.name)
	
  	
  end
end
Migrations / Evolutions
# --- !Ups
CREATE TABLE Users (
    id bigint(20) NOT NULL AUTO_INCREMENT,
    email varchar(255) NOT NULL,
    password varchar(255) NOT NULL,
    PRIMARY KEY (id)
);

# --- !Downs                                                               run: AUTOMATIC!
DROP TABLE Users;                                  conf/evolutions/{database name}/{#}.sql


class	
  CreateUsers	
  <	
  ActiveRecord::Migration
	
  	
  def	
  up
	
  	
  	
  	
  create_table	
  :users	
  do	
  |t|
	
  	
  	
  	
  	
  	
  t.string	
  :email
	
  	
  	
  	
  	
  	
  t.string	
  :password
	
  	
  	
  	
  	
  	
  t.timestamps
	
  	
  	
  	
  end
	
  	
  end
	
  	
  def	
  down
	
  	
  	
  	
  drop_table	
  :users                                  run:	
  rake	
  db:migrate
	
  	
  end                                         db/migrate/{timestamp}_create_users.rb
end
Web Services
def videos = Action { implicit request =>
  Async {
    val uri = "http://gdata.youtube.com/feed.xml"
    WS.url(uri).get().map { response =>
      Ok(views.html.videos(response.xml  "entry"))
    }
  }
}



class	
  VideosController	
  <	
  ApplicationController
	
  	
  def	
  index
	
  	
  	
  	
  uri	
  =	
  "http://gdata.youtube.com/feed.xml"
	
  	
  	
  	
  video_feed	
  =	
  RestClient.get(uri)
	
  	
  	
  	
  @videos	
  =	
  Hash.from_xml(video_feed)['feed']['entry']
	
  	
  end
end
XML
Ok(views.html.videos(response.xml  "entry"))

@(videos: scala.xml.NodeSeq)

@videos.map { video =>
    <a href="@{ ((video  "group")  "player")(0).attribute("url")}">
       @{(video  "title")(0).text}
    </a>
}


@videos	
  =	
  Hash.from_xml(video_feed)['feed']['entry']

<%	
  @videos.each	
  do	
  |video|	
  %>
	
  	
  	
  	
  	
  <a	
  href="<%=	
  video['group']['player']['url']	
  %>">
	
  	
  	
  	
  	
  	
  	
  	
  	
  <%=	
  video['title']	
  %>
	
  	
  	
  	
  	
  </a>
<%	
  end	
  %>
WS.url("https://graph.facebook.com/daniella.alcarpe/albums").get().map	
  {	
  response	
  =>
	
  	
  	
  	
  val	
  albuns	
  =	
  (response.json	
  	
  "data").
	
  	
  	
  	
  	
  	
  as[List[JsObject]].filter(album	
  =>
	
  	
  	
  	
  	
  	
  	
  	
  (album	
  	
  "description").toString.equals(""*""))
	
  
	
  	
  	
  	
  val	
  photos	
  =	
  albuns.map	
  {	
  album	
  =>
	
  	
  	
  	
  	
  	
  WS.url("https://graph.facebook.com/"	
  +	
  (album	
  	
  "id").toString.replace(""",	
  "")	
  +	
  
"/photos").get().map	
  {	
  response2	
  =>
	
  	
  	
  	
  	
  	
  	
  	
  (response2.json	
  	
  "data").as[List[JsObject]].map	
  {	
  photo	
  =>
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  ((photo	
  	
  "images")(3)	
  	
  "source").toString.replace(""",	
  "")
	
  	
  	
  	
  	
  	
  	
  	
  }
	
  	
  	
  	
  	
  	
  }
	
  	
  	
  	
  }
	
  	
  Ok(views.html.photos(photos))


                                                                                                         JSON
}


@albuns_photos	
  =	
  {}
	
  	
  	
  	
  @albuns	
  =	
  []
	
  	
  	
  	
  albuns	
  =	
  JSON.parse(RestClient.get("https://graph.facebook.com/
daniella.alcarpe/albums"))["data"]
	
  	
  	
  	
  albuns.each	
  do	
  |album|
	
  	
  	
  	
  	
  	
  if	
  (album['description']	
  ==	
  "*")
	
  	
  	
  	
  	
  	
  	
  	
  photos	
  =	
  JSON.parse(RestClient.get("https://graph.facebook.com/
#{album['id']}/photos"))["data"]
	
  	
  	
  	
  	
  	
  	
  	
  albuns_photos	
  =	
  photos.map	
  {|p|	
  p["images"][3]["source"]}
	
  	
  	
  	
  	
  	
  	
  	
  album['photos']	
  =	
  albuns_photos
	
  	
  	
  	
  	
  	
  	
  	
  @albuns	
  <<	
  album
	
  	
  	
  	
  	
  	
  end
	
  	
  	
  	
  end
Cache
def videos = Cached("videos", 18000) {
  Action {
  ...
  }
}




class	
  VideosController	
  <	
  ApplicationController
	
  	
  	
  	
  caches_action	
  :index,	
  :expires_in	
  =>	
  1.day
end
Unit Tests
@Test def myTest() {
  val array = List(1, 2, 3)
  assert(array(0) === 1)
}




test	
  "my	
  test"	
  do
	
  	
  array	
  =	
  [1,	
  2,	
  3]
	
  	
  assert_equal	
  1,	
  array.first
end
Specs
class HelloWorldSpec extends Specification {
  "The 'Hello world' string" should {
    "contain 11 characters" in {
                                                                   specs2
      "Hello world" must have size(11)
    }
    "end with 'world'" in {
      "Hello world" must endWith("world")
                                                                   autotest:
  }
    }
                                                                   $ ~ test
}



describe	
  "HelloWorldSpec"	
  do
  context	
  "The	
  'Hello	
  world'	
  string	
  should"	
  do
  	
  	
  it	
  "contain 11 characters"	
  do                      rspec
  	
  	
  	
  	
  "Hello	
  world".size.should	
  eq(11)
  	
  	
  end
  	
  	
  it	
  "end with 'world'"	
  do
  	
  	
  	
  	
  "Hello	
  world".should	
  end_with("world")     $ autospec
  	
  	
  end
  end
end
In Procfile:
                                 Deploy
web: target/start -Dhttp.port=${PORT} -DapplyEvolutions.default=true -
Ddb.default.url=${DATABASE_URL} -Ddb.default.driver=org.postgresql.Driver

In project/Build.scala:
val appDependencies = Seq(
  "postgresql" % "postgresql" % "8.4-702.jdbc4"
)

$ heroku create
$ git push heroku master




$	
  heroku	
  create
$	
  git	
  push	
  heroku	
  master
Adendo




Scala    X       Ruby


                    by @danicuki
Lambda

list.filter(_ < 100)      list.select	
  do	
  |el|
                          	
  	
  el	
  <	
  100
list.filter {             end	
  
  el: Int => (el < 100)
}
Types

Static:                  Dynamic:

val a = new              a	
  =	
  Hash.new
  HashMap[Int, String]   a	
  =	
  “BOO!”
Pattern Matching
                             require	
  'case'
                             def	
  matchTest	
  x
                             	
  case	
  x
                             	
  when	
  7
def myMatch(x: Any): Any =   	
  	
  	
  "seven"
x match {                    	
  when	
  "string"
  case 7 => “seven”
                             	
  	
  	
  0
  case “string” => 0
                             	
  when	
  Case::All[Integer]
  case y:Int => “no.”
  case 2 :: tail => tail     	
  	
  	
  "no."
}                            	
  when	
  
                             Case::Array[2,Case::Any]
                             	
  	
  	
  x[1..-­‐1]
                             	
  end
                             end
Monkey Patch
class MySuperString(original: String) {
  def myMethod = "yess!!!"
}
implicit def string2super(x: String) =
  new MySuperString(x)

println("a".myMethod) // => yess!!!


class	
  String
	
  	
  def	
  my_method
	
  	
  	
  "yess!!!"
	
  	
  end
end

puts	
  "a".my_method	
  #	
  =>	
  yess!!!
Dynamic Calls
 class Animal extends Dynamic                {
   def _select_(name: String)                = println("Animal says " + name)
   def _invoke_(name: String,                args: Any*) = {
     println("Animal wants to                " + name + args.mkString(", "))
     this
   }            val animal =        new Animal
 }              animal.qualk        // => Animal says qualk
                       animal.say("hello") // => Animal wants to say hello
class	
  Animal
	
  	
  def	
  method_missing	
  name,	
  *args
	
  	
  	
  	
  if	
  args.empty?
	
  	
  	
  	
  	
  	
  puts	
  "Animal	
  says	
  "	
  +	
  name.to_s
	
  	
  	
  	
  else
	
  	
  	
  	
  	
  	
  puts	
  "Animal	
  wants	
  to	
  "	
  +	
  name.to_s	
  +	
  	
  args.join(",	
  ")
	
  	
  	
  	
  end
	
  	
  	
  	
  self               animal	
  =	
  Animal.new
	
  	
  end                        animal.qualk	
  #	
  =>	
  Animal	
  says	
  :	
  qualks	
  !
end                                animal.say("hello")	
  #	
  =>	
  Animal	
  wants	
  to	
  say	
  hello
Modules / Traits
trait PimpMyClass {
  def myMethod = println("myMethod")
}
class IncludeTrait extends PimpMyClass
(new IncludeTrait).myMethod


module	
  PimpMyClass
	
  	
  def	
  my_method
	
  	
  	
  	
  puts	
  "my_method"
	
  	
  end
end
class	
  IncludeModule
	
  	
  include	
  PimpMyClass
end
IncludeModule.new.my_method
Duck Typing
class     Duck {                 def ActAsADuck(a: { def quack; def walk })= {
  def     quack = ...                 a.quack
  def     walk = ...                  a.walk
                                 }
}
class     Platypus {             val duck = new Duck
  def     quack = ...            val platypus = new Platypus
  def     walk = ...             ActAsADuck(duck)
}                                ActAsADuck(platypus)

class	
  Duck                    def	
  act_as_a_duck	
  animal
	
  	
  def	
  quack;	
  end     	
  	
  animal.quack
	
  	
  def	
  walk;	
  end      	
  	
  animal.walk
end                              end

class	
  Platypus                duck	
  =	
  Duck.new
	
  	
  def	
  quack;	
  end     platypus	
  =	
  Platypus.new
	
  	
  def	
  walk;	
  end      act_as_a_duck(duck)
end                              act_as_a_duck(platypus)
Actors
Performance
                                80
               70.74
                                                     Scala
                            60                       JRuby
                                                     Ruby


       39.74               40



                       20


2.07
                       0

                                     Source : http://shootout.alioth.debian.org
References
✦ http://www.playframework.com/documentation
✦ http://guides.rubyonrails.org/
✦ http://www.agileandart.com/
✦ http://www.slideshare.net/El_Picador/scala-vs-ruby
Obrigado!
www.agileandart.com
    @danicuki

Más contenido relacionado

La actualidad más candente

Mobile Open Day: React Native: Crossplatform fast dive
Mobile Open Day: React Native: Crossplatform fast diveMobile Open Day: React Native: Crossplatform fast dive
Mobile Open Day: React Native: Crossplatform fast diveepamspb
 
Java Play Restful JPA
Java Play Restful JPAJava Play Restful JPA
Java Play Restful JPAFaren faren
 
Java Play RESTful ebean
Java Play RESTful ebeanJava Play RESTful ebean
Java Play RESTful ebeanFaren faren
 
Keeping the frontend under control with Symfony and Webpack
Keeping the frontend under control with Symfony and WebpackKeeping the frontend under control with Symfony and Webpack
Keeping the frontend under control with Symfony and WebpackIgnacio Martín
 
Javascript Testing with Jasmine 101
Javascript Testing with Jasmine 101Javascript Testing with Jasmine 101
Javascript Testing with Jasmine 101Roy Yu
 
Building a real life application in node js
Building a real life application in node jsBuilding a real life application in node js
Building a real life application in node jsfakedarren
 
We Are All Testers Now: The Testing Pyramid and Front-End Development
We Are All Testers Now: The Testing Pyramid and Front-End DevelopmentWe Are All Testers Now: The Testing Pyramid and Front-End Development
We Are All Testers Now: The Testing Pyramid and Front-End DevelopmentAll Things Open
 
Migrating PriceChirp to Rails 3.0: The Pain Points
Migrating PriceChirp to Rails 3.0: The Pain PointsMigrating PriceChirp to Rails 3.0: The Pain Points
Migrating PriceChirp to Rails 3.0: The Pain PointsSteven Evatt
 
JavaOne - The JavaFX Community and Ecosystem
JavaOne - The JavaFX Community and EcosystemJavaOne - The JavaFX Community and Ecosystem
JavaOne - The JavaFX Community and EcosystemAlexander Casall
 
An Introduction to Celery
An Introduction to CeleryAn Introduction to Celery
An Introduction to CeleryIdan Gazit
 
Django Rest Framework and React and Redux, Oh My!
Django Rest Framework and React and Redux, Oh My!Django Rest Framework and React and Redux, Oh My!
Django Rest Framework and React and Redux, Oh My!Eric Palakovich Carr
 
Effective Doctrine2: Performance Tips for Symfony2 Developers
Effective Doctrine2: Performance Tips for Symfony2 DevelopersEffective Doctrine2: Performance Tips for Symfony2 Developers
Effective Doctrine2: Performance Tips for Symfony2 DevelopersMarcin Chwedziak
 
Django Celery - A distributed task queue
Django Celery - A distributed task queueDjango Celery - A distributed task queue
Django Celery - A distributed task queueAlex Eftimie
 
Europython 2011 - Playing tasks with Django & Celery
Europython 2011 - Playing tasks with Django & CeleryEuropython 2011 - Playing tasks with Django & Celery
Europython 2011 - Playing tasks with Django & CeleryMauro Rocco
 

La actualidad más candente (20)

Mobile Open Day: React Native: Crossplatform fast dive
Mobile Open Day: React Native: Crossplatform fast diveMobile Open Day: React Native: Crossplatform fast dive
Mobile Open Day: React Native: Crossplatform fast dive
 
Java Play Restful JPA
Java Play Restful JPAJava Play Restful JPA
Java Play Restful JPA
 
Java Play RESTful ebean
Java Play RESTful ebeanJava Play RESTful ebean
Java Play RESTful ebean
 
Rails Security
Rails SecurityRails Security
Rails Security
 
Ant
AntAnt
Ant
 
Introduction to Flask Micro Framework
Introduction to Flask Micro FrameworkIntroduction to Flask Micro Framework
Introduction to Flask Micro Framework
 
Keeping the frontend under control with Symfony and Webpack
Keeping the frontend under control with Symfony and WebpackKeeping the frontend under control with Symfony and Webpack
Keeping the frontend under control with Symfony and Webpack
 
Javascript Testing with Jasmine 101
Javascript Testing with Jasmine 101Javascript Testing with Jasmine 101
Javascript Testing with Jasmine 101
 
Building a real life application in node js
Building a real life application in node jsBuilding a real life application in node js
Building a real life application in node js
 
Presentation
PresentationPresentation
Presentation
 
We Are All Testers Now: The Testing Pyramid and Front-End Development
We Are All Testers Now: The Testing Pyramid and Front-End DevelopmentWe Are All Testers Now: The Testing Pyramid and Front-End Development
We Are All Testers Now: The Testing Pyramid and Front-End Development
 
Migrating PriceChirp to Rails 3.0: The Pain Points
Migrating PriceChirp to Rails 3.0: The Pain PointsMigrating PriceChirp to Rails 3.0: The Pain Points
Migrating PriceChirp to Rails 3.0: The Pain Points
 
JavaOne - The JavaFX Community and Ecosystem
JavaOne - The JavaFX Community and EcosystemJavaOne - The JavaFX Community and Ecosystem
JavaOne - The JavaFX Community and Ecosystem
 
An Introduction to Celery
An Introduction to CeleryAn Introduction to Celery
An Introduction to Celery
 
Debugging on rails
Debugging on railsDebugging on rails
Debugging on rails
 
Intro to-ant
Intro to-antIntro to-ant
Intro to-ant
 
Django Rest Framework and React and Redux, Oh My!
Django Rest Framework and React and Redux, Oh My!Django Rest Framework and React and Redux, Oh My!
Django Rest Framework and React and Redux, Oh My!
 
Effective Doctrine2: Performance Tips for Symfony2 Developers
Effective Doctrine2: Performance Tips for Symfony2 DevelopersEffective Doctrine2: Performance Tips for Symfony2 Developers
Effective Doctrine2: Performance Tips for Symfony2 Developers
 
Django Celery - A distributed task queue
Django Celery - A distributed task queueDjango Celery - A distributed task queue
Django Celery - A distributed task queue
 
Europython 2011 - Playing tasks with Django & Celery
Europython 2011 - Playing tasks with Django & CeleryEuropython 2011 - Playing tasks with Django & Celery
Europython 2011 - Playing tasks with Django & Celery
 

Similar a Play vs Rails

JRuby + Rails = Awesome Java Web Framework at Jfokus 2011
JRuby + Rails = Awesome Java Web Framework at Jfokus 2011JRuby + Rails = Awesome Java Web Framework at Jfokus 2011
JRuby + Rails = Awesome Java Web Framework at Jfokus 2011Nick Sieger
 
Rails 3: Dashing to the Finish
Rails 3: Dashing to the FinishRails 3: Dashing to the Finish
Rails 3: Dashing to the FinishYehuda Katz
 
Rails 3 overview
Rails 3 overviewRails 3 overview
Rails 3 overviewYehuda Katz
 
QConSP 2015 - Dicas de Performance para Aplicações Web
QConSP 2015 - Dicas de Performance para Aplicações WebQConSP 2015 - Dicas de Performance para Aplicações Web
QConSP 2015 - Dicas de Performance para Aplicações WebFabio Akita
 
Burn down the silos! Helping dev and ops gel on high availability websites
Burn down the silos! Helping dev and ops gel on high availability websitesBurn down the silos! Helping dev and ops gel on high availability websites
Burn down the silos! Helping dev and ops gel on high availability websitesLindsay Holmwood
 
Backbone.js — Introduction to client-side JavaScript MVC
Backbone.js — Introduction to client-side JavaScript MVCBackbone.js — Introduction to client-side JavaScript MVC
Backbone.js — Introduction to client-side JavaScript MVCpootsbook
 
Building web framework with Rack
Building web framework with RackBuilding web framework with Rack
Building web framework with Racksickill
 
[Coscup 2012] JavascriptMVC
[Coscup 2012] JavascriptMVC[Coscup 2012] JavascriptMVC
[Coscup 2012] JavascriptMVCAlive Kuo
 
Rich Portlet Development in uPortal
Rich Portlet Development in uPortalRich Portlet Development in uPortal
Rich Portlet Development in uPortalJennifer Bourey
 
All I Need to Know I Learned by Writing My Own Web Framework
All I Need to Know I Learned by Writing My Own Web FrameworkAll I Need to Know I Learned by Writing My Own Web Framework
All I Need to Know I Learned by Writing My Own Web FrameworkBen Scofield
 
Beyond DOMReady: Ultra High-Performance Javascript
Beyond DOMReady: Ultra High-Performance JavascriptBeyond DOMReady: Ultra High-Performance Javascript
Beyond DOMReady: Ultra High-Performance Javascriptaglemann
 
Spring into rails
Spring into railsSpring into rails
Spring into railsHiro Asari
 
Xitrum Web Framework Live Coding Demos / Xitrum Web Framework ライブコーディング
Xitrum Web Framework Live Coding Demos / Xitrum Web Framework ライブコーディングXitrum Web Framework Live Coding Demos / Xitrum Web Framework ライブコーディング
Xitrum Web Framework Live Coding Demos / Xitrum Web Framework ライブコーディングscalaconfjp
 
Xitrum @ Scala Matsuri Tokyo 2014
Xitrum @ Scala Matsuri Tokyo 2014Xitrum @ Scala Matsuri Tokyo 2014
Xitrum @ Scala Matsuri Tokyo 2014Ngoc Dao
 
Infrastructure-as-code: bridging the gap between Devs and Ops
Infrastructure-as-code: bridging the gap between Devs and OpsInfrastructure-as-code: bridging the gap between Devs and Ops
Infrastructure-as-code: bridging the gap between Devs and OpsMykyta Protsenko
 
Express Presentation
Express PresentationExpress Presentation
Express Presentationaaronheckmann
 
Jarv.us Showcase — SenchaCon 2011
Jarv.us Showcase — SenchaCon 2011Jarv.us Showcase — SenchaCon 2011
Jarv.us Showcase — SenchaCon 2011Chris Alfano
 

Similar a Play vs Rails (20)

JRuby + Rails = Awesome Java Web Framework at Jfokus 2011
JRuby + Rails = Awesome Java Web Framework at Jfokus 2011JRuby + Rails = Awesome Java Web Framework at Jfokus 2011
JRuby + Rails = Awesome Java Web Framework at Jfokus 2011
 
Play!ng with scala
Play!ng with scalaPlay!ng with scala
Play!ng with scala
 
Rails 3: Dashing to the Finish
Rails 3: Dashing to the FinishRails 3: Dashing to the Finish
Rails 3: Dashing to the Finish
 
Rails 3 overview
Rails 3 overviewRails 3 overview
Rails 3 overview
 
QConSP 2015 - Dicas de Performance para Aplicações Web
QConSP 2015 - Dicas de Performance para Aplicações WebQConSP 2015 - Dicas de Performance para Aplicações Web
QConSP 2015 - Dicas de Performance para Aplicações Web
 
Burn down the silos! Helping dev and ops gel on high availability websites
Burn down the silos! Helping dev and ops gel on high availability websitesBurn down the silos! Helping dev and ops gel on high availability websites
Burn down the silos! Helping dev and ops gel on high availability websites
 
Backbone.js — Introduction to client-side JavaScript MVC
Backbone.js — Introduction to client-side JavaScript MVCBackbone.js — Introduction to client-side JavaScript MVC
Backbone.js — Introduction to client-side JavaScript MVC
 
Building web framework with Rack
Building web framework with RackBuilding web framework with Rack
Building web framework with Rack
 
How to React Native
How to React NativeHow to React Native
How to React Native
 
[Coscup 2012] JavascriptMVC
[Coscup 2012] JavascriptMVC[Coscup 2012] JavascriptMVC
[Coscup 2012] JavascriptMVC
 
Rich Portlet Development in uPortal
Rich Portlet Development in uPortalRich Portlet Development in uPortal
Rich Portlet Development in uPortal
 
All I Need to Know I Learned by Writing My Own Web Framework
All I Need to Know I Learned by Writing My Own Web FrameworkAll I Need to Know I Learned by Writing My Own Web Framework
All I Need to Know I Learned by Writing My Own Web Framework
 
Beyond DOMReady: Ultra High-Performance Javascript
Beyond DOMReady: Ultra High-Performance JavascriptBeyond DOMReady: Ultra High-Performance Javascript
Beyond DOMReady: Ultra High-Performance Javascript
 
Spring into rails
Spring into railsSpring into rails
Spring into rails
 
Play framework
Play frameworkPlay framework
Play framework
 
Xitrum Web Framework Live Coding Demos / Xitrum Web Framework ライブコーディング
Xitrum Web Framework Live Coding Demos / Xitrum Web Framework ライブコーディングXitrum Web Framework Live Coding Demos / Xitrum Web Framework ライブコーディング
Xitrum Web Framework Live Coding Demos / Xitrum Web Framework ライブコーディング
 
Xitrum @ Scala Matsuri Tokyo 2014
Xitrum @ Scala Matsuri Tokyo 2014Xitrum @ Scala Matsuri Tokyo 2014
Xitrum @ Scala Matsuri Tokyo 2014
 
Infrastructure-as-code: bridging the gap between Devs and Ops
Infrastructure-as-code: bridging the gap between Devs and OpsInfrastructure-as-code: bridging the gap between Devs and Ops
Infrastructure-as-code: bridging the gap between Devs and Ops
 
Express Presentation
Express PresentationExpress Presentation
Express Presentation
 
Jarv.us Showcase — SenchaCon 2011
Jarv.us Showcase — SenchaCon 2011Jarv.us Showcase — SenchaCon 2011
Jarv.us Showcase — SenchaCon 2011
 

Más de Daniel Cukier

Solidity: Zero to Hero Corporate Training
Solidity: Zero to Hero Corporate TrainingSolidity: Zero to Hero Corporate Training
Solidity: Zero to Hero Corporate TrainingDaniel Cukier
 
Spring e Injeção de Dependência
Spring e Injeção de DependênciaSpring e Injeção de Dependência
Spring e Injeção de DependênciaDaniel Cukier
 
Eficiency and Low Cost: Pro Tips for you to save 50% of your money with Googl...
Eficiency and Low Cost: Pro Tips for you to save 50% of your money with Googl...Eficiency and Low Cost: Pro Tips for you to save 50% of your money with Googl...
Eficiency and Low Cost: Pro Tips for you to save 50% of your money with Googl...Daniel Cukier
 
Startup Communities: From Nascence to Maturity
Startup Communities: From Nascence to MaturityStartup Communities: From Nascence to Maturity
Startup Communities: From Nascence to MaturityDaniel Cukier
 
Technology Startups Ecosystem in China - Lessons to other ecosystems
Technology Startups  Ecosystem in China - Lessons to other ecosystemsTechnology Startups  Ecosystem in China - Lessons to other ecosystems
Technology Startups Ecosystem in China - Lessons to other ecosystemsDaniel Cukier
 
Software Startup Ecosystems Evolution - The New York City Case Study
Software Startup Ecosystems Evolution - The New York City Case StudySoftware Startup Ecosystems Evolution - The New York City Case Study
Software Startup Ecosystems Evolution - The New York City Case StudyDaniel Cukier
 
Maturity model for Startup Ecosystems
Maturity model for Startup EcosystemsMaturity model for Startup Ecosystems
Maturity model for Startup EcosystemsDaniel Cukier
 
Why Google Cloud is so special? Stories from a cloud user
Why Google Cloud is so special?  Stories from a cloud userWhy Google Cloud is so special?  Stories from a cloud user
Why Google Cloud is so special? Stories from a cloud userDaniel Cukier
 
Software Architectures for a Single Person Team
Software Architectures for a Single Person TeamSoftware Architectures for a Single Person Team
Software Architectures for a Single Person TeamDaniel Cukier
 
Introduction to Functional Programming with Scala
Introduction to Functional Programming with ScalaIntroduction to Functional Programming with Scala
Introduction to Functional Programming with ScalaDaniel Cukier
 
O dia a dia de uma Startup
O dia a dia de uma StartupO dia a dia de uma Startup
O dia a dia de uma StartupDaniel Cukier
 
Injeção de Dependência e Testes com Dublês
Injeção de Dependência e Testes com DublêsInjeção de Dependência e Testes com Dublês
Injeção de Dependência e Testes com DublêsDaniel Cukier
 
Selecting Empirical Methods for Software Engineering
Selecting Empirical Methods for Software EngineeringSelecting Empirical Methods for Software Engineering
Selecting Empirical Methods for Software EngineeringDaniel Cukier
 
Is Computer Science Science?
Is Computer Science Science?Is Computer Science Science?
Is Computer Science Science?Daniel Cukier
 
Better Science Through Art
Better Science Through ArtBetter Science Through Art
Better Science Through ArtDaniel Cukier
 
Designed as Designer
Designed as DesignerDesigned as Designer
Designed as DesignerDaniel Cukier
 
When Should You Consider Meta Architectures
When Should You Consider Meta ArchitecturesWhen Should You Consider Meta Architectures
When Should You Consider Meta ArchitecturesDaniel Cukier
 

Más de Daniel Cukier (20)

Solidity: Zero to Hero Corporate Training
Solidity: Zero to Hero Corporate TrainingSolidity: Zero to Hero Corporate Training
Solidity: Zero to Hero Corporate Training
 
Spring e Injeção de Dependência
Spring e Injeção de DependênciaSpring e Injeção de Dependência
Spring e Injeção de Dependência
 
Pair programming
Pair programmingPair programming
Pair programming
 
Eficiency and Low Cost: Pro Tips for you to save 50% of your money with Googl...
Eficiency and Low Cost: Pro Tips for you to save 50% of your money with Googl...Eficiency and Low Cost: Pro Tips for you to save 50% of your money with Googl...
Eficiency and Low Cost: Pro Tips for you to save 50% of your money with Googl...
 
Startup Communities: From Nascence to Maturity
Startup Communities: From Nascence to MaturityStartup Communities: From Nascence to Maturity
Startup Communities: From Nascence to Maturity
 
Technology Startups Ecosystem in China - Lessons to other ecosystems
Technology Startups  Ecosystem in China - Lessons to other ecosystemsTechnology Startups  Ecosystem in China - Lessons to other ecosystems
Technology Startups Ecosystem in China - Lessons to other ecosystems
 
Software Startup Ecosystems Evolution - The New York City Case Study
Software Startup Ecosystems Evolution - The New York City Case StudySoftware Startup Ecosystems Evolution - The New York City Case Study
Software Startup Ecosystems Evolution - The New York City Case Study
 
Maturity model for Startup Ecosystems
Maturity model for Startup EcosystemsMaturity model for Startup Ecosystems
Maturity model for Startup Ecosystems
 
Why Google Cloud is so special? Stories from a cloud user
Why Google Cloud is so special?  Stories from a cloud userWhy Google Cloud is so special?  Stories from a cloud user
Why Google Cloud is so special? Stories from a cloud user
 
Software Architectures for a Single Person Team
Software Architectures for a Single Person TeamSoftware Architectures for a Single Person Team
Software Architectures for a Single Person Team
 
Startup Communities
Startup CommunitiesStartup Communities
Startup Communities
 
Introduction to Functional Programming with Scala
Introduction to Functional Programming with ScalaIntroduction to Functional Programming with Scala
Introduction to Functional Programming with Scala
 
O dia a dia de uma Startup
O dia a dia de uma StartupO dia a dia de uma Startup
O dia a dia de uma Startup
 
Injeção de Dependência e Testes com Dublês
Injeção de Dependência e Testes com DublêsInjeção de Dependência e Testes com Dublês
Injeção de Dependência e Testes com Dublês
 
Selecting Empirical Methods for Software Engineering
Selecting Empirical Methods for Software EngineeringSelecting Empirical Methods for Software Engineering
Selecting Empirical Methods for Software Engineering
 
Is Computer Science Science?
Is Computer Science Science?Is Computer Science Science?
Is Computer Science Science?
 
Ruby Robots
Ruby RobotsRuby Robots
Ruby Robots
 
Better Science Through Art
Better Science Through ArtBetter Science Through Art
Better Science Through Art
 
Designed as Designer
Designed as DesignerDesigned as Designer
Designed as Designer
 
When Should You Consider Meta Architectures
When Should You Consider Meta ArchitecturesWhen Should You Consider Meta Architectures
When Should You Consider Meta Architectures
 

Último

SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESmohitsingh558521
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfMounikaPolabathina
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 
Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rick Flair
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningLars Bell
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsNathaniel Shimoni
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxhariprasad279825
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxLoriGlavin3
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersRaghuram Pandurangan
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 

Último (20)

SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdf
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 
Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine Tuning
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directions
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptx
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information Developers
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 

Play vs Rails

  • 1. Ruby Play 2.0 X On Rails by @danicuki
  • 3. Installing $ apt-get install java $  apt-­‐get  install  ruby $ wget play-2.1.0.zip $  apt-­‐get  install  rubygems $ unzip play-2.1.0.zip $  gem  install  rails $ export PATH=$PATH:/pathToPlay http://www.playframework.com/ documentation/2.1.0/Installing
  • 4. First App $ play new myapp $  rails  new  myapp
  • 5. Project Structure app/ app/ ! assets ! assets ! stylesheets ! stylesheets ! javascripts ! javascripts ! controllers ! controllers ! models ! helpers ! views ! mailers conf/ ! models ! application.conf ! views ! routes config/ public/ ! application.rb project ! routes.rb ! build.properties ! database.yml ! Build.scala config.ru ! plugins.sbt db lib/ GemFile logs/ lib/ target/ log/ public/ ! scala-2.10.0 script/ test/ test/ tmp/ vendor/
  • 7. Dependencies Maven project/Build.scala val appDependencies = Seq( "postgresql" % "postgresql" % "8.4-702.jdbc4" "org.mockito" % "mockito-all" % "1.8.5" % "test" ) RubyGems Gemfile gem "mysql2" group :test do gem "webmock" end
  • 8. Dependencies Support 429.000 jars mvnrepository.com 52,468 gems rubygems.org
  • 9. Views Templates STE (Scala Template Engine) @(title: String)(content: Html) <title> @Messages("site.title") - @title </title> @{(video "title")(0).text} ERB (Embedded Ruby) <title>    <%=  t("site.title")  %>  -­‐  <%=  yield(:title)  %> </title> <%=  video['title']  %>
  • 10. js / css <link rel="stylesheet" href="@routes.Assets.at("stylesheets/grid.css")"> <link rel="stylesheet" href="@routes.Assets.at("stylesheets/style.css")"> <link rel="stylesheet" href="@routes.Assets.at("stylesheets/galleriffic.css")"> <script src="@routes.Assets.at("javascripts/applicaton.js")" type="text/javascript" /> <script src="@routes.Assets.at("javascripts/jquery.js")" type="text/javascript" /> <%=  javascript_include_tag  :all,  :cache  =>  true  %>   <%=  stylesheet_link_tag  :all,  :cache  =>  true  %>
  • 11. Links <li class="menu"> <a href="@routes.Application.cantora">@Messages("site.singer")</a> </li> <li  class="menu">    <%=  link_to  "#{t('site.singer')}",  {:controller  =>  "cantora"}  %> </li>
  • 12. Routes GET /cantora controllers.Application.cantora GET /musicas controllers.Application.music GET /agenda controllers.Application.shows GET /novidades controllers.Application.news GET /clients/:id controllers.Clients.show(id: Long) map.connect  ':controller/:action/:id'
  • 13. Controllers def cantora = Action { implicit request =>; Ok(views.html.cantora()) } def music = Action { implicit request =>; Ok(views.html.music()) } def shows = Action { implicit request => Ok(views.html.shows()) } def news = Action { implicit request => Ok(views.html.news()) } /app/views/[method_name].scala.html class  CantoraController  <  ApplicationController def  index    end end class  NewsController  <  ApplicationController   def  index   end end /app/views/[controller_name]/index.erb.html
  • 15. SQL API: Databases val countries = SQL("Select name,population from Country")().collect { case Row("France", _) => France() case Row(name:String, pop:Int) if(pop > 1000000) => BigCountry(name) case Row(name:String, _) => SmallCountry(name) } val result: Int = SQL("delete from City where id = {id}").on(“id” -> 99).executeUpdate() Active  Record: Country.all.map  do  |c|    if  (c.name  ==  “France”)        France.new    else  if  (c.pop  >  1000000) Country.delete(99)        BigCountry.new(c.name)    else        SmallCountry.new(c.name)    end end
  • 16. Databases OGH (Old Good Hibernate) Active  Record: Country.all.map  do  |c|    if  (c.name  ==  “France”)        France.new    else  if  (c.pop  >  1000000) Country.delete(99)        BigCountry.new(c.name)    else        SmallCountry.new(c.name)    end end
  • 17. Migrations / Evolutions # --- !Ups CREATE TABLE Users ( id bigint(20) NOT NULL AUTO_INCREMENT, email varchar(255) NOT NULL, password varchar(255) NOT NULL, PRIMARY KEY (id) ); # --- !Downs run: AUTOMATIC! DROP TABLE Users; conf/evolutions/{database name}/{#}.sql class  CreateUsers  <  ActiveRecord::Migration    def  up        create_table  :users  do  |t|            t.string  :email            t.string  :password            t.timestamps        end    end    def  down        drop_table  :users run:  rake  db:migrate    end db/migrate/{timestamp}_create_users.rb end
  • 18. Web Services def videos = Action { implicit request => Async { val uri = "http://gdata.youtube.com/feed.xml" WS.url(uri).get().map { response => Ok(views.html.videos(response.xml "entry")) } } } class  VideosController  <  ApplicationController    def  index        uri  =  "http://gdata.youtube.com/feed.xml"        video_feed  =  RestClient.get(uri)        @videos  =  Hash.from_xml(video_feed)['feed']['entry']    end end
  • 19. XML Ok(views.html.videos(response.xml "entry")) @(videos: scala.xml.NodeSeq) @videos.map { video =>     <a href="@{ ((video "group") "player")(0).attribute("url")}">        @{(video "title")(0).text}     </a> } @videos  =  Hash.from_xml(video_feed)['feed']['entry'] <%  @videos.each  do  |video|  %>          <a  href="<%=  video['group']['player']['url']  %>">                  <%=  video['title']  %>          </a> <%  end  %>
  • 20. WS.url("https://graph.facebook.com/daniella.alcarpe/albums").get().map  {  response  =>        val  albuns  =  (response.json    "data").            as[List[JsObject]].filter(album  =>                (album    "description").toString.equals(""*""))          val  photos  =  albuns.map  {  album  =>            WS.url("https://graph.facebook.com/"  +  (album    "id").toString.replace(""",  "")  +   "/photos").get().map  {  response2  =>                (response2.json    "data").as[List[JsObject]].map  {  photo  =>                    ((photo    "images")(3)    "source").toString.replace(""",  "")                }            }        }    Ok(views.html.photos(photos)) JSON } @albuns_photos  =  {}        @albuns  =  []        albuns  =  JSON.parse(RestClient.get("https://graph.facebook.com/ daniella.alcarpe/albums"))["data"]        albuns.each  do  |album|            if  (album['description']  ==  "*")                photos  =  JSON.parse(RestClient.get("https://graph.facebook.com/ #{album['id']}/photos"))["data"]                albuns_photos  =  photos.map  {|p|  p["images"][3]["source"]}                album['photos']  =  albuns_photos                @albuns  <<  album            end        end
  • 21. Cache def videos = Cached("videos", 18000) {   Action { ...   } } class  VideosController  <  ApplicationController        caches_action  :index,  :expires_in  =>  1.day end
  • 22. Unit Tests @Test def myTest() { val array = List(1, 2, 3) assert(array(0) === 1) } test  "my  test"  do    array  =  [1,  2,  3]    assert_equal  1,  array.first end
  • 23. Specs class HelloWorldSpec extends Specification { "The 'Hello world' string" should { "contain 11 characters" in { specs2 "Hello world" must have size(11) } "end with 'world'" in { "Hello world" must endWith("world") autotest: } } $ ~ test } describe  "HelloWorldSpec"  do context  "The  'Hello  world'  string  should"  do    it  "contain 11 characters"  do rspec        "Hello  world".size.should  eq(11)    end    it  "end with 'world'"  do        "Hello  world".should  end_with("world") $ autospec    end end end
  • 24. In Procfile: Deploy web: target/start -Dhttp.port=${PORT} -DapplyEvolutions.default=true - Ddb.default.url=${DATABASE_URL} -Ddb.default.driver=org.postgresql.Driver In project/Build.scala: val appDependencies = Seq( "postgresql" % "postgresql" % "8.4-702.jdbc4" ) $ heroku create $ git push heroku master $  heroku  create $  git  push  heroku  master
  • 25. Adendo Scala X Ruby by @danicuki
  • 26. Lambda list.filter(_ < 100) list.select  do  |el|    el  <  100 list.filter { end   el: Int => (el < 100) }
  • 27. Types Static: Dynamic: val a = new a  =  Hash.new HashMap[Int, String] a  =  “BOO!”
  • 28. Pattern Matching require  'case' def  matchTest  x  case  x  when  7 def myMatch(x: Any): Any =      "seven" x match {  when  "string" case 7 => “seven”      0 case “string” => 0  when  Case::All[Integer] case y:Int => “no.” case 2 :: tail => tail      "no." }  when   Case::Array[2,Case::Any]      x[1..-­‐1]  end end
  • 29. Monkey Patch class MySuperString(original: String) { def myMethod = "yess!!!" } implicit def string2super(x: String) = new MySuperString(x) println("a".myMethod) // => yess!!! class  String    def  my_method      "yess!!!"    end end puts  "a".my_method  #  =>  yess!!!
  • 30. Dynamic Calls class Animal extends Dynamic { def _select_(name: String) = println("Animal says " + name) def _invoke_(name: String, args: Any*) = { println("Animal wants to " + name + args.mkString(", ")) this } val animal = new Animal } animal.qualk // => Animal says qualk animal.say("hello") // => Animal wants to say hello class  Animal    def  method_missing  name,  *args        if  args.empty?            puts  "Animal  says  "  +  name.to_s        else            puts  "Animal  wants  to  "  +  name.to_s  +    args.join(",  ")        end        self animal  =  Animal.new    end animal.qualk  #  =>  Animal  says  :  qualks  ! end animal.say("hello")  #  =>  Animal  wants  to  say  hello
  • 31. Modules / Traits trait PimpMyClass { def myMethod = println("myMethod") } class IncludeTrait extends PimpMyClass (new IncludeTrait).myMethod module  PimpMyClass    def  my_method        puts  "my_method"    end end class  IncludeModule    include  PimpMyClass end IncludeModule.new.my_method
  • 32. Duck Typing class Duck { def ActAsADuck(a: { def quack; def walk })= { def quack = ... a.quack def walk = ... a.walk } } class Platypus { val duck = new Duck def quack = ... val platypus = new Platypus def walk = ... ActAsADuck(duck) } ActAsADuck(platypus) class  Duck def  act_as_a_duck  animal    def  quack;  end    animal.quack    def  walk;  end    animal.walk end end class  Platypus duck  =  Duck.new    def  quack;  end platypus  =  Platypus.new    def  walk;  end act_as_a_duck(duck) end act_as_a_duck(platypus)
  • 34. Performance 80 70.74 Scala 60 JRuby Ruby 39.74 40 20 2.07 0 Source : http://shootout.alioth.debian.org
  • 35. References ✦ http://www.playframework.com/documentation ✦ http://guides.rubyonrails.org/ ✦ http://www.agileandart.com/ ✦ http://www.slideshare.net/El_Picador/scala-vs-ruby