How to implement delegation with metaClass and invokeMethod? - grails

im trying to create a tagging solution which is a bit flexible. I have previously thought about solving it like this: Polymorphic belongsTo in many to many mapping in grails? . But as this doesn't seem to bear any fruit so I wen't ahead in another direction.
What im trying to do now is to detect wheter a domain class has a hasMany reference to the Tag class. If it does, then i try to assign method delegation to the taggableService.
All the following code is trying to do is to find the specified method and invoke it on the current object. However if it doesn't find it then try to invoke it on the delegate object instead. And if all fails, throw a MissingMethodException.
for(GrailsClass c in grailsApplication.getDomainClasses()){
Map hasMany = c.getPropertyValue('hasMany')
//continue of has a many mapping with Tag class as its endpoint
if(hasMany && hasMany.containsValue(Tag)){
//replace invokeMethod with a delegate strategy
c.clazz.metaClass.invokeMethod = { String name, args ->
def metaMethod = c.clazz.metaClass.getMetaMethod(name,args)
if(metaMethod){
return metaMethod.invoke(delegate,args);
}
metaMethod = taggableService.class.metaClass.getMetaMethod(name, args)
if(metaMethod){
return metaMethod.invoke(taggableService,args);
}
throw new MissingMethodException(name,delegate.class,args)
}
}
}
This however doesn't seem to have the desired effect. I've have gone a bit lost in groovyland, can anyone help me?

Turns out it was just the test framework who didn't handle the bootstrap correctly. if i tested it in a controller class instead. it worked fine... :(

Related

Super simple but hard question for a Dart beginner

I am trying to learn Dart language. Following code seems very straight forward but does not work. I know it may be a foolish question for an expert but for me hard to understand why not ?
class Car{
carFun(){
print("Test");
}
}
main(){
Car.carFun();
}
Already answered but I'll give more context.
You need to mark your method as static:
static carFun(){ ...
This makes the method available as a 'Class Method'; right now, as you have defined it, it is an 'Object Method'. This means that you need to make an object out of the class Car to be able to use it, which would be something like this:
var myCar = new Car();
myCar.carFun();
This way you instantiated an object and used a defined method for it. Marking it as static would make this approach not work. This is one of the many differences between a Class and an Object.
Mark your method as static. Read more: https://dart.dev/guides/language/language-tour#class-variables-and-methods

In Grails, how can I get a reference to the datasource used by a particular class?

In the project I'm working on (in Grails 2.5.4/Hibernate 4.3) I have a bunch of different classes, using a few different dataSources. I need to determine whether two given Class objects use the same dataSource. What I would like to do is something like:
Boolean doDataSourcesMatch(Class a, Class b)
{
return a.mapping.datasource == b.mapping.datasource
}
But of course that doesn't work since a.mapping is a closure. Does anyone know how to access the dataSource used by a class? I don't need to know any of the properties of the connection, just whether queries on the two classes will use the same connection.
Many thanks!
Although none of these spell anything concrete out, they may help:
http://grails.1312388.n4.nabble.com/How-can-I-get-the-column-name-that-a-property-maps-to-for-a-domain-class-td4633766.html
How to get the name of the table GORM object is mapped to?
I haven't found anything specific, but this is all rather strange. I mean you already know and I presume this is some dynamic query otherwise you coding it would know what to query together etc.
Anyhow as a workaround, unsure if it can be since it depends on how many domainClasses we are talking about, and if this is something you have already put in place or thinking of writing up i.e nothing written in either case if you could add your own getter to all the domain classes in question
//
static String getDataSrc() {
return 'data_source_a'
}
//or
static boolean canQuery() {
return true/false
}
You could just check from anywhere something like this:
boolean canQuery = UserAttributes.canQuery()
String currentDataSource = UserAttributes.dataSrc
Since they are static methods, no instantiation is required. This means if you have
userObject(1) you don't need to do:
User user = User.get(1)
if (user.canQuery()) {
// this is ok
}
You can just call out the method directly from anywhere By referencing the upperCase class name and its method.
String currentDataSource = UserAttributes.dataSrc
//Where this is exactly the same as above
String currentDataSource = UserAttributes.getDataSrc()
E2A: The answer is:
import org.grails.orm.hibernate.cfg.GrailsDomainBinder
class TestController {
//either this method
def binder = new org.grails.orm.hibernate.cfg.GrailsDomainBinder().getMapping(Photos.class)
println "binder : ${binder.table.name}"
println "b: ${binder.datasources}"
//Or this
def dc=GrailsDomainBinder.getMapping(Photos.class)
println "-dc is ${dc}"
println "${dc.datasources}"
}
dc.datasources
is a list so you need to compare lists.
Of course silly me, if you are querying something like in HQL where you are giving dynamic table names ${tableA} ${tableB}
You will need to access actual domain class to be able to call GrailsDomainBinder
So something like: def domainClass = grailsApplication.getDomainClass(domain).clazz
would give you your actual domainClass for a given tableName. But your domain would have to be a fully qualified packaged name so that will cause you issues again.
If you querying com.domain.users.tableA and com.domain.info.tableB
So You could instead use If outside of service/controller):
def domainClass=Holders.grailsApplication?.domainClasses?.find { it.clazz.simpleName == tableName }?.clazz
or without Holders if you are declaring grailsApplication in controller service:
def domainClass=grailsApplication?.domainClasses?.find { it.clazz.simpleName == tableName }?.clazz

