location - User/Address association in Rails -


i'm working on first rails project , i'm trying create proper user/address (or rather user/location) association. thought problem common , others had done i'm trying , easy find answer wasn't case. there many different questions extremely different answers , couldn't figure out how things in case. here's scenario:

the location can country, state/region or city, not more specific (i'm using google places library's autocomplete feature). avoid lot of duplicate information in users table every time 1 or more users live in same city (country, state, city, latitude, longitude etc), figured should have locations table. worse, user should have "home_location" , "current_location". associations:

has_one

at first thought: "well, user has address/location, should use has_one association. turns out if use user has_one location, location table 1 pointing user's table, not want, since many users should able reference same location.

belongs_to/has_many

"ok, i'll use belongs_to/has_many association" thought. seemed pretty neat @ first. seemed make lot of sense. i'm using nested forms gem, works pretty else i've done far, , nested form locations loaded , information sent correctly. location created , added database successfully, there 1 problem: user.location wasn't saved. trying figure out why, realize there's weird whole thing. rails not treating design structure way need (the way feel more intuitive). indeed, association used "user/microposts" (like in hartl's tutorial) , kind of thing. in case idea different. humans understand that, rails doesn't seem to. want user able lives in "edit profile" page. i've been reading seems rails expecting location's edit page have nested form users. it's expecting me create user this:

@location.user.create(:email=>"john@example.com") 

while need create location this:

@user.location.create(:city=>"rio de janeiro", etc) 

ok. maybe want specific , rail's standard association won't work. after code above create duplicate cities, i'd need like:

@user.location.find_or_create(:city=>"rio de janeiro") (does exist associated objects?)

here's code attempt saved location didn't create association:

model

class user < activerecord::base   attr_accessible ... :home_location, :home_location_attributes,                   :current_location, :current_location_attributes, etc     belongs_to :home_location, :class_name => 'location'   accepts_nested_attributes_for :home_location    belongs_to :current_location, :class_name => 'location'   accepts_nested_attributes_for :current_location    ... end  class location < activerecord::base   attr_accessible :google_id, :latitude, :longitude,                   :administrative_area_level_1, :administrative_area_level_2,                   :city, :neighborhood, :country, :country_id    belongs_to :country    has_many :users end 

schema

  create_table "users", :force => true |t|     ...     t.integer  "home_location"     t.integer  "current_location"     t.text     "about_me"     t.datetime "created_at",                         :null => false     t.datetime "updated_at",                         :null => false     ...   end    create_table "locations", :force => true |t|     t.string   "google_id",                   :null => false     t.string   "latitude",                    :null => false     t.string   "longitude",                   :null => false     t.integer  "country_id",                  :null => false     t.string   "administrative_area_level_1"     t.string   "administrative_area_level_2"     t.string   "city"     t.string   "neighborhood"     t.datetime "created_at",                  :null => false     t.datetime "updated_at",                  :null => false   end 

but seemed wanted particular gave , tried add form_for @location. check in user controller if record existed , save in user's home_location attribute. removed following lines user model:

accepts_nested_attributes_for :home_location accepts_nested_attributes_for :current_location 

and replaced f.fields_for in edit_profile view form_for @location.

then in controller added code deal location:

class userscontroller < applicationcontroller   before_filter :signed_in_user,  only: [:index, :edit, :update, :destroy]   before_filter :signed_out_user, only: [:new, :create]   before_filter :correct_user,    only: [:edit, :update]    ...   def edit     if @user.speaks.length == 0       @user.speaks.new     end     if @user.wants_to_learn.length == 0       @user.wants_to_learn.new     end     if @user.home_location.blank?       @user.home_location = location.new     end   end    def update     logger.debug params      ...      @home_location = nil      params[:home_location][:country_id] = params[:home_location].delete(:country)      unless params[:home_location][:country_id].blank?       params[:home_location][:country_id] = country.find_by_iso_3166_code(params[:home_location][:country_id]).id        #@home_location = location.where(params[:home_location])       #the line above describe behavior want,       #but testing purposes simplified below:       @home_location = location.find(2) #there location id=2 in db        if @home_location.nil?         @home_location = location.new(params[:home_location])         if !@home_location.save @home_location = nil end       end     end      if @user.update_attributes(params[:user])       @user.home_location = @home_location       @user.save       flash[:success] = "profile updated"       sign_in @user       #render :action => :edit       redirect_to :action => :edit     else       render :action => :edit     end   end   ... end 

but still doesn't save association. in fact in console, no matter do, user's home_location attribute never gets saved database.

does have idea of may happening??

why association not being saved? what's correct way of doing in rails?

i'm sorry length of question. hope reads it. i'd grateful!

thanks

edit 1

following robheaton's tip, added custom setter in user model:

  def home_location= location #params[:user][:home_location]    locations = location.where(location)    @home_location = locations.first.id unless locations.empty?   end 

after fixing issues popped up, started working! data saved database. still have no idea why didn't work in controller though. body have guess? i'm wondering if mistake wasn't somewhere else , ended fixing without noticing because code better organized in model.

still, problem not solved. although value saved database, can't access associated model in standard rails way.

1.9.3p362 :001 > ariel = user.first   user load (0.5ms)  select "users".* "users" limit 1  => #<user id: 1, first_name: "ariel", last_name: "pontes", username: nil, email: "pontes@ariel.com", password_digest: "$2a$10$ue8dh/nrh9kl9lud8jjqu.okd6tte i4h1tphmroniq15...", remember_token: "kadybxrh1g0x-be_hxha4w", date_of_birth: nil, gender: nil, interested_in: 0, relationship_status: nil, home_location: 3, curr ent_location: nil, about_me: "", created_at: "2013-05-07 14:28:05", updated_at: "2013-05-09 20:10:41", home_details: nil, current_details: nil>  1.9.3p362 :002 > ariel.home_location  => nil 

the weird thing not isn't rails able return associated object, won't return integer id stored in object! how make sense? hoping location object and, worst case scenario, expecting 3 in return. instead nil.

i tried write custom getter anyway:

  def home_location     if @home_location.blank? return nil end     location.find(@home_location)   end 

but of course doesn't work. more ideas??

something like:

class user < activerecord::base    def location= city_name     write_attribute :location, location.find_by_city_name(city_name)   end  end 

should it. can define state=, city= , on , in each case find appropriate column. general principle want of logic out of controllers possible. writing 10+ lines of code process incoming params want consider whether can in model.


Comments

Popular posts from this blog

java - Jmockit String final length method mocking Issue -

asp.net - Razor Page Hosted on IIS 6 Fails Every Morning -

c++ - wxwidget compiling on windows command prompt -