Access Spock data provider variable from inside where: block - spring

I'm trying to access a where block variable from within the where block and it is not working. I'm thinking Spock doesn't allow this, but thought I'd give it a shot and see if anyone knows how to do it.
where:
testNumber << Stream.iterate(1, n -> n).iterator()
test << Stream.generate(() -> { testNumber > 15 }).iterator()
Result:
No such property: testNumber for class
If this isn't possible and someone has an alternative way to accomplish something similar I'm open to that. Basically I'm trying to make this test easier to manage, because keeping track of multiple arrays of 15-20 booleans is a bit of a pain:
testNumber << [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
post << [false, false, false, false, true, true, true, true, true, true, true, true, true, true, true, true]
postWeekend << [true, true, true, true, true, true, false, false, false, false, false, false, false, false, false]
dividendReinvested << [true, false, true, false, true, true, false, true, true, true, true, true, true, true, true]
createCCB << [false, false, false, false, false, false, false, false, false, false, false, false, false, false, true]
ntd << [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false]
But many of them I can set up based on the test number instead, if I can access it (and having the test number available also makes it easy to determine which test failed).

It looks like you want to calculate something based on testNumber.
You can use data variables for that.
Another problem is that you are using an infinite stream, which will not terminate before the jvm will run out of memory. So you need to either use .limit(20) or just use a groovy range to define it more succinctly.
import spock.lang.*
class ASpec extends Specification {
def "hello world"() {
expect:
testNumber > 15 == test
where:
testNumber << (1..20)
test = testNumber > 15
}
}
Try it in the Groovy Web Console.
If that isn't what you wanted then you should update your question as #kriegaex suggested to tell us what you actually want to achieve.

Please do not accept this answer, Leonard's one solved the original problem. I am just presenting some more details.
The Spock manual explains how to access other data variables inside a where block.
Additionally, if in another situation you only need the iteration index in the unrolled method name, but not inside the feature method itself, you can use #iterationIndex. The count starts at index 0. Here is an example showing you both:
package de.scrum_master.stackoverflow.q70661506
import spock.lang.Shared
import spock.lang.Specification
class ReferringToDataTableVariablesTest extends Specification {
#Shared
final n = 8
def "feature [#iterationIndex]: #testNumber, #testRange"() {
println "$testNumber, $testRange, ${testClosure()}"
expect:
true
where:
testNumber << (1..n)
testRange = testNumber + 3..2 * testNumber
testClosure = { -> testNumber / 2 > 2 }
}
}
Try it in the Groovy Web Console.
In my IDE, running the test looks like this:

Related

Merge multiple hashes after new key

I've got three hashes which I want to merge to base_options under new key - checks. Basically what I want to achieve is:
{
base_options,
checks: {
document_check,
identity_check,
dummy_check,
}
},
Below sample hash data:
dummy_check = {
dummy: {
enabled: true,
preferences: {
state: 0,
replay: true,
},
}
}
identity_check = {
identity: {
enabled: true,
preferences: {},
},
}
document_check = {
document: {
enabled: true,
preferences: {
face: false,
liveness: false,
docs_all: true,
},
},
}
base_options = {
send_email: true,
send_reminder: false,
reset_client_status: true,
}
So if I do base_options.merge!(checks: document_check.merge!(identity_check, dummy_check)) I will receive expected hash which is:
{
send_email: true,
send_reminder: false,
reset_client_status: true,
checks: {
document: {
...
},
identity: {
...
},
dummy: {
...
}
},
}
But this is not super flexible and I don't know if using .merge! two times in one line is not a crap. Are there any other alternatives?
I'm using Ruby 2.7 and Rails 6
Using merge! is fine and well understood. However, as you are setting a single key on your base_options hash, you can also simple use the hash accessor, i.e.
base_options[:checks] = document_check.merge!(identity_check, dummy_check)
Note that this will also change the document_hash object as merge! modified the receiver. If this is not desired, you can also use merge and return a new Hash. Thus could look like:
base_options[:checks] = document_check.merge(identity_check, dummy_check)
or equivalently
base_options[:checks] = {}.merge!(document_check, identity_check, dummy_check)
The latter option is slightly slower but might better show your intended behavior and is thus easier to understand to readers of your code.
If I understand correctly, you can try the Double Splat **. you can use like this:
base_options.merge(
checks: **document_check, **identity_check, **dummy_check
)
The answer is in your question, below can be a simple way of achieving the end result.
Below is after initializing values of base_options, document_check, identity_check,dummy check.
base_options = {
base_options: base_options,
checks: {
document_check: document_check,
identity_check: identity_check,
dummy_check: dummy_check,
}
}
=> {:base_options=>{:send_email=>true, :send_reminder=>false, :reset_client_status=>true}, :checks=>{:document_check=>{:document=>{:enabled=>true, :preferences=>{:face=>false, :liveness=>false, :docs_all=>true}}}, :identity_check=>{:identity=>{:enabled=>true, :preferences=>{}}}, :dummy_check=>{:dummy=>{:enabled=>true, :preferences=>{:state=>0, :replay=>true}}}}}

Remove header w/o losing resizeability

Here below the table i'm currently working on it. What I'm trying to achieve is to remove the header (A, B, C, ...) without losing the resizeability feature for the columns.
'config' : [
'columns': {
['data':6, 'type': 'numeric', 'readOnly': false],
['data':7, 'type': 'numeric', 'readOnly': false],
},
'copyPaste' : true,
'colHeaders' : false,
'fillHandle': false,
'manualColumnResize': true,
'colHeaders': true,
'wordWrap' : false,
]
Basically, once I set manualColumnResize = True the A,B,C Header appers. Is there a way to keep the manual resize without the header?
You have the colHeaders option listed twice. Remove the one that is set to true and it should remove the headers.
EDIT: I believe the resize functionality actually requires the headers. When you hover in between two columns' headers, you trigger the selector to expand or retract the size of the column. If you want to remove the (A, B, C) default header names, you can always pass a custom function to overwrite them:
...
// as function
colHeaders: function(index) {
return index + ': AB';
}
...

Auto-commenting on newline, SublimeText

Could someone point me how to make SublimeText insert comment continuation double-slashes when I enter a new line while inside a comment block?
// I have comments like this, and when I enter a '\n'
// it break's out of comment-entering mode
like this (drops slashes, cursor stays at leftmost column)
// and I want to have them automatically inserted after hiting '\n'
// like this
I might have changed that on accident while tweaking preference file, and I don't know how to set it back.
here is my user prefs:
{
"animation_enabled": false,
"auto_complete_commit_on_tab": true,
"auto_complete_delay": 200,
"auto_complete_size_limit": 2097152,
"auto_complete_triggers":
[
{
"characters": "<",
"selector": "text.html"
},
{
"characters": ".",
"selector": "source.python"
},
{
"characters": ".",
"selector": "source.javascript"
}
],
"bold_folder_labels": true,
"caret_extra_bottom": 1,
"caret_extra_top": 1,
"caret_extra_width": 0,
"caret_style": "solid",
"color_scheme": "Packages/User/base16-compact.dark (SL).tmTheme",
"copy_with_empty_selection": false,
"default_line_ending": "unix",
"drag_text": false,
"draw_white_space": "none",
"fade_fold_buttons": false,
"font_face": "Inconsolata",
"font_size": 10,
"highlight_modified_tabs": true,
"ignored_packages":
[
"Vintage",
"Diff",
"DocBlockr",
"Markdown",
"Shell Command"
],
"indent_guide_options":
[
"draw_normal"
],
"line_padding_bottom": 1,
"line_padding_top": 1,
"logging_level": "error",
"margin": 0,
"match_brackets_content": false,
"remember_open_files": false,
"scroll_past_end": true,
"scroll_speed": 0,
"shift_tab_unindent": true,
"show_encoding": true,
"show_line_endings": true,
"soda_classic_tabs": true,
"spell_check": false,
"tab_size": 2,
"theme": "Soda Dark.sublime-theme",
"translate_tabs_to_spaces": true,
"tree_animation_enabled": false,
"trim_automatic_white_space": false,
"use_tab_stops": true
}
The DocBlockr package adds this functionality. If you remove it from your 'ignored_packages', that should fix it!
(nb. I see from the comments above that this did indeed fix it, but I'm putting this here as an answer, because it's easy to miss the comments & took me a while to figure out that this functionality came from DocBlockr rather than Sublime Text itself)
just type this command:
CTRL + /
single line comments are single line, if you want to use another line use the multi-line comment.
/* */
to revert your preference:
remove all of the code on your user preference and replace it with {} and press CTRL+S to save it. it should do the revert.
If I'm understanding the OP correctly, what we want is, let's say we have this:
int foo; // a foo|
Treat the | as a cursor. And if we hit return at the trailing end of the line we automatically get
int foo; // a foo
// |
This is the functionality I've been trying to look for anyway. I found that the package DoxyDoxygen conveniently does this for me.

Data structure to describe multiple boolean values as keys

I have javascript weather classification app which I am porting to ruby.
The classifications are stored in a json as
"classification": [
{
"warm": false,
"sunny": false,
"windy": false,
"desc": "cold-drizzle"
},
{
"warm": false,
"sunny": false,
"windy": true,
"desc": "storm"
},
{
"warm": false,
"sunny": true,
"windy": false,
"desc": "winter-wonderland"
}, etc
There are with other words eight different classifications.
What would be a concise ruby way to describe this structure? Perhaps a hash with multiple booleans as key?
Hashes in Ruby can be indexed by anything, including other hashes. So:
classifications = {}
classifications[ {warm:false, sunny:false, windy:false} ] = "cold-drizzle"
classifications[ {warm:false, sunny:true, windy:false} ] = "winter-wonderland"
p classifications
#=> {
#=> {:warm=>false, :sunny=>false, :windy=>false}=>"cold-drizzle",
#=> {:warm=>false, :sunny=>true, :windy=>false}=>"winter-wonderland"
#=> }
p classifications[ {sunny:false, windy:false, warm:false } ]
#=> "cold-drizzle"
Note the arbitrary ordering I used for the hash keys when reading the value. You don't have to use the exact same hash object you used when writing (as you would with Lua), you simply need to use hash whose data is equivalent.
Due to the syntax sugar of Ruby's method calls, you can even leave off all the { and } in the above (except where the hash is declared):
classifications[ warm:false, sunny:false, windy:true ] = "stormy"
p classifications[ warm:false, sunny:false, windy:false ]
#=> "cold-drizzle"
If you want to be more terse but less descriptive, you can also just use arrays for your keys:
classifications = {}
classifications[ [false,false,false] ] = "cold-drizzle"
classifications[ [false,true, false] ] = "winter-wonderland"
p classifications[ [false,true,false] ]
#=> "winter-wonderland"
Note that—as with the hashes as keys—you do not need to use the exact same object to index the hash, just an object that is considered equal.
Exactly like the JSON (array of objects):
You could use the Struct class to replicate the objects in your JSON
classifications = []
Classification = Struct.new(:warm, :sunny, :windy, :desc)
classifications << Classification.new(false, false, false, "cold_drizzle")
You could also just have an array of hashes:
classifications = []
classifications << {warm: false, sunny: false, windy: false, desc: "cold_drizzle"}
Or, if you're looking for a hash with the three booleans as a key to the description:
You could use Struct again:
classifcations = {}
Classification = Struct.new(:warm, :sunny, :windy)
classifications[Classification.new(false, false, false)] = "cold_drizzle"
You could use plain integers:
classifications = {}
classifications[0] = "cold_drizzle"
classifications[1] = "storm"
You could use arrays:
classifications = {}
classifications[[false, false, false]] = "cold_drizzle"
Or anything else you like. This question is a little open-ended, but there are some ideas.
Use JSON#parse
Given a valid JSON string, you can just parse it into a valid Ruby hash with JSON#parse. For example:
require 'json'
json_string = <<EOF
{"classification": [{
"warm": false,
"sunny": false,
"windy": false,
"desc": "cold-drizzle"
}, {
"warm": false,
"sunny": false,
"windy": true,
"desc": "storm"
}, {
"warm": false,
"sunny": true,
"windy": false,
"desc": "winter-wonderland"
}]}
EOF
hash = JSON.parse(json_string)
You can then access your new Hash object with an assortment of methods. For example:
hash['classification'].first
#=> {"warm"=>false, "sunny"=>false, "windy"=>false, "desc"=>"cold-drizzle"}

Grails Gorm Disable Sorting for a Field in Scaffolding

I am looking for an easy way to disable the sorting link for just one column in a gorm model using scaffolding, but have not found anything to this regard.
something like
static constraints = {
entryDate(nullable: false, blank: false, sortable: false)
}
is this possible in gorm?
You can define your own attributes and customize the scaffolding-templates.
Custom attributes:
static constraints = {
entryDate(nullable: false, blank: false, attributes: [sortable: false])
}
Customizing the scaffolding-template could look like this:
props.eachWithIndex { p, i ->
cp = domainClass.constrainedProperties[p.name]
if (p.isAssociation() || (cp.attributes?.sortable != null && !cp.attributes.sortable) ) { %>

Resources