contains() method is not working - grails

I receive JSON data as below,
def data = JSON.parse(params.company) //it's [name:foo, users:[1,2,3]]
And I want to check if it contained. I did like this,
if(data.users.contains(2)){
println 'true'
}
else {
println 'false'
}
It's always print 'false'
But when I try by new data like
def test = [1,2,3]
if(test.contains(2)){
println 'true'
}
else {
println 'false'
}
It's 'true'.

Although you said in a comment that you solved it, I think you did it the wrong way.
You should try
def test = [1,2,3]
if(test.contains('2')){
println 'true'
}
else {
println 'false'
}
You have to understand that 2 == '2' is false. Types matters.

Related

How to put a variable into script scope?

I've been using Parametrized-pipelines in Jenkins and notice that while using parameters, the value is both useable from script scope as well as via params.variable.
PARAMETER == true
params.PARAMETER == true
In groovy, is it possible to add a variable to script scope from within a method? I would like to get similar functionality as the following...
// I don't want to have to declare value here
def function1(){
value = 1
}
def function2(){
assert value == 1
}
function1()
function2()
Is there a way to access value from within function2 without doing something like...
value = 0
def function1() {
value = 1
...
Could also do somthing like :
def f1() {
env.aaa = "hello"
}
def f2() {
assert aaa=="hello"
}
node{
f1()
f2()
}
Essentially setting it as an environment variable.
this pipeline works fine:
def f1(){
aaa = "hello"
}
def f2(){
assert aaa=="hello"
}
node{
f1()
f2()
}
the pipeline definition as actually an instance of org.jenkinsci.plugins.workflow.cps.CpsScript that extends groovy.lang.Script
so groovy script properties should work here.
You can use scope variable in script
import groovy.transform.Field
#Field List awe = [1, 2, 3]
def awesum() { awe.sum() }
assert awesum() == 6
http://docs.groovy-lang.org/2.4.9/html/gapi/groovy/transform/Field.html

Grails / Spock testing .. unexpected error thrown

Using spock to unit test a comand object .. I have a line in the command object ..
some code ..
} else {
if ((val && obj.part) && obj.transactionType.transactionIsATransfer()) {
println "obj.part .. class is ${obj.part.getClass()} .. serial is ${val.getClass()}"
if(! isAValidPartSerialCombo(obj.part,val)) <-- line 79
return 'com.myStuff.TransactionDetailCommand.serialReference.not.for.part'
}
..
def isAValidPartSerialCombo {part, serialReference ->
return InventoryMaster.hasPartandSerial(part,serialReference)
}
I have a unit test where I mock out the dependency
def obj = new TransactionDetailCommand(transactionType: new TransactionType(type: 'Transfer', requireSerial: true),
serialReference: 'AAA', part: new Part(partNumber: 'AAA'))
obj.metaClass.isAValidPartSerialCombo = {a,b -> false}
and: "we try to validate the transaction "
obj.validate()
then: "we get an error on the transaction for the 'serialReference' property"
obj.errors['serialReference']
which is giving me an error ..
java.lang.IllegalArgumentException: object is not an instance of declaring class
at com.vantec.TransactionDetailCommand._clinit__closure1_closure7(TransactionDetailCommand.groovy:90)
at grails.test.MockUtils.addValidateMethod_closure87_closure114(MockUtils.groovy:1035)
at grails.test.MockUtils.addValidateMethod_closure87(MockUtils.groovy:1031)
at grails.test.MockUtils.addValidateMethod_closure88(MockUtils.groovy:1065)
at com.myStuff.transaction.TransactionDetailCommandSpec.Ensure that for issues / transfer transactions then serial/part numbers are required to match .. (TransactionDetailCommandSpec.groovy:79)
However if I create a separate dummy test it works without a problem ..
def "A simple test .. "(){
when:
def obj = new TransactionDetailCommand()
obj.metaClass.isAValidPartSerialCombo = {a,b -> false}
then: 'we get a false ..'
!obj.isAValidPartSerialCombo(new Part(),"AAA")
}
Can anyone shed any light ??
Thanks
Complete test ...
def "Ensure that for issues / transfer transactions then serial/part numbers are required to match .. "(){
when: "The transaction type indicates a transfer and we supply a serial number and a part .."
def obj = new TransactionDetailCommand(transactionType: new TransactionType(type: 'Transfer', requireSerial: true),
serialReference: '12345', part: new Part(partNumber: 'PartA'))
obj.metaClass.isAValidPartSerialCombo = {a,b -> false}
and: "we try to validate the transaction "
obj.validate()
then: "we get an error on the transaction for the 'serialReference' property"
obj.errors['serialReference']
and: "the error is the correct one .."
'com.myStuff.TransactionDetailCommand.serialReference.not.for.part' == obj.errors['serialReference']
}
and the constraint i'm testing ..
serialReference nullable: true, validator: { val, obj ->
println "One .. "
if ((val == null || val.toString().isEmpty()) && obj.transactionType.requireSerial) {
println "Two .. "
return 'com.myStuff.TransactionDetailCommand.serialReference.required'
} else {
println "Three .. "
if ((val && obj.part) && obj.transactionType.transactionIsATransfer()) {
println "Four ..."
if(! isAValidPartSerialCombo(obj.part, val)){
println("Five .. ")
return 'com.myStuff.TransactionDetailCommand.serialReference.not.for.part'
}
}
}
return 'oops'
}
def isAValidPartSerialCombo = {part, serialReference ->
println "Six .."
// return InventoryMaster.hasPartandSerial(part,serialReference)
return true
}
The println's are just so I can see where the code goes ..
Not sure about it, but it would be worthy to give a try to mock the instance of obj after the creation of the instance
mockDomain(TransactionDetailCommand, [obj])
Try to organise in that way your test:
def "Ensure that for issues / transfer transactions then serial/part numbers are required to match .. "(){
given: "The transaction type indicates a transfer and we supply a serial number and a part .."
def obj = new TransactionDetailCommand(transactionType: new TransactionType(type: 'Transfer', requireSerial: true),
serialReference: '12345', part: new Part(partNumber: 'PartA'))
obj.metaClass.isAValidPartSerialCombo = {a,b -> false}
when: "we try to validate the transaction "
obj.validate()
then: "we get an error on the transaction for the 'serialReference' property"
obj.errors['serialReference']
and: "the error is the correct one .."
'com.myStuff.TransactionDetailCommand.serialReference.not.for.part' == obj.errors['serialReference']
}
as the creation of the object and the metaprogramming are all set up actions.

Checking if a collection is null or empty in Groovy

I need to perform a null or empty check on a collection; I think that !members?.empty is incorrect. Is there a groovier way to write the following?
if (members && !members.empty) {
// Some Work
}
There is indeed a Groovier Way.
if (members) {
//Some work
}
does everything if members is a collection. Null check as well as empty check (Empty collections are coerced to false). Hail Groovy Truth. :)
FYI this kind of code works (you can find it ugly, it is your right :) ) :
def list = null
list.each { println it }
soSomething()
In other words, this code has null/empty checks both useless:
if (members && !members.empty) {
members.each { doAnotherThing it }
}
def doAnotherThing(def member) {
// Some work
}
!members.find()
I think now the best way to solve this issue is code above. It works since Groovy 1.8.1 http://docs.groovy-lang.org/docs/next/html/groovy-jdk/java/util/Collection.html#find(). Examples:
def lst1 = []
assert !lst1.find()
def lst2 = [null]
assert !lst2.find()
def lst3 = [null,2,null]
assert lst3.find()
def lst4 = [null,null,null]
assert !lst4.find()
def lst5 = [null, 0, 0.0, false, '', [], 42, 43]
assert lst5.find() == 42
def lst6 = null;
assert !lst6.find()

