grails - beginners workshop - imada.sdu.dkjamik/gr8conf/grails - beginners workshop.pdf · grails...

68
GRAILS - BEGINNERS WORKSHOP Jacob Aae Mikkelsen

Upload: trankhanh

Post on 13-May-2018

239 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

GRAILS - BEGINNERS WORKSHOPJacob Aae Mikkelsen

Page 2: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

AGENDAInstalling Grails

Grails Intro

Application Scenario

Creating the application

Exercises

Page 3: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

JACOB AAE MIKKELSENSenior Engineer at Lego

Microservice based architechture on JVM

Previously 4 years at Gennemtænkt IT

Consultant on Groovy and Grails

External Associate Professor - University of SouthernDenmark

@JacobAae

Blogs The Grails Diary

Page 4: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

INSTALLING GRAILS

Page 5: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

USB WITH MATERIALOn the USB Sick passed around, the following materials are

available

These slides

Git repository with Grails application

Grails

IntelliJ editor

Bootstrap files

Page 6: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

MAC & LINUXUse Gvm tool

curl ­s get.gvmtool.net | bash

Restart terminal

gvm install grails 3.0.1

Page 7: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

WINDOWSOption 1: Use GVM Tool in Cygwin

Option 2: Use Posh-GVM in Powershell( )https://github.com/flofreud/posh-gvm

Option 3 Download Grails, and setup GRAILS_HOME(

)http://grails.asia/grails-tutorial-for-beginners-setup-your-

windows-development-environment/

Page 8: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

GRAILS INTROGrails is a full stack framework

-

Embrace the Don’t Repeat Yourself (DRY) principle

-

Encourages proper testing

-

Use the Groovy language and extensive use of DomainSpecific Languages (DSLs)

Page 9: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

INCLUDED WITH GRAILSObject Relational Mapping (ORM) layer → Hibernate

Expressive view technology → Groovy Server Pages (GSP)

Controller layer → Spring MVC

Interactive command line env and build system → Gradle

Embedded Tomcat container with on the fly reloading

Dependency injection → Spring container

i18n → Spring’s core MessageSource concept

Transactional service layer → Spring’s transactionabstraction

Page 10: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

LATEST VERSION: 3.0.1Groovy 2.4

Spring 4.1 and Spring Boot 1.2

Gradle Build System

Application Profiles

Redesigned API based on Traits

Filters → Interceptors

Main class → Easy to run from any IDE

Page 11: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

APPLICATION SCENARIOLets make a small conference application that can

keep track at what talks and workshops you haveattended

let attendees rate and supply feedback

Page 12: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

MODELWe need 3 domain classes in this small application

Attendee

Talk

Rating

Page 13: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

ATTENDEEName

Email

Which talks attended

Page 14: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

TALKSpeaker name

Starting time

List of ratings and comments

Page 15: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

RATINGAttendee who supplied the rating

The talk it rates

The rating (1-5)

Comment

Page 16: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

FUNCTIONALITYAttendees must be able to register which talks heattended

An attendee must be able to rate a talk from 1-5 andsubmit a comment too

A list of comments and an average grade must beavailable when vieving a talk

Page 17: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

STEP 1: CREATING THE APPLICATIONTo create a new Grails Application, run the grails

create-app command in a terminal

grails create­app eu­gr8conf­grailsdemo

Lets go through the tree view of whats generated

You don’t have to do the above step, if you clone thisrepo - then it is all done :)

git clone https://github.com/JacobAae/eu­gr8conf­grailsdemo.git

Page 18: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

WHATS GENERATED (1). build.gradle gradle wrapper gradle­wrapper.jar gradle­wrapper.properties gradle.properties gradlew gradlew.bat

Page 19: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

WHATS GENERATED (2) grails­app controllers UrlMappings.groovy domain services taglib utils views error.gsp index.gsp layouts main.gsp notFound.gsp

Page 20: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

WHATS GENERATED (3) grails­app assets images javascripts stylesheets conf application.yml logback.groovy spring resources.groovy i18n

Page 21: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

WHATS GENERATED (4) grails­app init BootStrap.groovy eu gr8conf grailsdemo Application.groovy

Page 22: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

WHATS GENERATED (5) src integration­test groovy main groovy webapp test groovy

Page 23: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

RUNNING OUR APPTo get to the interactive console:

grails

In interactive mode

run­app

Page 24: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

RESULTGo to: http://localhost:8080/

Page 25: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

STEP 2: FIRST DOMAIN CLASSLets create the first domin class with controller and views:

Attendee

Page 26: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

CREATING THE DOMAIN CLASSIn interactive mode

create­domain­class eu.gr8conf.grailsdemo.Attendee

Resulting in| Created grails-app/domain/eu/gr8conf/grailsdemo/Attendee.groovy| Created src/test/groovy/eu/gr8conf/grailsdemo/AttendeeSpec.groovy

Page 27: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

RUNNING TESTSIn interactive mode

