I am starting with Scala. I have my method in the model:
def get_courses = {
DB.withConnection { implicit connection =>
val result = SQL("SELECT * FROM courses")
result
}
When I call it from Controllers I am doing this (I want to get a List):
val AllCourses = CourseModel.get_courses
// Transform the resulting Stream[Row] as a List[(String)]
val CoursesList = AllCourses().map(row =>
row[String]("name")
).toList
When I am trying to transform the stream[Row] in a List (from https://www.playframework.com/documentation/2.0/ScalaAnorm) I am getting error
could not find implicit value for parameter connection: java.sql.Connection
related with AllCourses() code.
Any ideas?
However it is strange because when I add all the same method
def get_courses = DB.withConnection { implicit connection =>
val result = SQL("SELECT * FROM courses")
// Transform the resulting Stream[Row] as a List[(String)]
val CoursesList = result().map(row =>
row[String]("name")
).toList
}
it works (as the https://www.playframework.com/documentation/2.0/ScalaAnorm example)
But I want to have them separated in Controllers...
I suspect the answer to your question is that the actual database connection does not get used when you simply define the sql statement. If you hover over the SQL call, you will see it does not require a DB connection. result(), or SQL("...")() however, does need a connection and this is where the actual call to the database will take place.
Can I humbly suggest that you write your controllers only to operate on your class objects, and not to interact with anorm/database-level artefacts. So for example, your model layer would have a method get_courses : List[Course] (or perhaps simply all because you will probably reference it as a method of the Course companion object, i.e. Course.all(), so using course in the method name is probably not necessary) which returns Course objects. Your controllers would call this as needed, and not need to worry whether the Course object is coming from a database, from a json file, or from anywhere.
I also find parsers very useful, so define a parser courseP for example, which creates Course objects and is then used wherever you need to read one or more Courses - with something like SQL("select ... from course").as(courseP *) for a list of Courses, or SQL("select ...").as(courseP.singleOpt) for an Option[Course].
Related
Assume the following simple example data class:
data class SomeDataClass(
var id: String,
var name: String,
var deleted: String
)
With the following code it is possible to get the properties (and set or get their values):
import kotlin.reflect.full.memberProperties
val properties = SomeDataClass::class.memberProperties
print(properties.map { it.name }) // prints: [deleted, id, name]
The map within the print statement will return a List with the name of the properties in alphabetical order. I need the list in the order they have been defined in the source code, in this case: [id, name, deleted].
It doesn't seem achievable purely through reflection. The only solution I could come up with is to use a helper class defining the order:
val SomeDataClass_Order = listOf("id", "name", "deleted")
This wouldn't be a problem for one or two classes, but it is for hundreds of data classes with the largest one having up to almost one hundred properties.
Any idea would be welcome. I do not need detailed code, rather hints (like parsing the source code, annotations, etc).
If all the properties are declared in the primary constructor, you could "cheat":
val propertyNames = SomeDataClass::class.primaryConstructor!!.parameters.map { it.name }
If you want the KPropertys:
val properties = propertyNames.map { name ->
SomeDataClass::class.memberProperties.find { it.name == name }
}
This unfortunately doesn't find the properties that are declared in the class body.
I don't know about other platforms, but on Kotlin/JVM, the order in which the backing fields for the properties are generated in the class file is not specified, and a quick experiment finds that the order (at least for the version of kotlinc that I'm using right now), the order is the same as the declaration order. So in theory, you could read the class file of the data class, and find the fields. See this related answer for getting the methods in order. Alternatively, you can use Java reflection, which also doesn't guarantee any order to the returned fields, but "just so happens" to return them in declaration order:
// not guaranteed, might break in the future
val fields = SomeDataClass::class.java.declaredFields.toList()
If you do want to get the properties declared inside the class body in order too, I would suggest that you don't depend on the order at all.
I have a list of classes:
val availableClasses = listOf<Whatever>(
classA(),
classB(),
classC()
)
I am randomly selecting an item from this list using:
private var selection: Whatever = availableClasses.random()
Unfortunately, I think this approach is instantiating every class included in the list when the list is loaded.
I am hoping to work around this by replacing the list of classes with a list of strings:
val availableClasses = listOf<String>(
"classA",
"classB",
"classC"
)
Then once I have a selected string, instantiate only that one; something like:
private var selection: String = availableClasses.random()
// pseudo-code
val chosenClass = selection.toClass()
I can reference classes in Python using strings with the getattr function.
Is anything like this possible in Kotlin?
I'm also open to better approaches to this problem.
Instantiating classes by String name is more error-prone than using a constructor, because it relies on using a fully qualified, correctly spelled name, and the class having a specific constructor (either empty, or with specific arguments). So it can be done, but should be avoided when there are safer ways of doing it (ways where the compiler will give you an error if you're doing it wrong, instead of having an error occur only after you run the compiled program).
If I understand correctly, you want a list of classes that will only be instantiated one-at-a-time at random. One way to do this would be to make a list of class constructors.
val classConstructors = listOf<() -> Any>(
::ClassA,
::ClassB,
::ClassC
)
val randomInstantiatedClass = classConstructors.random()()
We are developing a Grails project and I am am a Grails/Groovy novice and I am seeing a pattern where we define a variable as an empty map in the controller, and then in a service method also defining another empty map, and populating it with key/value pairs from the DB.
My contention is that this pattern is wasteful. We are assigning an empty map to the controller variable, only to create another map in the service and then assigning the service map to the controller variable, thereby orphaning the empty map created in the controller, and releasing it for garbage collection.
A coworker contends that the data from the service map is ending up in the controller map, such that the original map created in the controller is being used and is therefore declaring it is not wasteful.
What is really happening? Is that first controller map being created only to be garbage collected, or is it somehow being filled with the data in the service map?
Controller method:
getMap() {
....
def output = [:]
output = someService.getHashMap()
...
}
Service method:
getHashMap() {
...
def output = [:]
output = [key0: 'value0', key1: 'value1', key2: 'value2']
}
There is no good reason to do something like this...
def output = [:]
output = [key0: 'value0', key1: 'value1', key2: 'value2']
Maybe this will help clarify what is going on. The following is equivalent to the code above...
def output = new LinkedHashMap()
output = new LinkedHashMap()
output.put 'key0', 'value0'
output.put 'key1', 'value1'
output.put 'key2', 'value2'
It is setting an object reference that is never used to a variable and then setting another reference of a different map instance (created inside the service probably). The garbage collector is going to remove the first empty map, it is not a big performance issue but is easily avoidable.
To add the contents of the map, you would need to use putAll or the left shift operator <<.
I'd personally resent (I know; it's a strong word) re-assigning values to a variable. The following (ugly) pattern is one of the main roots of evil in your code:
def x = foo()
// do something with 'x'
...
x = bar()
// do something else with 'x'
This can easily make understanding the code very difficult and introduce bugs. You have to constantly keep an eye on x to make sure it contains the value it is supposed to! Really!
Just create another variable to hold the second value; there's absolutely nothing wrong with it --the days of 64KB of memory are long gone now.
def fooX = foo()
// do something with 'fooX'
...
def barX = bar()
// do something with 'barX'
This makes reading the code and understanding its behaviour, much easier.
Personally, when I write code that needs to re-assign to a variable, I quickly realise that there's something wrong with the way I'm organising my code. I do it ONLY on extremely rare occasions.
Here is my code snippet, and the newer "constructParameterizedType" doesn't match my needs (unless I am missing something, which I assume I am). I have a genericized class called Result where T is any basic class that extends my "Inflatable" base class. represents the data records coming back from Salesforce REST API... so here is example of code that is working:
Class c = Class.forName("sfshare.UserRecord" );
JavaType type = mapper.getTypeFactory().constructParametricType(Result.class, c);
Result<T> res = mapper.readValue(rspData, type);
But if I use the newer (non-deprecated) "constructParameterizedType()" method, this same code will not compile because it isn't matching the parameters of constructParameterizedType. But constructParameterizedType isn't in use much yet and there are no examples to use... only the Javadoc - which doesn't make sense for my use-case.
If you look at arguments and specifically Javadocs, you will note that there is a new type: 2nd argument is the intended 'target' for parameters.
To give an example of meaning is that if you want to construct equivalent of:
ArrayList<String>
what you want to pass as arguments are:
constructParameterizedType(ArrayList.class, List.class, String.class)
or, possibly, Collection.class for second argument.
Think of it as the underlying relevant type you are trying to provide parameters for.
The underlying reason for this change is somewhat complicated and has to do with handling of "add-on" interfaces like Iterable<T>: for those cases it is necessary to provide different classes.
But in most end-user use cases you will just need to pass the same class as first and second argument.
Try this:
Class c = Class.forName("sfshare.UserRecord");
TypeFactory typeFactory = mapper.getTypeFactory();
JavaType type = typeFactory.constructParametrizedType(Result.class, Result.class, c);
Result<T> res = mapper.readValue(rspData, type);
or if your Result<T> class implements an interface:
JavaType type = typeFactory.constructParametrizedType(Result.class, ResultInterface.class, c);
Currently I am working partly with cfwheels and its Active Record ORM (which is great), and partly raw cfml with its Hibernate ORM (which is also great).
Both work well for applicable situations, but the thing I do miss most when using CF ORM is the model.update() method that is available in cfwheels, where you can just pass a form struct to the method, and it will map up the struct elements with the model properties and update the records.. really good for updating and maintaining large tables. In CF ORM, it seems the only way to to update a record is to set each column individually, then do a save. Is this the case?
Does cf9 ORM have an Active Record type update() (or equivalent) method which can just receive a struct with values to update and update the object without having to specify each one?
For example, instead of current:
member = entityLoadByPK('member',arguments.id);
member.setName(arguments.name);
member.setEmail(arguments.email);
is there a way to do something like this in CF ORM?
member = entityLoadByPK('member',arguments.id);
member.update(arguments);
Many thanks in advance
In my apps I usually create two helper functions for models which handle the task:
/*
* Get properties as key-value structure
* #limit Limit output to listed properties
*/
public struct function getMemento(string limit = "") {
local.props = {};
for (local.key in variables) {
if (isSimpleValue(variables[local.key]) AND (arguments.limit EQ "" OR ListFind(arguments.limit, local.key))) {
local.props[local.key] = variables[local.key];
}
}
return local.props;
}
/*
* Populate the model with given properties collection
* #props Properties collection
*/
public void function setMemento(required struct props) {
for (local.key in arguments.props) {
variables[local.key] = arguments.props[local.key];
}
}
For better security of setMemento it is possible to check existence of local.key in variables scope, but this will skip nullable properties.
So you can make myObject.setMemento(dataAsStruct); and then save it.
There's not a method exactly like the one you want, but EntityNew() does take an optional struct as a second argument, which will set the object's properties, although depending on how your code currently works, it may be clunky to use this method and I don;t know whether it'll have any bearing on whether a create/update is executed when you flush the ORM session.
If your ORM entities inherit form a master CFC, then you could add a method there. Alternatively, you could write one as a function and mix it into your objects.
I'm sure you're aware, but that update() feature can be a source of security problems (known as the mass assignment problem) if used with unsanitized user input (such as the raw FORM scope).