SlideShare une entreprise Scribd logo
1  sur  36
Télécharger pour lire hors ligne
à 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

Contenu connexe

Tendances

Deep Dive into AWS CLI - the command line interface
Deep Dive into AWS CLI - the command line interfaceDeep Dive into AWS CLI - the command line interface
Deep Dive into AWS CLI - the command line interfaceJohn Varghese
 
Jakub Kulhán - ReactPHP + Symfony = PROFIT (1. sraz přátel Symfony v Praze)
Jakub Kulhán - ReactPHP + Symfony = PROFIT (1. sraz přátel Symfony v Praze)Jakub Kulhán - ReactPHP + Symfony = PROFIT (1. sraz přátel Symfony v Praze)
Jakub Kulhán - ReactPHP + Symfony = PROFIT (1. sraz přátel Symfony v Praze)Péhápkaři
 
Webrtc mojo
Webrtc mojoWebrtc mojo
Webrtc mojobpmedley
 
Introducing Assetic (NYPHP)
Introducing Assetic (NYPHP)Introducing Assetic (NYPHP)
Introducing Assetic (NYPHP)Kris Wallsmith
 
Operation Oriented Web Applications / Yokohama pm7
Operation Oriented Web Applications / Yokohama pm7Operation Oriented Web Applications / Yokohama pm7
Operation Oriented Web Applications / Yokohama pm7Masahiro Nagano
 
Deep Dive: AWS Command Line Interface
Deep Dive: AWS Command Line InterfaceDeep Dive: AWS Command Line Interface
Deep Dive: AWS Command Line InterfaceAmazon Web Services
 
Building Cloud Castles
Building Cloud CastlesBuilding Cloud Castles
Building Cloud CastlesBen Scofield
 
Deep Dive: AWS Command Line Interface
Deep Dive: AWS Command Line InterfaceDeep Dive: AWS Command Line Interface
Deep Dive: AWS Command Line InterfaceAmazon Web Services
 
Deep Dive: AWS Command Line Interface
Deep Dive: AWS Command Line InterfaceDeep Dive: AWS Command Line Interface
Deep Dive: AWS Command Line InterfaceAmazon Web Services
 
Word Play in the Digital Age: Building Text Bots with Tracery
Word Play in the Digital Age: Building Text Bots with TraceryWord Play in the Digital Age: Building Text Bots with Tracery
Word Play in the Digital Age: Building Text Bots with TracerySarah Sexton
 
Phpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friendsPhpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friendsMichael Peacock
 
Amazon Cloud Services and Zend Framework
Amazon Cloud Services and Zend FrameworkAmazon Cloud Services and Zend Framework
Amazon Cloud Services and Zend FrameworkShahar Evron
 
Getting Started with Microsoft Bot Framework
Getting Started with Microsoft Bot FrameworkGetting Started with Microsoft Bot Framework
Getting Started with Microsoft Bot FrameworkSarah Sexton
 
Refresh Austin - Intro to Dexy
Refresh Austin - Intro to DexyRefresh Austin - Intro to Dexy
Refresh Austin - Intro to Dexyananelson
 
Asynchronous programming patterns in Perl
Asynchronous programming patterns in PerlAsynchronous programming patterns in Perl
Asynchronous programming patterns in Perldeepfountainconsulting
 
用Tornado开发RESTful API运用
用Tornado开发RESTful API运用用Tornado开发RESTful API运用
用Tornado开发RESTful API运用Felinx Lee
 
Realm: Building a mobile database
Realm: Building a mobile databaseRealm: Building a mobile database
Realm: Building a mobile databaseChristian Melchior
 

Tendances (20)

Deep Dive into AWS CLI - the command line interface
Deep Dive into AWS CLI - the command line interfaceDeep Dive into AWS CLI - the command line interface
Deep Dive into AWS CLI - the command line interface
 
Jakub Kulhán - ReactPHP + Symfony = PROFIT (1. sraz přátel Symfony v Praze)
Jakub Kulhán - ReactPHP + Symfony = PROFIT (1. sraz přátel Symfony v Praze)Jakub Kulhán - ReactPHP + Symfony = PROFIT (1. sraz přátel Symfony v Praze)
Jakub Kulhán - ReactPHP + Symfony = PROFIT (1. sraz přátel Symfony v Praze)
 
Webrtc mojo
Webrtc mojoWebrtc mojo
Webrtc mojo
 
Introducing Assetic (NYPHP)
Introducing Assetic (NYPHP)Introducing Assetic (NYPHP)
Introducing Assetic (NYPHP)
 
