views:

32

answers:

2

In the .Net universe I can use an arbitrary SELECT statement and load many rows into DataTable object. I can then find various DataRows using various field criteria (Name='Jack', Age=34, etc.).

In Ruby on Rails, after doing this to load all employees into memory

rs = Employee.find(:all)

I want to seek a row based an arbitrary criteria.

row = rs.seek(:name => 'Jack')

Does ActiveRow support this? I can't seem to find anything or I'm not using the correct terminology.

If not I'll have to walk all rows and build my own hash tables.

+1  A: 
Employee.find(:all)

will return an array of ActiveRecord instances, so you can either search the array for the relevant records or do something like this:

row = Employee.find_by_name('Jack')

or

rows = Employee.find_all_by_name('Jack')

in order to select the rows you are interested in.

Mr. Matt
AR doesn't really return an Array of relevant records, it returns some lazy object that it can use to build up a query until such time as the result is actually needed. This lets you chain criteria together like @project.tasks.assigned.active.not_for_user(current_user) where each of those methods are a named scope on the Task model. It also lets you do things like employee.accounts << account , if it were just an Array, that wouldn't work, and you'd spend a lot of time duplicating AR magic. Anyway, the OP should read http://guides.rubyonrails.org/active_record_querying.html
Joshua Cheek
@Joshua, railsapi.com says it does return an array: `Person.find(:all) # returns an array of objects for all the rows fetched by SELECT * FROM people`
j.
@Joshua, associations and named_scopes are lazy, but find isn't.
BaroqueBobcat
@Matt, does find_all_by_name, etc., hit the database or search the already loaded table/row data structure? My goal is to cache two queries [Employee.find(:all), Job.find(:all)], then seek in memory.
Pete Alvin
I would have put money down that you could (and that I have) done this, but just tested it out, and you are right, it returns an Array, and I cannot chain methods on it.
Joshua Cheek
I just found the documentation for find_by and it looks like it DOES hit the database. I don't think AR supports in memory filtering of records already selected from the database.
Pete Alvin
+2  A: 

Assuming you have a really good reason for fetching all the data and then filtering it, as opposed to using Rails dynamic finders or scopes.

ActiveRecord find returns an Array as others have commented above. You were really close, but the Array method you need is find (defined in module Enumerable)

all_employees = Employee.find(:all)

jack = all_employees.find { |employee| employee.name == 'Jack' }
Bryan Ash
Was just writing the same answer. Also look into Enumerable#detect and Enumerable#select.
François Beausoleil
Thanks! That's still O(n) [instead of hashtable O(log2n)] but it's better than hitting the disk! My algorithm calls for loading all the data into memory then doing lots of cross-references. I wish AR would build in memory indexes for various columns for super-quick filtering of field data.
Pete Alvin