Nox
Nox

Reputation: 395

Rails has_and_belongs_to_many always inserts into database

Here is my problem:

class Facility < ActiveRecord::Base
...
has_and_belongs_to_many :languages, :autosave => false, :join_table => 'facilities_languages'
... 
end

When I do something like this:

facility = Facility.find(1)
language = Language.find(1)
facility.languages << language

Rails always do the SQL request:

"INSERT INTO `facilities_languages` (`language_id`,`facility_id`) VALUES (1, 1)"

Is there a way to avoid database requests unless I call 'facility.save' ?

Apparently, :autosave option here does something else.

Upvotes: 2

Views: 2871

Answers (3)

davidb
davidb

Reputation: 8954

Your Problem is that you use has_and_belongs_to_many which isnt based on a Model so you cant access it as an Object. You could create a Model that is doing the associations and then you could create new objects of this association model. e.g.:

rails g scaffold JoinClass faculty_id:integer language_id:integer

In the Model

class JoinClass < ActiveRecord::Base
     belongs_to :faculty
     belongs_to :language
end

In the other models:

Faculty

class Faculty < ActiveRecord::Base
     has_many :join_classes
     has_many :languages, :though => :join_classes
end

Language

class Language < ActiveRecord::Base
     has_many :join_classes
     has_many :faculties, :through => :join_classes
end

Then you would be able to add associations by creating association objects which arent saved automaticly. For example you have a String containing ids that contains the ids of the language objects which should be associated called language_ids in the FacultyController:

language_ids.split(",").each do |language_id|
    JoinClass.create(:faculty_id => @faculty.id, :language_id => language_id)
end

Of cause this code should be conditioned and positioned after the save of faculty.

Upvotes: 2

Henrik
Henrik

Reputation: 3704

If you use the shovel operator << Rails automatically saves the associated object.

From the documentation http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html

collection<<(object, …)

Adds one or more objects to the collection by creating associations in the join table (collection.push and collection.concat are aliases to this method). Note that this operation instantly fires update sql without waiting for the save or update call on the parent object.

Upvotes: 1

Tom Maeckelberghe
Tom Maeckelberghe

Reputation: 1999

facility.languages = [language]

Upvotes: 0

Related Questions