Operation Oriented Web Applications / Yokohama pm7
Operation Oriented Web Applications / Yokohama pm7Operation Oriented Web Applications / Yokohama pm7
Operation Oriented Web Applications / Yokohama pm7
 
Deep Dive: AWS Command Line Interface
Deep Dive: AWS Command Line InterfaceDeep Dive: AWS Command Line Interface
Deep Dive: AWS Command Line Interface
 
Mojo as a_client
Mojo as a_clientMojo as a_client
Mojo as a_client
 
Building Cloud Castles
Building Cloud CastlesBuilding Cloud Castles
Building Cloud Castles
 
Deep Dive: AWS Command Line Interface
Deep Dive: AWS Command Line InterfaceDeep Dive: AWS Command Line Interface
Deep Dive: AWS Command Line Interface
 
ES6 is Nigh
ES6 is NighES6 is Nigh
ES6 is Nigh
 
Deep Dive: AWS Command Line Interface
Deep Dive: AWS Command Line InterfaceDeep Dive: AWS Command Line Interface
Deep Dive: AWS Command Line Interface
 
Word Play in the Digital Age: Building Text Bots with Tracery
Word Play in the Digital Age: Building Text Bots with TraceryWord Play in the Digital Age: Building Text Bots with Tracery
Word Play in the Digital Age: Building Text Bots with Tracery
 
Phpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friendsPhpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friends
 
Amazon Cloud Services and Zend Framework
Amazon Cloud Services and Zend FrameworkAmazon Cloud Services and Zend Framework
Amazon Cloud Services and Zend Framework
 
Getting Started with Microsoft Bot Framework
Getting Started with Microsoft Bot FrameworkGetting Started with Microsoft Bot Framework
Getting Started with Microsoft Bot Framework
 
Refresh Austin - Intro to Dexy
Refresh Austin - Intro to DexyRefresh Austin - Intro to Dexy
Refresh Austin - Intro to Dexy
 
Asynchronous programming patterns in Perl
Asynchronous programming patterns in PerlAsynchronous programming patterns in Perl
Asynchronous programming patterns in Perl
 
用Tornado开发RESTful API运用
用Tornado开发RESTful API运用用Tornado开发RESTful API运用
用Tornado开发RESTful API运用
 
Realm: Building a mobile database
Realm: Building a mobile databaseRealm: Building a mobile database
Realm: Building a mobile database
 
Mojolicious
MojoliciousMojolicious
Mojolicious
 

Similaire à Play á la Rails

wwc start-launched
wwc start-launchedwwc start-launched
wwc start-launchedMat Schaffer
 
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
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with ClojureDmitry Buzdin
 
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasmineSingle Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasminePaulo Ragonha
 
Painless Persistence in a Disconnected World
Painless Persistence in a Disconnected WorldPainless Persistence in a Disconnected World
Painless Persistence in a Disconnected WorldChristian Melchior
 
PTW Rails Bootcamp
PTW Rails BootcampPTW Rails Bootcamp
PTW Rails BootcampMat Schaffer
 
Jan Stępień - GraalVM: Fast, Polyglot, Native - Codemotion Berlin 2018
Jan Stępień - GraalVM: Fast, Polyglot, Native - Codemotion Berlin 2018Jan Stępień - GraalVM: Fast, Polyglot, Native - Codemotion Berlin 2018
Jan Stępień - GraalVM: Fast, Polyglot, Native - Codemotion Berlin 2018Codemotion
 
Scala @ TechMeetup Edinburgh
Scala @ TechMeetup EdinburghScala @ TechMeetup Edinburgh
Scala @ TechMeetup EdinburghStuart Roebuck
 
A tour on ruby and friends
A tour on ruby and friendsA tour on ruby and friends
A tour on ruby and friends旻琦 潘
 
mobl - model-driven engineering lecture
mobl - model-driven engineering lecturemobl - model-driven engineering lecture
mobl - model-driven engineering lecturezefhemel
 
Nosql hands on handout 04
Nosql hands on handout 04Nosql hands on handout 04
Nosql hands on handout 04Krishna Sankar
 
Terrastore - A document database for developers
Terrastore - A document database for developersTerrastore - A document database for developers
Terrastore - A document database for developersSergio Bossa
 
Crossing the Bridge: Connecting Rails and your Front-end Framework
Crossing the Bridge: Connecting Rails and your Front-end FrameworkCrossing the Bridge: Connecting Rails and your Front-end Framework
Crossing the Bridge: Connecting Rails and your Front-end FrameworkDaniel Spector
 

Similaire à Play á la Rails (20)

