Handling multiple models DRYly-- using eval, but better way?

I have a bunch of models (about 30) that are all handled roughly the
same way despite having different fields, text, etc (there's a big
data structure to drive all that). I'm trying to be DRY and handle
them generically. The best way I've come up with is occasional use of
eval. That leads to controller code like this to, say, add a bunch of
records to the db table...

    tbl = q.code # the particular model's id
    tblp = tbl.pluralize
    tblc = tbl.camelize
    @user_records = eval( "@user.#{tblp}")
    if @user_records.empty?
      stuff.each do |sh|
        rcd = eval( "#{tblc}.new")
        # code here to create new rcd from sh
        eval( "@user.#{tblp} << rcd")
      end
    end

and this, in the corresponding view...

<% form_for @page.code.to_s + "[]", :url => {:action
=> :question, :id => @page.code} do |form| %>
  <% @user_records.each do |rcd| %>
    <% eval "@#{@page.code}= rcd" %>
    <% @columns.each_column do |col| %>
      <%= "<p> #{qfield( form, col)}-- column = #{col.code} /
#{col.type} / #{col.text.to_s}</p>" %>
    <% end %>
  <% end %>
<% end %>

where qfield is a helper to construct the appropriate html for the
column according to its type and other characteristics.

My question -- is there a better way? Rails seems to want an actual
assignment to the @model variable to drive the view, so just pointing
at it with a more generic variable won't work (I think I tried this,
but maybe I didn't do it right). That's the reason behind the third
line of the view.

And is there a way to treat the model's class dynamically without
eval, in -- rcd = eval( "#{tblc}.new")

Thanks. --David.

Hi --

I have a bunch of models (about 30) that are all handled roughly the
same way despite having different fields, text, etc (there's a big
data structure to drive all that). I'm trying to be DRY and handle
them generically. The best way I've come up with is occasional use of
eval. That leads to controller code like this to, say, add a bunch of
records to the db table...

   tbl = q.code # the particular model's id
   tblp = tbl.pluralize
   tblc = tbl.camelize
   @user_records = eval( "@user.#{tblp}")

      @user_records = @user.send(tblp)

   if @user_records.empty?
     stuff.each do |sh|
       rcd = eval( "#{tblc}.new")

          rcd = tblc.constantize.new

       # code here to create new rcd from sh
       eval( "@user.#{tblp} << rcd")

          @user.send(tblp) << rcd

     end
   end

and this, in the corresponding view...

<% form_for @page.code.to_s + "[]", :url => {:action
=> :question, :id => @page.code} do |form| %>
<% @user_records.each do |rcd| %>
   <% eval "@#{@page.code}= rcd" %>

      <% instance_variable_set("@#{@page.code}", rcd) %>

   <% @columns.each_column do |col| %>
     <%= "<p> #{qfield( form, col)}-- column = #{col.code} /
#{col.type} / #{col.text.to_s}</p>" %>
   <% end %>
<% end %>
<% end %>

where qfield is a helper to construct the appropriate html for the
column according to its type and other characteristics.

My question -- is there a better way? Rails seems to want an actual
assignment to the @model variable to drive the view, so just pointing
at it with a more generic variable won't work (I think I tried this,
but maybe I didn't do it right). That's the reason behind the third
line of the view.

And is there a way to treat the model's class dynamically without
eval, in -- rcd = eval( "#{tblc}.new")

See above for alternatives to all of your eval uses (untested). The
methods I've used are all Ruby methods with the exception of
constantize, which is from ActiveSupport.

David