简体   繁体   中英

Remove element from ActiveRecord_Relation in rails

How can i remove the last element from an ActiveRecord_Relation in rails?

eg if I set:

@drivers = Driver.all

I can add a another Driver object called @new_driver to @drivers by doing:

@drivers << @new_driver

But how can I remove an object from @drivers?

The delete method doesn't seem to work, ie

@drivers.delete(0)

You can use the 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:

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.!).

In Ruby (and therefore Rails) convention, shebang methods (ending with ! ) tend to alter the given parameter. So reject! would imply modifying the source list... but an ActiveRecord_Relation is basically just a query , NOT an array of entries !


So you'd have 2 options:

  • Write your query differently to specifically say you don't want some 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:
@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.

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

drop(1) was the solution

In this case @drivers.drop(0) would work to drop the first element of the relation

由于它是一个对象数组,您是否尝试过编写类似 @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. You'll need to use the .destroy ActiveRecord method to get rid of the record from the database (and consequently the collection):

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

--

Scope

.delete will remove the record from the DB

If you want to pull specific elements from the db to populate the @drivers object, you'll need to use a 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

Since the accepted answer does not work in rails 5.2.3 and the right answer by sevenseacat is hidden in comment. Here is the answer again.

@drivers.delete(@new_driver)

As stated above, reject! doesn't work in Rails 4.2, but delete does, so @drivers.delete(@new_driver) works, and more generally:

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

Since the accepted answer doesn't work, here is the solution for Rails 5.2

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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