【问题标题】:RoR - `delete_at` like method in ActiveRecord::AssociationsRoR - ActiveRecord::Associations 中的 `delete_at` 类似方法
【发布时间】:2014-12-14 02:36:05
【问题描述】:

也许我只是淹死在一杯水里……

我有两个模型。

类队列
has_many :slots
结束

类插槽
结束

rails c中执行这个命令

q = Queue.create
s1 = Slot.create
s2 = Slot.create
s3 = Slot.create
q.slots

现在我只想从 q.slots 列表中删除第二个元素,而不删除其他 s2 元素(就像 #delete 一样)。类似于q.delete_at(1)。 有什么建议吗?

谢谢。

编辑:

这是我的 schema.rb

create_table "steps", force: true do |t|
t.整数值
结束

create_table "queues", force: true do |t|
t.string 名称
结束

create_table "steps_queues", force: true do |t|
t.integer "step_id"
t.integer "queue_id"
结束

添加索引“steps_queues”,[“step_id”],名称:“index_steps_queues_on_step_id”
add_index "steps_queues", ["queue_id"], name: "index_steps_queues_on_queue_id"

编辑二:

我通过has_many {:through} 关联解决了这个问题。添加对象模型以实现非业务逻辑目的并不是一个好主意。但是,嘿,它有效。

【问题讨论】:

  • 对于初学者来说,您必须保存您在控制台中创建的内容。所以 q.save s1.save 等...
  • 好吧,错误的例子:D 我在rails console 会话中使用已经创建的对象进行了测试。但问题依然存在。

标签: ruby-on-rails ruby activerecord ruby-on-rails-4


【解决方案1】:
a = [1,2,3,4,5,6]

a.delete_at(2) # a = [1,2,4,5,6]

delete_at 方法会删除你传递给它的数组的索引。

如果你想根据它的值删除一个项目,你可以使用 delete 方法。

pets = ['cat', 'dog', 'rabbit', 'parrot']

a.delete('dog')

# pets = ['cat', 'rabbit', 'parrot']

希望对你有帮助

【讨论】:

  • 在 Rails AcriveRecord::Associations 响应 #delete_at 但它不起作用(我认为它作用于数组的克隆)。而de#delete方法将从数组中删除对象的所有引用。
  • 你知道要删除数组中的什么值吗?
【解决方案2】:

ActiveRecord::Associations 不响应 #delete_at(它响应但没有任何反应),但是 Array 做到了!所以:

arr = q.steps.to_a # 返回一个数组
arr.delete_at(index_of_item_to_remove)
q.steps = [ ] # 消除所有关联。这是q.steps.size 更新的事务。
q.steps = arr # 插入 arr 的关联。这是一个带有arr.steps.size 更新的事务。

Array#delete_at 仅删除目标项,而 ActiveRecord::Associations#delete 删除所有等效项。

这种方法不是最好的,导致成本(2 * (q.steps.size - 1) 更新次数。可以实现一个自定义的 SQL 语句,这打破了抽象,这是一种不好的做法……听起来很脏。 :@

仍在寻找更好的解决方案

【讨论】:

    【解决方案3】:

    这将起作用:

    q.slots[1].destroy # will destroy the second record, it will remain in the association cache though
    q.slots(true)      # if you need the association again, passing true will refetch
    

    你也可以试试:

    q.slots.delete q.slots[1].destroy
    

    这应该从缓存的关联中删除元素,而不需要重新加载。

    【讨论】:

    • q.slots[1].destroy 将从 Slot 表中删除记录。我不希望这种情况发生。
    • 嗯?就像您希望 Slot 仍然存在但与 Queue 的关联中断?如果是这样,您将需要一个连接表。除非我完全误解了你的意图。
    • 事实上,关联映射在连接表中:) 是的,我希望 Slot 仍然存在,但关联已损坏。 #destroy 和 #delete 方法将从数据库中删除 Slot 实体。
    • 好的,我来演示一下;首先,您可以将您的架构添加到原始问题中吗?
    猜你喜欢
    • 1970-01-01
    • 2016-11-18
    • 2014-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多