开发者

Why can't I use Record.all.destroy in Rails?

I'm currently beginning to learn Ruby and the Ruby on Rails framework. I've found that in the table records, I can find a record with an id of 5 and delete it by using the following code:

Record.find(5).destroy

This makes sense- I chain methods to find the record and destroy it. However, if I want to destroy all the records in the table, the logical command would be the following, as the all selector selects all the records in the table:

Record.all.destroy

And this returns a NoMethodError! I am aware that I can use Record.destroy_all or Record.delete_all to accomplish this task, however, I'd like to know why I can't just use the most logical choice instead of having to look up things like delete_all. I am new to this framework, so it's entirely possible that I'm missing something fundamental here.

Thanks for any answer开发者_C百科s in advance.


It was a design decision. DataMapper took your approach. Being forced to write destroy_all explicitly can be tedious but will also prevent you from doing something you really don't want (i.e. delete everything in a table, like x = User; ...; x.destroy).


I agree it would be logical to be able to do this. Technically speaking, Record.all returns a collection (or proxy to a collection) which doesn't implement the destroy method.


When you have

Record.find(5)

this returns a Record object/instance that represents the data in a row in your table. Then you call the #destroy method on that object which is defined by your Record model.

When you have

Record.all

this returns an Array object. In order for you to then call #destroy on the array, you would have to monkey patch Ruby's core Array class to have a #destroy method.


The most simple way to avoid Record.destroy_all would be Record.all.each {|r| r.destroy}. This may somewhat satisfy your API design preferences, but should be much slower than the first option.


Actually you can (in a way). Since .all returns an array, and not an active record relation, what exactly would you be deleting? I wouldn't say Record.all.destroy is logical at all -- are you deleting the array object?

One thing you could do is map the resulting array, and since map accepts a proc(&), you can execute that proc for each object in your array.

Record.all.map(&:destroy)

Note, this is going to trigger callbacks on all of your objects, which might be slower than you intended. If you wanted to avoid triggering callbacks you could map the appropriate destructive method instead of destroy. (hint: :delete)

Alternately, you could just do:

Record.destroy_all or Record.delete_all

as you stated in your question.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