Find when you have the model name but not the class

Hi,

How can I get a model class and then search on it if I only have the
model name?

I have created an item_history to track the changes of an item in a
stock list. I use this method in the Stock model, to create the history
information:

def add_history(item, process)
    history = ItemHistory.new
    history.model = item.class.to_s
    history.item_id = item.id
    history.status = item.stock_status.name
    history.comments = item.comments
    history.process_name = process
    if user = User.find(session[:user_id])
      history.who = user.user_name
    end
    history.save
  end

I am then able to list the history of a particular item, or all history.
In the list of all history, I use:

<% if Stock.find(:first, :conditions => ["id = ?", 
history.item_id.to_i]) -%>
            <td><%= link_to "#{history.model}/#{history.item_id}",
                    :controller => history.model.pluralize.downcase,
                    :action => "show",
                    :id => history.item_id -%></td>
          <% else -%>
            <td><%=h history.model -%>/<%=h history.item_id -%></td>
          <% end -%>

This either outputs model/id or the same with a link to that item if the
item exists (if the action being recorded is delete, the item won’t be
there).

How do I recreate the “if Stock.find” statement to accept any model
name. I want something the will let me grab an instance of the model
class by passing history.model to it, and then let me do a find on that
class.

Is that possible?

I want to reuse this system in another model.

Try:

eval(model_name).find(:all)

You can do history.item.class.find …
Which will do a Stock.find if item is an instance of class Stock,
Badger.find if item is an instance of Badger etc…

Fred

2 ways I know of…

Object.const_get(“MyClass”)

eval(“MyClass”)

not sure which is more efficient

David F. wrote:

Try:

eval(model_name).find(:all)

Splendid. This worked a treat:

if eval(history.model).find(:first, :conditions => [“id = ?”,
history.item_id.to_i])

Thank you David and Chris for your prompt and useful responses.

Frederick C. wrote:

You can do history.item.class.find …
Which will do a Stock.find if item is an instance of class Stock,
Badger.find if item is an instance of Badger etc…

Fred

Thanks Fred. I missed that when I responded earlier.

I don’t think that will work because I am only storing the model name in
history_item, and not an instance of the model class. The class of the
history object is always HistoryItem I think.

Rob

Rob N. wrote:

always HistoryItem I think.

In fact ItemHistory

Rob N. wrote:

history.item_id.to_i])

Thank you David and Chris for your prompt and useful responses.

You can also do model_name.constantize.find…
if however ‘model_name’ isn’t the actual name of the class - meaning
‘MyTable’ and not eg. ‘my_tables’ - you need to call classify first, eg.
model_name.classify.constantize.find…

eval is also pretty cool though :]

Hope this helps!
Cheery-o
Gustav P.
[email protected]