Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions grails-forge/grails-forge-core/src/main/resources/gsp/index.gsp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<%@ page import="grails.util.Environment"%>
<%@ page import="grails.web.mime.MimeType"%>
<%@ page import="org.springframework.boot.SpringBootVersion"%>
<%@ page import="org.springframework.core.SpringVersion"%>
<%@ page import="org.springframework.util.ClassUtils"%>
Expand All @@ -8,7 +9,7 @@
value="${pluginManager.allPlugins.toList()
.withIndex()
.collect { p, i -> [plugin: p, order: ((int) i) + 1] }
.sort { a, b -> a.plugin.name.toLowerCase() <=> b.plugin.name.toLowerCase() }}"
.sort { Map row -> ((grails.plugins.GrailsPlugin) row.plugin).name.toLowerCase() }}"
/>
<g:def type="int" var="numControllers" value="${grailsApplication.controllerClasses.size()}"/>
<g:def type="int" var="numDomains" value="${grailsApplication.domainClasses.size()}"/>
Expand Down Expand Up @@ -455,11 +456,11 @@
<g:set var="domainsByPlugin"
value="${grailsApplication.domainClasses.toList()
.groupBy { dc ->
def plugin = null
try { plugin = pluginManager.getPluginForClass(dc.clazz) } catch (Throwable ignored) { }
plugin?.name ?: ''
String pluginName = ''
try { pluginName = pluginManager.getPluginForClass(dc.clazz)?.name ?: '' } catch (Throwable ignored) { }
pluginName
}
.sort { a, b -> a.key.toLowerCase() <=> b.key.toLowerCase() }}"/>
.sort { it.key.toLowerCase() }}"/>
<div id="domains-list">
<g:each var="pEntry" in="${domainsByPlugin}" status="pIndex">
<div class="${pIndex > 0 ? 'mt-4' : ''}" data-filter-group>
Expand Down Expand Up @@ -566,7 +567,7 @@
.collect { l -> [name: (l.getClass().simpleName ?: l.getClass().name.tokenize('.').last()),
packageName: (l.getClass().package?.name ?: ''),
detail: l.toString()] }
.sort { a, b -> (a.name.toLowerCase() <=> b.name.toLowerCase()) ?: (a.detail <=> b.detail) }}"/>
.sort { Map<String, String> a, Map<String, String> b -> (a.name.toLowerCase() <=> b.name.toLowerCase()) ?: (a.detail <=> b.detail) }}"/>
<g:set var="bindingGroups"
value="${[[code: 'welcome.binding.value', beans: applicationContext.getBeansOfType(grails.databinding.converters.ValueConverter)],
[code: 'welcome.binding.formatted', beans: applicationContext.getBeansOfType(grails.databinding.converters.FormattedValueConverter)],
Expand Down Expand Up @@ -1341,7 +1342,7 @@
<g:set var="mimeTypes"
value="${applicationContext.containsBean('mimeTypes') ?
applicationContext.getBean('mimeTypes').toList()
.sort { a, b -> ((a.extension ?: '').toLowerCase() <=> (b.extension ?: '').toLowerCase()) ?: (a.name <=> b.name) } : []}"/>
.sort { MimeType a, MimeType b -> ((a.extension ?: '').toLowerCase() <=> (b.extension ?: '').toLowerCase()) ?: (a.name <=> b.name) } : []}"/>
<div class="card border-1 shadow-sm mt-4">
<div class="card-body">
<div class="d-flex align-items-center justify-content-between mb-3">
Expand Down
14 changes: 10 additions & 4 deletions grails-gsp/core/src/main/groovy/org/grails/gsp/GroovyPage.java
Original file line number Diff line number Diff line change
Expand Up @@ -179,11 +179,17 @@ public void initRun(Writer target, OutputContext outputContext, GroovyPageMetaIn

private void applyModelFieldsFromBinding(Iterable<Field> modelFields) {
for (Field field : modelFields) {
Object value = getProperty(field.getName());
if (value == null) {
continue;
}
try {
Object value = getProperty(field.getName());
if (value != null) {
field.set(this, value);
}
field.set(this, value);
} catch (IllegalArgumentException e) {
throw new GroovyPagesException("Model field '" + field.getName() + "' is declared as " +
field.getType().getName() + " but the model supplied an instance of " +
value.getClass().getName() + ". Declare the field with a type the model value is " +
"assignable to; model values are not coerced.", e, -1, getGroovyPageFileName());
} catch (IllegalAccessException e) {
throw new GroovyPagesException("Error setting model field '" + field.getName() + "'", e, -1, getGroovyPageFileName());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,40 @@ Date d4=new Date(123L)
rendered == '123-456-789-123'
}

def "model field is applied when the model supplies the declared type"() {
given:
def template = '''@{ model="Long sampleCount"}${sampleCount}'''
when:
def rendered = renderTemplate(template, [sampleCount: 42L], true)
then:
rendered == '42'
}

def "a Number model field accepts every numeric type a controller may supply"() {
given:
def template = '''@{ model="Number sampleCount"}${sampleCount}'''
when:
def rendered = renderTemplate(template, [sampleCount: supplied], true)
then:
rendered == '42'
where:
// scaffolded controllers supply Long via the generated service and Integer
// via RestfulController.countResources()
supplied << [42 as Integer, 42L, 42 as Short, 42 as BigInteger]
}

def "a model value of the wrong type names the field and both types"() {
given:
def template = '''@{ model="Integer sampleCount"}${sampleCount}'''
when:
renderTemplate(template, [sampleCount: 42L], true)
then:
GroovyPagesException e = thrown()
e.message.contains("Model field 'sampleCount'")
e.message.contains('java.lang.Integer')
e.message.contains('java.lang.Long')
}

def renderTemplate(templateSource, model, expectedCompileStaticMode, printSource = false) {
def t = gpte.createTemplate(templateSource, "template${templateSource.hashCode()}")
assert t.metaInfo.compilationException == null
Expand Down
15 changes: 8 additions & 7 deletions grails-profiles/web/skeleton/grails-app/views/index.gsp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<%@ page import="grails.util.Environment"%>
<%@ page import="grails.web.mime.MimeType"%>
<%@ page import="org.springframework.boot.SpringBootVersion"%>
<%@ page import="org.springframework.core.SpringVersion"%>
<%@ page import="org.springframework.util.ClassUtils"%>
Expand All @@ -8,7 +9,7 @@
value="${pluginManager.allPlugins.toList()
.withIndex()
.collect { p, i -> [plugin: p, order: ((int) i) + 1] }
.sort { a, b -> a.plugin.name.toLowerCase() <=> b.plugin.name.toLowerCase() }}"
.sort { Map row -> ((grails.plugins.GrailsPlugin) row.plugin).name.toLowerCase() }}"
/>
<g:def type="int" var="numControllers" value="${grailsApplication.controllerClasses.size()}"/>
<g:def type="int" var="numDomains" value="${grailsApplication.domainClasses.size()}"/>
Expand Down Expand Up @@ -455,11 +456,11 @@
<g:set var="domainsByPlugin"
value="${grailsApplication.domainClasses.toList()
.groupBy { dc ->
def plugin = null
try { plugin = pluginManager.getPluginForClass(dc.clazz) } catch (Throwable ignored) { }
plugin?.name ?: ''
String pluginName = ''
try { pluginName = pluginManager.getPluginForClass(dc.clazz)?.name ?: '' } catch (Throwable ignored) { }
pluginName
}
.sort { a, b -> a.key.toLowerCase() <=> b.key.toLowerCase() }}"/>
.sort { it.key.toLowerCase() }}"/>
<div id="domains-list">
<g:each var="pEntry" in="${domainsByPlugin}" status="pIndex">
<div class="${pIndex > 0 ? 'mt-4' : ''}" data-filter-group>
Expand Down Expand Up @@ -566,7 +567,7 @@
.collect { l -> [name: (l.getClass().simpleName ?: l.getClass().name.tokenize('.').last()),
packageName: (l.getClass().package?.name ?: ''),
detail: l.toString()] }
.sort { a, b -> (a.name.toLowerCase() <=> b.name.toLowerCase()) ?: (a.detail <=> b.detail) }}"/>
.sort { Map<String, String> a, Map<String, String> b -> (a.name.toLowerCase() <=> b.name.toLowerCase()) ?: (a.detail <=> b.detail) }}"/>
<g:set var="bindingGroups"
value="${[[code: 'welcome.binding.value', beans: applicationContext.getBeansOfType(grails.databinding.converters.ValueConverter)],
[code: 'welcome.binding.formatted', beans: applicationContext.getBeansOfType(grails.databinding.converters.FormattedValueConverter)],
Expand Down Expand Up @@ -1341,7 +1342,7 @@
<g:set var="mimeTypes"
value="${applicationContext.containsBean('mimeTypes') ?
applicationContext.getBean('mimeTypes').toList()
.sort { a, b -> ((a.extension ?: '').toLowerCase() <=> (b.extension ?: '').toLowerCase()) ?: (a.name <=> b.name) } : []}"/>
.sort { MimeType a, MimeType b -> ((a.extension ?: '').toLowerCase() <=> (b.extension ?: '').toLowerCase()) ?: (a.name <=> b.name) } : []}"/>
<div class="card border-1 shadow-sm mt-4">
<div class="card-body">
<div class="d-flex align-items-center justify-content-between mb-3">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@{ model="List<${fullName}> ${propertyName}List; Integer ${propertyName}Count" }
@{ model="List<${fullName}> ${propertyName}List; Number ${propertyName}Count" }
<!DOCTYPE html>
<html>
<head>
Expand Down
Loading