Write to config.groovy - grails

I know it's possible to read in values from the grails-app/conf/Config.groovy but i was wondering if it is possible to write values as well?
something as simple as this doesn't seem to actually change the value in the Config.
def oldValue = grailsApplication.config.my.value
assert oldValue == "oldValue"
def newValue = "newValue"
grailsApplication.config.my.value = newValue
assert newValue == grailsApplication.config.my.value
I would like to use this as a way to store some values outside of a database without having to load up another properties file.

That's probably not going to be practical if I understand you correctly. You're really dealing with the compiled Config.class at runtime. Do you really want to check out Config.groovy from your VCS, modify it, check it back in, recompile it, and mess around with the Classloader to reload it? The only way I have found to do this is by externalizing their properties a database or file and managing state at runtime to deal with updates.

I agree with proflux's comment. Config.groovy is not the right place to persist any data generated by your application, and it's a good thing that what you try doesn't work :)
I am very curious as to why you don't want to persist these values in a regular database (of whatever kind). There is, of course always the option of storing this in a file somewhere, the path of which you can configure in Config.groovy. But even that to me only seems marginally helpful.
Why not add a domain class along the lines of this:
class Setting{
String key
String value
static constraints = {
key(unique: true)
}
}
This will probably be the easiest way of achieving what you're looking for, from what I can tell from here. But again, you should elaborate on what kind of data it is that you need to persist...

Related

Is it fine to access NSUserDefaults/UserDefaults frequently?

