Forum: Ruby on Rails noobie activerecord find query

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
B0be4bfef5a22697a0f44f4fe295aaef?d=identicon&s=25 James Whittaker (aftershock)
on 2006-05-10 15:40
In my webapp a todolist has many todo items. I am trying to display
lists that are completed. By incomplete I mean that all the items in
that list are done (booolean = true). I hope to have a list of active
lists and complete lists on one page.
I'm no ruby expert by any means so I think I have to 'pipe' some results
into another query??

Can you help please?
E1c74637dbb1b765861978e4c4f6388e?d=identicon&s=25 Tom Armitage (Guest)
on 2006-05-10 16:19
(Received via mailing list)
So you want to populate an instance variable with all the items which
are
done, basically. Here we go:

@todos = Todo.find(:all, :conditions => 'done = Y')

(or whatever the flag for done is).

Alternatively, you could use

@todos = Todo.find_all_by_done('Y')

but the former will probably get you into better habits.

It's not a Ruby problem at all, it's basic database stuff. There's no
need
to "pipe" anything to a second query, it's a basic WHERE clause.

How much do you know about development, and SQL in particular? You might
find Rails pretty rough going if this is tricky, just as a warning.

t.
B0be4bfef5a22697a0f44f4fe295aaef?d=identicon&s=25 James Whittaker (aftershock)
on 2006-05-10 16:27
Tom Armitage wrote:
> So you want to populate an instance variable with all the items which
> are
> done, basically. Here we go:
>
> @todos = Todo.find(:all, :conditions => 'done = Y')
>
> (or whatever the flag for done is).
>
> Alternatively, you could use
>
> @todos = Todo.find_all_by_done('Y')
>
> but the former will probably get you into better habits.
>
> It's not a Ruby problem at all, it's basic database stuff. There's no
> need
> to "pipe" anything to a second query, it's a basic WHERE clause.
>
> How much do you know about development, and SQL in particular? You might
> find Rails pretty rough going if this is tricky, just as a warning.
>
> t.

Thanks, sorry probably did not explain it correctly. My todo_list Has
Manay todo_items. each item has a done flag (boolean). A todo_list
becomes complete when all of its todo_items are marked as done,
otherwise it is not done. The todo_list does not have a done field in
the database.
E1c74637dbb1b765861978e4c4f6388e?d=identicon&s=25 Tom Armitage (Guest)
on 2006-05-10 16:43
(Received via mailing list)
OK, try pasting the following into your Todo_list model (todo_list.rb)
at the top

has_many :completed_items,
         :class_name => 'Todo_item',
         :conditions => 'done is not null'

def completed?
   if self.todo_items == self.completed_items
       true
   else
       false
   end
end

Then you'll find that Todo_list.completed? should return 'true' if all
the items are completed, and false if not. So now you can seperate out
completed and uncompleted lists

I think that'll work, anyhow. If it does, do you understand why?

