I am new to rails. I have three models tickets, tags and comments with relationships and it is working fine.
I want to display the total number of tickets in my ticket index view, but I don't know why...
I think that this is a really easy answer for you guys...
<%= ticket.count %> says undefined method.
Can you help me or do you need more informations? Thank you!
Assuming that in TicketController you have something like this:
def index
#tickets = Ticket.all
end
In your index view, to display the count of tickets, do as follows:
<%= #tickets.count %>
<% #tickets.each do |ticket| %>
.....
<% end %>
Call the count method on the collection object #ticket(Array of type ActiveRecord::Relation) and not on the ticket which is an instance of Ticket class.
In controller load ticket count
#ticket_count = Ticket.all.count
in view
<%= #ticket_count %>
ticket.count will not work because ticket is object of Ticket class which does not have count method defined . you can define count method for ticket and compute total of all Ticket then it will surely work.
I suggest to use Ticket.all.count which will return total no of tickets
Related
The run down. A person can have many bids, this particular person only has one bid.
In my index action I have #bids = Bid.find_by_person_id(params[:person_id])
in my view I do
<% #bids.each do |bid| %>
<%= bid.bid_amount %>
<% end %>
I am getting NoMethodError: undefined method each' for #<Bid:0x007f988a346f00> when visting the index view for person bids.
Is this because this person only has one bid? I feel thats not the case, but other than that im at a loss..
find_by returns the first item. I think you are looking for
Bid.where(person_id: params[:person_id])
Austio's answer is correct.
However, why are you calling the Bid model directly?...
A person can have many bids
You're obviously constructing data from the person model, so why not call the following:
#person = Person.find params[:person_id]
#bids = #person.bids #-> bids belong to #person
This will build the collection without calling where.
Of course, your method only uses a single db query. But even still, the above is much more intuitive.
--
As an aside, you'll also want to use a conditional before your loop:
<% if #bids.any? %>
<% #bids.each.... %>
<% end %>
Having one bid is fine, but having none will cause the loop to spit out an error. The above resolves that issue.
I am stuck on what seems should have a very simple solution, but I can not find anything that will work! I am iterating results from a table on the index page (which returns a list of states). This works without any problems when multiple records are returned. However, when a single record is returned, I get an error: undefined method 'each' for #
I know it is causing the error when only one record is returned, but I can not find any documentation on how to handle this, especially in the case that 1 or 0 records could be returned.
Code in controller:
#states = State.find(params[:id])
Code in index page:
<ul>
<% #states.each do |state| %>
<li>
<%= state.state_name %>
</li>
<% end %>
</ul>
Because you're using find, when you send multiple ids in the params, multiple records are matched; when you send a single id, a single instance is returned.
To ensure that each time, you get an ActiveRecord::Relation object that you can call each on, change your controller code to the following:
#states = State.where(id: params[:id]) # index action
You mentioned that it is the index view, so the above change should solve your problem.
If it's the show view, then you need to stick with find and change your view to display only one state.
You need to check if it responds to .each, which is the prime given for knowing if something implements the enumerable module.
if #states.respond_to?(:each)
# iteration goes here
else
# single handling goes here
Ofcourse you can also use the .where option in your query which returns always a collection
#states = State.where(id: params[:id])
Scenario 1:-
When record is queried in controller as:
#states = State.find(params[:id])
Then in view it should be like that:
<p><%= #states.state_name %></p>
Scenario 2:-
When record is queried in controller as:
#states = State.all
Then in view it should be like that:
<ul>
<% #states.each do |state| %>
<li>
<%= state.state_name %>
</li>
<% end %>
</ul>
Note:- In first scenario it is only one object but in second scenario it is a collection of object or a array of object. And only array are iterated.
I have a loop in my view:
<% #deals.each do |d| %>
<% end %>
Deal and ListItem share the :code attribute.
If I wanted to count all the list_items that shared :code with a certain deal, how can I do this in the controller while iterating through the loop?
I understand it's bad form to access Models in the view correct? So that would rule out doing something like this in the loop right?:
<%= "#{ListItem.where(:code => d.code).count}" %>
Can I use a variable or some custom method to achieve this? Please let me know if I can clarify. Thank you!
You want to do all the calculation on the server in your controller action before rendering the view.
So in addition to gathering the #deals, you will also set an instance variable for the count.
def index
#deals = Deals.all # or whatever your finder is
#common_listitem_count = ListItem.where(code: #deals.pluck(:code)).count
end
Then just call the count instance variable in the view:
<%= #common_listitem_count %>
I have the following view to show the categories with the count
<% #categories.each do |category| %>
<% category.sub_categories.sort.each do |sub_category| %>
<li><%= link_to sub_category.name, "category/#{sub_category.slug}", title: sub_category.name.capitalize %> <%= sub_category.posts.where(status: 1).count %></li>
<% end %>
<% end %>
But I dont think using where in view is not good idea. Is there any other way to perform such operation.
I am getting correct count but I need better way to do this. can anyone help
Your Post model should have a scope on it that encapsulates this status logic:
class Post < ActiveRecord::Base
def self.active
where(status: 1)
end
end
Then call it like so from the view:
sub_category.posts.active.count
use scope to do the same thing, your solution is ok otherwise. you don't need to do this controller.
scope :active_posts, lambda{ where(status: 1)}
The only problem I see with this is it causes N+1 queries, because you do 1 query for the categories THEN another query for EACH category. This is ok with small quantities, however can cause serious performance problems later on.
1) I recommend you look into "counter_cache"ing:
- http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-belongs_to
2) OR upon activation/deactivation of Posts, create a method that will increment/decrement a attribute on the Post's Category (i.e. "active_posts")
This code shows all the records of CommunityTopic that belongs to current Community.
How can I limit the numbers to 10 records to display here?
<ul>
<% #community.community_topics.each do |topic| %>
<li>
<%= link_to topic.title, community_topic_path(#community, topic) %>
<%= link_to topic.user.user_profile.nickname, community_topic_path(#community, topic) %>
</li>
<% end %>
</ul>
Use the limit method:
<% #community.community_topics.limit(10).each do |topic| %>
This will only supply the first 10 elements of the collection to the block. If you want to be more sophisticated, you could use something like will_paginate.
In general, such data fetching should take place in the controller. So instead of having a #community variable where the view gets the data from, have a #community_topics as well, which is prefilled with the data you want to render.
You shouldn't usually do this in the view, but rather in the controller. You can use limit as #Fermaref proposed, or you can use a paginator to help you out such as will_paginate or kaminari.
To move this to the controller, try something like this:
def some_action
#community = Community.find(params[:id])
#community_topics = #community.community_topics.order(:some_attribute).limit(10)
end
Then just use #community_topics in your view. One advantage here is that you can now move this logic to a private method for reuse if needed. You can also functionally test that #community_topics limits to 10 rows.
Use 8.3 reorder
The reorder method overrides the default scope order. For example:
#categories = Category.includes(:subcategories).where(active: true).references(:subcategories).order(name: :asc).reorder('categories.name ASC', 'subcategories.name ASC')
http://guides.rubyonrails.org/active_record_querying.html