wwc start-launched
wwc start-launchedwwc start-launched
wwc start-launched
 
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
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with Clojure
 
Play vs Rails
Play vs RailsPlay vs Rails
Play vs Rails
 
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasmineSingle Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
 
Painless Persistence in a Disconnected World
Painless Persistence in a Disconnected WorldPainless Persistence in a Disconnected World
Painless Persistence in a Disconnected World
 
How to React Native
How to React NativeHow to React Native
How to React Native
 
PTW Rails Bootcamp
PTW Rails BootcampPTW Rails Bootcamp
PTW Rails Bootcamp
 
Play framework
Play frameworkPlay framework
Play framework
 
Jan Stępień - GraalVM: Fast, Polyglot, Native - Codemotion Berlin 2018
Jan Stępień - GraalVM: Fast, Polyglot, Native - Codemotion Berlin 2018Jan Stępień - GraalVM: Fast, Polyglot, Native - Codemotion Berlin 2018
Jan Stępień - GraalVM: Fast, Polyglot, Native - Codemotion Berlin 2018
 
Scala @ TechMeetup Edinburgh
Scala @ TechMeetup EdinburghScala @ TechMeetup Edinburgh
Scala @ TechMeetup Edinburgh
 
Full Stack Scala
Full Stack ScalaFull Stack Scala
Full Stack Scala
 
Node.js
Node.jsNode.js
Node.js
 
A tour on ruby and friends
A tour on ruby and friendsA tour on ruby and friends
A tour on ruby and friends
 
mobl - model-driven engineering lecture
mobl - model-driven engineering lecturemobl - model-driven engineering lecture
mobl - model-driven engineering lecture
 
Nosql hands on handout 04
Nosql hands on handout 04Nosql hands on handout 04
Nosql hands on handout 04
 
Terrastore - A document database for developers
Terrastore - A document database for developersTerrastore - A document database for developers
Terrastore - A document database for developers
 
Crossing the Bridge: Connecting Rails and your Front-end Framework
Crossing the Bridge: Connecting Rails and your Front-end FrameworkCrossing the Bridge: Connecting Rails and your Front-end Framework
Crossing the Bridge: Connecting Rails and your Front-end Framework
 
mobl
moblmobl
mobl
 
AkJS Meetup - ES6++
AkJS Meetup -  ES6++AkJS Meetup -  ES6++
AkJS Meetup - ES6++
 

Dernier

Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesKari Kakkonen
 
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
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
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
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI AgeCprime
 
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesAssure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesThousandEyes
 
Data governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationData governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationKnoldus Inc.
 
Decarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityDecarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityIES VE
 
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
 
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Strongerpanagenda
 
Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Hiroshi SHIBATA
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demoHarshalMandlekar2
 
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentPim van der Noll
 
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Scott Andery
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesThousandEyes
 
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
 
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
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Farhan Tariq
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPathCommunity
 

Dernier (20)

Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examples
 
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
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
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
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI Age
 
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesAssure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
 
Data governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationData governance with Unity Catalog Presentation
Data governance with Unity Catalog Presentation
 
Decarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityDecarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a reality
 
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...
 
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
 
Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demo
 
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
 
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
 
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
 
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
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to Hero
 

Play á la Rails

  • 2. 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
  • 4.
  • 5. “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.”
  • 7.
  • 8. “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.”
  • 9. How Ruby is (self) perceived
  • 10. • Heavily inspired from Rails • Fun. Productive. Save + Reload. • Convention over Configuration. • Routing. REST. MVC... • ... but I missed some things ...
  • 11. ActiveRecord db:migrate Cucumber + Capybara Anorm? Slick? Evolutions? Specs? Rails’ vs. Play’s default offerings
  • 13. ActiveRecord db:migrate Cucumber + Capybara ActiveRecord (for Scala) Flyway Cucumber-JVM + Fluentlenium More “Rails-like” alternatives
  • 14.
  • 15. 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
  • 16. 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
  • 17. 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
  • 18.
  • 20. 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
  • 21. 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
  • 23. package db.migration class V1_03__CreateSomePosts extends JdbcMigration { override def migrate(ignoredConnection: Connection) { ... ... ... ... ... } } Code-based Migrations
  • 24. 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
  • 26. • Write in plain English • Separation of specification / implementation
  • 27. 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"
  • 28. 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
  • 29. • Part of Play2 • DSL wrapping Selenium • PhantomJS for headless testing Fluentlenium
  • 30. 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) => ... ... ... }
  • 31. 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
  • 33. 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
  • 35. 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 ;-)