I have 2 shell mehtods like this:
#ShellMethod(key = ["context set"])
fun setContext(dbContext: String) {
println("Set db context to $dbContext")
}
#ShellMethod(key = ["context clear"])
fun clearContext() {
println("Clear db context")
}
I set the key to start with "context" for better clarity. Is there a way to move the "context" to the group and have the shell methods inherit the key?
I didin't find anything in the documentation about it.
Thanks in advance.
Related
I was doing this code lab
https://developer.android.com/codelabs/android-room-with-a-view-kotlin#13
and having a question
class WordsApplication : Application() {
// No need to cancel this scope as it'll be torn down with the process
val applicationScope = CoroutineScope(SupervisorJob())
// Using by lazy so the database and the repository are only created when they're needed
// rather than when the application starts
val database by lazy { WordRoomDatabase.getDatabase(this, applicationScope) }
val repository by lazy { WordRepository(database.wordDao()) }
}
private class WordDatabaseCallback(
private val scope: CoroutineScope
) : RoomDatabase.Callback() {
override fun onCreate(db: SupportSQLiteDatabase) {
super.onCreate(db)
INSTANCE?.let { database ->
scope.launch {
var wordDao = database.wordDao()
// Delete all content here.
wordDao.deleteAll()
// Add sample words.
var word = Word("Hello")
wordDao.insert(word)
word = Word("World!")
wordDao.insert(word)
// TODO: Add your own words!
word = Word("TODO!")
wordDao.insert(word)
}
}
}
}
this is the code I found, as you can see, it is directly calling scope.launch(...)
my question is that:
isn't all the Room operations supposed to run in non-UI scope? Could someone help me to understand this? thanks so much!
Is CoroutineScope(SupervisorJob()) runs in Main scope?
No. By default CoroutineScope() uses Dispatchers.Default, as can be found in the documentation:
CoroutineScope() uses Dispatchers.Default for its coroutines.
isn't all the Room operations supposed to run in non-UI scope?
I'm not very familiar specifically with Room, but generally speaking it depends if the operation is suspending or blocking. You can run suspend functions from any dispatcher/thread. deleteAll() and insert() functions in the example are marked as suspend, therefore you can run them from both UI and non-UI threads.
I don't see the public method of the struct that I defined.
Can someone please let me understand why?
Here is the code:
// DataSaver.go:
package DataStorage
import (
"fmt"
"os"
)
type DataSaver struct {
// doesn't relevant to my question
fileName string
file *os.File
}
func PrintStr() {
fmt.Println("hello")
}
Then, I have a main method in other class. I initialized the struct and I wanted to call to PrintStr() function. However, I can't call to this method. Why?
Thank you!
That is not a method, it is just a function.
Import DataStorage (you should make it lower case) then you can call DataStorage.PrintStr()
I had a play around myself with this, and there are a few things to be careful of:
Make sure you import the package properly with respect to your GOPATH, e.g.
import "github.com/some-repo/datastorage"
And ensure that your packages/repos are in your GOPATH and in the correct directories (go is very fussy about how you do this)
Refer to your function using the package name like so:
func main(){
DataStorage.PrintStr()
}
The other poster is correct in that go conventions are to keep package names in lowercase.
Seems you dont have the concept of method receiver yet. Your method for the struct should be defined as below :
func (this DataSaver)PrintStr() {
fmt.Println("hello")
}
or
func (this *DataSaver)PrintStr() {
fmt.Println("hello")
}
which one you choose depends on you want to call the method on a pointer or not;
I want to extend existing goquery.Selection type with my own method and be able to use it from package's selectors. I know that I cannot "patch" existing method -- I need to create a new one. But how do I can force the existing package functions to use my new type? Something I'm missing in general or there's no "nice" way to do it and it's better to use a function?
package main
import (
"fmt"
"github.com/PuerkitoBio/goquery"
)
type customSelection goquery.Selection
func (s *customSelection) CustomMethod() int {
return 1
}
doc.Find("*").Each(func(i int, s *goquery.Selection) {
fmt.Println(s.CustomMethod()) // does not works since its still "goquery.Selection"
// how do I can get a result with customSelection type here?
})
Since inheritance is not supported, the best practice is to embed the non-local type into your own local type, and extend it.
In the Design Patterns lingo its better known as composition:
https://en.wikipedia.org/wiki/Composition_over_inheritance
You can use function instead of method:
func customFunc(s *goquery.Selection) int {
return 1
}
...
fmt.Println(customFunc(s))
I've been experimenting with Swift on my way home from WWDC. One of the most compelling new features of Swift, in my opinion, was namespacing. I haven't managed to get it to work as I expected it should though. Please see the attached screenshot and let me know if you have an idea of what I'm doing wrong.
EDIT: I have of course tried to remove the import statement.
Turns out that this is a known bug: https://devforums.apple.com/message/976286#976286
I am sorry, if I search for "namespace" or "namespacing" in the Swift-eBook there are no results. Maybe you can give me a link to an additional resource?
I would solve your problem simply with a struct and static functions.
ClassA
struct ClassA {
static func localize() {
println("Localized String")
}
}
ClassB
You can drop the import and execute the ClassA-function as follows:
ClassA.localize()
The second way
In your case you can also just make an extension of String like so:
extension String {
func localize() -> String {
return self+"-localized"
}
}
println("Test".localize()) // prints "Test-localized"
EDIT: Please let me be clear, I'm asking how to do this in Grails using Spring Dependency Injection, and NOT Grails' metaclass functionality or new().
I have a grails service that is for analyzing log files. Inside the service I use the current time for lots of things. For unit testing I have several example log files that I parse with this service. These have times in them obviously.
I want my service, DURING UNIT TESTING to think that the current time is no more than a few hours after the last logging statement in my example log files.
So, I'm willing to this:
class MyService {
def currentDate = { -> new Date() }
def doSomeStuff() {
// need to know when is "right now"
Date now = currentDate()
}
}
So, what I want to be able to do is have currentDate injected or set to be some other HARDCODED time, like
currentDate = { -> new Date(1308619647140) }
Is there not a way to do this with some mockWhatever method inside my unit test? This kind of stuff was super easy with Google Guice, but I have no idea how to do it in Spring.
It's pretty frustrating that when I Google "grails dependency injection" all I find are examples of
class SomeController {
// wow look how amazing this is, it's injected automatically!!
// isn't spring incredible OMG!
def myService
}
It feels like all that's showing me is that I don't have to type new ...()
Where do I tell it that when environment equals test, then do this:
currentDate = { -> new Date(1308619647140) }
Am I just stuck setting this property manually in my test??
I would prefer not to have to create a "timeService" because this seems silly considering I just want 1 tiny change.
Groovy is a dynamic language, and as such it allows you to do almost what you're asking for:
class MyServiceTests extends GrailsUnitTestCase {
def testDoSomeStuff() {
def service = new MyService()
service.currentDate = { -> new Date(1308619647140) }
// assert something on service.doSomeStuff()
}
}
Keep in mind this only modifies the service instance, not the class. If you need to modify the class you'll need to work with the metaClass. Take a look at this post by mrhaki.
Another option would be to make the current date a parameter to doSomeStuff(). That way you wouldn't need to modify your service instance.
Thanks for the help guys. The best solution I could come up with for using Spring DI in this case was to do the following in
resources.groovy
These are the two solutions I found:
1: If I want the timeNowService to be swapped for testing purposes everywhere:
import grails.util.GrailsUtil
// Place your Spring DSL code here
beans = {
if (GrailsUtil.environment == 'test') {
println ">>> test env"
timeNowService(TimeNowMockService)
} else {
println ">>> not test env"
timeNowService(TimeNowService)
}
}
2: I could do this if I only want this change to apply to this particular service:
import grails.util.GrailsUtil
// Place your Spring DSL code here
beans = {
if (GrailsUtil.environment == 'test') {
println ">>> test env"
time1(TimeNowMockService)
} else {
println ">>> not test env"
time1(TimeNowService)
}
myService(MyService) {
diTest = 'hello 2'
timeNowService = ref('time1')
}
}
In either case I would use the service by calling
timeNowService.now().
The one strange, and very frustrating thing to me was that I could not do this:
import grails.util.GrailsUtil
// Place your Spring DSL code here
beans = {
if (GrailsUtil.environment == 'test') {
println ">>> test env"
myService(MyService) {
timeNow = { -> new Date(1308486447140) }
}
} else {
println ">>> not test env"
myService(MyService) {
timeNow = { -> new Date() }
}
}
}
In fact, when I tried that I also had a dummy value in there, like dummy = 'hello 2' and then a default value of dummy = 'hello' in the myService class itself. And when I did this 3rd example with the dummy value set in there as well, it silently failed to set, apparently b/c timeNow blew something up in private.
I would be interested to know if anyone could explain why this fails.
Thanks for the help guys and sorry to be impatient...
Since Groovy is dynamic, you could just take away your currentDate() method from your service and replace it by one that suits your need. You can do this at runtime during the setup of your test.
Prior to having an instance of MyService instantiated, have the following code executed:
MyService.metaClass.currentDate << {-> new Date(1308619647140) }
This way, you can have a consistent behavior across all your tests.
However, if you prefer, you can override the instance method by a closure that does the same trick.
Let me know how it goes.
Vincent Giguère