Rails: update_column работает, но не update_attributes

У меня есть простая модель:

class Reply < ActiveRecord::Base
  attr_accessible :body
  belongs_to :post
end

В моем контроллере у меня есть простой метод обновления:

def update
  @reply = Reply.find(params[:id])
  if @reply.update_attributes!(params[:reply])
    render :js => "alert('I am trying to update!')"
  else
    render :js => "alert('<%= @reply.errors %>')"
  end
end

Это не вызывает ошибку, но также и не обновляет ответ. Вместо этого я получаю сообщение "Я пытаюсь обновить". сообщение, как все работало. Но когда я перезагружаю страницу и смотрю на ответ, у нее есть тот же текст. Он фактически не обновлялся. Если я заменил update_attributes на:

@reply.update_column(:body, params[:reply][:body])

Он отлично работает. Если я использую:

@reply.update_attribute(:body, params[:reply][:body])

Это еще раз не работает. Любая идея, что будет?

В моем журнале у меня есть следующее:

Started PUT "/posts/2/replies/20" for 127.0.0.1 at 2013-01-19 10:39:57 -0600
Processing by RepliesController#update as JS
Parameters: {"utf8"=>"✓", "authenticity_token"=>"Xot7E+ldXiBm0hVvw5XUP/U5guJU2g8e4QaLbDVGzDE=", "reply"=>{"body"=>"Updated text."}, "commit"=>"Submit Revision", "post_id"=>"2", "id"=>"20"
[1m[35mUser Load (1.0ms)[0m  SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
[1m[36mReply Load (0.0ms)[0m  [1mSELECT `replies`.* FROM `replies` WHERE `replies`.`id` = 20 LIMIT 1[0m
[1m[35m (1.0ms)[0m  BEGIN
[1m[36mPost Load (0.0ms)[0m  [1mSELECT `posts`.* FROM `posts` WHERE `posts`.`id` = 2 LIMIT 1[0m
[1m[35m (0.0ms)[0m  COMMIT
Rendered replies/_reply_content.html.erb (502.0ms)
Rendered replies/update.js.erb (505.0ms)
Completed 200 OK in 849ms (Views: 484.0ms | ActiveRecord: 94.0ms)

Ответы

Ответ 1

Три метода, которые вы используете, делают разные вещи:

  • update_attributes пытается проверить запись, вызывает обратные вызовы и сохраняет;
  • update_attribute не проверяет запись, вызывает обратные вызовы и сохраняет;
  • update_column не проверяет запись, не вызывает обратные вызовы, не вызывает метод сохранения, хотя он обновляет запись в базе данных.

Если единственным методом, который "работает", является update_column, я предполагаю, что у вас есть обратный вызов где-то, что вызывает ошибку. Попробуйте проверить файл log/development.log, чтобы узнать, что происходит.

Вы также можете использовать update_attributes!. Этот вариант выдает ошибку, поэтому он может предоставить вам информацию о том, почему ваша модель не сохраняет.

Вы должны использовать update_attributes и избегать двух других методов, если вы точно не знаете, что делаете. Если вы добавите проверки и обратные вызовы позже к своей модели, использование update_attribute и update_column может привести к неприятному поведению, которое действительно сложно отладить.

Вы можете проверить эту ссылку для получения дополнительной информации об этом.

Ответ 2

Предполагаю, что у вас есть проблема с массовым назначением, и вы должны добавить свои атрибуты в свою модель, например,

attr_accessible: :your_attribute, :your_attribute2

Ответ 3

У меня была эта же проблема, но с Rails 4. Проблема возникает, когда у вас есть параметры [] в update_attribute. В Rails 4 с сильными параметрами

@reply.update_attributes(params[reply_params])

должен быть

@reply.update_attributes(reply_params)

Я не знаком с Rails 3, но это должно быть проблемой:

@reply.update_attributes(params[:reply])

должен быть

@reply.update_attributes(:reply)