Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Remove element from ActiveRecord_Relation in rails

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

e.g. 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, i.e.

@drivers.delete(0)
like image 815
user3711600 Avatar asked Jun 24 '14 08:06

user3711600


People also ask

How to delete a row from a specific table in rails?

If you are using Rails 5 and above, the following solution will work. Show activity on this post. Deleting a row from a particular table or a record set from a table is pretty simple, from your console all you need to do is grab the record set by its Id then delete or destroy it.

What is active record relation in SQL Server?

Active Record Relation. The cache key is built with a fingerprint of the sql query, the number of records matched by the query and a timestamp of the last updated record. When a new record comes to match the query, or any of the existing records is updated or deleted, the cache key changes.

Why does my rails table keep running out of integers?

This can accelerate the problem of running out of integers, if the underlying table is still stuck on a primary key of type int (note: All Rails apps since 5.1+ have defaulted to bigint, which is not liable to this problem).


3 Answers

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

like image 73
Richard Peck Avatar answered Sep 21 '22 11:09

Richard Peck


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.

like image 21
gfd Avatar answered Sep 23 '22 11:09

gfd


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}
like image 35
cousine Avatar answered Sep 25 '22 11:09

cousine