test­app

Which fails since we have not yet implemented any test

Page 28: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

PROPERTIES AND CONSTRAINTSEdit the Attendee class to contain

String nameString emailString nationality

Date dateCreatedDate lastUpdated

static constraints = name blank: false email blank: false, unique: true, email: true nationality nullable: true

Page 29: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

GORMAdds lots of convenience

validate()

save()

get(id)

delete()

list()

Dynamic finders: Attendee.findByName('Jacob')

Page 30: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

TESTINGHere is an example of a test for constraints that are violated

@Unrollvoid "Test invalid properties for attendee: #comment"() when: Attendee attendee = new Attendee(name: name, email: email, nationality: nationality)

then: !attendee.validate()

where: name | email | nationality | comment '' | '[email protected]' | 'Danish' | 'Blank name'

INFO: Lets add positive and more negative tests for theconstraints.

Page 31: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

CONTROLLER AND VIEWSIn interactive mode

generate­all eu.gr8conf.grailsdemo.Attendee

And run the app again - and click the controller

Page 32: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

EXERCISEOpen AttendeeControllerSpec.groovy and update

it, so the tests passes

Page 33: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

STEP 3: MORE DOMAIN CLASSESLets make the other two domain classes, and see how they

can interact

Page 34: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

HINTS create­domain­class eu.gr8conf.grailsdemo.Talk create­domain­class eu.gr8conf.grailsdemo.Rating generate­all eu.gr8conf.grailsdemo.Talk generate­all eu.gr8conf.grailsdemo.Rating

Page 35: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

RELATIONSAttendee.groovy

static hasMany = [talks: Talk]

Talk.groovy

static belongsTo = Attendee // Where the addTo method will work from i.e. cascading savestatic hasMany = [attendees: Attendee,ratings: Rating]

Rating.groovy

static belongsTo = [talk:Talk]

Page 36: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

CONTROLLERSA controller handles requests and creates or prepares theresponse

Business logic placed elsewhere (services)

Placed in controller folder and ends in Controller

Methods → actions

Databinding

Page 37: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

VIEWS AND TEMPLATESMade with Groovy Server Pages (GSP)

Extensive suite of tags

formatting

looping

input fields

Page 38: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

CONTROLLERS AND VIEWSProblem: Lets make a new Display Attendee page, where we

can see talks attended better.

What to do:

Make a display action in the AttendeeController

Add a display.gsp view

add link to the new display or replace the show action

We could also rewrite the show action :)

Page 39: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

THE ACTIONdef display(Long id) Attendee attendee = Attendee.get(id) respond attendee

Page 40: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

THE VIEWCopy and paste the show.gsp view, and replace

<f:display bean="attendee" />

with

Page 41: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

THE VIEW (2)<ol class="property­list attendee"> <li class="fieldcontain"> <span id="name­label" class="property­label">Name</span> <span class="property­value" aria­labelledby="name­label"> $attendee.name</span></li> <!­­ email and nationalityleft out ­­> <li class="fieldcontain"> <span id="talks­label" class="property­label">Talks</span> <span class="property­value" aria­labelledby="talks­label"> <ul> <g:each in="$attendee.talks" var="talk"> <li>$talk.title</li> </g:each> </ul> </span> </li></ol>

Page 42: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

EXERCISESMake a link for each talk to go to an add rating page

Implement the add rating functionality

Page 43: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

STEP 4: SERVICESThe default code leaves too much logic in the controller, thisshould be in a service, that also should handle transactions

etc.

Lets try to cleanup the attendee controller and place someof the logic in a service

Page 44: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

SERVICESAre transactional by default

Easy to autoinject

Great place for logic and functionality

Page 45: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

HINTScreate­service eu.gr8conf.grailsdemo.AttendeeService

Page 46: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

USING SERVICES - AUTOINJECTIONIn the AttendeeController, where we will use the service, all

we need to do, is add this line

AttendeeService attendeeService

Then it will be autoinjected because Grails recognices thename

Page 47: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

CLEANING UP CONTROLLERSThe default generated controllers does everything

Lets cleanup the save method.

Page 48: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

HELPER CLASSESIn src/main/groovy you can place helper classes, or

non-Grails-artefacts

class Result def item Status status

enum Status OK, NOT_FOUND, HAS_ERRORS

Page 49: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

SERVICE METHODThe service method could look like

Result saveAttendee(Attendee attendee) if (attendee == null) transactionStatus.setRollbackOnly() return new Result(status: Status.NOT_FOUND) if (attendee.hasErrors()) transactionStatus.setRollbackOnly() return new Result(status: Status.HAS_ERRORS, item: attendee) attendee.save flush:true return new Result(status: Status.OK, item: attendee)

Page 50: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

