Activerecord 删除记录不会破坏关联

Activerecord 删除记录不会破坏关联,activerecord,ruby-on-rails-5,Activerecord,Ruby On Rails 5,我有一个任务模型和用户模型,我有一个连接表b/w任务和名为标记的用户。 Task.rb 但是这个测试失败了 Task untag should untag user from task Failure/Error: expect(@task2.tag_exists_for(@user)).to be false expected false got true 在进一步的调查中,我发现untagtag会删除标记记录,但当我调用task.tags时

我有一个任务模型和用户模型,我有一个连接表b/w任务和名为标记的用户。 Task.rb

但是这个测试失败了

Task untag should untag user from task
     Failure/Error: expect(@task2.tag_exists_for(@user)).to be false

       expected false
            got true
在进一步的调查中,我发现untagtag会删除标记记录,但当我调用task.tags时,它会显示在collectionproxy中

Tag.find_by(id: 39)
  Tag Load (0.3ms)  SELECT  `tags`.* FROM `tags` WHERE `tags`.`id` = 71 LIMIT 1
 => nil
2.4.1 :042 > t1.tags
 => #<ActiveRecord::Associations::CollectionProxy [#<Tag id: 39, user_id: "3", task_id: "37", created_at: "2018-01-18 11:13:23", updated_at: "2018-01-18 11:13:23">, #<Tag id: 43, user_id: "9", task_id: "37", created_at: "2018-01-22 04:56:13", updated_at: "2018-01-22 04:56:13">, #<Tag id: 44, user_id: "5", task_id: "37", created_at: "2018-01-22 05:31:16", updated_at: "2018-01-22 05:31:16">]>
2.4.1 :043 >
我来自Mongodb,nosql的背景,所以以前从未经历过这种行为。
有没有一种方法可以在不使用任何宝石的情况下删除关联,一些人建议使用偏执宝石,用真正的毁灭取代毁灭

之所以发生这种情况,是因为您销毁的标记对象仍然缓存在ruby中。这就是为什么重载解决了这个问题,因为它从数据库中重新获取标记

为了有一点性能提升,并且不必在测试中调用reload,我建议用以下方式重写标记了\u user\u id的方法:

def tagged_user_ids
  tags.pluck(:user_id)
end
首先,这将调用一个SQL查询,只获取user_id列,而不是所有列。其次,对该方法的每次调用都将执行一个新的SQL查询,在这种情况下,如果删除一些标记,则该方法将反映结果,而无需在task对象上调用reload

另一个不相关的改进是将标记的任务改写为:


通过::tags完成了许多:标记的任务这可能很有趣:调用@task.reload解决了问题Hey@Kkulikovskis谢谢你的详细解释,但我似乎不知道这将如何工作通过::tags完成了许多:标记的任务,我必须在标记模型中进行更改吗also@Supertracer不,您不需要更改标签型号。可能需要指定source:attribute,因为标记的任务与标记关联的任务名称不匹配。
describe "untag" do
    it "should untag user from task" do
      create_task_and_tag_user
      p @task2.tags
      @task2.untag(@user)
      p @task2.tags
      expect(@task2.tag_exists_for(@user)).to be false 
    end  
  end

def create_task_and_tag_user
    @user = User.create(email:"asd@jaka.com",password: 123456,name: "user1")
    @task1 = @user.tasks.create(description: "some description")
    @user2 = User.create(email:"user2@jaka.com",password: 123456,name: "user2")
    @task2 = @user2.tasks.create(description: "some other task")
    @task2.tag(@user)
  end
Task untag should untag user from task
     Failure/Error: expect(@task2.tag_exists_for(@user)).to be false

       expected false
            got true
Tag.find_by(id: 39)
  Tag Load (0.3ms)  SELECT  `tags`.* FROM `tags` WHERE `tags`.`id` = 71 LIMIT 1
 => nil
2.4.1 :042 > t1.tags
 => #<ActiveRecord::Associations::CollectionProxy [#<Tag id: 39, user_id: "3", task_id: "37", created_at: "2018-01-18 11:13:23", updated_at: "2018-01-18 11:13:23">, #<Tag id: 43, user_id: "9", task_id: "37", created_at: "2018-01-22 04:56:13", updated_at: "2018-01-22 04:56:13">, #<Tag id: 44, user_id: "5", task_id: "37", created_at: "2018-01-22 05:31:16", updated_at: "2018-01-22 05:31:16">]>
2.4.1 :043 >
def tagged_user_ids
  tags.pluck(:user_id)
end