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
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
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
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
@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






