I have Ajax-datatable-rails gem to manage a datatable. I added some filtering in my get_raw_records method.
def get_raw_records
query = Book.where(user_id: user.id)
query = query.where(subject: params[:subject_id]) if params[:subject_id].present?
query
end
Separately to the Ajax processing, i would like to retrieve the ids of the book which have been filtered out, and pass them to my view in a sort of hash or something.
I am not sure if this is the step where I could do that or in the .js.coffee file.
Is there a way to achieve this objective ?
Related
i think i used the right terminology for what i need, i currently have a database call in my home_controller that is returning a call to my database with all the entries in that table specified, Freelancer.
There is an attribute on these records that has either a true or false value, which is "featured".
I need a way to call a sort method, or some other way, on that object with the true being first and then the false being afterwards, i tried using this code
def index
#freelancers = Freelancer.all
p 'below im outputting featured freelancer i hope'
#freelancers.sort_by { |row| [row.featured ? 0 : 1, row.id]}
p #freelancers
end
But unfortunately this did not work, can anyone advise me on a way to get this to work? Id rather have the sorted object returned as is, rather then assigning it to a new one. Just for future features of adding pagy and a filter by cost.
Use order method
def index
#freelancers = Freelancer.order(featured: :desc)
end
I am looking for a better way to dynamically build a active record query without making a sql string.
The following method does a new search for every word in the search_str and returns the records that are returned by all the search scopes.
scope :multi_search, ->(search_str){
query = ''
if search_str.present?
search_str.split(' ').each do |x|
query += ".search('#{x}')"
end
eval(query[1..-1])
else
all
end
}
It works, but this is not a clean implementation with the use of eval. Is there a better way of doing this?
In a model method:
def self.multi_search(your_params)
scope = Model.scoped({})
your_params.split(' ').map{|v| scope = scope.search(v)}
scope
end
I am pretty new to Rails and I have a feeling I'm approaching this from the wrong angle but here it goes... I have a list page that displays vehicles and i am trying to add filter functionality where the user can filter the results by vehicle_size, manufacturer and/or payment_options.
Using three select form fields the user can set the values of :vehicle_size, :manufacturer and/or :payment_options parameters and submit these values to the controller where i'm using a
#vehicles = Vehicle.order("vehicles.id ASC").where(:visible => true, :vehicle_size => params[:vehicle_size] )
kind of query. this works fine for individual params (the above returns results for the correct vehicle size) but I want to be able to pass in all 3 params without getting no results if one of the parameters is left blank..
Is there a way of doing this without going through the process of writing if statements that define different where statements depending on what params are set? This could become very tedious if I add more filter options.. perhaps some sort of inline if has_key solution to the effect of:
#vehicles = Vehicle.order("vehicles.id ASC").where(:visible => true, if(params.has_key?(:vehicle_size):vehicle_size => params[:vehicle_size], end if(params.has_key?(:manufacturer):manufacturer => params[:manufacturer] end )
You can do:
#vehicles = Vehicle.order('vehicles.id ASC')
if params[:vehicle_size].present?
#vehicles = #vehicles.where(vehicle_size: params[:vehicle_size])
end
Or, you can create scope in your model:
scope :vehicle_size, ->(vehicle_size) { where(vehicle_size: vehicle_size) if vehicle_size.present? }
Or, according to this answer, you can create class method:
def self.vehicle_size(vehicle_size)
if vehicle_size.present?
where(vehicle_size: vehicle_size)
else
scoped # `all` if you use Rails 4
end
end
You call both scope and class method in your controller with, for example:
#vehicles = Vehicle.order('vehicles.id ASC').vehicle_size(params[:vehicle_size])
You can do same thing with remaining parameters respectively.
The has_scope gem applies scope methods to your search queries, and by default it ignores when parameters are empty, it might be worth checking
I've got a controller method that sorts elements by a derived attribute. I can print to the view as long as I don't attempt to paginate. When I call #foos = #foos.page params[:page] I get the following error: undefined method 'page' for #<Array:...>
Can anyone provide some guidance here? Thanks.
Here's the whole controller method:
def index_by_capacity
if current_user.is_view_major?
#foos = Foo.major_attr(:name)
else
#foos = Foo.order(:name)
end
#foos = #foos.sort_by! {|a| a.capacity_available.to_i }
#total_foos = #foos.count
#foos = #foos.page params[:page]
respond_to do |format|
format.html
format.json { render json: #foos }
end
end
The .sort_by! method returns an Array, which has no method page (a ruby Array can't be paginated, you would have to implement it yourself or use an external lib).
The pagination works on ActiveRecord::Relation objects, returned by queries like .where or .order
In you case, you should do an order at the DB-level (faster than doing a sort via Ruby):
#foos.order(:capacity_available)
If the capacity_available attribute is a String (not an Integer), you can CAST it as an INT:
#foos.order('CAST(capacity_available AS INT) ASC')
(You may need to edit the CAST() function, it should work on PostGreSQL, not sure about MySQL)
If you want to continue using an array instead of an active record relation object, you can simply include WillPaginate::Collection.
From WillPaginate Documentation
Previously, all objects returned from paginate methods were of WillPaginate::Collection type. This is no longer true; in Active Record 3, the paginate and page methods return a Relation that is extended to look like a WillPaginate::Collection. Similarly, DataMapper returns a regular DataMapper::Collection that is also extended.
Both ActiveRecord::Relation and DataMapper::Collection are lazy arrays in the way that they don't execute any SQL queries until the point when data is needed. This makes them better than ordinary arrays.
The WillPaginate::Collection class is still available, however, and mostly unchanged.
The Array#paginate method still exists, too, but is not loaded by default. If you need to paginate static arrays, first require it in your code:
require 'will_paginate/array'
Given a query like:
current_user.conversations.where("params[:projectid] = ?", projectid).limit(10).find(:all)
params[:projectid] is being sent from jQuery ajax. Sometimes that is an integer and the above works fine. But if the use selects "All Projects, that's a value of '' which rails turns into 0. which yields an invalid query
How with rails do you say search params[:projectid] = ? if defined?
Thanks
I think you may have mistyped the query a bit. "params[:projectid] = ?" shouldn't be a valid query condition under any circumstances.
In any case, you could do some sort of conditional statement:
if params[:project_id].blank?
#conversations = current_user.conversations.limit(10)
else
#conversations = current_user.conversations.where("project_id = ?", params[:project_id]).limit(10)
end
Although, I'd probably prefer something like this:
#conversations = current_user.conversations.limit(10)
#converstaions.where("project_id = ?", params[:project_id]) unless params[:project_id].blank?
Sidenotes:
You don't have to use .find(:all). Rails will automatically execute the query when the resultset is required (such as when you do #conversations.each).
Wherever possible, try to adhere to Rails' snakecasing naming scheme (eg. project_id as opposed to projectid). You'll save yourself and collaborators a lot of headaches in the long run.
Thanks but if the where query has lets say 3 params, project_id, project_status, ... for example, then the unless idea won't work. I'm shocked that Rails doesn't have a better way to handle conditional query params
EDIT: If you have multiple params that could be a part of the query, consider the fact that where takes a hash as its argument. With that, you can easily build a parameter hash dynamically, and pass it to where. Something like this, maybe:
conditions = [:project_id, :project_status, :something_else].inject({}) do |hsh, field|
hsh[field] = params[field] unless params[field].blank?
hsh
end
#conversations = current_user.conversations.where(conditions).limit(10)
In the above case, you'd loop over all fields in the array, and add each one of them to the resulting hash unless it's blank. Then, you pass the hash to the where function, and everything's fine and dandy.
I didn't understand why you put:
where("params[:projectid] = ?", projectid)
if you receive params[:project] from the ajax request, the query string shouldn't be:
where("projectid = ?", params[:projectid])
intead?
And if you are receiving an empty string ('') as the parameter you can always test for:
unless params[:projectid].blank?
I don't think i undestood your question, but i hope this helps.