Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Play vs Rails

52,721 views

Published on

Comparison between Play Framework (Scala) and RubyOnRails (Ruby)

Published in: Technology
  • Hmmm.. I went back and checked the link on the performance page and I think the colors are wrong on the chart.

    I get the following chart if I run the benchmarks which indicates that Scala (and Java 7) 1-2 orders of magnitude faster than Ruby.

    Scala used what fraction? used how many times more?
    Benchmark Time Memory Code
    fannkuch-redux † 1/229 4× 3×
    mandelbrot 1/72 3× ±
    n-body 1/28 4× ±
    k-nucleotide 1/24 2× 3×
    spectral-norm 1/23 ± ±
    fasta 1/17 1/9 ±
    binary-trees 1/12 6× ±
    reverse-complement † 1/6 3× 3×
    pidigits 2× 29× 2×
    regex-dna † 3× 3× ±
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

Play vs Rails

  1. RubyPlay2.0 X On Rails by @danicuki
  2. Documentationhttp://www.playframework.com/documentation/ http://guides.rubyonrails.org/
  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:/pathToPlayhttp://www.playframework.com/documentation/2.1.0/Installing
  4. First App$ play new myapp $  rails  new  myapp
  5. Project Structureapp/ app/ ! assets ! assets ! stylesheets ! stylesheets ! javascripts ! javascripts ! controllers ! controllers ! models ! helpers ! views ! mailersconf/ ! models ! application.conf ! views ! routes config/public/ ! application.rbproject ! routes.rb ! build.properties ! database.yml ! Build.scala config.ru ! plugins.sbt dblib/ GemFilelogs/ lib/target/ log/ public/ ! scala-2.10.0 script/test/ test/ tmp/ vendor/
  6. Console
  7. DependenciesMavenproject/Build.scalaval appDependencies = Seq( "postgresql" % "postgresql" % "8.4-702.jdbc4" "org.mockito" % "mockito-all" % "1.8.5" % "test")RubyGemsGemfilegem "mysql2"group :test do gem "webmock"end
  8. Dependencies Support 429.000 jars mvnrepository.com 52,468 gems rubygems.org
  9. Views TemplatesSTE (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. RoutesGET /cantora controllers.Application.cantoraGET /musicas controllers.Application.musicGET /agenda controllers.Application.showsGET /novidades controllers.Application.newsGET /clients/:id controllers.Clients.show(id: Long)map.connect  :controller/:action/:id
  13. Controllersdef 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.htmlclass  CantoraController  <  ApplicationController def  index    endendclass  NewsController  <  ApplicationController   def  index   endend/app/views/[controller_name]/index.erb.html
  14. Databasesconf/application.conf:db.default.driver=com.mysql.jdbc.Driverdb.default.url="jdbc:mysql://localhost/playdb"db.default.user=playdbuserdb.default.pass="a strong password"config/database.yml:development:    adapter:  mysql2    database:  blog_development    username:  root    password:
  15. SQL API: Databasesval 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)    endend
  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)    endend
  17. Migrations / Evolutions# --- !UpsCREATE 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}/{#}.sqlclass  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.rbend
  18. Web Servicesdef 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]    endend
  19. XMLOk(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. Cachedef videos = Cached("videos", 18000) {  Action { ...  }}class  VideosController  <  ApplicationController        caches_action  :index,  :expires_in  =>  1.dayend
  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.firstend
  23. Specsclass 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 endend
  24. In Procfile: Deployweb: target/start -Dhttp.port=${PORT} -DapplyEvolutions.default=true -Ddb.default.url=${DATABASE_URL} -Ddb.default.driver=org.postgresql.DriverIn 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. AdendoScala X Ruby by @danicuki
  26. Lambdalist.filter(_ < 100) list.select  do  |el|    el  <  100list.filter { end   el: Int => (el < 100)}
  27. TypesStatic: Dynamic:val a = new a  =  Hash.new HashMap[Int, String] a  =  “BOO!”
  28. Pattern Matching require  case def  matchTest  x  case  x  when  7def 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 Patchclass MySuperString(original: String) { def myMethod = "yess!!!"}implicit def string2super(x: String) = new MySuperString(x)println("a".myMethod) // => yess!!!class  String    def  my_method      "yess!!!"    endendputs  "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 helloclass  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 / Traitstrait PimpMyClass { def myMethod = println("myMethod")}class IncludeTrait extends PimpMyClass(new IncludeTrait).myMethodmodule  PimpMyClass    def  my_method        puts  "my_method"    endendclass  IncludeModule    include  PimpMyClassendIncludeModule.new.my_method
  32. Duck Typingclass 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.walkend endclass  Platypus duck  =  Duck.new    def  quack;  end platypus  =  Platypus.new    def  walk;  end act_as_a_duck(duck)end act_as_a_duck(platypus)
  33. Actors
  34. Performance 80 70.74 Scala 60 JRuby Ruby 39.74 40 202.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
  36. Obrigado!www.agileandart.com @danicuki

×