How to use with closure in updating the entities of an object? - groovy

Using the with closure is possible in creating new Instance of an object easier and simpler as stated here. But how can I use this closure when updating the entity values of my object?
Say I want to update the fields of my Person object that has an id = 1.
def p = Person.findById(1)
p.fname = 'First'
p.lname = 'Last'
p.save()

You mean like:
Person.findById(1).with {
fname = 'First'
lname = 'Last'
save()
}
It's not 100% clear from the question that this is what you mean...

Related

Is there a way to use variables as key in an object to find its value in rust? [duplicate]

This question already has answers here:
Access struct field by variable
(3 answers)
Closed last month.
I am new to rust with a javaScript background and i am stuck with getting a value of a json key dynamically.
In JS if i have an object = { "xyz" : "one" , "jkl" : "two" }; and if i have a variable name = "xyz"; , then i can find the corresponding value of 'xyz' key in the object using object[name] which will give me "one" as a result.
Now i have the exact same flow in rust, where i have
let obj = config.clone(); // because config is struct (only cloning could remove the error)
let name = "xyz"; // A variable which is a key in the object
let result = obj[name];` // result which is giving me "cannot index into a value of type `Configuration`" error
I am aware that creating a dict or hashmap will exponentially reduce the time, but the object i have can contain upto 1000 keys and values or more.
If i can create a hashmap with the object I already have, that would be a relief ( only if i knew ).
I have tried multiple ways by just googling a bunch of stuff
let result = obj[name];
let result = obj.&name];
let result = obj[$name];
let result = obj[&name];
let result = obj.$name;
none of them seems to solve the issue.
Thanks in advance.
Accessing fields of structs dynamically is not possible out of the box. See this earlier question.

NODE.JS: iterating over an array of objects, creating a new key if it does not exist

I am iterating over a collection of data, in my case, an array of objects. Here is a sample of 2 data points from it:
{
violation_id: '211315',
inspection_id: '268804',
violation_category: 'Garbage and Refuse',
violation_date: '2012-03-22 0:00',
violation_date_closed: '',
violation_type: 'Refuse Accumulation' },
{
violation_id: '214351',
inspection_id: '273183',
violation_category: 'Building Conditions',
violation_date: '2012-05-01 0:00',
violation_date_closed: '2012-04-17 0:00',
violation_type: 'Mold or Mildew' }
I need to create a new array of objects from this, one for each "violation_category" property. If Violation category already exists in the new array I am creating, i simply add the information to that existing category object (instead of having two "building conditions" objects for example, I would just add to an existing one).
However, I am having trouble assigning to the existing object if the current one exists (it's easy to check if it does not, but not the other way around). This is what am attempting to do currently:
if (violationCategory.uniqueCategoryName) {
violationCategory.uniqueCategoryName.violations = results[i].violation_id;
violationCategory.uniqueCategoryName.date = results[i].violation_date;
violationCategory.uniqueCategoryName.closed =
results[i].violation_date_closed;
} else {
category.violations = results[i].violation_id;
category.date = results[i].violation_date;
category.closed = results[i].violation_date_closed;
violationCategory.push(category);
}
In first condition, if this category (key) exists, I simply add to it, and in the second condition, this is where I am struggling. Any help appreciated. Thanks guys.
Just add an empty object to the key if there no object there :
violationCategory.uniqueCategoryName = violationCategory.uniqueCategoryName || {};
And only then, add the data you want to the object.
violationCategory.uniqueCategoryName.violations = results[i].violation_id;
violationCategory.uniqueCategoryName.date = results[i].violation_date;
violationCategory.uniqueCategoryName.closed =
results[i].violation_date_closed;
No condition needed.
Good luck!
Assuming that you have an input variable which is an array of objects, where the objects are looking like the objects of the question, you can generate your output like this:
var output = {};
for (var item of input) {
if (!output[item.violation_category]) output[item.violation_category] = [];
output[item.violation_category].push(item);
}
Of course you might customize it like you want.

ExpandoObject - why a Type behaves differently?

One for the gurus, please convince me/us what is going on.
List<ExpandoObject> peopleList = new List<ExpandoObject>();
dynamic expandoObj1 = new ExpandoObject();
expandoObj1.id = 1;
expandoObj1.first = "fred";
expandoObj1.last = "krugger";
peopleList.Add(expandoObj1);
dynamic expandoObj2 = new ExpandoObject();
expandoObj2.id = 2;
expandoObj2.first = "george";
expandoObj2.last = "benson";
peopleList.Add(expandoObj2);
//test access the props
var expObj = expandoObj1;
var name = expObj.first;
var expObj2 = peopleList[0] as dynamic;
var name2 = expObj2.first;
IDictionary<string, object> expObj3 = peopleList[0] as ExpandoObject;
var name3 = expObj3["first"];
var expObj4 = peopleList[0] as ExpandoObject;
//var name4 = expObj4.first; //THIS DOESN'T WORK - ExpandoObject does not contain a definition for 'first' etc...
In all cases, the LEFT-HAND SIDE is a System.Dynamic.ExpandoObject;
Why then, on the 4th case expObj4, i cannot access the property expObj4.first ?
ExpandoObject is a sealed class which stores data in a dictionary. It implements IDynamicMetaObjectProvider interface which provides dynamic behaviour to the classes implementing it. It also implements IDictionary interface which provides dictionary like behaviour to it. It is supposed to be checked and validated at compile time.
dynamic is a type which is not supposed to be checked by the compiler at compile time. It is checked and breaks at runtime. At compile time, a dynamic entity is assumed to support any operation. So, when you say, it is a expandoobject, the field called first does not get appended to object itself.
Check source code of expando object here
https://github.com/Microsoft/referencesource/blob/master/System.Core/Microsoft/Scripting/Actions/ExpandoObject.cs
Think of dynamic behavior like an object. You can put any type there. When you are adding to list, you are adding to list as dynamic, but the inherent type of item being added is ExpandoObject. So, you are able to cast it back to ExpandoObject.
When you say,
expandoObj1.first = "fred";
it is same as saying,
expandoObj1.Add("first", "fred");
When you used
var expObj = expandoObj1;
var name = expObj.first;
you were using expandoObject in dynamic form. So, you were able to access properties directly. When you cast it to ExpandoObject class, you were using actual ExpandoObject class which stores fields in Dictionary, so dot(.) notation does not work.
var expObj4 = peopleList[0] as ExpandoObject;
variable on left hand side is still ExpandoObject, not a dictionary. ExpandoObject exposes its members through collection search.
var name4 = expObj4.Where(t=>t.Key == "first").First().Value;
When you cast it to a dictionary, it works like a dictionary.
IDictionary<string, object> expObj3 = peopleList[0] as ExpandoObject;
var name3 = expObj3["first"];
When you cast it to a dynamic, you can access these keys like they are properties of the class.
Further reference
Dynamically adding properties to an ExpandoObject
This is because the variable expObj4 is declared as ExpandoObject and not as dynamic. This is an important difference.
Try this:
dynamic a = new ExpandoObject();
a.Name = "Test";
This compiles, but the following doesn't:
ExpandoObject a = new ExpandoObject();
a.Name = "Test";
you get this:
CS1061 'ExpandoObject' does not contain a definition for 'Name' and no extension method 'Name' accepting a first argument of type 'ExpandoObject' could be found
The variables you have that are related to this are:
expandoObj1 - dynamic
expandoObj2 - dynamic
expObj1 - dynamic
expObj2 - dynamic
expObj3 - dictionary, but you use dictionary access here, not dot-access
The magic "let's see if we can access the thing at runtime" code of the compiler only kicks in if the expression or variable is dynamic. ExpandoObject is just a type that supports this.

GORM - Update object without retrieving it first

I'd like to be able to update a previously persisted object for which I have an id without having to retrieve it first. The main thing that I'm trying to avoid is having to copy multiple values into the object's fields when that object has been retrieved from the database. I have these values in a map with keys corresponding to the field names so it's trivial to create the object via a constructor with the map as an argument. Unfortunately, an object created this way results in a new database record when saved even though the id field is set to that of an existing record.
I'm currently using a slight variation on one of the examples shown here for copying Groovy class properties but it's not a very elegant solution for multiple reasons.
Basically I'd like to be able to do something like this:
class Foo {
int a
String b
}
def data = [id: 99, a: 11, b: "bar"] //99 is the id of an existing record
def foo = new Foo(data)
foo.update() //or some other comparable persistence mechanism
Thanks
As long as your map keys have the same name as your object properties, you can use executeUpdate without specifying the individual property names with a closure or function like the following:
def updateString = { obj, map ->
def str = ""
map.each { key, value ->
str += "${obj}.${key}=:${key},"
}
return str[0..-2]
}
def data= [foo:"bar", machoMan:"RandySavage"]
In this case, println updateString("f", data) returns "f.foo=:foo,f.machoMan=:machoMan".
Then you can do this:
Foo.executeUpdate("update Foo f set ${updateString("f", data)}", data)
Or of course you could combine that all together into one closure or function.
You can use the executeUpdate method on the GORM domain class:
Foo.executeUpdate("update Foo f set f.a=:a, f.b=:b where f.id=:id", data)

Re-use of database object in sub-sonic

Yet another newbie SubSonic/ActiveRecord question. Suppose I want to insert a couple of records, currently I'm doing this:
using (var scope = new System.Transactions.TransactionScope())
{
// Insert company
company c = new company();
c.name = "ACME";
c.Save();
// Insert some options
company_option o = new company_option();
o.name = "ColorScheme";
o.value = "Red";
o.company_id = c.company_id;
o.Save();
o = new company_option();
o.name = "PreferredMode";
o.value = "Fast";
o.company_id = c.company_id;
o.Save();
scope.Complete();
}
Stepping through this code however, each of the company/company_option constructors go off and create a new myappDB object which just seems wasteful.
Is this the recommended approach or should I be trying to re-use a single DB object - and if so, what's the easiest way to do this?
I believe you can use the same object if you want to by setting its IsNew property to true, then change its data properties, save it again, repeat. Easy enough.
I 'm not so sure that you should bother, though. It depends on how bad those constructors are hurting you.
In my eyes assigning multiple objects to a single var is never a good idea but thats arguable. I would do this:
// Insert some options
company_option o1 = new company_option();
o1.name = "ColorScheme";
o1.value = "Red";
o1.company_id = c.company_id;
o1.Save();
company_option o2 = new company_option();
o2.name = "PreferredMode";
o2.value = "Fast";
o2.company_id = c.company_id;
o2.Save();
I you are worried about performance, that shouldn't be a issue unless you want to insert or update many objects at once. And again, in this case the time used for inserting the data takes longer than for the object creation.
If you are worried about performance you can skip the object creation and saving part completly by using a Insert query:
http://www.subsonicproject.com/docs/Linq_Inserts
db.Insert.Into<company_option>(
x => x.name,
x => x.value,
x => x.company_id)
.Values(
"ColorScheme",
"Red",
c.company_id
).Execute();

Resources