(Hope you didn't think I was condescending last time).
B0be4bfef5a22697a0f44f4fe295aaef?d=identicon&s=25 James Whittaker (aftershock)
on 2006-05-10 16:53
Tom Armitage wrote:
> OK, try pasting the following into your Todo_list model (todo_list.rb)
> at the top
>
> has_many :completed_items,
>          :class_name => 'Todo_item',
>          :conditions => 'done is not null'
>
> def completed?
>    if self.todo_items == self.completed_items
>        true
>    else
>        false
>    end
> end
>
> Then you'll find that Todo_list.completed? should return 'true' if all
> the items are completed, and false if not. So now you can seperate out
> completed and uncompleted lists
>
> I think that'll work, anyhow. If it does, do you understand why?
>
> (Hope you didn't think I was condescending last time).

Thanks for the help. It is very similar to what I have in the model
already:
def complete?
	   todo_items.each do |todoitem|
	      return false if not taskitem.done?
	   end
	   true
	end

What I was trying to do was get a has of each like this:

@active_lists = TodoList.find(:all,

@completed_lists = TodoList.find(:all,

The only way I can guess to do it it to return all the todolists then
ittterate over them one by one and add them to an 2 new arrays. Seems a
little complex. I need two variables because of the way the view is
listing them out.
E1c74637dbb1b765861978e4c4f6388e?d=identicon&s=25 Tom Armitage (Guest)
on 2006-05-10 17:02
(Received via mailing list)
Aha.

OK, try this: you could set a new field in your database/model called
"done". Then what you do is you have an ActiveRecord observer watch
the model, and every time one of its Todo_items gets marked as done,
the observer checks if they're all done, and if they're all done, it
sets Todo_list.done to be true. If any of them change status, it
unsets the done status on the list.

Then you CAN just say @active_list = TodoList.find_all(:conditions =>
"done is not null").

You could either use an observer or a callback on before_save. Have a
look in the agile book or the API documentation - off the top of my
head, I can't help you.

You don't need two variables for your view necessarily, but it's
better practice to have them.

I think this is getting near solving your problem: the extra field in
the DB will make the app so much faster, but you don't have to worry
about updating it, you can make it update itself.
B0be4bfef5a22697a0f44f4fe295aaef?d=identicon&s=25 James Whittaker (aftershock)
on 2006-05-10 17:21
Tom Armitage wrote:
> Aha.
>
> OK, try this: you could set a new field in your database/model called
> "done". Then what you do is you have an ActiveRecord observer watch
> the model, and every time one of its Todo_items gets marked as done,
> the observer checks if they're all done, and if they're all done, it
> sets Todo_list.done to be true. If any of them change status, it
> unsets the done status on the list.
>
> Then you CAN just say @active_list = TodoList.find_all(:conditions =>
> "done is not null").
>
> You could either use an observer or a callback on before_save. Have a
> look in the agile book or the API documentation - off the top of my
> head, I can't help you.
>
> You don't need two variables for your view necessarily, but it's
> better practice to have them.
>
> I think this is getting near solving your problem: the extra field in
> the DB will make the app so much faster, but you don't have to worry
> about updating it, you can make it update itself.

Tom, thats brilliant. I am just looking again at the Agile book trying
to get my head around the observers. It may take a while. (page 280
onwards).

Tell me Tom, could this help with my other problem I have looming. I
have an overview page that is going to list each of the users projects
and underneath each project there will be a list of the latest 10
updated/created items. These items will be from one of 4 ActiveRecord
models (like messages, todos, tickets) I was trying to work oyt how to
query each project then find the top 10 for each of the has_maany items,
then re iterate over the array of results ordering them in date order.
This would be for each project. Similar to basecamps dashboard (in
function anyway). This is the next hurdle! Would your suggestion here
help as well?
E1c74637dbb1b765861978e4c4f6388e?d=identicon&s=25 Tom Armitage (Guest)
on 2006-05-10 17:46
(Received via mailing list)
> then re iterate over the array of results ordering them in date order.
> This would be for each project. Similar to basecamps dashboard (in
> function anyway). This is the next hurdle! Would your suggestion here
> help as well?
>

OK. So one thing to consider is Single Table Inheritance; if the
"items" users are fairly similar, you could store them in a table
called "items" and then subclass items, ie
class Todo < Item

This is also in the Agile book, and might be the best way of doing
things. Alternatively, make a method on the User class called
"top_ten" that grabs the top ten from each type of item (the most
you'll ever need), rams them into an array, sort the array by
created_at desc, and then throw away all but the first ten.
Cumbersome, but it'll work.

But yeah, I'd consider STI, before the cumbersome way.

Also: do consider cacheing. Slow queries might not be too much of a
burn if they're only being made once every half hour, and then when
anything gets saved/altered...
E1c74637dbb1b765861978e4c4f6388e?d=identicon&s=25 Tom Armitage (Guest)
on 2006-05-10 17:52
(Received via mailing list)
Also, I should just add: I'm not that brilliant a developer, so other
people may be able to solve this problem better. But there's LOTS in
those two chapters on ActiveRecord that might help you, so do reread
them.
B0be4bfef5a22697a0f44f4fe295aaef?d=identicon&s=25 James Whittaker (aftershock)
on 2006-05-10 18:41
Tom Armitage wrote:
> Also, I should just add: I'm not that brilliant a developer, so other
> people may be able to solve this problem better. But there's LOTS in
> those two chapters on ActiveRecord that might help you, so do reread
> them.

I must admit i'm not really getting the observer thing yet, i'm trying
it now but can't seem to get what I want.

STI is out of the question for the items due to many differences and
complexities of the model. I

'm supprised that nobody has explained how the 37sigs guys do the
dashboard thing from an activerecord perspective. It would be most
interesting to see how they have done it with a few examples. Its stuff
like this that needs to be added to Rails Recipes, real world app stuff.
This topic is locked and can not be replied to.