ajax-datatables-rails, passing ids of records from get_raw_records to view - ruby-on-rails

I am using the gem ajax-datatables-rails and manage to build a table that works pretty well.
I would however to retrieve the list of IDs of my records at the get_raw_records function levels, before the data gets processed and formatted.
The reason is because I am using filters and I would like to call an action in the view that will affect ONLY the records filters (not only the ones in current page).
Could you please help me ?
my method looks as:
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

Related

Find records related to other records in controller (ruby on rails)

I'm grabbing a list of users and storing in #users.
Now I need to find properties related to only this list of users I have queried.
if params[:company].present?
#users = User.where(parent_id: params[:company]).or(User.where(id: params[:company]))
##properties = #properties.where(user_id: params[:company])
end
I would basically like to include #users inside #properties.where()
I need to get each property that has a user_id present in my #users array
edit:
I just did the following which gives me the result, however, I'm sure there's a much better way of doing this via activerecord:
ids = []
#users.each do |user|
ids.push(user.id)
end
#properties = #properties.where(user_id: ids)
#properties.where(user_id: #users.ids)
That should work. It'll take the id of user ids and perform a filter using the IN clause.
Perhaps adding your models and their relationships we can think about something better.

RoR: How to sort an array with the help of scopes

I have an array #products. Each element of the array is a hash, containing a few fields (but not all) from Product table and the corresponding values.
I have a scope descend_by_popularity in Product which allows me to sort the products based on popularity field. I'd like to sort the array #products using this scope.
What I tried:
#product_group = Array.new
#products.each do |product|
#product_group.push(Product.find(product['id']))
end
#product_group1 = #product_group.descend_by_popularity
But this gives me error:
undefined method `descend_by_popularity' for #<Array:0xb2497200>
I also want to change the sorted Product list back to the format of #products array.
Thanks
Scopes only make sense within the ActiveRecord context for requests to the database (since it is used to change the SQL query). What you did is throwing a lot of products into an array. This array then knows nothing about the scope anymore. You would have to use the scope when you create the #products object. (and it does not seem to make a lot of sense to move the result of a query into an array)
So something like
#products = Product.descend_by_popularity.where(some more stuff)
should work for you. After that you should have the records in the order defined by the scope and can then either use them directly or still push them into an array if that's what you want to do.
With the updated info from the comments it looks like maybe the best way to go would be to first collect only the Product ids from the solr response into an array and then run that as search together with your scope:
#product_group = #products.map{|product| product.id}
#result = Product.where(id: #product_group).descend_by_popularity
this should technically work, peformance is a different question. I would consider aggregating this data into the Solr document, if it doesn't change too often.
Now assuming you are only interested in the order of products as such, you could do something like this to get #products into this order:
#result.map{|r| #products.find{|p| p[:id] == r.id}
though this may slow down things a bit.
Try this: find_by_id as params
#product_group = Array.new
#products.each do |product|
#product_group.push(Product.find(params['id']))
end
and return the array of #product_group
#product_group1 = #product_group.descend_by_popularity

Rails active record query for search filters

Looking at the railscasts.com, I am wondering how Ryan implemented the search filters for the site. If the search param does not match anything in the database, then he is returning ALL records (for example, if we type an invalid param for the search param value in the URL, all records are returned because there is nothing to filter on). If it matches records in the database he is returning only those matching records.
How is being achieved? Can I use only Active Record without any gems/full-text-search for this? How would that query look like with Arel?
Also, how does he implement the filters link (links at the top of the page after we do a search)? Is he parsing through each of the search params and generating the links on the page by stripping out the search params one at a time?
I do not see Railscasts.com is showing all records when invalid filters (like search parameters). When no record is found, it is returning a link to see all episodes. For example, see this link:
http://railscasts.com/episodes?utf8=%E2%9C%93&search=
It says:
No episodes found. See all episodes.
However, you can show all records in such cases if you want. it's very easy.
def index
#records = []
if params[:search].present?
#YOUR SEARCH LOGIC and assign to #records. for example:
#records = Episode.where(:title => params[:search])
end
unless #records.length
#records = Episode.all
end
end

How to set default_scope order on attribute from another unassociated model

I have a Search resource that returns posts based on a filter as described in Railscast111, and have the following code:
def filter_posts
posts = Post.order('created_at DESC')
posts = posts.where("name ilike ?", "%#{keywords}%")
posts = posts.where(... #numerous other filters
posts
end
The filter itself seems to work fine. However, the content is not always returned in order of 'created_at DESC'. How can I sort the final output so that it's always in order of 'created_at DESC'? Currently, there is no association between the Post and Search models. Do I need to build one? If so, how?
Have you tried chaining the two conditions together?
posts = Post.where("name like?", "%#{keywords}%").order('created_at DESC')
Depending on how many filters you end up calling, you'll need to keep updating your original result, with the updated scope (based on your filter), as each time you use where it creates a new scope, instead of adjusting the original one. So you seem to be on the right path, as your original code does this, e.g
posts = Post.where("filter1")
posts = posts.where("filter2")
Have you tried sorting after all of the filters have been applied, so something like
posts = posts.order('created_at DESC')
or
posts = posts.sort_by &:created_at
Also, I'm not really sure what you mean by a Search resource, when (at least in this case) it appears you could keep the search logic within the Post model itself. Can you clarify, or maybe post the model?

Paginate data from two models into one newsfeed: Ruby on Rails 3 // Will_paginate

I'd like to make a newsfeed for the homepage of a site i'm playing around with. There are two models: Articles, and Posts. If I wanted just one in the newsfeed it would be easy:
#newsfeed_items = Article.paginate(:page => params[:page])
But I would like for the two to be both paginated into the same feed, in reverse chronological order. The default scope for the article and post model are already in that order.
How do I get the articles and posts to be combined in to the newsfeed as such?
Thanks!
EDIT: What about using SQL in the users model?
Just wondering: maybe would it be possible define in User.rb:
def feed
#some sql like (SELECT * FROM articles....)
end
Would this work at all?
in my last project i stuck into a problem, i had to paginate multiple models with single pagination in my search functionality. it should work in a way that the first model should appear first when the results of the first model a second model should continue the results and the third and so on as one single search feed, just like facebook feeds. this is the function i created to do this functionality
def multi_paginate(models, page, per_page)
WillPaginate::Collection.create(page, per_page) do |pager|
# set total entries
pager.total_entries = 0
counts = [0]
offsets = []
for model in models
pager.total_entries += model.count
counts << model.count
offset = pager.offset-(offsets[-1] || 0)
offset = offset>model.count ? model.count : offset
offsets << (offset<0 ? 0 : offset)
end
result = []
for i in 0...models.count
result += models[i].limit(pager.per_page-result.length).offset(offsets[i]).to_a
end
pager.replace(result)
end
end
try it and let me know if you have any problem with it, i also posted it as an issue to will_paginate repository, if everyone confirmed that it works correctly i'll fork and commit it to the library. https://github.com/mislav/will_paginate/issues/351
for those interested, please check this question: Creating a "feed" from multiple rails models, efficiently?
Here, Victor Piousbox provides a good, efficient solution.
Look at paginate_by_sql method. You can write unione query to fetch both articles and posts:
select 'article' as type, id from articles
union
select 'post' as type, id from posts
You can paginate both if you use AJAX. Here is well explained how to paginate using AJAX with WillPaginate.
You can paginate an array using WillPaginate::Collection.create. So you'd need to use ActiveRecord to find both sets of data and then combine them in a single array.
Then take a look at https://github.com/mislav/will_paginate/blob/master/lib/will_paginate/collection.rb for documentation on how to use the Collection to paginate any array.

Resources