Flask-WTF: How to allow zero upon DataRequired() validation - validation

I have defined a form like this:
class RecordForm(Form):
rating = IntegerField('Rating')
If no value is inserted I get a default message like this:
Not a valid integer value
I would like to have a custom message instead, so I came up with this:
class RecordForm(Form):
rating = IntegerField('Rating',[validators.DataRequired("Helllo???")])
The custom message works now, but I get a side effect. 0 (zero) is no longer accepted as an integer value. What are my options here please?

Use InputRequired instead:
class RecordForm(Form):
rating = IntegerField('Rating',[validators.InputRequired("You got to enter some rating!")])
From the docs:
Note there is a distinction between this and DataRequired in that InputRequired looks that form-input data was provided, and DataRequired looks at the post-coercion data.
(Emphasis mine)

Related

Fetch value from XML using dynamic tag in ESQL

I have an xml
<family>
<child_one>ROY</child_one>
<child_two>VIC</child_two>
</family>
I want to fetch the value from the XML based on the dynamic tag in ESQL. I have tried like this
SET dynamicTag = 'child_'||num;
SET value = InputRoot.XMLNSC.parent.(XML.Element)dynamicTag;
Here num is the value received from the input it can be one or two. The result should be value = ROY if num is one and value is VIC if num is two.
The chapter ESQL field reference overview describes this use case:
Because the names of the fields appear in the ESQL program, they must be known when the program is written. This limitation can be avoided by using the alternative syntax that uses braces ( { ... } ).
So can change your code like this:
SET value = InputRoot.XMLNSC.parent.(XMLNSC.Element){dynamicTag};
Notice the change of the element type as well, see comment of #kimbert.

Using one variable for multiple items data in descriptive programming

I know that with Descriptive programming you can do something like this:
Browser("StackOverflow").Page("StackOverflow").Link("text:=Go To Next Page ", "html tag:=A").Click
But is it possible to create some kind of string so I can assign more than one data value and pass it as single variable? I've tried many combinations using escape characters and I always get error.
For example in the case above, let's say I have more properties in the Page object, so I'd normally have to do something like this:
Browser("StackOverflow").Page("name:=StackOverflow", "html id:=PageID")...etc...
But I'd like to pass "name:=StackOverflow", "html id:=PageID" as a single variable, so when writing many objects I'd only have to write:
Browser(BrowserString).Page(PageString).WebEdit("name:=asdfgh")
And the first part would remain static, so if the parents' data needs to be modified I'd only have to modify two variables and not all the objects created in all libraries.
Is it possible?
If I was not clear enough please let me know.
Thank you in advance!
I think what you're looking for is UFT's Description object
This allows you finer grained control on the description since in descriptive programming all values are regular expressions but with Description you can turn the regular expression functionality off for a specific property.
Set desc = Description.Create()
desc("html tag").Value = "A"
desc("innertext").Value = "More information..."
desc("innertext").RegularExpression = False
Browser("Example Domain").Navigate "www.example.com"
Browser("Example Domain").Page("Example Domain").WebElement(desc).Click
If you want to represent this with plain string then it's a bit more of a problem, you can write a helper function but I'm not sure I would recommend it.
Function Desc(descString)
Set ret = Description.Create()
values = Split(descString, "::")
For Each value In values
keyVal = Split(value, ":=")
ret(keyVal(0)).Value = keyVal(1)
Next
Set Desc = ret
End Function
' Usage
Browser("StackOverflow").Page("StackOverflow").WebElement(Desc("html tag:=H2::innertext:=some text")).Click
Further reading about descriptive programming.
As an alternative to Motti's excellent answer, you could also Set a variable to match your initial descriptive object and then extend it as required:
Set myPage = Browser("StackOverflow").Page("name:=StackOverflow", "html id:=PageID")
after which you can then use
myPage.WebEdit("name:=asdfgh")
throughout the rest of the code, so long as the myPage object stays in scope...

how to send arguments on messages.properties when JSR 303 validation

