Method added in plugin is not immediately avail.?

Hi all

I have the following controller:

class MemberController < ApplicationController
performs_authentication :user_model_class => Member
performs_scaffolding :only => [:show, :edit],
:model_id => user.id

end

The first statement, performs_authentication, adds an instance method
“user” to the controller, which I want to use in the second statement
(see code above).
Sadly, I’m getting the following error:

undefined local variable or method `user’ for MemberController:Class

Is this normal behavior, that one can’t use a method, added by one
plugin, immediately? Or must I have done something wrong…?

Thanks
Josh

On 26 Nov 2007, at 14:54, Joshua M. wrote:

end

The first statement, performs_authentication, adds an instance method
“user” to the controller, which I want to use in the second statement
(see code above).
Sadly, I’m getting the following error:

undefined local variable or method `user’ for MemberController:Class

It’s all in the error message :slight_smile: It’s looking for class method and
you’ve added an instance method

Fred

Joshua :

“user” to the controller, which I want to use in the second statement
(see code above).
Sadly, I’m getting the following error:

undefined local variable or method `user’ for MemberController:Class

Is this normal behavior, that one can’t use a method, added by one
plugin, immediately? Or must I have done something wrong…?

You’re in the context of the class not of an instance.
performs_scaffolding is a class method,
and if you write user.id, user should be a local variable or a
class method.

Since user is an instance method and you’re not manipulating an
instance of MemberController, it doesn’t work.

I don’t know what really you want to do with :model_id => user.id
but you may look at creating a Proc object that you will be
called later in the right scope at the right moment.

See the :if => Proc.new { … } option in validations
macros for an example.

HTH,

-- Jean-François.

Hi! Thanks for the helpful answers.

I don’t know what really you want to do with :model_id => user.id

I have written a plugin that handles all the CRUD stuff that Rails’
scaffolds does. So instead of having index, list, show, new etc.
methods, I just can call performs_scaffolding which adds all the
required methods to the controller.

So far, it always used params[:id] to determine which instance to get
for edit, show, destroy etc.

But now I created a controller that represents the logged in user’s
(member) control panel:

class MemberController < ApplicationController
performs_scaffolding :only => [:show, :edit]

end

This controller doesn’t have a “param” part in the URL, because the
logged in user should work on his own “Member” model only (anything else
would be a hacking attempt):

map.member ‘member/:action’,
:controller => ‘member’

So at this time, there’s no params[:id] object when calling member/edit.
Because of this, performs_scaffolding needs another way on how to get an
ID from the programmer. So I added the optional key “model_id” to the
options hash:

performs_scaffolding :only => [:show, :edit],
:model_id => 1234

When this option is set, then performs_scaffolding doesn’t look for
params[:id] anymore but always uses the passed model ID.

So in my case, I want to pass always the ID of the logged in user which
is returned by the instance method “user”:

performs_scaffolding :only => [:show, :edit],
:model_id => user.id

So what to do now? Making the user method a class method? Or using the
Proc method? Or any better idea?

Thanks
Josh

Joshua :

So what to do now? Making the user method a class method?
Or using the Proc method? Or any better idea?

you can do either :

performs_scaffolding … :model_name => :user

Then your plugin does a send(options[:model_name]).id
to get the ID.

(the plugin knows how to get an ID, given a model name)

or :

performs_scaffolding … :model_getter => :user_id

and in the controller, you’ve got a private instance method

def user_id
user.id
end

that is, you tell the plugin the name of the method to get the right ID.

Better is to give the choice between a method name (as a symbol)
and an object Proc.

performs_scaffolding … :model_getter => Proc.new { user.id }

You can also make performs_scaffolding be called with a
block attached and store that block in a variable as a Proc object :

performs_scaffolding … do
user.id
end

then instead of a send, you will have a my_proc.call. See how
Rails handle callbacks like controller filter or AR callbacks
(before_save…)

Your choice depends on the way you want to expose your API.

– Jean-François.