CONTROLLERdef save(Attendee attendee) Result result = attendeeService.saveAttendee(attendee) switch( result.status) case Status.NOT_FOUND: notFound() break case Status.HAS_ERRORS: respond result.item.errors, view:'create' break case Status.OK: request.withFormat form multipartForm flash.message = message(code: 'default.created.message println attendee.dump() redirect attendee '*' respond attendee, [status: CREATED]

Page 51: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

TASKClean up the rest of the controller, removig everything that

needs the @Transactional annotation

Page 52: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

STEP 5: TAGLIBSTaglibs can help make the views more clean and DRY

Page 53: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

TAGLIBPlaced in grails-app/taglib

must end with TagLib.groovy

Closure taking parameters attrs and body

create­taglib eu.gr8conf.grailsdemo.RatingTagLib

Page 54: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

SERVICE TO CALCULATE AVERAGERATING

class TalkService

BigDecimal calculateAverageRating(Talk talk) if( !talk || !talk.ratings ) return null talk.ratings*.value.sum() / talk.ratings.size()

Page 55: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

THE TAGLIBTalkService talkService

def showRating = attrs ­> Talk talk = attrs.talk BigDecimal avg = talkService.calculateAverageRating(talk)

if( avg ) out << """<span class='average­rating'> $roundAverage(avg)</span>""" else out << "N/A" private roundAverage(BigDecimal average) "$Math.round(1.0 * average * 100) / 100 "

Page 56: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

TESTING TAGLIBSvoid "test output from showRating"() when: String output = tagLib.showRating(talk: new Talk(ratings: ratings), a ­> a )

then: output == expected

where: ratings | expected null | 'N/A' [new Rating(value: 5)] | "<span class='average­rating'>5</span>

Page 57: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

STEP 6: ASSETS, STYLING, PLUGINSAND LAYOUTS

Page 58: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

ASSETSJavascript, images and css files are handled by asset-

pipeline plugins

build.gradle

runtime "org.grails.plugins:asset­pipeline"

Compiles Less

Minifies JS

Combines files

Page 59: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

BOOTSTRAPLets include the (Twitter) Bootstrap project in our

application.

Page 60: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

BOOTSTRAPIn the grails-app/assets folder, place the Bootstrap

files

. fonts glyphicons­halflings­regular.eot ... + rest of fonts files images ... javascripts bootstrap.css.map bootstrap.js stylesheets bootstrap.css bootstrap­theme.css combined­bootstrap.css ...

Page 61: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

ASSET FILELets make a Bootstrap css asset package

combined-bootstrap.css

/**= require bootstrap*= require bootstrap­theme*= require_self*/

Page 62: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

LAYOUTSIn grails-app/views/layouts Layonts are placed

that can be reused across pages.

Page 63: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

LAYOUTSviews/layouts/bootstrap.gsp

<!doctype html><html lang="en" class="no­js"> <head> <meta http­equiv="Content­Type" content="text/html; charset=UTF­8 <meta http­equiv="X­UA­Compatible" content="IE=edge"> <title><g:layoutTitle default="Grails"/></title> <meta name="viewport" content="width=device­width, initial­scale=1 <asset:stylesheet src="combined­bootstrap.css"/> <asset:javascript src="application.js"/> <g:layoutHead/> </head> <body class="container"> <g:layoutBody/> <div class="footer" role="contentinfo"></div> <div id="spinner" class="spinner" style="display:none;"><g:message </body></html>

Page 64: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

USING LAYOUTSviews/attendee/display.gsp

<head> <meta name="layout" content="bootstrap">...

views/attendee/display.gsp

<g:link class="btn btn­primary" action="edit" resource="$attendee" <span class="glyphicon glyphicon­edit" aria­hidden="true"></span> <g:message code="default.button.edit.label" default="Edit" /></g:link>

Page 65: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

FIXING ICONSIn bootstrap.css, update the path to Glyphicons font

(line 267++)

views/attendee/display.gsp

@font­face font­family: 'Glyphicons Halflings'; src: url('../assets/fonts/glyphicons­halflings­regular.eot'); src: url('../assets/fonts/glyphicons­halflings­regular.eot?#iefix') format('embedded­opentype'), url('../fonts/glyphicons­halflings­regular.woff2') format('woff2'), url('../fonts/glyphicons­halflings­regular.woff') format('woff'), url('../fonts/glyphicons­halflings­regular.ttf') format('truetype'), url('../fonts/glyphicons­halflings­regular.svg#glyphicons_halflingsregular') format('svg');

Page 66: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

TASKSInclude Bootstrap

Restyle a page using a bootstrap layout

Page 67: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

EXERCISESShow the distribution of grades in the talk page (2*3, 2*4,4*5)

Page 68: GRAILS - BEGINNERS WORKSHOP - imada.sdu.dkjamik/gr8conf/Grails - Beginners Workshop.pdf · GRAILS INTRO Grails is a full stack framework-Embrace the Don’t Repeat Yourself (DRY)

LITERATUREhttp://gvmtool.net/

https://github.com/flofreud/posh-gvm

https://grails.org/single-page-documentation.html

http://getbootstrap.com/