views:

111

answers:

3

Here's the model file:

class ProfileTag < ActiveRecord::Base     
  def self.create_or_update(options = {})
    id = options.delete(:id)
    record = find_by_id(id) || new
    record.id = id
    record.attributes = options
    puts "record.profile_id is"
    puts record.profile_id

    record.save!

    record
  end
end

This gives me the correct print out in my log. But it also says that there's a call to UPDATE that sets profile_id to NULL. Here's some of the output in the log file:

Processing ProfilesController#update (for 127.0.0.1 at 2010-05-28 18:20:54) [PUT]
Parameters: {"commit"=>"Save", "profile"=>{"id"=>"2", "password_confirmation"=>"", "username"=>"user2", "first_name"=>"user2_first", "password"=>"", "last_name"=>"user2_last"}, "authenticity_token"=>"...", "tag"=>"1", "id"=>"2"}
  ?[4;36;1mProfileTag Create (0.0ms)?[0m   ?[0;1mINSERT INTO `profile_tags` 
(`reputation_value`, `updated_at`, `tag_id`, `id`, `profile_id`, `created_at`) VALUES(0, '2010-05-29 01:20:54', 1, NULL, 4, '2010-05-29 01:20:54')?[0m
  ?[4;35;1mSQL (2.0ms)?[0m   ?[0mCOMMIT?[0m
  ?[4;36;1mSQL (0.0ms)?[0m   ?[0;1mBEGIN?[0m
  ?[4;35;1mSQL (0.0ms)?[0m   ?[0mCOMMIT?[0m
  ?[4;36;1mProfileTag Load (0.0ms)?[0m   ?[0;1mSELECT * FROM `profile_tags` WHERE (`profile_tags`.profile_id = 4) ?[0m
  ?[4;35;1mSQL (1.0ms)?[0m   ?[0mBEGIN?[0m
  ?[4;36;1mProfileTag Update (0.0ms)?[0m   ?[0;1mUPDATE `profile_tags` SET profile_id = NULL WHERE (profile_id = 4 AND id IN (35)) ?[0m

I'm not sure I understand why the INSERT puts the value into profile_id properly, but then it sets it to NULL on an UPDATE.

[Edit] In ProfileController:

def update
  #...stuff. Set tags array.
  save_tags(tags) #These tags are correct. Verified by printouts before and after this call.
  respond_to do |format|
    if @profile.update_attributes(params[:profile])
      flash[:notice] = 'Profile was successfully updated.'
      #format.html { redirect_to(@profile) }
      format.html { redirect_to :action=>'show' }
      format.xml  { head :ok }
    else
      format.html { render :action => "edit" }
      format.xml  { render :xml => @profile.errors, :status => :unprocessable_entity }
    end
  end
end

def save_tags(tags)
  profile = find_profile #finds the correct profile. And I confirm that it exists with a printout
  tags.each do |t|
    ProfileTags.create_or_update(:profile_id => profile.profile_id, :tag_id => t.id)
  end
end

If you need more specifics, please let me know. I'm thinking that the save functionality does many things other than INSERTs into the database, but I don't know what I need to specify so that it will properly set profile_id.

A: 

save! itself should't do this.

Maybe your problem is the name of the method. ActiveRecord::Base already have a method named create_or_update (see http://github.com/rails/rails/blob/2-3-stable/activerecord/lib/active_record/base.rb#L2913) which is called by save! - maybe replacing it causes this weird problem.

Try changing the name of your method to something else, it might help.

Slobodan Kovacevic
Thanks for the suggestion, Slobodan, but it didn't work. I still get the UPDATE that sets the profile_id to NULL.
Teef L
Can you post the code from your controller where you call create_or_update?
Slobodan Kovacevic
The code has been added per your request! (:
Teef L
I would presume that you have something like has_many :profile_tags in your Profile model. If so then your problem might be @profile.update_attributes(params[:profile]) which saves the profile from memory which doesn't have any tags (so it sets it to null). Try commenting out save_tags call in controller and see in your log if there's still UPDATE query - if it's still there then update_attributes is to "blame".
Slobodan Kovacevic
A: 

You aren't passing the id attribute to the create_or_update method in the first place, so you don't need to call it, just call create instead, like so:

def save_tags(tags)
  profile = find_profile #finds the correct profile. And I confirm that it exists with a printout
  tags.each do |t|
    ProfileTag.create(:profile_id => profile.profile_id, :tag_id => t.id)
  end
end
Patrick Klingemann
+2  A: 

Look at the line:

 ProfileTags.create_or_update(:profile_id => profile.profile_id, :tag_id => t.id)

I believe you want to pass profile.id, and not profile.profile_id (which is probably null).

ndp