Grails searchable: search for a specific field in a member object? - plugins

Using the Grails Searchable plugin, I've got these classes:
class Person {
static searchable = {
address component: true
}
}
and:
class Address {
static searchable = {
root false
}
String country
}
I want to do a specific search for persons from a specific country. "country:NL" doesn't work. "address:country:NL" doesn't work either. I can't find anything about the syntax for this. Any ideas?
I think I'll have to do some clever indexing or some other trick in the searchable closure, but I just can't find it.

I created a basic app (Grails 1.3.5, Searchable 0.5.5.1) with your two classes and searching for 'country:NL' works for me. Did you remember to call index() before trying to search?
grails create-app search
grains install-plugin searchable
Person:
class Person {
static searchable = {
address component: true
}
Address address
}
Address:
class Address {
static belongsTo = Person
static searchable = {
root false
}
String country
}
Bootstrap:
class BootStrap {
def init = { servletContext ->
def p1 = new Person(address:new Address(country:'NL')).save()
def p2 = new Person(address:new Address(country:'DE')).save()
def p3 = new Person(address:new Address(country:'NZ')).save()
Person.index()
}
def destroy = {
}
}
Then I browsed to to /searchable and searched for country:NL and got person 1 returned.
If you want to see what Searchable is doing under the covers with regards to fields/indexes etc - Luke is a very handy tool (just download the executable JAR): http://code.google.com/p/luke/
The index files are in
<user.home>/.grails/projects/<project name>/searchable-index/development/index
cheers
Lee

The ugly solution that works: don't rely on Searchable. At the moment I first do a Person.search(params.query, [max:99999]).results, then do simple .findAll to find by country and .sublist() to get paging to work again.
It's a shame it's so hard to get something so obvious to work with Searchable.
Another solution I haven't gotten to work is making country a transient property on Person that returns address.country. Didn't work out of the box, and I have no idea on how to fix it.
If anyone has any prettier solutions for me, I'd love to hear them.

I am new to grails but why do you have to use the searchable plugin ?
what is wrong with a simple 1:1 or 1:n relationship ?
package com.test
class Person {
static constraints = {
name (nullable:false)
address (nullable:true)
}
String name
Address address
String toString() {
"name[" + name + "]. address[" + address + "]"
}
static mapping = {
address lazy:false
}
}
class Address {
static constraints = {
country (nullable:false)
town (nullable:false)
}
String country
String town
//Person person
static belongsTo = [person:Person]
// static belongsTo = Person
String toString(){
"town[" + town + "], country[" + country + "]"
}
}
package com.test
import grails.test.*
class PersonIntegrationTestTests extends GrailsUnitTestCase {
protected void setUp() {
super.setUp()
}
protected void tearDown() {
super.tearDown()
}
void testSomething() {
def bill = new Person(name:'bill', address:new Address(town:'york', country:'UK')).save()
def fred = new Person(name:'fred', address:new Address(town:'leeds', country:'UK')).save()
def bjork = new Person(name:'helen', address:new Address(town:'helsinki', country:'finland')).save()
def gustav = new Person(name:'john', address:new Address(town:'helsinki', country:'finland')).save()
List ukAddresses = Address.findAllByCountry('UK') // find all by country
println "num addresses-" + ukAddresses.size()
for (int i in 0..<ukAddresses.size())
{
println "found person:" + ukAddresses[i].person
}
assertNotNull "bill can not ne null", bill
assertTrue bill.validate() && !bill.hasErrors()
assertTrue fred.validate() && !fred.hasErrors()
assertTrue bjork.validate() && !bjork.hasErrors()
assertTrue gustav.validate() && !gustav.hasErrors()
assertEquals 2, ukAddresses.size()
}
}

Related

Find direct & indirect method usages if method is overriden in base class

please, help me to figure out how to write the query :)
The code is:
namespace ConsoleApplication1
{
class Program
{
static void Main()
{
var man = new Man("Joe");
Console.WriteLine(man.ToString());
}
}
public class SuperMan
{
public SuperMan(string name)
{
this.name = name;
}
public override string ToString()
{
return name;
}
string name;
}
public class Man : SuperMan
{
public Man(string name) : base(name)
{
}
}
}
I want to find all direct and indirect dependencies (methods) to Man.ToString(). There is only one call in Main() method.
The query I'm trying is:
from m in Methods
let depth0 = m.DepthOfIsUsing("ConsoleApplication1.SuperMan.ToString()")
where depth0 >= 0 orderby depth0
select new { m, depth0 }.
but it doesn't find dependent Program.Main() method....
How to modify query so that it finds usages for such kind of methods?
First let's look at direct callers. We want to list all methods that calls SuperMan.ToString() or any ToString() methods overriden by SuperMan.ToString(). It can looks like:
let baseMethods = Application.Methods.WithFullName("ConsoleApplication1.SuperMan.ToString()").Single().OverriddensBase
from m in Application.Methods.UsingAny(baseMethods)
where m.IsUsing("ConsoleApplication1.Man") // This filter can be added
select new { m, m.NbLinesOfCode }
Notice we put a filter clause, because in the real world pretty much every method calls object.ToString() (this is a particular case).
Now to handle indirect calls this is more tricky. We need to call the magic FillIterative() extension methods on generic sequences.
let baseMethods = Application.Methods.WithFullName("ConsoleApplication1.SuperMan.ToString()").Single().OverriddensBase
let recursiveCallers = baseMethods.FillIterative(methods => methods.SelectMany(m => m.MethodsCallingMe))
from pair in recursiveCallers
let method = pair.CodeElement
let depth = pair.Value
where method.IsUsing("ConsoleApplication1.Man") // Still same filter
select new { method , depth }
Et voilà!

