Delete by Id in mongoid - ruby-on-rails

Is there any one command in Mongoid to delete an object using id?
Something like,
ClassName.delete(:id)
Currently i dont see anything like that and im using,
obj = ClassName.find(:id)
obj.delete
Can it be any better?

Another Way
ClassName.any_in(:_id => ["id1", "id2"]).destroy_all

You can do something like the following:
ClassName.delete_all(conditions: { _id: BSON::ObjectId("whatevertheidis")})
You need the underscore in _id or it won't work.
Also, it may not matter, but destroy_all will run the model's callback methods while delete_all does not.

Related

Rails 5 bulk-update

What I need to do is something like this:
users.update_all(number: some_specific_number_different_for_each_user)
Is there a better way of doing it other than iterating through users and updating each one separately? Even if I enclose it in transaction, it seems very inefficient...
Or is there a way to just save all records once I adjust the value, something like:
users.each_with_index { |u,i| u.number = i }
users.save_all
Any ideas?
Not unless the value to be updated can be set by the SQL function.
See(EDIT2)
update_all with a method

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)
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
Since its an array of objects, have you tried to write something like #drivers.delete(#new_driver) or #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
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))

Rails ActiveRecord update_all array of ids

I have an ActiveRecord Model called Animal.
Animal has id and client_id.
In my app have an array called #selectedanimals that contains the id's of the animals I want to update such as: #selectedanimals: ["6", "14", "5"].
I have the value of a new client_id for these animals like #newclient.id and I want to update all of these Animal records with the new client_id.
What I have now is:
Animal.update_all({:client_id => #transferclient.id}, {:id => #selecteanimals})
I know this is not 100% correct because it is having a problem with :id.
I get an error like this:
Called id for nil, which would mistakenly be 8 -- if you really wanted the id of nil, use object_id
Forgive my ignorance but this is my first time using update_all and I don't see any examples where you pass it an array of the ids of the records you want to update so any help would be appreciated much.
EDIT:
Apparently the #transferclient.id was not properly defined. That was my problem.
Thanks all.
I am new to Ruby so I don't know if there's been some recent change in the API but Danpe's answer as well as the initial suggestion that actually worked according to the asker, didn't work for me. They both raised a syntax error.
The solution that worked for me and is actually proposed in the API documentation is this:
Animal.where(:id => #selectedanimals).update_all(:client_id => #transferclient.id)
You need to check if id is inside that array:
Animal.update_all({:client_id => #transferclient.id}, {"id IN (?)" , #selecteanimals})

Check if record exists in Rails before creating

I am trying to search my database before I enter the record, by doing this:
Product.update_or_create_by_name_and_date_and_applicationURL_and_server_and_addi_servers(app_name, app_date,url_app,server_name,addi_servers)
the problem is that I get an undefined method exception!
Is there another way to search for the same record before entering one?
You should use two steps:
#Suggestion 1
obj = Product.find_or_create_by_...
#Suggestion 2
obj = Product.find_or_initialize_by_...
obj.update_attributes hash_here
Rereading, your question, I can't really understand what do you want to update if you try to find an object with known attributes. Anyway, you would just have to adapt my answer a little if some fields are for identifying and some for update.
I would define a function in your model: something like
Product.find_by_everything
where you write out all the parameters of the search, instead of using the the long naming method.
Then, if that returns nil, create the product. This doesn't seem to be a good use case of using the built in activerecord naming methods.

rails/activerecord search eager loaded associations

I have a simple find statement as such:
m = MyModel.find(1, :include => :my_children)
With m.mychildren being an Array; is there anyway to find a particular record from within the array without having to iterate over the entire thing. If I do mychildren.find(1), a new DB query is issues, which doesn't make sense, since they are all loaded already
It looks like there's a little Rails magic going on here. Where Enumerable#find is being overridden by ActiveRecord::Base#find on methods created for associations.
On the upside Enumerable#find is aliased to Enumerable#detect.
Unfortunately Enumerable#find/Enumerable#detect have significantly different syntax from ActiveRecord::Base#find.
So you can't just do mychildren.find(1), instead you've got to do mychildren.detect{|c| c.id == 1} if you want to avoid hitting the database again. You may also want to consider extending Array for a more DRY way of doing this.
class Array
def id_find id
self.detect{|element| element.id == id}
end
end
I'm not quite sure what your asking, but have you tried select:
m.mychildren.select{ |child| child == <<some_statement>> }
This won't hit the database assuming you've used the :include option as you stated in your question.
Alternatively, if you know the number of the child you want, you should be able to just use
m.mychildren[1]

Resources