I have a class something like
class Sample{
#Min(1) #Max(20) private int num_seats;
...
}
and messages.properties like
Min.sample.num_seats = the number must be bigger than 1
Question is
how can I set the message dynamically by sending arguments as like "the number must bigger than {MIN_VALUE}"?
how can I share the message? such like "Min.* = the number .... " is possible?
Thank you Ralph it has helped me a lot to find a solution.
I would just add this:
I would use #Range in this case (except if you want two different message for min and max).
In Sample class
#Range(min = 1, max = 20)
private int num_seats;
And in messages.properties file
Range.sample.num_seats=The number must be between {2} and {1}.
Note that the min is argument numbered {2} and max is numbered {1} !
According to SPR-6730 (Juergen Hoellers comment) it should work in this way:
#Min(value="1", message="the number must be higher than {1}")
I have not tested it, but this is the way, I have understand the issue comment.
second question: You can share the text, be putting them in a message properties file.
If you use the same key as the default does, then you override the default message. If you want not to override the default message, then you need an other key, and need to write the key in currly brackets in the message attribute.
message properties file
javax.validation.constraints.Min.message=My mew default message
someOtherKey=Some Other Message
Using the other key:
#Min(value="1", message="{someOtherKey}")

How to print validation error outside of field constructor in Play framework 2

How can I show a validation error for a form field outside of a field constructor in Play framework 2? Here is what I tried:
#eventForm.("name").error.message
And I get this error:
value message is not a member of Option[play.api.data.FormError]
I'm confused because in the api docs it says message is a member of FormError. Also this works fine for global errors:
#eventForm.globalError.message
You can get a better grasp of it checking Form's sourcecode here
Form defines an apply method:
def apply(key: String): Field = Field(
this,
key,
constraints.get(key).getOrElse(Nil),
formats.get(key),
errors.collect { case e if e.key == key => e },
data.get(key))
That, as said in the doc, returns any field, even if it doesn't exist. And a Field has an errors member which returns a Seq[FormError]:
So, you could do something like that (for the Seq[FormError]):
eventForm("name").errors.foreach { error =>
<div>#error.message</div>
}
Or (for the Option[FormError])
eventForm("name").error.map { error =>
<div>#error.message</div>
}
Or, you could use Form errors:
def errors(key: String): Seq[FormError] = errors.filter(_.key == key)
And get all errors of a given key. Like this (for the Seq[FormError]):
eventForm.errors("name").foreach { error =>
<div>#error.message</div>
}
Or (for the Option[FormError])
eventForm.error("name").map { error =>
<div>#error.message</div>
}
If you want more details, check the source code. It's well written and well commented.
Cheers!
EDIT:
As biesior commented: to show human readable pretty messages with different languages you have to check how play works I18N out here
To be thorough you're probably going to have to deal with I18N. It's not hard at all to get it all working.
After reading the documentation you may still find yourself a bit consufed. I'll give you a little push. Add a messages file to your conf folder and you can copy its content from here. That way you'll have more control over the default messages. Now, in your view, you should be able to do something like that:
eventForm.errors("name").foreach { error =>
<div>#Messages(error.message, error.args: _*)</div>
}
For instance, if error.message were error.invalid it would show the message previously defined in the conf/messages file Invalid value. args define some arguments that your error message may handle. For instance, if you were handling an error.min, an arg could be the minimum value required. In your message you just have to follow the {n} pattern, where n is the order of your argument.
Of course, you're able to define your own messages like that:
error.futureBirthday=Are you sure you're born in the future? Oowww hay, we got ourselves a time traveler!
And in your controller you could check your form like that (just one line of code to show you the feeling of it)
"year" -> number.verifying("error.furtureBirthday", number <= 2012) // 2012 being the current year
If you want to play around with languages, just follow the documentation.
Cheers, again!
As you said yourself, message is a member of FormError, but you have an Option[FormError]. You could use
eventForm("name").error.map(_.message).getOrElse("")
That gives you the message, if there is an error, and "" if there isn't.

Ruby: How to get a class based on class name and how can I get object's field based on field name?

Question 1
How to get a class given a class name as a string ?
For example, say Product class has do_something method:
str = "product"
<what should be here based on str?>.do_something
Question 2
How to get object's field given a field name as a string ?
For example, say Product class has price field:
str = "price"
product = Product.new
product.<what should be here based on str?> = 1200
Jacob's answer to the first question assumes that you're using Rails and will work fine if you are. In case you're not you can call Kernel::const_get(str) to find an existing constant by name.
send is a pure ruby. There's no need to intern your strings with send though (convert them to symbols), straight strings work fine.
Use capitalize and constantize:
str.capitalize.constantize.do_something
Use send:
product.send(str + '=', 1200)

Resources