Hamdan
Hamdan

Reputation: 193

Related object not saved

I have the models:

class Idea < ActiveRecord::Base
  has_many :connections, :class_name => 'IdeaConnection', :foreign_key => 'idea_a_id', :dependent => :destroy
  has_many :ideas, :through => :connections, :source => :idea_b, :dependent => :destroy
end

class IdeaConnection < ActiveRecord::Base
  belongs_to :idea
  belongs_to :idea_a, :class_name => 'Idea'
  belongs_to :idea_b, :class_name => 'Idea'
  belongs_to :relationship
end

class Relationship < ActiveRecord::Base
  has_many :idea_connections 
end

Idea, as you can see, own itself through Connections (join table). Each Connection entry belongs to Relationship. What I'm trying to do is to, after adding an Idea to another with:

Idea.find(1).ideas << Idea.find(2)

which is working and saving properly, get its connection on join table and update its relationship:

Ex:

Idea.find(1).connections.find_by_idea_b_id(Idea.f
ind(2).id).relationship = Relationship.find(1)

It processes correctly but it won't save.

Please, help, what am I missing?

ps: I don't want to do it by manually editting the relationship_id since it's ugly. ps2: Before you answer, remember the fact that autosave:true do not work for belongs_to/has_many relationships.

Upvotes: 0

Views: 620

Answers (3)

Nikita Shilnikov
Nikita Shilnikov

Reputation: 1204

You're working with connection object. Remember it. Your problem is that you call find_by... method in has_many association. It returns one record BUT Idea model has no ruby attribute link to that. See here why. That's why Idea#save cannot call IdeaConnection#save (remember that for cascade saving connections realtion must have autosave: true if connection already exists).

So I suggest you two options:

  1. Set :inverse_of on Idea#connections and IdeaConnection#idea_a relations and preload all records before mangling with Idea.find(1).connections.find_by_idea_b_id(Idea.f ind(2).id).relationship = Relationship.find(1). But I don't recommend you to do so because:
  2. As I said you're working with connection object. Just do so:

    Idea.find(1).connections.create do |connection|
      connection.idea_b = Idea.find(2)
      connection.relationship = Relationship.first
    end
    

Upvotes: 1

euwest
euwest

Reputation: 31

Assignments on the relational object level don't/won't automatically save; you have to tell them to. In ActiveRecord the push method (<<) has save built into it, which is why that was working for you. Setting a value (=) however does not have save built in, so you have to do it manually.

If you're interested, here's a link to another SO question where an answer talks about why push saves: Rails push into array saves object

Upvotes: 0

mohameddiaa27
mohameddiaa27

Reputation: 3597

This line of code won't save it

Idea.find(1).connections.first.relationship = Relationship.first   

What you need to do is:

Method #1: ( add the connection to the has_many relation )

Relationship.first.idea_connections << Idea.find(1).connections.first

OR

Method #2: ( add relationship_id to the connection then manually save it)

connection = Idea.find(1).connections.first
connection.relationship_id = Relationship.first.id
connection.save

Upvotes: 0

Related Questions