How to design the classes with OOP?

I have problems about classes design now. The question is as follows:
I want to design classes for fruit and juicer. The classes for fruit (Apple, pear peach) are done. Now I want to design classes for juicer.
The requirement for juicer are:
1.Juicers take specific fruit (apple, pear, peach) and produce juice. NOTE: there may be mixed juice (such as flavor of apple and pear).
2.One kind of juicer can only produce one kind of juice.
3.Juicers have space to store fruit, and we can know how many apples or pears are still there. (We assume that every time one juicer uses one apple or pear).
Could anyone give me some advices?
If your language supports generics (as do C# and Java), the simplest solution would be to make the Juicer generic:
public class Juicer<T>
{
private T[] fruits;
public Juicer(T[] fruits)
{
this.fruits = fruits;
}
public FruitCount
{
get { return this.fruits.Length; }
}
// Other members can go here...
}
You can create one object that's a Juicer<Apple>, another as a Juicer<Pear>, and so on. A Juicer<Apple> can only contain Apple objects, etc.
Mark's answer is pretty good and a good start... I'd expand a bit. I probably wouldn't use an array for fruits since you will be adding, removing etc... probably easier to implement with a list or similar. Also, Laine says he wants multiple fruits in some juicers.. that complicates things a bit and gives us some decisions to make.
If it will always be a maximum of two fruits, I would probably just make two juicer classes similar to those in Mark's answer:
public interface IFruit
{
string Name {get;}
}
public class Apple : IFruit
{
public string Name { get {return "Apple";} }
}
public class Pear : IFruit
{
public string Name { get {return "Pear";} }
}
public class Juicer<IFruit>
{
private IList<IFruit> fruits;
public Juicer(IList<IFruit> fruits)
{
this.fruits = fruits;
}
public int FruitCount
{
get { return this.fruits.Count; }
}
// Other members can go here...
}
public class TwoFruitJuicer<IFruit, IFruit2>
{
private IList<IFruit> fruits;
private IList<IFruit2> fruits2;
public TwoFruitJuicer(IList<IFruit> fruits, IList<IFruit2> fruits2)
{
this.fruits = fruits;
this.fruits2 = fruits2;
}
public int FruitCount
{
get { return this.fruits.Count + this.fruits2.Count; }
}
// Other members can go here...
}
But, say you wanted 3 or 4 different juicers combined...
public class MulitJuicer
{
private IList<Juicer<IFruit>> _juicers;
public MulitJuicer(IList<Juicer<IFruit>> juicers)
{
this._juicers = juicers;
}
public int FruitCount
{
get {
int allFruitCount = 0;
foreach (var j in _juicers)
{
allFruitCount += j.FruitCount;
}
return allFruitCount;
}
}
}
However, That would probably be pretty difficult to use, a lot of lists inside of lists to keep track of build up and whatnot... what if you wanted just once juicer that you could just dump a bunch of fruits in? We can use Reflection to verify that only allowed fruits are put in the juicer:
public class MultiFruitJuicer
{
private IList<Type> _juiceTypes;
private IList<IFruit> _fruits;
public MultiFruitJuicer(IList<Type> juiceTypes, IList<IFruit> fruits)
{
_juiceTypes = juiceTypes;
_fruits = fruits;
if (!ValidateFruits())
{
//you may not want to actually throw here...
throw new Exception("Not all proper fruit types");
}
}
public bool ValidateFruits()
{
//there are about a million ways to do this... this is probably not the best...
foreach(var f in _fruits)
{
if (!_juiceTypes.Contains(f.GetType()))
{
return false;
}
}
return true;
}
public int FruitCount
{
get { return this._fruits.Count; }
}
}
I would start by implementing Builder design pattern for the
design classes for juicer
It'll help you to construct a complex object (juice) and separate its representation, so that the same construction process can create different representations (kinds of juice).
Add some interface (IFruit) and base class (shared code for Weight, Size etc.) to
classes for fruit (Apple, pear peach)
Each Juicer will have
ICollection<IFruit> fruits
that can be managed - .Count(), .Add(IFruit) or .Remove(IFruit).

Grails 2.3 - accessing REST functionality

I have my domain classes defined as follows, have no code in my controllers
import grails.rest.*
#Resource(formats=['json', 'xml'])
class Product {
String name
static hasMany = [productPrices: ProductPrice]
}
import grails.rest.*
#Resource(formats=['json', 'xml'])
class ProductPrice {
int price
static belongsTo = [product:Product]
}
My UrlMappings is defined as
"/products"(resources:"product")
{
"/productprices"(resources: "productprice")
}
I have also tried the following based on SO input - but it does not work
ProductPriceController extends RestfulController<ProductPrice> {
static responseFormats = ['json', 'xml']
ProductPriceController()
{
super(ProductPrice)
}
#Override def index()
{
def productId = params.productId
respond ProductPrice.where { product.id == productId }.list()
}
}
I can access my data using the urls /MyApp/products and /MyApp/products/1.
However I cannot access my data at the second level e.g. and /MyApp/products/1/ productprices – It gives me a 404. I am just trying to get my basic code skeleton to work.
I am referring primarily to the post nested RESTful resources.
Note: I know that long term I need to probably implement custom controllers as described in this article Grails get child domain objects, but before that I can't seem to get this basic code to work.
Pointers appreciated.

Refecltion - Dynamic class invocation

The following is the code where if else is used. If i need to dynamically create a class. how can i do it? is Reflection used ? If so : how can i implement the same using reflection?
public static Pizza getConcretePizza(String PType)
{
Pizza p=null;
if (PType.equals("Cheese"))
{
p=new CheesePizza();
//ResultIng = cp.FetchIng();
} else if (PType.equals("Pepperoni"))
{
p=new PepperoniPizza();
// ResultIng = pp.FetchIng();
}
else if (PType.equals("Clam"))
{
p = new CalmPizza();
//ResultIng = cap.FetchIng();
}
else if (PType.equals("Veggie"))
{
p= new VeggiePizza();
// ResultIng = vp.FetchIng();
}
return(p);
}
I tried getting the answer and finally found the solution.
(INSTEAD OF THE IF _ ELSE WE NEED TO REPLACE THE FOLLWOING CODE)
Class<?> clazz = Class.forName("PizzaTrail." + PType);
Object instance = clazz.newInstance();
p = (Pizza) instance;
return (p);
the above code will resolve the issue of writing the if else and reflection will help calling the class dynamically.

Using DataAnnotations (DisplayColumn) in WCF RIA Services

I have created an entity framework 4.0 (DB-First) model, added my partial classes and used DataAnnotations on them to have a perfect UI on the client.
I have some relations between my tables and used DisplayColumn on top my classes. e.g. I have a User class that has [DataColumn("UserName")] attribute on top of the class. And a Message class which has "public User Sender" which has [Include] attribute on top of the property.
Also, I have used .Include("User") in my DomainService to load the User who's related to a message.
But in my datagrid, I see User : (UserID) (UserID=Key property of User entity) instead of UserName that I have specified. I looked in the generated code in my SL project and it correctly decorated my User class with DisplayColumn attribute. But still, I cannot see UserName in my grid.
Any help would be greatly appreciated.
Update: Here's my question in code:
As I have mentioned, Owner, UserName, MessageId, UserId have been defined in my auto-generated model. UserMeta class has nothing special.
[MetadataType(typeof(MessageMeta))]
public partial class Message
{
}
public class MessageMeta
{
[Include()]
[Display(Name = "Belongs to", Order = 4)]
[Association("Message_User","MessageId","UserId",IsForeignKey = true)]
public virtual User Owner { get; set; }
}
[MetadataType(typeof(UserMeta))]
[DisplayColumn("UserName")]
public partial class User
{
}
In my DomainService:
public IQueryable<Message> GetMessages()
{
return this.ObjectContext.Messages.Include("Owner");
}
At last, I had to use Reflection. For DataGrid:
private void OnAutoGenerateColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
//Need to get an array, but should always just have a single DisplayColumnAttribute
var atts = e.PropertyType.GetCustomAttributes(typeof(DisplayColumnAttribute),true);
foreach (DisplayColumnAttribute d in atts)
{
DataGridTextColumn col = (DataGridTextColumn)e.Column;
//Make sure that we always have the base path
if(col.Binding.Path.Path!="")
{
col.Binding = new Binding()
{
Path = new PropertyPath(col.Binding.Path.Path + "." + d.DisplayColumn)
};
}
//Only do the first one, just in case we have more than one in metadata
break;
}
}
And for Telerik RadGridView:
var column = e.Column as GridViewDataColumn;
if (column == null)
{
return;
}
// Need to get an array, but should always just have a single DisplayColumnAttribute
var atts = column.DataType.GetCustomAttributes(typeof(DisplayColumnAttribute), true);
foreach (DisplayColumnAttribute d in atts)
{
// Make sure that we always have the base path
if (column.DataMemberBinding.Path.Path != "")
{
column.DataMemberBinding = new Binding()
{
Path = new PropertyPath(column.DataMemberBinding.Path.Path + "." + d.DisplayColumn)
};
}
// Only do the first one, just in case we have more than one in metadata
break;
}