简体   繁体   English

从 rails 中的 ActiveRecord_Relation 中删除元素

[英]Remove element from ActiveRecord_Relation in rails

How can i remove the last element from an ActiveRecord_Relation in rails?如何从 Rails 中的 ActiveRecord_Relation 中删除最后一个元素?

eg if I set:例如,如果我设置:

@drivers = Driver.all

I can add a another Driver object called @new_driver to @drivers by doing:我可以通过以下方式将另一个名为 @new_driver 的驱动程序 object 添加到 @drivers:

@drivers << @new_driver

But how can I remove an object from @drivers?但是如何从@drivers 中删除 object?

The delete method doesn't seem to work, ie删除方法似乎不起作用,即

@drivers.delete(0)

You can use the reject!您可以使用reject! method, this will remove the object from the collection without affecting the db方法,这将从集合中删除对象而不影响数据库

for example:例如:

driver_to_delete = @driver.first # you need the object that you want removed
@drivers.reject!{|driver| driver == driver_to_delete}

Very late too, but I arrived here looking for a fast answer and finished by thinking by myself;)也很晚了,但我来到这里寻找快速答案并通过自己思考完成;)

Just to clarify about the different answers and the Rails 6.1 comment on accepted answer:只是为了澄清不同的答案和 Rails 6.1 对已接受答案的评论:

The OP wanted to remove one entry from a query, but NOT remove it from database, so any answer with delete or destroy is just wrong (this WILL delete data from your database.!). OP 想从查询中删除一个条目,而不是将其从数据库中删除,因此任何使用deletedestroy的答案都是错误的(这将从您的数据库中删除数据。!)。

In Ruby (and therefore Rails) convention, shebang methods (ending with ! ) tend to alter the given parameter.在 Ruby(以及 Rails)约定中,shebang 方法(以!结尾)倾向于改变给定的参数。 So reject!所以reject! would imply modifying the source list... but an ActiveRecord_Relation is basically just a query , NOT an array of entries !将意味着修改源列表...但是ActiveRecord_Relation基本上只是一个查询,而不是一个条目数组!


So you'd have 2 options:所以你有两个选择:

  • Write your query differently to specifically say you don't want some id:以不同的方式编写您的查询,具体说明您不需要某些 ID:
@drivers.where.not(id: @driver_to_remove)  # This still is an ActiveRecord_Relation
  • Use reject (NO shebang) on your query to transform it into an Array and "manually" remove the entry you don't want:在查询中使用reject (NO shebang) 将其转换为数组并“手动”删除不需要的条目:
@drivers.reject{ |driver| driver ==  @driver_to_remove}
# The `reject` forces the execution of the query in DB and returns an Array)

On a performance point of view, I would personally recommend the first solution as it would be just a little more complex against the DB where the latter implies looping on the whole (eventually large) array.性能的角度来看,我个人会推荐第一个解决方案,因为它对 DB 来说稍微复杂一点,后者意味着在整个(最终是大的)数组上循环。

Late to the question, but just had the same issue and hope this helps someone else.问题迟到了,但刚刚遇到了同样的问题,希望这对其他人有所帮助。

reject! did not work for ActiveRecord_Relation in Rails 4.2不适用于 Rails 4.2 中的 ActiveRecord_Relation

drop(1) was the solution drop(1)是解决方案

In this case @drivers.drop(0) would work to drop the first element of the relation在这种情况下, @drivers.drop(0)将删除关系的第一个元素

由于它是一个对象数组,您是否尝试过编写类似 @drivers.delete(@new_driver) 或 @drivers.delete(id: @new_driver.id) 的内容?

This is the documentation you need : 这是您需要的文档

@group.avatars << Avatar.new
@group.avatars.delete(@group.avatars.last)

-- ——

.destroy

The problem you've got is you're trying to use collection methods on a non-collection object.您遇到的问题是您试图在非集合对象上使用collection方法。 You'll need to use the .destroy ActiveRecord method to get rid of the record from the database (and consequently the collection):您需要使用.destroy ActiveRecord 方法从数据库(以及集合)中删除记录:

@drivers = Driver.all
@drivers.last.destroy

-- ——

Scope范围

.delete will remove the record from the DB .delete将从数据库中删除记录

If you want to pull specific elements from the db to populate the @drivers object, you'll need to use a scope :如果要从数据库中提取特定元素以填充@drivers对象,则需要使用scope

#app/models/driver.rb
Class Driver < ActiveRecord::Base
   scope :your_scope, -> { where column: "value" }
end

This will allow you to call:这将允许您调用:

#app/controllers/drivers_controller.rb
def index
   @drivers = Driver.your_scope
end

I think you're getting the MVC programming pattern confused - data manipulation is meant to happen in the model , not the controller我认为您对MVC 编程模式感到困惑-数据操作旨在发生在model ,而不是在controller

Since the accepted answer does not work in rails 5.2.3 and the right answer by sevenseacat is hidden in comment. 由于接受的答案在rails 5.2.3中不起作用,并且sevenseacat的正确答案隐藏在评论中。 Here is the answer again. 这是答案。

@drivers.delete(@new_driver)

As stated above, reject!如上所述, reject! doesn't work in Rails 4.2, but delete does, so @drivers.delete(@new_driver) works, and more generally:在 Rails 4.2 中不起作用,但 delete 可以,所以@drivers.delete(@new_driver)起作用,更一般地说:

@drivers.delete(Driver.where(your condition))

Since the accepted answer doesn't work, here is the solution for Rails 5.2由于接受的答案不起作用,这里是 Rails 5.2 的解决方案

# to remove first element
@drivers = @drivers.second_to_last

#to remove last element
@drivers = @drivers.take(@drivers.size-1)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM