In order to support UTFMB8 encoding I added the following default constraint in Config.groovy
grails.gorm.default.constraints = {
'*'(maxSize: 191)
unlimitedSize(maxSize: Integer.MAX_VALUE)
}
I also added the unlimitedSize shared constraint which I use in some of my domain classes to override this default, e.g.
class BlogPost {
String body
static constraints = {
body shared: 'unlimitedSize'
}
}
However, there are a couple of classes in plugins that also need to override the default maxSize of 191. In these cases, I can't use the shared constraint, because I can't edit the source code. One option is to copy the classes into my application, and edit the copies (because artifacts in an application override those in plugins), but this is not very appealing because I've then effectively forked those classes.
Is there a better way? For example, is it possible for me to add constraints to these domain classes in Bootstrap.groovy?
Constraints can be added during boostrap something like:
class BootStrap {
def grailsApplication
def init = { servletContext ->
grailsApplication.domainClasses.each { GrailsDomainClass gdc ->
Class domainClass = gdc.clazz
if (domainClass.simpleName == 'BookFromPlugin') {
def field = domainClass.declaredFields.find {
it.name == 'body' && it.type == String
}
if (field) {
domainClass.constraints.body.maxSize = Integer.MAX_VALUE
}
}
}
}
}
where BookFromPlugin is a domain class from plugin and body is a property from the domain class. This can be optimized and made applicable to more than one domain class.
Since bootstrap is the last thing that is taken care of, it should eventually override the constraint previously defined in domain class.
UPDATE:
I guess you meant domainClass.constraints is accessing the private variable from domain class, but that is not true. domain.constraints gives a map where propery name is mapped to all its constraints. This is map is taken from ConstrainedProperty which is comprised of 3 elements: class owning the constraint, property name where constraint will be applied and the type of the property.
So when we use domain.constraints.body it actually gives a list of constraints applied to body as the value for key body. Each element in the list is a ConstrainedProperty.
By calling setMaxSize() we are just adding another ConstrainedProperty to the list of constraints.
Related
I have two classes that are same but are present in different places. One inside framework and one in Normal App classes. I want to copy all the fields between them.
class Account {
var prodCode;
var subProdCode;
}
Same class inside the framework.
class Account {
var prodCode;
var subProdCode;
}
I need all fields to be copied from Object of 1st class to Object second class.
What is the best and easy way to do in Swift?
Add a method to MyAccout to update values of properties in your class, which accepts FrameworkAccount as parameter.
class MyAccout {
//...
func updateValues(account: FrameworkAccount) {
prodCode = account.prodCode
subProdCode = account.subProdCode
}
}
I've created a custom constraint (most code copied from NullableConstraint) that I'd like to use in my project.
How do I register this new constraint so I can use it in my domain classes and command objects? I've tried following this answer but that didn't work. I also tried copying the code from here but that didn't work either.
In your Config.groovy add the follow:
grails.gorm.default.constraints = {
validMobilePhone(validator: { value, obj, errors ->
if (!value) return
value = PhoneNumberUtils.sanitizeNumber(value)
if (!PhoneNumberUtils.validateMobilePhone(value)) {
errors.rejectValue('mobilePhone', "invalid")
}
})
nonNegative(min: new BigDecimal(0))
}
And then use this constraint in your domain:
static constraints = {
value shared: 'nonNegative'
}
I set up a few custom Constraint classes in a Grails 3 project and carried them forward to Grails 4.
In my Application class, I register the custom constraints to 2 constraint registries. There are a few methods on the Application class you can choose from to implement this. I don't know if my selection was the best.
void doWithDynamicMethods(){
//for domains
applicationContext.getBean(
org.grails.datastore.mapping.validation.ValidatorRegistry
).addConstraintFactory( someConstraintFactory )
//for command objects
(
(DefaultConstraintEvaluator)
applicationContext.getBean(
org.grails.datastore.gorm.validation.constraints.eval.ConstraintsEvaluator
)
).constraintRegistry.addConstraintFactory( someConstraintFactory )
}
I'm having trouble grasping the proper way of instantiating variables that always need to be set before an object is fully functional but may need to be instantiated after the constructor. Based on Swift's other conventions and restrictions it seems like there is a design pattern I'm unaware of.
Here is my use case:
I have a class that inherits from UIViewController and will programmatically create views based on user actions
I need to attach these views to this class, but to do so I need to retrieve their content based on configuration data supplied by another controller
I don't care if this configuration data is passed to the constructor (in which case it would always be required) or supplied by a secondary call to this object before it is used
My problem seems to be that both of the approaches in bullet 3 seem flawed.
In the first case, there is only one legitimate constructor this class can be called with, yet I'm forced to override other constructors and initialize member variables with fake values even if the other constructors are never intended to be used (I'm also trying to keep these variables as let types based on Swift's best practices).
In the second case, I'm effectively splitting my constructor into two parts and introduce an additional point of failure in case the second part fails to be called prior to class being used. I also can't move this second part to a method that's guaranteed to be called prior to usage (such as viewDidLoad) because I still need to pass in additional arguments from the config. While I can make sure to call the initPartTwo manually, I'd prefer to have a mechanism that better groups it with the actual constructor. I can't be the first one to run into this and it seems like there is a pattern I'm not seeing to make this cleaner.
UPDATE:
I ended up going with a modified version of the pattern matt suggested:
struct Thing {
let item1: String
let item2: String
struct Config {
let item3: String
let item4: String
}
var config:Config! {
willSet {
if self.config != nil {
fatalError("tried to initialize config twice")
}
}
}
init() {
self.item1 = ...
self.item2 = ...
...
}
public func phaseTwoInit(item3: String, item4: String) {
self.item3 = item3
self.item4 = item4
...
}
}
var t = Thing()
...
t.phaseTwoInit(...)
...
// start using t
If an initial instance variable property value can't be supplied at object initialization time, the usual thing is to declare it as an Optional. That way it doesn't need to be initialized by the class's initializers (it has a value - it is nil automatically), plus your code subsequently can distinguished uninitialized (nil) from initialized (not nil).
If the Optional if an implicitly unwrapped Optional, this arrangement need have no particular effect on your code (i.e. it won't have to be peppered with unwrappings).
If your objection is that you are forced to open the door to multiple settings of this instance variable because now it must be declared with var, then close the door with a setter observer:
struct Thing {
var name:String! {
willSet {
if self.name != nil {
fatalError("tried to set name twice")
}
}
}
}
var t = Thing()
t.name = "Matt" // no problem
t.name = "Rumplestiltskin" // crash
I would like to create a custom simple constraint (like display and editable) which I can use within my Domain class. Is it possible to extend ConstrainedProperty class?
class City {
String title
BigDecimal latitude
BigDecimal longitude
Country country
static constraints = {
title ( blank: false, customConstraint: true ) // filter can be also be applied as attributes: [customConstraint: true]
}
}
Somebody familiar with this case?
To create your own constraint:
extend org.codehaus.groovy.grails.validation.AbstractConstraint
register the class as a constraint by calling org.codehaus.groovy.grails.validation.ConstrainedProperty.registerNewConstraint
Take a look at the grails implementation of the size constraint for an example.
Is there a way to group domain object constraints? Something like this:
static constraints = {
personalDetails {
firstName(nullable: false)
}
address {
street(nullable: false)
}
}
Rich domain plugin does this for NON-domain objects... I want to do this FOR domain objects.
As i know this format does not supported by Grails. May be shared constraints will help you.