Build associated model confusion

I’m new to Rails3, and I’m just trying to get one last thing to work
before I call it a night. The situation is the following (please if
the code is horrible, just let me know, still learning):

I want to log a dive. I might have a new location on that dive at
which point I have to create a new Location, and then create the dive.
A dive has_one location. A location has_many dives. Currently the
foreign key is on dive as location_id.

How do I properly, in my dives_controller, generate the location, get
the ID, and pass it on to my new dive? It would be nice to have the
constructor of Location called, but if it doesn’t work that way, then
that’s okay too.

My code is below:

Thanks.

Melih O.

==========CODE==========

class Dive < ActiveRecord::Base
belongs_to :user
has_one :location

end

require ‘json’
require ‘net/http’
require ‘uri’

class Location < ActiveRecord::Base
has_many :dive

def initialize(location)
@name = location[:name]
@city = location[:city]
@region = location[:region]
@country = location[:country]

 url = "http://maps.googleapis.com/maps/api/geocode/json?

address=“+location[:city].sub(’ ', ‘+’)+”+“+location[:region].sub(’ ',
‘+’)+”+“+location[:country].sub(’ ', ‘+’)+”&sensor=false"
resp = Net::HTTP.get_response(URI.parse(url))
googMapsResponse = JSON.parse(resp.body)

 @latitude = googMapsResponse["results"][0]["geometry"]["location"]

[“lat”]
@longitude = googMapsResponse[“results”][0][“geometry”][“location”]
[“lng”]
end

def to_str
“#{self.name}::#{self.city}::#{self.region}::#{self.country}”
end
end

class DivesController < ApplicationController
def create
@dive = Dive.new(params[:dive])

if params[:location][:id] == "" then
@location = create_location(params[:location])

@dive.location_id = @location.id

else
@dive.location_id = params[:location][:id]
end

@dive.user_id = params[:user][:id]

end
end

Melih Onvural wrote in post #968249:

I’m new to Rails3, and I’m just trying to get one last thing to work
before I call it a night. The situation is the following (please if
the code is horrible, just let me know, still learning):

I want to log a dive. I might have a new location on that dive at
which point I have to create a new Location, and then create the dive.
A dive has_one location. A location has_many dives. Currently the
foreign key is on dive as location_id.

Then Dive belongs_to Location. Go review the difference between
belongs_to and has_one.

Best,

Marnen Laibow-Koser
http://www.marnen.org
[email protected]

Sent from my iPhone

A bit closer now. I now have it such that:

dive
belongs_to :location
end

I’ve got the initialize function following through, but it’s still
throwing an error on this code here:

@location = @dive.create_location(params[:location])

@dive.location_id = @location.id

with the following error message:

“You have a nil object when you didn’t expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.delete”

any clues?

melih

Thanks you guys!

Got things working, but having some problems with GeoKit and Rails3.
I’ll have to do some more investigation on that front!


Melih O.

A comment about your Location model:

You rarely need ‘initialize’ when creating new model instances (and in
this case you don’t).
The beauty of ActiveRecord is that it automagically gives you instance
variables for all table columns.
If you need any variables that are not a table column use
attr_accessor :foo_bar

Also, for all geocoding needs I would use http://geokit.rubyforge.org/

class Location < AR

has_many :dives

before_validation :geocode # or before_save/before_create, your call

def geocode
# call geokit to do the geocoding
end

end

Hope this helps!

Simon

Simon Baumgartner wrote in post #968527:

A comment about your Location model:

You rarely need ‘initialize’ when creating new model instances (and in
this case you don’t).

Good catch! But make that “never”, not “rarely”. ActiveRecord
constructors generally shouldn’t be overridden. Instead, use before_ or
after_create callbacks to set values (as in your example).

The beauty of ActiveRecord is that it automagically gives you instance
variables for all table columns.
If you need any variables that are not a table column use
attr_accessor :foo_bar

Also, for all geocoding needs I would use http://geokit.rubyforge.org/

Indeed. Also investigate Spatial Adapter, and consider PostGIS if
you’re using PostgreSQL. (If you’re not using PostgreSQL, you probably
should be. :slight_smile: )

Best,

Marnen Laibow-Koser
http://www.marnen.org
[email protected]