Questions about inheritance in Rails


#1

I am in the process of subclassing some things in a current Rails
project and would like some feedback on how I’m approaching it… what I
have works but I’m not sure if there is a better way to approach this.
:slight_smile:

I am currently subclassing controllers like so:

class LookupsController < ApplicationController

GET /lookups

def index
end

#-----------------------------------------------------------------

the rest of these methods are called from subclassed controllers

#-----------------------------------------------------------------

GET /{controller_name}

GET /{controller_name}.xml

def index_list
render ‘lookups/index’ and return if controller_name == ‘lookups’
eval(’@’ + controller_name + ’ = ’ + model_name + ‘.find(:all)’)
respond_to do |format|
format.html { render ‘lookups/list’ }
format.xml { render :xml => eval(’@’ + controller_name +
‘.to_xml’) }
end
end

… and so on …

end

class StatesController < LookupsController
def index
index_list
end
end

and the shared view template looks like this;

<%= pretty_controller_name %>

<% for item in eval('@' + controller_name) %> "> <% end %>
Actions Name
  <%= link_to(image_tag('item_delete.gif'), eval(model_name + '_path(:id => item)'), :confirm => 'Are you sure?', :method => :delete, :class => 'image_link') %> <%= link_to(image_tag('item_edit.gif'), eval('edit_' + model_name + '_path(:id => item)'), :class => 'image_link') %> <%= item.name %> (<%= pluralize(item.jobs.count, "job") %>)

<%= submit_tag "Add a " + pretty_model_name, {:type => 'button', :onClick=>"parent.location='" + eval('new_' + model_name + '_path') + "'" } %>

and a helper like so:

module LookupsHelper
def controller_name
controller.controller_name
end
def model_name
controller.controller_name.singularize
end
def pretty_model_name
model_name.gsub(’’, ’ ‘).capitalize_all
end
def pretty_controller_name
controller_name.gsub(’
’, ’ ').capitalize_all
end
end

My main question revolves around the liberal use of eval() … is there
a better way? Am I making this harder than it should be?

Thanks for any feedback…

Cheers,
Tim


#2

Hi –

On Wed, 6 Jun 2007, Tim F. wrote:

GET /lookups

render ‘lookups/index’ and return if controller_name == ‘lookups’
eval(’@’ + controller_name + ’ = ’ + model_name + ‘.find(:all)’)
respond_to do |format|
format.html { render ‘lookups/list’ }
format.xml { render :xml => eval(’@’ + controller_name +
‘.to_xml’) }
end
end

This is all sort of at first glance, so I could well be overlooking
some pitfalls, but why don’t you just say @items or something instead
of all the eval’ing? Also, instead of model_name, you could have your
helper method return a model class. That way, you could do:

@items = model.find(:all)

<% for item in eval(’@’ + controller_name) %>

">   <%= link_to(image_tag('item_delete.gif'), eval(model_name + '_path(:id => item)'),

At the very least I would use send there:

send("#{model_name}_path", :id => item)

But it’s nicer if you can encapsulated that kind of calculation in the
controller or a helper method.

I’ll leave it at that, pending feedback on what I’ve missed :slight_smile:

David


Q. What is THE Ruby book for Rails developers?
A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black)
(See what readers are saying! http://www.rubypal.com/r4rrevs.pdf)
Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
A. Ruby Power and Light, LLC (http://www.rubypal.com)


#3

David wrote:

This is all sort of at first glance, so I could well be overlooking
some pitfalls, but why don’t you just say @items or something instead
of all the eval’ing? Also, instead of model_name, you could have your
helper method return a model class. That way, you could do:

@items = model.find(:all)

Thanks… good point. :slight_smile: I was so focused on translating the existing
code that I missed that.

At the very least I would use send there:

send("#{model_name}_path", :id => item)

But it’s nicer if you can encapsulated that kind of calculation in the
controller or a helper method.

In other words, wrap the route method invocation with a helper method to
simplify the view code?

One other question comes to mind… in the view I am creating a
button…

<%= submit_tag "Add a " + pretty_model_name, {:type => ‘button’,
:onClick=>“parent.location=’” + eval(‘new_’ + model_name + ‘_path’) +
“’” } %>

Is there a cleaner way to do this besides building the onClick
javascript?

I’ll leave it at that, pending feedback on what I’ve missed :slight_smile:

Thanks much for the feedback!

Cheers,
Tim


#4

Hi –

On Wed, 6 Jun 2007, Tim F. wrote:

In other words, wrap the route method invocation with a helper method to
simplify the view code?

Yes – something like:

def model_path(*args)
send("#{model_name}_path", *args)
end

at which point you could do:

<%= link to “Click here”, model_path :id => item %>

There may be yet further ways to simplify it all but initially at
least I’d go for pushing all the low-level-ish stuff out of the views
and see what happens.

(Punting on the JS question… :slight_smile:

David


Q. What is THE Ruby book for Rails developers?
A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black)
(See what readers are saying! http://www.rubypal.com/r4rrevs.pdf)
Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
A. Ruby Power and Light, LLC (http://www.rubypal.com)