views:

33

answers:

2

Hi Everyone,

I have a number of records in a model called Kases, each kase record has a status which can be Active, On Hold, Invoice Sent or Archived.

I am trying to work out how to add a number on the dashboard for the total number of kase records, the total number of kase records marked as on hold, the total number of kase records marked as invoice sent, and the total number of kase records marked as archived.

Currently, I set the status of the kase record with the following:

<li>Case Status<span><%= f.select "kase_status", ['Active', 'On Hold', 'Archived', 'Invoice Sent'] %></span></li>

The kase_status is a field in the kases table, and is a string:

  t.string :kase_status

Is there a simple way to do this?

Thanks,

Danny

EDIT:

Console Error Message:

>> Kases.find(:all).select { |k| k.kase_status == "Active"}.size
NameError: uninitialized constant Kases
    from /Library/Ruby/Gems/1.8/gems/activesupport-2.3.8/lib/active_support/dependencies.rb:443:in `load_missing_constant'
    from /Library/Ruby/Gems/1.8/gems/activesupport-2.3.8/lib/active_support/dependencies.rb:80:in `const_missing'
    from /Library/Ruby/Gems/1.8/gems/activesupport-2.3.8/lib/active_support/dependencies.rb:92:in `const_missing'
    from (irb):1
>> 
+1  A: 

Yep!

Update

Following the advice of everyone, I updated the answer. This is a far faster and more appropriate way to accomplish this.

Controller

@kases_active_count = Kase.count(:conditions => ['kase_status = ?', 'Active'])
@kases_on_hold_count = Kase.count(:conditions => ['kase_status = ?', 'On Hold'])
@kases_archived_count = Kase.count(:conditions => ['kase_status = ?', 'Archived'])
@kases_invoice_sent_count = Kase.count(:conditions => ['kase_status = ?', 'Invoice Sent'])

HTML

<%= @kases_active_count %>
Trip
Hi, would it need to be like this?: <%-h Kases.find(:all).select { |k| k.kase_status == "Active"}.size %>?
dannymcc
@dannymcc, I would add it in your controller. Like above. I'll update
Trip
Check to make sure those commands work in IRB though before applying them. That's what I do at least.
Trip
Hi thanks for the pointer, greatly appreciated...but...I have added the controller code to the def index and also tried the def show but neither make the count figure show up. No errors though!
dannymcc
Does this work in `script/console` :: `Kases.find(:all).select { |k| k.kase_status == "Active"}.size` ?
Trip
No: >> Kases.find(:all).select { |k| k.kase_status == "Active"}.sizeNameError: uninitialized constant Kases from /Library/Ruby/Gems/1.8/gems/activesupport-2.3.8/lib/active_support/dependencies.rb:443:in `load_missing_constant' from /Library/Ruby/Gems/1.8/gems/activesupport-2.3.8/lib/active_support/dependencies.rb:80:in `const_missing' from /Library/Ruby/Gems/1.8/gems/activesupport-2.3.8/lib/active_support/dependencies.rb:92:in `const_missing' from (irb):1>>
dannymcc
Ah, I thought you had a model called Kases. Maybe it's called `Kase` ? If that's the case just remove the s from the end of all those statements. Try it in IRB, if it works , apply it to the rest. If it doesn't, let me know what you're model is explicitly called. If you just write `Kase` or `Kases` , then it should let you know what attributes are available to that class. Right now it says, that you have no class or model called `Kases`
Trip
Ok, that was the problem. Final problem - how do I make the figure available outside of the Kase views?
dannymcc
You will have to instantiate it in the controller you want it to be seen in, but you can still call the class from other controllers. So let's say you're in foobars_controller.rb . Inside that file you can have `@klass_statuses = Klass.find(:all).select{|k| k.kase_status }`. Then you will be able to grab it from whatever respect view its in relatively to its controller function.
Trip
Don't forget to vote the answerer up, and check the answer as correct..if it is. :D
Trip
Already done ;), Thanks again!
dannymcc
Hey @dannymcc, I updated my answer after some inquiry. You should do the same. This is a far faster way to accomplish this, and a good practice in general. All obeisance to Shadwell.
Trip
Done. Massive thanks to Trip and Shadwell!
dannymcc
+2  A: 

You can use the count method on Kase, for example:

Kase.count(:conditions => ['kase_status = ?', 'Active'])

This means you just do a query to count the number of matching objects rather than fetching every single Kase instance from the database and checking the value.

If you want to get all of the different status values in a single query you can do:

@all_counts = Kase.find(:all, :group => 'kase_status', :select => 'kase_status, count(*) as how_many)

which will return you a collection of Kase-like objects with the kase_status and how_many attributes. You can then use that collection to display all of your status counts. E.g.

<% @all_counts.each do |c| %>
    <%= c.kase_status %> : <%= c.how_many %>
<% end %>
Shadwell
@shadwell, Your count method seems excellent. When would, if ever, there be a reason to choose my example then when you retrieve all the results and query them?
Trip
@Trip The main reason to get them all and process them one by one would be if you were counting on a derived field - i.e. one that isn't in the database. Maybe (unrealistic but simple example) you might want to count the number of inactive Kases using a method on Kase `inactive?` which returns true if the status is an inactive one.I'm very wary of finding all instances of a model though. I think trying it with more than a few instances in your database you'll find it pretty slow (though you will need indexes on the attributes you group by).
Shadwell