Paginate an include variable - sql

I'm building an app which have group > posts > comments
To reduce the number of SQL requests, i'm using the includes method
# group controller
def show
#posts = #group.posts.includes(:comments)
end
Now, I would like to paginate comments. But I don't know how to use the function .paginate from the gem will_paginate
Do you have a tips for that ?

Issue with pagination inside controller
Since you want paginated comments associated with individual post, it's complicate to achieve in controller as you need to create N paginated comment object (say you have N posts).
What you can do
1.load posts as usual with included comments to reduce excess queries. But don't run paginate here
2.achieve pagination inside view only
<%= #posts.each do | post | %>
<% comments = post.comments.paginate(page: params[:page]) %>
..
...
...
<%= will_paginate comments%>
<% end %>

Related

Rails List record and count for each

I have a model called Note. Each note belongs_to :call_reason. And call_reason has_many :notes.
What I want to do in a view is display a list of call_reasons and a total count of each next to it so we can see what the most popular call reasons are.
Here's what I have so far:
dashboard_controller:
def index
#notes = Note.all
end
dashboard view:
<% #notes.each do |n| %>
<%= n.call_reason.reason %>
<% end %>
This lists all notes' call_reasons.
I'm stumbling on how to list each call_reason once with a total count next to it. What I have now just lists all the call_reasons per note which is a mess. I think I could scope this out somehow or change the instance variable but I'm having a hard time getting it right.
Any thoughts?
Since you want to list call reasons, you should start with that:
def index
#call_reasons = CallReason.all
end
Then in your view you can do this:
<% #call_reasons.each do |call_reason| %>
<%= call_reason.reason %> <%= call_reason.notes.count %>
<% end %>
Note that this will perform a query for every call reason in your database. To prevent this you can use a counter cache. Check out the section on counter cache on Rails Guides too.

Editing multiple records at once - how to update without IDs