Trying to stub chained methods for a model in Rspec 3

I am really new to Rspec and tried to find my answer, but it keeps on pointing me to use stub_chain, but it seems like it is deprecated on Rspec3. I have the following I am trying to stub:
active_automation = Client.automation_active_status.new_client
Where Client is my model and automation_active_status is the following in my Client model
scope :automation_active_status, -> { where(automation_status: true) }
new_client is an attribute I want to call to further filter my result
I tried to implement stub_chain but that did not work. My goal is to get the following to work:
Client.any_instance( black_box_I_can_not_figure_out ).returns[something]
Thank you.
I believe you might be looking for allow and receive_message_chain.
allow(Client).to receive_message_chain(:automation_active_status, :new_client) { [thing_to_return] }
This will stub the methods allowed it, and return whatever comes out of the block you pass it. Hope it helps.
Client.stub_chain(:automation_active_status, :new_client).and_return([thing-to-return]) should get you where you're trying to get.
Additionally, any_instance should be used on instances of a class. For instance, Client.first would be an instance, but Client is the class (and you can stub directly on it).

How out object work for custom tag library in grails?

In Grails i am using custom tag library, here is my code
def isCheck = { attrs, body ->
def checkUser = springSecurityService.currentUser
def owner = attrs?.owner
if(checkUser?.id == owner?.id) {
out << body()
}
}
But here how the out object work.I think its from TagLibraryApi class.But without any initialization how it's work.
can anyone give me the concept for using out object.
From the Grails docs:
there is an implicit out variable that refers to the output Writer which you can use to append content to the response
Think of it like a field from a super class that you are referencing.
In this context out refers to the output stream/writer. Typically this is going to be the GroovyPage from which it's called.
As far as using it, I'm not sure what you are looking for but your example is pretty complete. You can always browse the source code for the built in tags for Grails on Github.

Using bindData method outside of controller

I was wondering if anyone had an idea for the best way to provide the
functionality of bindData() outside of my grails controllers. In my current
project I have created several groovy classes to model objects returned by
an api. In these classes I have a static method that parses xml and returns
a List of objects of the class. I would like to skip all the type casting
nonsense by using the bindData method in these classes. Any suggestions on
how to do this would be appreciated.
I was looking for a similar solution, to use bindData in a service class. I found a solution in JT's blog. The solution is basically to import:
import org.codehaus.groovy.grails.web.metaclass.BindDynamicMethod
then add this to your code:
def foo = new Foo()
BindDynamicMethod bind = new BindDynamicMethod()
def args = [ foo, params, [exclude:['name', 'mail']] ] // for example
bind.invoke( foo, 'bind', (Object[])args)
The (Object[]) cast is necessary du to Groovy/Java compatability. (Groovy is treating the ‘args’ object as an ArrayList, not an array of Objects.)

Resources