Forum: Ruby on Rails form for

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
9d79da034ee21c2aa1304e3c02e993eb?d=identicon&s=25 Nobody Else (nyxx)
on 2007-02-05 11:10
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...
391f7ae8dd8c10dc323b7fbfe55b71a2?d=identicon&s=25 monki (Guest)
on 2007-02-05 21:59
(Received via mailing list)
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).
9d79da034ee21c2aa1304e3c02e993eb?d=identicon&s=25 Nobody Else (nyxx)
on 2007-02-05 23:07
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
21f7ed21f11a809050594c82eab11d67?d=identicon&s=25 Robert Walker (Guest)
on 2007-02-05 23:15
(Received via mailing list)
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-
9d79da034ee21c2aa1304e3c02e993eb?d=identicon&s=25 Nobody Else (nyxx)
on 2007-02-05 23:36
Robert Walker 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
21f7ed21f11a809050594c82eab11d67?d=identicon&s=25 Robert Walker (Guest)
on 2007-02-05 23:44
(Received via mailing list)
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.
9d79da034ee21c2aa1304e3c02e993eb?d=identicon&s=25 Nobody Else (nyxx)
on 2007-02-05 23:44
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
9d79da034ee21c2aa1304e3c02e993eb?d=identicon&s=25 Nobody Else (nyxx)
on 2007-02-05 23:45
Robert Walker 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
8217faf2bfdfa7daf10135d41ddd421e?d=identicon&s=25 Jeff Cohen (jeff)
on 2007-02-06 02:04
(Received via mailing list)
> 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
391f7ae8dd8c10dc323b7fbfe55b71a2?d=identicon&s=25 monki (Guest)
on 2007-02-06 05:23
(Received via mailing list)
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.
9d79da034ee21c2aa1304e3c02e993eb?d=identicon&s=25 Nobody Else (nyxx)
on 2007-02-06 10:01
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 !! :) Got the code to work and right back on
track again... Thanks people, great help!

- Danny
9d79da034ee21c2aa1304e3c02e993eb?d=identicon&s=25 Nobody Else (nyxx)
on 2007-02-06 10:16
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 :(

- danny
391f7ae8dd8c10dc323b7fbfe55b71a2?d=identicon&s=25 monki (Guest)
on 2007-02-06 15:15
(Received via mailing list)
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.
9d79da034ee21c2aa1304e3c02e993eb?d=identicon&s=25 Nobody Else (nyxx)
on 2007-02-06 15:53
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 :) 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
9d79da034ee21c2aa1304e3c02e993eb?d=identicon&s=25 Nobody Else (nyxx)
on 2007-02-07 13:12
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
This topic is locked and can not be replied to.