Form for


#1

Hey people,

I was wondering… The newest version of rails has the form_tag helper
deprecated so I wanted to use the new form_for… I saw it done this way
ever since I needed to use Acts as Authenticated inside my application.
After some time I had the basic functionality up and running considering
the signup of new users. Now I run into the following problem:

<% form_for :tenant do |f| -%>

<div>
  <label for="country">land</label>
  <%= f.text_field :country %>
</div>

Above is part of the signup form I have created which uses the Acts as
Authenticated plugin… Now most of the fields work just fine, but the
country field is not inside the tenants table, but is linked trough a
country_id foreign key… Obviously the code above generates the error
that the country method is not found…

How can I make a join to the country table? The thing I have tried is
this:

<% form_for :tenant do |f| -%>

<div>
  <label for="country">land</label>
  <%= f.country.text_field :country %>
</div>

and multiple variations on that theme… Any thoughts?

Thanks in advance…


#2

Here is what I have done in that situation.

in the form you will want:
<%= f.text_field :country %>

Then inside your tenant model:
def country=(country)
self.country = Country.find_by_name(country)
end

That way whenever you create or update records, when it comes time to
assign them to an instance of the model you can intercept them and
replace them with the value you really want (which happens to be
elsewhere).


#3

monki wrote:

Here is what I have done in that situation.

in the form you will want:
<%= f.text_field :country %>

Then inside your tenant model:
def country=(country)
self.country = Country.find_by_name(country)
end

That way whenever you create or update records, when it comes time to
assign them to an instance of the model you can intercept them and
replace them with the value you really want (which happens to be
elsewhere).

thanks alot, i think this might help me move forward… will try this
later tonight:)

  • danny

#4

Wait! It’s my understanding that “form_start_tag” and “form_end_tag”
are deprecated. The use of “form_tag” is still perfectly fine for non-
model related forms.

Please correct me if I wrong on this.

On Feb 5, 5:10 am, Daniel Owen van Dommelen <rails-mailing-


#5

monki wrote:

Here is what I have done in that situation.
in the form you will want:
<%= f.text_field :country %>

Then inside your tenant model:
def country=(country)
self.country = Country.find_by_name(country)
end

Would the country method be an endless loop, where self.country =
Country.find_by_name(country) would call the country method
again…and again…and again?

Which would inevitably cause a stack overflow.

Still new to Ruby that that seems logical.


#6

got something that doesn’t look right…

SystemStackError: stack level too deep: SELECT * FROM countries WHERE
(countries.name IS NULL) LIMIT 1

sql syntax looks wrong(?)

-danny


#7

Robert W. wrote:

monki wrote:

Here is what I have done in that situation.
in the form you will want:
<%= f.text_field :country %>

Then inside your tenant model:
def country=(country)
self.country = Country.find_by_name(country)
end

Would the country method be an endless loop, where self.country =
Country.find_by_name(country) would call the country method
again…and again…and again?

Which would inevitably cause a stack overflow.

Still new to Ruby that that seems logical.

you’re right it does become an endless loop…

tailed the dev log and it goes on for quite a while…

-danny


#8

Robert W. wrote:

Wait! It’s my understanding that “form_start_tag” and “form_end_tag”
are deprecated. The use of “form_tag” is still perfectly fine for non-
model related forms.

Please correct me if I wrong on this.

On Feb 5, 5:10 am, Daniel Owen van Dommelen <rails-mailing-

you’re probably right on that, might have mis-memorized some info I read
on some site…

b.t.w. @monki >> That code I tried you gave generates an error I haven’t
seen before:

stack level too deep…

looked liked it was going to work, need to find out what’s going on
there…

  • danny

#9

oops.

Yeah, I gave myself this error too.

UG…

I fought with that earlier.

What I proposed should work, but you’ll want to name the country field
something else on the form (something different from what the actual
field is called in the database).

So you should be able to get it to work like this:
in the form you will want:
<%= f.text_field :country_name %>

Then inside your tenant model:
def country_name=(country_name)
self.country = Country.find_by_name(country_name)
end

That way you get the effect you want and don’t get the loop.
Sorry about the confusion. The infinite loop there is tricky bits.


#10

SystemStackError: stack level too deep: SELECT * FROM countries WHERE
(countries.name IS NULL) LIMIT 1

self.country = anything is going to recursively call your new
definition of country=.

Try

self[:country_id] = Country.find_by_name(country).id rescue nil

instead.

(The rescue part is in case find_by_name fails and it ends up calling
nil.id)

Jeff
softiesonrails.com


#11

monki wrote:

oops.

Yeah, I gave myself this error too.

UG…

I fought with that earlier.

What I proposed should work, but you’ll want to name the country field
something else on the form (something different from what the actual
field is called in the database).

So you should be able to get it to work like this:
in the form you will want:
<%= f.text_field :country_name %>

Then inside your tenant model:
def country_name=(country_name)
self.country = Country.find_by_name(country_name)
end

That way you get the effect you want and don’t get the loop.
Sorry about the confusion. The infinite loop there is tricky bits.

REALLY LOVE THIS FORUM !! :slight_smile: Got the code to work and right back on
track again… Thanks people, great help!

  • Danny

#12

One more thing…

What if I had like a street, number and unit, existing inside an
addresses table and I wanted to have the id from a given street, number
and unit also put inside my tenants table?

the form allows people to enter their address, I want to look it up
inside the addresses table and then store te retrieved id inside my
tenants table…

I tried the following:

def address=(street, number, unit)
self[:address_id] = Address.find(:first, :conditions[“street = ? AND
number = ? AND unit = ?”, street, number, unit]).id rescue nil
end

doesn’t work :frowning:

  • danny

#13

monki wrote:

The:
def something=(something)
will only work if there is a field on the form named ‘something’.
Since there isn’t one named ‘street, number, unit’ that function
wouldn’t get called at all.

You could do this like the following.
For each of the street, number, and unit fields:
First, add a street name field to your form.
Then, in the model:
def street_name=(street_name)
@street_name = street_name
end

After you assign all three values you are ready to do the lookup (the
instance variables won’t get saved, so you need to put them into a
field that will).
So, in your model use a callback after the save (when all the instance
variables would be assigned):

after_save :find_address
def find_address
self[:address_id] = Address.find(:first, :conditions[“street = ?
AND
number = ? AND unit = ?”, @street, @number, @unit]).id rescue nil
end

I think that will get you what you were after.

Once more, thank you :slight_smile: I actually DO have the street, number, unit
fields inside my form, and I already figured I needed to have the def
street=(street), so I added those to the model, just didn’t know what to
put inside them… Going to add the rest now…

  • Danny

#14

Wanted to add one more thing to this discussion. I have ran my problems
alongside the main programmer at our company and he suggested looking
into the attr_reader and attr_writer functions of ruby, seems to be
working fine in my case!

  • Danny

#15

The:
def something=(something)
will only work if there is a field on the form named ‘something’.
Since there isn’t one named ‘street, number, unit’ that function
wouldn’t get called at all.

You could do this like the following.
For each of the street, number, and unit fields:
First, add a street name field to your form.
Then, in the model:
def street_name=(street_name)
@street_name = street_name
end

After you assign all three values you are ready to do the lookup (the
instance variables won’t get saved, so you need to put them into a
field that will).
So, in your model use a callback after the save (when all the instance
variables would be assigned):

after_save :find_address
def find_address
self[:address_id] = Address.find(:first, :conditions[“street = ?
AND
number = ? AND unit = ?”, @street, @number, @unit]).id rescue nil
end

I think that will get you what you were after.