Create dynamically closures in Groovy from a String object

i would like to create a query with the Criteria API in Grails (GORM).
The query will have to be something like this:
MyEntity.createCriteria().list{
assoc{
parent{
eq("code", val)
}
}
}
What i need is to build the nested closure dynamically from a String object. The String for the example above will be "assoc.parent.code" . I splitted the String by dot (by doing String.split("\\.") ) but i don't know how to construct the nested closures:
assoc{
parent{
eq("code", val)
}
}
dynamically based on the array of the splitted Strings above.
What about createAlias?. You could try something like this:
def path = "assoc.parent.code"
def split = path.split(/\./)
MyEntity.createCriteria().list {
// this will get you 'createAlias( assoc.parent, alias1 )'
createAlias split.take( split.size() - 1 ), "alias1"
// this will get you 'eq(alias1.code, userInput)'
eq "alias1.${split[-1]}", userInput
}
This snippet is not generic, but you get the idea.
Update
Not conventional, but you can build a string containing the code with the closures and evaluate it using GroovyShell:
assoc = 'assoc.parent.child.name'
split = assoc.split( /\./ )
path = split[-2..0] // will get us 'child.parent.assoc';
// we will build it from inside-out
def firstClosure = "{ eq '${split[-1]}', 'john doe' }"
def lastClosure = firstClosure
for (entity in path) {
def criteriaClosure = "{ ${entity} ${lastClosure} }"
lastClosure = criteriaClosure
}
assert lastClosure == "{ assoc { parent { child { eq 'name', 'john doe' } } } }"
def builtClosure = new GroovyShell().evaluate("return " + lastClosure)
assert builtClosure instanceof Closure
A more generic approach would be to metaClass String as below, and use it for any kind of separator
. | , - ~ and more.
String.metaClass.convertToClosureWithValue = {op, val ->
split = delegate.split(op) as List
if(split.size() == 1) {return "Cannot split string '$delegate' on '$op'"}
items = []
split.each{
if(it == split.last()){
items << "{ eq '$it', $val }"
split.indexOf(it).times{items.push("}")}
} else {
items << "{$it"
}
}
println items.join()
new GroovyShell().evaluate("return " + items.join())
}
assert "assoc.parent.child.name".convertToClosureWithValue(/\./, "John Doe") instanceof Closure
assert "assoc-parent-child-name".convertToClosureWithValue(/\-/, "Billy Bob") instanceof Closure
assert "assoc|parent|child|grandChild|name".convertToClosureWithValue(/\|/, "Max Payne") instanceof Closure
assert "assoc~parent~child~grandChild~name".convertToClosureWithValue('\\~', "Private Ryan") instanceof Closure
assert "assocparentchildname".convertToClosureWithValue(/\|/, "Captain Miller") == "Cannot split string 'assocparentchildname' on '\\|'"
//Print lines from items.join()
{assoc{parent{child{ eq 'name', John Doe }}}}
{assoc{parent{child{ eq 'name', Billy Bob }}}}
{assoc{parent{child{grandChild{ eq 'name', Max Payne }}}}}
{assoc{parent{child{grandChild{ eq 'name', Private Ryan }}}}}

rails rspec, any way to handle multiple 'should' for the same example via a block?

Suppose the model method foo() returns an array [true, false, 'unable to create widget']
Is there a way to write an rspec example that passes that array as a block that verifies [0] = true, [1] = false, and [2] matches a regex like /
Currently, I do it like:
result = p.foo
result[2].should match(/unable/i)
result[0].should == true
result[1].should == false
I can't quite get my head around how that might be doable with a block?
It would be slightly over engineered but try to run this spec with --format documentation. You will see a very nice specdocs for this method ;)
describe '#some_method' do
describe 'result' do
let(:result) { subject.some_method }
subject { result }
it { should be_an_instance_of(Array) }
describe 'first returned value' do
subject { result.first }
it { should be_false }
end
describe 'second returned value' do
subject { result.second }
it { should be_true }
end
describe 'third returned value' do
subject { result.third }
it { should == 'some value' }
end
end
end
Do you mean that your result is an array and you have to iterate over to test it's various cases?
Then, you can do that by following, right:
result = p.foo
result.each_with_index do |value, index|
case index
when 0 then value.should == true
when 1 then value.should == false
when 2 then value.shoud match(/unable/i)
end
end

Resources