In grails, I have two domain classes Question and QuestionOption.One question have many options.Each option has a question.
I went through 4 different scenario.
These scenarios has combination of instantiation-namedQuery , belongsTo-namedQuery , instantiation-hasMany and belongsTo-hasMany.
Scenario 1:
class Question
{
String quesText
static constraints={}
static namedQueries={
getAllQuestionOptions{question->
return QuestionOption.findAllWhere(question:question)
}
}
}
class QuestionOption
{
String optionText
Question question
static constraints={}
}
.
Scenario 2:
class Question
{
String quesText
static constraints={}
static namedQueries={
getAllQuestionOptions{question->
return QuestionOption.findAllWhere(question:question)
}
}
}
class QuestionOption
{
String optionText
static constraints={}
static belongsTo=[question:Question]
}
.
Scenario 3:
class Question
{
String quesText
static constraints={}
static hasMany=[questionOption:QuestionOption]
}
class QuestionOption
{
String optionText
Question question
static constraints={}
}
.
Scenario 4:
class Question
{
String quesText
static constraints={}
static hasMany=[questionOption:QuestionOption]
}
class QuestionOption
{
String optionText
static constraints={}
static belongsTo=[question:Question]
}
I used all these scenarios with mysql and all resulted with same schema
mysql> desc question;
+-------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+----------------+
| id | bigint(20) | NO | PRI | NULL | auto_increment |
| version | bigint(20) | NO | | NULL | |
| ques_text | varchar(255) | NO | | NULL | |
+-------------+--------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)
mysql> desc question_option;
+-------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+----------------+
| id | bigint(20) | NO | PRI | NULL | auto_increment |
| version | bigint(20) | NO | | NULL | |
| option_text | varchar(255) | NO | | NULL | |
| question_id | bigint(20) | NO | MUL | NULL | |
+-------------+--------------+------+-----+---------+----------------+
What is difference between using these scenarios in the terms of cascading , unidirectional-bidirectional and aggregation-composition?
Bidirectional means when both entity knows about each other.Unidirectional means first entity know about second but reverse is not true.
To understand cascading I referred this: http://www.mkyong.com/hibernate/hibernate-cascade-example-save-update-delete-and-delete-orphan/ .
Please help
belongsTo and hasMany associations in Grails effect the cascading behavior when it relates to updating/deleting instances. It has no effect on the named queries or querying in general.
Related
I'm new to F# and Bolero. and after initialize the project as the docs shows, I find that sample application demonstrates 3 types of web applications but main codes is in one file called Main.fs .
here is part codes:
type Message =
| SetPage of Page
| Increment
| Decrement
| SetCounter of int
| GetBooks
| GotBooks of Book[]
| SetUsername of string
| SetPassword of string
| GetSignedInAs
| RecvSignedInAs of option<string>
| SendSignIn
| RecvSignIn of option<string>
| SendSignOut
| RecvSignOut
| Error of exn
| ClearError
let update remote message model =
let onSignIn = function
| Some _ -> Cmd.ofMsg GetBooks
| None -> Cmd.none
match message with
| SetPage page ->
{ model with page = page }, Cmd.none
| Increment ->
{ model with counter = model.counter + 1 }, Cmd.none
| Decrement ->
{ model with counter = model.counter - 1 }, Cmd.none
| SetCounter value ->
{ model with counter = value }, Cmd.none
| GetBooks ->
let cmd = Cmd.OfAsync.either remote.getBooks () GotBooks Error
{ model with books = None }, cmd
| GotBooks books ->
{ model with books = Some books }, Cmd.none
| SetUsername s ->
{ model with username = s }, Cmd.none
| SetPassword s ->
{ model with password = s }, Cmd.none
| GetSignedInAs ->
model, Cmd.OfAuthorized.either remote.getUsername () RecvSignedInAs Error
| RecvSignedInAs username ->
{ model with signedInAs = username }, onSignIn username
| SendSignIn ->
model, Cmd.OfAsync.either remote.signIn (model.username, model.password) RecvSignIn Error
| RecvSignIn username ->
{ model with signedInAs = username; signInFailed = Option.isNone username }, onSignIn username
| SendSignOut ->
model, Cmd.OfAsync.either remote.signOut () (fun () -> RecvSignOut) Error
| RecvSignOut ->
{ model with signedInAs = None; signInFailed = false }, Cmd.none
| Error RemoteUnauthorizedException ->
{ model with error = Some "You have been logged out."; signedInAs = None }, Cmd.none
| Error exn ->
{ model with error = Some exn.Message }, Cmd.none
| ClearError ->
{ model with error = None }, Cmd.none
As you can see, the code is too long to manage. if I add more functionality I can barely imagine what the file will be like.
so how can I split the code into different files ?
The most basic thing you could do is to split your Message type into multiple separate types and have one corresponding to different aspects of the logic. For example:
type CounterMessage =
| Increment
| Decrement
| SetCounter of int
type BooksMessage =
| GetBooks
| GotBooks of Book[]
type Message =
| SetPage of Page
| CounterMessage of CounterMessage
| BooksMessage of BooksMessage
Then you can similarly split your update function - and move each of the message-specific functions to a separate file:
let updateCounter remote message model =
match message with
| Increment ->
{ model with counter = model.counter + 1 }, Cmd.none
| Decrement ->
{ model with counter = model.counter - 1 }, Cmd.none
| SetCounter value ->
{ model with counter = value }, Cmd.none
let update remote message model =
match message with
| SetPage page ->
{ model with page = page }, Cmd.none
| CounterMessage msg ->
updateCounter remote message model
// (...)
This is something using just basic F# langauge mechanisms. Perhaps Bolero has some more sophisticated methods for structuring projects, but this is simple option will always work. The disadvantage is that you need to handle the "forwarding" of the messages yourself (and this is something that a more sophisticated option may alleviate) - but I think that for a moderately sized project, it is not such a bad things (and it helps making things explicit and clear).
Suppose I have a DU like this:
type Fruit =
| Apple of int
| Banana of string
| Cherry of int * string
Now, I want to talk about the cases of the DU (not concrete items in the DU):
[<RequireQualifiedAccess>]
type FruitType =
| Apple
| Banana
| Cherry
module FruitType =
let ofFruit =
function
| Apple _ -> FruitType.Apple
| Banana _ -> FruitType.Banana
| Cherry _ -> FruitType.Cherry
type FruitSaladRecipe =
{
FruitsRequired : Set<FruitType>
}
As you can see, there is some code duplication here: every case of Fruit has an equivalent case in FruitType, and vice-versa.
Is there a more elegant way to write this?
Bonus points for not using reflection, this should be possible at compile-time.
This problem has come up a few times for me, but I will try to give a more concrete example.
Let's say you were building a form designer where the user can add custom elements like:
Drop downs
Text inputs
Sliders
In the menu for creating a new element, the first stage might be to pick a FormElementType:
[<RequireQualifiedAccess>]
type FormElementType =
| DropDown
| TextInput
| Slider
let! chooseFormElementType : UserInteraction<FormElementType> = ...
After choosing a FormElementType, the user will design an actual FormElement:
type FormElement =
| DropDown of string list
| TextInput of string option
| Slider of int * int
let createFormElement formElementType : UserInteraction<FormElement> =
match formElementType with
| FormElementType.DropDown ->
createDropDown
| FormElementType.TextInput ->
createTextInput
| FormElementType.Slider ->
createSlider
And then the new element can be added to a collection:
let form = Form.append formElement form
I am trying to learn KQL and had a query where I wanted to take 2 values from Windows Event codes 4624 (login) and 4634 (logout) and return them for different scenarios I'm still trying to build.
But primarily I would just like to be able to return the values in a table (print or project?)
let login = SecurityEvent
| where TimeGenerated > ago(1h)
| where EventID == '4624'
| project loginTime = TimeGenerated;
let logout = SecurityEvent
| where TimeGenerated > ago(1h)
| where EventID == '4634'
| project logoutTime = TimeGenerated;
print login
The error I am getting is "'project' operator: Failed to resolve scalar expression named 'login'"
What I would have hoped to see is:
loginTime | logoutTime
----------------------------------------------
01/02/2021 18:46:30 | 01/02/2021 18:45:45
01/02/2021 18:47:30 | 01/02/2021 18:47:45
01/02/2021 18:48:30 | 01/02/2021 18:48:45
Would a join be better? It is in the same table (SecurityEvent), so I thought it would be possible to do it this way?
The dataset is from the MS provided Azure portal: https://portal.azure.com/#blade/Microsoft_Azure_Monitoring_Logs/DemoLogsBlade
Thanks for the help!
The problem is that "login" is a table type but print is expecting a scalar type.
let login = SecurityEvent
| where TimeGenerated > ago(1h)
| where EventID == '4624'
| project loginTime = TimeGenerated;
let logout = SecurityEvent
| where TimeGenerated > ago(1h)
| where EventID == '4634'
| project logoutTime = TimeGenerated;
print toscalar (login)
As to the result you are trying to get, I think this might be what you need:
Updated to improve clarity/perf
let login = SecurityEvent
| where TimeGenerated > ago(1h)
| where EventID == '4624'
| project TargetLogonId, loginTime = TimeGenerated;
let logout = SecurityEvent
| where TimeGenerated > ago(1h)
| where EventID == '4634'
| project TargetLogonId, logoutTime = TimeGenerated;
login
| join kind=leftouter logout on TargetLogonId
| project loginTime, logoutTime
I added some changes that encompass #GenericUser and #Slavik-N suggested and brings out the information that I was looking to calculate:
let login = SecurityEvent
| where TimeGenerated > ago(1h)
| where EventID == '4624'
| where AccountType == 'User'
| project Computer,Account ,TargetLogonId, loginTime = TimeGenerated;
let logout = SecurityEvent
| where TimeGenerated > ago(1h)
| where EventID == '4634'
| where AccountType == 'User'
| project Computer,Account,TargetLogonId, logoutTime = TimeGenerated;
login
| join kind=inner logout on TargetLogonId
| project Computer,Account,loginTime, logoutTime, minute = datetime_diff('minute',logoutTime,loginTime)
| where minute >0
| sort by minute desc
This is making me crazy: even though I was sure I have defined this custom mapping correctly, it keeps 404ing.
The resource is nested: a publisher has many channels, a channel belongs to a publisher.
I am trying to make an AJAX call that invokes the getMostRecentURLsWithoutChannels function in the Channel controller.
The desired URL format is /publishers/1009303/channels/getMostRecentURLsWithoutChannels
From UrlMappings.groovy:
"/publishers"(resources: 'publisher') {
"/configurations"(resources: "configuration")
"/metadatas"(resources: "metadata")
"/xpaths"(resources: "xpath")
"/channels"(resources: "channel")
"/crawlrequest"(resources: "crawlRequest")
}
"/publishers/${publisherId}/channels/getMostRecentURLsWithoutChannels"(controller: "channel", action: "getMostRecentURLsWithoutChannels", method: "GET")
The UrlMappingsReport shows:
Controller: channel
| GET | /publishers/${publisherId}/channels | Action: index |
| GET | /publishers/${publisherId}/channels/create | Action: create |
| POST | /publishers/${publisherId}/channels | Action: save |
| GET | /publishers/${publisherId}/channels/${id} | Action: show |
| GET | /publishers/${publisherId}/channels/${id}/edit | Action: edit |
| PUT | /publishers/${publisherId}/channels/${id} | Action: update |
| PATCH | /publishers/${publisherId}/channels/${id} | Action: patch |
| DELETE | /publishers/${publisherId}/channels/${id} | Action: delete |
| GET | /publishers/*/channels/getUrlsForChannel | Action: getUrlsForChannel |
| GET | /publishers/${publisherId}/channels/getMostRecentURLsWithoutChannels | Action: getMostRecentURLsWithoutChannels
Moving the custom mapping above or below the general publisher/channel block has no effect.
Even the createLink tag correctly creates the URL:
<g:createLink resource="publisher/channel" publisherId="${params.publisherId}" action="getMostRecentURLsWithoutChannels" />
results in
https://localhost:8443/publishers/1009303/channels/getMostRecentURLsWithoutChannels
The function in the controller is defined as:
def getMostRecentURLsWithoutChannels(Integer pub) {..}
What am I missing?
I have a domain class with property pairs:
Boolean statement1
Boolean statement1Missing
These pairs number up to nine.
The following constraints apply to each pairing:
statement1 nullable: true
statement1Missing validator: {val, obj ->
if ( val == true &&
(obj.statement1 == true || obj.statement1 == false)) {
return ['statement.not.missing', 1]
}
if (obj.statement1 == null && val == false) {
return ['statement.is.missing', 1]
}
}
I have devised an integration test that can accommodate one pair of statements:
#Unroll
def "Validation of custom validation for statement1"() {
given: "New data"
def participant = new Data(studyId: "M00001",
formVersion: Version.get(7)
)
and: "an initial set of test values"
participant.statement1 = statement1
participant.statement1Missing = statement1Missing
when: "the validator is invoked"
def isValidConsentData = participant.validate()
then: "the appropriate fields are flagged as errors"
isValidConsentData == anticipatedValid
participant.errors.getFieldError(fieldInError)?.code == errorCode
where:
statement1 | statement1Missing | anticipatedValid | fieldInError | errorCode
true | false | true | null | null
false | false | true | null | null
null | true | true | null | null
null | false | false | "statement1Missing" | "statement.is.missing"
true | true | false | "statement1Missing" | "statement.not.missing"
false | true | false | "statement1Missing" | "statement.not.missing"
}
This handles all the combinations for statement1 that I wish to test.
I have been trying to work out how I can repeat this test for all nine statement pairs. I have tried putting in a loop like this:
(1..9).each { statementNo
...
and ...
participant.("statement" + statementNo) = ("statement" + statementNo)
...
where:
("statement" + StatementNo) | ("statement" + StatementNo + Missing) | ...
}
I have used this type of iteration before when wanting to iterate over properties, but it does not work in Spock. The test is just ignored completely. I really do not want to repeat this code for each statement pair.
I have investigated the use of this type of structure http://www.christianoestreich.com/2012/11/domain-constraints-grails-spock-updated/ but this only allows you to test one property value at a time, whereas I want to test one property value many times.
The other option is to explicitly include every property pair in the 'where' block and every possible outcome, but that would be very cumbersome.
Please provide some suggestions as to how I can use an iterative structure to perform these tests.
How about something like:
...
and: "an initial set of test values"
(1..9).each { statementNo ->
participant."statement$statementNo" = statement
participant."statement${statementNo}Missing" = statementMissing
}
when: "the validator is invoked"
def isValidConsentData = participant.validate()
then: "the appropriate fields are flagged as errors"
(1..9).each { statementNo ->
def fieldInError
if (anticipatedValid) {
fieldInError = null
} else {
fieldInError = "statement${statementNo}Missing"
}
assert isValidConsentData == anticipatedValid
assert participant.errors.getFieldError(fieldInError)?.code == errorCode
}
where:
statement | statementMissing | anticipatedValid | errorCode
true | false | true | null
false | false | true | null
null | true | true | null
null | false | false | "statement.is.missing"
true | true | false | "statement.not.missing"
false | true | false | "statement.not.missing"
Not sure how it behaves for getFieldError(fieldName) when there are is no error for a given field so you may need to add some condition for the second assert using !anticipatedValid if exception would be thrown.
Important is that implicit assert are necessary as each is void thus there would be nothing checked by the test at all otherwise.