How get instance of form_for object from @object_name ?

I have a custom form builder. In it I have a method for retrieving validation error messages.

Currently it gets used like this:

   <% form_for :my_obj.....
   <%= form.draw_invalid_msg(my_obj.errors[:userHosts]) %>

I would like to reduce that to this:

   <%= form.draw_invalid_msg(:userHosts) %>

My method code would that start with something like this:

   def draw_invalid_msg(field_name)
     invalid_messages = @object_name.errors[field_name]

Well, that doesn't work, of course, because @object_name is just a symbol, not the actual AR object data. So, yes, I could explicitly pass in the obj to start with, but that's exactly what I am trying to eliminate.

So, what introspective tricky can be used to yield access to the actual object within :my_obj via the @object_name ivar value?

Make sense?

-- gw

I think this will get it:

invalid_messages = instance_eval("@#{object_name}").errors[field_name]

Nope. I think your idea would have needed @object_name not just object_name, but that didn't work either.

I tried a few versions with eval too, but no luck so far.

-- gw

Nope. I think your idea would have needed @object_name not just
object_name, but that didn't work either.

I tried a few versions with eval too, but no luck so far.

form.object :slight_smile:

Fred

form.object :slight_smile:

ooOOOooo. Tricky! :stuck_out_tongue:

-- gw (egads)

Oops. Not so tricky. form doesn't propogate into the custom builder methods -- which makes sense. So, I would guesd that form.object works inside the form, but it doesn't inside a custom builder method.

   def draw_invalid_msg(field_name)
     invalid_messages = form.object.errors[field_name]

That's what I tried, which I should have recognized wasn't going to work.

-- gw

Oops. Not so tricky. form doesn't propogate into the custom builder
methods -- which makes sense. So, I would guesd that form.object
works inside the form, but it doesn't inside a custom builder method.

  def draw_invalid_msg(field_name)
    invalid_messages = form.object.errors[field_name]

That's what I tried, which I should have recognized wasn't going to
work.

is this in a form builder ? in which case self is the form build, so
just object.errors should work

Fred

Yes, it is. Nope, it didn't.

Currently, my baseline code gets used like this:

    <% form_for :my_obj.....
    <%= form.draw_invalid_msg(my_obj.errors[:userHosts]) %>

I would like to reduce that to this:

    <%= form.draw_invalid_msg(:userHosts) %>

My custom form builder method would start with something like this:

    def draw_invalid_msg(field_name)
      invalid_messages = @object_name.errors[field_name]

...but I need a replacement for @object_name. form.object, or just object doesn't work.

This would be greatly simplified if the form builder had access to the originating controller's instance variables, but that appears to not be the case (though I ran into false data on ivar scope before :wink:

Anyway, it would seem that any variable usable within my form builder method must be an instance var like @object_name, and not just a local var like object ?

-- gw

Yes, it is. Nope, it didn't.

Currently, my baseline code gets used like this:

   <% form_for :my_obj.....
   <%= form.draw_invalid_msg(my_obj.errors[:userHosts]) %>

I would like to reduce that to this:

   <%= form.draw_invalid_msg(:userHosts) %>

My custom form builder method would start with something like this:

   def draw_invalid_msg(field_name)
     invalid_messages = @object_name.errors[field_name]

...but I need a replacement for @object_name. form.object, or just
object doesn't work.

