yeyo
yeyo

Reputation: 3009

how do I disassociate a record from an activerecord association without deleting the record?

How do I disassociate a record from an association without deleting the record?

Consider the following scenario, a Game has many rules and a rule has many Games so

>> game.rules   #=> [#<rule id: 1, ...>,  #<rule id:2, ...>]

how do I disassociate the rule of id 2 from game without deleting it, so the relation ends up like this:

>> game.rules   #=> [#<rule id: 1, ...>]

I tried reassigning an updated array to the relation, however that's preventing the association from saving future insertions somehow. I believe one can't assign arrays to relations.

This is what I've tried:

>> tmp = game.rules.to_a
>> tmp.delete(rule_of_id2)
>> game.rules = tmp
^D

but then, future insertions does not persist.

>> games.rules << new_rule_of_id3
^D

>> game.rules   #=> [#<rule id: 1, ...>

It shoult return #=> [#<rule id: 1, ...>, #<rule id: 3, ...>]

how can I update the relation without explicitly deleting a rule.

Upvotes: 1

Views: 3292

Answers (2)

PlatypusMaximus
PlatypusMaximus

Reputation: 74

In Rails 6.1 I override the _delete_row method to search for the correct columns. Works with delete and destroy.

relationship.ruby

class Goal::Relationship < ApplicationRecord
  belongs_to :parent, foreign_key: :parent_id, class_name: :Goal, inverse_of: :child_relationships
  belongs_to :child, foreign_key: :child_id, class_name: :Goal, inverse_of: :parent_relationships

  def _delete_row
    self.class._delete_record({ parent_id: parent_id, child_id: child_id })
  end
end

Matching tests


class Goal::RelationshipTest < ActiveSupport::TestCase
  setup do
    @parent = goals(:parent1)
  end

  test 'should delete a relationship' do
    assert_difference -> { Goal::Relationship.count }, -1 do
      @parent.child_relationships.first.delete
    end
  end

  test 'should destroy relationships' do
    assert_difference -> { Goal::Relationship.count }, -1 do
      @parent.child_relationships.first.destroy
    end
  end
end

Upvotes: 0

Prajna
Prajna

Reputation: 1255

game.rules.delete(Rule.find(2))

or

game.rule_ids = [1]
game.save

Upvotes: 4

Related Questions