2012-06-07 3 views
7

Вы знаете упражнение: в базе данных производятся данные о некорректных данных, и вам нужно избавиться от него. Вы запустите ваш Rails консоли на сервере и типа в запросе:Как просмотреть запрос delete_all или destroy_all в Rails

Foo.where(bar: 'baz').all 

Вы проверяете возвращаемые данные, и это то, что вам нужно удалить. Затем вы вводите:

Foo.where(bar: 'baz').destroy_all 

И ваше сердце останавливается на секунду. Вы просто хотите увидеть запрос до его запуска.

Есть ли способ сделать это в Rails? Я ищу способ похож на

Foo.where(bar: 'baz').to_sql 

, но тот, который будет возвращать DELETE запроса.

ответ

1

Сверху моей головы вы можете запустить консоль в режиме песочницы и запустить запрос на удаление, чтобы увидеть sql. Изменения будут просто отменены при выходе.

+0

Я предполагаю, что это на самом деле не ответьте на ваш вопрос, хотя, если вы действительно ищете «to_sql» -подобный комм а также. – cdesrosiers

+0

Я полностью забыл о режиме песочницы! Это не совсем то, что я искал, но он делает именно то, что мне нужно для этого. Особенно учитывая то, что то, что я искал, невозможно: D –

2

Проблема заключается в том, что destroy_all не запускает один SQL-запрос. Он выполняет итерацию через хэш объектов, запускает их, запускает свои обратные вызовы и затем вызывает метод уничтожения объекта. Rails не имеет встроенного способа создания массива этих запросов.

Cdesroisiers прав, что вы можете протестировать запрос в режиме песочницы, но настоящая проблема заключается в том, что вы угадываете свое решение о запуске delete_all, даже несмотря на то, что вы проверяли, какие данные нацелены.

Рассмотрите возможность использования драгоценного камня с версией ActiveRecord, например PaperTrail, если вы не хотите доверять ActiveRecord для правильного удаления объектов.

+0

Какое оправдание для того, чтобы не внедрять 'delete_all' в качестве пакетной операции, я думал, что это намного дешевле сделать в пакете, а не совершать серьезные поездки туда и обратно в базу данных. – Bedasso

+2

delete_all - пакетная операция. destroy_all делает их один за другим. delete_all существует, потому что он быстрее, destroy_all может быть полезен, поскольку он срабатывает до/после уничтожения обратных вызовов. –

+0

PaperTrail отлично подходит для использования в приложении, но мне просто нужно было избавиться от некоторых избыточных данных. Спасибо, в любом случае! –

1

метод destroy_all так же, как делают:

Foo.where(bar: 'baz').each { |object| object.destroy } 

Так SQL становится

DELETE FROM foo WHERE foo.id = your_objects_id_attribute 



Из документации:

def destroy_all(conditions = nil) 
    find(:all, :conditions => conditions).each { |object| object.destroy } 
    end 
+1

Я считаю, что сгенерированный SQL будет состоять из нескольких запросов DELETE - по одному на каждый найденный объект. – mrt