Still new to Rails. I'll try to provide as much detail as possible.
I have a form that lets me update multiple records at one time.
It's based off the 'Editing Multiple Individually' Railscast episode.
<%= form_tag(auction_clerk_path(#auction), :method => :put) do %>
<% #lots.each do |lot| %>
<%= fields_for "lots[]", lot do |f| %>
<%= f.number_field :sale_price %>
<% end %>
<% end %>
<% end %>
(Simplified to just include a single input for each instance)
An Auction contains multiple Lots (items for sale).
The auction_clerk_path is the route I'm using to just show all lots on one auction.
Everything is working just fine... until I use try to customize my lot paths...
I've added the following to my lot.rb file to be able to use:
/auctions/:auction_id/lots/:lot_number
instead of /auctions/:auction_id/lots/:id
def to_param
lot_number
end
So, in the form mentioned earlier, the fields render with name="lots[12][sale_price]" where 12 is the id.
However with the to_param change, now the fields render with name="lots[1][sale_price]" where 1 is the lot_number.
When I save, the submitted parameters are lot_numbers instead of ids.
So obviously when it tries to update, it won't find the correct records.
My method definition looks like this:
def save_clerking
#updated_lots = Lot.update(params[:lots].keys, params[:lots].values).reject { |l| l.errors.empty? }
if #updated_lots.empty?
flash[:notice] = "Lots updated"
redirect_to auction_clerk_path(#auction)
else
render :action => "clerk"
end
end
I either need to change my method definition to lookup by lot number, or change the form to somehow output IDs in the first place... but I don't know how.
Any help is appreciated. Thanks!
Fixed this through some help on another question.
I changed my method def to
#updated_lots = []
params[:lots].each do |lot_number, attributes|
lot = Lot.where("lot_number = ? AND auction_id = ?", lot_number, params[:auction_id]).first
if lot.update_attributes(attributes)
#updated_lots << lot
end
end
You could fetch the ids by lot number in the controller action and feed those to the update method instead of the params keys.

Does MongoID do a separate query for .count(true)?

I have a ruby on rails 3 project in which I query for a certain number of objects by using a .limit(3) . Then, in my view, I loop through these objects. After that, if there are 3 objects in the view, I display a "load more" button. Here is the view code:
<% #objects.each do |object| %>
<%= render object._type.pluralize.underscore + '/teaser', :object => object %>
<% end %>
<% if #objects.size(true) == 3 %>
#load more link here
<% end %>
The size(true) is passed a boolean to ensure that mongoID takes into account the .limit and .offset on my query (otherwise it returns the total number of objects that matched, regardless of the limit / offset). Here are the relevant development log lines:
MONGODB project_development['system.indexes'].insert([{:name=>"_public_id_1", :ns=>"project_development.objects", :key=>{"_public_id"=>1}, :unique=>true}])
MONGODB project_development['objects'].find({:deleted_at=>{"$exists"=>false}}).limit(3).sort([[:created_at, :desc]])
#some rendering of views
MONGODB project_development['system.indexes'].insert([{:name=>"_public_id_1", :ns=>"project_development.objects", :key=>{"_public_id"=>1}, :unique=>true}])
MONGODB project_development['$cmd'].find({"count"=>"objects", "query"=>{:deleted_at=>{"$exists"=>false}}, "limit"=>3, "fields"=>nil})
My question is: does MongoID do a separate query for my #objects.size(true)? I imagine the ['$cmd'] might indicate otherwise, but I'm not sure.
I don't think so, there was a pull request month ago to add aliases for :size, :length to :count to avoid re-running queries. You can check that.

Merging the List, Show, New and Edit actions of Rails

I am new in Rails.
I want a Simple Example in Rails 3 with only one index.html.erb file with All Actions merged including New, listing, Show , Edit (e.g all Actions) and If Example with Relationship of 1-to-Many will be perfect for me.
Take Example as Purchase Order(PO_Num, Date) has many Products(Name, Qty, Price)
Why do you want to merge the templates for all of the actions into one template? They're all conceptually quite different views, so having separate templates is normally a good idea. If you have shared code between them, there are better ways of achieving this (eg using partials or helpers).
If you really want to override a template used in an action, you can just call the render method:
def show
render "index"
end
You can check for action_name in the view:
<% case action_name %>
<% when 'index' %>
... view part for index action here
<% when 'show' %>
... view part for show action here
<% when 'new' %>
... view part for new action here
<% when 'edit' %>
... view part for edit action here
<% end %>

Running a SQL query in rails

I have a rails application where I have to subtract 2 time stamps and display the result on the webpage
I have used the following sql statement and I am getting the results.
select (julianday(resolutions.created_at)-julianday(tickets.created_at))*24 from tickets,resolutions
the value of tickets.created_at is 2010-04-05 18:59:02 which is a time stamp and value of resolutions.created_at is 2010-04-08 08:10:33
Now where do I put this sql so that I can be seen in my webpage.
I tried it in the views page with the following but nothing showed up:
<% #sql = "select (julianday(resolutions.created_at)-julianday(tickets.created_at))*24 from tickets,resolutions" %>
<% #t=(ActiveRecord::Base.connection.execute(#sql)) %>
So how do I display it on my webpage?
when I perform the above I get the output printed on the webpage as
061.1919444389641(julianday(resolutions.created_at)-julianday(tickets.created_at))*2461.1919444389641
only 61.1919444389641 is supposed to be printed but the query statement is also getting printed.
You should put your custom SQL in your model class, definitely not in the view.
In your controller
#tickets = Tickets.find(
:all,
:joins => :resolution,
:select => '(julianday(resolutions.created_at)-julianday(tickets.created_at))*24 AS interval'
)
In your view
<% #tickets.each do |ticket|%>
<%= ticket.interval %>
<% end %>
Generally you would put this logic in one of your models though, like this:
In your Tickets Model
def time_to_resolve
resolution.created_at - created_at
end
To reduce the number of queries when iterating over multiple queries you would use this:
Tickets.find(:all, :include => :resolution)