I have a login view controller in which the user enters their preferences like whether or not he wants to activate certain UI features.
I store these as variables whose getters and setters directly access UserDefaults, here is an example of one of these:
class Preferences {
static var likesSpaghetti : Bool {
set (likesSpaghetti) {
UserDefaults.standard.set(likesSpaghetti, forKey: "likesSpaghetti")
}
get {
return UserDefaults.standard.bool(forKey: "likesSpaghetti")
}
}
}
So that whenever I want to set any of these I simply write something like this:
Preferences.likesSpaghetti = false
Now, my question is: Can I set these variables every time the user flicks the on/off switch or should I keep the preference represented as a local variable and then only set:
Preferences.likesSpaghetti = spaghettiSwitch.isOn
when the user segue's away from the loginViewController? Is every access of UserDefault instant and quick? or is it laggy and should be used mercifully?
Edit after closing this question: So I learned to not prematurely optimize, and that it is probably ok within the scope of a few dozen elements. So I should be fine. I'm going to just update every time the user modifies anything so that my code is a lot easier to read and maintain.
Thanks everyone!
Your code is just fine. Don't worry about such optimizations until you actually encounter an issue. Trust that UserDefaults is implemented smartly (because it is). There is nothing "laggy" about setting something as simple as a Bool in UserDefaults.
You also wish to review another one of my answers which is related to this question: When and why should you use NSUserDefaults's synchronize() method?
Actually userDefaults (it's originally a plist file) is used for this purpose which is storing app settings and that light-wight content creating a variable may consum memory if you have to configure many of them , besides not reflecting the new setting change directly to defaults made by user , may cause un-expectable old settings to happen at the time of change such as a localized alert or part of code (such as push notification callback) that check the same setting where the user thinks it's already reflected
Adding to both #rmaddy #Sh_Khan, if you think about the security aspect of it, NSUserDafault is exactly for the details which is app specific such as settings, preferences or some configurations which are not security sensitive while things like passwords, usernames and sensitive data are not recommended to store in UserDefaults. You should use services like keychain which is encrypted for such data.

SWFAddress used to change INDIVIDUAL params in the url

I am using SWFAddress in actionscript 3 to control urls for navigation and controls, and while I am able to target and change specific parameters, I feel like I am missing a cleaner and more consistent way of handling it, perhaps even a feature or method I am not aware of.
Say I have a url and I want to change just the second param of def to xyz.
http://localhost/some-page/#/?param1=abc&param2=def&param3=ghi changed to
http://localhost/some-page/#/?param1=abc&param2=xyz&param3=ghi
I currently am doing:
if (SWFAddress.getParameterNames().indexOf("param2") >= 0) {
SWFAddress.setValue(SWFAddress.getPath() + "?"
+ SWFAddress.getQueryString().replace("param2=" + SWFAddress.getParameter("param2"), "param2=xyz"))
Essentially, checking if the param exists, checking what its current value is, then recreating the whole url using base, '?", and query, making sure I replace the the parameter and the parameter's value, making sure I don't miss the equal sign. This get's sloppy, and is error prone if the param exists but is not set to anything, or whether or not there is an equal sign, and a host of other pitfalls.
So, I can not just tell SWFAddress to update that one parameter in the url? A theoretical function of SWFAddress.setParam("param2, "xyz").
Has anyone coded their own method to micro-manipulate SWFAddress and the url, beyond the single function they supply you with of setValue(val:String)?
I think the short answer is no. According to the documentation there is no setParameter to go with the getParameter method. Looking at the code, it seems that the URL is not cached as a property in the class and therefore cannot be manipulated other than via the setValue method which, of course, updates the URL in the browser.
Presumably you're already parsing the URL in your onChange event so you can use the values to set your application state? If so, you shouldn't need to do so again when you come to rebuild the URL prior to updating it from Flash. If you store the deep-link properties on a Model class somewhere you can handle the defaulting, updating, and error checking without needing to resort to String manipulation. You would then rebuild the URL using those properties, a process you could abstract into a method in your Model class if required.
You should also note that the following line is not particularly robust since it will return true for properties such as param22 and sparam2:
if (SWFAddress.getParameterNames().indexOf("param2") >= 0) { }

Is there a way to mark a NSManagedObject as dirty?

In my NSManagedObject subclass I have an NSString ivar that splits up into an NSSet of entities. I'd like to be able to set the string and during a call to save, do the split, however, only setting the string will not trigger a dirty flag or a need to save.
You can implement the + (BOOL)contextShouldIgnoreUnmodeledPropertyChanges on you NSManagedObject subclass and return NO rather than the default (YES).
This should then cause the NSManagedObjectContext to be notified of changes properties even if they aren't represented by actual columns in the database.
I assume you mean "attribute" instead of "ivar". Your scheme of having a string being split into a set and then saving the set is perhaps debatable, but I guess that is not the issue here.
Why do you need to have the Managed Object marked as "dirty"? This is really not necessary. Just save it, dirty or not!
I do not know how you check the "dirtiness" of your managed object, but I assume you want this to trigger a save at a certain point. At that point you might just as well as check your own BOOL "dirtyFlag" which you can set as appropriate and keep available for checking.
It is always better to make these kinds of things explicit. Your code will become more readable and transparent.

grails delete all data from table / domain class, i.e. "deleteAll"

I've got a domain class, Widget, that I need to delete all instances out of -- clear it out. After that, I will load in fresh data. What do you suggest as a mechanism to do this?
P.S. Note this is not at bootstrap time, but at "run-time".
The easiest way is to use HQL directly:
DomainClass.executeUpdate('delete from DomainClass')
DomainClass.findAll().each { it.delete() }
If you want to avoid any GORM gotchas, such as needing to delete the object immediately and checking to make sure it actually gets deleted, add some arguments.
DomainClass.findAll().each { it.delete(flush:true, failOnError:true) }
Fairly old post, but still actual.
If your table is very large (millions of entries), iterating using findall()*.delete() might not be the best option, as you can run into transaction timeouts (e.g. MySQL innodb_lock_wait_timeout setting) besides potential memory problems stated by GreenGiant.
So at least for MySQL Innodb, much faster is to use TRUNCATE TABLE:
sessionFactory.currentSession
.createSQLQuery("truncate table ${sessionFactory.getClassMetadata(MyDomainClass).tableName}")
.executeUpdate()
This is only useful if your table is not referenced by other objects as a foreign key.
From what I learnt, I agree with #ataylor the below code is fastest IF there are no associations in your domain object (Highly unlikely in any real application):
DomainClass.executeUpdate('delete from DomainClass')
But if you have assiciations with other domains, then the safest way to delete (and also a bit slower than the one mentioned above) would be the following:
def domainObjects = DomainClass.findAll()
domainObjects.each {
it.delete(flush:it==domainObjects.last, failOnError:true)
}
If you have a list of objects and want to delete all elements, you can use * operator.
'*' will split the list and pass its elements as separate arguments.
Example.
List<Book> books = Book.findAllByTitle('grails')
books*.delete()

Erlang and the records

What is wrong in this code?
I was expected "titi" in person.name but I still have "toto"!
More explicitly, how to modify a record in a function?
init1()->
S=#person{name="toto"}, %record creation and field setting
fct(S),
io:format("~s~n",[S#person.name]).
fct(R)->
R#person{name="titi"}. %record updating
You need to get a result of fct():
init1()->
S=#person{name="toto"}, %record creation and field setting
S2 = fct(S), % Get updated record
io:format("~s~n",[S2#person.name]).
fct(R)->
R#person{name="titi"}. %record updating
Bertaud, I think you are getting ahead of yourself a bit. You really need to understand the basics of immutability before you write any more code. (i.e. "variables" do not vary : you can only assign a value to them once.) I suggest you read the free online guide "Learn You Some Erlang For Great Good", at http://learnyousomeerlang.com/. The section that covers the basics of variables is http://learnyousomeerlang.com/starting-out-for-real#invariable-variables.
It is impossible to stress too much that all data in Erlang is immutable. So to do something like in your original question you need to modify it like #hdima did. The record is not updated but rewritten. In the same way there is no global data in Erlang, all data belongs to a process. This is even true of ETS tables as they basically behave like a process, albeit a built-in one without explicit communication.
So if you use the process dictionary or an ETS table the data itself can never be updated, only the dictionary/table. This means that to modify some data in the dictionary/table you basically have to:
"Read" the data
Update the data making new data
"Write" the new back into the dictionary/table
Without writing the new data back into the dictionary/table it will be lost, as your new data was.
Within fct(), you're not mutating the record, but you're returning a new value for the record, which needs to be used further. If you're calling fct(S), without handling the return value, then you'll lose that new value ("titi").

Resources