Add dynamic instance methods in a controller class

Hello All,

I have a problem while developping an application using rails.
In fact, this is more a general question on Ruby methods.
I’d like to add some methods to my controller depending upon some
parameters read from an xml file during initialisation (I hope I am
quite clear :slight_smile: )
Below is the code I am using:


require ‘rexml/Document’
include REXML

class MyController < ApplicationController

def index
            # Xsd is a model (not ActiveRecord that is used to get

values from an XML file
xsd = Xsd.new(“myfile.xsd”)

	# Get main section
	@main_sections = xsd.get_main_sections

	# Get item for first section
	@item = xsd.get_items_per_section(@main_sections[0].to_s)

	# Dynamically create method for to retrieve list of fields for each

main sections
# THIS PART IS NOT WORKING
@main_sections.each do |section|
self.instance_eval{ define_method(“get_item_for_#{section}”)
{“toto”}}
end
end
end

While testing this, I have an error message saying that the
define_method does not exist !!!
Why is this method not found ???
I am still not sure about the instance_eval, class_eval, define_method
I need to use.
Do you have any clues regarding this problem ?

Thanks a lot,

Luc

Luc J. wrote:

I have a problem while developping an application using rails.
[snip]

You might have better luck asking this question on the Rails group:
http://groups.google.com/group/rubyonrails-talk

Il giorno 04/nov/06, alle ore 16:03, Luc J. ha scritto:

           # THIS PART IS NOT WORKING
  @main_sections.each do |section|
  	self.instance_eval{ define_method("get_item_for_#{section}")  

{“toto”}}
end

I suggest something like:

@main_sections.each do |section|
eval %Q(
def get_item_for_#{section}
“toto”
end
)
end

I didn’t try it but I think it should work.

Hello All,

(I first tried to post this message directly from googlegroup but it
did not show up, do you know why ?)

I have a problem while developping an application using rails.
I’d like to add some methods to my controller depending upon some
parameters read from an xml file during initialisation (I hope I am
quite clear :slight_smile: )
Below is the code I am using:


require ‘rexml/Document’
include REXML

class MyController < ApplicationController

    def index
            # Xsd is a model (not ActiveRecord that is used to get

values from an XML file
xsd = Xsd.new(“myfile.xsd”)

            # Get main section
            @main_sections = xsd.get_main_sections

            # Get item for first section
            @item = 

xsd.get_items_per_section(@main_sections[0].to_s)

            # Dynamically create method for to retrieve list of

fields for each
main sections
# THIS PART IS NOT WORKING
@main_sections.each do |section|
self.instance_eval{
define_method(“get_item_for_#{section}”) {“toto”}}
end
end
end

While testing this, I have an error message saying that the
define_method does not exist !!!
Why is this method not found ???
I am still not sure about the instance_eval, class_eval, define_method
I need to use.
Do you have any clues regarding this problem ?

Thanks a lot,

Luc

Thanks a lot, I have post it in rubyonrails-talk.
Sorry for this but I though this was more linked to ruby than to rails.
Luc

Hi –

On Sun, 5 Nov 2006, Luc J. wrote:

Below is the code I am using:
xsd = Xsd.new(“myfile.xsd”)
# THIS PART IS NOT WORKING
@main_sections.each do |section|
self.instance_eval{

instance_eval just sets “self” temporarily to a new value. In this
case, you’re setting self to self :slight_smile:

define_method(“get_item_for_#{section}”) {“toto”}}
end
end
end

While testing this, I have an error message saying that the
define_method does not exist !!!
Why is this method not found ???

Because it’s not a method of the object to which you’re sending the
message – namely, your controller object. It’s a method of the
controller class. So you’d want to do:

self.class.class_eval { define_method … }

David


David A. Black | [email protected]
Author of “Ruby for Rails” [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB’s Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] Ruby for Rails | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org

Helo David,

I tried the following code but this is not working:

@main_sections.each do |section|
puts “defining get_item_for_#{section} method”
self.class.class_eval do
puts “before defining method”
define_method(“get_item_for_#{section}”) do
puts “inside defining method”
end
puts “after defining method”
end
end

several methods should be created (get_item_for_header,
get_item_for_competencies, …)

In the log file (in the server console), they seems to be defined:

defining get_item_for_header method
before defining method
after defining method
defining get_item_for_competencies method
before defining method
after defining method

bug when I try http://localhost:3000/cv/get_item_for_header I got the
following error:

Unknown action
No action responded to get_item_for_header

if I open a console and list all the CvController methods, the new
methods do not show up.

Do you have any idea?

Thanks a lot,

Luc

Hello All,

Does everybody have a clue for this problem?
I guess this is more ruby related but as a controller is in the
place… :slight_smile:

Thanks a lot,

Luc

Great, thanks a lot David,
I will try this !!!
Luc

Hi –

On Sun, 5 Nov 2006, Luc wrote:

  	puts "inside defining method"
  end
  puts "after defining method"

end
end

several methods should be created (get_item_for_header,
get_item_for_competencies, …)

Is this at the top level of the class (rather than in an instance
method)? If so, lose the “self.class.” part :slight_smile:

David


David A. Black | [email protected]
Author of “Ruby for Rails” [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB’s Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] Ruby for Rails | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org

Hi again –

On Sun, 5 Nov 2006, Luc wrote:

bug when I try http://localhost:3000/cv/get_item_for_header I got the
following error:

Unknown action
No action responded to get_item_for_header

I think I (finally) spot the issue. The new methods are not going to
persist from one action to another. You might need to define them in
a before_filter, so that they’ll get defined each time, or find some
other way to persist or cache them.

David


David A. Black | [email protected]
Author of “Ruby for Rails” [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB’s Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] Ruby for Rails | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org

Hi David,

So you think the class definition is not keep from one action to the
other one? Then the problem I have make some sense. But, isn’t strange
to have to redefine those methods each time ? I think I will then need
to find a way to store the sections array to be able to reconstruct the
methd for each action.
What is the best way to keep variable to one action to another, can I
use a session variable ?

Thanks a lot David (those problem are good for me as I can learn rails
then :slight_smile: )
Cheers,
Luc

Hello David,

I got your point and set a before_filter in which I create those
methods, that seems to work fine that way.
But, because there is a but :-), I do not really understand why after
having added some instance method to a given class, those methods are
not available to all instances created afterwards !!! This seems
really strange and that make me think that maybe I am not using the
correct syntax to define my methods within the index method !!!
What do you think ?

Sorry for bothering you with this,

Thanks a lot,

Luc