Play á la Rails
Upcoming SlideShare
Loading in...5
×
 

Play á la Rails

on

  • 800 views

My attempts to make my experience developing Play 2 web-applications (in Scala) more Rails-like. ...

My attempts to make my experience developing Play 2 web-applications (in Scala) more Rails-like.

I show 3 frameworks employed that draw nearer to the Ruby/Rails spirit than Play's default offerings.

Statistics

Views

Total Views
800
Views on SlideShare
800
Embed Views
0

Actions

Likes
1
Downloads
4
Comments
2

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel

12 of 2

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
  • Hi, take a look at my demo project at: https://github.com/sebnozzi/play-ala-rails
    Are you sure you want to
    Your message goes here
    Processing…
  • It'd have been great if there were some slides with configuration options for Play 2.2 to enable ActiveRecord. Current instructions for Play 2.1 do not work.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Play á la Rails Play á la Rails Presentation Transcript

    • à la Sebastian Nozzi
    • Background • Working with Java since 2001 • Flirting with Smalltalk all these years • Involved with Rails since September 2012 • Hooked with Scala since January 2013 • Developing with Play since June 2013
    • Ruby Let’s talk about
    • “A dynamic, open source programming language with a focus on simplicity and productivity. It has an elegant syntax that is natural to read and easy to write.”
    • Let’s talk about
    • “Ruby on Rails is an open- source web framework that’s optimized for programmer happiness and sustainable productivity. It lets you write beautiful code by favoring convention over configuration.”
    • How Ruby is (self) perceived
    • • Heavily inspired from Rails • Fun. Productive. Save + Reload. • Convention over Configuration. • Routing. REST. MVC... • ... but I missed some things ...
    • ActiveRecord db:migrate Cucumber + Capybara Anorm? Slick? Evolutions? Specs? Rails’ vs. Play’s default offerings
    • not “railsy” enough
    • ActiveRecord db:migrate Cucumber + Capybara ActiveRecord (for Scala) Flyway Cucumber-JVM + Fluentlenium More “Rails-like” alternatives
    • case class User(var username: String) extends ActiveRecord { lazy val posts = hasMany[Post] } case class Post(var text: String) extends ActiveRecord with Timestamps { var userId: Long = _ lazy val user = belongsTo[User] } Declaring Entities
    • object Tables extends ActiveRecordTables { val users = table[User]("users") val posts = table[Post]("posts") } object User extends ActiveRecordCompanion[User] object Post extends ActiveRecordCompanion[Post] Declaring the Schema
    • val newUser = User(username=“Homer”).create() val users: List[User] = User.toList User.findBy(“username”, “Homer”).foreach { user => val posts = user.posts.orderBy(_.createdAt desc).toList ... ... user.posts << Post(“Ohhh donuts!”) } Basic Operations
    • Play Integration
    • object Global extends GlobalSettings { override def onStart(app: Application) { if(!Play.isTest) { val flyway = new Flyway() // .. get values from Play’s config ... flyway.setDataSource(url, user, password) flyway.setInitOnMigrate(true) flyway.migrate() } Tables.initialize(...) // ActiveRecord } } Triggering the Migrations
    • object Global extends GlobalSettings { override def onStart(app: Application) { if(!Play.isTest) { val flyway = new Flyway() // .. get values from Play’s config ... flyway.setDataSource(url, user, password) flyway.setInitOnMigrate(true) flyway.migrate() } Tables.initialize(...) // ActiveRecord } } Initializing ActiveRecord
    • SQL-based Migrations
    • package db.migration class V1_03__CreateSomePosts extends JdbcMigration { override def migrate(ignoredConnection: Connection) { ... ... ... ... ... } } Code-based Migrations
    • package db.migration class V1_03__CreateSomePosts extends JdbcMigration { override def migrate(ignoredConnection: Connection) { User.findBy("username", "Homer").foreach { homer => homer.posts << Post("I'm hungry") homer.posts << Post("I should go to Moe's") homer.posts << Post("Or order some Pizza") } } } Code-based Migrations
    • + Fluentlenium
    • • Write in plain English • Separation of specification / implementation
    • Feature: Posting status updates The goal of the system is keep co-workers informed by posting status updates. Background: Given that user "manager" exists And that user "manager" posted | first day at work | | meeting people | | working like crazy | Scenario: Posts are ordered chronologically (newest on top) When I go to the posts page of user "manager" Then the post nr. 1 should contain "working" And the post nr. 2 should contain "meeting" And the post nr. 3 should contain "first"
    • When("""^I type "([^"]*)" in the "([^"]*)" field$""") { (text: String, fieldName: String) => ... } And("""^press "([^"]*)"$""") { (buttonLabel: String) => ... ... } Then("""^I should be on the posts page of "([^"]*)"$""") { (username: String) => ... ... ... } Step Declarations
    • • Part of Play2 • DSL wrapping Selenium • PhantomJS for headless testing Fluentlenium
    • When("""^I type "([^"]*)" in the "([^"]*)" field$""") { (text: String, fieldName: String) => ... } And("""^press "([^"]*)"$""") { (buttonLabel: String) => ... ... } Then("""^I should be on the posts page of "([^"]*)"$""") { (username: String) => ... ... ... }
    • When("""^I type "([^"]*)" in the "([^"]*)" field$""") { (text: String, fieldName: String) => browser.fill("*", withName(fieldName)).`with`(text) } And("""^press "([^"]*)"$""") { (buttonLabel: String) => val button = browser.find("button", withText(buttonLabel)) button.click() } Then("""^I should be on the posts page of "([^"]*)"$""") { (username: String) => val user = User.findBy("username", username).get val expectedUrl = controllers.routes.UserActions.posts(user.id).url driver.getCurrentUrl() should endWith(expectedUrl) } Step Implementations
    • Conclusions
    • Conclusions • Satisfied with my choices (so far) • Integration was doable • Play flexible enough • to replace some parts • to let different libraries co-exist • Reached a more Rails-like experience
    • Some Thoughts
    • Some Thoughts • Programming can (and should!) be fun • Scala embraces some of that “fun” • ... but we can do more • Go check Ruby / Rails • Let’s steal get inspired from them ;-)
    • Thank you