Question regarding symbols

I asked in #rubyonrails on freenode, but unfortunately, am either clueless to the explanation technoweenie gave about using a block, or he didn’t understand my problem.

I have a site in the works, based on nested controllers and rest.

eg: /clients/1/foo/2/bar/3

The problem, is in the controller foo, i have to have:

before_filter :load_client

In bar,

before_filter :load_foo

The issue is when i have a large app, I don’t want to have 50 versions of the load_* when all they do is set @key = Something.find params[:something_id]

So, my question, how would I be able to create a method named load_parent and do:

before_filter :load_parent :client

Then have load_parent take :symbol and do @(symbol.to_s
) = symbl.to_s.find params[:symbol_id]

Hopefully this makes sense.

Thanks.

Hi --

I asked in #rubyonrails on freenode, but unfortunately, am either clueless
to the explanation technoweenie gave about using a block, or he didn't
understand my problem.

I have a site in the works, based on nested controllers and rest.

eg: /clients/1/foo/2/bar/3

The problem, is in the controller foo, i have to have:

before_filter :load_client

In bar,

before_filter :load_foo

The issue is when i have a large app, I don't want to have 50 versions of
the load_* when all they do is set @key = Something.findparams[:something_id]

So, my question, how would I be able to create a method named load_parent
and do:

before_filter :load_parent :client

Don't forget the comma between arguments in method calls :slight_smile:

Then have load_parent take :symbol and do @(symbol.to_s) =
symbl.to_s.findparams[:symbol_id]

Hopefully this makes sense.

I didn't see Rick's suggestion, so I don't know whether this is
similar, but here's one possibility. (If you don't understand it,
there's a book I can recommend that serves the specific purpose of
explaining Ruby in depth to Rails developers :slight_smile:

First, in application.rb (the parent controller file), write your
load_param (or parent, but I think param makes more sense) method. In
fact, make it plural, so that you can handle more than one symbol at a
time:

   def load_params(*symbols)
     symbols.each do |sym|
       c = Object.const_get(Inflector.classify(sym))
       instance_variable_set("@#{sym}", c.find(params["#{sym}_id"]))
     end
   end

That method uses the utility object Inflector to get the class-like
version of sym (:x becomes "X", :some_thing becomes "SomeThing",
etc.). That string can then be used by Object.const_get to get the
actual class object.

The next line does the actual setting of the instance variable.

Now, in the controller where you want this to happen, you can do:

   before_filter {|c| c.load_params(:a,:b,:c) }

When you give a code block to before_filter, the controller object
itself gets yielded to the block; that's c. So you can then call
load_param on c, passing in the params you want to set.

There are other ways to engineer this, but that's one way that gives
you a pretty high-level interface in the controller itself.

David

David,

Thanks for the help. It didn’t seem to be working, I was getting:

`@{sym}’ is not allowed as an instance variable name

I realized I had to convert the symbol to a string first, also, {} isn’t allowed in the variable name (it’s not being interpolated?), thus, my solution (which works great).

instance_variable_set(’@’ + sym.to_s, c.find(params["#{sym}_id"]))

replace that line and it’s great :smiley:

Thanks for the help, much appreciated.

Hi --

David,

Thanks for the help. It didn't seem to be working, I was getting:

`@{sym}' is not allowed as an instance variable name

You need:

   "@#{sym}"

Here's my example again:

   def load_params(*symbols)
     symbols.each do |sym|
       c = Object.const_get(Inflector.classify(sym))
       instance_variable_set("@#{sym}", c.find(params["#{sym}_id"]))
     end
   end

You don't have to do any to_s; string interpolation does that
automatically.

David

I feel like an idiot. Thanks :slight_smile: