Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detecting changes in a rails has_many :through relationship

I have a model that has a number of has_many, and has_many :through model relationships. For example, in my User class I have:

has_many :languages, through: :profile_languages

What I would like is to be able to detect when these are added or removed using the 'User.changes' function, which returns an array of attributes that have been changed when called with the User.language_ids= function.

Has anyone else tried to do this, or have experience with this?

Info on the ActiveModel changes function: http://api.rubyonrails.org/classes/ActiveModel/Dirty.html

Edit: As requested, here is what I am doing.

After a user's attributes are assigned and before it is saved, I am looking at all of the values returned from the .changes, in order to log all the changes made in an external log.

So if I call u.name = "new name"

then u.changes returns {name: ['old name', 'new name']}

However, when I pass a user a bunch of language ids, such as

u.language_ids = [4,5]

Then there are a number of ProfileLanguage models created, and the u.changes hash is left blank.

I am attempting to create some callbacks in the ProfileLanguage model that would manually create some sort of a hash, but I am wondering if this is indeed the best solution.

like image 816
MR-RON Avatar asked Nov 09 '12 00:11

MR-RON


2 Answers

My somewhat dirty solution I am going with now is to add callbacks to the has_many function:

has_many :languages, through: :profile_languages, 
        :after_add => :language_add, 
        :before_remove => :language_remove

And adding this info to a custom hash that will be checked on the saving of a profile when I am looking at the .changes function.

like image 186
MR-RON Avatar answered Nov 17 '22 15:11

MR-RON


I had the same problem, I was trying to check if a new relationship was created or deleted when updating a model.

I tried using model.relationship.any? { |a| a.changed? } but this only detects changes of alredy existing objects, so it didnt work on creation and deletion of relationships.

Searching for a solution, I found this very brief article which solves our problem: link

Using model.select { |a| a.new_record? || e.marked_for_destruction? }.any? I've been able to get all records that are being created or destroyed.

Combining this with a.changed? I can get every changes in my relationship.

like image 42
fabio.sang Avatar answered Nov 17 '22 14:11

fabio.sang