I'm new to Rails and I'm using Google Translate to post.
I currently have this filter, however, it filters only one item from public_sphere, how do I make it a multiple filter, in this case, the user can select more than one option from public_sphere.
scope :filter_public_sphere, -> (params) {
params[:public_sphere].present? ?
where(
"public_sphere = ?",
AtaPublic.public_spheres[params[:public_sphere]]
)
:
all
}
In this case, the API must receive an array instead of a value. For that, what would my filter look like?
Arel should do the work for you. If you have a where clause in the form where(attribute: [array of attribute values]) it will generate an IN clause for the SQL
scope :filter_public_sphere, -> (params) {
params[:public_sphere].present? ?
where(
public_sphere: AtaPublic.public_spheres[params[:public_sphere]]
)
:
all
}
Assuming AtaPublic.public_spheres[params[:public_sphere]] returns an array of "public_sphere" identifiers.
Related
I have a rails app with mongoid5.
In my Project model has an attribute like this:
permissions : {
"18748343" : 2,
"23453744" : 3,
"23453444" : 1
}
and an array like this
role_ids = ["123456", "23453744"]
I want to query on projects that has one of the role_ids members as key in their permissions attribute and value of that key is more than 1.
How can I make this query with mongoid criteria?
If you are using Mongoid::Attributes::Dynamic, mongoid5 will allow you to query like this:
Project.where('permissions.123456'.ne => nil)
This is because in mongo, permissions is document, with keys
In my application, the query is being built by appending the first part(where clause) with the second part(order by) using a separate script like QueryBuilder.groovy and hence the order by part is prone to HQL injection which can't be sanitized by using Named Parameters. Therefore, I want to use findAll to retrieve a set of records by passing it a query and sorting and paging parameters separately. I saw an implementation like this:
domainClass.findAll(query,[namedParams],[max: 10, offset: 5])
When i passed sortColumn and sortDirection as named parameters, sortColumn worked fine but sortDirection didn't work. i need a way to either make sortDirection work as a named parameter or any other way which will combine 'sorting by direction' with the findAll result. Many people have suggested on various forums to just use the parameters directly as part of the query but it is unacceptable for my application as it will expose the query to HQL Injection.
Thanks in advance.
here is an example:
queryString = "FROM BookCatalog b WHERE b.bookNumber = :bookNumber"
this is passed to the QueryBuilder.groovy where something like this happens:
sort = "$params.sortColumn $params.sortDirection"
queryString.order(sort)
public void sort(String query){
this.query = this.query+" order by "+query
}
finally findAll retrieves the list of records:
def list = findAll(queryString,namedParams,queryParams)
so as the logic just appends the sorting parameters to the query string a potential hacker can do something like this:
bookCatalogView?offset=2&max=5&sortColumn=1,2,3 **or 1=1**
or
bookCatalogView?offset=2&max=5&sortColumn=1,2,3;**select * from whatever**
Don't concat strings, it's bad practice.
If you want to create complex queries, consider using createCriteria()
SomeDomainClass.createCriteria().list {
order("propName", "desc")
}
or, if you need more control, in the sessionFactory way:
query = sessionFactory.getCurrentSession().createCriteria(DomainClass.class)
query.addOrder(Order.asc("someField"))
query.addOrder(Order.desc("someotherField"))
I have User class which has a field type, which is in turn a list.
So type might look like : ["a","b"]
I have a another list, say search like ["c","b"] (this is pre-defined)
Now what I want is to search all my User instances such that I can find users type matching with any one of the elements from search.
I came up with a partial solution :
def newQ = User.findAllByUsernameIsNotNull()
newQ.each { eachIndex ->
query = eachIndex.type
result = query.findAll { it == "c" }
if(result.size() > 0 )
{
ans << eachIndex.username
}
}
The above code works, ans list have all User which satisfy my condition. But you can clearly see that in query.findAll line, I'm doing a search only for one element from search. I want to perform search operation for all search element against query(which is User's type field).
How can I achieve that? Apart from my solution are there any easy way to do that?
Thanks in advance.
You could do something like:
def ans = []
search.each{s->
ans += User.findAll("from User u where u.username is not null and ? in elements(u.type)",[s])
}
I can't think of a way to do it in a single query
User.withCriteria {
isNotNull("username")
'in' ("type", search)
}
When searching you want to go to the database as few times as possible since those are usually the most expensive operations. If the User.withCriteria {..} works I'd use that (I'm not as familiar with .withCriteria{}). This would work as well if you still wanted to use the dynamic finders since mockDomain doesn't work with HSQL (again not sure if .withCriteria{} works with mockDomain).
def search = ["c", "b"]
def users = User.findAllByUsernameIsNotNull()
users = users.findAll {it.type.intersect(search)}
I have an admin module, that lists orders.
One of the filters is a drop down, which lists the order_status and is a relation to the order_status table.
These order_id's are an id, from 1-10.
What I'm looking to do, is to filter by more than one of these order_id's.
So something like 1,2,3,4,5 or 6,7,8,9,10
Is this possible, or do I need to create a custom filter?
Why not? Allow to your order widget multiple selections.
Set option 'multiple' => true
Update:
Try to handle value of orders types manually. Here is example:
public function addOwnGroupIdColumnQuery(Doctrine_Query $query, $field, $value)
{
if (!$value)
{
return;
}
$query->leftJoin($query->getRootAlias().'.OwnGroups pgr');
$query->andWhereIn("pgr.id", $value);
}
Locate this method into your filter class.
As I noticed in the answers of another question there are a few problems when testing finder methods in GORM.
I want to get all objects from Something and have support for sorting and pagination, so I wrote this:
SomethingListVO findAllSomethings(int offset = 0, int limit = 50) {
def somethingCount = Something.count()
def somethings = Something.findAll([max: limit,
offset:offset,
sort: "number",
order: "asc"])
return new SomethingListVO(somethingCount,somethings)
}
This can't work because if you want to add something like pagination or sorting you need to have a query. But if you add a query like SELECT * FROM Something your test will fail.
Is there any way to test this method (with pagination/sorting)?
This approach seems to provide more features but it won't work with my grails installation.
Just do this for your query
Something.list([max: limit,offset:offset,sort: "number",order: "asc"])