Updating additional data fields in has and belongs to many relationship

Updating additional data fields in has and belongs to many relationship


It's always been problem to update additional fields in HABTM tables.
Unfortunately rails have no direct support to update fields. I have written patch to update those fields in HABTM additional fields.
The code snippet and example are given below:

We have following models with HABTM relationship

Photo Model:
class Photo < ActiveRecord::Base
has_and_belongs_to_many :profiles
end

Profile Model:
class Profile < ActiveRecord::Base
has_and_belongs_to_many :photos
end

Table structure for photos_profiles:

photo_id
profile_id
status
password
profile_photo -> Default Photo

Here the problem is to update default photo in profile and it needs multiple and single update.
Solution:

Add patch patch_habtm.rb in lib directory:

module ActiveRecord
module Associations
class HasAndBelongsToManyAssociation
def initialize(owner, reflection)
super
construct_sql
end
def update_attributes(record, join_attributes = {})
if record.is_a? ActiveRecord::Base
record_id = record.id
else
record_id = record
end
cols, vals = [], []
join_attributes.each do | key, val |
cols << key.to_s
vals << val
end
col_string = cols.join(' = ?, ')
@owner.connection().update(sanitize_sql(["UPDATE #{@reflection.options[:join_table]} SET #{col_string} = ? WHERE
#{@reflection.primary_key_name} = ? AND #{@reflection.association_foreign_key} = ?", vals, @owner.id,
record_id].flatten), "Update Attributes")
end

def update_attributes_multi( join_attributes = {})
cols, vals = [], []
join_attributes.each do | key, val |
cols << key.to_s
vals << val
end
col_string = cols.join(' = ?, ')
@owner.connection().update(sanitize_sql(["UPDATE #{@reflection.options[:join_table]} SET #{col_string} = ? WHERE
#{@reflection.primary_key_name} = ? ", vals, @owner.id].flatten), "Update Attributes")
end
end
end
end

Add following line in environment.rb
require 'patch_habtm'

Don’t forget to restart the server as we have changed the environment.

Controller Code:

if !params[:id].blank?
@prof = Profile.find(8)
@photo=Photo.find(params[:id])
@prof.photos.update_attributes_multi(:profile_photo => false)
@prof.photos.update_attributes(@photo,:status=> false,:profile_photo => true, :password =>"000000")
end