Как обновить один атрибут без сенсорного атрибута updated_at? - PullRequest
42 голосов
/ 03 февраля 2011

Как мне этого добиться?

пытался создать 2 метода с именем

def disable_timestamps
  ActiveRecord::Base.record_timestamps = false
end

def enable_timestamps
  ActiveRecord::Base.record_timestamps = true
end

и сам метод обновления:

def increment_pagehit
  update_attribute(:pagehit, pagehit+1)
end

включить отметки времени иотключить использование обратных вызовов, таких как:

before_update :disable_timestamps, :only => :increment_pagehit
after_update :enable_timestamps, :only => :increment_pagehit

, но это ничего не обновляет, даже требуемый атрибут (pagehit).

Любой совет?Я не хочу создавать другую таблицу только для подсчета количества страниц.

Ответы [ 7 ]

91 голосов
/ 31 мая 2012

В качестве альтернативы update_attribute, в Rails 3.1+ вы можете использовать update_column.

update_attribute, пропускает проверки, но прикасается к updated_at и выполняет обратные вызовы.

update_column пропускает проверки, не касается updated_at и не выполняет обратные вызовы.

Таким образом, update_column является отличным выбором, если вы не хотите влиять на updated_at и не нуждаетесьобратные вызовы.

См. http://api.rubyonrails.org/classes/ActiveRecord/Persistence.html для получения дополнительной информации.

Также обратите внимание, что update_column обновит значение атрибута в модели в памяти и не будетпомечен как грязныйНапример:

p = Person.new(:name => "Nathan")
p.save
p.update_column(:name, "Andrew")
p.name == "Andrew" # True
p.name_changed? # False
12 голосов
/ 03 февраля 2011

Если все, что вы хотите сделать, это увеличить счетчик, я бы вместо этого использовал метод increment_counter:

ModelName.increment_counter :pagehit, id
2 голосов
/ 06 марта 2013

это не очень хорошая идея:

self.class.update_all({ pagehit: pagehit+1 }, { id: id })

это должно быть

self.class.update_all("pagehit = pagehit + 1", { id: id })

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

2 голосов
/ 11 октября 2012

Чтобы избежать Monkeypatchingtroubles, вы также можете использовать ModelName.update_all для этой цели:

def increment_pagehit
  self.class.update_all({ pagehit: pagehit+1 }, { id: id })
end

Это также не касается временных меток записи.

1 голос
/ 20 октября 2016

У вас также есть decrement и increment (и их версии взрыва), которые не изменяют updated_at, не запускают обратные вызовы проверки правильности и, очевидно, удобны счетчики / целые числа.

0 голосов
/ 26 мая 2014

Если точность не так уж важна, и вы не ожидаете, что код будет выполняться много раз, вы можете попробовать изменить значение updated_at, сохраненное в базе данных, например:

u = User.first
u.name = "Alex 2" # make some changes...
u.updated_at = u.updated_at + 0.000001.second # alter updated_at
u.save

, чтобы Rails попытался сохранить то же значение, а не заменить его на Time.now.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...