This would be greatly simplified if the form builder had access to
the originating controller's instance variables, but that appears to
not be the case (though I ran into false data on ivar scope before :wink:

it's a completely distinct object so would be a little crazy.

Anyway, it would seem that any variable usable within my form builder
method must be an instance var like @object_name, and not just a
local var like object ?

it's @object, but there's an accessor, so object should work. There are plenty of built in helpers using @object so object/@object should work, unless you're doing something really funny,

Fred

Just to be sure -- are you talking Rails 2.0? I am using 1.2.6.

As far as I can tell, I'm not doing anything weird. Generated a form builder, have a number of HTML drawing methods that I use just fine. Nothing tricky, just some simple string rendering.

Just to see if @object exists, I used debug(@object) right inside the form_for boundaries (not one of my builder methods), and I get nothing. if I debug (object) then I get local var not defined error. If I debug (my_obj) then I get a full object dump. So it seems to me dey ain't no @object. So either it's Rails 2 or I broke it.

-- gw

Currently, my baseline code gets used like this:

  <% form_for :my_obj.....
  <%= form.draw_invalid_msg(my_obj.errors[:userHosts]) %>

I would like to reduce that to this:

  <%= form.draw_invalid_msg(:userHosts) %>

My custom form builder method would start with something like this:

  def draw_invalid_msg(field_name)
    invalid_messages = @object_name.errors[field_name]

...but I need a replacement for @object_name. form.object, or just
object doesn't work.

Anyway, it would seem that any variable usable within my form
builder
method must be an instance var like @object_name, and not just a
local var like object ?

it's @object, but there's an accessor, so object should work. There
are plenty of built in helpers using @object so object/@object should
work, unless you're doing something really funny,

Just to be sure -- are you talking Rails 2.0? I am using 1.2.6.

Ah yes, I almost certainly am. No clue what's going on in 1.2.6,
although a cursory look at the source suggests it's the same

As far as I can tell, I'm not doing anything weird. Generated a form
builder, have a number of HTML drawing methods that I use just fine.
Nothing tricky, just some simple string rendering.

Just to see if @object exists, I used debug(@object) right inside the
form_for boundaries (not one of my builder methods), and I get
nothing. if I debug (object) then I get local var not defined error.

if you mean

<% form_for ... do |f| %>
<%= object %>
<% end %>
then that won't work (since object is evaluated in the context of the
view, not in the context of the form builder (f.object should work
there though).

If I debug (my_obj) then I get a full object dump. So it seems to me
dey ain't no @object. So either it's Rails 2 or I broke it.

Fred

Just to be sure -- are you talking Rails 2.0? I am using 1.2.6.

Ah yes, I almost certainly am. No clue what's going on in 1.2.6,
although a cursory look at the source suggests it's the same

As far as I can tell, I'm not doing anything weird. Generated a form
builder, have a number of HTML drawing methods that I use just fine.
Nothing tricky, just some simple string rendering.

Just to see if @object exists, I used debug(@object) right inside the
form_for boundaries (not one of my builder methods), and I get
nothing. if I debug (object) then I get local var not defined error.

if you mean

<% form_for ... do |f| %>
<%= object %>
<% end %>
then that won't work (since object is evaluated in the context of the
view, not in the context of the form builder (f.object should work
there though).

   <% form_for :edp_target,
     :url => {:action => :record_editor},
     :builder => EdpBuilder do |form| %>

     <%= debug() %>

where () = (@object), (form.object), or (object) -- none yield any data.

So, @object appears to be 2.0-specific.

What I do have is @object_name, but I can't figure out how to leverage that into a reference to the actual data held in @edp_target to which :edp_target is the name of.

It's not critical. I was just hoping to simplify something.

-- gw

Just to be sure -- are you talking Rails 2.0? I am using 1.2.6.

Ah yes, I almost certainly am. No clue what's going on in 1.2.6,
although a cursory look at the source suggests it's the same

As far as I can tell, I'm not doing anything weird. Generated a form
builder, have a number of HTML drawing methods that I use just fine.
Nothing tricky, just some simple string rendering.

Just to see if @object exists, I used debug(@object) right inside
the
form_for boundaries (not one of my builder methods), and I get
nothing. if I debug (object) then I get local var not defined error.

if you mean

<% form_for ... do |f| %>
<%= object %>
<% end %>
then that won't work (since object is evaluated in the context of the
view, not in the context of the form builder (f.object should work
there though).

  <% form_for :edp_target,
    :url => {:action => :record_editor},
    :builder => EdpBuilder do |form| %>

    <%= debug() %>

where () = (@object), (form.object), or (object) -- none yield any
data.

Reading the source, it appears that form_for :edp_target, @edp_target
will populate object properly with @edp_target (and with 2.0, just
form_for @edp_target would work)

Fred

Ah. OK, after more tinkering using this version:

   <% form_for :edp_target, @edp_target,

form.object is populated within the form_for boundaries, but @object is not. However, in my EdpBuilder methods, @object is available--which is all I need. From there, I can do what I need.

Thanks for sticking with this Fred -- as always your vantage point has helped. I'm going to owe you a nice dinner someday.

-- greg

Nope. I think your idea would have needed @object_name not just
object_name, but that didn't work either.

I tried a few versions with eval too, but no luck so far.

-- gw

It should have been the symbol of the name of the object. The
instance_eval statment would get inspected into @some-named-object via
string interpolation and the instance_eval would have evaluated that
against the instance.

FWIW, I've used that trick to do something very similar to what you're
after. I built a little lib of methods that allow me to use ruby
syntax to generate extjs compatible javascript. In my scenario I was
emulating form_for with ext_form_for and needed to account for the
cases where you either supplied a symbol (that stood for the name of
the object) or a symbol and the object (as an instance variable). Of
course I ripped all that off by studying the Rails form_for. :slight_smile: