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)

person nullnullnull    schedule 19.01.2013    source источник
comment
какую версию рельсов вы используете?   -  person Wasi    schedule 19.01.2013
comment
Я использую версию 3.2.11, последнюю в ветке 3.2.   -  person nullnullnull    schedule 19.01.2013
comment
Вы можете использовать update_attributes!, чтобы узнать, почему он не сохраняется.   -  person alestanis    schedule 19.01.2013
comment
Откуда берется почтовая нагрузка? Это в ваших параметрах и вашем журнале, но не в вашем коде контроллера.   -  person Geoff    schedule 27.01.2013
comment
Если я не ошибаюсь, это происходит с моей точки зрения. Есть строка, которая вызывает answer.post для проверки разрешений пользователя.   -  person nullnullnull    schedule 27.01.2013
comment
@timothythehuman, почему он отображает update.js.erb код, завернутый в блок формата response_to   -  person Viren    schedule 29.01.2013
comment
@Viren Если я правильно понимаю ваш вопрос, это потому, что обновление использует удаленный вызов и возвращает файл .js.   -  person nullnullnull    schedule 29.01.2013


Ответы (3)


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

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

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

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

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

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

person alestanis    schedule 19.01.2013
comment
Спасибо за информацию. Странно, даже с треском update_attributes! не выдает ошибку. Я также не могу обнаружить никаких ошибок в своем файле журнала, хотя, возможно, я его неправильно читаю. Я добавил журнал в свой пост, если вы не против взглянуть на него. - person nullnullnull; 19.01.2013
comment
Я обновил вопрос с дополнительной информацией. В частности, я добавил условие в контроллер, чтобы он выдавал ошибки, если они есть. Вместо этого он действует так, как будто сохраняет правильно. Что-то здесь очень странное, правда? - person nullnullnull; 19.01.2013
comment
@timothythehuman Ваше состояние бесполезно с взрывной версией. В любом случае это вызовет ошибку, если не сможет сохраниться, поэтому вы никогда не доберетесь до строки @reply.errors. Вы должны использовать обычную версию, если хотите распечатать какие-либо ошибки. И да, что-то есть очень странное... - person alestanis; 19.01.2013
comment
Убрал челку, но выдает сообщение Я пытаюсь обновить. Можете предложить какое-то другое направление? Я буду продолжать возиться с этим, несмотря ни на что. Как вы упомянули, возвращаться к update_column не идеально. - person nullnullnull; 19.01.2013
comment
@timothythehuman Когда вы говорите, что он работает с update_column, вы имеете в виду, что объект отображается в представлении или сохраняется в базе данных? Вы звоните save после update_column? - person alestanis; 19.01.2013
comment
Я имею в виду, что он сохраняется в базе данных. С update_attributes он отображается в представлении, но фактически не сохраняется. Я также пытался вызывать save, но безрезультатно. - person nullnullnull; 19.01.2013
comment
@timothythehuman Извините, ваш код выглядит правильно, у меня больше нет идей о том, что может пойти не так... :( - person alestanis; 19.01.2013
comment
Но спасибо за попытку. Я буду держать вас в курсе, когда выясню это. - person nullnullnull; 20.01.2013
comment
Этот ответ НЕВЕРЕН или устарел в Rails 4: #update_column сохраняет запись! - person collimarco; 26.07.2013
comment
@collimarco Эй, не будь агрессивным. Вопрос помечен как «ruby-on-rails-3», так что да, это Rails 3, а не Rails 4. - person alestanis; 27.07.2013
comment
@alestanis Извините, это не должно было быть агрессивным :) Проблема в том, что там много путаницы: если вы пытаетесь понять разницу и читаете этот ответ, вы еще больше запутаетесь. Возможно, вопрос следует обновить, чтобы сказать, что он относится к Rails 3, потому что тег недостаточно виден. - person collimarco; 27.07.2013
comment
Я сталкиваюсь с той же проблемой в Rails 3.2. Единственное отличие состоит в том, что столбец, который я пытаюсь обновить, представляет собой столбец :binary, и я обновляю его значение с помощью Marshal.dump(val). update_column работает, но никакие другие способы обновления не работают. Сначала я подумал, что это ошибка, связанная с использованием Marshal в столбце :binary, но я думаю, что это более распространено? - person jamesfzhang; 06.02.2014
comment
В вашем объяснении update_column какая разница между вызовом метода сохранения и обновлением базы данных? @алестанис - person Martin Verdejo; 13.09.2018

У меня была такая же проблема, но с Rails 4. Проблема возникает, когда у вас есть params[] в 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)
person ChrisBarthol    schedule 30.04.2014

Интуитивным предположением было бы сказать, что у вас есть проблема с массовым назначением, и вы должны добавить свои атрибуты в свою модель следующим образом.

attr_accessible: :your_attribute, :your_attribute2
person Pasta    schedule 24.01.2013
comment
Это тоже была моя первая догадка. К сожалению, я сделал это (единственный атрибут, который я меняю) attr_accessible. Спасибо, в любом случае! - person nullnullnull; 24.01.2013